mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-16 17:55:15 +00:00
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@10303 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
893 lines
26 KiB
Java
893 lines
26 KiB
Java
/*
|
|
* Copyright (C) 2006-2008 Alfresco Software Limited.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
* As a special exception to the terms and conditions of version 2.0 of
|
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
|
* FLOSS exception. You should have recieved a copy of the text describing
|
|
* the FLOSS exception, and it is also available here:
|
|
* http://www.alfresco.com/legal/licensing"
|
|
*/
|
|
|
|
package org.alfresco.filesys.repo;
|
|
|
|
import java.io.Serializable;
|
|
import java.util.Map;
|
|
|
|
import javax.transaction.UserTransaction;
|
|
|
|
import org.alfresco.filesys.state.FileState;
|
|
import org.alfresco.filesys.state.FileStateTable;
|
|
import org.alfresco.jlan.server.filesys.FileStatus;
|
|
import org.alfresco.jlan.server.filesys.NotifyChange;
|
|
import org.alfresco.jlan.smb.server.notify.NotifyChangeHandler;
|
|
import org.alfresco.model.ContentModel;
|
|
import org.alfresco.repo.node.NodeServicePolicies;
|
|
import org.alfresco.repo.policy.JavaBehaviour;
|
|
import org.alfresco.repo.policy.PolicyComponent;
|
|
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
|
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
|
import org.alfresco.repo.transaction.TransactionListenerAdapter;
|
|
import org.alfresco.service.cmr.model.FileFolderService;
|
|
import org.alfresco.service.cmr.model.FileFolderServiceType;
|
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.NodeService;
|
|
import org.alfresco.service.cmr.repository.Path;
|
|
import org.alfresco.service.cmr.repository.StoreRef;
|
|
import org.alfresco.service.cmr.security.PermissionService;
|
|
import org.alfresco.service.namespace.NamespaceService;
|
|
import org.alfresco.service.namespace.QName;
|
|
import org.alfresco.service.transaction.TransactionService;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
/**
|
|
* Node Monitor Class
|
|
*
|
|
* <p>Monitor node events from the node service to update the file state cache and feed notification events into
|
|
* the file server change notification handler.
|
|
*
|
|
* @author gkspencer
|
|
*/
|
|
public class NodeMonitor extends TransactionListenerAdapter
|
|
implements NodeServicePolicies.OnCreateNodePolicy,
|
|
NodeServicePolicies.OnUpdatePropertiesPolicy,
|
|
NodeServicePolicies.BeforeDeleteNodePolicy,
|
|
NodeServicePolicies.OnMoveNodePolicy,
|
|
Runnable
|
|
{
|
|
// Logging
|
|
|
|
private static final Log logger = LogFactory.getLog(NodeMonitor.class);
|
|
|
|
// Transaction object binding keys
|
|
|
|
public static final String FileSysNodeEvent = "FileSysNodeEvent";
|
|
public static final String FileSysNodeEvent2 = "FileSysNodeEvent2";
|
|
|
|
// Services/components
|
|
|
|
private PolicyComponent m_policyComponent;
|
|
private NodeService m_nodeService;
|
|
private FileFolderService m_fileFolderService;
|
|
private PermissionService m_permissionService;
|
|
private TransactionService m_transService;
|
|
|
|
// Filesystem driver and context
|
|
|
|
private ContentDiskDriver m_filesysDriver;
|
|
private ContentContext m_filesysCtx;
|
|
|
|
// File state table and change notification handler
|
|
|
|
private FileStateTable m_stateTable;
|
|
private NotifyChangeHandler m_changeHandler;
|
|
|
|
// Root node path and store
|
|
|
|
private String m_rootPath;
|
|
private StoreRef m_storeRef;
|
|
|
|
// Queue of node update events
|
|
|
|
private NodeEventQueue m_eventQueue;
|
|
|
|
// Thread for the main event processing
|
|
|
|
private Thread m_thread;
|
|
private boolean m_shutdown;
|
|
|
|
/**
|
|
* Class constructor
|
|
*
|
|
* @param filesysDriver ContentDiskDriver
|
|
* @param filesysCtx ContentContext
|
|
*/
|
|
public NodeMonitor( ContentDiskDriver filesysDriver, ContentContext filesysCtx) {
|
|
m_filesysDriver = filesysDriver;
|
|
m_filesysCtx = filesysCtx;
|
|
|
|
// Initialize the node monitor
|
|
|
|
init();
|
|
}
|
|
|
|
/**
|
|
* Initialize the node monitor
|
|
*/
|
|
public final void init() {
|
|
|
|
// Get various services via the filesystem driver
|
|
|
|
m_nodeService = m_filesysDriver.getNodeService();
|
|
m_policyComponent = m_filesysDriver.getPolicyComponent();
|
|
m_fileFolderService = m_filesysDriver.getFileFolderService();
|
|
m_permissionService = m_filesysDriver.getPermissionService();
|
|
m_transService = m_filesysDriver.getTransactionService();
|
|
|
|
// Disable change notifications from the file server
|
|
|
|
m_filesysCtx.setFileServerNotifications( false);
|
|
|
|
// Register for node service events
|
|
|
|
m_policyComponent.bindClassBehaviour( QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateNode"),
|
|
this, new JavaBehaviour(this, "onCreateNode"));
|
|
m_policyComponent.bindClassBehaviour( QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
|
|
this, new JavaBehaviour(this, "beforeDeleteNode"));
|
|
m_policyComponent.bindClassBehaviour( QName.createQName(NamespaceService.ALFRESCO_URI, "onDeleteNode"),
|
|
this, new JavaBehaviour(this, "onDeleteNode"));
|
|
m_policyComponent.bindClassBehaviour( QName.createQName(NamespaceService.ALFRESCO_URI, "onMoveNode"),
|
|
this, new JavaBehaviour(this, "onMoveNode"));
|
|
m_policyComponent.bindClassBehaviour( QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
|
|
this, new JavaBehaviour(this, "onUpdateProperties"));
|
|
|
|
// Get the store
|
|
|
|
m_storeRef = m_filesysCtx.getRootNode().getStoreRef();
|
|
|
|
// Get the root node path
|
|
|
|
String rootPath = (String) m_nodeService.getProperty( m_filesysCtx.getRootNode(), ContentModel.PROP_NAME);
|
|
|
|
StringBuilder pathBuilder= new StringBuilder();
|
|
pathBuilder.append("/");
|
|
if ( rootPath != null && rootPath.length() > 0)
|
|
pathBuilder.append( rootPath);
|
|
|
|
m_rootPath = pathBuilder.toString();
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("Node monitor filesystem=" + m_filesysCtx.getDeviceName() + ", rootPath=" + m_rootPath);
|
|
|
|
// Create the node event queue
|
|
|
|
m_eventQueue = new NodeEventQueue();
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("Node monitor installed for " + m_filesysCtx.getDeviceName());
|
|
}
|
|
|
|
/**
|
|
* Start the node monitor thread
|
|
*/
|
|
public void startMonitor() {
|
|
|
|
// Get the file state table and change notification handler, if enabled
|
|
|
|
m_stateTable = m_filesysCtx.getStateTable();
|
|
m_changeHandler = m_filesysCtx.getChangeHandler();
|
|
|
|
// Start the event processing thread
|
|
|
|
m_thread = new Thread( this);
|
|
m_thread.setName( "NodeMonitor_" + m_filesysCtx.getDeviceName());
|
|
m_thread.setDaemon( true);
|
|
|
|
m_thread.start();
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("NodeMonitor started, " + m_thread.getName());
|
|
}
|
|
|
|
/**
|
|
* Create node event
|
|
*
|
|
* @param childAssocRef ChildAssociationRef
|
|
*/
|
|
public void onCreateNode(ChildAssociationRef childAssocRef) {
|
|
|
|
// Check if the node is a file/folder
|
|
|
|
NodeRef nodeRef = childAssocRef.getChildRef();
|
|
if ( nodeRef.getStoreRef().equals( m_storeRef) == false)
|
|
return;
|
|
|
|
QName nodeType = m_nodeService.getType( nodeRef);
|
|
FileFolderServiceType fType = m_fileFolderService.getType( nodeType);
|
|
|
|
if ( fType != FileFolderServiceType.INVALID) {
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled()) {
|
|
|
|
// Get the full path to the file/folder node
|
|
|
|
Path nodePath = m_nodeService.getPath( nodeRef);
|
|
String fName = (String) m_nodeService.getProperty( nodeRef, ContentModel.PROP_NAME);
|
|
|
|
logger.debug("OnCreateNode: nodeRef=" + nodeRef + ", name=" + fName + ", path=" + nodePath.toDisplayPath(m_nodeService, m_permissionService));
|
|
}
|
|
|
|
// Create an event to process the node creation
|
|
|
|
NodeEvent nodeEvent = new CreateNodeEvent( fType, nodeRef);
|
|
|
|
// Store the event in the transaction until committed, and register the transaction listener
|
|
|
|
AlfrescoTransactionSupport.bindListener( this);
|
|
AlfrescoTransactionSupport.bindResource( FileSysNodeEvent, nodeEvent);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update properties event
|
|
*
|
|
* @param nodeRef NodeRef
|
|
* @param before Map<QName, Serializable>
|
|
* @param after Map<QName, Serializable>
|
|
*/
|
|
public void onUpdateProperties( NodeRef nodeRef, Map<QName, Serializable> before, Map<QName, Serializable> after) {
|
|
|
|
// Check that the node is in our store
|
|
|
|
if ( nodeRef.getStoreRef().equals( m_storeRef) == false)
|
|
return;
|
|
|
|
// Check if the node is a file/folder
|
|
|
|
QName nodeType = m_nodeService.getType( nodeRef);
|
|
FileFolderServiceType fType = m_fileFolderService.getType( nodeType);
|
|
|
|
if ( fType != FileFolderServiceType.INVALID) {
|
|
|
|
// Check if there has been a lock change
|
|
|
|
NodeEvent nodeEvent = null;
|
|
|
|
String beforeLock = (String) before.get( ContentModel.PROP_LOCK_TYPE);
|
|
String afterLock = (String) after.get( ContentModel.PROP_LOCK_TYPE);
|
|
|
|
if (( beforeLock != null && afterLock == null) ||
|
|
( beforeLock == null && afterLock != null)) {
|
|
|
|
// Process the update
|
|
|
|
nodeEvent = new LockNodeEvent( fType, nodeRef, beforeLock, afterLock);
|
|
}
|
|
|
|
// Check if a node event has been created
|
|
|
|
if ( nodeEvent != null) {
|
|
|
|
// Check for an existing event
|
|
|
|
String eventKey = FileSysNodeEvent;
|
|
if ( AlfrescoTransactionSupport.getResource( FileSysNodeEvent) != null)
|
|
eventKey = FileSysNodeEvent2;
|
|
|
|
// Store the event in the transaction until committed, and register the transaction listener
|
|
|
|
AlfrescoTransactionSupport.bindListener( this);
|
|
AlfrescoTransactionSupport.bindResource( eventKey, nodeEvent);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete node event
|
|
*
|
|
* @param childAssocRef ChildAssociationRef
|
|
* @param isArchiveNode boolean
|
|
*/
|
|
public void onDeleteNode(ChildAssociationRef childAssocRef, boolean isArchivedNode) {
|
|
|
|
// Check if there is a node event stored in the transaction
|
|
|
|
NodeEvent nodeEvent = (NodeEvent) AlfrescoTransactionSupport.getResource( FileSysNodeEvent);
|
|
|
|
if ( nodeEvent != null && nodeEvent instanceof DeleteNodeEvent) {
|
|
|
|
// Should be the same node id
|
|
|
|
DeleteNodeEvent deleteEvent = (DeleteNodeEvent) nodeEvent;
|
|
NodeRef nodeRef = childAssocRef.getChildRef();
|
|
|
|
if ( nodeRef.equals( deleteEvent.getNodeRef())) {
|
|
|
|
// Confirm the node delete
|
|
|
|
deleteEvent.setDeleteConfirm( true);
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("OnDeleteNode: confirm delete nodeRef=" + nodeRef);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Move node event
|
|
*
|
|
* @param oldChildAssocRef ChildAssociationRef
|
|
* @param newChildAssocRef ChildAssociationRef
|
|
*/
|
|
public void onMoveNode(ChildAssociationRef oldChildAssocRef, ChildAssociationRef newChildAssocRef) {
|
|
|
|
// Check if the node is a file/folder, and for our store
|
|
|
|
NodeRef nodeRef = oldChildAssocRef.getChildRef();
|
|
if ( nodeRef.getStoreRef().equals( m_storeRef) == false)
|
|
return;
|
|
|
|
QName nodeType = m_nodeService.getType( nodeRef);
|
|
FileFolderServiceType fType = m_fileFolderService.getType( nodeType);
|
|
|
|
if ( fType != FileFolderServiceType.INVALID) {
|
|
|
|
// Get the full path to the file/folder node
|
|
|
|
Path nodePath = m_nodeService.getPath( nodeRef);
|
|
String fName = (String) m_nodeService.getProperty( nodeRef, ContentModel.PROP_NAME);
|
|
|
|
// Build the share relative path to the node
|
|
|
|
StringBuilder pathStr = new StringBuilder();
|
|
pathStr.append( nodePath.toDisplayPath(m_nodeService, m_permissionService));
|
|
if ( pathStr.charAt(pathStr.length() - 1) != '/' && pathStr.charAt(pathStr.length() - 1) != '\\')
|
|
pathStr.append("\\");
|
|
pathStr.append( fName);
|
|
|
|
String relPath = pathStr.toString();
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("OnMoveNode: nodeRef=" + nodeRef + ", relPath=" + relPath);
|
|
|
|
// Queue an event to process the node move
|
|
|
|
if ( relPath.startsWith( m_rootPath)) {
|
|
|
|
// Create a move event
|
|
|
|
NodeEvent nodeEvent = new MoveNodeEvent( fType, nodeRef, relPath, newChildAssocRef.getChildRef());
|
|
|
|
// Store the event in the transaction until committed, and register the transaction listener
|
|
|
|
AlfrescoTransactionSupport.bindListener( this);
|
|
AlfrescoTransactionSupport.bindResource( FileSysNodeEvent, nodeEvent);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Before delete node event
|
|
*
|
|
* @param nodeRef NodeRef
|
|
*/
|
|
public void beforeDeleteNode(NodeRef nodeRef) {
|
|
|
|
// Check if the node is in the filesystem store
|
|
|
|
if ( nodeRef.getStoreRef().equals( m_storeRef) == false)
|
|
return;
|
|
|
|
// Check if the node is a file/folder
|
|
|
|
QName nodeType = m_nodeService.getType( nodeRef);
|
|
FileFolderServiceType fType = m_fileFolderService.getType( nodeType);
|
|
|
|
if ( fType != FileFolderServiceType.INVALID) {
|
|
|
|
// Get the full path to the file/folder node
|
|
|
|
Path nodePath = m_nodeService.getPath( nodeRef);
|
|
String fName = (String) m_nodeService.getProperty( nodeRef, ContentModel.PROP_NAME);
|
|
|
|
// Build the share relative path to the node
|
|
|
|
StringBuilder pathStr = new StringBuilder();
|
|
pathStr.append( nodePath.toDisplayPath(m_nodeService, m_permissionService));
|
|
if ( pathStr.length() == 0 || (pathStr.charAt(pathStr.length() - 1) != '/' && pathStr.charAt(pathStr.length() - 1) != '\\'))
|
|
pathStr.append("\\");
|
|
pathStr.append( fName);
|
|
|
|
String relPath = pathStr.toString();
|
|
|
|
// Create an event to process the node deletion
|
|
|
|
if ( relPath.startsWith( m_rootPath)) {
|
|
|
|
// Create a delete event
|
|
|
|
NodeEvent nodeEvent = new DeleteNodeEvent( fType, nodeRef, relPath);
|
|
|
|
// Store the event in the transaction until committed, and register the transaction listener
|
|
|
|
AlfrescoTransactionSupport.bindListener( this);
|
|
AlfrescoTransactionSupport.bindResource( FileSysNodeEvent, nodeEvent);
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("BeforeDeleteNode: nodeRef=" + nodeRef + ", relPath=" + relPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Request the node monitor thread to shut down
|
|
*/
|
|
public final void shutdownRequest() {
|
|
|
|
if ( m_thread != null) {
|
|
|
|
// Set the shutdown request flag
|
|
|
|
m_shutdown = true;
|
|
|
|
// Interrupt the event processing thread
|
|
|
|
try {
|
|
m_thread.interrupt();
|
|
}
|
|
catch ( Exception ex) {
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Transaction processing hook
|
|
*/
|
|
public void afterCommit() {
|
|
|
|
// Get the node event that was stored in the transaction
|
|
|
|
NodeEvent nodeEvent = (NodeEvent) AlfrescoTransactionSupport.getResource( FileSysNodeEvent);
|
|
if ( nodeEvent != null) {
|
|
|
|
// Queue the primary event for processing
|
|
|
|
m_eventQueue.addEvent( nodeEvent);
|
|
|
|
// Check for a secondary event
|
|
|
|
nodeEvent = (NodeEvent) AlfrescoTransactionSupport.getResource(FileSysNodeEvent2);
|
|
if ( nodeEvent != null)
|
|
m_eventQueue.addEvent( nodeEvent);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Event queue processing
|
|
*/
|
|
public void run() {
|
|
|
|
// Clear the shutdown flag
|
|
|
|
m_shutdown = false;
|
|
|
|
// Use the system user as the authenticated context for the node monitor
|
|
|
|
AuthenticationComponent authComponent = m_filesysDriver.getAuthComponent();
|
|
authComponent.setCurrentUser( authComponent.getSystemUserName());
|
|
|
|
// Loop until shutdown
|
|
|
|
NodeEvent nodeEvent = null;
|
|
UserTransaction tx = null;
|
|
|
|
while ( m_shutdown == false) {
|
|
|
|
// Wait for an event to process
|
|
|
|
try {
|
|
nodeEvent = m_eventQueue.removeEvent();
|
|
}
|
|
catch ( InterruptedException ex) {
|
|
}
|
|
|
|
// Check for a shutdown
|
|
|
|
if ( m_shutdown == true)
|
|
continue;
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("Processing event " + nodeEvent);
|
|
|
|
// Create a transaction
|
|
|
|
tx = m_transService.getUserTransaction( true);
|
|
|
|
try {
|
|
|
|
// Start the transaction
|
|
|
|
tx.begin();
|
|
|
|
// Process the event
|
|
|
|
if ( nodeEvent instanceof CreateNodeEvent) {
|
|
|
|
// Node created
|
|
|
|
processCreateNode((CreateNodeEvent) nodeEvent);
|
|
}
|
|
|
|
else if ( nodeEvent instanceof DeleteNodeEvent) {
|
|
|
|
// Node deleted
|
|
|
|
processDeleteNode((DeleteNodeEvent) nodeEvent);
|
|
}
|
|
else if ( nodeEvent instanceof MoveNodeEvent) {
|
|
|
|
// Node moved
|
|
|
|
processMoveNode((MoveNodeEvent) nodeEvent);
|
|
}
|
|
else if ( nodeEvent instanceof LockNodeEvent) {
|
|
|
|
// Node locked/unlocked
|
|
|
|
processLockNode(( LockNodeEvent) nodeEvent);
|
|
}
|
|
|
|
// Commit the transaction
|
|
|
|
tx.commit();
|
|
tx = null;
|
|
}
|
|
catch ( Exception ex) {
|
|
logger.error( ex);
|
|
}
|
|
finally
|
|
{
|
|
// If there is an active transaction then roll it back
|
|
|
|
if ( tx != null)
|
|
{
|
|
try
|
|
{
|
|
tx.rollback();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logger.warn("Failed to rollback transaction", ex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process a create node event
|
|
*
|
|
* @param createEvent CreateNodeEvent
|
|
*/
|
|
private final void processCreateNode(NodeEvent createEvent) {
|
|
|
|
// Get the full path to the file/folder node
|
|
|
|
Path nodePath = m_nodeService.getPath( createEvent.getNodeRef());
|
|
String relPath = nodePath.toDisplayPath(m_nodeService, m_permissionService);
|
|
String fName = (String) m_nodeService.getProperty( createEvent.getNodeRef(), ContentModel.PROP_NAME);
|
|
|
|
// Check if the path is within the filesystem view
|
|
|
|
if ( relPath.startsWith( m_rootPath)) {
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("CreateNode nodeRef=" + createEvent.getNodeRef() + ", fName=" + fName + ", path=" + relPath);
|
|
|
|
// Build the full file path
|
|
|
|
StringBuilder fullPath = new StringBuilder();
|
|
fullPath.append( relPath.substring( m_rootPath.length()));
|
|
fullPath.append( "/");
|
|
fullPath.append( fName);
|
|
|
|
relPath = fullPath.toString();
|
|
|
|
// Update an existing file state to indicate that the file exists, may have been marked as deleted
|
|
|
|
if ( m_stateTable != null) {
|
|
|
|
// Check if there is file state for this file
|
|
|
|
FileState fState = m_stateTable.findFileState( relPath);
|
|
if ( fState != null && fState.exists() == false) {
|
|
|
|
// Check if the new node is a file or folder
|
|
|
|
if ( createEvent.getFileType() == FileFolderServiceType.FILE)
|
|
fState.setFileStatus(FileStatus.FileExists);
|
|
else
|
|
fState.setFileStatus(FileStatus.DirectoryExists);
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("CreateNode updated file state - " + fState);
|
|
}
|
|
}
|
|
|
|
// If change notifications are enabled then send an event to registered listeners
|
|
|
|
if ( m_changeHandler != null) {
|
|
|
|
// Check if there are any active notifications
|
|
|
|
if ( m_changeHandler.getGlobalNotifyMask() != 0) {
|
|
|
|
// Send a file created event to the change notification handler
|
|
|
|
if ( createEvent.getFileType() == FileFolderServiceType.FILE)
|
|
m_changeHandler.notifyFileChanged(NotifyChange.ActionAdded, relPath);
|
|
else
|
|
m_changeHandler.notifyDirectoryChanged(NotifyChange.ActionAdded, relPath);
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("CreateNode queued change notification");
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("CreateNode ignored nodeRef=" + createEvent.getNodeRef() + ", path=" + relPath);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Process a node delete event
|
|
*
|
|
* @param deleteEvent DeleteNodeEvent
|
|
*/
|
|
private final void processDeleteNode(DeleteNodeEvent deleteEvent) {
|
|
|
|
// Check if the delete was confirmed
|
|
|
|
if ( deleteEvent.hasDeleteConfirm() == false) {
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("DeleteNode not confirmed, nodeRef=" + deleteEvent.getNodeRef() + ", path=" + deleteEvent.getPath());
|
|
|
|
return;
|
|
}
|
|
|
|
// Strip the root path
|
|
|
|
String relPath = deleteEvent.getPath().substring( m_rootPath.length()).replace( '/', '\\');
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("DeleteNode nodeRef=" + deleteEvent.getNodeRef() + ", path=" + relPath);
|
|
|
|
// Update an existing file state to indicate that the file does not exist
|
|
|
|
if ( m_stateTable != null) {
|
|
|
|
// Check if there is file state for this file
|
|
|
|
FileState fState = m_stateTable.findFileState( relPath);
|
|
if ( fState != null && fState.exists() == true) {
|
|
|
|
// Mark the file/folder as no longer existing
|
|
|
|
fState.setFileStatus(FileStatus.NotExist);
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("DeleteNode updated file state - " + fState);
|
|
}
|
|
}
|
|
|
|
// If change notifications are enabled then send an event to registered listeners
|
|
|
|
if ( m_changeHandler != null) {
|
|
|
|
// Check if there are any active notifications
|
|
|
|
if ( m_changeHandler.getGlobalNotifyMask() != 0) {
|
|
|
|
// Send a file created event to the change notification handler
|
|
|
|
if ( deleteEvent.getFileType() == FileFolderServiceType.FILE)
|
|
m_changeHandler.notifyFileChanged(NotifyChange.ActionRemoved, relPath);
|
|
else
|
|
m_changeHandler.notifyDirectoryChanged(NotifyChange.ActionRemoved, relPath);
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("DeleteNode queued change notification");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process a node move event
|
|
*
|
|
* @param moveEvent MoveNodeEvent
|
|
*/
|
|
private final void processMoveNode(MoveNodeEvent moveEvent) {
|
|
|
|
// Strip the root path
|
|
|
|
String fromPath = moveEvent.getPath().substring( m_rootPath.length()).replace( '/', '\\');
|
|
|
|
// Get the destination relative path
|
|
|
|
Path nodePath = m_nodeService.getPath( moveEvent.getMoveToNodeRef());
|
|
String fName = (String) m_nodeService.getProperty( moveEvent.getMoveToNodeRef(), ContentModel.PROP_NAME);
|
|
|
|
// Build the share relative path to the destination
|
|
|
|
StringBuilder pathStr = new StringBuilder();
|
|
pathStr.append( nodePath.toDisplayPath(m_nodeService, m_permissionService));
|
|
if ( pathStr.charAt(pathStr.length() - 1) != '/' && pathStr.charAt(pathStr.length() - 1) != '\\')
|
|
pathStr.append("\\");
|
|
pathStr.append( fName);
|
|
|
|
String toPath = pathStr.toString().substring( m_rootPath.length()).replace( '/', '\\');
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("MoveNode fromPath=" + fromPath + ", toPath=" + toPath);
|
|
|
|
// Update an existing file state to indicate that the file does not exist
|
|
|
|
if ( m_stateTable != null) {
|
|
|
|
// Check if there is file state for the orginal file/folder
|
|
|
|
FileState fState = m_stateTable.findFileState( fromPath);
|
|
if ( fState != null && fState.exists() == true) {
|
|
|
|
// Mark the file/folder as no longer existing
|
|
|
|
fState.setFileStatus(FileStatus.NotExist);
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("MoveNode updated state for fromPath=" + fromPath);
|
|
}
|
|
|
|
// Check if there is a file state for the destination file/folder
|
|
|
|
fState = m_stateTable.findFileState( toPath);
|
|
if ( fState != null && fState.exists() == false) {
|
|
|
|
// Indicate the the file or folder exists
|
|
|
|
if ( moveEvent.getFileType() == FileFolderServiceType.FILE)
|
|
fState.setFileStatus(FileStatus.FileExists);
|
|
else
|
|
fState.setFileStatus(FileStatus.DirectoryExists);
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("MoveNode updated state for toPath=" + toPath);
|
|
}
|
|
}
|
|
|
|
// If change notifications are enabled then send an event to registered listeners
|
|
|
|
if ( m_changeHandler != null) {
|
|
|
|
// Check if there are any active notifications
|
|
|
|
if ( m_changeHandler.getGlobalNotifyMask() != 0) {
|
|
|
|
// Send a file renamed event to the change notification handler
|
|
|
|
m_changeHandler.notifyRename( fromPath, toPath);
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("MoveNode queued change notification");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process a node lock/unlock event
|
|
*
|
|
* @param lockEvent LockNodeEvent
|
|
*/
|
|
private final void processLockNode(LockNodeEvent lockEvent) {
|
|
|
|
// Get the full path to the file/folder node
|
|
|
|
Path nodePath = m_nodeService.getPath( lockEvent.getNodeRef());
|
|
String relPath = nodePath.toDisplayPath(m_nodeService, m_permissionService);
|
|
String fName = (String) m_nodeService.getProperty( lockEvent.getNodeRef(), ContentModel.PROP_NAME);
|
|
|
|
// Check if the path is within the filesystem view
|
|
|
|
if ( relPath.startsWith( m_rootPath)) {
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("LockNode nodeRef=" + lockEvent.getNodeRef() + ", fName=" + fName + ", path=" + relPath);
|
|
|
|
// Build the full file path
|
|
|
|
StringBuilder fullPath = new StringBuilder();
|
|
fullPath.append( relPath.substring( m_rootPath.length()));
|
|
fullPath.append( "/");
|
|
fullPath.append( fName);
|
|
|
|
relPath = fullPath.toString().replace( '/', '\\');
|
|
|
|
// Node has been locked or unlocked, send a change notification to indicate the file attributes have changed
|
|
|
|
if ( m_changeHandler != null) {
|
|
|
|
// Send out a change of attributes notification
|
|
|
|
m_changeHandler.notifyAttributesChanged( relPath, lockEvent.getFileType() == FileFolderServiceType.FILE ? false : true);
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("LockNode queued change notification");
|
|
}
|
|
}
|
|
}
|
|
}
|