Merged 5.1.N (5.1.2) to 5.2.N (5.2.1)

125605 rmunteanu: Merged 5.1.1 (5.1.1) to 5.1.N (5.1.2)
      125498 slanglois: MNT-16155 Update source headers - remove svn:eol-style property on Java and JSP source files


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@125783 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Raluca Munteanu
2016-04-26 13:03:25 +00:00
parent 8674e2bfc8
commit dc6b2852d0
830 changed files with 142585 additions and 142585 deletions

View File

@@ -1,49 +1,49 @@
package org.alfresco.email.server; package org.alfresco.email.server;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import org.alfresco.repo.copy.CopyBehaviourCallback; import org.alfresco.repo.copy.CopyBehaviourCallback;
import org.alfresco.repo.copy.CopyDetails; import org.alfresco.repo.copy.CopyDetails;
import org.alfresco.repo.copy.DefaultCopyBehaviourCallback; import org.alfresco.repo.copy.DefaultCopyBehaviourCallback;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
public class AliasableAspectCopyBehaviourCallback extends DefaultCopyBehaviourCallback public class AliasableAspectCopyBehaviourCallback extends DefaultCopyBehaviourCallback
{ {
static final CopyBehaviourCallback INSTANCE = new AliasableAspectCopyBehaviourCallback(); static final CopyBehaviourCallback INSTANCE = new AliasableAspectCopyBehaviourCallback();
/** /**
* Disallows copying of the {@link EmailServerModel#ASPECT_ALIASABLE} aspect. * Disallows copying of the {@link EmailServerModel#ASPECT_ALIASABLE} aspect.
*/ */
@Override @Override
public boolean getMustCopy(QName classQName, CopyDetails copyDetails) public boolean getMustCopy(QName classQName, CopyDetails copyDetails)
{ {
if (classQName.equals(EmailServerModel.ASPECT_ALIASABLE)) if (classQName.equals(EmailServerModel.ASPECT_ALIASABLE))
{ {
return false; return false;
} }
else else
{ {
return true; return true;
} }
} }
/** /**
* Prevents copying off the {@link org.alfresco.model.ContentModel#PROP_NAME <b>cm:name</b>} property. * Prevents copying off the {@link org.alfresco.model.ContentModel#PROP_NAME <b>cm:name</b>} property.
*/ */
@Override @Override
public Map<QName, Serializable> getCopyProperties( public Map<QName, Serializable> getCopyProperties(
QName classQName, QName classQName,
CopyDetails copyDetails, CopyDetails copyDetails,
Map<QName, Serializable> properties) Map<QName, Serializable> properties)
{ {
if (classQName.equals(EmailServerModel.ASPECT_ALIASABLE)) if (classQName.equals(EmailServerModel.ASPECT_ALIASABLE))
{ {
return Collections.emptyMap(); return Collections.emptyMap();
} }
return properties; return properties;
} }
} }

View File

@@ -1,64 +1,64 @@
package org.alfresco.encryption; package org.alfresco.encryption;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEvent;
import org.springframework.extensions.surf.util.AbstractLifecycleBean; import org.springframework.extensions.surf.util.AbstractLifecycleBean;
/** /**
* *
* @since 4.0 * @since 4.0
* *
*/ */
public class BootstrapReEncryptor extends AbstractLifecycleBean public class BootstrapReEncryptor extends AbstractLifecycleBean
{ {
private static Log logger = LogFactory.getLog(BootstrapReEncryptor.class); private static Log logger = LogFactory.getLog(BootstrapReEncryptor.class);
private boolean enabled; private boolean enabled;
private ReEncryptor reEncryptor; private ReEncryptor reEncryptor;
public void setEnabled(boolean enabled) public void setEnabled(boolean enabled)
{ {
this.enabled = enabled; this.enabled = enabled;
} }
public void setReEncryptor(ReEncryptor reEncryptor) public void setReEncryptor(ReEncryptor reEncryptor)
{ {
this.reEncryptor = reEncryptor; this.reEncryptor = reEncryptor;
} }
public int reEncrypt() public int reEncrypt()
{ {
try try
{ {
return reEncryptor.bootstrapReEncrypt(); return reEncryptor.bootstrapReEncrypt();
} }
catch(MissingKeyException e) catch(MissingKeyException e)
{ {
throw new AlfrescoRuntimeException("Bootstrap re-encryption failed", e); throw new AlfrescoRuntimeException("Bootstrap re-encryption failed", e);
} }
} }
@Override @Override
protected void onBootstrap(ApplicationEvent event) protected void onBootstrap(ApplicationEvent event)
{ {
if(enabled) if(enabled)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Re-encrypting encryptable properties..."); logger.debug("Re-encrypting encryptable properties...");
} }
int propertiesReEncrypted = reEncrypt(); int propertiesReEncrypted = reEncrypt();
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("...done, re-encrypted " + propertiesReEncrypted + " properties."); logger.debug("...done, re-encrypted " + propertiesReEncrypted + " properties.");
} }
} }
} }
@Override @Override
protected void onShutdown(ApplicationEvent event) protected void onShutdown(ApplicationEvent event)
{ {
} }
} }

View File

@@ -1,66 +1,66 @@
package org.alfresco.encryption; package org.alfresco.encryption;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEvent;
import org.springframework.extensions.surf.util.AbstractLifecycleBean; import org.springframework.extensions.surf.util.AbstractLifecycleBean;
/** /**
* The EncryptionChecker checks the state of the repository's encryption system. * The EncryptionChecker checks the state of the repository's encryption system.
* In particular it checks: * In particular it checks:
* <ul> * <ul>
* <li> that the keystore exists and, if not, creates one. * <li> that the keystore exists and, if not, creates one.
* <li> that the encryption keys have not been changed. If so, the bootstrap will be halted. * <li> that the encryption keys have not been changed. If so, the bootstrap will be halted.
* </ul> * </ul>
* *
* @since 4.0 * @since 4.0
* *
*/ */
public class EncryptionChecker extends AbstractLifecycleBean public class EncryptionChecker extends AbstractLifecycleBean
{ {
private TransactionService transactionService; private TransactionService transactionService;
private KeyStoreChecker keyStoreChecker; private KeyStoreChecker keyStoreChecker;
public void setKeyStoreChecker(KeyStoreChecker keyStoreChecker) public void setKeyStoreChecker(KeyStoreChecker keyStoreChecker)
{ {
this.keyStoreChecker = keyStoreChecker; this.keyStoreChecker = keyStoreChecker;
} }
public void setTransactionService(TransactionService transactionService) public void setTransactionService(TransactionService transactionService)
{ {
this.transactionService = transactionService; this.transactionService = transactionService;
} }
@Override @Override
protected void onBootstrap(ApplicationEvent event) protected void onBootstrap(ApplicationEvent event)
{ {
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper(); RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
txnHelper.setForceWritable(true); // Force write in case server is read-only txnHelper.setForceWritable(true); // Force write in case server is read-only
txnHelper.doInTransaction(new RetryingTransactionCallback<Void>() txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
{ {
public Void execute() throws Throwable public Void execute() throws Throwable
{ {
try try
{ {
keyStoreChecker.validateKeyStores(); keyStoreChecker.validateKeyStores();
} }
catch(Throwable e) catch(Throwable e)
{ {
// Just throw as a runtime exception // Just throw as a runtime exception
throw new AlfrescoRuntimeException("Keystores are invalid", e); throw new AlfrescoRuntimeException("Keystores are invalid", e);
} }
return null; return null;
} }
}); });
} }
@Override @Override
protected void onShutdown(ApplicationEvent event) protected void onShutdown(ApplicationEvent event)
{ {
} }
} }

View File

@@ -1,208 +1,208 @@
package org.alfresco.encryption; package org.alfresco.encryption;
import java.io.Serializable; import java.io.Serializable;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.Key; import java.security.Key;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.attributes.AttributeService; import org.alfresco.service.cmr.attributes.AttributeService;
import org.alfresco.service.cmr.attributes.AttributeService.AttributeQueryCallback; import org.alfresco.service.cmr.attributes.AttributeService.AttributeQueryCallback;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.EqualsHelper; import org.alfresco.util.EqualsHelper;
import org.alfresco.util.GUID; import org.alfresco.util.GUID;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* Registered Encryption Keys are stored in the AttributeService directly under a top level key defined by * Registered Encryption Keys are stored in the AttributeService directly under a top level key defined by
* TOP_LEVEL_KEY (which means that all key aliases must be unique across however many keystores are being used). * TOP_LEVEL_KEY (which means that all key aliases must be unique across however many keystores are being used).
* *
* @since 4.0 * @since 4.0
* *
*/ */
// TODO caching? This will probably not be used extensively. // TODO caching? This will probably not be used extensively.
// TODO instead of persisting the Pair when registering a key, create two attributes per key (one for the // TODO instead of persisting the Pair when registering a key, create two attributes per key (one for the
// guid and one for the encrypted value of the guid). This means a custom class does not need to be bound to // guid and one for the encrypted value of the guid). This means a custom class does not need to be bound to
// the attribute service. // the attribute service.
public class EncryptionKeysRegistryImpl implements EncryptionKeysRegistry public class EncryptionKeysRegistryImpl implements EncryptionKeysRegistry
{ {
public static String TOP_LEVEL_KEY = "keyCheck"; public static String TOP_LEVEL_KEY = "keyCheck";
private static final Log logger = LogFactory.getLog(EncryptionKeysRegistryImpl.class); private static final Log logger = LogFactory.getLog(EncryptionKeysRegistryImpl.class);
private TransactionService transactionService; private TransactionService transactionService;
private AttributeService attributeService; private AttributeService attributeService;
private String cipherAlgorithm; private String cipherAlgorithm;
private String cipherProvider; private String cipherProvider;
public void setAttributeService(AttributeService attributeService) public void setAttributeService(AttributeService attributeService)
{ {
this.attributeService = attributeService; this.attributeService = attributeService;
} }
public void setCipherAlgorithm(String cipherAlgorithm) public void setCipherAlgorithm(String cipherAlgorithm)
{ {
this.cipherAlgorithm = cipherAlgorithm; this.cipherAlgorithm = cipherAlgorithm;
} }
public void setCipherProvider(String cipherProvider) public void setCipherProvider(String cipherProvider)
{ {
this.cipherProvider = cipherProvider; this.cipherProvider = cipherProvider;
} }
public void setTransactionService(TransactionService transactionService) public void setTransactionService(TransactionService transactionService)
{ {
this.transactionService = transactionService; this.transactionService = transactionService;
} }
protected Encryptor getEncryptor(final KeyMap keys) protected Encryptor getEncryptor(final KeyMap keys)
{ {
DefaultEncryptor encryptor = new DefaultEncryptor(); DefaultEncryptor encryptor = new DefaultEncryptor();
encryptor.setCipherAlgorithm(cipherAlgorithm); encryptor.setCipherAlgorithm(cipherAlgorithm);
encryptor.setCipherProvider(cipherProvider); encryptor.setCipherProvider(cipherProvider);
encryptor.setKeyProvider(new KeyProvider() encryptor.setKeyProvider(new KeyProvider()
{ {
@Override @Override
public Key getKey(String keyAlias) public Key getKey(String keyAlias)
{ {
return keys.getCachedKey(keyAlias).getKey(); return keys.getCachedKey(keyAlias).getKey();
} }
}); });
return encryptor; return encryptor;
} }
public void init() public void init()
{ {
} }
public void registerKey(String keyAlias, Key key) public void registerKey(String keyAlias, Key key)
{ {
if(isKeyRegistered(keyAlias)) if(isKeyRegistered(keyAlias))
{ {
throw new IllegalArgumentException("Key " + keyAlias + " is already registered"); throw new IllegalArgumentException("Key " + keyAlias + " is already registered");
} }
// register the key by creating an attribute that stores a guid and its encrypted value // register the key by creating an attribute that stores a guid and its encrypted value
String guid = GUID.generate(); String guid = GUID.generate();
KeyMap keys = new KeyMap(); KeyMap keys = new KeyMap();
keys.setKey(keyAlias, key); keys.setKey(keyAlias, key);
Encryptor encryptor = getEncryptor(keys); Encryptor encryptor = getEncryptor(keys);
Serializable encrypted = encryptor.sealObject(keyAlias, null, guid); Serializable encrypted = encryptor.sealObject(keyAlias, null, guid);
Pair<String, Serializable> keyCheck = new Pair<String, Serializable>(guid, encrypted); Pair<String, Serializable> keyCheck = new Pair<String, Serializable>(guid, encrypted);
attributeService.createAttribute(keyCheck, TOP_LEVEL_KEY, keyAlias); attributeService.createAttribute(keyCheck, TOP_LEVEL_KEY, keyAlias);
logger.info("Registered key " + keyAlias); logger.info("Registered key " + keyAlias);
} }
public void unregisterKey(String keyAlias) public void unregisterKey(String keyAlias)
{ {
attributeService.removeAttribute(TOP_LEVEL_KEY, keyAlias); attributeService.removeAttribute(TOP_LEVEL_KEY, keyAlias);
} }
public boolean isKeyRegistered(String keyAlias) public boolean isKeyRegistered(String keyAlias)
{ {
try try
{ {
return (attributeService.getAttribute(TOP_LEVEL_KEY, keyAlias) != null); return (attributeService.getAttribute(TOP_LEVEL_KEY, keyAlias) != null);
} }
catch(Throwable e) catch(Throwable e)
{ {
// there is an issue getting the attribute. Remove it. // there is an issue getting the attribute. Remove it.
attributeService.removeAttribute(TOP_LEVEL_KEY, keyAlias); attributeService.removeAttribute(TOP_LEVEL_KEY, keyAlias);
return (attributeService.getAttribute(TOP_LEVEL_KEY, keyAlias) != null); return (attributeService.getAttribute(TOP_LEVEL_KEY, keyAlias) != null);
} }
} }
public List<String> getRegisteredKeys(final Set<String> keyStoreKeys) public List<String> getRegisteredKeys(final Set<String> keyStoreKeys)
{ {
final List<String> registeredKeys = new ArrayList<String>(); final List<String> registeredKeys = new ArrayList<String>();
attributeService.getAttributes(new AttributeQueryCallback() attributeService.getAttributes(new AttributeQueryCallback()
{ {
public boolean handleAttribute(Long id, Serializable value, public boolean handleAttribute(Long id, Serializable value,
Serializable[] keys) Serializable[] keys)
{ {
// Add as a registered key if the keystore contains the key // Add as a registered key if the keystore contains the key
String keyAlias = (String)keys[1]; String keyAlias = (String)keys[1];
if(keyStoreKeys.contains(keyAlias)) if(keyStoreKeys.contains(keyAlias))
{ {
registeredKeys.add(keyAlias); registeredKeys.add(keyAlias);
} }
return true; return true;
} }
}, },
TOP_LEVEL_KEY); TOP_LEVEL_KEY);
return registeredKeys; return registeredKeys;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public KEY_STATUS checkKey(String keyAlias, Key key) public KEY_STATUS checkKey(String keyAlias, Key key)
{ {
Pair<String, Serializable> keyCheck = null; Pair<String, Serializable> keyCheck = null;
if(attributeService.exists(TOP_LEVEL_KEY, keyAlias)) if(attributeService.exists(TOP_LEVEL_KEY, keyAlias))
{ {
try try
{ {
// check that the key has not changed by decrypting the encrypted guid attribute // check that the key has not changed by decrypting the encrypted guid attribute
// comparing against the guid // comparing against the guid
try try
{ {
keyCheck = (Pair<String, Serializable>)attributeService.getAttribute(TOP_LEVEL_KEY, keyAlias); keyCheck = (Pair<String, Serializable>)attributeService.getAttribute(TOP_LEVEL_KEY, keyAlias);
} }
catch(Throwable e) catch(Throwable e)
{ {
// there is an issue getting the attribute. Remove it. // there is an issue getting the attribute. Remove it.
attributeService.removeAttribute(TOP_LEVEL_KEY, keyAlias); attributeService.removeAttribute(TOP_LEVEL_KEY, keyAlias);
return KEY_STATUS.MISSING; return KEY_STATUS.MISSING;
} }
if(keyCheck == null) if(keyCheck == null)
{ {
return KEY_STATUS.MISSING; return KEY_STATUS.MISSING;
} }
KeyMap keys = new KeyMap(); KeyMap keys = new KeyMap();
keys.setKey(keyAlias, key); keys.setKey(keyAlias, key);
Encryptor encryptor = getEncryptor(keys); Encryptor encryptor = getEncryptor(keys);
Serializable storedGUID = encryptor.unsealObject(keyAlias, keyCheck.getSecond()); Serializable storedGUID = encryptor.unsealObject(keyAlias, keyCheck.getSecond());
return EqualsHelper.nullSafeEquals(storedGUID, keyCheck.getFirst()) ? KEY_STATUS.OK : KEY_STATUS.CHANGED; return EqualsHelper.nullSafeEquals(storedGUID, keyCheck.getFirst()) ? KEY_STATUS.OK : KEY_STATUS.CHANGED;
} }
catch(InvalidKeyException e) catch(InvalidKeyException e)
{ {
// key exception indicates that the key has changed - it can't decrypt the // key exception indicates that the key has changed - it can't decrypt the
// previously-encrypted data // previously-encrypted data
return KEY_STATUS.CHANGED; return KEY_STATUS.CHANGED;
} }
} }
else else
{ {
return KEY_STATUS.MISSING; return KEY_STATUS.MISSING;
} }
} }
// note that this removes _all_ keys in the keystore. Use with care. // note that this removes _all_ keys in the keystore. Use with care.
public void removeRegisteredKeys(final Set<String> keys) public void removeRegisteredKeys(final Set<String> keys)
{ {
RetryingTransactionHelper retryingTransactionHelper = transactionService.getRetryingTransactionHelper(); RetryingTransactionHelper retryingTransactionHelper = transactionService.getRetryingTransactionHelper();
final RetryingTransactionCallback<Void> removeKeysCallback = new RetryingTransactionCallback<Void>() final RetryingTransactionCallback<Void> removeKeysCallback = new RetryingTransactionCallback<Void>()
{ {
public Void execute() throws Throwable public Void execute() throws Throwable
{ {
for(String keyAlias : keys) for(String keyAlias : keys)
{ {
attributeService.removeAttribute(TOP_LEVEL_KEY, keyAlias); attributeService.removeAttribute(TOP_LEVEL_KEY, keyAlias);
} }
return null; return null;
} }
}; };
retryingTransactionHelper.doInTransaction(removeKeysCallback, false); retryingTransactionHelper.doInTransaction(removeKeysCallback, false);
} }
} }

View File

@@ -1,30 +1,30 @@
package org.alfresco.encryption; package org.alfresco.encryption;
/** /**
* Checks the repository key stores. * Checks the repository key stores.
* *
* @since 4.0 * @since 4.0
* *
*/ */
public class KeyStoreChecker public class KeyStoreChecker
{ {
private AlfrescoKeyStore mainKeyStore; private AlfrescoKeyStore mainKeyStore;
public KeyStoreChecker() public KeyStoreChecker()
{ {
} }
public void setMainKeyStore(AlfrescoKeyStore mainKeyStore) public void setMainKeyStore(AlfrescoKeyStore mainKeyStore)
{ {
this.mainKeyStore = mainKeyStore; this.mainKeyStore = mainKeyStore;
} }
public void validateKeyStores() throws InvalidKeystoreException, MissingKeyException public void validateKeyStores() throws InvalidKeystoreException, MissingKeyException
{ {
mainKeyStore.validateKeys(); mainKeyStore.validateKeys();
if(!mainKeyStore.exists()) if(!mainKeyStore.exists())
{ {
mainKeyStore.create(); mainKeyStore.create();
} }
} }
} }

View File

@@ -1,335 +1,335 @@
package org.alfresco.encryption; package org.alfresco.encryption;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.crypto.SealedObject; import javax.crypto.SealedObject;
import org.alfresco.repo.batch.BatchProcessWorkProvider; import org.alfresco.repo.batch.BatchProcessWorkProvider;
import org.alfresco.repo.batch.BatchProcessor; import org.alfresco.repo.batch.BatchProcessor;
import org.alfresco.repo.dictionary.DictionaryDAO; import org.alfresco.repo.dictionary.DictionaryDAO;
import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.node.NodePropertyEntity; import org.alfresco.repo.domain.node.NodePropertyEntity;
import org.alfresco.repo.domain.node.NodePropertyKey; import org.alfresco.repo.domain.node.NodePropertyKey;
import org.alfresco.repo.domain.node.NodePropertyValue; import org.alfresco.repo.domain.node.NodePropertyValue;
import org.alfresco.repo.domain.qname.QNameDAO; import org.alfresco.repo.domain.qname.QNameDAO;
import org.alfresco.repo.lock.JobLockService; import org.alfresco.repo.lock.JobLockService;
import org.alfresco.repo.lock.LockAcquisitionException; import org.alfresco.repo.lock.LockAcquisitionException;
import org.alfresco.repo.node.encryption.MetadataEncryptor; import org.alfresco.repo.node.encryption.MetadataEncryptor;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
/** /**
* Re-encrypts encryptable repository properties using a new set of encryption keys. * Re-encrypts encryptable repository properties using a new set of encryption keys.
* Decrypts the repository properties using the default encryptor, falling back to * Decrypts the repository properties using the default encryptor, falling back to
* a backup decryptor (using the old encryption keys) if necessary, and then re-encrypts * a backup decryptor (using the old encryption keys) if necessary, and then re-encrypts
* the properties. * the properties.
* *
* Can run in one of two ways: * Can run in one of two ways:
* *
* <ul> * <ul>
* <li> during bootstrap. * <li> during bootstrap.
* <li> by using JMX (available only to Enterprise). In this case, the system can stay running while the re-encryption takes place. * <li> by using JMX (available only to Enterprise). In this case, the system can stay running while the re-encryption takes place.
* </ul> * </ul>
* *
* @since 4.0 * @since 4.0
*/ */
public class ReEncryptor implements ApplicationContextAware public class ReEncryptor implements ApplicationContextAware
{ {
private static Log logger = LogFactory.getLog(ReEncryptor.class); private static Log logger = LogFactory.getLog(ReEncryptor.class);
private NodeDAO nodeDAO; private NodeDAO nodeDAO;
private DictionaryDAO dictionaryDAO; private DictionaryDAO dictionaryDAO;
private QNameDAO qnameDAO; private QNameDAO qnameDAO;
private MetadataEncryptor metadataEncryptor; private MetadataEncryptor metadataEncryptor;
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
private TransactionService transactionService; private TransactionService transactionService;
private RetryingTransactionHelper transactionHelper; private RetryingTransactionHelper transactionHelper;
private int numThreads; private int numThreads;
private int chunkSize; private int chunkSize;
private boolean splitTxns = true; private boolean splitTxns = true;
private static final QName LOCK = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "OrphanReaper"); private static final QName LOCK = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "OrphanReaper");
private JobLockService jobLockService; private JobLockService jobLockService;
/** /**
* Set the transaction provider so that each execution can be performed within a transaction * Set the transaction provider so that each execution can be performed within a transaction
*/ */
public void setTransactionService(TransactionService transactionService) public void setTransactionService(TransactionService transactionService)
{ {
this.transactionService = transactionService; this.transactionService = transactionService;
this.transactionHelper = transactionService.getRetryingTransactionHelper(); this.transactionHelper = transactionService.getRetryingTransactionHelper();
} }
public void setMetadataEncryptor(MetadataEncryptor metadataEncryptor) public void setMetadataEncryptor(MetadataEncryptor metadataEncryptor)
{ {
this.metadataEncryptor = metadataEncryptor; this.metadataEncryptor = metadataEncryptor;
} }
public MetadataEncryptor getMetadataEncryptor() public MetadataEncryptor getMetadataEncryptor()
{ {
return metadataEncryptor; return metadataEncryptor;
} }
public void setJobLockService(JobLockService jobLockService) public void setJobLockService(JobLockService jobLockService)
{ {
this.jobLockService = jobLockService; this.jobLockService = jobLockService;
} }
public void setNumThreads(int numThreads) public void setNumThreads(int numThreads)
{ {
this.numThreads = numThreads; this.numThreads = numThreads;
} }
public void setChunkSize(int chunkSize) public void setChunkSize(int chunkSize)
{ {
this.chunkSize = chunkSize; this.chunkSize = chunkSize;
} }
public void setSplitTxns(boolean splitTxns) public void setSplitTxns(boolean splitTxns)
{ {
this.splitTxns = splitTxns; this.splitTxns = splitTxns;
} }
public void setNodeDAO(NodeDAO nodeDAO) public void setNodeDAO(NodeDAO nodeDAO)
{ {
this.nodeDAO = nodeDAO; this.nodeDAO = nodeDAO;
} }
public void setDictionaryDAO(DictionaryDAO dictionaryDAO) public void setDictionaryDAO(DictionaryDAO dictionaryDAO)
{ {
this.dictionaryDAO = dictionaryDAO; this.dictionaryDAO = dictionaryDAO;
} }
public void setQnameDAO(QNameDAO qnameDAO) public void setQnameDAO(QNameDAO qnameDAO)
{ {
this.qnameDAO = qnameDAO; this.qnameDAO = qnameDAO;
} }
/** /**
* Attempts to get the lock. If the lock couldn't be taken, then <tt>null</tt> is returned. * Attempts to get the lock. If the lock couldn't be taken, then <tt>null</tt> is returned.
* *
* @return Returns the lock token or <tt>null</tt> * @return Returns the lock token or <tt>null</tt>
*/ */
private String getLock(long time) private String getLock(long time)
{ {
try try
{ {
return jobLockService.getLock(LOCK, time); return jobLockService.getLock(LOCK, time);
} }
catch (LockAcquisitionException e) catch (LockAcquisitionException e)
{ {
return null; return null;
} }
} }
/** /**
* Attempts to get the lock. If it fails, the current transaction is marked for rollback. * Attempts to get the lock. If it fails, the current transaction is marked for rollback.
*/ */
private void refreshLock(String lockToken, long time) private void refreshLock(String lockToken, long time)
{ {
if (lockToken == null) if (lockToken == null)
{ {
throw new IllegalArgumentException("Must provide existing lockToken"); throw new IllegalArgumentException("Must provide existing lockToken");
} }
jobLockService.refreshLock(lockToken, LOCK, time); jobLockService.refreshLock(lockToken, LOCK, time);
} }
protected void reEncryptProperties(final List<NodePropertyEntity> properties, final String lockToken) protected void reEncryptProperties(final List<NodePropertyEntity> properties, final String lockToken)
{ {
final Iterator<NodePropertyEntity> it = properties.iterator(); final Iterator<NodePropertyEntity> it = properties.iterator();
// TODO use BatchProcessWorkerAdaptor? // TODO use BatchProcessWorkerAdaptor?
BatchProcessor.BatchProcessWorker<NodePropertyEntity> worker = new BatchProcessor.BatchProcessWorker<NodePropertyEntity>() BatchProcessor.BatchProcessWorker<NodePropertyEntity> worker = new BatchProcessor.BatchProcessWorker<NodePropertyEntity>()
{ {
public String getIdentifier(NodePropertyEntity entity) public String getIdentifier(NodePropertyEntity entity)
{ {
return String.valueOf(entity.getNodeId()); return String.valueOf(entity.getNodeId());
} }
public void beforeProcess() throws Throwable public void beforeProcess() throws Throwable
{ {
refreshLock(lockToken, chunkSize * 100L); refreshLock(lockToken, chunkSize * 100L);
} }
public void afterProcess() throws Throwable public void afterProcess() throws Throwable
{ {
} }
public void process(final NodePropertyEntity entity) throws Throwable public void process(final NodePropertyEntity entity) throws Throwable
{ {
NodePropertyValue nodePropValue = entity.getValue(); NodePropertyValue nodePropValue = entity.getValue();
// TODO check that we have the correct type i.e. can be cast to Serializable // TODO check that we have the correct type i.e. can be cast to Serializable
Serializable value = nodePropValue.getSerializableValue(); Serializable value = nodePropValue.getSerializableValue();
if(value instanceof SealedObject) if(value instanceof SealedObject)
{ {
SealedObject sealed = (SealedObject)value; SealedObject sealed = (SealedObject)value;
NodePropertyKey propertyKey = entity.getKey(); NodePropertyKey propertyKey = entity.getKey();
QName propertyQName = qnameDAO.getQName(propertyKey.getQnameId()).getSecond(); QName propertyQName = qnameDAO.getQName(propertyKey.getQnameId()).getSecond();
// decrypt... // decrypt...
Serializable decrypted = metadataEncryptor.decrypt(propertyQName, sealed); Serializable decrypted = metadataEncryptor.decrypt(propertyQName, sealed);
// ...and then re-encrypt. The new key will be used. // ...and then re-encrypt. The new key will be used.
Serializable resealed = metadataEncryptor.encrypt(propertyQName, decrypted); Serializable resealed = metadataEncryptor.encrypt(propertyQName, decrypted);
// TODO update resealed using batch update? // TODO update resealed using batch update?
// does the node DAO do batch updating? // does the node DAO do batch updating?
nodeDAO.setNodeProperties(entity.getNodeId(), Collections.singletonMap(propertyQName, resealed)); nodeDAO.setNodeProperties(entity.getNodeId(), Collections.singletonMap(propertyQName, resealed));
} }
else else
{ {
NodePropertyKey nodeKey = entity.getKey(); NodePropertyKey nodeKey = entity.getKey();
QName propertyQName = qnameDAO.getQName(nodeKey.getQnameId()).getSecond(); QName propertyQName = qnameDAO.getQName(nodeKey.getQnameId()).getSecond();
logger.warn("Encountered an encrypted property that is not a SealedObject, for node id " + logger.warn("Encountered an encrypted property that is not a SealedObject, for node id " +
entity.getNodeId() + ", property " + propertyQName); entity.getNodeId() + ", property " + propertyQName);
} }
} }
}; };
BatchProcessWorkProvider<NodePropertyEntity> provider = new BatchProcessWorkProvider<NodePropertyEntity>() BatchProcessWorkProvider<NodePropertyEntity> provider = new BatchProcessWorkProvider<NodePropertyEntity>()
{ {
@Override @Override
public int getTotalEstimatedWorkSize() public int getTotalEstimatedWorkSize()
{ {
return properties.size(); return properties.size();
} }
@Override @Override
public Collection<NodePropertyEntity> getNextWork() public Collection<NodePropertyEntity> getNextWork()
{ {
List<NodePropertyEntity> sublist = new ArrayList<NodePropertyEntity>(chunkSize); List<NodePropertyEntity> sublist = new ArrayList<NodePropertyEntity>(chunkSize);
synchronized(it) synchronized(it)
{ {
int count = 0; int count = 0;
while(it.hasNext() && count < chunkSize) while(it.hasNext() && count < chunkSize)
{ {
sublist.add(it.next()); sublist.add(it.next());
count++; count++;
} }
} }
return sublist; return sublist;
} }
}; };
new BatchProcessor<NodePropertyEntity>( new BatchProcessor<NodePropertyEntity>(
"Reencryptor", "Reencryptor",
transactionHelper, transactionHelper,
provider, provider,
numThreads, chunkSize, numThreads, chunkSize,
applicationContext, applicationContext,
logger, 100).process(worker, splitTxns); logger, 100).process(worker, splitTxns);
} }
/** /**
* Re-encrypt using the configured backup keystore to decrypt and the main keystore to encrypt * Re-encrypt using the configured backup keystore to decrypt and the main keystore to encrypt
*/ */
public int bootstrapReEncrypt() throws MissingKeyException public int bootstrapReEncrypt() throws MissingKeyException
{ {
if(!metadataEncryptor.backupKeyAvailable(KeyProvider.ALIAS_METADATA)) if(!metadataEncryptor.backupKeyAvailable(KeyProvider.ALIAS_METADATA))
{ {
throw new MissingKeyException("Backup key store is either not present or does not contain a metadata encryption key"); throw new MissingKeyException("Backup key store is either not present or does not contain a metadata encryption key");
} }
return reEncrypt(); return reEncrypt();
} }
/** /**
* Re-encrypt by decrypting using the configured keystore and encrypting using a keystore configured using the provided new key store parameters. * Re-encrypt by decrypting using the configured keystore and encrypting using a keystore configured using the provided new key store parameters.
* Called from e.g. JMX. * Called from e.g. JMX.
* *
* Assumes that the main key store has been already been reloaded. * Assumes that the main key store has been already been reloaded.
* *
* Note: it is the responsibility of the end user to ensure that the underlying keystores have been set up appropriately * Note: it is the responsibility of the end user to ensure that the underlying keystores have been set up appropriately
* i.e. the old key store is backed up to the location defined by the property '${dir.keystore}/backup-keystore' and the new * i.e. the old key store is backed up to the location defined by the property '${dir.keystore}/backup-keystore' and the new
* key store replaces it. This can be done while the repository is running. * key store replaces it. This can be done while the repository is running.
*/ */
public int reEncrypt() throws MissingKeyException public int reEncrypt() throws MissingKeyException
{ {
if(!metadataEncryptor.keyAvailable(KeyProvider.ALIAS_METADATA)) if(!metadataEncryptor.keyAvailable(KeyProvider.ALIAS_METADATA))
{ {
throw new MissingKeyException("Main key store is either not present or does not contain a metadata encryption key"); throw new MissingKeyException("Main key store is either not present or does not contain a metadata encryption key");
} }
if(!metadataEncryptor.backupKeyAvailable(KeyProvider.ALIAS_METADATA)) if(!metadataEncryptor.backupKeyAvailable(KeyProvider.ALIAS_METADATA))
{ {
throw new MissingKeyException("Backup key store is either not present or does not contain a metadata encryption key"); throw new MissingKeyException("Backup key store is either not present or does not contain a metadata encryption key");
} }
int numProps = reEncryptImpl(); int numProps = reEncryptImpl();
return numProps; return numProps;
} }
protected int reEncryptImpl() protected int reEncryptImpl()
{ {
// Take out a re-encryptor lock // Take out a re-encryptor lock
RetryingTransactionCallback<String> txnWork = new RetryingTransactionCallback<String>() RetryingTransactionCallback<String> txnWork = new RetryingTransactionCallback<String>()
{ {
public String execute() throws Exception public String execute() throws Exception
{ {
String lockToken = getLock(20000L); String lockToken = getLock(20000L);
return lockToken; return lockToken;
} }
}; };
String lockToken = transactionService.getRetryingTransactionHelper().doInTransaction(txnWork, false, true); String lockToken = transactionService.getRetryingTransactionHelper().doInTransaction(txnWork, false, true);
if(lockToken == null) if(lockToken == null)
{ {
logger.warn("Can't get lock. Assume multiple re-encryptors ..."); logger.warn("Can't get lock. Assume multiple re-encryptors ...");
return 0; return 0;
} }
// get encrypted properties // get encrypted properties
Collection<PropertyDefinition> propertyDefs = dictionaryDAO.getPropertiesOfDataType(DataTypeDefinition.ENCRYPTED); Collection<PropertyDefinition> propertyDefs = dictionaryDAO.getPropertiesOfDataType(DataTypeDefinition.ENCRYPTED);
Set<QName> qnames = new HashSet<QName>(); Set<QName> qnames = new HashSet<QName>();
for(PropertyDefinition propDef : propertyDefs) for(PropertyDefinition propDef : propertyDefs)
{ {
qnames.add(propDef.getName()); qnames.add(propDef.getName());
} }
// TODO use callback mechanism, or select based on set of nodes? // TODO use callback mechanism, or select based on set of nodes?
List<NodePropertyEntity> properties = nodeDAO.selectNodePropertiesByTypes(qnames); List<NodePropertyEntity> properties = nodeDAO.selectNodePropertiesByTypes(qnames);
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Found " + properties.size() + " properties to re-encrypt..."); logger.debug("Found " + properties.size() + " properties to re-encrypt...");
} }
// reencrypt these properties TODO don't call if num props == 0 // reencrypt these properties TODO don't call if num props == 0
reEncryptProperties(properties, lockToken); reEncryptProperties(properties, lockToken);
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("...done re-encrypting."); logger.debug("...done re-encrypting.");
} }
return properties.size(); return properties.size();
} }
@Override @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{ {
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
} }
} }

View File

@@ -1,29 +1,29 @@
package org.alfresco.filesys.alfresco; package org.alfresco.filesys.alfresco;
/** /**
* Does this NetworkFile have reference counting? * Does this NetworkFile have reference counting?
*/ */
public interface NetworkFileLegacyReferenceCount public interface NetworkFileLegacyReferenceCount
{ {
/** /**
* Increment the file open count, first open = 1; * Increment the file open count, first open = 1;
* *
* @return the current open count * @return the current open count
*/ */
public int incrementLegacyOpenCount(); public int incrementLegacyOpenCount();
/** /**
* Decrement the file open count * Decrement the file open count
* *
* @return the current open count * @return the current open count
*/ */
public int decrementLagacyOpenCount(); public int decrementLagacyOpenCount();
/** /**
* Return the open file count * Return the open file count
* *
* @return the current open count * @return the current open count
*/ */
public int getLegacyOpenCount(); public int getLegacyOpenCount();
} }

