Search in sources :

Example 21 with FileState

use of org.alfresco.jlan.server.filesys.cache.FileState in project alfresco-repository by Alfresco.

the class ContentDiskDriver method closeFile.

/**
 * Close the file.
 *
 * @param sess Server session
 * @param tree Tree connection.
 * @param file Network file context.
 * @exception java.io.IOException If an error occurs.
 */
public void closeFile(SrvSession sess, TreeConnection tree, final NetworkFile file) throws IOException {
    if (logger.isDebugEnabled()) {
        logger.debug("Close file: file" + file);
    }
    // Get the associated file state
    final ContentContext ctx = (ContentContext) tree.getContext();
    FileState toUpdate = null;
    if (file instanceof ContentNetworkFile) {
        if (ctx.hasStateCache()) {
            FileState fstate = ctx.getStateCache().findFileState(file.getFullName());
            if (fstate != null) {
                if (file.getGrantedAccess() > NetworkFile.ATTRIBUTESONLY && fstate.decrementOpenCount() == 0)
                    fstate.setSharedAccess(SharingMode.READWRITE + SharingMode.DELETE);
                if (file.hasOpLock()) {
                    // Release the oplock
                    OpLockInterface flIface = (OpLockInterface) this;
                    OpLockManager oplockMgr = flIface.getOpLockManager(sess, tree);
                    oplockMgr.releaseOpLock(file.getOpLock().getPath());
                    if (logger.isDebugEnabled())
                        logger.debug("Released oplock for closed file, file=" + file.getFullName());
                }
                if (file.hasDeleteOnClose() == false && fstate.hasModifyDateTime() && fstate.hasFilesystemObject() && fstate.isDirectory() == false) {
                    // Update the modification date on the file/folder node
                    toUpdate = fstate;
                }
            }
        }
        // Decrement the file open count
        ContentNetworkFile contentFile = (ContentNetworkFile) file;
        if (contentFile.decrementOpenCount() > 0) {
            if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                logger.debug("Deferred file close, path=" + file.getFullName() + ", openCount=" + contentFile.getOpenCount());
            return;
        } else if (logger.isDebugEnabled())
            logger.debug("Last reference to file, closing, path=" + file.getFullName() + ", access=" + file.getGrantedAccessAsString() + ", fid=" + file.getProtocolId() + ", modified=" + contentFile.isModified());
    }
    // Check if there is a quota manager enabled
    long fileSize = 0L;
    if (ctx.hasQuotaManager() && file.hasDeleteOnClose()) {
        if (file instanceof ContentNetworkFile) {
            ContentNetworkFile contentFile = (ContentNetworkFile) file;
            if (contentFile.hasContent() == false)
                contentFile.openContent(false, false);
            // Save the current file size
            fileSize = contentFile.getFileSize();
        }
    }
    // Depending on whether the node has the NO_CONTENT aspect, we may have to wipe it out on error
    final CallableIO<Void> errorHandler = new CallableIO<Void>() {

        public Void call() throws IOException {
            if (file instanceof NodeRefNetworkFile) {
                NodeRef nodeRef = ((NodeRefNetworkFile) file).getNodeRef();
                if (nodeService.exists(nodeRef) && nodeService.hasAspect(nodeRef, ContentModel.ASPECT_NO_CONTENT)) {
                    logger.debug("No content - delete");
                    fileFolderService.delete(nodeRef);
                }
            }
            return null;
        }
    };
    try {
        // Perform repository updates in a retryable write transaction
        final FileState finalFileState = toUpdate;
        Pair<NodeRef, Boolean> result = doInWriteTransaction(sess, new CallableIO<Pair<NodeRef, Boolean>>() {

            public Pair<NodeRef, Boolean> call() throws IOException {
                if (file instanceof OpenOfficeContentNetworkFile) {
                    OpenOfficeContentNetworkFile ooFile = (OpenOfficeContentNetworkFile) file;
                    if (ooFile.truncatedToZeroLength()) {
                        // Inhibit versioning for this transaction
                        getPolicyFilter().disableBehaviour(ContentModel.ASPECT_VERSIONABLE);
                        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                            logger.debug("OpenOffice file truncation update only, inhibit versioning, " + file.getFullName());
                    }
                }
                // Update the modification date on the file/folder node
                if (finalFileState != null && file instanceof ContentNetworkFile) {
                    NodeRef nodeRef = (NodeRef) finalFileState.getFilesystemObject();
                    // Check if the file data has been updated, if not then inhibit versioning for this txn
                    // so the timestamp update does not generate a new file version
                    ContentNetworkFile contentFile = (ContentNetworkFile) file;
                    if (contentFile.isModified() == false && nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE)) {
                        // Stop a new file version being generated
                        getPolicyFilter().disableBehaviour(ContentModel.ASPECT_VERSIONABLE);
                        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                            logger.debug("Timestamp update only, inhibit versioning, " + file.getFullName());
                    }
                    // Update the modification timestamp
                    getPolicyFilter().disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
                    if (permissionService.hasPermission((NodeRef) finalFileState.getFilesystemObject(), PermissionService.WRITE_PROPERTIES) == AccessStatus.ALLOWED) {
                        nodeService.setProperty(nodeRef, ContentModel.PROP_MODIFIER, authService.getCurrentUserName());
                        Date modifyDate = new Date(finalFileState.getModifyDateTime());
                        nodeService.setProperty(nodeRef, ContentModel.PROP_MODIFIED, modifyDate);
                        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                            logger.debug("Updated modification timestamp, " + file.getFullName() + ", modTime=" + modifyDate);
                    }
                }
                // Defer to the network file to close the stream and remove the content
                file.close();
                if (file.hasDeleteOnClose()) {
                    logger.debug("File has delete on close");
                    if (file instanceof NodeRefNetworkFile) {
                        NodeRefNetworkFile nodeNetFile = (NodeRefNetworkFile) file;
                        final NodeRef nodeRef = nodeNetFile.getNodeRef();
                        if (fileFolderService.exists(nodeRef)) {
                            try {
                                boolean isVersionable = nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE);
                                try {
                                    // Delete the file
                                    FileState fileState = ctx.getStateCache().findFileState(file.getFullName());
                                    if (fileState != null && fileState.findAttribute(CanDeleteWithoutPerms) != null) {
                                        // Has CanDeleteWithoutPerms attribute, so delete from system user
                                        AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>() {

                                            @Override
                                            public Object doWork() throws Exception {
                                                logger.debug("delete as system" + nodeRef);
                                                fileFolderService.delete(nodeRef);
                                                return null;
                                            }
                                        }, AuthenticationUtil.getSystemUserName());
                                    } else {
                                        logger.debug("delete nodeRef:" + nodeRef);
                                        fileFolderService.delete(nodeRef);
                                    }
                                } catch (Exception ex) {
                                    logger.debug("on delete on close", ex);
                                    // Propagate retryable errors. Log the rest.
                                    if (RetryingTransactionHelper.extractRetryCause(ex) != null) {
                                        if (ex instanceof RuntimeException) {
                                            throw (RuntimeException) ex;
                                        } else {
                                            throw new AlfrescoRuntimeException("Error during delete on close, " + file.getFullName(), ex);
                                        }
                                    }
                                    if (logger.isWarnEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                                        logger.warn("Error during delete on close, " + file.getFullName(), ex);
                                }
                                // Return a node ref to update in the state table
                                return new Pair<NodeRef, Boolean>(nodeRef, isVersionable);
                            } catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) {
                                if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                                    logger.debug("Delete on close - access denied, " + file.getFullName());
                                throw new AccessDeniedException("Delete on close " + file.getFullName());
                            }
                        }
                    }
                }
                return null;
            }
        });
        if (result != null) {
            if (ctx.hasQuotaManager())
                ctx.getQuotaManager().releaseSpace(sess, tree, file.getFileId(), file.getFullName(), fileSize);
            if (ctx.hasStateCache()) {
                if (result.getSecond()) {
                    // Get, or create, the file state
                    FileState fState = ctx.getStateCache().findFileState(file.getFullName(), true);
                    // Indicate that the file was deleted via a delete on close request
                    fState.setFileStatus(DeleteOnClose);
                    // Make sure the file state is cached for a short while, save the noderef details
                    fState.setExpiryTime(System.currentTimeMillis() + FileState.RenameTimeout);
                    fState.setFilesystemObject(result.getFirst());
                } else {
                    // Remove the file state
                    ctx.getStateCache().removeFileState(file.getFullName());
                }
            }
        }
        if (logger.isDebugEnabled() && (ctx.hasDebug(AlfrescoContext.DBG_FILE) || ctx.hasDebug(AlfrescoContext.DBG_RENAME))) {
            logger.debug("Closed file: network file=" + file + " delete on close=" + file.hasDeleteOnClose());
            if (file.hasDeleteOnClose() == false && file instanceof ContentNetworkFile) {
                ContentNetworkFile cFile = (ContentNetworkFile) file;
                logger.debug("  File " + file.getFullName() + ", version=" + nodeService.getProperty(cFile.getNodeRef(), ContentModel.PROP_VERSION_LABEL));
            }
        }
    }// Make sure we clean up before propagating exceptions
     catch (IOException e) {
        try {
            doInWriteTransaction(sess, errorHandler);
        } catch (Throwable t) {
            logger.error(t.getMessage(), t);
        }
        throw e;
    } catch (RuntimeException e) {
        try {
            doInWriteTransaction(sess, errorHandler);
        } catch (Throwable t) {
            logger.error(t.getMessage(), t);
        }
        throw e;
    } catch (Error e) {
        try {
            doInWriteTransaction(sess, errorHandler);
        } catch (Throwable t) {
            logger.error(t.getMessage(), t);
        }
        throw e;
    }
}
Also used : FileState(org.alfresco.jlan.server.filesys.cache.FileState) AccessDeniedException(org.alfresco.jlan.server.filesys.AccessDeniedException) NodeRef(org.alfresco.service.cmr.repository.NodeRef) AlfrescoRuntimeException(org.alfresco.error.AlfrescoRuntimeException) Pair(org.alfresco.util.Pair) ContentIOException(org.alfresco.service.cmr.repository.ContentIOException) IOException(java.io.IOException) Date(java.util.Date) DiskFullException(org.alfresco.jlan.server.filesys.DiskFullException) FileSharingException(org.alfresco.jlan.server.filesys.FileSharingException) DeviceContextException(org.alfresco.jlan.server.core.DeviceContextException) FileExistsException(org.alfresco.jlan.server.filesys.FileExistsException) FileNotFoundException(java.io.FileNotFoundException) QuotaManagerException(org.alfresco.jlan.server.filesys.quota.QuotaManagerException) InvalidNodeRefException(org.alfresco.service.cmr.repository.InvalidNodeRefException) NodeLockedException(org.alfresco.service.cmr.lock.NodeLockedException) AccessDeniedException(org.alfresco.jlan.server.filesys.AccessDeniedException) ContentIOException(org.alfresco.service.cmr.repository.ContentIOException) IOException(java.io.IOException) AlfrescoRuntimeException(org.alfresco.error.AlfrescoRuntimeException) DirectoryNotEmptyException(org.alfresco.jlan.server.filesys.DirectoryNotEmptyException) OpLockInterface(org.alfresco.jlan.server.locking.OpLockInterface) AlfrescoRuntimeException(org.alfresco.error.AlfrescoRuntimeException) OpLockManager(org.alfresco.jlan.server.locking.OpLockManager)

