001/* 002 * (C) Copyright 2012 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 * Antoine Taillefer <ataillefer@nuxeo.com> 018 */ 019package org.nuxeo.drive.service.impl; 020 021import java.security.Principal; 022import java.util.Map; 023 024import org.apache.commons.logging.Log; 025import org.apache.commons.logging.LogFactory; 026import org.nuxeo.drive.adapter.FileSystemItem; 027import org.nuxeo.drive.adapter.FolderItem; 028import org.nuxeo.drive.adapter.impl.AbstractFileSystemItem; 029import org.nuxeo.drive.service.FileSystemItemAdapterService; 030import org.nuxeo.drive.service.FileSystemItemFactory; 031import org.nuxeo.drive.service.FileSystemItemManager; 032import org.nuxeo.ecm.core.api.CoreInstance; 033import org.nuxeo.ecm.core.api.CoreSession; 034import org.nuxeo.ecm.core.api.DocumentModel; 035import org.nuxeo.ecm.core.api.DocumentNotFoundException; 036import org.nuxeo.ecm.core.api.DocumentSecurityException; 037import org.nuxeo.ecm.core.api.IdRef; 038import org.nuxeo.ecm.core.api.NuxeoException; 039import org.nuxeo.runtime.api.Framework; 040 041/** 042 * Base class for {@link FileSystemItemFactory} implementers. It is {@link DocumentModel} backed. 043 * 044 * @author Antoine Taillefer 045 * @see DefaultFileSystemItemFactory 046 */ 047public abstract class AbstractFileSystemItemFactory implements FileSystemItemFactory { 048 049 private static final Log log = LogFactory.getLog(AbstractFileSystemItemFactory.class); 050 051 protected String name; 052 053 /*--------------------------- FileSystemItemFactory ---------------------*/ 054 @Override 055 public abstract void handleParameters(Map<String, String> parameters); 056 057 @Override 058 public abstract boolean isFileSystemItem(DocumentModel doc, boolean includeDeleted, boolean relaxSyncRootConstraint); 059 060 /** 061 * Adapts the given {@link DocumentModel} to a {@link FileSystemItem}. 062 * 063 * @see #getFileSystemItem(DocumentModel, boolean, FolderItem, boolean, boolean, boolean) 064 */ 065 protected abstract FileSystemItem adaptDocument(DocumentModel doc, boolean forceParentItem, FolderItem parentItem, 066 boolean relaxSyncRootConstraint, boolean getLockInfo); 067 068 @Override 069 public String getName() { 070 return name; 071 } 072 073 @Override 074 public void setName(String name) { 075 this.name = name; 076 } 077 078 @Override 079 public boolean isFileSystemItem(DocumentModel doc) { 080 return isFileSystemItem(doc, false); 081 } 082 083 @Override 084 public boolean isFileSystemItem(DocumentModel doc, boolean includeDeleted) { 085 return isFileSystemItem(doc, includeDeleted, false); 086 } 087 088 @Override 089 public FileSystemItem getFileSystemItem(DocumentModel doc) { 090 return getFileSystemItem(doc, false); 091 } 092 093 @Override 094 public FileSystemItem getFileSystemItem(DocumentModel doc, boolean includeDeleted) { 095 return getFileSystemItem(doc, false, null, includeDeleted, false, true); 096 } 097 098 @Override 099 public FileSystemItem getFileSystemItem(DocumentModel doc, boolean includeDeleted, boolean relaxSyncRootConstraint) { 100 return getFileSystemItem(doc, false, null, includeDeleted, relaxSyncRootConstraint, true); 101 } 102 103 @Override 104 public FileSystemItem getFileSystemItem(DocumentModel doc, boolean includeDeleted, boolean relaxSyncRootConstraint, 105 boolean getLockInfo) { 106 return getFileSystemItem(doc, false, null, includeDeleted, relaxSyncRootConstraint, getLockInfo); 107 } 108 109 @Override 110 public FileSystemItem getFileSystemItem(DocumentModel doc, FolderItem parentItem) { 111 return getFileSystemItem(doc, parentItem, false); 112 } 113 114 @Override 115 public FileSystemItem getFileSystemItem(DocumentModel doc, FolderItem parentItem, boolean includeDeleted) { 116 return getFileSystemItem(doc, true, parentItem, includeDeleted, false, true); 117 } 118 119 @Override 120 public FileSystemItem getFileSystemItem(DocumentModel doc, FolderItem parentItem, boolean includeDeleted, 121 boolean relaxSyncRootConstraint) { 122 return getFileSystemItem(doc, true, parentItem, includeDeleted, relaxSyncRootConstraint, true); 123 } 124 125 @Override 126 public FileSystemItem getFileSystemItem(DocumentModel doc, FolderItem parentItem, boolean includeDeleted, 127 boolean relaxSyncRootConstraint, boolean getLockInfo) { 128 return getFileSystemItem(doc, true, parentItem, includeDeleted, relaxSyncRootConstraint, getLockInfo); 129 } 130 131 @Override 132 public boolean canHandleFileSystemItemId(String id) { 133 try { 134 parseFileSystemId(id); 135 } catch (IllegalArgumentException e) { 136 log.trace(e.getMessage()); 137 return false; 138 } 139 return true; 140 } 141 142 /** 143 * The default factory considers that a {@link FileSystemItem} with the given id exists if the backing 144 * {@link DocumentModel} can be fetched and {@link #isFileSystemItem(DocumentModel)} returns true. 145 * 146 * @see #isFileSystemItem(DocumentModel) 147 */ 148 @Override 149 public boolean exists(String id, Principal principal) { 150 String[] idFragments = parseFileSystemId(id); 151 String repositoryName = idFragments[1]; 152 String docId = idFragments[2]; 153 try (CoreSession session = CoreInstance.openCoreSession(repositoryName, principal)) { 154 DocumentModel doc = getDocumentById(docId, session); 155 return isFileSystemItem(doc); 156 } catch (DocumentNotFoundException e) { 157 if (log.isDebugEnabled()) { 158 log.debug(String.format("No doc related to id %s, returning false.", docId)); 159 } 160 return false; 161 } catch (DocumentSecurityException e) { 162 if (log.isDebugEnabled()) { 163 log.debug(String.format("User %s cannot access doc %s, returning false.", principal.getName(), docId)); 164 } 165 return false; 166 } 167 } 168 169 @Override 170 public FileSystemItem getFileSystemItemById(String id, Principal principal) { 171 String[] idFragments = parseFileSystemId(id); 172 String repositoryName = idFragments[1]; 173 String docId = idFragments[2]; 174 try (CoreSession session = CoreInstance.openCoreSession(repositoryName, principal)) { 175 DocumentModel doc = getDocumentById(docId, session); 176 return getFileSystemItem(doc); 177 } catch (DocumentNotFoundException e) { 178 if (log.isDebugEnabled()) { 179 log.debug(String.format("No doc related to id %s, returning null.", docId)); 180 } 181 return null; 182 } catch (DocumentSecurityException e) { 183 if (log.isDebugEnabled()) { 184 log.debug(String.format("User %s cannot access doc %s, returning null.", principal.getName(), docId)); 185 } 186 return null; 187 } 188 } 189 190 @Override 191 public FileSystemItem getFileSystemItemById(String id, String parentId, Principal principal) { 192 String[] idFragments = parseFileSystemId(id); 193 String repositoryName = idFragments[1]; 194 String docId = idFragments[2]; 195 try (CoreSession session = CoreInstance.openCoreSession(repositoryName, principal)) { 196 FileSystemItem parentItem = Framework.getService(FileSystemItemAdapterService.class) 197 .getFileSystemItemFactoryForId(parentId) 198 .getFileSystemItemById(parentId, principal); 199 if (!(parentItem instanceof FolderItem)) { 200 throw new NuxeoException(String.format("FileSystemItem with id %s should be a FolderItem", parentId)); 201 } 202 DocumentModel doc = getDocumentById(docId, session); 203 return getFileSystemItem(doc, (FolderItem) parentItem); 204 } catch (DocumentNotFoundException e) { 205 if (log.isDebugEnabled()) { 206 log.debug(String.format("No doc related to id %s, returning null.", docId)); 207 } 208 return null; 209 } catch (DocumentSecurityException e) { 210 if (log.isDebugEnabled()) { 211 log.debug(String.format("User %s cannot access doc %s, returning null.", principal.getName(), docId)); 212 } 213 return null; 214 } 215 } 216 217 @Deprecated 218 @Override 219 public DocumentModel getDocumentByFileSystemId(String id, Principal principal) { 220 // Parse id, expecting 221 // pattern:fileSystemItemFactoryName#repositoryName#docId 222 String[] idFragments = parseFileSystemId(id); 223 String repositoryName = idFragments[1]; 224 String docId = idFragments[2]; 225 CoreSession session = Framework.getService(FileSystemItemManager.class).getSession(repositoryName, 226 principal); 227 return getDocumentById(docId, session); 228 } 229 230 /*--------------------------- Protected ---------------------------------*/ 231 protected FileSystemItem adaptDocument(DocumentModel doc, boolean forceParentItem, FolderItem parentItem) { 232 return adaptDocument(doc, forceParentItem, parentItem, false, true); 233 } 234 235 protected FileSystemItem getFileSystemItem(DocumentModel doc, boolean forceParentItem, FolderItem parentItem, 236 boolean includeDeleted, boolean relaxSyncRootConstraint, boolean getLockInfo) { 237 238 // If the doc is not adaptable as a FileSystemItem return null 239 if (!isFileSystemItem(doc, includeDeleted, relaxSyncRootConstraint)) { 240 if (log.isTraceEnabled()) { 241 log.trace(String.format("Document %s cannot be adapted as a FileSystemItem => returning null.", 242 doc.getId())); 243 } 244 return null; 245 } 246 return adaptDocument(doc, forceParentItem, parentItem, relaxSyncRootConstraint, getLockInfo); 247 } 248 249 protected String[] parseFileSystemId(String id) { 250 251 // Parse id, expecting pattern: 252 // fileSystemItemFactoryName#repositoryName#docId 253 String[] idFragments = id.split(AbstractFileSystemItem.FILE_SYSTEM_ITEM_ID_SEPARATOR); 254 if (idFragments.length != 3) { 255 throw new IllegalArgumentException( 256 String.format( 257 "FileSystemItem id %s cannot be handled by factory named %s. Should match the 'fileSystemItemFactoryName#repositoryName#docId' pattern.", 258 id, name)); 259 } 260 261 // Check if factory name matches 262 String factoryName = idFragments[0]; 263 if (!name.equals(factoryName)) { 264 throw new IllegalArgumentException(String.format( 265 "Factoy name [%s] parsed from id %s does not match the actual factory name [%s].", factoryName, id, 266 name)); 267 } 268 return idFragments; 269 } 270 271 protected DocumentModel getDocumentById(String docId, CoreSession session) { 272 return session.getDocument(new IdRef(docId)); 273 } 274 275}