View File

@@ -1,44 +1,44 @@
package org.alfresco.filesys.alfresco; package org.alfresco.filesys.alfresco;
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile; import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileList; import org.alfresco.jlan.server.filesys.pseudo.PseudoFileList;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
public interface PseudoFileOverlay public interface PseudoFileOverlay
{ {
/** /**
* Is this a pseudo file? * Is this a pseudo file?
* @param parentDir NodeRef * @param parentDir NodeRef
* @param name String * @param name String
* @return true the file is a pseudo file * @return true the file is a pseudo file
*/ */
public boolean isPseudoFile(NodeRef parentDir, String name); public boolean isPseudoFile(NodeRef parentDir, String name);
/** /**
* Get the pseudo file * Get the pseudo file
* @param parentDir NodeRef * @param parentDir NodeRef
* @param name String * @param name String
* @return the pseudoFile or null if there is no pseudo file * @return the pseudoFile or null if there is no pseudo file
*/ */
public PseudoFile getPseudoFile(NodeRef parentDir, String name); public PseudoFile getPseudoFile(NodeRef parentDir, String name);
/** /**
* Search for the pseudo files on the specified path * Search for the pseudo files on the specified path
* @param parentDir NodeRef * @param parentDir NodeRef
* @param name String * @param name String
* @return list of pseudo files. * @return list of pseudo files.
*/ */
public PseudoFileList searchPseudoFiles(NodeRef parentDir, String name); public PseudoFileList searchPseudoFiles(NodeRef parentDir, String name);
/** /**
* Delete a pseudo file. * Delete a pseudo file.
* *
* Pseudo files may need to be deleted for delete folder operations to work * Pseudo files may need to be deleted for delete folder operations to work
* correctly. * correctly.
* *
* A pseudo file can be deleted for a short time. However it may re-appear at some point * A pseudo file can be deleted for a short time. However it may re-appear at some point
* later since there is no permanent persistence of pseudo files which are ephemeral! * later since there is no permanent persistence of pseudo files which are ephemeral!
*/ */
public void delete(NodeRef parentDir, String name); public void delete(NodeRef parentDir, String name);
} }

View File

@@ -1,125 +1,125 @@
package org.alfresco.filesys.alfresco; package org.alfresco.filesys.alfresco;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import org.alfresco.filesys.repo.OpenFileMode; import org.alfresco.filesys.repo.OpenFileMode;
import org.alfresco.jlan.server.SrvSession; import org.alfresco.jlan.server.SrvSession;
import org.alfresco.jlan.server.filesys.NetworkFile; import org.alfresco.jlan.server.filesys.NetworkFile;
import org.alfresco.jlan.server.filesys.TreeConnection; import org.alfresco.jlan.server.filesys.TreeConnection;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Extra methods for DiskInterface, primarily implemented to support CIFS shuffles. * Extra methods for DiskInterface, primarily implemented to support CIFS shuffles.
*/ */
public interface RepositoryDiskInterface public interface RepositoryDiskInterface
{ {
/** /**
* Copy the content from one node to another. * Copy the content from one node to another.
* *
* @param rootNode NodeRef * @param rootNode NodeRef
* @param fromPath - the source node * @param fromPath - the source node
* @param toPath - the target node * @param toPath - the target node
* @throws FileNotFoundException * @throws FileNotFoundException
*/ */
public void copyContent(NodeRef rootNode, String fromPath, String toPath) throws FileNotFoundException; public void copyContent(NodeRef rootNode, String fromPath, String toPath) throws FileNotFoundException;
/** /**
* CreateFile. * CreateFile.
* *
* @param rootNode NodeRef * @param rootNode NodeRef
* @param Path - path * @param Path - path
* @param allocationSize size to allocate for new file * @param allocationSize size to allocate for new file
* @param isHidden boolean * @param isHidden boolean
* @throws FileNotFoundException * @throws FileNotFoundException
*/ */
public NetworkFile createFile(NodeRef rootNode, String Path, long allocationSize, boolean isHidden) throws IOException; public NetworkFile createFile(NodeRef rootNode, String Path, long allocationSize, boolean isHidden) throws IOException;
/** /**
* RestoreFile. * RestoreFile.
* *
* Either restores the file or creates a new one. * Either restores the file or creates a new one.
* *
* @param sess SrvSession * @param sess SrvSession
* @param tree TreeConnection * @param tree TreeConnection
* @param rootNode NodeRef * @param rootNode NodeRef
* @param path - path * @param path - path
* @param allocationSize size to allocate for new file * @param allocationSize size to allocate for new file
* @param originalNodeRef NodeRef * @param originalNodeRef NodeRef
* @throws FileNotFoundException * @throws FileNotFoundException
*/ */
public NetworkFile restoreFile(SrvSession sess, public NetworkFile restoreFile(SrvSession sess,
TreeConnection tree, TreeConnection tree,
NodeRef rootNode, NodeRef rootNode,
String path, String path,
long allocationSize, long allocationSize,
NodeRef originalNodeRef) throws IOException; NodeRef originalNodeRef) throws IOException;
/** /**
* *
* @param session // temp until refactor * @param session // temp until refactor
* @param tree // temp until refactor * @param tree // temp until refactor
* @param rootNode NodeRef * @param rootNode NodeRef
* @param path String * @param path String
* @param mode OpenFileMode * @param mode OpenFileMode
* @param truncate boolean * @param truncate boolean
* @return NetworkFile * @return NetworkFile
*/ */
public NetworkFile openFile(SrvSession session, TreeConnection tree, NodeRef rootNode, String path, OpenFileMode mode, boolean truncate) throws IOException; public NetworkFile openFile(SrvSession session, TreeConnection tree, NodeRef rootNode, String path, OpenFileMode mode, boolean truncate) throws IOException;
/** /**
* CloseFile. * CloseFile.
* *
* @param tree TreeConnection * @param tree TreeConnection
* @param rootNode NodeRef * @param rootNode NodeRef
* @param Path - path * @param Path - path
* @param file - file * @param file - file
* @throws FileNotFoundException * @throws FileNotFoundException
* @return node ref of deleted file or null if no file deleted * @return node ref of deleted file or null if no file deleted
*/ */
public NodeRef closeFile(TreeConnection tree, NodeRef rootNode, String Path, NetworkFile file) throws IOException; public NodeRef closeFile(TreeConnection tree, NodeRef rootNode, String Path, NetworkFile file) throws IOException;
/** /**
* Delete file * Delete file
* @param session SrvSession * @param session SrvSession
* @param tree TreeConnection * @param tree TreeConnection
* @param rootNode NodeRef * @param rootNode NodeRef
* @param path String * @param path String
* @return NodeRef of file deleted or null if no file deleted * @return NodeRef of file deleted or null if no file deleted
* @throws IOException * @throws IOException
*/ */
public NodeRef deleteFile2(final SrvSession session, final TreeConnection tree, NodeRef rootNode, String path) throws IOException; public NodeRef deleteFile2(final SrvSession session, final TreeConnection tree, NodeRef rootNode, String path) throws IOException;
/** /**
* *
* @param session SrvSession * @param session SrvSession
* @param tree TreeConnection * @param tree TreeConnection
* @param file NetworkFile * @param file NetworkFile
*/ */
public void reduceQuota(SrvSession session, TreeConnection tree, NetworkFile file); public void reduceQuota(SrvSession session, TreeConnection tree, NetworkFile file);
/** /**
* *
* @param rootNode NodeRef * @param rootNode NodeRef
* @param path String * @param path String
*/ */
public void deleteEmptyFile(NodeRef rootNode, String path); public void deleteEmptyFile(NodeRef rootNode, String path);
/** /**
* Rename the specified file. * Rename the specified file.
* *
* @param rootNode root node * @param rootNode root node
* @param oldName java.lang.String * @param oldName java.lang.String
* @param newName java.lang.String * @param newName java.lang.String
* @param soft boolean * @param soft boolean
* @param moveAsSystem move as system * @param moveAsSystem move as system
* @exception java.io.IOException The exception description. * @exception java.io.IOException The exception description.
*/ */
public void renameFile(NodeRef rootNode, String oldName, String newName, boolean soft, boolean moveAsSystem) public void renameFile(NodeRef rootNode, String oldName, String newName, boolean soft, boolean moveAsSystem)
throws java.io.IOException; throws java.io.IOException;
} }

View File

@@ -1,59 +1,59 @@
package org.alfresco.filesys.alfresco; package org.alfresco.filesys.alfresco;
/** /**
* Cache for alfresco "save shuffles" which are used by some applications * Cache for alfresco "save shuffles" which are used by some applications
* to compensate for a most computer filesystem being non atomic. * to compensate for a most computer filesystem being non atomic.
* *
* <p> * <p>
* Overlays an Alfresco repository with temporary files being created and * Overlays an Alfresco repository with temporary files being created and
* soft deleted from folders that are likely to have save shuffles going on. * soft deleted from folders that are likely to have save shuffles going on.
* <p> * <p>
* Implementations must be thread safe * Implementations must be thread safe
*/ */
public interface ShuffleCache public interface ShuffleCache
{ {
/** /**
* Add a new temporary file to the "shuffle cache". Content is not persisted * Add a new temporary file to the "shuffle cache". Content is not persisted
* in the alfresco repo until either a rename occurs or after a time delay. * in the alfresco repo until either a rename occurs or after a time delay.
*/ */
public void createTemporaryFile(String path); public void createTemporaryFile(String path);
/** /**
* Soft delete a file. The file may be re-instated later or the delete made * Soft delete a file. The file may be re-instated later or the delete made
* permenant after a time delay. * permenant after a time delay.
*/ */
public void softDelete(String path); public void softDelete(String path);
/** /**
* Takes the contents of a temporary file and applies it to the new path. * Takes the contents of a temporary file and applies it to the new path.
* <p> * <p>
* If the new path has been soft deleted then the soft delete is removed. * If the new path has been soft deleted then the soft delete is removed.
* <p> * <p>
* After the contents of the temporary file have been written the it may may be made * After the contents of the temporary file have been written the it may may be made
* available for garbage collection. * available for garbage collection.
* *
* @param oldPath the location of the temporaryFile * @param oldPath the location of the temporaryFile
* @param newPath the location of the new file. * @param newPath the location of the new file.
*/ */
public void renameTemporaryFile(String oldPath, String newPath); public void renameTemporaryFile(String oldPath, String newPath);
/** /**
* Does the specified directory contain a shuffled temporary file * Does the specified directory contain a shuffled temporary file
* @param dir String * @param dir String
* @return boolean * @return boolean
*/ */
boolean isShuffleDirectory(String dir); boolean isShuffleDirectory(String dir);
/** /**
* Has the path been "soft deleted" * Has the path been "soft deleted"
*/ */
boolean isDeleted(String path); boolean isDeleted(String path);
/** /**
* Has the path been "soft created" * Has the path been "soft created"
* @param path String * @param path String
* @return boolean * @return boolean
*/ */
boolean isCreated(String path); boolean isCreated(String path);
} }

View File

@@ -1,101 +1,101 @@
package org.alfresco.filesys.alfresco; package org.alfresco.filesys.alfresco;
import java.util.Map; import java.util.Map;
/** /**
* Cache for alfresco "CIFS shuffles" * Cache for alfresco "CIFS shuffles"
* *
* *
*/ */
public class ShuffleCacheImpl implements ShuffleCache public class ShuffleCacheImpl implements ShuffleCache
{ {
/** /**
* time in ms that temporary files should live in the cache before * time in ms that temporary files should live in the cache before
* being persisted. * being persisted.
*/ */
private long timeBeforePersist = 5 * 60000L; // 5 minutes default private long timeBeforePersist = 5 * 60000L; // 5 minutes default
/** /**
* Is the cache caseSensitive? * Is the cache caseSensitive?
*/ */
private boolean caseSensitive; private boolean caseSensitive;
/** /**
* The shuffle folder cache keyed by path. * The shuffle folder cache keyed by path.
* <path> <shuffleFolderInfo> * <path> <shuffleFolderInfo>
*/ */
private Map<String, ShuffleFolderInfo> folderCache; private Map<String, ShuffleFolderInfo> folderCache;
/** /**
* The information held for each folder that has a "shuffle" * The information held for each folder that has a "shuffle"
* in progress. * in progress.
* @author mrogers * @author mrogers
*/ */
private class ShuffleFolderInfo private class ShuffleFolderInfo
{ {
} }
@Override @Override
public void createTemporaryFile(String path) public void createTemporaryFile(String path)
{ {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
@Override @Override
public void softDelete(String path) public void softDelete(String path)
{ {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
@Override @Override
public void renameTemporaryFile(String oldPath, String newPath) public void renameTemporaryFile(String oldPath, String newPath)
{ {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
@Override @Override
public boolean isShuffleDirectory(String dir) public boolean isShuffleDirectory(String dir)
{ {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return false; return false;
} }
@Override @Override
public boolean isDeleted(String path) public boolean isDeleted(String path)
{ {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return false; return false;
} }
@Override @Override
public boolean isCreated(String path) public boolean isCreated(String path)
{ {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return false; return false;
} }
void setTimeBeforePersist(long timeBeforePersist) void setTimeBeforePersist(long timeBeforePersist)
{ {
this.timeBeforePersist = timeBeforePersist; this.timeBeforePersist = timeBeforePersist;
} }
long getTimeBeforePersist() long getTimeBeforePersist()
{ {
return timeBeforePersist; return timeBeforePersist;
} }
public void setCaseSensitive(boolean caseSensitive) public void setCaseSensitive(boolean caseSensitive)
{ {
this.caseSensitive = caseSensitive; this.caseSensitive = caseSensitive;
} }
public boolean isCaseSensitive() public boolean isCaseSensitive()
{ {
return caseSensitive; return caseSensitive;
} }
} }

View File

@@ -1,15 +1,15 @@
/** /**
* FileSystem * FileSystem
* *
* DesktopAction * DesktopAction
* *
* AlfrescoDiskDriver * AlfrescoDiskDriver
* *
* MultiTenantShareMapper * MultiTenantShareMapper
* *
* *
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys.alfresco; package org.alfresco.filesys.alfresco;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,14 +1,14 @@
/** /**
* Provides authentication implementations for CIFS * Provides authentication implementations for CIFS
* <p> * <p>
* AlfrescoCifsAuthenticator * AlfrescoCifsAuthenticator
* EnterpriseCifsAuthenticator deals with Kerberos, NTLMv1 and NTLMv2 * EnterpriseCifsAuthenticator deals with Kerberos, NTLMv1 and NTLMv2
* PassthruCifsAuthenticator deals with authenticating against an external system * PassthruCifsAuthenticator deals with authenticating against an external system
* *
* <p> * <p>
* CifsAuthenticatorBase abstract base class. * CifsAuthenticatorBase abstract base class.
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys.auth.cifs; package org.alfresco.filesys.auth.cifs;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,5 +1,5 @@
/** /**
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys.auth.ftp; package org.alfresco.filesys.auth.ftp;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,5 +1,5 @@
/** /**
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys.auth.nfs; package org.alfresco.filesys.auth.nfs;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,5 +1,5 @@
/** /**
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys.auth; package org.alfresco.filesys.auth;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,45 +1,45 @@
package org.alfresco.filesys.config; package org.alfresco.filesys.config;
/** /**
* The Class ClusterConfigBean. * The Class ClusterConfigBean.
* *
* @author mrogers * @author mrogers
* @since 4.0 * @since 4.0
*/ */
public class ClusterConfigBean public class ClusterConfigBean
{ {
private String debugFlags; private String debugFlags;
private int nearCacheTimeout; private int nearCacheTimeout;
public boolean getClusterEnabled() public boolean getClusterEnabled()
{ {
// No clustering support in community edition. // No clustering support in community edition.
return false; return false;
} }
public String getClusterName() public String getClusterName()
{ {
// No clustering support in community edition. // No clustering support in community edition.
return null; return null;
} }
public void setDebugFlags(String debugFlags) public void setDebugFlags(String debugFlags)
{ {
this.debugFlags = debugFlags; this.debugFlags = debugFlags;
} }
public String getDebugFlags() public String getDebugFlags()
{ {
return debugFlags; return debugFlags;
} }
public void setNearCacheTimeout(int nearCacheTimeout) public void setNearCacheTimeout(int nearCacheTimeout)
{ {
this.nearCacheTimeout = nearCacheTimeout; this.nearCacheTimeout = nearCacheTimeout;
} }
public int getNearCacheTimeout() public int getNearCacheTimeout()
{ {
return nearCacheTimeout; return nearCacheTimeout;
} }
} }

View File

@@ -1,5 +1,5 @@
/** /**
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys.config.acl; package org.alfresco.filesys.config.acl;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,5 +1,5 @@
/** /**
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys.config; package org.alfresco.filesys.config;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,5 +1,5 @@
/** /**
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys.debug; package org.alfresco.filesys.debug;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,6 +1,6 @@
/** /**
* The Alfresco file system interface implementation * The Alfresco file system interface implementation
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys; package org.alfresco.filesys;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,93 +1,93 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import java.io.IOException; import java.io.IOException;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.jlan.server.filesys.FileInfo; import org.alfresco.jlan.server.filesys.FileInfo;
import org.alfresco.jlan.server.filesys.NetworkFile; import org.alfresco.jlan.server.filesys.NetworkFile;
import org.alfresco.jlan.server.filesys.cache.FileState; import org.alfresco.jlan.server.filesys.cache.FileState;
import org.alfresco.jlan.server.filesys.cache.NetworkFileStateInterface; import org.alfresco.jlan.server.filesys.cache.NetworkFileStateInterface;
/** /**
* Object returned to JLAN if the repository object is a folder. * Object returned to JLAN if the repository object is a folder.
*/ */
public class AlfrescoFolder extends NetworkFile implements NetworkFileStateInterface public class AlfrescoFolder extends NetworkFile implements NetworkFileStateInterface
{ {
public AlfrescoFolder(String path, FileInfo fileInfo, boolean readOnly) public AlfrescoFolder(String path, FileInfo fileInfo, boolean readOnly)
{ {
super(path); super(path);
setFullName(path); setFullName(path);
// Set the file timestamps // Set the file timestamps
if ( fileInfo.hasCreationDateTime()) if ( fileInfo.hasCreationDateTime())
setCreationDate( fileInfo.getCreationDateTime()); setCreationDate( fileInfo.getCreationDateTime());
if ( fileInfo.hasModifyDateTime()) if ( fileInfo.hasModifyDateTime())
setModifyDate(fileInfo.getModifyDateTime()); setModifyDate(fileInfo.getModifyDateTime());
if ( fileInfo.hasAccessDateTime()) if ( fileInfo.hasAccessDateTime())
setAccessDate(fileInfo.getAccessDateTime()); setAccessDate(fileInfo.getAccessDateTime());
// Set the file attributes // Set the file attributes
setAttributes(fileInfo.getFileAttributes()); setAttributes(fileInfo.getFileAttributes());
} }
@Override @Override
public void openFile(boolean createFlag) throws IOException public void openFile(boolean createFlag) throws IOException
{ {
throw new AlfrescoRuntimeException("Unable to open channel for a directory network file: " + this); throw new AlfrescoRuntimeException("Unable to open channel for a directory network file: " + this);
} }
@Override @Override
public int readFile(byte[] buf, int len, int pos, long fileOff) public int readFile(byte[] buf, int len, int pos, long fileOff)
throws IOException throws IOException
{ {
throw new AlfrescoRuntimeException("Unable to open channel for a directory network file: " + this); throw new AlfrescoRuntimeException("Unable to open channel for a directory network file: " + this);
} }
@Override @Override
public void writeFile(byte[] buf, int len, int pos, long fileOff) public void writeFile(byte[] buf, int len, int pos, long fileOff)
throws IOException throws IOException
{ {
throw new AlfrescoRuntimeException("Unable to open channel for a directory network file: " + this); throw new AlfrescoRuntimeException("Unable to open channel for a directory network file: " + this);
} }
@Override @Override
public long seekFile(long pos, int typ) throws IOException public long seekFile(long pos, int typ) throws IOException
{ {
return 0; return 0;
} }
@Override @Override
public void flushFile() throws IOException public void flushFile() throws IOException
{ {
// Do nothing. // Do nothing.
} }
@Override @Override
public void truncateFile(long siz) throws IOException public void truncateFile(long siz) throws IOException
{ {
throw new AlfrescoRuntimeException("Unable to open channel for a directory network file: " + this); throw new AlfrescoRuntimeException("Unable to open channel for a directory network file: " + this);
} }
@Override @Override
public void closeFile() throws IOException public void closeFile() throws IOException
{ {
setClosed(true); setClosed(true);
} }
// For JLAN file state lock manager // For JLAN file state lock manager
public void setFileState(FileState fileState) public void setFileState(FileState fileState)
{ {
this.fileState = fileState; this.fileState = fileState;
} }
@Override @Override
public FileState getFileState() public FileState getFileState()
{ {
return fileState; return fileState;
} }
private FileState fileState; private FileState fileState;
} }

View File

@@ -1,498 +1,498 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.util.EqualsHelper; import org.alfresco.util.EqualsHelper;
import org.alfresco.util.TempFileProvider; import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.HSLFSlideShow;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.EntryUtils; import org.apache.poi.poifs.filesystem.EntryUtils;
import org.apache.poi.poifs.filesystem.FilteringDirectoryNode; import org.apache.poi.poifs.filesystem.FilteringDirectoryNode;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
/** /**
* Compares content for to see if content is equal. * Compares content for to see if content is equal.
* <p> * <p>
* Most mimetypes can simply be binary compared but for some mimetypes * Most mimetypes can simply be binary compared but for some mimetypes
* there may be trivial differences so a binary compare is not sufficient. * there may be trivial differences so a binary compare is not sufficient.
* <p> * <p>
* In particular MS Project and MS Excel write to header fields without changing content. * In particular MS Project and MS Excel write to header fields without changing content.
* *
* @author mrogers * @author mrogers
* *
*/ */
public class CIFSContentComparator implements ContentComparator public class CIFSContentComparator implements ContentComparator
{ {
// TODO Externalize Map of mimetype to comparator // TODO Externalize Map of mimetype to comparator
private Map<String, ContentComparator> customComparators = new HashMap<String, ContentComparator>(); private Map<String, ContentComparator> customComparators = new HashMap<String, ContentComparator>();
private static final Log logger = LogFactory.getLog(CIFSContentComparator.class); private static final Log logger = LogFactory.getLog(CIFSContentComparator.class);
/** /**
* *
*/ */
public void init() public void init()
{ {
customComparators.put("application/vnd.ms-project", new MPPContentComparator()); customComparators.put("application/vnd.ms-project", new MPPContentComparator());
customComparators.put("application/vnd.ms-excel", new XLSContentComparator()); customComparators.put("application/vnd.ms-excel", new XLSContentComparator());
customComparators.put("application/vnd.ms-powerpoint", new PPTContentComparator()); customComparators.put("application/vnd.ms-powerpoint", new PPTContentComparator());
} }
@Override @Override
public boolean isContentEqual(ContentReader existingContent, public boolean isContentEqual(ContentReader existingContent,
File newFile) File newFile)
{ {
String mimetype = existingContent.getMimetype(); String mimetype = existingContent.getMimetype();
logger.debug("isContentEqual mimetype=" + mimetype); logger.debug("isContentEqual mimetype=" + mimetype);
long newSize = newFile.length(); long newSize = newFile.length();
ContentComparator custom = customComparators.get(mimetype); ContentComparator custom = customComparators.get(mimetype);
if(custom == null) if(custom == null)
{ {
// No custom comparator - check length then do a binary diff // No custom comparator - check length then do a binary diff
if(existingContent.getSize() != newSize) if(existingContent.getSize() != newSize)
{ {
// Different size // Different size
logger.debug("generic comparision, size is different - not equal"); logger.debug("generic comparision, size is different - not equal");
return false; return false;
} }
InputStream rightIs = null; InputStream rightIs = null;
InputStream leftIs = null; InputStream leftIs = null;
try try
{ {
rightIs = new BufferedInputStream(new FileInputStream(newFile)); rightIs = new BufferedInputStream(new FileInputStream(newFile));
leftIs = existingContent.getContentInputStream(); leftIs = existingContent.getContentInputStream();
boolean retVal = EqualsHelper.binaryStreamEquals(leftIs, rightIs); boolean retVal = EqualsHelper.binaryStreamEquals(leftIs, rightIs);
rightIs = null; rightIs = null;
leftIs = null; leftIs = null;
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("generic comparision, binary content comparison equal=" + retVal); logger.debug("generic comparision, binary content comparison equal=" + retVal);
} }
return retVal; return retVal;
} }
catch (IOException e) catch (IOException e)
{ {
logger.debug("Unable to compare contents", e); logger.debug("Unable to compare contents", e);
return false; return false;
} }
finally finally
{ {
if(leftIs != null) if(leftIs != null)
{ {
try try
{ {
leftIs.close(); leftIs.close();
} }
catch (IOException e) catch (IOException e)
{ {
// Do nothing this is cleanup code // Do nothing this is cleanup code
} }
} }
if(rightIs != null) if(rightIs != null)
{ {
try try
{ {
rightIs.close(); rightIs.close();
} }
catch (IOException e) catch (IOException e)
{ {
// Do nothing this is cleanup code // Do nothing this is cleanup code
} }
} }
} }
} }
else else
{ {
// there is a custom comparator for this mimetype // there is a custom comparator for this mimetype
return custom.isContentEqual(existingContent, newFile); return custom.isContentEqual(existingContent, newFile);
} }
} }
private boolean isContentIdentical(NPOIFSFileSystem fs1, NPOIFSFileSystem fs2, Collection<String> excludes) throws IOException private boolean isContentIdentical(NPOIFSFileSystem fs1, NPOIFSFileSystem fs2, Collection<String> excludes) throws IOException
{ {
DirectoryEntry de1 = fs1.getRoot(); DirectoryEntry de1 = fs1.getRoot();
DirectoryEntry de2 = fs2.getRoot(); DirectoryEntry de2 = fs2.getRoot();
FilteringDirectoryNode fs1Filtered = new FilteringDirectoryNode(de1, excludes); FilteringDirectoryNode fs1Filtered = new FilteringDirectoryNode(de1, excludes);
FilteringDirectoryNode fs2Filtered = new FilteringDirectoryNode(de2, excludes); FilteringDirectoryNode fs2Filtered = new FilteringDirectoryNode(de2, excludes);
boolean retVal = EntryUtils.areDirectoriesIdentical(fs1Filtered, fs2Filtered); boolean retVal = EntryUtils.areDirectoriesIdentical(fs1Filtered, fs2Filtered);
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("returning equal="+ retVal); logger.debug("returning equal="+ retVal);
} }
return retVal; return retVal;
} }
// Comparator for MS Project // Comparator for MS Project
private class MPPContentComparator implements ContentComparator private class MPPContentComparator implements ContentComparator
{ {
@Override @Override
public boolean isContentEqual(ContentReader existingContent, public boolean isContentEqual(ContentReader existingContent,
File newFile) File newFile)
{ {
long newSize = newFile.length(); long newSize = newFile.length();
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("comparing two project files size:" + existingContent.getSize() + ", and " + newFile.length()); logger.debug("comparing two project files size:" + existingContent.getSize() + ", and " + newFile.length());
} }
if(existingContent.getSize() != newSize) if(existingContent.getSize() != newSize)
{ {
logger.debug("project files are different size"); logger.debug("project files are different size");
// Different size // Different size
return false; return false;
} }
/** /**
* Use POI to compare the content of the MPP file, exluding certain properties * Use POI to compare the content of the MPP file, exluding certain properties
*/ */
InputStream leftIs = null; InputStream leftIs = null;
try try
{ {
Collection<String> excludes = new HashSet<String>(); Collection<String> excludes = new HashSet<String>();
excludes.add("Props"); excludes.add("Props");
excludes.add("Props12"); excludes.add("Props12");
excludes.add("Props9"); excludes.add("Props9");
leftIs = existingContent.getContentInputStream(); leftIs = existingContent.getContentInputStream();
// this call guarantees that leftIs is closed. // this call guarantees that leftIs is closed.
NPOIFSFileSystem fs2 = new NPOIFSFileSystem(leftIs); NPOIFSFileSystem fs2 = new NPOIFSFileSystem(leftIs);
// this call keeps an open file handle and needs closing. // this call keeps an open file handle and needs closing.
NPOIFSFileSystem fs1 = new NPOIFSFileSystem(newFile); NPOIFSFileSystem fs1 = new NPOIFSFileSystem(newFile);
try try
{ {
return isContentIdentical(fs1, fs2, excludes); return isContentIdentical(fs1, fs2, excludes);
} }
finally finally
{ {
try try
{ {
fs1.close(); fs1.close();
} }
catch (IOException e) catch (IOException e)
{ {
// ignore // ignore
} }
try try
{ {
fs2.close(); fs2.close();
} }
catch (IOException e) catch (IOException e)
{ {
// ignore // ignore
} }
} }
} }
catch (ContentIOException ce) catch (ContentIOException ce)
{ {
logger.debug("Unable to compare contents", ce); logger.debug("Unable to compare contents", ce);
return false; return false;
} }
catch (IOException e) catch (IOException e)
{ {
logger.debug("Unable to compare contents", e); logger.debug("Unable to compare contents", e);
return false; return false;
} }
finally finally
{ {
if(leftIs != null) if(leftIs != null)
{ {
try try
{ {
leftIs.close(); leftIs.close();
} }
catch (IOException e) catch (IOException e)
{ {
// Ignore // Ignore
} }
} }
} }
} }
} }
// Comparator for MS Excel // Comparator for MS Excel
private class XLSContentComparator implements ContentComparator private class XLSContentComparator implements ContentComparator
{ {
@Override @Override
public boolean isContentEqual(ContentReader existingContent, public boolean isContentEqual(ContentReader existingContent,
File newFile) File newFile)
{ {
long newSize = newFile.length(); long newSize = newFile.length();
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("comparing two excel files size:" + existingContent.getSize() + ", and " + newFile.length()); logger.debug("comparing two excel files size:" + existingContent.getSize() + ", and " + newFile.length());
} }
if(existingContent.getSize() != newSize) if(existingContent.getSize() != newSize)
{ {
logger.debug("excel files are different size"); logger.debug("excel files are different size");
// Different size // Different size
return false; return false;
} }
/** /**
* Use POI to compare the content of the XLS file, exluding certain properties * Use POI to compare the content of the XLS file, exluding certain properties
*/ */
File tpm1 = null; File tpm1 = null;
File tpm2 = null; File tpm2 = null;
InputStream leftIs = null; InputStream leftIs = null;
try try
{ {
Collection<String> excludes = new HashSet<String>(); Collection<String> excludes = new HashSet<String>();
tpm1 = TempFileProvider.createTempFile("CIFSContentComparator1", "xls"); tpm1 = TempFileProvider.createTempFile("CIFSContentComparator1", "xls");
tpm2 = TempFileProvider.createTempFile("CIFSContentComparator2", "xls"); tpm2 = TempFileProvider.createTempFile("CIFSContentComparator2", "xls");
leftIs = existingContent.getContentInputStream(); leftIs = existingContent.getContentInputStream();
HSSFWorkbook wb1 = new HSSFWorkbook(leftIs); HSSFWorkbook wb1 = new HSSFWorkbook(leftIs);
HSSFWorkbook wb2 = new HSSFWorkbook(new FileInputStream(newFile)); HSSFWorkbook wb2 = new HSSFWorkbook(new FileInputStream(newFile));
wb1.writeProtectWorkbook("", "CIFSContentComparator"); wb1.writeProtectWorkbook("", "CIFSContentComparator");
wb2.writeProtectWorkbook("", "CIFSContentComparator"); wb2.writeProtectWorkbook("", "CIFSContentComparator");
FileOutputStream os = new FileOutputStream(tpm1); FileOutputStream os = new FileOutputStream(tpm1);
try try
{ {
wb1.write(os); wb1.write(os);
} }
finally finally
{ {
os.close(); os.close();
} }
FileOutputStream os2 = new FileOutputStream(tpm2); FileOutputStream os2 = new FileOutputStream(tpm2);
try try
{ {
wb2.write(os2); wb2.write(os2);
} }
finally finally
{ {
os2.close(); os2.close();
} }
NPOIFSFileSystem fs1 = new NPOIFSFileSystem(tpm1); NPOIFSFileSystem fs1 = new NPOIFSFileSystem(tpm1);
NPOIFSFileSystem fs2 = new NPOIFSFileSystem(tpm2); NPOIFSFileSystem fs2 = new NPOIFSFileSystem(tpm2);
return isContentIdentical(fs1, fs2, excludes); return isContentIdentical(fs1, fs2, excludes);
} }
catch (ContentIOException ce) catch (ContentIOException ce)
{ {
logger.debug("Unable to compare contents", ce); logger.debug("Unable to compare contents", ce);
return false; return false;
} }
catch (IOException e) catch (IOException e)
{ {
logger.debug("Unable to compare contents", e); logger.debug("Unable to compare contents", e);
return false; return false;
} }
finally finally
{ {
if(tpm1 != null) if(tpm1 != null)
{ {
try try
{ {
tpm1.delete(); tpm1.delete();
} }
catch (Exception e) catch (Exception e)
{ {
// ignore // ignore
} }
} }
if(tpm2 != null) if(tpm2 != null)
{ {
try try
{ {
tpm2.delete(); tpm2.delete();
} }
catch (Exception e) catch (Exception e)
{ {
// ignore // ignore
} }
} }
if(leftIs != null) if(leftIs != null)
{ {
try try
{ {
leftIs.close(); leftIs.close();
} }
catch (IOException e) catch (IOException e)
{ {
// Ignore // Ignore
} }
} }
} }
} }
} }
// Comparator for MS PowerPoint // Comparator for MS PowerPoint
private class PPTContentComparator implements ContentComparator private class PPTContentComparator implements ContentComparator
{ {
@Override @Override
public boolean isContentEqual(ContentReader existingContent, File newFile) public boolean isContentEqual(ContentReader existingContent, File newFile)
{ {
long fileSizesDifference = newFile.length() - existingContent.getSize(); long fileSizesDifference = newFile.length() - existingContent.getSize();
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("comparing two powerpoint files size:" + existingContent.getSize() + ", and " + newFile.length()); logger.debug("comparing two powerpoint files size:" + existingContent.getSize() + ", and " + newFile.length());
} }
File tpm1 = null; File tpm1 = null;
File tpm2 = null; File tpm2 = null;
InputStream leftIs = null; InputStream leftIs = null;
try try
{ {
if(fileSizesDifference != 0) if(fileSizesDifference != 0)
{ {
// ALF-18793 // ALF-18793
// Experience has shown that the size of opened/closed file increases to 3072 bytes. // Experience has shown that the size of opened/closed file increases to 3072 bytes.
// (That occurs only in case if the file has been created on one MS PowerPoint instance and opened/closed on another // (That occurs only in case if the file has been created on one MS PowerPoint instance and opened/closed on another
// due to change of lastEditUsername property (if they are different)). // due to change of lastEditUsername property (if they are different)).
if (fileSizesDifference > 3072 && fileSizesDifference < 0) if (fileSizesDifference > 3072 && fileSizesDifference < 0)
{ {
logger.debug("powerpoint files are different size"); logger.debug("powerpoint files are different size");
// Different size // Different size
return false; return false;
} }
Collection<String> excludes = new HashSet<String>(); Collection<String> excludes = new HashSet<String>();
excludes.add("Current User"); excludes.add("Current User");
leftIs = existingContent.getContentInputStream(); leftIs = existingContent.getContentInputStream();
HSLFSlideShow slideShow1 = new HSLFSlideShow(leftIs); HSLFSlideShow slideShow1 = new HSLFSlideShow(leftIs);
HSLFSlideShow slideShow2 = new HSLFSlideShow(new FileInputStream(newFile)); HSLFSlideShow slideShow2 = new HSLFSlideShow(new FileInputStream(newFile));
String lastEditUsername1 = slideShow1.getCurrentUserAtom().getLastEditUsername(); String lastEditUsername1 = slideShow1.getCurrentUserAtom().getLastEditUsername();
String lastEditUsername2 = slideShow2.getCurrentUserAtom().getLastEditUsername(); String lastEditUsername2 = slideShow2.getCurrentUserAtom().getLastEditUsername();
if (lastEditUsername1.equals(lastEditUsername2)) if (lastEditUsername1.equals(lastEditUsername2))
{ {
logger.debug("powerpoint files are edited by different users"); logger.debug("powerpoint files are edited by different users");
// Different size // Different size
return false; return false;
} }
else else
{ {
//make sure that nothing has been changed except lastEditUsername //make sure that nothing has been changed except lastEditUsername
tpm1 = TempFileProvider.createTempFile("CIFSContentComparator1", "ppt"); tpm1 = TempFileProvider.createTempFile("CIFSContentComparator1", "ppt");
FileOutputStream os = new FileOutputStream(tpm1); FileOutputStream os = new FileOutputStream(tpm1);
try try
{ {
slideShow1.write(os); slideShow1.write(os);
} }
finally finally
{ {
try try
{ {
os.close(); os.close();
} }
catch (IOException ie) catch (IOException ie)
{ {
// ignore // ignore
} }
} }
tpm2 = TempFileProvider.createTempFile("CIFSContentComparator2", "ppt"); tpm2 = TempFileProvider.createTempFile("CIFSContentComparator2", "ppt");
FileOutputStream os2 = new FileOutputStream(tpm2); FileOutputStream os2 = new FileOutputStream(tpm2);
try try
{ {
slideShow2.write(os2); slideShow2.write(os2);
} }
finally finally
{ {
try try
{ {
os2.close(); os2.close();
} }
catch (IOException ie) catch (IOException ie)
{ {
// ignore // ignore
} }
} }
NPOIFSFileSystem fs1 = new NPOIFSFileSystem(tpm1); NPOIFSFileSystem fs1 = new NPOIFSFileSystem(tpm1);
NPOIFSFileSystem fs2 = new NPOIFSFileSystem(tpm2); NPOIFSFileSystem fs2 = new NPOIFSFileSystem(tpm2);
return isContentIdentical(fs1, fs2, excludes); return isContentIdentical(fs1, fs2, excludes);
} }
} }
return true; return true;
} }
catch (ContentIOException ce) catch (ContentIOException ce)
{ {
logger.debug("Unable to compare contents", ce); logger.debug("Unable to compare contents", ce);
return false; return false;
} }
catch (IOException e) catch (IOException e)
{ {
logger.debug("Unable to compare contents", e); logger.debug("Unable to compare contents", e);
return false; return false;
} }
finally finally
{ {
if(tpm1 != null) if(tpm1 != null)
{ {
try try
{ {
tpm1.delete(); tpm1.delete();
} }
catch (Exception e) catch (Exception e)
{ {
// ignore // ignore
} }
} }
if(tpm2 != null) if(tpm2 != null)
{ {
try try
{ {
tpm2.delete(); tpm2.delete();
} }
catch (Exception e) catch (Exception e)
{ {
// ignore // ignore
} }
} }
if(leftIs != null) if(leftIs != null)
{ {
try try
{ {
leftIs.close(); leftIs.close();
} }
catch (IOException e) catch (IOException e)
{ {
// Ignore // Ignore
} }
} }
} }
} }
} }
} }