Example 22 with FileState

use of org.alfresco.jlan.server.filesys.cache.FileState in project alfresco-repository by Alfresco.

the class ContentDiskDriver method createFile.

/**
 * Create a new file on the file system.
 *
 * <p>
 * WARNING : side effect - closes current transaction context.
 *
 * @param sess Server session
 * @param tree Tree connection
 * @param params File create parameters
 * @return NetworkFile
 * @exception java.io.IOException If an error occurs.
 */
public NetworkFile createFile(SrvSession sess, final TreeConnection tree, final FileOpenParams params) throws IOException {
    final ContentContext ctx = (ContentContext) tree.getContext();
    try {
        // Access the repository in a retryable write transaction
        Pair<String, NodeRef> result = doInWriteTransaction(sess, new CallableIO<Pair<String, NodeRef>>() {

            public Pair<String, NodeRef> call() throws IOException {
                // Get the device root
                NodeRef deviceRootNodeRef = ctx.getRootNode();
                String path = params.getPath();
                String parentPath = null;
                if (ctx.hasStateCache()) {
                    // See if the parent folder has a file state, we can avoid having to walk the path
                    String[] paths = FileName.splitPath(path);
                    if (paths[0] != null && paths[0].length() > 1) {
                        // Find the node ref for the folder being searched
                        NodeRef nodeRef = getNodeForPath(tree, paths[0]);
                        if (nodeRef != null) {
                            deviceRootNodeRef = nodeRef;
                            path = paths[1];
                            if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                                logger.debug("Create file using cached noderef for path " + paths[0]);
                        }
                        parentPath = paths[0];
                    }
                }
                // Create it - the path will be created, if necessary
                if (logger.isDebugEnabled()) {
                    logger.debug("create new file" + path);
                }
                NodeRef nodeRef = null;
                try {
                    nodeRef = cifsHelper.createNode(deviceRootNodeRef, path, ContentModel.TYPE_CONTENT);
                    nodeService.addAspect(nodeRef, ContentModel.ASPECT_NO_CONTENT, null);
                } catch (FileExistsException ex) {
                    nodeRef = cifsHelper.getNodeRef(deviceRootNodeRef, path);
                    if (!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_SOFT_DELETE)) {
                        throw ex;
                    }
                }
                return new Pair<String, NodeRef>(parentPath, nodeRef);
            }
        });
        // Get or create the file state for the parent folder
        FileState parentState = null;
        String parentPath = result.getFirst();
        if (parentPath != null) {
            parentState = getStateForPath(tree, parentPath);
            if (parentState == null && ctx.hasStateCache())
                parentState = ctx.getStateCache().findFileState(parentPath, true);
        }
        NodeRef nodeRef = result.getSecond();
        if (nodeRef != null && nodeService.hasAspect(nodeRef, ContentModel.ASPECT_SOFT_DELETE)) {
            nodeService.removeAspect(nodeRef, ContentModel.ASPECT_SOFT_DELETE);
        }
        // Create the network file
        ContentNetworkFile netFile = ContentNetworkFile.createFile(nodeService, contentService, mimetypeService, cifsHelper, result.getSecond(), params.getPath(), params.isReadOnlyAccess(), params.isAttributesOnlyAccess(), sess);
        // Always allow write access to a newly created file
        netFile.setGrantedAccess(NetworkFile.READWRITE);
        // Set the owner process id for this open file
        netFile.setProcessId(params.getProcessId());
        // Truncate the file so that the content stream is created
        netFile.truncateFile(0L);
        // Indicate the file is open
        netFile.setClosed(false);
        if (netFile != null) {
            long id = DefaultTypeConverter.INSTANCE.convert(Long.class, nodeService.getProperty(netFile.getNodeRef(), ContentModel.PROP_NODE_DBID));
            netFile.setFileId((int) (id & 0xFFFFFFFFL));
        }
        if (ctx.hasStateCache()) {
            FileState fstate = ctx.getStateCache().findFileState(params.getPath(), true);
            if (fstate != null) {
                // Save the file sharing mode, needs to be done before the open count is incremented
                fstate.setSharedAccess(params.getSharedAccess());
                fstate.setProcessId(params.getProcessId());
                // Indicate that the file is open
                fstate.setFileStatus(FileExists);
                fstate.incrementOpenCount();
                fstate.setFilesystemObject(result.getSecond());
                // Track the intial allocation size
                fstate.setAllocationSize(params.getAllocationSize());
                // Store the file state with the file
                netFile.setFileState(fstate);
                if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                    logger.debug("Create file, state=" + fstate);
            }
            if (parentState != null)
                parentState.updateModifyDateTime();
        }
        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
            logger.debug("Created file: path=" + params.getPath() + " file open parameters=" + params + " node=" + result.getSecond() + " network file=" + netFile);
        return netFile;
    } catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) {
        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
            logger.debug("Create file - access denied, " + params.getFullPath());
        throw new AccessDeniedException("Create file " + params.getFullPath());
    } catch (ContentIOException ex) {
        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
            logger.debug("Create file - content I/O error, " + params.getFullPath());
        throw new DiskFullException("Create file " + params.getFullPath());
    } catch (RuntimeException ex) {
        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
            logger.debug("Create file error", ex);
        throw new IOException("Create file " + params.getFullPath(), ex);
    }
}
Also used : FileState(org.alfresco.jlan.server.filesys.cache.FileState) AccessDeniedException(org.alfresco.jlan.server.filesys.AccessDeniedException) ContentIOException(org.alfresco.service.cmr.repository.ContentIOException) IOException(java.io.IOException) ContentIOException(org.alfresco.service.cmr.repository.ContentIOException) NodeRef(org.alfresco.service.cmr.repository.NodeRef) AlfrescoRuntimeException(org.alfresco.error.AlfrescoRuntimeException) DiskFullException(org.alfresco.jlan.server.filesys.DiskFullException) Pair(org.alfresco.util.Pair) FileExistsException(org.alfresco.jlan.server.filesys.FileExistsException)

