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