View File

@@ -1,22 +1,22 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import java.io.IOException; import java.io.IOException;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.jlan.server.SrvSession; import org.alfresco.jlan.server.SrvSession;
import org.alfresco.jlan.server.filesys.TreeConnection; import org.alfresco.jlan.server.filesys.TreeConnection;
/** /**
* The Command Executor - executes commands! * The Command Executor - executes commands!
*/ */
public interface CommandExecutor public interface CommandExecutor
{ {
/** /**
* Execute the command. * Execute the command.
* @param command * @param command
* *
* @return an object for return or null if there is no return value. * @return an object for return or null if there is no return value.
* @throws IOException * @throws IOException
*/ */
public Object execute(SrvSession sess, TreeConnection tree, Command command) throws IOException; public Object execute(SrvSession sess, TreeConnection tree, Command command) throws IOException;
} }

View File

@@ -1,391 +1,391 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.util.List; import java.util.List;
import org.alfresco.filesys.alfresco.ExtendedDiskInterface; import org.alfresco.filesys.alfresco.ExtendedDiskInterface;
import org.alfresco.filesys.alfresco.RepositoryDiskInterface; import org.alfresco.filesys.alfresco.RepositoryDiskInterface;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.filesys.repo.rules.commands.CloseFileCommand; import org.alfresco.filesys.repo.rules.commands.CloseFileCommand;
import org.alfresco.filesys.repo.rules.commands.CompoundCommand; import org.alfresco.filesys.repo.rules.commands.CompoundCommand;
import org.alfresco.filesys.repo.rules.commands.CopyContentCommand; import org.alfresco.filesys.repo.rules.commands.CopyContentCommand;
import org.alfresco.filesys.repo.rules.commands.CreateFileCommand; import org.alfresco.filesys.repo.rules.commands.CreateFileCommand;
import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand; import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand;
import org.alfresco.filesys.repo.rules.commands.DoNothingCommand; import org.alfresco.filesys.repo.rules.commands.DoNothingCommand;
import org.alfresco.filesys.repo.rules.commands.MoveFileCommand; import org.alfresco.filesys.repo.rules.commands.MoveFileCommand;
import org.alfresco.filesys.repo.rules.commands.OpenFileCommand; import org.alfresco.filesys.repo.rules.commands.OpenFileCommand;
import org.alfresco.filesys.repo.rules.commands.ReduceQuotaCommand; import org.alfresco.filesys.repo.rules.commands.ReduceQuotaCommand;
import org.alfresco.filesys.repo.rules.commands.RemoveNoContentFileOnError; import org.alfresco.filesys.repo.rules.commands.RemoveNoContentFileOnError;
import org.alfresco.filesys.repo.rules.commands.RemoveTempFileCommand; import org.alfresco.filesys.repo.rules.commands.RemoveTempFileCommand;
import org.alfresco.filesys.repo.rules.commands.RenameFileCommand; import org.alfresco.filesys.repo.rules.commands.RenameFileCommand;
import org.alfresco.filesys.repo.rules.commands.RestoreFileCommand; import org.alfresco.filesys.repo.rules.commands.RestoreFileCommand;
import org.alfresco.filesys.repo.rules.commands.ReturnValueCommand; import org.alfresco.filesys.repo.rules.commands.ReturnValueCommand;
import org.alfresco.jlan.server.SrvSession; import org.alfresco.jlan.server.SrvSession;
import org.alfresco.jlan.server.filesys.TreeConnection; import org.alfresco.jlan.server.filesys.TreeConnection;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.FileFilterMode; import org.alfresco.util.FileFilterMode;
import org.alfresco.util.PropertyCheck; import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* Content Disk Driver Command Executor * Content Disk Driver Command Executor
* <p> * <p>
* Executes commands against the repository. * Executes commands against the repository.
*/ */
public class CommandExecutorImpl implements CommandExecutor public class CommandExecutorImpl implements CommandExecutor
{ {
private static Log logger = LogFactory.getLog(CommandExecutorImpl.class); private static Log logger = LogFactory.getLog(CommandExecutorImpl.class);
// Services go here. // Services go here.
private TransactionService transactionService; private TransactionService transactionService;
private RepositoryDiskInterface repositoryDiskInterface; private RepositoryDiskInterface repositoryDiskInterface;
private ExtendedDiskInterface diskInterface; private ExtendedDiskInterface diskInterface;
public void init() public void init()
{ {
PropertyCheck.mandatory(this, "transactionService", transactionService); PropertyCheck.mandatory(this, "transactionService", transactionService);
PropertyCheck.mandatory(this, "diskInterface", diskInterface); PropertyCheck.mandatory(this, "diskInterface", diskInterface);
PropertyCheck.mandatory(this, "repositoryDiskInterface", getRepositoryDiskInterface()); PropertyCheck.mandatory(this, "repositoryDiskInterface", getRepositoryDiskInterface());
} }
@Override @Override
public Object execute(final SrvSession sess, final TreeConnection tree, final Command command) throws IOException public Object execute(final SrvSession sess, final TreeConnection tree, final Command command) throws IOException
{ {
TxnReadState readState = command.getTransactionRequired(); TxnReadState readState = command.getTransactionRequired();
Object ret = null; Object ret = null;
// No transaction required. // No transaction required.
if(readState == TxnReadState.TXN_NONE) if(readState == TxnReadState.TXN_NONE)
{ {
ret = executeInternal(sess, tree, command, null); ret = executeInternal(sess, tree, command, null);
} }
else else
{ {
// Yes a transaction is required. // Yes a transaction is required.
RetryingTransactionHelper helper = transactionService.getRetryingTransactionHelper(); RetryingTransactionHelper helper = transactionService.getRetryingTransactionHelper();
boolean readOnly = readState == TxnReadState.TXN_READ_ONLY; boolean readOnly = readState == TxnReadState.TXN_READ_ONLY;
RetryingTransactionCallback<Object> cb = new RetryingTransactionCallback<Object>() RetryingTransactionCallback<Object> cb = new RetryingTransactionCallback<Object>()
{ {
/** /**
* Perform a set of commands as a unit of transactional work. * Perform a set of commands as a unit of transactional work.
* *
* @return Return the result of the unit of work * @return Return the result of the unit of work
* @throws IOException * @throws IOException
*/ */
public Object execute() throws IOException public Object execute() throws IOException
{ {
try try
{ {
return executeInternal(sess, tree, command, null); return executeInternal(sess, tree, command, null);
} }
catch (IOException e) catch (IOException e)
{ {
// Ensure original checked IOExceptions get propagated // Ensure original checked IOExceptions get propagated
throw new PropagatingException(e); throw new PropagatingException(e);
} }
} }
}; };
try try
{ {
ret = helper.doInTransaction(cb, readOnly); ret = helper.doInTransaction(cb, readOnly);
} }
catch(PropagatingException pe) catch(PropagatingException pe)
{ {
if(command instanceof CompoundCommand) if(command instanceof CompoundCommand)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("error executing command :command" + command, pe); logger.debug("error executing command :command" + command, pe);
} }
CompoundCommand c = (CompoundCommand)command; CompoundCommand c = (CompoundCommand)command;
// Error Callback Here ? // Error Callback Here ?
List<Command> commands = c.getPostErrorCommands(); List<Command> commands = c.getPostErrorCommands();
if(commands != null) if(commands != null)
{ {
for(Command c2 : commands) for(Command c2 : commands)
{ {
try try
{ {
executeInternal(sess, tree, c2, ret); executeInternal(sess, tree, c2, ret);
} }
catch(Throwable t) catch(Throwable t)
{ {
logger.warn("caught and ignored exception from error handler", t); logger.warn("caught and ignored exception from error handler", t);
// Swallow exception from error handler. // Swallow exception from error handler.
} }
} }
} }
} }
// Unwrap checked exceptions // Unwrap checked exceptions
throw (IOException) pe.getCause(); throw (IOException) pe.getCause();
} }
} }
/** /**
* execute post commit commands. * execute post commit commands.
*/ */
if(command instanceof CompoundCommand) if(command instanceof CompoundCommand)
{ {
logger.debug("post commit of compound command"); logger.debug("post commit of compound command");
CompoundCommand c = (CompoundCommand)command; CompoundCommand c = (CompoundCommand)command;
List<Command> commands = c.getPostCommitCommands(); List<Command> commands = c.getPostCommitCommands();
if(commands != null) if(commands != null)
{ {
for(Command c2 : commands) for(Command c2 : commands)
{ {
// TODO - what about exceptions from post commit? // TODO - what about exceptions from post commit?
executeInternal(sess, tree, c2, ret); executeInternal(sess, tree, c2, ret);
} }
} }
} }
return ret; return ret;
} }
/** /**
* @param sess SrvSession * @param sess SrvSession
* @param tree TreeConnection * @param tree TreeConnection
* @param command Command * @param command Command
* @param result Object * @param result Object
* @return Object * @return Object
* @throws IOException * @throws IOException
*/ */
private Object executeInternal(SrvSession sess, TreeConnection tree, Command command, Object result) throws IOException private Object executeInternal(SrvSession sess, TreeConnection tree, Command command, Object result) throws IOException
{ {
FileFilterMode.setClient(ClientHelper.getClient(sess)); FileFilterMode.setClient(ClientHelper.getClient(sess));
try try
{ {
if(command instanceof CompoundCommand) if(command instanceof CompoundCommand)
{ {
Object ret = null; Object ret = null;
logger.debug("compound command received"); logger.debug("compound command received");
CompoundCommand x = (CompoundCommand)command; CompoundCommand x = (CompoundCommand)command;
for(Command compoundPart : x.getCommands()) for(Command compoundPart : x.getCommands())
{ {
logger.debug("running part of compound command"); logger.debug("running part of compound command");
Object val = executeInternal(sess, tree, compoundPart, result); Object val = executeInternal(sess, tree, compoundPart, result);
if(val != null) if(val != null)
{ {
// Return the value from the last command. // Return the value from the last command.
ret = val; ret = val;
} }
} }
return ret; return ret;
} }
else if(command instanceof CreateFileCommand) else if(command instanceof CreateFileCommand)
{ {
logger.debug("create file command"); logger.debug("create file command");
CreateFileCommand create = (CreateFileCommand)command; CreateFileCommand create = (CreateFileCommand)command;
return repositoryDiskInterface.createFile(create.getRootNode(), create.getPath(), create.getAllocationSize(), create.isHidden()); return repositoryDiskInterface.createFile(create.getRootNode(), create.getPath(), create.getAllocationSize(), create.isHidden());
} }
else if(command instanceof RestoreFileCommand) else if(command instanceof RestoreFileCommand)
{ {
logger.debug("restore file command"); logger.debug("restore file command");
RestoreFileCommand restore = (RestoreFileCommand)command; RestoreFileCommand restore = (RestoreFileCommand)command;
return repositoryDiskInterface.restoreFile(sess, tree, restore.getRootNode(), restore.getPath(), restore.getAllocationSize(), restore.getOriginalNodeRef()); return repositoryDiskInterface.restoreFile(sess, tree, restore.getRootNode(), restore.getPath(), restore.getAllocationSize(), restore.getOriginalNodeRef());
} }
else if(command instanceof DeleteFileCommand) else if(command instanceof DeleteFileCommand)
{ {
logger.debug("delete file command"); logger.debug("delete file command");
DeleteFileCommand delete = (DeleteFileCommand)command; DeleteFileCommand delete = (DeleteFileCommand)command;
return repositoryDiskInterface.deleteFile2(sess, tree, delete.getRootNode(), delete.getPath()); return repositoryDiskInterface.deleteFile2(sess, tree, delete.getRootNode(), delete.getPath());
} }
else if(command instanceof OpenFileCommand) else if(command instanceof OpenFileCommand)
{ {
logger.debug("open file command"); logger.debug("open file command");
OpenFileCommand o = (OpenFileCommand)command; OpenFileCommand o = (OpenFileCommand)command;
OpenFileMode mode = o.getMode(); OpenFileMode mode = o.getMode();
return repositoryDiskInterface.openFile(sess, tree, o.getRootNodeRef(), o.getPath(), mode, o.isTruncate()); return repositoryDiskInterface.openFile(sess, tree, o.getRootNodeRef(), o.getPath(), mode, o.isTruncate());
} }
else if(command instanceof CloseFileCommand) else if(command instanceof CloseFileCommand)
{ {
logger.debug("close file command"); logger.debug("close file command");
CloseFileCommand c = (CloseFileCommand)command; CloseFileCommand c = (CloseFileCommand)command;
return repositoryDiskInterface.closeFile(tree, c.getRootNodeRef(), c.getPath(), c.getNetworkFile()); return repositoryDiskInterface.closeFile(tree, c.getRootNodeRef(), c.getPath(), c.getNetworkFile());
} }
else if(command instanceof ReduceQuotaCommand) else if(command instanceof ReduceQuotaCommand)
{ {
logger.debug("reduceQuota file command"); logger.debug("reduceQuota file command");
ReduceQuotaCommand r = (ReduceQuotaCommand)command; ReduceQuotaCommand r = (ReduceQuotaCommand)command;
repositoryDiskInterface.reduceQuota(sess, tree, r.getNetworkFile()); repositoryDiskInterface.reduceQuota(sess, tree, r.getNetworkFile());
} }
else if(command instanceof RenameFileCommand) else if(command instanceof RenameFileCommand)
{ {
logger.debug("rename command"); logger.debug("rename command");
RenameFileCommand rename = (RenameFileCommand)command; RenameFileCommand rename = (RenameFileCommand)command;
repositoryDiskInterface.renameFile(rename.getRootNode(), rename.getFromPath(), rename.getToPath(), rename.isSoft(), false); repositoryDiskInterface.renameFile(rename.getRootNode(), rename.getFromPath(), rename.getToPath(), rename.isSoft(), false);
} }
else if(command instanceof MoveFileCommand) else if(command instanceof MoveFileCommand)
{ {
logger.debug("move command"); logger.debug("move command");
MoveFileCommand move = (MoveFileCommand)command; MoveFileCommand move = (MoveFileCommand)command;
repositoryDiskInterface.renameFile(move.getRootNode(), move.getFromPath(), move.getToPath(), false, move.isMoveAsSystem()); repositoryDiskInterface.renameFile(move.getRootNode(), move.getFromPath(), move.getToPath(), false, move.isMoveAsSystem());
} }
else if(command instanceof CopyContentCommand) else if(command instanceof CopyContentCommand)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Copy content command - copy content"); logger.debug("Copy content command - copy content");
} }
CopyContentCommand copy = (CopyContentCommand)command; CopyContentCommand copy = (CopyContentCommand)command;
repositoryDiskInterface.copyContent(copy.getRootNode(), copy.getFromPath(), copy.getToPath()); repositoryDiskInterface.copyContent(copy.getRootNode(), copy.getFromPath(), copy.getToPath());
} }
else if(command instanceof DoNothingCommand) else if(command instanceof DoNothingCommand)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Do Nothing Command - doing nothing"); logger.debug("Do Nothing Command - doing nothing");
} }
} }
else if(command instanceof ResultCallback) else if(command instanceof ResultCallback)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Result Callback"); logger.debug("Result Callback");
} }
ResultCallback callback = (ResultCallback)command; ResultCallback callback = (ResultCallback)command;
callback.execute(result); callback.execute(result);
} }
else if(command instanceof RemoveTempFileCommand) else if(command instanceof RemoveTempFileCommand)
{ {
RemoveTempFileCommand r = (RemoveTempFileCommand)command; RemoveTempFileCommand r = (RemoveTempFileCommand)command;
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Remove Temp File:" + r.getNetworkFile()); logger.debug("Remove Temp File:" + r.getNetworkFile());
} }
File file = r.getNetworkFile().getFile(); File file = r.getNetworkFile().getFile();
boolean isDeleted = file.delete(); boolean isDeleted = file.delete();
if(!isDeleted) if(!isDeleted)
{ {
logger.debug("unable to delete temp file:" + r.getNetworkFile() + ", closed="+ r.getNetworkFile().isClosed()); logger.debug("unable to delete temp file:" + r.getNetworkFile() + ", closed="+ r.getNetworkFile().isClosed());
/* /*
* Unable to delete temporary file * Unable to delete temporary file
* Could be a bug with the file handle not being closed, but yourkit does not * Could be a bug with the file handle not being closed, but yourkit does not
* find anything awry. * find anything awry.
* There are reported Windows JVM bugs such as 4715154 ... * There are reported Windows JVM bugs such as 4715154 ...
*/ */
FileOutputStream fos = new FileOutputStream(file); FileOutputStream fos = new FileOutputStream(file);
FileChannel outChan = null; FileChannel outChan = null;
try try
{ {
outChan = fos.getChannel(); outChan = fos.getChannel();
outChan.truncate(0); outChan.truncate(0);
} }
catch (IOException e) catch (IOException e)
{ {
logger.debug("unable to clean up file", e); logger.debug("unable to clean up file", e);
} }
finally finally
{ {
if(outChan != null) if(outChan != null)
{ {
try try
{ {
outChan.close(); outChan.close();
} }
catch(IOException e){} catch(IOException e){}
} }
fos.close(); fos.close();
} }
} }
} }
else if(command instanceof ReturnValueCommand) else if(command instanceof ReturnValueCommand)
{ {
ReturnValueCommand r = (ReturnValueCommand)command; ReturnValueCommand r = (ReturnValueCommand)command;
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Return value"); logger.debug("Return value");
} }
return r.getReturnValue(); return r.getReturnValue();
} }
else if(command instanceof RemoveNoContentFileOnError) else if(command instanceof RemoveNoContentFileOnError)
{ {
RemoveNoContentFileOnError r = (RemoveNoContentFileOnError)command; RemoveNoContentFileOnError r = (RemoveNoContentFileOnError)command;
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Remove no content file on error"); logger.debug("Remove no content file on error");
} }
repositoryDiskInterface.deleteEmptyFile(r.getRootNodeRef(), r.getPath()); repositoryDiskInterface.deleteEmptyFile(r.getRootNodeRef(), r.getPath());
} }
} }
finally finally
{ {
FileFilterMode.clearClient(); FileFilterMode.clearClient();
} }
return null; return null;
} }
public void setTransactionService(TransactionService transactionService) public void setTransactionService(TransactionService transactionService)
{ {
this.transactionService = transactionService; this.transactionService = transactionService;
} }
public TransactionService getTransactionService() public TransactionService getTransactionService()
{ {
return transactionService; return transactionService;
} }
public void setRepositoryDiskInterface(RepositoryDiskInterface repositoryDiskInterface) public void setRepositoryDiskInterface(RepositoryDiskInterface repositoryDiskInterface)
{ {
this.repositoryDiskInterface = repositoryDiskInterface; this.repositoryDiskInterface = repositoryDiskInterface;
} }
public RepositoryDiskInterface getRepositoryDiskInterface() public RepositoryDiskInterface getRepositoryDiskInterface()
{ {
return repositoryDiskInterface; return repositoryDiskInterface;
} }
public void setDiskInterface(ExtendedDiskInterface diskInterface) public void setDiskInterface(ExtendedDiskInterface diskInterface)
{ {
this.diskInterface = diskInterface; this.diskInterface = diskInterface;
} }
public ExtendedDiskInterface getDiskInterface() public ExtendedDiskInterface getDiskInterface()
{ {
return diskInterface; return diskInterface;
} }
/** /**
* A wrapper for checked exceptions to be passed through the retrying transaction handler. * A wrapper for checked exceptions to be passed through the retrying transaction handler.
*/ */
protected static class PropagatingException extends RuntimeException protected static class PropagatingException extends RuntimeException
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* @param cause Throwable * @param cause Throwable
*/ */
public PropagatingException(Throwable cause) public PropagatingException(Throwable cause)
{ {
super(cause); super(cause);
} }
} }
} }

View File

@@ -1,21 +1,21 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentReader;
public interface ContentComparator public interface ContentComparator
{ {
/** /**
* Are the two content items equal? * Are the two content items equal?
* <p> * <p>
* For most cases a simple binary comparison is sufficient but some mimetypes * For most cases a simple binary comparison is sufficient but some mimetypes
* trivial changes need to be discarded. * trivial changes need to be discarded.
* <p> * <p>
* @param existingContent * @param existingContent
* @param file file * @param file file
* @return true content is equal, false content is different. * @return true content is equal, false content is different.
*/ */
boolean isContentEqual(ContentReader existingContent, File file); boolean isContentEqual(ContentReader existingContent, File file);
} }

View File

@@ -1,76 +1,76 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import java.io.IOException; import java.io.IOException;
import org.alfresco.filesys.config.ServerConfigurationBean; import org.alfresco.filesys.config.ServerConfigurationBean;
import org.alfresco.jlan.server.SrvSession; import org.alfresco.jlan.server.SrvSession;
import org.alfresco.jlan.server.core.DeviceContext; import org.alfresco.jlan.server.core.DeviceContext;
import org.alfresco.jlan.server.core.DeviceContextException; import org.alfresco.jlan.server.core.DeviceContextException;
import org.alfresco.jlan.server.filesys.FileInfo; import org.alfresco.jlan.server.filesys.FileInfo;
import org.alfresco.jlan.server.filesys.FileOpenParams; import org.alfresco.jlan.server.filesys.FileOpenParams;
import org.alfresco.jlan.server.filesys.NetworkFile; import org.alfresco.jlan.server.filesys.NetworkFile;
import org.alfresco.jlan.server.filesys.SearchContext; import org.alfresco.jlan.server.filesys.SearchContext;
import org.alfresco.jlan.server.filesys.TreeConnection; import org.alfresco.jlan.server.filesys.TreeConnection;
/** /**
* Called by the NonTransactionalContentDiskDriver to advise of operations completed * Called by the NonTransactionalContentDiskDriver to advise of operations completed
* by the ContentDiskInterface. * by the ContentDiskInterface.
*/ */
public interface ContentDiskCallback public interface ContentDiskCallback
{ {
public void getFileInformation(SrvSession sess, TreeConnection tree, public void getFileInformation(SrvSession sess, TreeConnection tree,
String path, FileInfo info); String path, FileInfo info);
public void fileExists(SrvSession sess, TreeConnection tree, String path, int fileExists); public void fileExists(SrvSession sess, TreeConnection tree, String path, int fileExists);
public void treeOpened(SrvSession sess, TreeConnection tree); public void treeOpened(SrvSession sess, TreeConnection tree);
public void treeClosed(SrvSession sess, TreeConnection tree); public void treeClosed(SrvSession sess, TreeConnection tree);
public void closeFile(SrvSession sess, TreeConnection tree, public void closeFile(SrvSession sess, TreeConnection tree,
NetworkFile param); NetworkFile param);
public void createDirectory(SrvSession sess, TreeConnection tree, public void createDirectory(SrvSession sess, TreeConnection tree,
FileOpenParams params); FileOpenParams params);
public void createFile(SrvSession sess, TreeConnection tree, public void createFile(SrvSession sess, TreeConnection tree,
FileOpenParams params, NetworkFile newFile); FileOpenParams params, NetworkFile newFile);
public void deleteDirectory(SrvSession sess, TreeConnection tree, String dir); public void deleteDirectory(SrvSession sess, TreeConnection tree, String dir);
public void deleteFile(SrvSession sess, TreeConnection tree, String name); public void deleteFile(SrvSession sess, TreeConnection tree, String name);
public void flushFile(SrvSession sess, TreeConnection tree, NetworkFile file); public void flushFile(SrvSession sess, TreeConnection tree, NetworkFile file);
public void isReadOnly(SrvSession sess, DeviceContext ctx, boolean isReadOnly); public void isReadOnly(SrvSession sess, DeviceContext ctx, boolean isReadOnly);
public void openFile(SrvSession sess, TreeConnection tree, public void openFile(SrvSession sess, TreeConnection tree,
FileOpenParams param, NetworkFile openFile); FileOpenParams param, NetworkFile openFile);
public void readFile(SrvSession sess, TreeConnection tree, NetworkFile file, public void readFile(SrvSession sess, TreeConnection tree, NetworkFile file,
byte[] buf, int bufPos, int siz, long filePos, int readSize); byte[] buf, int bufPos, int siz, long filePos, int readSize);
public void renameFile(SrvSession sess, TreeConnection tree, public void renameFile(SrvSession sess, TreeConnection tree,
String oldPath, String newPath); String oldPath, String newPath);
public void seekFile(SrvSession sess, TreeConnection tree, public void seekFile(SrvSession sess, TreeConnection tree,
NetworkFile file, long pos, int typ) throws IOException; NetworkFile file, long pos, int typ) throws IOException;
public void setFileInformation(SrvSession sess, TreeConnection tree, public void setFileInformation(SrvSession sess, TreeConnection tree,
String name, FileInfo info) throws IOException; String name, FileInfo info) throws IOException;
public void startSearch(SrvSession sess, TreeConnection tree, public void startSearch(SrvSession sess, TreeConnection tree,
String searchPath, int attrib, SearchContext context); String searchPath, int attrib, SearchContext context);
public void truncateFile(SrvSession sess, TreeConnection tree, public void truncateFile(SrvSession sess, TreeConnection tree,
NetworkFile file, long siz); NetworkFile file, long siz);
public void writeFile(SrvSession sess, TreeConnection tree, public void writeFile(SrvSession sess, TreeConnection tree,
NetworkFile file, byte[] buf, int bufoff, int siz, long fileoff, int writeSize); NetworkFile file, byte[] buf, int bufoff, int siz, long fileoff, int writeSize);
public void registerContext(DeviceContext ctx, ServerConfigurationBean serverConfig) public void registerContext(DeviceContext ctx, ServerConfigurationBean serverConfig)
throws DeviceContextException; throws DeviceContextException;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,12 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
/** /**
* *
* @author mrogers * @author mrogers
* *
*/ */
public interface InFlightCorrectable public interface InFlightCorrectable
{ {
public void setInFlightCorrector(InFlightCorrector correctable); public void setInFlightCorrector(InFlightCorrector correctable);
} }

View File

@@ -1,29 +1,29 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import java.util.Date; import java.util.Date;
import org.alfresco.jlan.server.filesys.FileInfo; import org.alfresco.jlan.server.filesys.FileInfo;
import org.alfresco.jlan.server.filesys.TreeConnection; import org.alfresco.jlan.server.filesys.TreeConnection;
import org.alfresco.jlan.server.filesys.cache.FileState; import org.alfresco.jlan.server.filesys.cache.FileState;
import org.alfresco.jlan.server.filesys.cache.FileStateCache; import org.alfresco.jlan.server.filesys.cache.FileStateCache;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* The in flight corrector corrects search results that have not yet been committed to the * The in flight corrector corrects search results that have not yet been committed to the
* repository. * repository.
* *
* It substitutes the "in flight" valuses from the state cache in place of the values committed to * It substitutes the "in flight" valuses from the state cache in place of the values committed to
* the repo * the repo
* *
* @author mrogers * @author mrogers
*/ */
public interface InFlightCorrector public interface InFlightCorrector
{ {
/** /**
* Correct thr results with in flight details. * Correct thr results with in flight details.
* @param info * @param info
* @param folderPath * @param folderPath
*/ */
public void correct(FileInfo info, String folderPath); public void correct(FileInfo info, String folderPath);
} }

View File

@@ -1,92 +1,92 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import java.util.Date; import java.util.Date;
import org.alfresco.jlan.server.filesys.FileInfo; import org.alfresco.jlan.server.filesys.FileInfo;
import org.alfresco.jlan.server.filesys.TreeConnection; import org.alfresco.jlan.server.filesys.TreeConnection;
import org.alfresco.jlan.server.filesys.cache.FileState; import org.alfresco.jlan.server.filesys.cache.FileState;
import org.alfresco.jlan.server.filesys.cache.FileStateCache; import org.alfresco.jlan.server.filesys.cache.FileStateCache;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* The in flight corrector corrects search results that have not yet been committed to the * The in flight corrector corrects search results that have not yet been committed to the
* repository. * repository.
* *
* It substitutes the "in flight" valuses from the state cache in place of the values committed to * It substitutes the "in flight" valuses from the state cache in place of the values committed to
* the repo * the repo
* *
* @author mrogers * @author mrogers
*/ */
public class InFlightCorrectorImpl implements InFlightCorrector public class InFlightCorrectorImpl implements InFlightCorrector
{ {
TreeConnection tree; TreeConnection tree;
private static final Log logger = LogFactory.getLog(InFlightCorrectorImpl.class); private static final Log logger = LogFactory.getLog(InFlightCorrectorImpl.class);
public InFlightCorrectorImpl(TreeConnection tree) public InFlightCorrectorImpl(TreeConnection tree)
{ {
this.tree = tree; this.tree = tree;
} }
public void correct(FileInfo info, String folderPath) public void correct(FileInfo info, String folderPath)
{ {
ContentContext tctx = (ContentContext) tree.getContext(); ContentContext tctx = (ContentContext) tree.getContext();
String path = folderPath + info.getFileName(); String path = folderPath + info.getFileName();
if(tctx.hasStateCache()) if(tctx.hasStateCache())
{ {
FileStateCache cache = tctx.getStateCache(); FileStateCache cache = tctx.getStateCache();
FileState fstate = cache.findFileState( path, true); FileState fstate = cache.findFileState( path, true);
if(fstate != null) if(fstate != null)
{ {
logger.debug("correct " + path); logger.debug("correct " + path);
/* /*
* What about stale file state values here? * What about stale file state values here?
*/ */
if(fstate.hasFileSize()) if(fstate.hasFileSize())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("replace file size " + info.getSize() + " with " + fstate.getFileSize()); logger.debug("replace file size " + info.getSize() + " with " + fstate.getFileSize());
} }
info.setFileSize(fstate.getFileSize()); info.setFileSize(fstate.getFileSize());
} }
if ( fstate.hasAccessDateTime()) if ( fstate.hasAccessDateTime())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("replace access date " + new Date(info.getAccessDateTime()) + " with " + new Date(fstate.getAccessDateTime())); logger.debug("replace access date " + new Date(info.getAccessDateTime()) + " with " + new Date(fstate.getAccessDateTime()));
} }
info.setAccessDateTime(fstate.getAccessDateTime()); info.setAccessDateTime(fstate.getAccessDateTime());
} }
if ( fstate.hasChangeDateTime()) if ( fstate.hasChangeDateTime())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("replace change date " + new Date(info.getChangeDateTime()) + " with " + new Date(fstate.getChangeDateTime())); logger.debug("replace change date " + new Date(info.getChangeDateTime()) + " with " + new Date(fstate.getChangeDateTime()));
} }
info.setChangeDateTime(fstate.getChangeDateTime()); info.setChangeDateTime(fstate.getChangeDateTime());
} }
if ( fstate.hasModifyDateTime()) if ( fstate.hasModifyDateTime())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("replace modified date " + new Date(info.getModifyDateTime()) + " with " + new Date(fstate.getModifyDateTime())); logger.debug("replace modified date " + new Date(info.getModifyDateTime()) + " with " + new Date(fstate.getModifyDateTime()));
} }
info.setModifyDateTime(fstate.getModifyDateTime()); info.setModifyDateTime(fstate.getModifyDateTime());
} }
if ( fstate.hasAllocationSize()) if ( fstate.hasAllocationSize())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("replace allocation size" + info.getAllocationSize() + " with " + fstate.getAllocationSize()); logger.debug("replace allocation size" + info.getAllocationSize() + " with " + fstate.getAllocationSize());
} }
info.setAllocationSize(fstate.getAllocationSize()); info.setAllocationSize(fstate.getAllocationSize());
} }
} }
} }
} }
} }

View File

@@ -1,32 +1,32 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* The lock keeper tracks multiple locks on files open via the file system protocols. * The lock keeper tracks multiple locks on files open via the file system protocols.
* *
* There can be multiple locks on the same file, the lock keeper keeps track of the individual locks and delegates to the LockService * There can be multiple locks on the same file, the lock keeper keeps track of the individual locks and delegates to the LockService
* *
* @author mrogers * @author mrogers
*/ */
public interface LockKeeper public interface LockKeeper
{ {
/** /**
* Transactional method to make a lock on the specified node ref. * Transactional method to make a lock on the specified node ref.
* *
* @param nodeRef * @param nodeRef
*/ */
public void addLock(NodeRef nodeRef); public void addLock(NodeRef nodeRef);
/** /**
* Transactional method to remove a lock on the specified node ref. * Transactional method to remove a lock on the specified node ref.
* @param nodeRef * @param nodeRef
*/ */
public void removeLock(NodeRef nodeRef); public void removeLock(NodeRef nodeRef);
/** /**
* *
*/ */
public void refreshAllLocks(); public void refreshAllLocks();
} }

View File

