001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Gagnavarslan ehf 018 */ 019package org.nuxeo.ecm.webdav.backend; 020 021import java.util.ArrayList; 022import java.util.HashMap; 023import java.util.LinkedList; 024import java.util.List; 025import java.util.Map; 026import java.util.concurrent.ConcurrentHashMap; 027 028import org.apache.commons.lang.StringUtils; 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031import org.nuxeo.common.utils.Path; 032import org.nuxeo.ecm.core.api.Blob; 033import org.nuxeo.ecm.core.api.CoreSession; 034import org.nuxeo.ecm.core.api.DocumentModel; 035import org.nuxeo.ecm.core.api.DocumentRef; 036import org.nuxeo.ecm.core.api.PathRef; 037 038public abstract class AbstractVirtualBackend extends AbstractCoreBackend implements VirtualBackend { 039 040 private static final Log log = LogFactory.getLog(AbstractVirtualBackend.class); 041 042 protected Map<String, Backend> backendMap; 043 044 protected LinkedList<String> orderedBackendNames; 045 046 protected String rootUrl; 047 048 private String backendDisplayName; 049 050 private RealBackendFactory realBackendFactory; 051 052 protected AbstractVirtualBackend(String name, String rootUrl, CoreSession session, 053 RealBackendFactory realBackendFactory) { 054 super(session); 055 this.backendDisplayName = name; 056 this.rootUrl = new Path(rootUrl).append(this.backendDisplayName).toString(); 057 this.realBackendFactory = realBackendFactory; 058 } 059 060 protected void registerSimpleBackends(List<DocumentModel> docs) { 061 List<String> paths = new ArrayList<String>(); 062 for (DocumentModel doc : docs) { 063 paths.add(doc.getPathAsString()); 064 } 065 066 List<String> heads = new ArrayList<String>(); 067 for (int idx = 0; idx < paths.size(); idx++) { 068 String path = paths.get(idx); 069 if (isHead(path, paths, idx)) { 070 heads.add(path); 071 } 072 } 073 074 for (String head : heads) { 075 String headName = new Path(head).lastSegment(); 076 String name = headName; 077 int idx = 1; 078 while (backendMap.containsKey(name)) { 079 name = headName + "-" + idx; 080 idx = idx + 1; 081 } 082 083 Backend backend = realBackendFactory.createBackend(name, head, 084 new Path(this.rootUrl).append(name).toString(), getSession()); 085 086 registerBackend(backend); 087 } 088 } 089 090 private boolean isHead(String path, List<String> paths, int idx) { 091 int level = new Path(path).segmentCount(); 092 093 for (int i = idx; i >= 0; i--) { 094 String other = paths.get(i); 095 if (path.contains(other)) { 096 if (new Path(other).segmentCount() == level - 1) { 097 return false; 098 } 099 } 100 } 101 return true; 102 } 103 104 @Override 105 public String getRootPath() { 106 return ""; 107 } 108 109 @Override 110 public String getRootUrl() { 111 return rootUrl; 112 } 113 114 @Override 115 public final boolean isVirtual() { 116 return true; 117 } 118 119 @Override 120 public boolean isRoot() { 121 return false; 122 } 123 124 @Override 125 public String getBackendDisplayName() { 126 return backendDisplayName; 127 } 128 129 @Override 130 public LinkedList<String> getVirtualFolderNames() { 131 initIfNeed(); 132 if (orderedBackendNames == null) { 133 return new LinkedList<String>(); 134 } 135 return orderedBackendNames; 136 } 137 138 protected void registerBackend(Backend backend) { 139 if (backendMap == null) { 140 backendMap = new ConcurrentHashMap<String, Backend>(); 141 } 142 if (orderedBackendNames == null) { 143 orderedBackendNames = new LinkedList<String>(); 144 } 145 backendMap.put(backend.getBackendDisplayName(), backend); 146 orderedBackendNames.add(backend.getBackendDisplayName()); 147 } 148 149 @Override 150 public Backend getBackend(String uri) { 151 Path path = new Path(uri); 152 if (path.segmentCount() == 0) { 153 return this; 154 } else { 155 String key = path.segment(0); 156 initIfNeed(); 157 if (backendMap == null) { 158 return null; 159 } 160 Backend backend = backendMap.get(key); 161 if (backend == null) { 162 return null; 163 } 164 String location = path.removeFirstSegments(1).toString(); 165 return backend.getBackend(location); 166 } 167 } 168 169 protected void initIfNeed() { 170 if (backendMap == null || orderedBackendNames == null) { 171 backendMap = new HashMap<String, Backend>(); 172 orderedBackendNames = new LinkedList<String>(); 173 init(); 174 } 175 } 176 177 protected abstract void init(); 178 179 @Override 180 public boolean isLocked(DocumentRef ref) { 181 throw new UnsupportedOperationException(); 182 } 183 184 @Override 185 public boolean canUnlock(DocumentRef ref) { 186 throw new UnsupportedOperationException(); 187 } 188 189 @Override 190 public String lock(DocumentRef ref) { 191 throw new UnsupportedOperationException(); 192 } 193 194 @Override 195 public boolean unlock(DocumentRef ref) { 196 throw new UnsupportedOperationException(); 197 } 198 199 @Override 200 public String getCheckoutUser(DocumentRef ref) { 201 throw new UnsupportedOperationException(); 202 } 203 204 @Override 205 public DocumentModel resolveLocation(String location) { 206 throw new UnsupportedOperationException(location); 207 } 208 209 @Override 210 public Path parseLocation(String location) { 211 throw new UnsupportedOperationException(); 212 } 213 214 @Override 215 public void removeItem(String location) { 216 throw new UnsupportedOperationException(); 217 } 218 219 @Override 220 public void removeItem(DocumentRef ref) { 221 throw new UnsupportedOperationException(); 222 } 223 224 @Override 225 public void renameItem(DocumentModel source, String destinationName) { 226 throw new UnsupportedOperationException(); 227 } 228 229 @Override 230 public DocumentModel moveItem(DocumentModel source, PathRef targetParentRef) { 231 throw new UnsupportedOperationException(); 232 } 233 234 @Override 235 public DocumentModel copyItem(DocumentModel source, PathRef targetParentRef) { 236 throw new UnsupportedOperationException(); 237 } 238 239 @Override 240 public DocumentModel createFolder(String parentPath, String name) { 241 throw new UnsupportedOperationException(); 242 } 243 244 @Override 245 public DocumentModel createFile(String parentPath, String name, Blob content) { 246 throw new UnsupportedOperationException(); 247 } 248 249 @Override 250 public DocumentModel createFile(String parentPath, String name) { 251 throw new UnsupportedOperationException(); 252 } 253 254 @Override 255 public List<DocumentModel> getChildren(DocumentRef ref) { 256 throw new UnsupportedOperationException(); 257 } 258 259 @Override 260 public boolean isRename(String source, String destination) { 261 throw new UnsupportedOperationException(); 262 } 263 264 @Override 265 public boolean exists(String location) { 266 throw new UnsupportedOperationException(location); 267 } 268 269 @Override 270 public String getDisplayName(DocumentModel doc) { 271 throw new UnsupportedOperationException(); 272 } 273 274 @Override 275 public boolean hasPermission(DocumentRef docRef, String permission) { 276 throw new UnsupportedOperationException(); 277 } 278 279 @Override 280 public DocumentModel getDocument(String location) { 281 throw new UnsupportedOperationException(); 282 } 283 284 @Override 285 public DocumentModel updateDocument(DocumentModel doc, String name, Blob content) { 286 throw new UnsupportedOperationException(); 287 } 288 289 @Override 290 public DocumentModel moveItem(DocumentModel source, DocumentRef targetParentRef, String name) 291 { 292 throw new UnsupportedOperationException(); 293 } 294 295 @Override 296 public String getVirtualPath(String path) { 297 initIfNeed(); 298 for (String backendName : orderedBackendNames) { 299 Backend backend = backendMap.get(backendName); 300 String url = backend.getVirtualPath(path); 301 if (StringUtils.isNotEmpty(url)) { 302 return url; 303 } 304 } 305 return null; 306 } 307 308 @Override 309 public LinkedList<String> getOrderedBackendNames() { 310 initIfNeed(); 311 return orderedBackendNames; 312 } 313 314}