Example 23 with FileState

use of org.alfresco.jlan.server.filesys.cache.FileState in project alfresco-repository by Alfresco.

the class ContentDiskDriver method fileExists.

/**
 * Check if the specified file exists, and whether it is a file or directory.
 *
 * <p>
 * WARNING: side effect, commit or roll back current user transaction context.  Current transaction becomes read only.
 *
 * @param sess Server session
 * @param tree Tree connection
 * @param name the path of the file
 * @return FileStatus (0: NotExist, 1 : FileExist, 2: DirectoryExists)
 * @see FileStatus
 */
public int fileExists(SrvSession sess, TreeConnection tree, String name) {
    ContentContext ctx = (ContentContext) tree.getContext();
    int status = FileStatus.Unknown;
    FileState fstate = null;
    try {
        if (ctx.hasStateCache())
            fstate = ctx.getStateCache().findFileState(name, true);
        if (fstate != null && fstate.getFileStatus() != FileUnknown) {
            status = fstate.getFileStatus();
            if (status >= CustomFileStatus)
                status = FileNotExist;
            if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO))
                logger.debug("Cache hit - fileExists() " + name + ", sts=" + status);
        } else {
            if (status == FileStatus.Unknown) {
                // Create the transaction
                beginReadTransaction(sess);
                // Get the file information to check if the file/folder exists
                FileInfo info = getFileInformation(sess, tree, name);
                NodeRef nodeRef = getNodeOrNull(name, ctx, fstate);
                nodeRef = ((null == nodeRef) && (info instanceof ContentFileInfo)) ? (((ContentFileInfo) info).getNodeRef()) : (nodeRef);
                if ((null == nodeRef) || !fileFolderService.exists(nodeRef)) {
                    status = FileStatus.NotExist;
                } else {
                    if (info.isDirectory()) {
                        status = FileStatus.DirectoryExists;
                    } else {
                        status = FileStatus.FileExists;
                    }
                }
                if (fstate != null)
                    fstate.setFileStatus(status);
            }
        }
    } catch (FileNotFoundException e) {
        status = FileStatus.NotExist;
        if (fstate != null)
            fstate.setFileStatus(status);
    } catch (IOException e) {
        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO))
            logger.debug("File exists error, " + name, e);
        status = FileStatus.NotExist;
    }
    if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO))
        logger.debug("File status determined: name=" + name + " status=" + fileStatusString(fstate.getFileStatus()));
    return status;
}
Also used : FileState(org.alfresco.jlan.server.filesys.cache.FileState) NodeRef(org.alfresco.service.cmr.repository.NodeRef) FileInfo(org.alfresco.jlan.server.filesys.FileInfo) FileNotFoundException(java.io.FileNotFoundException) ContentIOException(org.alfresco.service.cmr.repository.ContentIOException) IOException(java.io.IOException)