@@ -1,225 +1,225 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import org.alfresco.repo.cache.TransactionalCache; import org.alfresco.repo.cache.TransactionalCache;
import org.alfresco.repo.lock.mem.Lifetime; import org.alfresco.repo.lock.mem.Lifetime;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.lock.LockService; import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockStatus; import org.alfresco.service.cmr.lock.LockStatus;
import org.alfresco.service.cmr.lock.LockType; import org.alfresco.service.cmr.lock.LockType;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.PropertyCheck; import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* AlfrescoLockKeeperImpl * AlfrescoLockKeeperImpl
* <p> * <p>
* Repository level locking for CIFS, prevents files open via CIFS/FTP/JLAN being interfered with by the alfresco "back end". * Repository level locking for CIFS, prevents files open via CIFS/FTP/JLAN being interfered with by the alfresco "back end".
* *
* Delegates ephemeral locking requests to the lockService. * Delegates ephemeral locking requests to the lockService.
* *
* @author mrogers * @author mrogers
* *
*/ */
public class LockKeeperImpl implements LockKeeper public class LockKeeperImpl implements LockKeeper
{ {
private String LOCK_KEEPER_KEY = "AlfrescoLockKeeperImpl"; private String LOCK_KEEPER_KEY = "AlfrescoLockKeeperImpl";
private LockService lockService; private LockService lockService;
private TransactionService transactionService; private TransactionService transactionService;
private TransactionalCache<NodeRef, KeeperInfo> lockKeeperTransactionalCache; private TransactionalCache<NodeRef, KeeperInfo> lockKeeperTransactionalCache;
private int timeToExpire = 3600 * 2; // 2 Hours private int timeToExpire = 3600 * 2; // 2 Hours
private boolean lockEnabled = true; private boolean lockEnabled = true;
private static final Log logger = LogFactory.getLog(LockKeeperImpl.class); private static final Log logger = LogFactory.getLog(LockKeeperImpl.class);
public void init() public void init()
{ {
PropertyCheck.mandatory(this, "lockService", getLockService()); PropertyCheck.mandatory(this, "lockService", getLockService());
PropertyCheck.mandatory(this, "lockKeeperTransactionalCache", getLockKeeperTransactionalCache()); PropertyCheck.mandatory(this, "lockKeeperTransactionalCache", getLockKeeperTransactionalCache());
PropertyCheck.mandatory(this, "transactionService", getTransactionService()); PropertyCheck.mandatory(this, "transactionService", getTransactionService());
} }
@Override @Override
public void addLock(NodeRef nodeRef) public void addLock(NodeRef nodeRef)
{ {
if(lockEnabled) if(lockEnabled)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("lock nodeRef:" + nodeRef); logger.debug("lock nodeRef:" + nodeRef);
} }
getLockService().lock(nodeRef, LockType.WRITE_LOCK, getTimeToExpire(), Lifetime.EPHEMERAL, LOCK_KEEPER_KEY); getLockService().lock(nodeRef, LockType.WRITE_LOCK, getTimeToExpire(), Lifetime.EPHEMERAL, LOCK_KEEPER_KEY);
lockKeeperTransactionalCache.put(nodeRef, new KeeperInfo(AuthenticationUtil.getFullyAuthenticatedUser())); lockKeeperTransactionalCache.put(nodeRef, new KeeperInfo(AuthenticationUtil.getFullyAuthenticatedUser()));
} }
} }
@Override @Override
public void removeLock(NodeRef nodeRef) public void removeLock(NodeRef nodeRef)
{ {
if(lockEnabled) if(lockEnabled)
{ {
logger.trace("removeLock nodeRef:" + nodeRef); logger.trace("removeLock nodeRef:" + nodeRef);
getLockService().unlock(nodeRef); getLockService().unlock(nodeRef);
lockKeeperTransactionalCache.remove(nodeRef); lockKeeperTransactionalCache.remove(nodeRef);
} }
} }
@Override @Override
public void refreshAllLocks() public void refreshAllLocks()
{ {
Collection<NodeRef> nodes = lockKeeperTransactionalCache.getKeys(); Collection<NodeRef> nodes = lockKeeperTransactionalCache.getKeys();
if(logger.isTraceEnabled()) if(logger.isTraceEnabled())
{ {
logger.trace("RefreshAllLocks called for #locks, " + nodes.size()); logger.trace("RefreshAllLocks called for #locks, " + nodes.size());
} }
if(!transactionService.getAllowWrite()) if(!transactionService.getAllowWrite())
{ {
if(logger.isTraceEnabled()) if(logger.isTraceEnabled())
{ {
logger.trace("Repo is read only - do nothing"); logger.trace("Repo is read only - do nothing");
return; return;
} }
} }
for(NodeRef nodeRef : nodes) for(NodeRef nodeRef : nodes)
{ {
final NodeRef nodeRefToRefresh = nodeRef; final NodeRef nodeRefToRefresh = nodeRef;
final KeeperInfo keeperInfo = lockKeeperTransactionalCache.get(nodeRefToRefresh); final KeeperInfo keeperInfo = lockKeeperTransactionalCache.get(nodeRefToRefresh);
final String additionalInfo = lockService.getAdditionalInfo(nodeRefToRefresh); final String additionalInfo = lockService.getAdditionalInfo(nodeRefToRefresh);
transactionService.getRetryingTransactionHelper().doInTransaction( transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<Void>() new RetryingTransactionCallback<Void>()
{ {
@Override @Override
public Void execute() throws Throwable public Void execute() throws Throwable
{ {
if(LOCK_KEEPER_KEY.equalsIgnoreCase(additionalInfo)) if(LOCK_KEEPER_KEY.equalsIgnoreCase(additionalInfo))
{ {
// Its one of this class's locks // Its one of this class's locks
AuthenticationUtil.setFullyAuthenticatedUser(keeperInfo.getOwner()); AuthenticationUtil.setFullyAuthenticatedUser(keeperInfo.getOwner());
//TODO What about node does not exist? //TODO What about node does not exist?
switch (lockService.getLockStatus(nodeRefToRefresh)) switch (lockService.getLockStatus(nodeRefToRefresh))
{ {
case LOCK_OWNER: case LOCK_OWNER:
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("refresh ephemeral lock nodeRef: " + nodeRefToRefresh); logger.debug("refresh ephemeral lock nodeRef: " + nodeRefToRefresh);
} }
// Expect to go here - refresh the lock // Expect to go here - refresh the lock
getLockService().lock(nodeRefToRefresh, LockType.WRITE_LOCK, getTimeToExpire(), Lifetime.EPHEMERAL, LOCK_KEEPER_KEY); getLockService().lock(nodeRefToRefresh, LockType.WRITE_LOCK, getTimeToExpire(), Lifetime.EPHEMERAL, LOCK_KEEPER_KEY);
break; break;
case LOCKED: case LOCKED:
// Locked by somebody else? Something has gone wrong here // Locked by somebody else? Something has gone wrong here
case LOCK_EXPIRED: case LOCK_EXPIRED:
default: default:
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("remove lock from lock keeper cache, nodeRef: " + nodeRefToRefresh); logger.debug("remove lock from lock keeper cache, nodeRef: " + nodeRefToRefresh);
} }
lockKeeperTransactionalCache.remove(nodeRefToRefresh); lockKeeperTransactionalCache.remove(nodeRefToRefresh);
} }
} }
else else
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("not a lock keeper lock, remove lock from lock keeper cache, nodeRef: " + nodeRefToRefresh); logger.debug("not a lock keeper lock, remove lock from lock keeper cache, nodeRef: " + nodeRefToRefresh);
} }
lockKeeperTransactionalCache.remove(nodeRefToRefresh); lockKeeperTransactionalCache.remove(nodeRefToRefresh);
} }
return null; return null;
} }
}, false, true); }, false, true);
} }
} }
public void setLockEnabled(boolean lockEnabled) { public void setLockEnabled(boolean lockEnabled) {
this.lockEnabled = lockEnabled; this.lockEnabled = lockEnabled;
} }
public boolean isLockEnabled() { public boolean isLockEnabled() {
return lockEnabled; return lockEnabled;
} }
public void setLockService(LockService lockService) { public void setLockService(LockService lockService) {
this.lockService = lockService; this.lockService = lockService;
} }
public LockService getLockService() { public LockService getLockService() {
return lockService; return lockService;
} }
public void setLockKeeperTransactionalCache( public void setLockKeeperTransactionalCache(
TransactionalCache<NodeRef, KeeperInfo> lockKeeperTransactionalCache) TransactionalCache<NodeRef, KeeperInfo> lockKeeperTransactionalCache)
{ {
this.lockKeeperTransactionalCache = lockKeeperTransactionalCache; this.lockKeeperTransactionalCache = lockKeeperTransactionalCache;
} }
public TransactionalCache<NodeRef, KeeperInfo> getLockKeeperTransactionalCache() public TransactionalCache<NodeRef, KeeperInfo> getLockKeeperTransactionalCache()
{ {
return lockKeeperTransactionalCache; return lockKeeperTransactionalCache;
} }
public void setTransactionService(TransactionService transactionHelper) public void setTransactionService(TransactionService transactionHelper)
{ {
this.transactionService = transactionHelper; this.transactionService = transactionHelper;
} }
public TransactionService getTransactionService() public TransactionService getTransactionService()
{ {
return transactionService; return transactionService;
} }
public void setTimeToExpire(int timeToExpire) { public void setTimeToExpire(int timeToExpire) {
this.timeToExpire = timeToExpire; this.timeToExpire = timeToExpire;
} }
public int getTimeToExpire() { public int getTimeToExpire() {
return timeToExpire; return timeToExpire;
} }
private class KeeperInfo implements Serializable private class KeeperInfo implements Serializable
{ {
/** /**
* *
*/ */
private static final long serialVersionUID = -4200553975218699638L; private static final long serialVersionUID = -4200553975218699638L;
/** /**
* *
*/ */
KeeperInfo(String owner) KeeperInfo(String owner)
{ {
this.setOwner(owner); this.setOwner(owner);
lockTime = new Date(); lockTime = new Date();
} }
public void setOwner(String owner) { public void setOwner(String owner) {
this.owner = owner; this.owner = owner;
} }
public String getOwner() { public String getOwner() {
return owner; return owner;
} }
private String owner; private String owner;
Date lockTime; Date lockTime;
} }
} }

View File

@@ -1,43 +1,43 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.quartz.Job; import org.quartz.Job;
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException; import org.quartz.JobExecutionException;
public class LockKeeperRefreshJob implements Job public class LockKeeperRefreshJob implements Job
{ {
private static final Log log = LogFactory.getLog(LockKeeperRefreshJob.class); private static final Log log = LogFactory.getLog(LockKeeperRefreshJob.class);
@Override public void execute(JobExecutionContext context) throws JobExecutionException @Override public void execute(JobExecutionContext context) throws JobExecutionException
{ {
if (log.isTraceEnabled()) if (log.isTraceEnabled())
{ {
log.trace("Starting Lock Keeper Refresh Job"); log.trace("Starting Lock Keeper Refresh Job");
} }
final LockKeeper lockKeeper = getRequiredQuartzJobParameter(context, "alfrescoLockKeeper", LockKeeper.class); final LockKeeper lockKeeper = getRequiredQuartzJobParameter(context, "alfrescoLockKeeper", LockKeeper.class);
lockKeeper.refreshAllLocks(); lockKeeper.refreshAllLocks();
} }
private <T> T getRequiredQuartzJobParameter(JobExecutionContext context, String dataKey, Class<T> requiredClass) throws JobExecutionException private <T> T getRequiredQuartzJobParameter(JobExecutionContext context, String dataKey, Class<T> requiredClass) throws JobExecutionException
{ {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final T result = (T) context.getJobDetail().getJobDataMap().get(dataKey); final T result = (T) context.getJobDetail().getJobDataMap().get(dataKey);
if (result == null) if (result == null)
{ {
if (log.isErrorEnabled()) if (log.isErrorEnabled())
{ {
log.error("PULL: Did not retrieve required service for quartz job: " + dataKey); log.error("PULL: Did not retrieve required service for quartz job: " + dataKey);
} }
throw new JobExecutionException("Missing job data: " + dataKey); throw new JobExecutionException("Missing job data: " + dataKey);
} }
return result; return result;
} }
} }

View File

@@ -1,10 +1,10 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
public enum OpenFileMode public enum OpenFileMode
{ {
READ_ONLY, READ_ONLY,
WRITE_ONLY, WRITE_ONLY,
READ_WRITE, READ_WRITE,
DELETE, DELETE,
ATTRIBUTES_ONLY ATTRIBUTES_ONLY
} }

View File

@@ -1,13 +1,13 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
public interface ResultCallback extends Command public interface ResultCallback extends Command
{ {
/** /**
* Call the callback with the result of the operation. * Call the callback with the result of the operation.
* @param result the result. * @param result the result.
*/ */
void execute(Object result); void execute(Object result);
} }

View File

@@ -1,212 +1,212 @@
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import org.alfresco.filesys.alfresco.NetworkFileLegacyReferenceCount; import org.alfresco.filesys.alfresco.NetworkFileLegacyReferenceCount;
import org.alfresco.jlan.server.filesys.FileAttribute; import org.alfresco.jlan.server.filesys.FileAttribute;
import org.alfresco.jlan.server.filesys.cache.FileState; import org.alfresco.jlan.server.filesys.cache.FileState;
import org.alfresco.jlan.server.filesys.cache.NetworkFileStateInterface; import org.alfresco.jlan.server.filesys.cache.NetworkFileStateInterface;
import org.alfresco.jlan.smb.server.disk.JavaNetworkFile; import org.alfresco.jlan.smb.server.disk.JavaNetworkFile;
/** /**
* Temporary Java backed network file. * Temporary Java backed network file.
* *
* @author mrogers * @author mrogers
*/ */
public class TempNetworkFile extends JavaNetworkFile public class TempNetworkFile extends JavaNetworkFile
implements NetworkFileStateInterface, implements NetworkFileStateInterface,
NetworkFileLegacyReferenceCount NetworkFileLegacyReferenceCount
{ {
private boolean changed = false; private boolean changed = false;
boolean modificationDateSetDirectly = false; boolean modificationDateSetDirectly = false;
/** /**
* Create a new temporary file with no existing content. * Create a new temporary file with no existing content.
* *
* @param file the underlying File * @param file the underlying File
* @param netPath where in the repo this file is going. * @param netPath where in the repo this file is going.
*/ */
public TempNetworkFile(File file, String netPath) public TempNetworkFile(File file, String netPath)
{ {
super(file, netPath); super(file, netPath);
setFullName(netPath); setFullName(netPath);
setAttributes(FileAttribute.NTNormal); setAttributes(FileAttribute.NTNormal);
setClosed(false); setClosed(false);
} }
/** /**
* A new temporary network file with some existing content. * A new temporary network file with some existing content.
* @param file File * @param file File
* @param netPath String * @param netPath String
* @param existingContent Reader * @param existingContent Reader
*/ */
public TempNetworkFile(File file, String netPath, Reader existingContent) public TempNetworkFile(File file, String netPath, Reader existingContent)
{ {
super(file, netPath); super(file, netPath);
setFullName(netPath); setFullName(netPath);
setAttributes(FileAttribute.NTNormal); setAttributes(FileAttribute.NTNormal);
setClosed(false); setClosed(false);
} }
/** /**
* Access to the underlying file. * Access to the underlying file.
* @return the file. * @return the file.
*/ */
public File getFile() public File getFile()
{ {
return m_file; return m_file;
} }
public String toString() public String toString()
{ {
return "TempNetworkFile:" + getFullName() + " path: " + m_file.getAbsolutePath(); return "TempNetworkFile:" + getFullName() + " path: " + m_file.getAbsolutePath();
} }
@Override @Override
public int readFile(byte[] buf, int len, int pos, long fileOff) public int readFile(byte[] buf, int len, int pos, long fileOff)
throws java.io.IOException throws java.io.IOException
{ {
if(fileState != null) if(fileState != null)
{ {
fileState.updateAccessDateTime(); fileState.updateAccessDateTime();
} }
return super.readFile(buf, len, pos, fileOff); return super.readFile(buf, len, pos, fileOff);
} }
@Override @Override
public void writeFile(byte[] buf, int len, int pos) throws IOException public void writeFile(byte[] buf, int len, int pos) throws IOException
{ {
changed = true; changed = true;
super.writeFile(buf, len, pos); super.writeFile(buf, len, pos);
long size = m_io.length(); long size = m_io.length();
setFileSize(size); setFileSize(size);
if(fileState != null) if(fileState != null)
{ {
fileState.updateModifyDateTime(); fileState.updateModifyDateTime();
fileState.updateAccessDateTime(); fileState.updateAccessDateTime();
fileState.setFileSize(size); fileState.setFileSize(size);
fileState.setAllocationSize((size + 512L) & 0xFFFFFFFFFFFFFE00L); fileState.setAllocationSize((size + 512L) & 0xFFFFFFFFFFFFFE00L);
} }
} }
@Override @Override
public void writeFile(byte[] buffer, int length, int position, long fileOffset) public void writeFile(byte[] buffer, int length, int position, long fileOffset)
throws IOException throws IOException
{ {
changed = true; changed = true;
super.writeFile(buffer, length, position, fileOffset); super.writeFile(buffer, length, position, fileOffset);
long size = m_io.length(); long size = m_io.length();
setFileSize(size); setFileSize(size);
if(fileState != null) if(fileState != null)
{ {
fileState.updateModifyDateTime(); fileState.updateModifyDateTime();
fileState.updateAccessDateTime(); fileState.updateAccessDateTime();
fileState.setFileSize(size); fileState.setFileSize(size);
fileState.setAllocationSize((size + 512L) & 0xFFFFFFFFFFFFFE00L); fileState.setAllocationSize((size + 512L) & 0xFFFFFFFFFFFFFE00L);
} }
} }
@Override @Override
public void truncateFile(long size) throws IOException public void truncateFile(long size) throws IOException
{ {
super.truncateFile(size); super.truncateFile(size);
if(size == 0) if(size == 0)
{ {
changed = true; changed = true;
} }
setFileSize(size); setFileSize(size);
if(fileState != null) if(fileState != null)
{ {
fileState.updateModifyDateTime(); fileState.updateModifyDateTime();
fileState.updateAccessDateTime(); fileState.updateAccessDateTime();
fileState.setFileSize(size); fileState.setFileSize(size);
fileState.setAllocationSize((size + 512L) & 0xFFFFFFFFFFFFFE00L); fileState.setAllocationSize((size + 512L) & 0xFFFFFFFFFFFFFE00L);
} }
} }
// For JLAN file state lock manager // For JLAN file state lock manager
public void setFileState(FileState fileState) public void setFileState(FileState fileState)
{ {
this.fileState = fileState; this.fileState = fileState;
} }
@Override @Override
public FileState getFileState() public FileState getFileState()
{ {
return fileState; return fileState;
} }
/** /**
* Tell JLAN it needs to call disk.closeFile rather than short cutting. * Tell JLAN it needs to call disk.closeFile rather than short cutting.
* @return boolean * @return boolean
*/ */
public boolean allowsOpenCloseViaNetworkFile() { public boolean allowsOpenCloseViaNetworkFile() {
return false; return false;
} }
public void setChanged(boolean changed) public void setChanged(boolean changed)
{ {
this.changed = changed; this.changed = changed;
} }
public boolean isChanged() public boolean isChanged()
{ {
return changed; return changed;
} }
public boolean isModificationDateSetDirectly() public boolean isModificationDateSetDirectly()
{ {
return modificationDateSetDirectly; return modificationDateSetDirectly;
} }
public void setModificationDateSetDirectly(boolean modificationDateSetDirectly) public void setModificationDateSetDirectly(boolean modificationDateSetDirectly)
{ {
this.modificationDateSetDirectly = modificationDateSetDirectly; this.modificationDateSetDirectly = modificationDateSetDirectly;
} }
private int legacyOpenCount = 0; private int legacyOpenCount = 0;
/** /**
* Increment the legacy file open count * Increment the legacy file open count
* *
* @return int * @return int
*/ */
public synchronized final int incrementLegacyOpenCount() { public synchronized final int incrementLegacyOpenCount() {
legacyOpenCount++; legacyOpenCount++;
return legacyOpenCount; return legacyOpenCount;
} }
/** /**
* Decrement the legacy file open count * Decrement the legacy file open count
* *
* @return int * @return int
*/ */
public synchronized final int decrementLagacyOpenCount() { public synchronized final int decrementLagacyOpenCount() {
legacyOpenCount--; legacyOpenCount--;
return legacyOpenCount; return legacyOpenCount;
} }
/** /**
* Return the legacy open file count * Return the legacy open file count
* *
* @return int * @return int
*/ */
public final int getLegacyOpenCount() { public final int getLegacyOpenCount() {
return legacyOpenCount; return legacyOpenCount;
} }
private FileState fileState; private FileState fileState;
} }

View File

@@ -1,6 +1,6 @@
/** /**
* Implementation of desk top actions for file system protocols. * Implementation of desk top actions for file system protocols.
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys.repo.desk; package org.alfresco.filesys.repo.desk;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,21 +1,21 @@
/** /**
* The Alfesco filesystem to repository translation layer * The Alfesco filesystem to repository translation layer
* *
* <p> * <p>
* Alfresco ContentDiskDriver and supporting classes. * Alfresco ContentDiskDriver and supporting classes.
* *
* <p> * <p>
* NodeEventQueue containing NodeEvents such as when a node * NodeEventQueue containing NodeEvents such as when a node
* is created or deleted. * is created or deleted.
* *
* <p> * <p>
* NodeMonitor which is bound to various node policies and updates * NodeMonitor which is bound to various node policies and updates
* the file state cache. * the file state cache.
* *
* <p> * <p>
* Quota Management which contains a UserQuota for each active user. * Quota Management which contains a UserQuota for each active user.
* *
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys.repo; package org.alfresco.filesys.repo;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,18 +1,18 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
/** /**
* A Command is something that must be done. Commands are higher level * A Command is something that must be done. Commands are higher level
* than Operations. So a rule returns a command or set of commands to * than Operations. So a rule returns a command or set of commands to
* implement an operation. * implement an operation.
*/ */
public interface Command public interface Command
{ {
/** /**
* Is a transaction required to run this command? * Is a transaction required to run this command?
*/ */
TxnReadState getTransactionRequired(); TxnReadState getTransactionRequired();
} }

View File

@@ -1,21 +1,21 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.List; import java.util.List;
/** /**
* A dependent instance takes account of some other instance. * A dependent instance takes account of some other instance.
*/ */
public interface DependentInstance public interface DependentInstance
{ {
/** /**
* Notifies the scenario that there are conflicting loosing scenarios. * Notifies the scenario that there are conflicting loosing scenarios.
* <p> * <p>
* The winning scenario may modify its behavior to take account of the loosers. * The winning scenario may modify its behavior to take account of the loosers.
* <p> * <p>
* @param results * @param results
* @param command * @param command
* @return the new command * @return the new command
*/ */
Command win(List<ScenarioResult> results, Command command); Command win(List<ScenarioResult> results, Command command);
} }

View File

@@ -1,30 +1,30 @@
/** /**
* package org.alfresco.filesys.repo.rules; * package org.alfresco.filesys.repo.rules;
* @author mrogers * @author mrogers
* *
*/ */
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
* EvaluatorContext * EvaluatorContext
*/ */
public interface EvaluatorContext public interface EvaluatorContext
{ {
/** /**
* Get the current scenario instances for this context * Get the current scenario instances for this context
* @return a list of the curent scenario instances * @return a list of the curent scenario instances
*/ */
public List<ScenarioInstance> getScenarioInstances(); public List<ScenarioInstance> getScenarioInstances();
/** /**
* Get the session state for this context. * Get the session state for this context.
* @return the session state for this context. * @return the session state for this context.
*/ */
public Map<String, Object> getSessionState(); public Map<String, Object> getSessionState();
} }

View File

@@ -1,10 +1,10 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
/** /**
* An operation is a primitive thing that needs to be executed. * An operation is a primitive thing that needs to be executed.
* Such as a create, rename or delete. * Such as a create, rename or delete.
*/ */
public interface Operation public interface Operation
{ {
} }

View File

@@ -1,11 +1,11 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
/** /**
* An operation executor is an implementation of how to execute an * An operation executor is an implementation of how to execute an
* operation. i.e. It is the thing that does stuff to the repo. * operation. i.e. It is the thing that does stuff to the repo.
*/ */
public interface OperationExecutor public interface OperationExecutor
{ {
public void execute(Operation operation); public void execute(Operation operation);
} }

View File

@@ -1,34 +1,34 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.Map; import java.util.Map;
/** /**
* The Rule Evaluator evaluates the operation and returns * The Rule Evaluator evaluates the operation and returns
* details of the commands to implement those operations. * details of the commands to implement those operations.
* <p> * <p>
* It is configured with a list of scenarios. * It is configured with a list of scenarios.
*/ */
public interface RuleEvaluator public interface RuleEvaluator
{ {
/** /**
* Create a new evaluator context. Typically for a particular folder. * Create a new evaluator context. Typically for a particular folder.
* An evaluator context groups operations together. * An evaluator context groups operations together.
* @return the new context. * @return the new context.
*/ */
public EvaluatorContext createContext(Map<String, Object>sessionContext); public EvaluatorContext createContext(Map<String, Object>sessionContext);
/** /**
* Evaluate the scenarios contained within the context against the current operation * Evaluate the scenarios contained within the context against the current operation
* @param context - the context to evaluate the operation * @param context - the context to evaluate the operation
* @param operation - the operation to be evaluated. * @param operation - the operation to be evaluated.
* @return Command the command to fulfil the operation * @return Command the command to fulfil the operation
*/ */
public Command evaluate(EvaluatorContext context, Operation operation); public Command evaluate(EvaluatorContext context, Operation operation);
/** /**
* Tell the context of a rename * Tell the context of a rename
*/ */
public void notifyRename(EvaluatorContext context, Operation operation, Command c); public void notifyRename(EvaluatorContext context, Operation operation, Command c);
} }

View File

@@ -1,216 +1,216 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
import org.alfresco.filesys.repo.rules.commands.CompoundCommand; import org.alfresco.filesys.repo.rules.commands.CompoundCommand;
import org.alfresco.util.PropertyCheck; import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* The Rule Evaluator evaluates the operation and returns * The Rule Evaluator evaluates the operation and returns
* details of the commands to implement those operations. * details of the commands to implement those operations.
* <p> * <p>
* It is configured with a list of scenarios which act as factories for scenario instances. * It is configured with a list of scenarios which act as factories for scenario instances.
*/ */
public class RuleEvaluatorImpl implements RuleEvaluator public class RuleEvaluatorImpl implements RuleEvaluator
{ {
private static Log logger = LogFactory.getLog(RuleEvaluatorImpl.class); private static Log logger = LogFactory.getLog(RuleEvaluatorImpl.class);
/** /**
* The evaluator context, one for each folder * The evaluator context, one for each folder
*/ */
private class EvaluatorContextImpl implements EvaluatorContext private class EvaluatorContextImpl implements EvaluatorContext
{ {
Map<String, Object>sessionState; Map<String, Object>sessionState;
EvaluatorContextImpl (Map<String, Object>sessionState) EvaluatorContextImpl (Map<String, Object>sessionState)
{ {
this.sessionState = sessionState; this.sessionState = sessionState;
} }
/** /**
* Current instances of scenarios * Current instances of scenarios
*/ */
private List<ScenarioInstance> currentScenarioInstances = new ArrayList<ScenarioInstance>(); private List<ScenarioInstance> currentScenarioInstances = new ArrayList<ScenarioInstance>();
@Override @Override
public List<ScenarioInstance> getScenarioInstances() public List<ScenarioInstance> getScenarioInstances()
{ {
return currentScenarioInstances; return currentScenarioInstances;
} }
@Override @Override
public Map<String, Object> getSessionState() public Map<String, Object> getSessionState()
{ {
return sessionState; return sessionState;
} }
} }
public void init() public void init()
{ {
PropertyCheck.mandatory(this, "scenarios", scenarios); PropertyCheck.mandatory(this, "scenarios", scenarios);
} }
/** /**
* The scenarios contained within this RuleEvaluator * The scenarios contained within this RuleEvaluator
*/ */
private List<Scenario> scenarios; private List<Scenario> scenarios;
/** /**
* Evaluate the scenarios against the current operation * Evaluate the scenarios against the current operation
* @param operation the operation to be evaluated * @param operation the operation to be evaluated
* @return the command to execute that operation * @return the command to execute that operation
*/ */
public Command evaluate(EvaluatorContext context, Operation operation) public Command evaluate(EvaluatorContext context, Operation operation)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("evaluate:" + operation); logger.debug("evaluate:" + operation);
} }
/** /**
* For each scenario, do we need to create a new scenario * For each scenario, do we need to create a new scenario
* instance for the specified operation ? * instance for the specified operation ?
*/ */
List<ScenarioResult> results = new ArrayList<ScenarioResult>(5); List<ScenarioResult> results = new ArrayList<ScenarioResult>(5);
// currentScenarioInstances needs to be protected for concurrency. // currentScenarioInstances needs to be protected for concurrency.
synchronized (context.getScenarioInstances()) synchronized (context.getScenarioInstances())
{ {
for(Scenario scenario : scenarios) for(Scenario scenario : scenarios)
{ {
ScenarioInstance instance = scenario.createInstance(context, operation); ScenarioInstance instance = scenario.createInstance(context, operation);
if(instance != null) if(instance != null)
{ {
context.getScenarioInstances().add(instance); context.getScenarioInstances().add(instance);
} }
} }
/** /**
* For each active scenario. * For each active scenario.
*/ */
Iterator<ScenarioInstance> i = context.getScenarioInstances().iterator(); Iterator<ScenarioInstance> i = context.getScenarioInstances().iterator();
while(i.hasNext()) while(i.hasNext())
{ {
ScenarioInstance scenario = i.next(); ScenarioInstance scenario = i.next();
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("evaluating:" + scenario + " operation: " +operation ); logger.debug("evaluating:" + scenario + " operation: " +operation );
} }
Command executor = scenario.evaluate(operation); Command executor = scenario.evaluate(operation);
if(executor != null) if(executor != null)
{ {
results.add(new ScenarioResult(scenario, executor)); results.add(new ScenarioResult(scenario, executor));
} }
if(scenario.isComplete()) if(scenario.isComplete())
{ {
// That scenario is no longer active. // That scenario is no longer active.
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Scenario is complete:" + scenario); logger.debug("Scenario is complete:" + scenario);
} }
i.remove(); i.remove();
} }
} }
} // End of syncronized block } // End of syncronized block
// results contains the results of the evaluator // results contains the results of the evaluator
Map<Ranking, ScenarioResult> executors = new HashMap<Ranking, ScenarioResult>(); Map<Ranking, ScenarioResult> executors = new HashMap<Ranking, ScenarioResult>();
// HOW to arbitrate between many scenario executors // HOW to arbitrate between many scenario executors
// Idea : Scenarios have rankings. // Idea : Scenarios have rankings.
for(ScenarioResult result : results) for(ScenarioResult result : results)
{ {
executors.put(result.scenario.getRanking(), result); executors.put(result.scenario.getRanking(), result);
} }
ScenarioResult ex = executors.get(Ranking.HIGH); ScenarioResult ex = executors.get(Ranking.HIGH);
if (ex != null) if (ex != null)
{ {
if(ex.scenario instanceof DependentInstance) if(ex.scenario instanceof DependentInstance)
{ {
DependentInstance di = (DependentInstance)ex.scenario; DependentInstance di = (DependentInstance)ex.scenario;
for(ScenarioResult looser : results) for(ScenarioResult looser : results)
{ {
if(ex != looser) if(ex != looser)
{ {
Command c = di.win(results, ex.command); Command c = di.win(results, ex.command);
logger.debug("returning merged high priority executor"); logger.debug("returning merged high priority executor");
return c; return c;
} }
} }
} }
logger.debug("returning high priority executor"); logger.debug("returning high priority executor");
return ex.command; return ex.command;
} }
ex = executors.get(Ranking.MEDIUM); ex = executors.get(Ranking.MEDIUM);
if (ex != null) if (ex != null)
{ {
logger.debug("returning medium priority executor"); logger.debug("returning medium priority executor");
return ex.command; return ex.command;
} }
ex = executors.get(Ranking.LOW); ex = executors.get(Ranking.LOW);
if (ex != null) if (ex != null)
{ {
logger.debug("returning low priority executor"); logger.debug("returning low priority executor");
return ex.command; return ex.command;
} }
return null; return null;
} }
public void setScenarios(List<Scenario> scenarios) public void setScenarios(List<Scenario> scenarios)
{ {
this.scenarios = scenarios; this.scenarios = scenarios;
} }
public List<Scenario> getScenarios() public List<Scenario> getScenarios()
{ {
return scenarios; return scenarios;
} }
@Override @Override
public EvaluatorContext createContext(Map<String, Object>sessionState) public EvaluatorContext createContext(Map<String, Object>sessionState)
{ {
EvaluatorContextImpl impl = new EvaluatorContextImpl(sessionState); EvaluatorContextImpl impl = new EvaluatorContextImpl(sessionState);
return impl; return impl;
} }
@Override @Override
public void notifyRename(EvaluatorContext context, Operation operation, public void notifyRename(EvaluatorContext context, Operation operation,
Command command) Command command)
{ {
// currentScenarioInstances needs to be protected for concurrency. // currentScenarioInstances needs to be protected for concurrency.
synchronized (context.getScenarioInstances()) synchronized (context.getScenarioInstances())
{ {
/** /**
* For each active scenario. * For each active scenario.
*/ */
Iterator<ScenarioInstance> i = context.getScenarioInstances().iterator(); Iterator<ScenarioInstance> i = context.getScenarioInstances().iterator();
while(i.hasNext()) while(i.hasNext())
{ {
ScenarioInstance scenario = i.next(); ScenarioInstance scenario = i.next();
if(scenario instanceof ScenarioInstanceRenameAware) if(scenario instanceof ScenarioInstanceRenameAware)
{ {
ScenarioInstanceRenameAware awareScenario = (ScenarioInstanceRenameAware)scenario; ScenarioInstanceRenameAware awareScenario = (ScenarioInstanceRenameAware)scenario;
awareScenario.notifyRename(operation, command); awareScenario.notifyRename(operation, command);
} }
} }
} }
} }
} }

View File

@@ -1,23 +1,23 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.List; import java.util.List;
/** /**
* A scenario is a factory for scenario instances. * A scenario is a factory for scenario instances.
* *
*/ */
public interface Scenario public interface Scenario
{ {
/** /**
* Create a new ScenarioInstance * Create a new ScenarioInstance
* <p> * <p>
* If the scenario is interested in the specified operation then * If the scenario is interested in the specified operation then
* return a new scenario instance. * return a new scenario instance.
* @param ctx EvaluatorContext. * @param ctx EvaluatorContext.
* @param operation the operation to be performed * @param operation the operation to be performed
* @return the scenario instance or null if a new instance is not required. * @return the scenario instance or null if a new instance is not required.
*/ */
ScenarioInstance createInstance(EvaluatorContext ctx, Operation operation); ScenarioInstance createInstance(EvaluatorContext ctx, Operation operation);
} }

View File

@@ -1,97 +1,97 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
import org.alfresco.filesys.repo.rules.operations.CreateFileOperation; import org.alfresco.filesys.repo.rules.operations.CreateFileOperation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* A shuffle * A shuffle
* *
* a) New file created. * a) New file created.
* b) Existing file moved out of the way * b) Existing file moved out of the way
* c) New file moved into place. * c) New file moved into place.
* d) Old file deleted. * d) Old file deleted.
*/ */
public class ScenarioCreateShuffle implements Scenario public class ScenarioCreateShuffle implements Scenario
{ {
private static Log logger = LogFactory.getLog(ScenarioCreateShuffle.class); private static Log logger = LogFactory.getLog(ScenarioCreateShuffle.class);
/** /**
* The regex pattern of a create that will trigger a new instance of * The regex pattern of a create that will trigger a new instance of
* the scenario. * the scenario.
*/ */
private Pattern pattern; private Pattern pattern;
private String strPattern; private String strPattern;
private long timeout = 30000; private long timeout = 30000;
private Ranking ranking = Ranking.HIGH; private Ranking ranking = Ranking.HIGH;
@Override @Override
public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation) public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation)
{ {
/** /**
* This scenario is triggered by a create of a file matching * This scenario is triggered by a create of a file matching
* the pattern * the pattern
*/ */
if(operation instanceof CreateFileOperation) if(operation instanceof CreateFileOperation)
{ {
CreateFileOperation c = (CreateFileOperation)operation; CreateFileOperation c = (CreateFileOperation)operation;
Matcher m = pattern.matcher(c.getName()); Matcher m = pattern.matcher(c.getName());
if(m.matches()) if(m.matches())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("New Scenario Create Shuffle Instance pattern:" + strPattern); logger.debug("New Scenario Create Shuffle Instance pattern:" + strPattern);
} }
ScenarioCreateShuffleInstance instance = new ScenarioCreateShuffleInstance() ; ScenarioCreateShuffleInstance instance = new ScenarioCreateShuffleInstance() ;
instance.setTimeout(timeout); instance.setTimeout(timeout);
instance.setRanking(ranking); instance.setRanking(ranking);
return instance; return instance;
} }
} }
// No not interested. // No not interested.
return null; return null;
} }
public void setPattern(String pattern) public void setPattern(String pattern)
{ {
this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
this.strPattern = pattern; this.strPattern = pattern;
} }
public String getPattern() public String getPattern()
{ {
return this.strPattern; return this.strPattern;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
} }

View File

