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