Example 24 with FileState

use of org.alfresco.jlan.server.filesys.cache.FileState in project alfresco-repository by Alfresco.

the class ContentDiskDriver method getNodeForPath.

/**
 * Get the node for the specified path
 *
 * @param tree TreeConnection
 * @param path String
 * @return NodeRef
 * @exception FileNotFoundException
 */
public NodeRef getNodeForPath(TreeConnection tree, String path) throws FileNotFoundException {
    // Check if there is a cached state for the path
    ContentContext ctx = (ContentContext) tree.getContext();
    NodeRef result = null;
    if (ctx.hasStateCache()) {
        // Try and get the node ref from an in memory file state
        FileState fstate = ctx.getStateCache().findFileState(path);
        if (null != (result = getNodeOrNull(path, ctx, fstate))) {
            return result;
        }
    }
    return cifsHelper.getNodeRef(ctx.getRootNode(), path);
}
Also used : NodeRef(org.alfresco.service.cmr.repository.NodeRef) FileState(org.alfresco.jlan.server.filesys.cache.FileState)

Example 25 with FileState

use of org.alfresco.jlan.server.filesys.cache.FileState in project alfresco-repository by Alfresco.

the class ContentDiskDriver method openFile.

/**
 * Open a file or folder
 *
 * @param sess SrvSession
 * @param tree TreeConnection
 * @param params FileOpenParams
 * @return NetworkFile
 * @exception IOException
 */