@@ -1,273 +1,273 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.alfresco.filesys.repo.rules.commands.CompoundCommand; import org.alfresco.filesys.repo.rules.commands.CompoundCommand;
import org.alfresco.filesys.repo.rules.commands.CopyContentCommand; import org.alfresco.filesys.repo.rules.commands.CopyContentCommand;
import org.alfresco.filesys.repo.rules.commands.RenameFileCommand; import org.alfresco.filesys.repo.rules.commands.RenameFileCommand;
import org.alfresco.filesys.repo.rules.operations.CreateFileOperation; import org.alfresco.filesys.repo.rules.operations.CreateFileOperation;
import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation; import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation;
import org.alfresco.filesys.repo.rules.operations.RenameFileOperation; import org.alfresco.filesys.repo.rules.operations.RenameFileOperation;
import org.alfresco.jlan.server.filesys.FileName; import org.alfresco.jlan.server.filesys.FileName;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* This is an instance of a "classic shuffle" triggered by a create of a * This is an instance of a "classic shuffle" triggered by a create of a
* file matching a specified pattern. * file matching a specified pattern.
* <p> * <p>
* a) New file created. Typically with an obscure name. * a) New file created. Typically with an obscure name.
* b) Existing file moved out of the way * b) Existing file moved out of the way
* c) New file moved into place. * c) New file moved into place.
* d) Old file deleted. * d) Old file deleted.
* *
* <p> * <p>
* If this filter is active then this is what happens. * If this filter is active then this is what happens.
* a) New file created. New file created (X). * a) New file created. New file created (X).
* b) Existing file moved out of the way (Y to Z). Raname tracked. * b) Existing file moved out of the way (Y to Z). Raname tracked.
* c) New file moved into place (X to Y). Scenario kicks in to change commands. * c) New file moved into place (X to Y). Scenario kicks in to change commands.
* d) Old file deleted. * d) Old file deleted.
*/ */
public class ScenarioCreateShuffleInstance implements ScenarioInstance public class ScenarioCreateShuffleInstance implements ScenarioInstance
{ {
private static Log logger = LogFactory.getLog(ScenarioCreateShuffleInstance.class); private static Log logger = LogFactory.getLog(ScenarioCreateShuffleInstance.class);
enum InternalState enum InternalState
{ {
NONE, NONE,
RENAME, RENAME,
DELETE DELETE
} }
InternalState internalState = InternalState.NONE; InternalState internalState = InternalState.NONE;
private Date startTime = new Date(); private Date startTime = new Date();
private String createName; private String createName;
private String move1; private String move1;
private String move2; private String move2;
private Ranking ranking; private Ranking ranking;
/** /**
* Timeout in ms. Default 30 seconds. * Timeout in ms. Default 30 seconds.
*/ */
private long timeout = 60000; private long timeout = 60000;
private boolean isComplete; private boolean isComplete;
/** /**
* Keep track of re-names * Keep track of re-names
*/ */
private Map<String, String>renames = new HashMap<String, String>(); private Map<String, String>renames = new HashMap<String, String>();
/** /**
* Evaluate the next operation * Evaluate the next operation
* @param operation Operation * @param operation Operation
*/ */
public Command evaluate(Operation operation) public Command evaluate(Operation operation)
{ {
/** /**
* Anti-pattern : timeout * Anti-pattern : timeout
*/ */
Date now = new Date(); Date now = new Date();
if(now.getTime() > startTime.getTime() + getTimeout()) if(now.getTime() > startTime.getTime() + getTimeout())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Instance timed out createName:" + createName); logger.debug("Instance timed out createName:" + createName);
isComplete = true; isComplete = true;
return null; return null;
} }
} }
/** /**
* Anti-pattern for all states - delete the file we are * Anti-pattern for all states - delete the file we are
* shuffling * shuffling
*/ */
if(createName != null) if(createName != null)
{ {
if(operation instanceof DeleteFileOperation) if(operation instanceof DeleteFileOperation)
{ {
DeleteFileOperation d = (DeleteFileOperation)operation; DeleteFileOperation d = (DeleteFileOperation)operation;
if(d.getName().equals(createName)) if(d.getName().equals(createName))
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Anti-pattern : Shuffle file deleted createName:" + createName); logger.debug("Anti-pattern : Shuffle file deleted createName:" + createName);
} }
isComplete = true; isComplete = true;
return null; return null;
} }
} }
} }
switch (internalState) switch (internalState)
{ {
case NONE: case NONE:
// Looking for a create transition // Looking for a create transition
if(operation instanceof CreateFileOperation) if(operation instanceof CreateFileOperation)
{ {
CreateFileOperation c = (CreateFileOperation)operation; CreateFileOperation c = (CreateFileOperation)operation;
this.createName = c.getName(); this.createName = c.getName();
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("entering RENAME state: " + createName); logger.debug("entering RENAME state: " + createName);
} }
internalState = InternalState.RENAME; internalState = InternalState.RENAME;
return null; return null;
} }
else else
{ {
// anything else bomb out // anything else bomb out
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("State error, expected a CREATE"); logger.debug("State error, expected a CREATE");
} }
isComplete = true; isComplete = true;
} }
break; break;
case RENAME: case RENAME:
/** /**
* Looking for two renames X(createName) to Y(middle) to Z(end) * Looking for two renames X(createName) to Y(middle) to Z(end)
*/ */
if(operation instanceof RenameFileOperation) if(operation instanceof RenameFileOperation)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Tracking rename: " + operation); logger.debug("Tracking rename: " + operation);
} }
RenameFileOperation r = (RenameFileOperation)operation; RenameFileOperation r = (RenameFileOperation)operation;
renames.put(r.getFrom(), r.getTo()); renames.put(r.getFrom(), r.getTo());
// Now see if this rename makes a pair. // Now see if this rename makes a pair.
String middle = renames.get(createName); String middle = renames.get(createName);
if(middle != null) if(middle != null)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Got second rename" ); logger.debug("Got second rename" );
} }
String end = renames.get(middle); String end = renames.get(middle);
if(end != null) if(end != null)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Got two renames " ); logger.debug("Got two renames " );
} }
this.move1 = middle; this.move1 = middle;
this.move2 = end; this.move2 = end;
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("entering DELETE state"); logger.debug("entering DELETE state");
} }
internalState = InternalState.DELETE; internalState = InternalState.DELETE;
/** /**
* This shuffle reverses the rename out of the way and then copies the * This shuffle reverses the rename out of the way and then copies the
* content only. Finally it moves the temp file into place for the subsequent * content only. Finally it moves the temp file into place for the subsequent
* delete. * delete.
* a) Rename Z to Y (Reverse previous move) * a) Rename Z to Y (Reverse previous move)
* b) Copy Content from X to Y * b) Copy Content from X to Y
* c) Rename X to Z (move temp file out to old location) * c) Rename X to Z (move temp file out to old location)
*/ */
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Go and shuffle! createName:" + createName + " move1 " + move1 + " move2 " + move2); logger.debug("Go and shuffle! createName:" + createName + " move1 " + move1 + " move2 " + move2);
} }
String[] paths = FileName.splitPath(r.getFromPath()); String[] paths = FileName.splitPath(r.getFromPath());
String oldFolder = paths[0]; String oldFolder = paths[0];
// String oldFile = paths[1]; // String oldFile = paths[1];
ArrayList<Command> commands = new ArrayList<Command>(); ArrayList<Command> commands = new ArrayList<Command>();
RenameFileCommand r1 = new RenameFileCommand(end, middle, r.getRootNodeRef(), oldFolder + "\\" + end, oldFolder + "\\" + middle); RenameFileCommand r1 = new RenameFileCommand(end, middle, r.getRootNodeRef(), oldFolder + "\\" + end, oldFolder + "\\" + middle);
CopyContentCommand copyContent = new CopyContentCommand(createName, move1, r.getRootNodeRef(), oldFolder + "\\" + createName, oldFolder + "\\" + middle); CopyContentCommand copyContent = new CopyContentCommand(createName, move1, r.getRootNodeRef(), oldFolder + "\\" + createName, oldFolder + "\\" + middle);
RenameFileCommand r2 = new RenameFileCommand(createName, end, r.getRootNodeRef(), oldFolder + "\\" + createName, oldFolder + "\\" + end); RenameFileCommand r2 = new RenameFileCommand(createName, end, r.getRootNodeRef(), oldFolder + "\\" + createName, oldFolder + "\\" + end);
commands.add(r1); commands.add(r1);
commands.add(copyContent); commands.add(copyContent);
commands.add(r2); commands.add(r2);
return new CompoundCommand(commands); return new CompoundCommand(commands);
} }
} }
} }
break; break;
case DELETE: case DELETE:
/** /**
* Looking for a delete of the destination * Looking for a delete of the destination
*/ */
if(operation instanceof DeleteFileOperation) if(operation instanceof DeleteFileOperation)
{ {
DeleteFileOperation d = (DeleteFileOperation)operation; DeleteFileOperation d = (DeleteFileOperation)operation;
if(d.getName().equals(move2)) if(d.getName().equals(move2))
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Scenario complete createName:" + createName); logger.debug("Scenario complete createName:" + createName);
} }
isComplete = true; isComplete = true;
} }
} }
/** /**
* Todo consider create shuffle with backup file which will never * Todo consider create shuffle with backup file which will never
* calls delete - do we need to pattern match on "Backup*". * calls delete - do we need to pattern match on "Backup*".
* At the moment the delete state does nothing - hence * At the moment the delete state does nothing - hence
* we can simply set complete here for all situations. * we can simply set complete here for all situations.
*/ */
isComplete = true; isComplete = true;
break; break;
} }
return null; return null;
} }
@Override @Override
public boolean isComplete() public boolean isComplete()
{ {
return isComplete; return isComplete;
} }
@Override @Override
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public String toString() public String toString()
{ {
return "ScenarioShuffleInstance: createName:" + createName; return "ScenarioShuffleInstance: createName:" + createName;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
} }

View File

@@ -1,128 +1,128 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
import org.alfresco.filesys.repo.rules.operations.CloseFileOperation; import org.alfresco.filesys.repo.rules.operations.CloseFileOperation;
import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation; import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* The DeleteOnClose rename shuffle is a delete on close of a file resulting in a file being deleted followed by a * The DeleteOnClose rename shuffle is a delete on close of a file resulting in a file being deleted followed by a
* rename or a create * rename or a create
* *
* First case of this is Mac Mountain Lion Preview application. * First case of this is Mac Mountain Lion Preview application.
* and then a new copy of the file put into place. * and then a new copy of the file put into place.
* *
* a) DeleteOnClose fileA * a) DeleteOnClose fileA
* b) Close fileA * b) Close fileA
* c) Rename whatever fileA * c) Rename whatever fileA
* *
* Second case First case of this is Mac Drag and drop. * Second case First case of this is Mac Drag and drop.
* and then a new copy of the file put into place. * and then a new copy of the file put into place.
* *
* a) Delete fileA * a) Delete fileA
* b) Close fileA * b) Close fileA
* c) Create fileA * c) Create fileA
* *
* Third case Gedit. * Third case Gedit.
* *
* a) Delete fileA * a) Delete fileA
* b) Rename .goutputstream fileA * b) Rename .goutputstream fileA
* *
*/ */
public class ScenarioDeleteRenameOrCreate implements Scenario public class ScenarioDeleteRenameOrCreate implements Scenario
{ {
private static Log logger = LogFactory.getLog(ScenarioDeleteRenameOrCreate.class); private static Log logger = LogFactory.getLog(ScenarioDeleteRenameOrCreate.class);
/** /**
* The regex pattern of a close that will trigger a new instance of * The regex pattern of a close that will trigger a new instance of
* the scenario. * the scenario.
*/ */
private Pattern pattern; private Pattern pattern;
private String strPattern; private String strPattern;
private long timeout = 30000; private long timeout = 30000;
@Override @Override
public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation) public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation)
{ {
/** /**
* This scenario is triggered by a rename of a file matching * This scenario is triggered by a rename of a file matching
* the pattern * the pattern
*/ */
if(operation instanceof CloseFileOperation) if(operation instanceof CloseFileOperation)
{ {
CloseFileOperation c = (CloseFileOperation)operation; CloseFileOperation c = (CloseFileOperation)operation;
Matcher m = pattern.matcher(c.getName()); Matcher m = pattern.matcher(c.getName());
if(m.matches() && c.getNetworkFile().hasDeleteOnClose()) if(m.matches() && c.getNetworkFile().hasDeleteOnClose())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("New Scenario ScenarioDeleteRenameOrCreate strPattern:" + pattern); logger.debug("New Scenario ScenarioDeleteRenameOrCreate strPattern:" + pattern);
} }
ScenarioDeleteRenameOrCreateInstance instance = new ScenarioDeleteRenameOrCreateInstance(); ScenarioDeleteRenameOrCreateInstance instance = new ScenarioDeleteRenameOrCreateInstance();
instance.setTimeout(timeout); instance.setTimeout(timeout);
instance.setRanking(ranking); instance.setRanking(ranking);
return instance; return instance;
} }
} }
if(operation instanceof DeleteFileOperation) if(operation instanceof DeleteFileOperation)
{ {
DeleteFileOperation c = (DeleteFileOperation)operation; DeleteFileOperation c = (DeleteFileOperation)operation;
Matcher m = pattern.matcher(c.getName()); Matcher m = pattern.matcher(c.getName());
if(m.matches()) if(m.matches())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("New Scenario ScenarioDeleteRenameOrCreate strPattern:" + pattern); logger.debug("New Scenario ScenarioDeleteRenameOrCreate strPattern:" + pattern);
} }
ScenarioDeleteRenameOrCreateInstance instance = new ScenarioDeleteRenameOrCreateInstance(); ScenarioDeleteRenameOrCreateInstance instance = new ScenarioDeleteRenameOrCreateInstance();
instance.setTimeout(timeout); instance.setTimeout(timeout);
instance.setRanking(ranking); instance.setRanking(ranking);
return instance; return instance;
} }
} }
// No not interested. // No not interested.
return null; return null;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
public void setPattern(String pattern) public void setPattern(String pattern)
{ {
this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
this.strPattern = pattern; this.strPattern = pattern;
} }
public String getPattern() public String getPattern()
{ {
return strPattern; return strPattern;
} }
private Ranking ranking = Ranking.HIGH; private Ranking ranking = Ranking.HIGH;
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
} }

View File

@@ -1,270 +1,270 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import org.alfresco.filesys.repo.ResultCallback; import org.alfresco.filesys.repo.ResultCallback;
import org.alfresco.filesys.repo.rules.commands.CloseFileCommand; import org.alfresco.filesys.repo.rules.commands.CloseFileCommand;
import org.alfresco.filesys.repo.rules.commands.CompoundCommand; import org.alfresco.filesys.repo.rules.commands.CompoundCommand;
import org.alfresco.filesys.repo.rules.commands.CopyContentCommand; import org.alfresco.filesys.repo.rules.commands.CopyContentCommand;
import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand; import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand;
import org.alfresco.filesys.repo.rules.commands.RestoreFileCommand; import org.alfresco.filesys.repo.rules.commands.RestoreFileCommand;
import org.alfresco.filesys.repo.rules.operations.CloseFileOperation; import org.alfresco.filesys.repo.rules.operations.CloseFileOperation;
import org.alfresco.filesys.repo.rules.operations.CreateFileOperation; import org.alfresco.filesys.repo.rules.operations.CreateFileOperation;
import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation; import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation;
import org.alfresco.filesys.repo.rules.operations.MoveFileOperation; import org.alfresco.filesys.repo.rules.operations.MoveFileOperation;
import org.alfresco.filesys.repo.rules.operations.RenameFileOperation; import org.alfresco.filesys.repo.rules.operations.RenameFileOperation;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* First case of this is Mac Mountain Lion Preview application. * First case of this is Mac Mountain Lion Preview application.
* and then a new copy of the file put into place. * and then a new copy of the file put into place.
* *
* a) DeleteOnClose fileA * a) DeleteOnClose fileA
* b) Close fileA * b) Close fileA
* c) Rename whatever fileA * c) Rename whatever fileA
* *
* a) Delete fileA * a) Delete fileA
* b)Rename File~ to File * b)Rename File~ to File
* *
* This rule will kick in and ... * This rule will kick in and ...
* *
*/ */
class ScenarioDeleteRenameOrCreateInstance implements ScenarioInstance class ScenarioDeleteRenameOrCreateInstance implements ScenarioInstance
{ {
private static Log logger = LogFactory.getLog(ScenarioDeleteRenameOrCreateInstance.class); private static Log logger = LogFactory.getLog(ScenarioDeleteRenameOrCreateInstance.class);
private Date startTime = new Date(); private Date startTime = new Date();
/** /**
* Timeout in ms. Default 30 seconds. * Timeout in ms. Default 30 seconds.
*/ */
private long timeout = 30000; private long timeout = 30000;
private boolean isComplete = false; private boolean isComplete = false;
private Ranking ranking = Ranking.HIGH; private Ranking ranking = Ranking.HIGH;
private NodeRef originalNodeRef = null; private NodeRef originalNodeRef = null;
enum InternalState enum InternalState
{ {
NONE, NONE,
INITIALISED INITIALISED
} ; } ;
InternalState state = InternalState.NONE; InternalState state = InternalState.NONE;
String name; String name;
/** /**
* Evaluate the next operation * Evaluate the next operation
* @param operation * @param operation
*/ */
public Command evaluate(Operation operation) public Command evaluate(Operation operation)
{ {
/** /**
* Anti-pattern : timeout * Anti-pattern : timeout
*/ */
Date now = new Date(); Date now = new Date();
if(now.getTime() > startTime.getTime() + getTimeout()) if(now.getTime() > startTime.getTime() + getTimeout())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Instance timed out"); logger.debug("Instance timed out");
} }
isComplete = true; isComplete = true;
return null; return null;
} }
switch (state) switch (state)
{ {
case NONE: case NONE:
if(operation instanceof CloseFileOperation) if(operation instanceof CloseFileOperation)
{ {
CloseFileOperation c = (CloseFileOperation)operation; CloseFileOperation c = (CloseFileOperation)operation;
this.name = c.getName(); this.name = c.getName();
logger.debug("New scenario initialised for file " + name); logger.debug("New scenario initialised for file " + name);
state = InternalState.INITIALISED; state = InternalState.INITIALISED;
ArrayList<Command> commands = new ArrayList<Command>(); ArrayList<Command> commands = new ArrayList<Command>();
ArrayList<Command> postCommitCommands = new ArrayList<Command>(); ArrayList<Command> postCommitCommands = new ArrayList<Command>();
ArrayList<Command> postErrorCommands = new ArrayList<Command>(); ArrayList<Command> postErrorCommands = new ArrayList<Command>();
commands.add(new CloseFileCommand(c.getName(), c.getNetworkFile(), c.getRootNodeRef(), c.getPath())); commands.add(new CloseFileCommand(c.getName(), c.getNetworkFile(), c.getRootNodeRef(), c.getPath()));
postCommitCommands.add(newDeleteFileCallbackCommand()); postCommitCommands.add(newDeleteFileCallbackCommand());
return new CompoundCommand(commands, postCommitCommands, postErrorCommands); return new CompoundCommand(commands, postCommitCommands, postErrorCommands);
} }
if(operation instanceof DeleteFileOperation) if(operation instanceof DeleteFileOperation)
{ {
DeleteFileOperation c = (DeleteFileOperation)operation; DeleteFileOperation c = (DeleteFileOperation)operation;
this.name = c.getName(); this.name = c.getName();
logger.debug("New scenario initialised for file " + name); logger.debug("New scenario initialised for file " + name);
state = InternalState.INITIALISED; state = InternalState.INITIALISED;
ArrayList<Command> commands = new ArrayList<Command>(); ArrayList<Command> commands = new ArrayList<Command>();
ArrayList<Command> postCommitCommands = new ArrayList<Command>(); ArrayList<Command> postCommitCommands = new ArrayList<Command>();
ArrayList<Command> postErrorCommands = new ArrayList<Command>(); ArrayList<Command> postErrorCommands = new ArrayList<Command>();
commands.add(new DeleteFileCommand(c.getName(), c.getRootNodeRef(), c.getPath())); commands.add(new DeleteFileCommand(c.getName(), c.getRootNodeRef(), c.getPath()));
postCommitCommands.add(newDeleteFileCallbackCommand()); postCommitCommands.add(newDeleteFileCallbackCommand());
return new CompoundCommand(commands, postCommitCommands, postErrorCommands); return new CompoundCommand(commands, postCommitCommands, postErrorCommands);
} }
break; break;
case INITIALISED: case INITIALISED:
if(operation instanceof CreateFileOperation) if(operation instanceof CreateFileOperation)
{ {
CreateFileOperation c = (CreateFileOperation)operation; CreateFileOperation c = (CreateFileOperation)operation;
if(c.getName().equalsIgnoreCase(name)) if(c.getName().equalsIgnoreCase(name))
{ {
isComplete = true; isComplete = true;
if(originalNodeRef != null) if(originalNodeRef != null)
{ {
logger.debug("Delete create shuffle fire!:" + this); logger.debug("Delete create shuffle fire!:" + this);
return new RestoreFileCommand(c.getName(), c.getRootNodeRef(), c.getPath(), c.getAllocationSize(), originalNodeRef); return new RestoreFileCommand(c.getName(), c.getRootNodeRef(), c.getPath(), c.getAllocationSize(), originalNodeRef);
} }
return null; return null;
} }
} }
if(operation instanceof RenameFileOperation) if(operation instanceof RenameFileOperation)
{ {
RenameFileOperation r = (RenameFileOperation)operation; RenameFileOperation r = (RenameFileOperation)operation;
if(name.equals(r.getTo())) if(name.equals(r.getTo()))
{ {
logger.debug("Delete Rename shuffle - fire!"); logger.debug("Delete Rename shuffle - fire!");
if(originalNodeRef != null) if(originalNodeRef != null)
{ {
/** /**
* Shuffle is as follows * Shuffle is as follows
* a) Copy content from File to File~ * a) Copy content from File to File~
* b) Delete File * b) Delete File
* c) Rename File~ to File * c) Rename File~ to File
*/ */
ArrayList<Command> commands = new ArrayList<Command>(); ArrayList<Command> commands = new ArrayList<Command>();
RestoreFileCommand r1 = new RestoreFileCommand(r.getTo(), r.getRootNodeRef(), r.getToPath(), 0, originalNodeRef); RestoreFileCommand r1 = new RestoreFileCommand(r.getTo(), r.getRootNodeRef(), r.getToPath(), 0, originalNodeRef);
CopyContentCommand copyContent = new CopyContentCommand(r.getFrom(), r.getTo(), r.getRootNodeRef(), r.getFromPath(), r.getToPath()); CopyContentCommand copyContent = new CopyContentCommand(r.getFrom(), r.getTo(), r.getRootNodeRef(), r.getFromPath(), r.getToPath());
DeleteFileCommand d1 = new DeleteFileCommand(r.getFrom(), r.getRootNodeRef(), r.getFromPath()); DeleteFileCommand d1 = new DeleteFileCommand(r.getFrom(), r.getRootNodeRef(), r.getFromPath());
commands.add(r1); commands.add(r1);
commands.add(copyContent); commands.add(copyContent);
commands.add(d1); commands.add(d1);
logger.debug("Scenario complete"); logger.debug("Scenario complete");
isComplete = true; isComplete = true;
return new CompoundCommand(commands); return new CompoundCommand(commands);
} }
else else
{ {
logger.debug("Scenario complete"); logger.debug("Scenario complete");
isComplete = true; isComplete = true;
return null; return null;
} }
} }
} }
if(operation instanceof MoveFileOperation) if(operation instanceof MoveFileOperation)
{ {
MoveFileOperation r = (MoveFileOperation)operation; MoveFileOperation r = (MoveFileOperation)operation;
if(name.equals(r.getTo())) if(name.equals(r.getTo()))
{ {
logger.debug("Delete Rename shuffle - fire!"); logger.debug("Delete Rename shuffle - fire!");
if(originalNodeRef != null) if(originalNodeRef != null)
{ {
/** /**
* Shuffle is as follows * Shuffle is as follows
* a) Copy content from File to File~ * a) Copy content from File to File~
* b) Delete File * b) Delete File
* c) Rename File~ to File * c) Rename File~ to File
*/ */
ArrayList<Command> commands = new ArrayList<Command>(); ArrayList<Command> commands = new ArrayList<Command>();
RestoreFileCommand r1 = new RestoreFileCommand(r.getTo(), r.getRootNodeRef(), r.getToPath(), 0, originalNodeRef); RestoreFileCommand r1 = new RestoreFileCommand(r.getTo(), r.getRootNodeRef(), r.getToPath(), 0, originalNodeRef);
CopyContentCommand copyContent = new CopyContentCommand(r.getFrom(), r.getTo(), r.getRootNodeRef(), r.getFromPath(), r.getToPath()); CopyContentCommand copyContent = new CopyContentCommand(r.getFrom(), r.getTo(), r.getRootNodeRef(), r.getFromPath(), r.getToPath());
DeleteFileCommand d1 = new DeleteFileCommand(r.getFrom(), r.getRootNodeRef(), r.getFromPath()); DeleteFileCommand d1 = new DeleteFileCommand(r.getFrom(), r.getRootNodeRef(), r.getFromPath());
commands.add(r1); commands.add(r1);
commands.add(copyContent); commands.add(copyContent);
commands.add(d1); commands.add(d1);
logger.debug("Scenario complete"); logger.debug("Scenario complete");
isComplete = true; isComplete = true;
return new CompoundCommand(commands); return new CompoundCommand(commands);
} }
else else
{ {
logger.debug("Scenario complete"); logger.debug("Scenario complete");
isComplete = true; isComplete = true;
return null; return null;
} }
} }
} }
} }
return null; return null;
} }
@Override @Override
public boolean isComplete() public boolean isComplete()
{ {
return isComplete; return isComplete;
} }
public String toString() public String toString()
{ {
return "ScenarioDeleteRenameOrCreate name:" + name ; return "ScenarioDeleteRenameOrCreate name:" + name ;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
@Override @Override
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
/** /**
* Called for delete file. * Called for delete file.
*/ */
private ResultCallback newDeleteFileCallbackCommand() private ResultCallback newDeleteFileCallbackCommand()
{ {
return new ResultCallback() return new ResultCallback()
{ {
@Override @Override
public void execute(Object result) public void execute(Object result)
{ {
if(result instanceof NodeRef) if(result instanceof NodeRef)
{ {
logger.debug("got node ref of deleted node"); logger.debug("got node ref of deleted node");
originalNodeRef = (NodeRef)result; originalNodeRef = (NodeRef)result;
} }
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_NONE; return TxnReadState.TXN_NONE;
} }
}; };
} }
} }

View File

@@ -1,94 +1,94 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation; import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* A delete restore shuffle. * A delete restore shuffle.
* *
* Files are deleted then re-created. * Files are deleted then re-created.
*/ */
public class ScenarioDeleteRestore implements Scenario public class ScenarioDeleteRestore implements Scenario
{ {
private static Log logger = LogFactory.getLog(ScenarioDeleteRestore.class); private static Log logger = LogFactory.getLog(ScenarioDeleteRestore.class);
/** /**
* The regex pattern of a create that will trigger a new instance of * The regex pattern of a create that will trigger a new instance of
* the scenario. * the scenario.
*/ */
private Pattern pattern; private Pattern pattern;
private String strPattern; private String strPattern;
private long timeout = 30000; private long timeout = 30000;
private Ranking ranking = Ranking.HIGH; private Ranking ranking = Ranking.HIGH;
@Override @Override
public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation) public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation)
{ {
/** /**
* This scenario is triggered by a delete of a file matching * This scenario is triggered by a delete of a file matching
* the pattern * the pattern
*/ */
if(operation instanceof DeleteFileOperation) if(operation instanceof DeleteFileOperation)
{ {
DeleteFileOperation c = (DeleteFileOperation)operation; DeleteFileOperation c = (DeleteFileOperation)operation;
Matcher m = pattern.matcher(c.getName()); Matcher m = pattern.matcher(c.getName());
if(m.matches()) if(m.matches())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("New Scenario Delete Restore Shuffle Instance:" + c.getName()); logger.debug("New Scenario Delete Restore Shuffle Instance:" + c.getName());
} }
ScenarioDeleteRestoreInstance instance = new ScenarioDeleteRestoreInstance() ; ScenarioDeleteRestoreInstance instance = new ScenarioDeleteRestoreInstance() ;
instance.setTimeout(timeout); instance.setTimeout(timeout);
instance.setRanking(ranking); instance.setRanking(ranking);
return instance; return instance;
} }
} }
// No not interested. // No not interested.
return null; return null;
} }
public void setPattern(String pattern) public void setPattern(String pattern)
{ {
this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
this.strPattern = pattern; this.strPattern = pattern;
} }
public String getPattern() public String getPattern()
{ {
return this.strPattern; return this.strPattern;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
} }

View File

@@ -1,214 +1,214 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.alfresco.filesys.repo.ResultCallback; import org.alfresco.filesys.repo.ResultCallback;
import org.alfresco.filesys.repo.rules.commands.CompoundCommand; import org.alfresco.filesys.repo.rules.commands.CompoundCommand;
import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand; import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand;
import org.alfresco.filesys.repo.rules.commands.RestoreFileCommand; import org.alfresco.filesys.repo.rules.commands.RestoreFileCommand;
import org.alfresco.filesys.repo.rules.operations.CreateFileOperation; import org.alfresco.filesys.repo.rules.operations.CreateFileOperation;
import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation; import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation;
import org.alfresco.jlan.server.filesys.NetworkFile; import org.alfresco.jlan.server.filesys.NetworkFile;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* This is an instance of a "delete restore shuffle" * This is an instance of a "delete restore shuffle"
* *
* Triggered by a delete of a file followed by a recreate of that same file. * Triggered by a delete of a file followed by a recreate of that same file.
* *
* <p> First implemented for MacOS Lion Finder. * <p> First implemented for MacOS Lion Finder.
* *
* <p> * <p>
* Sequence of operations. * Sequence of operations.
* a) File Deleted * a) File Deleted
* b) File Created. * b) File Created.
*/ */
public class ScenarioDeleteRestoreInstance implements ScenarioInstance public class ScenarioDeleteRestoreInstance implements ScenarioInstance
{ {
private static Log logger = LogFactory.getLog(ScenarioDeleteRestoreInstance.class); private static Log logger = LogFactory.getLog(ScenarioDeleteRestoreInstance.class);
enum InternalState enum InternalState
{ {
NONE, NONE,
LOOKING_FOR_CREATE LOOKING_FOR_CREATE
} }
InternalState internalState = InternalState.NONE; InternalState internalState = InternalState.NONE;
private Date startTime = new Date(); private Date startTime = new Date();
private String deleteName; private String deleteName;
private NodeRef originalNodeRef; private NodeRef originalNodeRef;
private Ranking ranking; private Ranking ranking;
/** /**
* Timeout in ms. Default 30 seconds. * Timeout in ms. Default 30 seconds.
*/ */
private long timeout = 60000; private long timeout = 60000;
private boolean isComplete; private boolean isComplete;
/** /**
* Keep track of deletes that we substitute with a rename * Keep track of deletes that we substitute with a rename
* could be more than one if scenarios overlap * could be more than one if scenarios overlap
* *
* From, TempFileName * From, TempFileName
*/ */
private Map<String, String> deletes = new HashMap<String, String>(); private Map<String, String> deletes = new HashMap<String, String>();
/** /**
* Evaluate the next operation * Evaluate the next operation
* @param operation Operation * @param operation Operation
*/ */
public Command evaluate(Operation operation) public Command evaluate(Operation operation)
{ {
/** /**
* Anti-pattern : timeout * Anti-pattern : timeout
*/ */
Date now = new Date(); Date now = new Date();
if(now.getTime() > startTime.getTime() + getTimeout()) if(now.getTime() > startTime.getTime() + getTimeout())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Instance timed out deleteName:" + deleteName); logger.debug("Instance timed out deleteName:" + deleteName);
isComplete = true; isComplete = true;
return null; return null;
} }
} }
switch (internalState) switch (internalState)
{ {
case NONE: case NONE:
/** /**
* Looking for file being deleted deleted * Looking for file being deleted deleted
*/ */
if(operation instanceof DeleteFileOperation) if(operation instanceof DeleteFileOperation)
{ {
DeleteFileOperation d = (DeleteFileOperation)operation; DeleteFileOperation d = (DeleteFileOperation)operation;
deleteName = d.getName(); deleteName = d.getName();
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("entering LOOKING_FOR_CREATE state: " + deleteName); logger.debug("entering LOOKING_FOR_CREATE state: " + deleteName);
} }
internalState = InternalState.LOOKING_FOR_CREATE; internalState = InternalState.LOOKING_FOR_CREATE;
ArrayList<Command> commands = new ArrayList<Command>(); ArrayList<Command> commands = new ArrayList<Command>();
ArrayList<Command> postCommitCommands = new ArrayList<Command>(); ArrayList<Command> postCommitCommands = new ArrayList<Command>();
ArrayList<Command> postErrorCommands = new ArrayList<Command>(); ArrayList<Command> postErrorCommands = new ArrayList<Command>();
commands.add(new DeleteFileCommand(d.getName(), d.getRootNodeRef(), d.getPath())); commands.add(new DeleteFileCommand(d.getName(), d.getRootNodeRef(), d.getPath()));
postCommitCommands.add(newDeleteFileCallbackCommand()); postCommitCommands.add(newDeleteFileCallbackCommand());
return new CompoundCommand(commands, postCommitCommands, postErrorCommands); return new CompoundCommand(commands, postCommitCommands, postErrorCommands);
} }
else else
{ {
// anything else bomb out // anything else bomb out
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("State error, expected a DELETE"); logger.debug("State error, expected a DELETE");
} }
isComplete = true; isComplete = true;
} }
break; break;
case LOOKING_FOR_CREATE: case LOOKING_FOR_CREATE:
/** /**
* Looking for a create operation of the deleted file * Looking for a create operation of the deleted file
*/ */
if(operation instanceof CreateFileOperation) if(operation instanceof CreateFileOperation)
{ {
CreateFileOperation c = (CreateFileOperation)operation; CreateFileOperation c = (CreateFileOperation)operation;
if(c.getName().equalsIgnoreCase(deleteName)) if(c.getName().equalsIgnoreCase(deleteName))
{ {
isComplete = true; isComplete = true;
if(originalNodeRef != null) if(originalNodeRef != null)
{ {
logger.debug("Scenario fires:" + this); logger.debug("Scenario fires:" + this);
return new RestoreFileCommand(c.getName(), c.getRootNodeRef(), c.getPath(), c.getAllocationSize(), originalNodeRef); return new RestoreFileCommand(c.getName(), c.getRootNodeRef(), c.getPath(), c.getAllocationSize(), originalNodeRef);
} }
return null; return null;
} }
} }
} }
return null; return null;
} }
@Override @Override
public boolean isComplete() public boolean isComplete()
{ {
return isComplete; return isComplete;
} }
@Override @Override
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public String toString() public String toString()
{ {
return "ScenarioDeleteRestoreShuffleInstance:" + deleteName; return "ScenarioDeleteRestoreShuffleInstance:" + deleteName;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
/** /**
* Called for delete file. * Called for delete file.
*/ */
private ResultCallback newDeleteFileCallbackCommand() private ResultCallback newDeleteFileCallbackCommand()
{ {
return new ResultCallback() return new ResultCallback()
{ {
@Override @Override
public void execute(Object result) public void execute(Object result)
{ {
if(result instanceof NodeRef) if(result instanceof NodeRef)
{ {
logger.debug("got node ref of deleted node"); logger.debug("got node ref of deleted node");
originalNodeRef = (NodeRef)result; originalNodeRef = (NodeRef)result;
} }
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_NONE; return TxnReadState.TXN_NONE;
} }
}; };
} }
} }

View File

@@ -1,138 +1,138 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
import org.alfresco.filesys.repo.rules.operations.RenameFileOperation; import org.alfresco.filesys.repo.rules.operations.RenameFileOperation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* A double rename shuffle * A double rename shuffle
* *
* a) Existing file renamed out of the way. X.fm to X.backup.fm * a) Existing file renamed out of the way. X.fm to X.backup.fm
* b) New file moved renamed into place. X.fm.C29 * b) New file moved renamed into place. X.fm.C29
* *
* Scenario is triggered by the first rename matching a pattern. * Scenario is triggered by the first rename matching a pattern.
*/ */
public class ScenarioDoubleRenameShuffle implements Scenario public class ScenarioDoubleRenameShuffle implements Scenario
{ {
private static Log logger = LogFactory.getLog(ScenarioDoubleRenameShuffle.class); private static Log logger = LogFactory.getLog(ScenarioDoubleRenameShuffle.class);
/** /**
* The regex pattern of a create that will trigger a new instance of * The regex pattern of a create that will trigger a new instance of
* the scenario. * the scenario.
*/ */
private Pattern pattern; private Pattern pattern;
private String strPattern; private String strPattern;
private Pattern interimPattern; private Pattern interimPattern;
private String strInterimPattern; private String strInterimPattern;
private boolean deleteBackup; private boolean deleteBackup;
private boolean moveAsSystem; private boolean moveAsSystem;
private long timeout = 30000; private long timeout = 30000;
private Ranking ranking = Ranking.HIGH; private Ranking ranking = Ranking.HIGH;
@Override @Override
public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation) public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation)
{ {
/** /**
* This scenario is triggered by a rename of a file matching * This scenario is triggered by a rename of a file matching
* the pattern * the pattern
*/ */
if(operation instanceof RenameFileOperation) if(operation instanceof RenameFileOperation)
{ {
RenameFileOperation r = (RenameFileOperation)operation; RenameFileOperation r = (RenameFileOperation)operation;
Matcher m = pattern.matcher(r.getTo()); Matcher m = pattern.matcher(r.getTo());
if(m.matches()) if(m.matches())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("New Scenario Double Rename Shuffle Instance strPattern:" + pattern + " matches" + r.getTo()); logger.debug("New Scenario Double Rename Shuffle Instance strPattern:" + pattern + " matches" + r.getTo());
} }
ScenarioDoubleRenameShuffleInstance instance = new ScenarioDoubleRenameShuffleInstance(); ScenarioDoubleRenameShuffleInstance instance = new ScenarioDoubleRenameShuffleInstance();
instance.setTimeout(timeout); instance.setTimeout(timeout);
instance.setRanking(ranking); instance.setRanking(ranking);
instance.setDeleteBackup(deleteBackup); instance.setDeleteBackup(deleteBackup);
instance.setMoveAsSystem(moveAsSystem); instance.setMoveAsSystem(moveAsSystem);
if (interimPattern != null) if (interimPattern != null)
{ {
instance.setInterimPattern(interimPattern); instance.setInterimPattern(interimPattern);
} }
return instance; return instance;
} }
} }
// No not interested. // No not interested.
return null; return null;
} }
public void setPattern(String pattern) public void setPattern(String pattern)
{ {
this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
this.strPattern = pattern; this.strPattern = pattern;
} }
public String getPattern() public String getPattern()
{ {
return this.strPattern; return this.strPattern;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
public void setDeleteBackup(boolean deleteBackup) public void setDeleteBackup(boolean deleteBackup)
{ {
this.deleteBackup = deleteBackup; this.deleteBackup = deleteBackup;
} }
public boolean isDeleteBackup() public boolean isDeleteBackup()
{ {
return deleteBackup; return deleteBackup;
} }
public boolean isMoveAsSystem() public boolean isMoveAsSystem()
{ {
return moveAsSystem; return moveAsSystem;
} }
public void setMoveAsSystem(boolean retryAsSystem) public void setMoveAsSystem(boolean retryAsSystem)
{ {
this.moveAsSystem = retryAsSystem; this.moveAsSystem = retryAsSystem;
} }
public void setInterimPattern(String intermediateMovePattern) public void setInterimPattern(String intermediateMovePattern)
{ {
if (null != intermediateMovePattern) if (null != intermediateMovePattern)
{ {
this.interimPattern = Pattern.compile(intermediateMovePattern, Pattern.CASE_INSENSITIVE); this.interimPattern = Pattern.compile(intermediateMovePattern, Pattern.CASE_INSENSITIVE);
this.strInterimPattern = intermediateMovePattern; this.strInterimPattern = intermediateMovePattern;
} }
} }
public String getInterimPattern() public String getInterimPattern()
{ {
return this.strInterimPattern; return this.strInterimPattern;
} }
} }

