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