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