View File

@@ -1,339 +1,339 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.alfresco.filesys.repo.rules.commands.CompoundCommand; import org.alfresco.filesys.repo.rules.commands.CompoundCommand;
import org.alfresco.filesys.repo.rules.commands.CopyContentCommand; import org.alfresco.filesys.repo.rules.commands.CopyContentCommand;
import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand; import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand;
import org.alfresco.filesys.repo.rules.commands.MoveFileCommand; import org.alfresco.filesys.repo.rules.commands.MoveFileCommand;
import org.alfresco.filesys.repo.rules.commands.RenameFileCommand; import org.alfresco.filesys.repo.rules.commands.RenameFileCommand;
import org.alfresco.filesys.repo.rules.operations.MoveFileOperation; import org.alfresco.filesys.repo.rules.operations.MoveFileOperation;
import org.alfresco.filesys.repo.rules.operations.RenameFileOperation; import org.alfresco.filesys.repo.rules.operations.RenameFileOperation;
import org.alfresco.jlan.server.filesys.FileName; import org.alfresco.jlan.server.filesys.FileName;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* This is an instance of a "double rename shuffle" triggered by rename of a file to a special pattern * This is an instance of a "double rename shuffle" triggered by rename of a file to a special pattern
* file matching a specified pattern. (*.backup.fm) * file matching a specified pattern. (*.backup.fm)
* *
* a) Existing file moved out of the way. X.fm to X.backup.fm * a) Existing file moved out of the way. X.fm to X.backup.fm
* b) New file moved into place. X.fm.C29 X.fm * b) New file moved into place. X.fm.C29 X.fm
* <p> * <p>
* If this filter is active then this is what happens. * If this filter is active then this is what happens.
* a) Existing file moved out of the way (Y to Z). Raname tracked. * a) Existing file moved out of the way (Y to Z). Raname tracked.
* b) New file moved into place (X to Y). * b) New file moved into place (X to Y).
* *
* Scenario kicks in to change commands. * Scenario kicks in to change commands.
*/ */
public class ScenarioDoubleRenameShuffleInstance implements ScenarioInstance public class ScenarioDoubleRenameShuffleInstance implements ScenarioInstance
{ {
private static Log logger = LogFactory.getLog(ScenarioDoubleRenameShuffleInstance.class); private static Log logger = LogFactory.getLog(ScenarioDoubleRenameShuffleInstance.class);
enum InternalState enum InternalState
{ {
NONE, NONE,
RENAME1, RENAME1,
RENAME2 RENAME2
} }
InternalState internalState = InternalState.NONE; InternalState internalState = InternalState.NONE;
private Date startTime = new Date(); private Date startTime = new Date();
private String fileMiddle; private String fileMiddle;
private String fileFrom; private String fileFrom;
private String fileEnd; private String fileEnd;
private Ranking ranking; private Ranking ranking;
private boolean deleteBackup; private boolean deleteBackup;
private boolean moveAsSystem; private boolean moveAsSystem;
private Pattern interimPattern; private Pattern interimPattern;
/** /**
* Timeout in ms. Default 30 seconds. * Timeout in ms. Default 30 seconds.
*/ */
private long timeout = 30000; private long timeout = 30000;
private boolean isComplete; private boolean isComplete;
private String folderMiddle; private String folderMiddle;
private String folderEnd; private String folderEnd;
/** /**
* Keep track of re-names * Keep track of re-names
*/ */
private Map<String, String> renames = new HashMap<String, String>(); private Map<String, String> renames = new HashMap<String, String>();
/** /**
* Evaluate the next operation * Evaluate the next operation
* @param operation * @param operation
*/ */
public Command evaluate(Operation operation) public Command evaluate(Operation operation)
{ {
/** /**
* Anti-pattern : timeout * Anti-pattern : timeout
*/ */
Date now = new Date(); Date now = new Date();
if(now.getTime() > startTime.getTime() + getTimeout()) if(now.getTime() > startTime.getTime() + getTimeout())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Instance timed out"); logger.debug("Instance timed out");
} }
isComplete = true; isComplete = true;
return null; return null;
} }
switch (internalState) switch (internalState)
{ {
case NONE: case NONE:
/** /**
* Looking for first rename Y(middle) to Z(end) * Looking for first rename Y(middle) to Z(end)
*/ */
if(operation instanceof RenameFileOperation) if(operation instanceof RenameFileOperation)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Got first rename - tracking rename: " + operation); logger.debug("Got first rename - tracking rename: " + operation);
} }
RenameFileOperation r = (RenameFileOperation)operation; RenameFileOperation r = (RenameFileOperation)operation;
fileMiddle = r.getFrom(); fileMiddle = r.getFrom();
fileEnd = r.getTo(); fileEnd = r.getTo();
String[] paths = FileName.splitPath(r.getFromPath()); String[] paths = FileName.splitPath(r.getFromPath());
folderMiddle = paths[0]; folderMiddle = paths[0];
String[] paths2 = FileName.splitPath(r.getToPath()); String[] paths2 = FileName.splitPath(r.getToPath());
folderEnd = paths2[0]; folderEnd = paths2[0];
internalState = InternalState.RENAME1; internalState = InternalState.RENAME1;
return new RenameFileCommand(r.getFrom(), r.getTo(), r.getRootNodeRef(), r.getFromPath(), r.getToPath()); return new RenameFileCommand(r.getFrom(), r.getTo(), r.getRootNodeRef(), r.getFromPath(), r.getToPath());
} }
else else
{ {
// anything else bomb out // anything else bomb out
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("State error, expected a RENAME"); logger.debug("State error, expected a RENAME");
} }
isComplete = true; isComplete = true;
} }
case RENAME1: case RENAME1:
/** /**
* Looking for the second of two renames X(createName) to Y(middle) to Z(end) * Looking for the second of two renames X(createName) to Y(middle) to Z(end)
*/ */
if(operation instanceof RenameFileOperation) if(operation instanceof RenameFileOperation)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Tracking rename: " + operation); logger.debug("Tracking rename: " + operation);
} }
RenameFileOperation r = (RenameFileOperation)operation; RenameFileOperation r = (RenameFileOperation)operation;
// Now see if this rename makes a pair // Now see if this rename makes a pair
if(fileMiddle.equalsIgnoreCase(r.getTo())) if(fileMiddle.equalsIgnoreCase(r.getTo()))
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Got second rename" ); logger.debug("Got second rename" );
} }
fileFrom = r.getFrom(); fileFrom = r.getFrom();
/** /**
* This shuffle reverses the rename out of the way and then copies the * This shuffle reverses the rename out of the way and then copies the
* content only. Finally it moves the temp file into place for the subsequent * content only. Finally it moves the temp file into place for the subsequent
* delete. * delete.
* a) Rename Z to Y (Reverse previous move) * a) Rename Z to Y (Reverse previous move)
* b) Copy Content from X to Y * b) Copy Content from X to Y
* c) Rename X to Z (move temp file out to old location) * c) Rename X to Z (move temp file out to old location)
*/ */
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Go and shuffle! fromName:" + fileFrom + " middle: " + fileMiddle + " end: " + fileEnd); logger.debug("Go and shuffle! fromName:" + fileFrom + " middle: " + fileMiddle + " end: " + fileEnd);
} }
String[] paths = FileName.splitPath(r.getFromPath()); String[] paths = FileName.splitPath(r.getFromPath());
String oldFolder = paths[0]; String oldFolder = paths[0];
ArrayList<Command> commands = new ArrayList<Command>(); ArrayList<Command> commands = new ArrayList<Command>();
RenameFileCommand r1 = new RenameFileCommand(fileEnd, fileMiddle, r.getRootNodeRef(), oldFolder + "\\" + fileEnd, oldFolder + "\\" + fileMiddle); RenameFileCommand r1 = new RenameFileCommand(fileEnd, fileMiddle, r.getRootNodeRef(), oldFolder + "\\" + fileEnd, oldFolder + "\\" + fileMiddle);
commands.add(r1); commands.add(r1);
CopyContentCommand copyContent = new CopyContentCommand(fileFrom, fileMiddle, r.getRootNodeRef(), oldFolder + "\\" + fileFrom, oldFolder + "\\" + fileMiddle); CopyContentCommand copyContent = new CopyContentCommand(fileFrom, fileMiddle, r.getRootNodeRef(), oldFolder + "\\" + fileFrom, oldFolder + "\\" + fileMiddle);
commands.add(copyContent); commands.add(copyContent);
if(deleteBackup) if(deleteBackup)
{ {
logger.debug("deleteBackup option turned on"); logger.debug("deleteBackup option turned on");
DeleteFileCommand d1 = new DeleteFileCommand(oldFolder, r.getRootNodeRef(), oldFolder + "\\" + fileFrom); DeleteFileCommand d1 = new DeleteFileCommand(oldFolder, r.getRootNodeRef(), oldFolder + "\\" + fileFrom);
commands.add(d1); commands.add(d1);
} }
else else
{ {
RenameFileCommand r2 = new RenameFileCommand(fileFrom, fileEnd, r.getRootNodeRef(), oldFolder + "\\" + fileFrom, oldFolder + "\\" + fileEnd); RenameFileCommand r2 = new RenameFileCommand(fileFrom, fileEnd, r.getRootNodeRef(), oldFolder + "\\" + fileFrom, oldFolder + "\\" + fileEnd);
commands.add(r2); commands.add(r2);
} }
/** /**
* TODO - we may need to copy a new node for the backup and delete the temp node. * TODO - we may need to copy a new node for the backup and delete the temp node.
* It depends if we care about the contents of the Backup file. * It depends if we care about the contents of the Backup file.
*/ */
isComplete = true; isComplete = true;
return new CompoundCommand(commands); return new CompoundCommand(commands);
} }
} }
if(operation instanceof MoveFileOperation) if(operation instanceof MoveFileOperation)
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.info("Tracking rename: " + operation); logger.info("Tracking rename: " + operation);
} }
MoveFileOperation r = (MoveFileOperation)operation; MoveFileOperation r = (MoveFileOperation)operation;
// Now see if this rename makes a pair // Now see if this rename makes a pair
if(fileMiddle.equalsIgnoreCase(r.getTo())) if(fileMiddle.equalsIgnoreCase(r.getTo()))
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Got second rename" ); logger.debug("Got second rename" );
} }
fileFrom = r.getFrom(); fileFrom = r.getFrom();
/** /**
* This shuffle reverses the rename out of the way and then copies the * This shuffle reverses the rename out of the way and then copies the
* content only. Finally it moves the temp file into place for the subsequent * content only. Finally it moves the temp file into place for the subsequent
* delete. * delete.
* a) Rename Z to Y (Reverse previous move) * a) Rename Z to Y (Reverse previous move)
* b) Copy Content from X to Y * b) Copy Content from X to Y
* c) Rename X to Z (move temp file out to old location) * c) Rename X to Z (move temp file out to old location)
*/ */
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Go and shuffle! fromName:" + fileFrom + " middle: " + fileMiddle + " end: " + fileEnd); logger.debug("Go and shuffle! fromName:" + fileFrom + " middle: " + fileMiddle + " end: " + fileEnd);
} }
String[] paths = FileName.splitPath(r.getFromPath()); String[] paths = FileName.splitPath(r.getFromPath());
String oldFolder = paths[0]; String oldFolder = paths[0];
ArrayList<Command> commands = new ArrayList<Command>(); ArrayList<Command> commands = new ArrayList<Command>();
RenameFileCommand r1 = new RenameFileCommand(fileEnd, fileMiddle, r.getRootNodeRef(), folderEnd + "\\" + fileEnd, folderMiddle + "\\" + fileMiddle); RenameFileCommand r1 = new RenameFileCommand(fileEnd, fileMiddle, r.getRootNodeRef(), folderEnd + "\\" + fileEnd, folderMiddle + "\\" + fileMiddle);
commands.add(r1); commands.add(r1);
CopyContentCommand copyContent = new CopyContentCommand(fileFrom, fileMiddle, r.getRootNodeRef(), oldFolder + "\\" + fileFrom, folderMiddle + "\\" + fileMiddle); CopyContentCommand copyContent = new CopyContentCommand(fileFrom, fileMiddle, r.getRootNodeRef(), oldFolder + "\\" + fileFrom, folderMiddle + "\\" + fileMiddle);
commands.add(copyContent); commands.add(copyContent);
if(deleteBackup) if(deleteBackup)
{ {
logger.debug("deleteBackup option turned on"); logger.debug("deleteBackup option turned on");
DeleteFileCommand d1 = new DeleteFileCommand(oldFolder, r.getRootNodeRef(), oldFolder + "\\" + fileFrom); DeleteFileCommand d1 = new DeleteFileCommand(oldFolder, r.getRootNodeRef(), oldFolder + "\\" + fileFrom);
commands.add(d1); commands.add(d1);
} }
else else
{ {
MoveFileCommand m1 = new MoveFileCommand(fileFrom, fileEnd, r.getRootNodeRef(), oldFolder + "\\" + fileFrom, folderEnd + "\\" + fileEnd, isMoveAsSystem()); MoveFileCommand m1 = new MoveFileCommand(fileFrom, fileEnd, r.getRootNodeRef(), oldFolder + "\\" + fileFrom, folderEnd + "\\" + fileEnd, isMoveAsSystem());
commands.add(m1); commands.add(m1);
} }
/** /**
* TODO - we may need to copy a new node for the backup and delete the temp node. * TODO - we may need to copy a new node for the backup and delete the temp node.
* It depends if we care about the contents of the Backup file. * It depends if we care about the contents of the Backup file.
*/ */
isComplete = true; isComplete = true;
return new CompoundCommand(commands); return new CompoundCommand(commands);
} }
else else
{ {
if ((interimPattern != null)) if ((interimPattern != null))
{ {
// ALF-16257: temporary Word file moved from .TemporaryItems // ALF-16257: temporary Word file moved from .TemporaryItems
Matcher m = interimPattern.matcher(r.getFromPath()); Matcher m = interimPattern.matcher(r.getFromPath());
if(m.matches() && r.getFrom().equals(r.getTo())) if(m.matches() && r.getFrom().equals(r.getTo()))
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Got system move from temporary folder: " + r.getFrom() + " to " + r.getToPath()); logger.debug("Got system move from temporary folder: " + r.getFrom() + " to " + r.getToPath());
} }
return new MoveFileCommand(r.getFrom(), r.getTo(), r.getRootNodeRef(), r.getFromPath(), r.getToPath(), true); return new MoveFileCommand(r.getFrom(), r.getTo(), r.getRootNodeRef(), r.getFromPath(), r.getToPath(), true);
} }
} }
} }
} }
break; break;
} }
return null; return null;
} }
public boolean isMoveAsSystem() public boolean isMoveAsSystem()
{ {
return moveAsSystem; return moveAsSystem;
} }
public void setMoveAsSystem(boolean moveAsSystem) public void setMoveAsSystem(boolean moveAsSystem)
{ {
this.moveAsSystem = moveAsSystem; this.moveAsSystem = moveAsSystem;
} }
@Override @Override
public boolean isComplete() public boolean isComplete()
{ {
return isComplete; return isComplete;
} }
@Override @Override
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public String toString() public String toString()
{ {
return "ScenarioDoubleRename:" + fileMiddle; return "ScenarioDoubleRename:" + fileMiddle;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
public void setDeleteBackup(boolean deleteBackup) public void setDeleteBackup(boolean deleteBackup)
{ {
this.deleteBackup = deleteBackup; this.deleteBackup = deleteBackup;
} }
public boolean isDeleteBackup() public boolean isDeleteBackup()
{ {
return deleteBackup; return deleteBackup;
} }
public void setInterimPattern(Pattern interimPattern) public void setInterimPattern(Pattern interimPattern)
{ {
this.interimPattern = interimPattern; this.interimPattern = interimPattern;
} }
} }

View File

@@ -1,40 +1,40 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
/** /**
* A scenario instance is an active scenario. It has a ranking, an * A scenario instance is an active scenario. It has a ranking, an
* evaluate method and knows whether it is complete. * evaluate method and knows whether it is complete.
* <p> * <p>
* The evaluate method is called repeatedly as operations are processed. * The evaluate method is called repeatedly as operations are processed.
*/ */
public interface ScenarioInstance public interface ScenarioInstance
{ {
enum Ranking enum Ranking
{ {
LOW, // Bottom priority LOW, // Bottom priority
MEDIUM, MEDIUM,
HIGH, HIGH,
}; };
/** /**
* Get the Ranking * Get the Ranking
* @return Ranking * @return Ranking
*/ */
public Ranking getRanking(); public Ranking getRanking();
/** /**
* evaluate the scenario against the current operation * evaluate the scenario against the current operation
* *
* @param operation Operation * @param operation Operation
*/ */
public Command evaluate(Operation operation); public Command evaluate(Operation operation);
/** /**
* Is the scenario complete? * Is the scenario complete?
* *
* @return boolean * @return boolean
*/ */
public boolean isComplete(); public boolean isComplete();
} }

View File

@@ -1,19 +1,19 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
/** /**
* The scenario instance wants to be notified about rename. * The scenario instance wants to be notified about rename.
* *
* @author mrogers * @author mrogers
* *
*/ */
public interface ScenarioInstanceRenameAware public interface ScenarioInstanceRenameAware
{ {
/** /**
* Notify the scenario of a successful rename operation. * Notify the scenario of a successful rename operation.
* *
* @param operation * @param operation
* @param command * @param command
*/ */
public void notifyRename(Operation operation, Command command); public void notifyRename(Operation operation, Command command);
} }

View File

@@ -1,163 +1,163 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
import org.alfresco.filesys.repo.rules.operations.CreateFileOperation; import org.alfresco.filesys.repo.rules.operations.CreateFileOperation;
import org.alfresco.filesys.repo.rules.operations.OpenFileOperation; import org.alfresco.filesys.repo.rules.operations.OpenFileOperation;
import org.alfresco.filesys.repo.rules.operations.RenameFileOperation; import org.alfresco.filesys.repo.rules.operations.RenameFileOperation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* The Open File Scenario is a sequence of multiple openFile operations * The Open File Scenario is a sequence of multiple openFile operations
* *
* Only on the last close does the repo get closed. Open Files in the middle * Only on the last close does the repo get closed. Open Files in the middle
* share the same file handle. * share the same file handle.
* *
* For example: * For example:
* *
* 1) open(readOnly) * 1) open(readOnly)
* 2) open(readWrite) * 2) open(readWrite)
* 3) open(readOnly) - does nothing. * 3) open(readOnly) - does nothing.
* 4) close - does nothing * 4) close - does nothing
* 5) close - does nothing * 5) close - does nothing
* 6) close - updates the repo * 6) close - updates the repo
*/ */
public class ScenarioOpenFile implements Scenario public class ScenarioOpenFile implements Scenario
{ {
private static Log logger = LogFactory.getLog(ScenarioOpenFile.class); private static Log logger = LogFactory.getLog(ScenarioOpenFile.class);
private String pattern; private String pattern;
private long timeout = 300000; private long timeout = 300000;
@Override @Override
public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation) public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation)
{ {
/** /**
* This scenario is triggered by an open or create of a new file * This scenario is triggered by an open or create of a new file
*/ */
if(operation instanceof CreateFileOperation) if(operation instanceof CreateFileOperation)
{ {
CreateFileOperation c = (CreateFileOperation)operation; CreateFileOperation c = (CreateFileOperation)operation;
if(c.getName() == null) if(c.getName() == null)
{ {
logger.debug("c.getName is null! - scenario not active"); logger.debug("c.getName is null! - scenario not active");
return null; return null;
} }
if(c.getName().matches(pattern)) if(c.getName().matches(pattern))
{ {
if(checkScenarioActive(c.getName(),ctx.getScenarioInstances())) if(checkScenarioActive(c.getName(),ctx.getScenarioInstances()))
{ {
logger.debug("scenario already active for name" + c.getName()); logger.debug("scenario already active for name" + c.getName());
return null; return null;
} }
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("New Open File Instance for CreateFileOperation:" + c); logger.debug("New Open File Instance for CreateFileOperation:" + c);
} }
ScenarioOpenFileInstance instance = new ScenarioOpenFileInstance(); ScenarioOpenFileInstance instance = new ScenarioOpenFileInstance();
instance.setTimeout(timeout); instance.setTimeout(timeout);
instance.setRanking(ranking); instance.setRanking(ranking);
return instance; return instance;
} }
} }
if(operation instanceof OpenFileOperation) if(operation instanceof OpenFileOperation)
{ {
OpenFileOperation o = (OpenFileOperation)operation; OpenFileOperation o = (OpenFileOperation)operation;
if(o.getName() == null) if(o.getName() == null)
{ {
logger.debug("o.getName is null! - scenario not active"); logger.debug("o.getName is null! - scenario not active");
return null; return null;
} }
if(o.getName().matches(pattern)) if(o.getName().matches(pattern))
{ {
if(checkScenarioActive(o.getName(),ctx.getScenarioInstances())) if(checkScenarioActive(o.getName(),ctx.getScenarioInstances()))
{ {
logger.debug("scenario already active for name" + o.getName()); logger.debug("scenario already active for name" + o.getName());
return null; return null;
} }
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("New Open File Instance for OpenFileOperation:" + o); logger.debug("New Open File Instance for OpenFileOperation:" + o);
} }
ScenarioOpenFileInstance instance = new ScenarioOpenFileInstance(); ScenarioOpenFileInstance instance = new ScenarioOpenFileInstance();
instance.setTimeout(timeout); instance.setTimeout(timeout);
instance.setRanking(ranking); instance.setRanking(ranking);
return instance; return instance;
} }
} }
// No not interested. // No not interested.
return null; return null;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
public void setPattern(String pattern) public void setPattern(String pattern)
{ {
this.pattern = pattern; this.pattern = pattern;
} }
public String getPattern() public String getPattern()
{ {
return pattern; return pattern;
} }
private Ranking ranking = Ranking.HIGH; private Ranking ranking = Ranking.HIGH;
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
/** /**
* Check whether there is already an instance of the ScenarioOpenFile for the file * Check whether there is already an instance of the ScenarioOpenFile for the file
*/ */
private boolean checkScenarioActive(String name, final List<ScenarioInstance> currentInstances) private boolean checkScenarioActive(String name, final List<ScenarioInstance> currentInstances)
{ {
for(ScenarioInstance instance: currentInstances) for(ScenarioInstance instance: currentInstances)
{ {
if(instance instanceof ScenarioOpenFileInstance) if(instance instanceof ScenarioOpenFileInstance)
{ {
ScenarioOpenFileInstance i = (ScenarioOpenFileInstance)instance; ScenarioOpenFileInstance i = (ScenarioOpenFileInstance)instance;
if(i.getName() != null && name != null) if(i.getName() != null && name != null)
{ {
if(i.getName().equalsIgnoreCase(name)) if(i.getName().equalsIgnoreCase(name))
{ {
return true; return true;
} }
} }
} }
} }
return false; return false;
} }
} }

View File

@@ -1,88 +1,88 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
import org.alfresco.filesys.repo.rules.operations.RenameFileOperation; import org.alfresco.filesys.repo.rules.operations.RenameFileOperation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
public class ScenarioRenameCreateShuffle implements Scenario public class ScenarioRenameCreateShuffle implements Scenario
{ {
private static Log logger = LogFactory.getLog(ScenarioRenameCreateShuffle.class); private static Log logger = LogFactory.getLog(ScenarioRenameCreateShuffle.class);
/** /**
* The regex pattern of a create that will trigger a new instance of * The regex pattern of a create that will trigger a new instance of
* the scenario. * the scenario.
*/ */
private Pattern pattern; private Pattern pattern;
private String strPattern; private String strPattern;
private long timeout = 30000; private long timeout = 30000;
@Override @Override
public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation) public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation)
{ {
/** /**
* This scenario is triggered by a rename of a file matching * This scenario is triggered by a rename of a file matching
* the pattern * the pattern
*/ */
if(operation instanceof RenameFileOperation) if(operation instanceof RenameFileOperation)
{ {
RenameFileOperation r = (RenameFileOperation)operation; RenameFileOperation r = (RenameFileOperation)operation;
Matcher m = pattern.matcher(r.getTo()); Matcher m = pattern.matcher(r.getTo());
if(m.matches()) if(m.matches())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("New Scenario Rename Shuffle Create Instance strPattern:" + pattern); logger.debug("New Scenario Rename Shuffle Create Instance strPattern:" + pattern);
} }
ScenarioRenameCreateShuffleInstance instance = new ScenarioRenameCreateShuffleInstance(); ScenarioRenameCreateShuffleInstance instance = new ScenarioRenameCreateShuffleInstance();
instance.setTimeout(timeout); instance.setTimeout(timeout);
instance.setRanking(ranking); instance.setRanking(ranking);
return instance; return instance;
} }
} }
// No not interested. // No not interested.
return null; return null;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
public void setPattern(String pattern) public void setPattern(String pattern)
{ {
this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
this.strPattern = pattern; this.strPattern = pattern;
} }
public String getPattern() public String getPattern()
{ {
return strPattern; return strPattern;
} }
private Ranking ranking = Ranking.HIGH; private Ranking ranking = Ranking.HIGH;
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
} }

View File

@@ -1,130 +1,130 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
import org.alfresco.filesys.repo.rules.commands.CompoundCommand; import org.alfresco.filesys.repo.rules.commands.CompoundCommand;
import org.alfresco.filesys.repo.rules.commands.CopyContentCommand; import org.alfresco.filesys.repo.rules.commands.CopyContentCommand;
import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand; import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand;
import org.alfresco.filesys.repo.rules.commands.RenameFileCommand; import org.alfresco.filesys.repo.rules.commands.RenameFileCommand;
import org.alfresco.filesys.repo.rules.commands.SoftRenameFileCommand; import org.alfresco.filesys.repo.rules.commands.SoftRenameFileCommand;
import org.alfresco.filesys.repo.rules.operations.CreateFileOperation; import org.alfresco.filesys.repo.rules.operations.CreateFileOperation;
import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation; import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation;
import org.alfresco.filesys.repo.rules.operations.RenameFileOperation; import org.alfresco.filesys.repo.rules.operations.RenameFileOperation;
import org.alfresco.jlan.server.filesys.FileName; import org.alfresco.jlan.server.filesys.FileName;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* A rename create scenario is ... * A rename create scenario is ...
* *
* a) Rename File to File~ * a) Rename File to File~
* b) Create File * b) Create File
* *
* This rule will kick in and copy the content and then switch the two file over. * This rule will kick in and copy the content and then switch the two file over.
* *
*/ */
class ScenarioRenameCreateShuffleInstance implements ScenarioInstance class ScenarioRenameCreateShuffleInstance implements ScenarioInstance
{ {
private static Log logger = LogFactory.getLog(ScenarioRenameShuffleInstance.class); private static Log logger = LogFactory.getLog(ScenarioRenameShuffleInstance.class);
private Date startTime = new Date(); private Date startTime = new Date();
/** /**
* Timeout in ms. Default 30 seconds. * Timeout in ms. Default 30 seconds.
*/ */
private long timeout = 30000; private long timeout = 30000;
private boolean isComplete = false; private boolean isComplete = false;
private Ranking ranking = Ranking.HIGH; private Ranking ranking = Ranking.HIGH;
enum InternalState enum InternalState
{ {
NONE, NONE,
INITIALISED, INITIALISED,
LOOK_FOR_DELETE LOOK_FOR_DELETE
} ; } ;
InternalState state = InternalState.NONE; InternalState state = InternalState.NONE;
String from; String from;
String to; String to;
/** /**
* Evaluate the next operation * Evaluate the next operation
* @param operation * @param operation
*/ */
public Command evaluate(Operation operation) public Command evaluate(Operation operation)
{ {
/** /**
* Anti-pattern : timeout * Anti-pattern : timeout
*/ */
Date now = new Date(); Date now = new Date();
if(now.getTime() > startTime.getTime() + getTimeout()) if(now.getTime() > startTime.getTime() + getTimeout())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Instance timed out"); logger.debug("Instance timed out");
} }
isComplete = true; isComplete = true;
return null; return null;
} }
switch (state) switch (state)
{ {
case NONE: case NONE:
if(operation instanceof RenameFileOperation) if(operation instanceof RenameFileOperation)
{ {
logger.debug("New scenario initialised"); logger.debug("New scenario initialised");
RenameFileOperation r = (RenameFileOperation)operation; RenameFileOperation r = (RenameFileOperation)operation;
this.from = r.getFrom(); this.from = r.getFrom();
this.to = r.getTo(); this.to = r.getTo();
state = InternalState.INITIALISED; state = InternalState.INITIALISED;
SoftRenameFileCommand r1 = new SoftRenameFileCommand(from, to, r.getRootNodeRef(), r.getFromPath(), r.getToPath()); SoftRenameFileCommand r1 = new SoftRenameFileCommand(from, to, r.getRootNodeRef(), r.getFromPath(), r.getToPath());
isComplete = true; isComplete = true;
return r1; return r1;
} }
break; break;
} }
return null; return null;
} }
@Override @Override
public boolean isComplete() public boolean isComplete()
{ {
return isComplete; return isComplete;
} }
public String toString() public String toString()
{ {
return "ScenarioRenameCreateShuffleInstance from:" + from + " to:" + to; return "ScenarioRenameCreateShuffleInstance from:" + from + " to:" + to;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
@Override @Override
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
} }

View File

@@ -1,97 +1,97 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
import org.alfresco.filesys.repo.rules.operations.RenameFileOperation; import org.alfresco.filesys.repo.rules.operations.RenameFileOperation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* The "Vi" rename shuffle is a sequence where a file is moved out of the way * The "Vi" rename shuffle is a sequence where a file is moved out of the way
* and then a new copy of the file put into place. * and then a new copy of the file put into place.
* *
* a) Rename File to File~ * a) Rename File to File~
* b) Create File * b) Create File
* c) Delete File~ * c) Delete File~
* *
*/ */
public class ScenarioRenameShuffle implements Scenario public class ScenarioRenameShuffle implements Scenario
{ {
private static Log logger = LogFactory.getLog(ScenarioRenameShuffle.class); private static Log logger = LogFactory.getLog(ScenarioRenameShuffle.class);
/** /**
* The regex pattern of a create that will trigger a new instance of * The regex pattern of a create that will trigger a new instance of
* the scenario. * the scenario.
*/ */
private Pattern pattern; private Pattern pattern;
private String strPattern; private String strPattern;
private long timeout = 30000; private long timeout = 30000;
@Override @Override
public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation) public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation)
{ {
/** /**
* This scenario is triggered by a rename of a file matching * This scenario is triggered by a rename of a file matching
* the pattern * the pattern
*/ */
if(operation instanceof RenameFileOperation) if(operation instanceof RenameFileOperation)
{ {
RenameFileOperation r = (RenameFileOperation)operation; RenameFileOperation r = (RenameFileOperation)operation;
Matcher m = pattern.matcher(r.getTo()); Matcher m = pattern.matcher(r.getTo());
if(m.matches()) if(m.matches())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("New Scenario Rename Shuffle Instance strPattern:" + pattern); logger.debug("New Scenario Rename Shuffle Instance strPattern:" + pattern);
} }
ScenarioRenameShuffleInstance instance = new ScenarioRenameShuffleInstance(); ScenarioRenameShuffleInstance instance = new ScenarioRenameShuffleInstance();
instance.setTimeout(timeout); instance.setTimeout(timeout);
instance.setRanking(ranking); instance.setRanking(ranking);
return instance; return instance;
} }
} }
// No not interested. // No not interested.
return null; return null;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
public void setPattern(String pattern) public void setPattern(String pattern)
{ {
this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
this.strPattern = pattern; this.strPattern = pattern;
} }
public String getPattern() public String getPattern()
{ {
return strPattern; return strPattern;
} }
private Ranking ranking = Ranking.HIGH; private Ranking ranking = Ranking.HIGH;
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
} }

View File

@@ -1,172 +1,172 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
import org.alfresco.filesys.repo.rules.commands.CompoundCommand; import org.alfresco.filesys.repo.rules.commands.CompoundCommand;
import org.alfresco.filesys.repo.rules.commands.CopyContentCommand; import org.alfresco.filesys.repo.rules.commands.CopyContentCommand;
import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand; import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand;
import org.alfresco.filesys.repo.rules.commands.RenameFileCommand; import org.alfresco.filesys.repo.rules.commands.RenameFileCommand;
import org.alfresco.filesys.repo.rules.operations.CreateFileOperation; import org.alfresco.filesys.repo.rules.operations.CreateFileOperation;
import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation; import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation;
import org.alfresco.filesys.repo.rules.operations.RenameFileOperation; import org.alfresco.filesys.repo.rules.operations.RenameFileOperation;
import org.alfresco.jlan.server.filesys.FileName; import org.alfresco.jlan.server.filesys.FileName;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* A rename scenario is ... * A rename scenario is ...
* *
* a) Rename File to File~ * a) Rename File to File~
* b) Create File * b) Create File
* c) Delete File~ * c) Delete File~
* *
* This rule will kick in and copy the content and then switch the two file over. * This rule will kick in and copy the content and then switch the two file over.
* *
*/ */
class ScenarioRenameShuffleInstance implements ScenarioInstance class ScenarioRenameShuffleInstance implements ScenarioInstance
{ {
private static Log logger = LogFactory.getLog(ScenarioRenameShuffleInstance.class); private static Log logger = LogFactory.getLog(ScenarioRenameShuffleInstance.class);
private Date startTime = new Date(); private Date startTime = new Date();
/** /**
* Timeout in ms. Default 30 seconds. * Timeout in ms. Default 30 seconds.
*/ */
private long timeout = 30000; private long timeout = 30000;
private boolean isComplete = false; private boolean isComplete = false;
private Ranking ranking = Ranking.HIGH; private Ranking ranking = Ranking.HIGH;
enum InternalState enum InternalState
{ {
NONE, NONE,
INITIALISED, INITIALISED,
LOOK_FOR_DELETE LOOK_FOR_DELETE
} ; } ;
InternalState state = InternalState.NONE; InternalState state = InternalState.NONE;
String from; String from;
String to; String to;
/** /**
* Evaluate the next operation * Evaluate the next operation
* @param operation Operation * @param operation Operation
*/ */
public Command evaluate(Operation operation) public Command evaluate(Operation operation)
{ {
/** /**
* Anti-pattern : timeout * Anti-pattern : timeout
*/ */
Date now = new Date(); Date now = new Date();
if(now.getTime() > startTime.getTime() + getTimeout()) if(now.getTime() > startTime.getTime() + getTimeout())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Instance timed out"); logger.debug("Instance timed out");
} }
isComplete = true; isComplete = true;
return null; return null;
} }
switch (state) switch (state)
{ {
case NONE: case NONE:
if(operation instanceof RenameFileOperation) if(operation instanceof RenameFileOperation)
{ {
logger.debug("New scenario initialised"); logger.debug("New scenario initialised");
RenameFileOperation r = (RenameFileOperation)operation; RenameFileOperation r = (RenameFileOperation)operation;
this.from = r.getFrom(); this.from = r.getFrom();
this.to = r.getTo(); this.to = r.getTo();
state = InternalState.INITIALISED; state = InternalState.INITIALISED;
} }
break; break;
case INITIALISED: case INITIALISED:
if(operation instanceof CreateFileOperation) if(operation instanceof CreateFileOperation)
{ {
CreateFileOperation c = (CreateFileOperation)operation; CreateFileOperation c = (CreateFileOperation)operation;
if(from.equals(c.getName())) if(from.equals(c.getName()))
{ {
logger.debug("transition to LOOK_FOR_DELETE"); logger.debug("transition to LOOK_FOR_DELETE");
state = InternalState.LOOK_FOR_DELETE; state = InternalState.LOOK_FOR_DELETE;
} }
} }
break; break;
case LOOK_FOR_DELETE: case LOOK_FOR_DELETE:
if(operation instanceof DeleteFileOperation) if(operation instanceof DeleteFileOperation)
{ {
DeleteFileOperation d = (DeleteFileOperation)operation; DeleteFileOperation d = (DeleteFileOperation)operation;
if(to.equals(d.getName())) if(to.equals(d.getName()))
{ {
logger.debug("Rename shuffle complete - fire!"); logger.debug("Rename shuffle complete - fire!");
String[] paths = FileName.splitPath(d.getPath()); String[] paths = FileName.splitPath(d.getPath());
String oldFolder = paths[0]; String oldFolder = paths[0];
/** /**
* Shuffle is as follows * Shuffle is as follows
* a) Copy content from File to File~ * a) Copy content from File to File~
* b) Delete File * b) Delete File
* c) Rename File~ to File * c) Rename File~ to File
*/ */
ArrayList<Command> commands = new ArrayList<Command>(); ArrayList<Command> commands = new ArrayList<Command>();
CopyContentCommand copyContent = new CopyContentCommand(from, to, d.getRootNodeRef(), oldFolder + "\\" + from, oldFolder + "\\" + to); CopyContentCommand copyContent = new CopyContentCommand(from, to, d.getRootNodeRef(), oldFolder + "\\" + from, oldFolder + "\\" + to);
RenameFileCommand r1 = new RenameFileCommand(to, from, d.getRootNodeRef(), oldFolder + "\\" + to, oldFolder + "\\" + from); RenameFileCommand r1 = new RenameFileCommand(to, from, d.getRootNodeRef(), oldFolder + "\\" + to, oldFolder + "\\" + from);
DeleteFileCommand d1 = new DeleteFileCommand(from, d.getRootNodeRef(), oldFolder + "\\" + from); DeleteFileCommand d1 = new DeleteFileCommand(from, d.getRootNodeRef(), oldFolder + "\\" + from);
commands.add(copyContent); commands.add(copyContent);
commands.add(d1); commands.add(d1);
commands.add(r1); commands.add(r1);
logger.debug("Scenario complete"); logger.debug("Scenario complete");
isComplete = true; isComplete = true;
return new CompoundCommand(commands); return new CompoundCommand(commands);
} }
} }
} }
return null; return null;
} }
@Override @Override
public boolean isComplete() public boolean isComplete()
{ {
return isComplete; return isComplete;
} }
public String toString() public String toString()
{ {
return "ScenarioRenameShuffleInstance from:" + from + " to:" + to; return "ScenarioRenameShuffleInstance from:" + from + " to:" + to;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
@Override @Override
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
} }