public NetworkFile openFile(SrvSession sess, TreeConnection tree, FileOpenParams params) throws IOException {
    // Create the transaction
    beginReadTransaction(sess);
    ContentContext ctx = (ContentContext) tree.getContext();
    try {
        // Not a pseudo file, try and open a normal file/folder node
        NodeRef nodeRef = getNodeForPath(tree, params.getPath());
        if (params.hasAccessMode(AccessMode.NTRead) && permissionService.hasPermission(nodeRef, PermissionService.READ) == AccessStatus.DENIED)
            throw new AccessDeniedException("No read access to " + params.getFullPath());
        if (params.hasAccessMode(AccessMode.NTWrite) && permissionService.hasPermission(nodeRef, PermissionService.WRITE) == AccessStatus.DENIED)
            throw new AccessDeniedException("No write access to " + params.getFullPath());
        // Check for delete access
        // if ( params.hasAccessMode(AccessMode.NTDelete) &&
        // permissionService.hasPermission(nodeRef, PermissionService.DELETE) == AccessStatus.DENIED)
        // throw new AccessDeniedException("No delete access to " + params.getFullPath());
        // Check if the file has a lock
        String lockTypeStr = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_LOCK_TYPE);
        if (params.hasAccessMode(AccessMode.NTWrite) && lockTypeStr != null)
            throw new AccessDeniedException("File is locked, no write access to " + params.getFullPath());
        // Check if there is a file state for the file
        FileState fstate = null;
        if (ctx.hasStateCache()) {
            // Check if there is a file state for the file
            fstate = ctx.getStateCache().findFileState(params.getPath());
            if (fstate != null) {
                if (fstate.exists() == false)
                    throw new FileNotFoundException();
            } else {
                // Create a file state for the path
                fstate = ctx.getStateCache().findFileState(params.getPath(), true);
            }
            // Check if the current file open allows the required shared access
            boolean nosharing = false;
            String noshrReason = null;
            if (params.getAccessMode() == AccessMode.NTFileGenericExecute && params.getPath().toLowerCase().endsWith(".exe") == false) {
                if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE)) {
                    logger.debug("Execute access mode, path" + params.getPath());
                    logger.debug("  Fstate=" + fstate);
                }
                throw new AccessDeniedException("Invalid access mode");
            }
            if (fstate.getOpenCount() > 0 && params.isAttributesOnlyAccess() == false) {
                if (params.getSecurityLevel() == WinNT.SecurityImpersonation && params.getProcessId() == fstate.getProcessId())
                    nosharing = false;
                else if (params.isReadOnlyAccess() && (fstate.getSharedAccess() & SharingMode.READ) != 0)
                    nosharing = false;
                else if ((params.isReadWriteAccess() || params.isWriteOnlyAccess()) && (fstate.getSharedAccess() & SharingMode.WRITE) == 0) {
                    nosharing = true;
                    noshrReason = "Sharing mode disallows write";
                    if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                        logger.debug("Sharing mode disallows write access path=" + params.getPath());
                } else if (fstate.getSharedAccess() == SharingMode.NOSHARING) {
                    nosharing = true;
                    noshrReason = "Sharing mode exclusive";
                } else if ((fstate.getSharedAccess() & params.getSharedAccess()) != params.getSharedAccess()) {
                    nosharing = true;
                    noshrReason = "Sharing mode mismatch";
                    if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                        logger.debug("Local share mode=0x" + Integer.toHexString(fstate.getSharedAccess()) + ", params share mode=0x" + Integer.toHexString(params.getSharedAccess()));
                } else if (params.getSharedAccess() == SharingMode.NOSHARING) {
                    nosharing = true;
                    noshrReason = "Requestor wants exclusive mode";
                }
            }
            if (nosharing == true) {
                if (params.getPath().equals("\\") == false) {
                    if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                        logger.debug("Sharing violation path=" + params.getPath() + ", sharing=0x" + Integer.toHexString(fstate.getSharedAccess()) + ",reason=" + noshrReason);
                    throw new FileSharingException("File already open, " + params.getPath());
                }
            }
            // Update the file sharing mode and process id, if this is the first file open
            fstate.setSharedAccess(params.getSharedAccess());
            fstate.setProcessId(params.getProcessId());
            if (logger.isDebugEnabled() && fstate.getOpenCount() == 0 && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                logger.debug("Path " + params.getPath() + ", sharing=0x" + Integer.toHexString(params.getSharedAccess()) + ", PID=" + params.getProcessId());
        }
        // Check if the node is a link node
        NodeRef linkRef = (NodeRef) nodeService.getProperty(nodeRef, ContentModel.PROP_LINK_DESTINATION);
        AlfrescoNetworkFile netFile = null;
        if (linkRef == null) {
            if (tree.openFileCount() > 0 && params.isAttributesOnlyAccess() == false) {
                // Search the open file table for this session/virtual circuit
                int idx = 0;
                while (idx < tree.getFileTableLength() && netFile == null) {
                    // Get the current file from the open file table
                    NetworkFile curFile = tree.findFile(idx);
                    if (curFile != null && curFile instanceof ContentNetworkFile) {
                        // Check if the file is the same path and process id
                        ContentNetworkFile contentFile = (ContentNetworkFile) curFile;
                        if (contentFile.getProcessId() == params.getProcessId() && contentFile.getFullName().equalsIgnoreCase(params.getFullPath())) {
                            if ((params.isReadWriteAccess() && contentFile.getGrantedAccess() == NetworkFile.READWRITE) || (params.isReadOnlyAccess() && contentFile.getGrantedAccess() == NetworkFile.READONLY)) {
                                // Found a match, re-use the open file
                                netFile = contentFile;
                                // Increment the file open count, last file close will actually close the file/stream
                                contentFile.incrementOpenCount();
                                if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                                    logger.debug("Re-use existing file open Path " + params.getPath() + ", PID=" + params.getProcessId() + ", params=" + (params.isReadOnlyAccess() ? "ReadOnly" : "Write") + ", file=" + (contentFile.getGrantedAccess() <= NetworkFile.READONLY ? "ReadOnly" : "Write"));
                            } else if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                                logger.debug("Not re-using file path=" + params.getPath() + ", readWrite=" + (params.isReadWriteAccess() ? "true" : "false") + ", readOnly=" + (params.isReadOnlyAccess() ? "true" : "false") + ", grantedAccess=" + contentFile.getGrantedAccessAsString());
                        }
                    }
                    // Update the file table index
                    idx++;
                }
            }
            if (netFile == null) {
                // Create a new network file for the open request
                netFile = ContentNetworkFile.createFile(nodeService, contentService, mimetypeService, cifsHelper, nodeRef, params.getPath(), params.isReadOnlyAccess(), params.isAttributesOnlyAccess(), sess);
            }
        } else {
            // Get the CIFS server name
            String srvName = null;
            SMBServer cifsServer = (SMBServer) sess.getServer().getConfiguration().findServer("CIFS");
            if (sess instanceof SMBSrvSession) {
                SMBSrvSession smbSess = (SMBSrvSession) sess;
                srvName = smbSess.getShareHostName();
            } else if (cifsServer != null) {
                // Use the CIFS server name in the URL
                srvName = cifsServer.getServerName();
            } else {
                // Use the local server name in the URL
                srvName = InetAddress.getLocalHost().getHostName();
            }
            // Convert the target node to a path, convert to URL format
            String path = getPathForNode(tree, linkRef);
            path = path.replace(FileName.DOS_SEPERATOR, '/');
            // Build the URL file data
            StringBuilder urlStr = new StringBuilder();
            urlStr.append("[InternetShortcut]\r\n");
            urlStr.append("URL=file://");
            urlStr.append(srvName);
            urlStr.append("/");
            urlStr.append(tree.getSharedDevice().getName());
            urlStr.append(path);
            urlStr.append("\r\n");
            // Create the in memory pseudo file for the URL link
            byte[] urlData = urlStr.toString().getBytes();
            // Get the file information for the link node
            FileInfo fInfo = cifsHelper.getFileInformation(nodeRef, isReadOnly, isLockedFilesAsOffline);
            // Set the file size to the actual data length
            fInfo.setFileSize(urlData.length);
            // Create the network file using the in-memory file data
            netFile = new LinkMemoryNetworkFile(fInfo.getFileName(), urlData, fInfo, nodeRef);
            netFile.setFullName(params.getPath());
        }
        if (netFile != null) {
            long id = DefaultTypeConverter.INSTANCE.convert(Long.class, nodeService.getProperty(nodeRef, ContentModel.PROP_NODE_DBID));
            netFile.setFileId((int) (id & 0xFFFFFFFFL));
            // Indicate the file is open
            netFile.setClosed(false);
        }
        if (params.isOverwrite() && netFile != null) {
            // Truncate the file to zero length
            netFile.truncateFile(0L);
        }
        if (ctx.hasStateCache()) {
            if (fstate == null)
                fstate = ctx.getStateCache().findFileState(params.getPath(), true);
            if (netFile.getGrantedAccess() > NetworkFile.ATTRIBUTESONLY)
                fstate.incrementOpenCount();
            fstate.setFilesystemObject(nodeRef);
            // Store the state with the file
            netFile.setFileState(fstate);
            if (fstate.hasFileSize())
                netFile.setFileSize(fstate.getFileSize());
        }
        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
            logger.debug("Opened network file: path=" + params.getPath() + " file open parameters=" + params + " network file=" + netFile);
        return netFile;
    } catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) {
        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
            logger.debug("Open file - access denied, " + params.getFullPath());
        throw new AccessDeniedException("Open file " + params.getFullPath());
    } catch (RuntimeException ex) {
        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
            logger.debug("Open file error", ex);
        throw new IOException("Open file " + params.getFullPath());
    }
}
Also used : FileState(org.alfresco.jlan.server.filesys.cache.FileState) AccessDeniedException(org.alfresco.jlan.server.filesys.AccessDeniedException) FileNotFoundException(java.io.FileNotFoundException) NodeRef(org.alfresco.service.cmr.repository.NodeRef) AlfrescoRuntimeException(org.alfresco.error.AlfrescoRuntimeException) AlfrescoNetworkFile(org.alfresco.filesys.alfresco.AlfrescoNetworkFile) FileInfo(org.alfresco.jlan.server.filesys.FileInfo) SMBSrvSession(org.alfresco.jlan.smb.server.SMBSrvSession) NetworkFile(org.alfresco.jlan.server.filesys.NetworkFile) AlfrescoNetworkFile(org.alfresco.filesys.alfresco.AlfrescoNetworkFile) SMBServer(org.alfresco.jlan.smb.server.SMBServer) ContentIOException(org.alfresco.service.cmr.repository.ContentIOException) IOException(java.io.IOException) FileSharingException(org.alfresco.jlan.server.filesys.FileSharingException)

