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 <[email protected]> 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.CloseableCoreSession; 029import org.nuxeo.ecm.core.api.CoreInstance; 030import org.nuxeo.ecm.core.api.CoreSession; 031import org.nuxeo.ecm.core.api.DocumentModel; 032import org.nuxeo.ecm.core.api.DocumentNotFoundException; 033import org.nuxeo.ecm.core.api.DocumentSecurityException; 034import org.nuxeo.ecm.core.api.IdRef; 035import org.nuxeo.ecm.core.api.NuxeoException; 036import org.nuxeo.ecm.core.api.NuxeoPrincipal; 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 Logger log = LogManager.getLogger(AbstractFileSystemItemFactory.class); 048 049 protected String name; 050 051 /** 052 * Adapts the given {@link DocumentModel} to a {@link FileSystemItem}. 053 * 054 * @see #getFileSystemItem(DocumentModel, boolean, FolderItem, boolean, boolean, boolean) 055 */ 056 protected abstract FileSystemItem adaptDocument(DocumentModel doc, boolean forceParentItem, FolderItem parentItem, 057 boolean relaxSyncRootConstraint, boolean getLockInfo); 058 059 @Override 060 public String getName() { 061 return name; 062 } 063 064 @Override 065 public void setName(String name) { 066 this.name = name; 067 } 068 069 @Override 070 public boolean isFileSystemItem(DocumentModel doc) { 071 return isFileSystemItem(doc, false); 072 } 073 074 @Override 075 public boolean isFileSystemItem(DocumentModel doc, boolean includeDeleted) { 076 return isFileSystemItem(doc, includeDeleted, false); 077 } 078 079 @Override 080 public FileSystemItem getFileSystemItem(DocumentModel doc) { 081 return getFileSystemItem(doc, false); 082 } 083 084 @Override 085 public FileSystemItem getFileSystemItem(DocumentModel doc, boolean includeDeleted) { 086 return getFileSystemItem(doc, false, null, includeDeleted, false, true); 087 } 088 089 @Override 090 public FileSystemItem getFileSystemItem(DocumentModel doc, boolean includeDeleted, 091 boolean relaxSyncRootConstraint) { 092 return getFileSystemItem(doc, false, null, includeDeleted, relaxSyncRootConstraint, true); 093 } 094 095 @Override 096 public FileSystemItem getFileSystemItem(DocumentModel doc, boolean includeDeleted, boolean relaxSyncRootConstraint, 097 boolean getLockInfo) { 098 return getFileSystemItem(doc, false, null, includeDeleted, relaxSyncRootConstraint, getLockInfo); 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, true); 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, true); 115 } 116 117 @Override 118 public FileSystemItem getFileSystemItem(DocumentModel doc, FolderItem parentItem, boolean includeDeleted, 119 boolean relaxSyncRootConstraint, boolean getLockInfo) { 120 return getFileSystemItem(doc, true, parentItem, includeDeleted, relaxSyncRootConstraint, getLockInfo); 121 } 122 123 @Override 124 public boolean canHandleFileSystemItemId(String id) { 125 try { 126 parseFileSystemId(id); 127 } catch (IllegalArgumentException e) { 128 log.trace(e::getMessage); 129 return false; 130 } 131 return true; 132 } 133 134 /** 135 * The default factory considers that a {@link FileSystemItem} with the given id exists if the backing 136 * {@link DocumentModel} can be fetched and {@link #isFileSystemItem(DocumentModel)} returns true. 137 * 138 * @see #isFileSystemItem(DocumentModel) 139 */ 140 @Override 141 public boolean exists(String id, NuxeoPrincipal principal) { 142 String[] idFragments = parseFileSystemId(id); 143 String repositoryName = idFragments[1]; 144 String docId = idFragments[2]; 145 try (CloseableCoreSession session = CoreInstance.openCoreSession(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 (CloseableCoreSession session = CoreInstance.openCoreSession(repositoryName, principal)) { 163 DocumentModel doc = getDocumentById(docId, session); 164 return getFileSystemItem(doc); 165 } catch (DocumentNotFoundException e) { 166 167 log.debug("No doc related to id {}, returning null.", docId); 168 return null; 169 } catch (DocumentSecurityException e) { 170 log.debug("User {} cannot access doc {}, returning null.", principal, docId); 171 return null; 172 } 173 } 174 175 @Override 176 public FileSystemItem getFileSystemItemById(String id, String parentId, NuxeoPrincipal principal) { 177 String[] idFragments = parseFileSystemId(id); 178 String repositoryName = idFragments[1]; 179 String docId = idFragments[2]; 180 try (CloseableCoreSession session = CoreInstance.openCoreSession(repositoryName, principal)) { 181 FileSystemItem parentItem = Framework.getService(FileSystemItemAdapterService.class) 182 .getFileSystemItemFactoryForId(parentId) 183 .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 log.debug("No doc related to id {}, returning null.", docId); 191 return null; 192 } catch (DocumentSecurityException e) { 193 log.debug("User {} cannot access doc {}, returning null.", principal, docId); 194 return null; 195 } 196 197 } 198 199 /*--------------------------- Protected ---------------------------------*/ 200 protected FileSystemItem adaptDocument(DocumentModel doc, boolean forceParentItem, FolderItem parentItem) { 201 return adaptDocument(doc, forceParentItem, parentItem, false, true); 202 } 203 204 protected FileSystemItem getFileSystemItem(DocumentModel doc, boolean forceParentItem, FolderItem parentItem, 205 boolean includeDeleted, boolean relaxSyncRootConstraint, boolean getLockInfo) { 206 207 // If the doc is not adaptable as a FileSystemItem return null 208 if (!isFileSystemItem(doc, includeDeleted, relaxSyncRootConstraint)) { 209 log.trace("Document {} cannot be adapted as a FileSystemItem => returning null.", doc::getId); 210 return null; 211 } 212 return adaptDocument(doc, forceParentItem, parentItem, relaxSyncRootConstraint, getLockInfo); 213 } 214 215 protected String[] parseFileSystemId(String id) { 216 217 // Parse id, expecting pattern: 218 // fileSystemItemFactoryName#repositoryName#docId 219 String[] idFragments = id.split(AbstractFileSystemItem.FILE_SYSTEM_ITEM_ID_SEPARATOR); 220 if (idFragments.length != 3) { 221 throw new IllegalArgumentException(String.format( 222 "FileSystemItem id %s cannot be handled by factory named %s. Should match the 'fileSystemItemFactoryName#repositoryName#docId' pattern.", 223 id, name)); 224 } 225 226 // Check if factory name matches 227 String factoryName = idFragments[0]; 228 if (!name.equals(factoryName)) { 229 throw new IllegalArgumentException( 230 String.format("Factoy name [%s] parsed from id %s does not match the actual factory name [%s].", 231 factoryName, id, name)); 232 } 233 return idFragments; 234 } 235 236 protected DocumentModel getDocumentById(String docId, CoreSession session) { 237 return session.getDocument(new IdRef(docId)); 238 } 239 240}