View File

@@ -1,14 +1,14 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
public class ScenarioResult public class ScenarioResult
{ {
public ScenarioResult(ScenarioInstance scenario, Command command) public ScenarioResult(ScenarioInstance scenario, Command command)
{ {
this.scenario = scenario; this.scenario = scenario;
this.command = command; this.command = command;
} }
ScenarioInstance scenario; ScenarioInstance scenario;
Command command; Command command;
}; };

View File

@@ -1,43 +1,43 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.List; import java.util.List;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
/** /**
* The Bog Standard Instance. This always executes. * The Bog Standard Instance. This always executes.
* *
* @author mrogers * @author mrogers
*/ */
public class ScenarioSimpleNonBuffered implements Scenario public class ScenarioSimpleNonBuffered implements Scenario
{ {
private ScenarioSimpleNonBufferedInstance instance = new ScenarioSimpleNonBufferedInstance(); private ScenarioSimpleNonBufferedInstance instance = new ScenarioSimpleNonBufferedInstance();
private Ranking ranking = Ranking.LOW; private Ranking ranking = Ranking.LOW;
@Override @Override
public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation) public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation)
{ {
/** /**
* The bog standard scenario is always interested. * The bog standard scenario is always interested.
*/ */
return instance; return instance;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
instance.setRanking(ranking); instance.setRanking(ranking);
} }
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
public String toString() public String toString()
{ {
return "ScenarioSimpleNonBuffered - default instance"; return "ScenarioSimpleNonBuffered - default instance";
} }
} }

View File

@@ -1,118 +1,118 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.ArrayList; import java.util.ArrayList;
import org.alfresco.filesys.repo.TempNetworkFile; import org.alfresco.filesys.repo.TempNetworkFile;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
import org.alfresco.filesys.repo.rules.commands.CloseFileCommand; import org.alfresco.filesys.repo.rules.commands.CloseFileCommand;
import org.alfresco.filesys.repo.rules.commands.CompoundCommand; import org.alfresco.filesys.repo.rules.commands.CompoundCommand;
import org.alfresco.filesys.repo.rules.commands.CopyContentCommand; import org.alfresco.filesys.repo.rules.commands.CopyContentCommand;
import org.alfresco.filesys.repo.rules.commands.CreateFileCommand; import org.alfresco.filesys.repo.rules.commands.CreateFileCommand;
import org.alfresco.filesys.repo.rules.commands.DoNothingCommand; import org.alfresco.filesys.repo.rules.commands.DoNothingCommand;
import org.alfresco.filesys.repo.rules.commands.MoveFileCommand; import org.alfresco.filesys.repo.rules.commands.MoveFileCommand;
import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand; import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand;
import org.alfresco.filesys.repo.rules.commands.OpenFileCommand; import org.alfresco.filesys.repo.rules.commands.OpenFileCommand;
import org.alfresco.filesys.repo.rules.commands.ReduceQuotaCommand; import org.alfresco.filesys.repo.rules.commands.ReduceQuotaCommand;
import org.alfresco.filesys.repo.rules.commands.RemoveNoContentFileOnError; import org.alfresco.filesys.repo.rules.commands.RemoveNoContentFileOnError;
import org.alfresco.filesys.repo.rules.commands.RemoveTempFileCommand; import org.alfresco.filesys.repo.rules.commands.RemoveTempFileCommand;
import org.alfresco.filesys.repo.rules.commands.RenameFileCommand; import org.alfresco.filesys.repo.rules.commands.RenameFileCommand;
import org.alfresco.filesys.repo.rules.operations.CloseFileOperation; import org.alfresco.filesys.repo.rules.operations.CloseFileOperation;
import org.alfresco.filesys.repo.rules.operations.CreateFileOperation; import org.alfresco.filesys.repo.rules.operations.CreateFileOperation;
import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation; import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation;
import org.alfresco.filesys.repo.rules.operations.MoveFileOperation; import org.alfresco.filesys.repo.rules.operations.MoveFileOperation;
import org.alfresco.filesys.repo.rules.operations.OpenFileOperation; import org.alfresco.filesys.repo.rules.operations.OpenFileOperation;
import org.alfresco.filesys.repo.rules.operations.RenameFileOperation; import org.alfresco.filesys.repo.rules.operations.RenameFileOperation;
import org.alfresco.jlan.server.filesys.NetworkFile; import org.alfresco.jlan.server.filesys.NetworkFile;
/** /**
* The Simple Standard Scenario is what will be done if no other * The Simple Standard Scenario is what will be done if no other
* scenario intervenes. * scenario intervenes.
*/ */
public class ScenarioSimpleNonBufferedInstance implements ScenarioInstance public class ScenarioSimpleNonBufferedInstance implements ScenarioInstance
{ {
private Ranking ranking = Ranking.LOW; private Ranking ranking = Ranking.LOW;
@Override @Override
public Command evaluate(Operation operation) public Command evaluate(Operation operation)
{ {
if(operation instanceof CreateFileOperation) if(operation instanceof CreateFileOperation)
{ {
CreateFileOperation c = (CreateFileOperation)operation; CreateFileOperation c = (CreateFileOperation)operation;
return new CreateFileCommand(c.getName(), c.getRootNodeRef(), c.getPath(), c.getAllocationSize(), c.isHidden()); return new CreateFileCommand(c.getName(), c.getRootNodeRef(), c.getPath(), c.getAllocationSize(), c.isHidden());
} }
else if(operation instanceof DeleteFileOperation) else if(operation instanceof DeleteFileOperation)
{ {
DeleteFileOperation d = (DeleteFileOperation)operation; DeleteFileOperation d = (DeleteFileOperation)operation;
return new DeleteFileCommand(d.getName(), d.getRootNodeRef(), d.getPath()); return new DeleteFileCommand(d.getName(), d.getRootNodeRef(), d.getPath());
} }
else if(operation instanceof RenameFileOperation) else if(operation instanceof RenameFileOperation)
{ {
RenameFileOperation r = (RenameFileOperation)operation; RenameFileOperation r = (RenameFileOperation)operation;
return new RenameFileCommand(r.getFrom(), r.getTo(), r.getRootNodeRef(), r.getFromPath(), r.getToPath()); return new RenameFileCommand(r.getFrom(), r.getTo(), r.getRootNodeRef(), r.getFromPath(), r.getToPath());
} }
else if(operation instanceof MoveFileOperation) else if(operation instanceof MoveFileOperation)
{ {
MoveFileOperation m = (MoveFileOperation)operation; MoveFileOperation m = (MoveFileOperation)operation;
return new MoveFileCommand(m.getFrom(), m.getTo(), m.getRootNodeRef(), m.getFromPath(), m.getToPath()); return new MoveFileCommand(m.getFrom(), m.getTo(), m.getRootNodeRef(), m.getFromPath(), m.getToPath());
} }
else if(operation instanceof OpenFileOperation) else if(operation instanceof OpenFileOperation)
{ {
OpenFileOperation o = (OpenFileOperation)operation; OpenFileOperation o = (OpenFileOperation)operation;
return new OpenFileCommand(o.getName(), o.getMode(), o.isTruncate(), o.getRootNodeRef(), o.getPath()); return new OpenFileCommand(o.getName(), o.getMode(), o.isTruncate(), o.getRootNodeRef(), o.getPath());
} }
else if(operation instanceof CloseFileOperation) else if(operation instanceof CloseFileOperation)
{ {
CloseFileOperation c = (CloseFileOperation)operation; CloseFileOperation c = (CloseFileOperation)operation;
NetworkFile file = c.getNetworkFile(); NetworkFile file = c.getNetworkFile();
ArrayList<Command> commands = new ArrayList<Command>(); ArrayList<Command> commands = new ArrayList<Command>();
ArrayList<Command> postCommitCommands = new ArrayList<Command>(); ArrayList<Command> postCommitCommands = new ArrayList<Command>();
ArrayList<Command> postErrorCommands = new ArrayList<Command>(); ArrayList<Command> postErrorCommands = new ArrayList<Command>();
commands.add(new CloseFileCommand(c.getName(), file, c.getRootNodeRef(), c.getPath())); commands.add(new CloseFileCommand(c.getName(), file, c.getRootNodeRef(), c.getPath()));
// postErrorCommands.add(new RemoveNoContentFileOnError(c.getName(), c.getRootNodeRef(), c.getPath())); // postErrorCommands.add(new RemoveNoContentFileOnError(c.getName(), c.getRootNodeRef(), c.getPath()));
if(c.isDeleteOnClose()) if(c.isDeleteOnClose())
{ {
postCommitCommands.add(new ReduceQuotaCommand(c.getName(), file, c.getRootNodeRef(), c.getPath())); postCommitCommands.add(new ReduceQuotaCommand(c.getName(), file, c.getRootNodeRef(), c.getPath()));
} }
if (file instanceof TempNetworkFile) if (file instanceof TempNetworkFile)
{ {
postCommitCommands.add(new RemoveTempFileCommand((TempNetworkFile)file)); postCommitCommands.add(new RemoveTempFileCommand((TempNetworkFile)file));
} }
return new CompoundCommand(commands, postCommitCommands, postErrorCommands); return new CompoundCommand(commands, postCommitCommands, postErrorCommands);
} }
else return new DoNothingCommand(); else return new DoNothingCommand();
} }
@Override @Override
public boolean isComplete() public boolean isComplete()
{ {
/** /**
* This instance is always complete * This instance is always complete
*/ */
return true; return true;
} }
@Override @Override
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public String toString() public String toString()
{ {
return "ScenarioSimpleNonBuffered default instance"; return "ScenarioSimpleNonBuffered default instance";
} }
} }

View File

@@ -1,209 +1,209 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking; import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
import org.alfresco.filesys.repo.rules.operations.CreateFileOperation; import org.alfresco.filesys.repo.rules.operations.CreateFileOperation;
import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation; import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation;
import org.alfresco.filesys.repo.rules.operations.MoveFileOperation; import org.alfresco.filesys.repo.rules.operations.MoveFileOperation;
import org.alfresco.jlan.server.filesys.FileName; import org.alfresco.jlan.server.filesys.FileName;
import org.alfresco.util.MaxSizeMap; import org.alfresco.util.MaxSizeMap;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* A temp delete shuffle. * A temp delete shuffle.
* *
* Files are created in a temporary directory * Files are created in a temporary directory
* and then a delete and move. * and then a delete and move.
*/ */
public class ScenarioTempDeleteShuffle implements Scenario public class ScenarioTempDeleteShuffle implements Scenario
{ {
private static Log logger = LogFactory.getLog(ScenarioTempDeleteShuffle.class); private static Log logger = LogFactory.getLog(ScenarioTempDeleteShuffle.class);
protected final static String SCENARIO_KEY = "org.alfresco.filesys.repo.rules.ScenarioTempDeleteShuffle"; protected final static String SCENARIO_KEY = "org.alfresco.filesys.repo.rules.ScenarioTempDeleteShuffle";
/** /**
* The regex pattern of a create that will identify a temporary directory. * The regex pattern of a create that will identify a temporary directory.
*/ */
private Pattern tempDirPattern; private Pattern tempDirPattern;
private String strTempDirPattern; private String strTempDirPattern;
/** /**
* The regex pattern of a create that will trigger a new instance of * The regex pattern of a create that will trigger a new instance of
* the scenario. * the scenario.
*/ */
private Pattern pattern; private Pattern pattern;
private String strPattern; private String strPattern;
private long timeout = 30000; private long timeout = 30000;
private Ranking ranking = Ranking.HIGH; private Ranking ranking = Ranking.HIGH;
@Override @Override
public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation) public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation)
{ {
/** /**
* This scenario is triggered by a delete of a file matching * This scenario is triggered by a delete of a file matching
* the pattern * the pattern
*/ */
if(operation instanceof CreateFileOperation) if(operation instanceof CreateFileOperation)
{ {
CreateFileOperation c = (CreateFileOperation)operation; CreateFileOperation c = (CreateFileOperation)operation;
// check whether file is below .TemporaryItems // check whether file is below .TemporaryItems
String path = c.getPath(); String path = c.getPath();
// if path contains .TemporaryItems // if path contains .TemporaryItems
Matcher d = tempDirPattern.matcher(path); Matcher d = tempDirPattern.matcher(path);
if(d.matches()) if(d.matches())
{ {
logger.debug("pattern matches temp dir folder so this is a new create in a temp dir"); logger.debug("pattern matches temp dir folder so this is a new create in a temp dir");
Matcher m = pattern.matcher(c.getName()); Matcher m = pattern.matcher(c.getName());
if(m.matches()) if(m.matches())
{ {
// and how to lock - since we are already have one lock on the scenarios/folder here // and how to lock - since we are already have one lock on the scenarios/folder here
// this is a potential deadlock and synchronization bottleneck // this is a potential deadlock and synchronization bottleneck
Map<String, String> createdTempFiles = (Map<String,String>)ctx.getSessionState().get(SCENARIO_KEY); Map<String, String> createdTempFiles = (Map<String,String>)ctx.getSessionState().get(SCENARIO_KEY);
if(createdTempFiles == null) if(createdTempFiles == null)
{ {
synchronized(ctx.getSessionState()) synchronized(ctx.getSessionState())
{ {
logger.debug("created new temp file map and added it to the session state"); logger.debug("created new temp file map and added it to the session state");
createdTempFiles = (Map<String,String>)ctx.getSessionState().get(SCENARIO_KEY); createdTempFiles = (Map<String,String>)ctx.getSessionState().get(SCENARIO_KEY);
if(createdTempFiles == null) if(createdTempFiles == null)
{ {
createdTempFiles = Collections.synchronizedMap(new MaxSizeMap<String, String>(5, false)); createdTempFiles = Collections.synchronizedMap(new MaxSizeMap<String, String>(5, false));
ctx.getSessionState().put(SCENARIO_KEY, createdTempFiles); ctx.getSessionState().put(SCENARIO_KEY, createdTempFiles);
} }
} }
} }
createdTempFiles.put(c.getName(), c.getName()); createdTempFiles.put(c.getName(), c.getName());
// TODO - Return a different scenario instance here ??? // TODO - Return a different scenario instance here ???
// So it can time out and have anti-patterns etc? // So it can time out and have anti-patterns etc?
} }
} }
} }
if (operation instanceof MoveFileOperation) if (operation instanceof MoveFileOperation)
{ {
MoveFileOperation mf = (MoveFileOperation)operation; MoveFileOperation mf = (MoveFileOperation)operation;
// check whether file is below .TemporaryItems // check whether file is below .TemporaryItems
String path = mf.getFromPath(); String path = mf.getFromPath();
// if path contains .TemporaryItems // if path contains .TemporaryItems
Matcher d = tempDirPattern.matcher(path); Matcher d = tempDirPattern.matcher(path);
if(d.matches()) if(d.matches())
{ {
logger.debug("pattern matches temp dir folder so this is a new create in a temp dir"); logger.debug("pattern matches temp dir folder so this is a new create in a temp dir");
Matcher m = pattern.matcher(mf.getFrom()); Matcher m = pattern.matcher(mf.getFrom());
if(m.matches()) if(m.matches())
{ {
// and how to lock - since we are already have one lock on the scenarios/folder here // and how to lock - since we are already have one lock on the scenarios/folder here
// this is a potential deadlock and synchronization bottleneck // this is a potential deadlock and synchronization bottleneck
Map<String, String> createdTempFiles = (Map<String,String>)ctx.getSessionState().get(SCENARIO_KEY); Map<String, String> createdTempFiles = (Map<String,String>)ctx.getSessionState().get(SCENARIO_KEY);
if(createdTempFiles == null) if(createdTempFiles == null)
{ {
synchronized(ctx.getSessionState()) synchronized(ctx.getSessionState())
{ {
logger.debug("created new temp file map and added it to the session state"); logger.debug("created new temp file map and added it to the session state");
createdTempFiles = (Map<String,String>)ctx.getSessionState().get(SCENARIO_KEY); createdTempFiles = (Map<String,String>)ctx.getSessionState().get(SCENARIO_KEY);
if(createdTempFiles == null) if(createdTempFiles == null)
{ {
createdTempFiles = Collections.synchronizedMap(new MaxSizeMap<String, String>(5, false)); createdTempFiles = Collections.synchronizedMap(new MaxSizeMap<String, String>(5, false));
ctx.getSessionState().put(SCENARIO_KEY, createdTempFiles); ctx.getSessionState().put(SCENARIO_KEY, createdTempFiles);
} }
} }
} }
createdTempFiles.remove(mf.getFrom()); createdTempFiles.remove(mf.getFrom());
// TODO - Return a different scenario instance here ??? // TODO - Return a different scenario instance here ???
// So it can time out and have anti-patterns etc? // So it can time out and have anti-patterns etc?
} }
} }
} }
if(operation instanceof DeleteFileOperation) if(operation instanceof DeleteFileOperation)
{ {
DeleteFileOperation c = (DeleteFileOperation)operation; DeleteFileOperation c = (DeleteFileOperation)operation;
Matcher m = pattern.matcher(c.getName()); Matcher m = pattern.matcher(c.getName());
if(m.matches()) if(m.matches())
{ {
Map<String, String> createdTempFiles = (Map<String,String>)ctx.getSessionState().get(SCENARIO_KEY); Map<String, String> createdTempFiles = (Map<String,String>)ctx.getSessionState().get(SCENARIO_KEY);
if(createdTempFiles != null) if(createdTempFiles != null)
{ {
if(createdTempFiles.containsKey(c.getName())) if(createdTempFiles.containsKey(c.getName()))
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("New Scenario Temp Delete Shuffle Instance:" + c.getName()); logger.debug("New Scenario Temp Delete Shuffle Instance:" + c.getName());
} }
ScenarioTempDeleteShuffleInstance instance = new ScenarioTempDeleteShuffleInstance() ; ScenarioTempDeleteShuffleInstance instance = new ScenarioTempDeleteShuffleInstance() ;
instance.setTimeout(timeout); instance.setTimeout(timeout);
instance.setRanking(ranking); instance.setRanking(ranking);
return instance; return instance;
} }
} }
} }
} }
// No not interested. // No not interested.
return null; return null;
} }
public void setPattern(String pattern) public void setPattern(String pattern)
{ {
this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
this.strPattern = pattern; this.strPattern = pattern;
} }
public String getPattern() public String getPattern()
{ {
return this.strPattern; return this.strPattern;
} }
public void setTempDirPattern(String tempDirPattern) public void setTempDirPattern(String tempDirPattern)
{ {
this.tempDirPattern = Pattern.compile(tempDirPattern, Pattern.CASE_INSENSITIVE); this.tempDirPattern = Pattern.compile(tempDirPattern, Pattern.CASE_INSENSITIVE);
this.strTempDirPattern = tempDirPattern; this.strTempDirPattern = tempDirPattern;
} }
public String getTempDirPattern() public String getTempDirPattern()
{ {
return this.strTempDirPattern; return this.strTempDirPattern;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
} }

View File

@@ -1,223 +1,223 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.alfresco.filesys.repo.rules.commands.CompoundCommand; import org.alfresco.filesys.repo.rules.commands.CompoundCommand;
import org.alfresco.filesys.repo.rules.commands.CopyContentCommand; import org.alfresco.filesys.repo.rules.commands.CopyContentCommand;
import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand; import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand;
import org.alfresco.filesys.repo.rules.commands.RenameFileCommand; import org.alfresco.filesys.repo.rules.commands.RenameFileCommand;
import org.alfresco.filesys.repo.rules.operations.CreateFileOperation; import org.alfresco.filesys.repo.rules.operations.CreateFileOperation;
import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation; import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation;
import org.alfresco.filesys.repo.rules.operations.MoveFileOperation; import org.alfresco.filesys.repo.rules.operations.MoveFileOperation;
import org.alfresco.filesys.repo.rules.operations.RenameFileOperation; import org.alfresco.filesys.repo.rules.operations.RenameFileOperation;
import org.alfresco.jlan.server.filesys.FileName; import org.alfresco.jlan.server.filesys.FileName;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
/** /**
* This is an instance of a "temp delete shuffle" triggered by a delete of a file matching * This is an instance of a "temp delete shuffle" triggered by a delete of a file matching
* a newly created file in a temporary directory. * a newly created file in a temporary directory.
* *
* <p> First implemented for TextEdit from MacOS Lion * <p> First implemented for TextEdit from MacOS Lion
* *
* <p> * <p>
* Sequence of operations. * Sequence of operations.
* a) Temporary Directory Created * a) Temporary Directory Created
* b) Temporary file created in temporary directory. * b) Temporary file created in temporary directory.
* c) Target file deleted * c) Target file deleted
* d) Temp file moved in place of target file. * d) Temp file moved in place of target file.
* e) Temporary directory deleted. * e) Temporary directory deleted.
* <p> * <p>
* If this filter is active then this is what happens. * If this filter is active then this is what happens.
* a) Temp file created - in another folder. * a) Temp file created - in another folder.
* b) Existing file deleted. Scenario kicks in to rename rather than delete. * b) Existing file deleted. Scenario kicks in to rename rather than delete.
* c) New file moved into place (X to Y). Scenario kicks in * c) New file moved into place (X to Y). Scenario kicks in
* 1) renames file from step c * 1) renames file from step c
* 2) copies content from temp file to target file * 2) copies content from temp file to target file
* 3) deletes temp file. * 3) deletes temp file.
* d) Clean up scenario. * d) Clean up scenario.
*/ */
public class ScenarioTempDeleteShuffleInstance implements ScenarioInstance public class ScenarioTempDeleteShuffleInstance implements ScenarioInstance
{ {
private static Log logger = LogFactory.getLog(ScenarioTempDeleteShuffleInstance.class); private static Log logger = LogFactory.getLog(ScenarioTempDeleteShuffleInstance.class);
enum InternalState enum InternalState
{ {
NONE, NONE,
DELETE_SUBSTITUTED, // Scenario has intervened and renamed rather than delete DELETE_SUBSTITUTED, // Scenario has intervened and renamed rather than delete
MOVED MOVED
} }
InternalState internalState = InternalState.NONE; InternalState internalState = InternalState.NONE;
private Date startTime = new Date(); private Date startTime = new Date();
private String lockName; private String lockName;
private Ranking ranking; private Ranking ranking;
/** /**
* Timeout in ms. Default 30 seconds. * Timeout in ms. Default 30 seconds.
*/ */
private long timeout = 60000; private long timeout = 60000;
private boolean isComplete; private boolean isComplete;
/** /**
* Keep track of deletes that we substitute with a rename * Keep track of deletes that we substitute with a rename
* could be more than one if scenarios overlap * could be more than one if scenarios overlap
* *
* From, TempFileName * From, TempFileName
*/ */
private Map<String, String> deletes = new HashMap<String, String>(); private Map<String, String> deletes = new HashMap<String, String>();
/** /**
* Evaluate the next operation * Evaluate the next operation
* @param operation * @param operation
*/ */
public Command evaluate(Operation operation) public Command evaluate(Operation operation)
{ {
/** /**
* Anti-pattern : timeout * Anti-pattern : timeout
*/ */
Date now = new Date(); Date now = new Date();
if(now.getTime() > startTime.getTime() + getTimeout()) if(now.getTime() > startTime.getTime() + getTimeout())
{ {
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("Instance timed out lockName:" + lockName); logger.debug("Instance timed out lockName:" + lockName);
isComplete = true; isComplete = true;
return null; return null;
} }
} }
switch (internalState) switch (internalState)
{ {
case NONE: case NONE:
/** /**
* Looking for target file being deleted * Looking for target file being deleted
* *
* Need to intervene and replace delete with a rename to temp file. * Need to intervene and replace delete with a rename to temp file.
*/ */
if(operation instanceof DeleteFileOperation) if(operation instanceof DeleteFileOperation)
{ {
DeleteFileOperation d = (DeleteFileOperation)operation; DeleteFileOperation d = (DeleteFileOperation)operation;
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("entering DELETE_SUBSTITUTED state: " + lockName); logger.debug("entering DELETE_SUBSTITUTED state: " + lockName);
} }
String tempName = ".shuffle" + d.getName(); String tempName = ".shuffle" + d.getName();
deletes.put(d.getName(), tempName); deletes.put(d.getName(), tempName);
String[] paths = FileName.splitPath(d.getPath()); String[] paths = FileName.splitPath(d.getPath());
String currentFolder = paths[0]; String currentFolder = paths[0];
RenameFileCommand r1 = new RenameFileCommand(d.getName(), tempName, d.getRootNodeRef(), d.getPath(), currentFolder + "\\" + tempName); RenameFileCommand r1 = new RenameFileCommand(d.getName(), tempName, d.getRootNodeRef(), d.getPath(), currentFolder + "\\" + tempName);
internalState = InternalState.DELETE_SUBSTITUTED; internalState = InternalState.DELETE_SUBSTITUTED;
return r1; return r1;
} }
else else
{ {
// anything else bomb out // anything else bomb out
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug("State error, expected a DELETE"); logger.debug("State error, expected a DELETE");
} }
isComplete = true; isComplete = true;
} }
break; break;
case DELETE_SUBSTITUTED: case DELETE_SUBSTITUTED:
/** /**
* Looking for a move operation of the deleted file * Looking for a move operation of the deleted file
*/ */
if(operation instanceof MoveFileOperation) if(operation instanceof MoveFileOperation)
{ {
MoveFileOperation m = (MoveFileOperation)operation; MoveFileOperation m = (MoveFileOperation)operation;
String targetFile = m.getTo(); String targetFile = m.getTo();
if(deletes.containsKey(targetFile)) if(deletes.containsKey(targetFile))
{ {
String tempName = deletes.get(targetFile); String tempName = deletes.get(targetFile);
String[] paths = FileName.splitPath(m.getToPath()); String[] paths = FileName.splitPath(m.getToPath());
String currentFolder = paths[0]; String currentFolder = paths[0];
/** /**
* This is where the scenario fires. * This is where the scenario fires.
* a) Rename the temp file back to the targetFile * a) Rename the temp file back to the targetFile
* b) Copy content from moved file * b) Copy content from moved file
* c) Delete rather than move file * c) Delete rather than move file
*/ */
logger.debug("scenario fires"); logger.debug("scenario fires");
ArrayList<Command> commands = new ArrayList<Command>(); ArrayList<Command> commands = new ArrayList<Command>();
RenameFileCommand r1 = new RenameFileCommand(tempName, targetFile, m.getRootNodeRef(), currentFolder + "\\" + tempName, m.getToPath()); RenameFileCommand r1 = new RenameFileCommand(tempName, targetFile, m.getRootNodeRef(), currentFolder + "\\" + tempName, m.getToPath());
CopyContentCommand copyContent = new CopyContentCommand(m.getFrom(), targetFile, m.getRootNodeRef(), m.getFromPath(), m.getToPath()); CopyContentCommand copyContent = new CopyContentCommand(m.getFrom(), targetFile, m.getRootNodeRef(), m.getFromPath(), m.getToPath());
DeleteFileCommand d1 = new DeleteFileCommand(m.getFrom(), m.getRootNodeRef(), m.getFromPath()); DeleteFileCommand d1 = new DeleteFileCommand(m.getFrom(), m.getRootNodeRef(), m.getFromPath());
commands.add(r1); commands.add(r1);
commands.add(copyContent); commands.add(copyContent);
commands.add(d1); commands.add(d1);
logger.debug("Scenario complete"); logger.debug("Scenario complete");
isComplete = true; isComplete = true;
return new CompoundCommand(commands); return new CompoundCommand(commands);
} }
} }
} }
return null; return null;
} }
@Override @Override
public boolean isComplete() public boolean isComplete()
{ {
return isComplete; return isComplete;
} }
@Override @Override
public Ranking getRanking() public Ranking getRanking()
{ {
return ranking; return ranking;
} }
public void setRanking(Ranking ranking) public void setRanking(Ranking ranking)
{ {
this.ranking = ranking; this.ranking = ranking;
} }
public String toString() public String toString()
{ {
return "ScenarioTempDeleteShuffleInstance:" + lockName; return "ScenarioTempDeleteShuffleInstance:" + lockName;
} }
public void setTimeout(long timeout) public void setTimeout(long timeout)
{ {
this.timeout = timeout; this.timeout = timeout;
} }
public long getTimeout() public long getTimeout()
{ {
return timeout; return timeout;
} }
} }

View File

@@ -1,6 +1,6 @@
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
public class VirtualFilesystem public class VirtualFilesystem
{ {
} }

View File

@@ -1,22 +1,22 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
/** /**
* Callback command. * Callback command.
* *
* Makes a callback when executed. * Makes a callback when executed.
*/ */
public class CallbackCommand implements Command public class CallbackCommand implements Command
{ {
public CallbackCommand() public CallbackCommand()
{ {
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_NONE; return TxnReadState.TXN_NONE;
} }
} }

View File