Aggregations

FileState (org.alfresco.jlan.server.filesys.cache.FileState)28 IOException (java.io.IOException)14 ContentIOException (org.alfresco.service.cmr.repository.ContentIOException)12 NodeRef (org.alfresco.service.cmr.repository.NodeRef)12 AlfrescoRuntimeException (org.alfresco.error.AlfrescoRuntimeException)10 AccessDeniedException (org.alfresco.jlan.server.filesys.AccessDeniedException)9 FileNotFoundException (java.io.FileNotFoundException)8 FileStateCache (org.alfresco.jlan.server.filesys.cache.FileStateCache)8 FileInfo (org.alfresco.jlan.server.filesys.FileInfo)6 Date (java.util.Date)5 DirectoryNotEmptyException (org.alfresco.jlan.server.filesys.DirectoryNotEmptyException)4 QuotaManager (org.alfresco.jlan.server.filesys.quota.QuotaManager)4 Pair (org.alfresco.util.Pair)4 NetworkFileLegacyReferenceCount (org.alfresco.filesys.alfresco.NetworkFileLegacyReferenceCount)3 DiskFullException (org.alfresco.jlan.server.filesys.DiskFullException)3 FileAccessToken (org.alfresco.jlan.server.filesys.FileAccessToken)3 FileExistsException (org.alfresco.jlan.server.filesys.FileExistsException)3 FileSharingException (org.alfresco.jlan.server.filesys.FileSharingException)3 NetworkFile (org.alfresco.jlan.server.filesys.NetworkFile)3 NodeLockedException (org.alfresco.service.cmr.lock.NodeLockedException)3