@@ -1,52 +1,52 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.jlan.server.filesys.NetworkFile; import org.alfresco.jlan.server.filesys.NetworkFile;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Open File command * Open File command
*/ */
public class CloseFileCommand implements Command public class CloseFileCommand implements Command
{ {
private String name; private String name;
private String path; private String path;
private NodeRef rootNode; private NodeRef rootNode;
private NetworkFile networkFile; private NetworkFile networkFile;
public CloseFileCommand(String name, NetworkFile networkFile, NodeRef rootNode, String path) public CloseFileCommand(String name, NetworkFile networkFile, NodeRef rootNode, String path)
{ {
this.name = name; this.name = name;
this.networkFile = networkFile; this.networkFile = networkFile;
this.rootNode = rootNode; this.rootNode = rootNode;
this.path = path; this.path = path;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public NetworkFile getNetworkFile() public NetworkFile getNetworkFile()
{ {
return networkFile; return networkFile;
} }
public NodeRef getRootNodeRef() public NodeRef getRootNodeRef()
{ {
return rootNode; return rootNode;
} }
public String getPath() public String getPath()
{ {
return path; return path;
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_READ_WRITE; return TxnReadState.TXN_READ_WRITE;
} }
} }

View File

@@ -1,80 +1,80 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
/** /**
* A compound operation contains one or more other commands. * A compound operation contains one or more other commands.
*/ */
public class CompoundCommand implements Command public class CompoundCommand implements Command
{ {
List<Command> commands; List<Command> commands;
List<Command> postCommitCommands; List<Command> postCommitCommands;
List<Command> postErrorCommands; List<Command> postErrorCommands;
/** /**
* New Compound Command containing the specified commands. * New Compound Command containing the specified commands.
* @param commands * @param commands
*/ */
public CompoundCommand(List<Command> commands) public CompoundCommand(List<Command> commands)
{ {
this.commands = new ArrayList<Command>(commands); this.commands = new ArrayList<Command>(commands);
} }
/** /**
* New Compound Command containing the specified commands. * New Compound Command containing the specified commands.
* @param commands * @param commands
*/ */
public CompoundCommand(List<Command> commands, List<Command> postCommitCommands) public CompoundCommand(List<Command> commands, List<Command> postCommitCommands)
{ {
this.commands = new ArrayList<Command>(commands); this.commands = new ArrayList<Command>(commands);
this.postCommitCommands = new ArrayList<Command>(postCommitCommands); this.postCommitCommands = new ArrayList<Command>(postCommitCommands);
} }
public CompoundCommand(List<Command> commands, List<Command> postCommitCommands, List<Command>postErrorCommands) public CompoundCommand(List<Command> commands, List<Command> postCommitCommands, List<Command>postErrorCommands)
{ {
this.commands = new ArrayList<Command>(commands); this.commands = new ArrayList<Command>(commands);
this.postCommitCommands = new ArrayList<Command>(postCommitCommands); this.postCommitCommands = new ArrayList<Command>(postCommitCommands);
this.postErrorCommands = new ArrayList<Command>(postErrorCommands); this.postErrorCommands = new ArrayList<Command>(postErrorCommands);
} }
public List<Command> getCommands() public List<Command> getCommands()
{ {
return commands; return commands;
} }
public List<Command> getPostCommitCommands() public List<Command> getPostCommitCommands()
{ {
return postCommitCommands; return postCommitCommands;
} }
public List<Command> getPostErrorCommands() public List<Command> getPostErrorCommands()
{ {
return postErrorCommands; return postErrorCommands;
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
TxnReadState readState = TxnReadState.TXN_NONE; TxnReadState readState = TxnReadState.TXN_NONE;
for(Command command : commands) for(Command command : commands)
{ {
TxnReadState x = command.getTransactionRequired(); TxnReadState x = command.getTransactionRequired();
if(x != null && x.compareTo(readState) > 0) if(x != null && x.compareTo(readState) > 0)
{ {
readState = x; readState = x;
} }
} }
return readState; return readState;
} }
} }

View File

@@ -1,63 +1,63 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import java.util.List; import java.util.List;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* CopyContent command * CopyContent command
* *
* Copy just the content from one node to another * Copy just the content from one node to another
* *
*/ */
public class CopyContentCommand implements Command public class CopyContentCommand implements Command
{ {
private String from; private String from;
private String to; private String to;
private NodeRef rootNode; private NodeRef rootNode;
private String fromPath; private String fromPath;
private String toPath; private String toPath;
public CopyContentCommand(String from, String to, NodeRef rootNode, String fromPath, String toPath) public CopyContentCommand(String from, String to, NodeRef rootNode, String fromPath, String toPath)
{ {
this.from = from; this.from = from;
this.to = to; this.to = to;
this.rootNode = rootNode; this.rootNode = rootNode;
this.fromPath = fromPath; this.fromPath = fromPath;
this.toPath = toPath; this.toPath = toPath;
} }
public String getTo() public String getTo()
{ {
return from; return from;
} }
public String getFrom() public String getFrom()
{ {
return from; return from;
} }
public NodeRef getRootNode() public NodeRef getRootNode()
{ {
return rootNode; return rootNode;
} }
public String getFromPath() public String getFromPath()
{ {
return fromPath; return fromPath;
} }
public String getToPath() public String getToPath()
{ {
return toPath; return toPath;
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_READ_WRITE; return TxnReadState.TXN_READ_WRITE;
} }
} }

View File

@@ -1,66 +1,66 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import java.util.List; import java.util.List;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* CreateFile command * CreateFile command
*/ */
public class CreateFileCommand implements Command public class CreateFileCommand implements Command
{ {
private String name; private String name;
private NodeRef rootNode; private NodeRef rootNode;
private String path; private String path;
private long allocationSize; private long allocationSize;
private boolean isHidden; private boolean isHidden;
public CreateFileCommand(String name, NodeRef rootNode, String path, long allocationSize, boolean isHidden) public CreateFileCommand(String name, NodeRef rootNode, String path, long allocationSize, boolean isHidden)
{ {
this.name = name; this.name = name;
this.path = path; this.path = path;
this.rootNode = rootNode; this.rootNode = rootNode;
this.allocationSize = allocationSize; this.allocationSize = allocationSize;
this.isHidden = isHidden; this.isHidden = isHidden;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public NodeRef getRootNode() public NodeRef getRootNode()
{ {
return rootNode; return rootNode;
} }
public String getPath() public String getPath()
{ {
return path; return path;
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_READ_WRITE; return TxnReadState.TXN_READ_WRITE;
} }
public void setAllocationSize(long allocationSize) public void setAllocationSize(long allocationSize)
{ {
this.allocationSize = allocationSize; this.allocationSize = allocationSize;
} }
public long getAllocationSize() public long getAllocationSize()
{ {
return allocationSize; return allocationSize;
} }
public boolean isHidden() public boolean isHidden()
{ {
return isHidden; return isHidden;
} }
} }

View File

@@ -1,49 +1,49 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Delete File command * Delete File command
*/ */
public class DeleteFileCommand implements Command public class DeleteFileCommand implements Command
{ {
private String name; private String name;
private NodeRef rootNode; private NodeRef rootNode;
private String path; private String path;
/** /**
* *
* @param name name of file * @param name name of file
* @param rootNode root node * @param rootNode root node
* @param path full path of file * @param path full path of file
*/ */
public DeleteFileCommand(String name, NodeRef rootNode, String path) public DeleteFileCommand(String name, NodeRef rootNode, String path)
{ {
this.name = name; this.name = name;
this.rootNode = rootNode; this.rootNode = rootNode;
this.path = path; this.path = path;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public NodeRef getRootNode() public NodeRef getRootNode()
{ {
return rootNode; return rootNode;
} }
public String getPath() public String getPath()
{ {
return path; return path;
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_READ_WRITE; return TxnReadState.TXN_READ_WRITE;
} }
} }

View File

@@ -1,22 +1,22 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Do Nothing Command, Does what it says on the tin! * Do Nothing Command, Does what it says on the tin!
*/ */
public class DoNothingCommand implements Command public class DoNothingCommand implements Command
{ {
public DoNothingCommand() public DoNothingCommand()
{ {
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_NONE; return TxnReadState.TXN_NONE;
} }
} }

View File

@@ -1,90 +1,90 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
public class MoveFileCommand implements Command public class MoveFileCommand implements Command
{ {
private String from; private String from;
private String to; private String to;
private NodeRef rootNode; private NodeRef rootNode;
private String fromPath; private String fromPath;
private String toPath; private String toPath;
private boolean isMoveAsSystem = false; private boolean isMoveAsSystem = false;
public MoveFileCommand(String from, String to, NodeRef rootNode, String fromPath, String toPath) public MoveFileCommand(String from, String to, NodeRef rootNode, String fromPath, String toPath)
{ {
this.from = from; this.from = from;
this.to = to; this.to = to;
this.rootNode = rootNode; this.rootNode = rootNode;
this.fromPath = fromPath; this.fromPath = fromPath;
this.toPath = toPath; this.toPath = toPath;
} }
// ALF-16257: in shuffle scenarios if user has insufficient permissions rename should be done as System // ALF-16257: in shuffle scenarios if user has insufficient permissions rename should be done as System
public MoveFileCommand(String from, String to, NodeRef rootNode, String fromPath, String toPath, boolean moveAsSystem) public MoveFileCommand(String from, String to, NodeRef rootNode, String fromPath, String toPath, boolean moveAsSystem)
{ {
this(from, to, rootNode, fromPath, toPath); this(from, to, rootNode, fromPath, toPath);
this.isMoveAsSystem = moveAsSystem; this.isMoveAsSystem = moveAsSystem;
} }
public String getFrom() public String getFrom()
{ {
return from; return from;
} }
public String getTo() public String getTo()
{ {
return to; return to;
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_READ_WRITE; return TxnReadState.TXN_READ_WRITE;
} }
public void setRootNode(NodeRef rootNode) public void setRootNode(NodeRef rootNode)
{ {
this.rootNode = rootNode; this.rootNode = rootNode;
} }
public NodeRef getRootNode() public NodeRef getRootNode()
{ {
return rootNode; return rootNode;
} }
public void setFromPath(String fromPath) public void setFromPath(String fromPath)
{ {
this.fromPath = fromPath; this.fromPath = fromPath;
} }
public String getFromPath() public String getFromPath()
{ {
return fromPath; return fromPath;
} }
public void setToPath(String toPath) public void setToPath(String toPath)
{ {
this.toPath = toPath; this.toPath = toPath;
} }
public String getToPath() public String getToPath()
{ {
return toPath; return toPath;
} }
public boolean isMoveAsSystem() public boolean isMoveAsSystem()
{ {
return isMoveAsSystem; return isMoveAsSystem;
} }
} }

View File

@@ -1,68 +1,68 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import java.util.List; import java.util.List;
import org.alfresco.filesys.repo.OpenFileMode; import org.alfresco.filesys.repo.OpenFileMode;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Open File command * Open File command
*/ */
public class OpenFileCommand implements Command public class OpenFileCommand implements Command
{ {
private String name; private String name;
private OpenFileMode mode = OpenFileMode.READ_ONLY; private OpenFileMode mode = OpenFileMode.READ_ONLY;
private boolean truncate = false; private boolean truncate = false;
private String path; private String path;
private NodeRef rootNode; private NodeRef rootNode;
/** /**
* *
* @param name * @param name
* @param mode * @param mode
* @param truncate * @param truncate
* @param rootNode * @param rootNode
* @param path * @param path
*/ */
public OpenFileCommand(String name, OpenFileMode mode, boolean truncate, NodeRef rootNode, String path) public OpenFileCommand(String name, OpenFileMode mode, boolean truncate, NodeRef rootNode, String path)
{ {
this.name = name; this.name = name;
this.mode = mode; this.mode = mode;
this.truncate = truncate; this.truncate = truncate;
this.rootNode = rootNode; this.rootNode = rootNode;
this.path = path; this.path = path;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public String getPath() public String getPath()
{ {
return path; return path;
} }
public NodeRef getRootNodeRef() public NodeRef getRootNodeRef()
{ {
return rootNode; return rootNode;
} }
public OpenFileMode getMode() public OpenFileMode getMode()
{ {
return mode; return mode;
} }
public boolean isTruncate() public boolean isTruncate()
{ {
return truncate; return truncate;
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_READ_ONLY; return TxnReadState.TXN_READ_ONLY;
} }
} }

View File

@@ -1,15 +1,15 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import java.util.List; import java.util.List;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
/** /**
* The post commit command is executed after a successful completion of a command. * The post commit command is executed after a successful completion of a command.
* @author mrogers * @author mrogers
* *
*/ */
public class PostCommitCommand public class PostCommitCommand
{ {
List<Command> commands; List<Command> commands;
} }

View File

@@ -1,51 +1,51 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.jlan.server.filesys.NetworkFile; import org.alfresco.jlan.server.filesys.NetworkFile;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Remove file with CONTENT_NO_ASPECT on error * Remove file with CONTENT_NO_ASPECT on error
*/ */
public class RemoveNoContentFileOnError implements Command public class RemoveNoContentFileOnError implements Command
{ {
private String name; private String name;
private String path; private String path;
private NodeRef rootNode; private NodeRef rootNode;
private NetworkFile networkFile; private NetworkFile networkFile;
public RemoveNoContentFileOnError(String name, NodeRef rootNode, String path) public RemoveNoContentFileOnError(String name, NodeRef rootNode, String path)
{ {
this.name = name; this.name = name;
this.rootNode = rootNode; this.rootNode = rootNode;
this.path = path; this.path = path;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public NetworkFile getNetworkFile() public NetworkFile getNetworkFile()
{ {
return networkFile; return networkFile;
} }
public NodeRef getRootNodeRef() public NodeRef getRootNodeRef()
{ {
return rootNode; return rootNode;
} }
public String getPath() public String getPath()
{ {
return path; return path;
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_NONE; return TxnReadState.TXN_NONE;
} }
} }

View File

@@ -1,32 +1,32 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import org.alfresco.filesys.repo.TempNetworkFile; import org.alfresco.filesys.repo.TempNetworkFile;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.jlan.server.filesys.NetworkFile; import org.alfresco.jlan.server.filesys.NetworkFile;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Remove a temporary file * Remove a temporary file
*/ */
public class RemoveTempFileCommand implements Command public class RemoveTempFileCommand implements Command
{ {
private TempNetworkFile networkFile; private TempNetworkFile networkFile;
public RemoveTempFileCommand(TempNetworkFile file) public RemoveTempFileCommand(TempNetworkFile file)
{ {
this.networkFile = file; this.networkFile = file;
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_NONE; return TxnReadState.TXN_NONE;
} }
public TempNetworkFile getNetworkFile() public TempNetworkFile getNetworkFile()
{ {
return networkFile; return networkFile;
} }
} }

View File

@@ -1,87 +1,87 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Rename command * Rename command
*/ */
public class RenameFileCommand implements Command public class RenameFileCommand implements Command
{ {
private String from; private String from;
private String to; private String to;
private NodeRef rootNode; private NodeRef rootNode;
private String fromPath; private String fromPath;
private String toPath; private String toPath;
private boolean isSoft = false; private boolean isSoft = false;
public RenameFileCommand(String from, String to, NodeRef rootNode, String fromPath, String toPath) public RenameFileCommand(String from, String to, NodeRef rootNode, String fromPath, String toPath)
{ {
this.from = from; this.from = from;
this.to = to; this.to = to;
this.rootNode = rootNode; this.rootNode = rootNode;
this.fromPath = fromPath; this.fromPath = fromPath;
this.toPath = toPath; this.toPath = toPath;
} }
public String getFrom() public String getFrom()
{ {
return from; return from;
} }
public String getTo() public String getTo()
{ {
return to; return to;
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_READ_WRITE; return TxnReadState.TXN_READ_WRITE;
} }
public void setRootNode(NodeRef rootNode) public void setRootNode(NodeRef rootNode)
{ {
this.rootNode = rootNode; this.rootNode = rootNode;
} }
public NodeRef getRootNode() public NodeRef getRootNode()
{ {
return rootNode; return rootNode;
} }
public void setFromPath(String fromPath) public void setFromPath(String fromPath)
{ {
this.fromPath = fromPath; this.fromPath = fromPath;
} }
public String getFromPath() public String getFromPath()
{ {
return fromPath; return fromPath;
} }
public void setToPath(String toPath) public void setToPath(String toPath)
{ {
this.toPath = toPath; this.toPath = toPath;
} }
public String getToPath() public String getToPath()
{ {
return toPath; return toPath;
} }
public boolean isSoft() public boolean isSoft()
{ {
return isSoft; return isSoft;
} }
} }

View File

@@ -1,63 +1,63 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Restore File Command * Restore File Command
*/ */
public class RestoreFileCommand implements Command public class RestoreFileCommand implements Command
{ {
private String name; private String name;
private NodeRef rootNode; private NodeRef rootNode;
private String path; private String path;
private long allocationSize; private long allocationSize;
private NodeRef originalNodeRef; private NodeRef originalNodeRef;
public RestoreFileCommand(String name, NodeRef rootNode, String path, long allocationSize, NodeRef originalNodeRef) public RestoreFileCommand(String name, NodeRef rootNode, String path, long allocationSize, NodeRef originalNodeRef)
{ {
this.name = name; this.name = name;
this.path = path; this.path = path;
this.rootNode = rootNode; this.rootNode = rootNode;
this.allocationSize = allocationSize; this.allocationSize = allocationSize;
this.originalNodeRef = originalNodeRef; this.originalNodeRef = originalNodeRef;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public NodeRef getRootNode() public NodeRef getRootNode()
{ {
return rootNode; return rootNode;
} }
public String getPath() public String getPath()
{ {
return path; return path;
} }
public NodeRef getOriginalNodeRef() public NodeRef getOriginalNodeRef()
{ {
return originalNodeRef; return originalNodeRef;
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_READ_WRITE; return TxnReadState.TXN_READ_WRITE;
} }
public void setAllocationSize(long allocationSize) public void setAllocationSize(long allocationSize)
{ {
this.allocationSize = allocationSize; this.allocationSize = allocationSize;
} }
public long getAllocationSize() public long getAllocationSize()
{ {
return allocationSize; return allocationSize;
} }
} }

View File

@@ -1,29 +1,29 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
/** /**
* Return a specified value to the executor * Return a specified value to the executor
*/ */
public class ReturnValueCommand implements Command public class ReturnValueCommand implements Command
{ {
Object returnValue; Object returnValue;
public ReturnValueCommand(Object returnValue) public ReturnValueCommand(Object returnValue)
{ {
this.returnValue = returnValue; this.returnValue = returnValue;
} }
public Object getReturnValue() public Object getReturnValue()
{ {
return returnValue; return returnValue;
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_NONE; return TxnReadState.TXN_NONE;
} }
} }

View File

@@ -1,19 +1,19 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
public class SoftRenameFileCommand extends RenameFileCommand public class SoftRenameFileCommand extends RenameFileCommand
{ {
public SoftRenameFileCommand(String from, String to, NodeRef rootNode, public SoftRenameFileCommand(String from, String to, NodeRef rootNode,
String fromPath, String toPath) String fromPath, String toPath)
{ {
super(from, to, rootNode, fromPath, toPath); super(from, to, rootNode, fromPath, toPath);
} }
public boolean isSoft() public boolean isSoft()
{ {
return true; return true;
} }
} }

View File

@@ -1,22 +1,22 @@
package org.alfresco.filesys.repo.rules.commands; package org.alfresco.filesys.repo.rules.commands;
import org.alfresco.filesys.repo.rules.Command; import org.alfresco.filesys.repo.rules.Command;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Update the user's quota. * Update the user's quota.
*/ */
public class UpdateQuotaCommand implements Command public class UpdateQuotaCommand implements Command
{ {
public UpdateQuotaCommand() public UpdateQuotaCommand()
{ {
} }
@Override @Override
public TxnReadState getTransactionRequired() public TxnReadState getTransactionRequired()
{ {
return TxnReadState.TXN_NONE; return TxnReadState.TXN_NONE;
} }
} }

View File

@@ -1,84 +1,84 @@
package org.alfresco.filesys.repo.rules.operations; package org.alfresco.filesys.repo.rules.operations;
import org.alfresco.filesys.repo.rules.Operation; import org.alfresco.filesys.repo.rules.Operation;
import org.alfresco.jlan.server.filesys.NetworkFile; import org.alfresco.jlan.server.filesys.NetworkFile;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Close File Operation. * Close File Operation.
* <p> * <p>
* Close a file with the given name. * Close a file with the given name.
*/ */
public class CloseFileOperation implements Operation public class CloseFileOperation implements Operation
{ {
private String name; private String name;
private NodeRef rootNodeRef; private NodeRef rootNodeRef;
private String path; private String path;
private NetworkFile networkFile; private NetworkFile networkFile;
boolean deleteOnClose; boolean deleteOnClose;
boolean force; boolean force;
public CloseFileOperation(String name, NetworkFile networkFile, NodeRef rootNodeRef, String path, boolean deleteOnClose, boolean force) public CloseFileOperation(String name, NetworkFile networkFile, NodeRef rootNodeRef, String path, boolean deleteOnClose, boolean force)
{ {
this.name = name; this.name = name;
this.networkFile = networkFile; this.networkFile = networkFile;
this.rootNodeRef = rootNodeRef; this.rootNodeRef = rootNodeRef;
this.path = path; this.path = path;
this.deleteOnClose = deleteOnClose; this.deleteOnClose = deleteOnClose;
this.force = force; this.force = force;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public NodeRef getRootNodeRef() public NodeRef getRootNodeRef()
{ {
return rootNodeRef; return rootNodeRef;
} }
public String getPath() public String getPath()
{ {
return path; return path;
} }
public NetworkFile getNetworkFile() public NetworkFile getNetworkFile()
{ {
return networkFile; return networkFile;
} }
public String toString() public String toString()
{ {
return "CloseFileOperation: " + name; return "CloseFileOperation: " + name;
} }
public int hashCode() public int hashCode()
{ {
return name.hashCode(); return name.hashCode();
} }
public boolean isDeleteOnClose() public boolean isDeleteOnClose()
{ {
return deleteOnClose; return deleteOnClose;
} }
public boolean isForce() public boolean isForce()
{ {
return force; return force;
} }
public boolean equals(Object o) public boolean equals(Object o)
{ {
if(o instanceof CloseFileOperation) if(o instanceof CloseFileOperation)
{ {
CloseFileOperation c = (CloseFileOperation)o; CloseFileOperation c = (CloseFileOperation)o;
if(name.equals(c.getName())) if(name.equals(c.getName()))
{ {
return true; return true;
} }
} }
return false; return false;
} }
} }

View File

@@ -1,80 +1,80 @@
package org.alfresco.filesys.repo.rules.operations; package org.alfresco.filesys.repo.rules.operations;
import org.alfresco.filesys.repo.rules.Operation; import org.alfresco.filesys.repo.rules.Operation;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Create File Operation. * Create File Operation.
* <p> * <p>
* Create a file with the given name. * Create a file with the given name.
*/ */
public class CreateFileOperation implements Operation public class CreateFileOperation implements Operation
{ {
private String name; private String name;
private NodeRef rootNodeRef; private NodeRef rootNodeRef;
private String path; private String path;
private long allocationSize; private long allocationSize;
boolean isHidden; boolean isHidden;
public CreateFileOperation(String name, NodeRef rootNodeRef, String path, long allocationSize, boolean isHidden) public CreateFileOperation(String name, NodeRef rootNodeRef, String path, long allocationSize, boolean isHidden)
{ {
this.name = name; this.name = name;
this.rootNodeRef = rootNodeRef; this.rootNodeRef = rootNodeRef;
this.path = path; this.path = path;
this.allocationSize = allocationSize; this.allocationSize = allocationSize;
this.isHidden = isHidden; this.isHidden = isHidden;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public String toString() public String toString()
{ {
return "CreateFileOperation: " + name; return "CreateFileOperation: " + name;
} }
public String getPath() public String getPath()
{ {
return path; return path;
} }
public NodeRef getRootNodeRef() public NodeRef getRootNodeRef()
{ {
return rootNodeRef; return rootNodeRef;
} }
public int hashCode() public int hashCode()
{ {
return name.hashCode(); return name.hashCode();
} }
public boolean equals(Object o) public boolean equals(Object o)
{ {
if(o instanceof CreateFileOperation) if(o instanceof CreateFileOperation)
{ {
CreateFileOperation c = (CreateFileOperation)o; CreateFileOperation c = (CreateFileOperation)o;
if(name.equals(c.getName())) if(name.equals(c.getName()))
{ {
return true; return true;
} }
} }
return false; return false;
} }
public void setAllocationSize(long allocationSize) public void setAllocationSize(long allocationSize)
{ {
this.allocationSize = allocationSize; this.allocationSize = allocationSize;
} }
public long getAllocationSize() public long getAllocationSize()
{ {
return allocationSize; return allocationSize;
} }
public boolean isHidden() public boolean isHidden()
{ {
return isHidden; return isHidden;
} }
} }

View File

@@ -1,64 +1,64 @@
package org.alfresco.filesys.repo.rules.operations; package org.alfresco.filesys.repo.rules.operations;
import org.alfresco.filesys.repo.rules.Operation; import org.alfresco.filesys.repo.rules.Operation;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
public class DeleteFileOperation implements Operation public class DeleteFileOperation implements Operation
{ {
private String name; private String name;
private NodeRef rootNodeRef; private NodeRef rootNodeRef;
private String path; private String path;
/** /**
* Delete File Operation * Delete File Operation
* @param name of file * @param name of file
* @param rootNodeRef root node ref * @param rootNodeRef root node ref
* @param path path + name of file to delete * @param path path + name of file to delete
*/ */
public DeleteFileOperation(String name, NodeRef rootNodeRef, String path) public DeleteFileOperation(String name, NodeRef rootNodeRef, String path)
{ {
this.name = name; this.name = name;
this.rootNodeRef = rootNodeRef; this.rootNodeRef = rootNodeRef;
this.path = path; this.path = path;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public String getPath() public String getPath()
{ {
return path; return path;
} }
public NodeRef getRootNodeRef() public NodeRef getRootNodeRef()
{ {
return rootNodeRef; return rootNodeRef;
} }
public String toString() public String toString()
{ {
return "DeleteFileOperation: " + name; return "DeleteFileOperation: " + name;
} }
public int hashCode() public int hashCode()
{ {
return name.hashCode(); return name.hashCode();
} }
public boolean equals(Object o) public boolean equals(Object o)
{ {
if(o instanceof DeleteFileOperation) if(o instanceof DeleteFileOperation)
{ {
DeleteFileOperation c = (DeleteFileOperation)o; DeleteFileOperation c = (DeleteFileOperation)o;
if(name.equals(c.getName())) if(name.equals(c.getName()))
{ {
return true; return true;
} }
} }
return false; return false;
} }
} }

View File

@@ -1,85 +1,85 @@
package org.alfresco.filesys.repo.rules.operations; package org.alfresco.filesys.repo.rules.operations;
import org.alfresco.filesys.repo.rules.Operation; import org.alfresco.filesys.repo.rules.Operation;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Rename a file within the same directory * Rename a file within the same directory
*/ */
public class MoveFileOperation implements Operation public class MoveFileOperation implements Operation
{ {
private String from; private String from;
private String to; private String to;
private String fromPath; private String fromPath;
private String toPath; private String toPath;
NodeRef rootNodeRef; NodeRef rootNodeRef;
/** /**
* *
* @param from name of file from * @param from name of file from
* @param to name of file to * @param to name of file to
* @param fromPath full path of from * @param fromPath full path of from
* @param toPath full path of to * @param toPath full path of to
* @param rootNodeRef * @param rootNodeRef
*/ */
public MoveFileOperation(String from, String to, String fromPath, String toPath, NodeRef rootNodeRef) public MoveFileOperation(String from, String to, String fromPath, String toPath, NodeRef rootNodeRef)
{ {
this.from = from; this.from = from;
this.to = to; this.to = to;
this.fromPath = fromPath; this.fromPath = fromPath;
this.toPath = toPath; this.toPath = toPath;
this.rootNodeRef = rootNodeRef; this.rootNodeRef = rootNodeRef;
} }
public String getFrom() public String getFrom()
{ {
return from; return from;
} }
public String getTo() public String getTo()
{ {
return to; return to;
} }
public String getToPath() public String getToPath()
{ {
return toPath; return toPath;
} }
public String getFromPath() public String getFromPath()
{ {
return fromPath; return fromPath;
} }
public NodeRef getRootNodeRef() public NodeRef getRootNodeRef()
{ {
return rootNodeRef; return rootNodeRef;
} }
public String toString() public String toString()
{ {
return "MoveFileOperation: from " + fromPath + " to "+ toPath; return "MoveFileOperation: from " + fromPath + " to "+ toPath;
} }
public int hashCode() public int hashCode()
{ {
return fromPath.hashCode(); return fromPath.hashCode();
} }
public boolean equals(Object o) public boolean equals(Object o)
{ {
if(o instanceof MoveFileOperation) if(o instanceof MoveFileOperation)
{ {
MoveFileOperation r = (MoveFileOperation)o; MoveFileOperation r = (MoveFileOperation)o;
if(fromPath.equals(r.getFromPath()) && toPath.equals(r.getToPath())) if(fromPath.equals(r.getFromPath()) && toPath.equals(r.getToPath()))
{ {
return true; return true;
} }
} }
return false; return false;
} }
} }

View File

@@ -1,85 +1,85 @@
package org.alfresco.filesys.repo.rules.operations; package org.alfresco.filesys.repo.rules.operations;
import org.alfresco.filesys.repo.OpenFileMode; import org.alfresco.filesys.repo.OpenFileMode;
import org.alfresco.filesys.repo.rules.Operation; import org.alfresco.filesys.repo.rules.Operation;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Open File Operation. * Open File Operation.
* <p> * <p>
* Open a file with the given name. * Open a file with the given name.
*/ */
public class OpenFileOperation implements Operation public class OpenFileOperation implements Operation
{ {
private String name; private String name;
private OpenFileMode mode; private OpenFileMode mode;
private boolean truncate = false; private boolean truncate = false;
private String path; private String path;
private NodeRef rootNode; private NodeRef rootNode;
/** /**
* *
* @param name the name of the file to open * @param name the name of the file to open
* @param mode if true open the file in read/write * @param mode if true open the file in read/write
* @param truncate boolean * @param truncate boolean
* @param rootNode root node * @param rootNode root node
* @param path the full path/name to open * @param path the full path/name to open
*/ */
public OpenFileOperation(String name, OpenFileMode mode, boolean truncate, NodeRef rootNode, String path) public OpenFileOperation(String name, OpenFileMode mode, boolean truncate, NodeRef rootNode, String path)
{ {
this.name = name; this.name = name;
this.rootNode = rootNode; this.rootNode = rootNode;
this.truncate = truncate; this.truncate = truncate;
this.path = path; this.path = path;
this.mode = mode; this.mode = mode;
} }
public String getName() public String getName()
{ {
return name; return name;
} }
public String getPath() public String getPath()
{ {
return path; return path;
} }
public NodeRef getRootNodeRef() public NodeRef getRootNodeRef()
{ {
return rootNode; return rootNode;
} }
public OpenFileMode getMode() public OpenFileMode getMode()
{ {
return mode; return mode;
} }
public boolean isTruncate() public boolean isTruncate()
{ {
return truncate; return truncate;
} }
public String toString() public String toString()
{ {
return "OpenFileOperation: " + name; return "OpenFileOperation: " + name;
} }
public int hashCode() public int hashCode()
{ {
return name.hashCode(); return name.hashCode();
} }
public boolean equals(Object o) public boolean equals(Object o)
{ {
if(o instanceof OpenFileOperation) if(o instanceof OpenFileOperation)
{ {
OpenFileOperation c = (OpenFileOperation)o; OpenFileOperation c = (OpenFileOperation)o;
if(name.equals(c.getName())) if(name.equals(c.getName()))
{ {
return true; return true;
} }
} }
return false; return false;
} }
} }

View File

@@ -1,85 +1,85 @@
package org.alfresco.filesys.repo.rules.operations; package org.alfresco.filesys.repo.rules.operations;
import org.alfresco.filesys.repo.rules.Operation; import org.alfresco.filesys.repo.rules.Operation;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
* Rename a file within the same directory * Rename a file within the same directory
*/ */
public class RenameFileOperation implements Operation public class RenameFileOperation implements Operation
{ {
private String from; private String from;
private String to; private String to;
private String fromPath; private String fromPath;
private String toPath; private String toPath;
NodeRef rootNodeRef; NodeRef rootNodeRef;
/** /**
* *
* @param from name of file from * @param from name of file from
* @param to name of file to * @param to name of file to
* @param fromPath full path of from * @param fromPath full path of from
* @param toPath full path of to * @param toPath full path of to
* @param rootNodeRef * @param rootNodeRef
*/ */
public RenameFileOperation(String from, String to, String fromPath, String toPath, NodeRef rootNodeRef) public RenameFileOperation(String from, String to, String fromPath, String toPath, NodeRef rootNodeRef)
{ {
this.from = from; this.from = from;
this.to = to; this.to = to;
this.fromPath = fromPath; this.fromPath = fromPath;
this.toPath = toPath; this.toPath = toPath;
this.rootNodeRef = rootNodeRef; this.rootNodeRef = rootNodeRef;
} }
public String getFrom() public String getFrom()
{ {
return from; return from;
} }
public String getTo() public String getTo()
{ {
return to; return to;
} }
public String getToPath() public String getToPath()
{ {
return toPath; return toPath;
} }
public String getFromPath() public String getFromPath()
{ {
return fromPath; return fromPath;
} }
public NodeRef getRootNodeRef() public NodeRef getRootNodeRef()
{ {
return rootNodeRef; return rootNodeRef;
} }
public String toString() public String toString()
{ {
return "RenameFileOperation: from " + from + " to "+ to; return "RenameFileOperation: from " + from + " to "+ to;
} }
public int hashCode() public int hashCode()
{ {
return from.hashCode(); return from.hashCode();
} }
public boolean equals(Object o) public boolean equals(Object o)
{ {
if(o instanceof RenameFileOperation) if(o instanceof RenameFileOperation)
{ {
RenameFileOperation r = (RenameFileOperation)o; RenameFileOperation r = (RenameFileOperation)o;
if(from.equals(r.getFrom()) && to.equals(r.getTo())) if(from.equals(r.getFrom()) && to.equals(r.getTo()))
{ {
return true; return true;
} }
} }
return false; return false;
} }
} }

View File

@@ -1,19 +1,19 @@
/** /**
* Filesystem Rule Evaluator to support Scenarios. * Filesystem Rule Evaluator to support Scenarios.
* <p> * <p>
* Low level operations (create, update, delete etc) are passed into the RuleEvaluator. * Low level operations (create, update, delete etc) are passed into the RuleEvaluator.
* <p> * <p>
* The RuleEvaluator is configured with a list of Scenarios which process the operations as and * The RuleEvaluator is configured with a list of Scenarios which process the operations as and
* when their patterns match. * when their patterns match.
* The RuleEvaluator evaluates the stream of operations and returns commands to execute. * The RuleEvaluator evaluates the stream of operations and returns commands to execute.
* <p> * <p>
* The Command Executor executes the commands returned from the RuleEvaluator. * The Command Executor executes the commands returned from the RuleEvaluator.
* <p> * <p>
* Each Scenario is a Factory for A ScenarioInstance. The RuleEvaluator contains a set of active scenario instances. * Each Scenario is a Factory for A ScenarioInstance. The RuleEvaluator contains a set of active scenario instances.
* <p> * <p>
* @since 4.0 * @since 4.0
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys.repo.rules; package org.alfresco.filesys.repo.rules;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,10 +1,10 @@
/** /**
* Filesystem utilities * Filesystem utilities
* *
* Contains : * Contains :
* CifsMounter to mount and unmount a CIFS filesystem. * CifsMounter to mount and unmount a CIFS filesystem.
* *
*/ */
@PackageMarker @PackageMarker
package org.alfresco.filesys.util; package org.alfresco.filesys.util;
import org.alfresco.util.PackageMarker; import org.alfresco.util.PackageMarker;

View File

@@ -1,44 +1,44 @@
package org.alfresco.model; package org.alfresco.model;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
/** /**
* @author Kevin Roast * @author Kevin Roast
*/ */
public interface ApplicationModel public interface ApplicationModel
{ {
// workflow // workflow
static final QName ASPECT_SIMPLE_WORKFLOW = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "simpleworkflow"); static final QName ASPECT_SIMPLE_WORKFLOW = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "simpleworkflow");
static final QName PROP_APPROVE_STEP = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "approveStep"); static final QName PROP_APPROVE_STEP = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "approveStep");
static final QName PROP_APPROVE_FOLDER = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "approveFolder"); static final QName PROP_APPROVE_FOLDER = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "approveFolder");
static final QName PROP_APPROVE_MOVE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "approveMove"); static final QName PROP_APPROVE_MOVE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "approveMove");
static final QName PROP_REJECT_STEP = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "rejectStep"); static final QName PROP_REJECT_STEP = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "rejectStep");
static final QName PROP_REJECT_FOLDER = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "rejectFolder"); static final QName PROP_REJECT_FOLDER = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "rejectFolder");
static final QName PROP_REJECT_MOVE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "rejectMove"); static final QName PROP_REJECT_MOVE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "rejectMove");
// ui facets aspect // ui facets aspect
static final QName ASPECT_UIFACETS = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "uifacets"); static final QName ASPECT_UIFACETS = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "uifacets");
static final QName PROP_ICON = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "icon"); static final QName PROP_ICON = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "icon");
// inlineeditable aspect // inlineeditable aspect
static final QName ASPECT_INLINEEDITABLE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "inlineeditable"); static final QName ASPECT_INLINEEDITABLE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "inlineeditable");
static final QName PROP_EDITINLINE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "editInline"); static final QName PROP_EDITINLINE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "editInline");
// configurable aspect // configurable aspect
static final QName ASPECT_CONFIGURABLE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "configurable"); static final QName ASPECT_CONFIGURABLE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "configurable");
static final QName TYPE_CONFIGURATIONS = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "configurations"); static final QName TYPE_CONFIGURATIONS = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "configurations");
static final QName ASSOC_CONFIGURATIONS = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "configurations"); static final QName ASSOC_CONFIGURATIONS = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "configurations");
// object links // object links
static final QName TYPE_FILELINK = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "filelink"); static final QName TYPE_FILELINK = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "filelink");
static final QName TYPE_FOLDERLINK = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "folderlink"); static final QName TYPE_FOLDERLINK = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "folderlink");
// feed source aspect // feed source aspect
static final QName ASPECT_FEEDSOURCE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "feedsource"); static final QName ASPECT_FEEDSOURCE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "feedsource");
static final QName PROP_FEEDTEMPLATE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "template"); static final QName PROP_FEEDTEMPLATE = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "template");
// Default view config aspect // Default view config aspect
static final QName ASPECT_DEFAULT_VIEW_CONFIG = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "defaultViewConfig"); static final QName ASPECT_DEFAULT_VIEW_CONFIG = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "defaultViewConfig");
static final QName PROP_DEFAULT_VIEW_ID = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "defaultViewId"); static final QName PROP_DEFAULT_VIEW_ID = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "defaultViewId");
} }

View File

@@ -1,29 +1,29 @@
package org.alfresco.model; package org.alfresco.model;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
/** /**
* @author Roy Wetherall * @author Roy Wetherall
*/ */
public interface BlogIntegrationModel public interface BlogIntegrationModel
{ {
static final String MODEL_URL = "http://www.alfresco.org/model/blogintegration/1.0"; static final String MODEL_URL = "http://www.alfresco.org/model/blogintegration/1.0";
static final String MODEL_PREFIX = "blg"; static final String MODEL_PREFIX = "blg";
static final QName ASPECT_BLOG_DETAILS = QName.createQName(MODEL_URL, "blogDetails"); static final QName ASPECT_BLOG_DETAILS = QName.createQName(MODEL_URL, "blogDetails");
static final QName PROP_BLOG_IMPLEMENTATION = QName.createQName(MODEL_URL, "blogImplementation"); static final QName PROP_BLOG_IMPLEMENTATION = QName.createQName(MODEL_URL, "blogImplementation");
static final QName PROP_ID = QName.createQName(MODEL_URL, "id"); static final QName PROP_ID = QName.createQName(MODEL_URL, "id");
static final QName PROP_NAME = QName.createQName(MODEL_URL, "name"); static final QName PROP_NAME = QName.createQName(MODEL_URL, "name");
static final QName PROP_DESCRIPTION = QName.createQName(MODEL_URL, "description"); static final QName PROP_DESCRIPTION = QName.createQName(MODEL_URL, "description");
static final QName PROP_URL = QName.createQName(MODEL_URL, "url"); static final QName PROP_URL = QName.createQName(MODEL_URL, "url");
static final QName PROP_USER_NAME = QName.createQName(MODEL_URL, "userName"); static final QName PROP_USER_NAME = QName.createQName(MODEL_URL, "userName");
static final QName PROP_PASSWORD = QName.createQName(MODEL_URL, "password"); static final QName PROP_PASSWORD = QName.createQName(MODEL_URL, "password");
static final QName ASPECT_BLOG_POST = QName.createQName(MODEL_URL, "blogPost"); static final QName ASPECT_BLOG_POST = QName.createQName(MODEL_URL, "blogPost");
static final QName PROP_POST_ID = QName.createQName(MODEL_URL, "postId"); static final QName PROP_POST_ID = QName.createQName(MODEL_URL, "postId");
static final QName PROP_PUBLISHED = QName.createQName(MODEL_URL, "published"); static final QName PROP_PUBLISHED = QName.createQName(MODEL_URL, "published");
static final QName PROP_LINK = QName.createQName(MODEL_URL, "link"); static final QName PROP_LINK = QName.createQName(MODEL_URL, "link");
static final QName PROP_POSTED = QName.createQName(MODEL_URL, "posted"); static final QName PROP_POSTED = QName.createQName(MODEL_URL, "posted");
static final QName PROP_LAST_UPDATE = QName.createQName(MODEL_URL, "lastUpdate"); static final QName PROP_LAST_UPDATE = QName.createQName(MODEL_URL, "lastUpdate");
static final QName ASSOC_BLOG_DETAILS = QName.createQName(MODEL_URL, "blogDetails"); static final QName ASSOC_BLOG_DETAILS = QName.createQName(MODEL_URL, "blogDetails");
} }

Some files were not shown because too many files have changed in this diff Show More