diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml index 6e6f0609fa..0f3120d194 100644 --- a/config/alfresco/core-services-context.xml +++ b/config/alfresco/core-services-context.xml @@ -278,18 +278,18 @@ org.alfresco.repo.search.IndexerAndSearcher - + - + - + - + @@ -319,8 +319,8 @@ - + @@ -330,9 +330,6 @@ - - - ${dir.indexes} @@ -374,6 +371,70 @@ + + + + + + + + + + + + + + ${dir.indexes} + + + + + + + + + + + + + + + + + + ${lucene.maxAtomicTransformationTime} + + + ${lucene.query.maxClauses} + + + ${lucene.indexer.batchSize} + + + ${dir.indexes.lock} + + + ${lucene.indexer.maxFieldLength} + + + ${lucene.write.lock.timeout} + + + ${lucene.commit.lock.timeout} + + + ${lucene.lock.poll.interval} + + + EXACT_LANGUAGE_AND_ALL + + + EXACT_LANGUAGE_AND_ALL + + + + @@ -387,7 +448,7 @@ - + @@ -681,7 +742,7 @@ + class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" depends-on="indexerAndSearcherFactory"> org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer @@ -689,11 +750,7 @@ - - - - - + @@ -702,14 +759,22 @@ + + + + + + + class="org.alfresco.repo.search.impl.lucene.AbstractLuceneIndexerAndSearcherFactory$LuceneIndexBackupComponent"> - - + + + + diff --git a/config/alfresco/extension/language-specific-index-and-search-context.xml.sample b/config/alfresco/extension/language-specific-index-and-search-context.xml.sample index 7082320a76..43bb907ef5 100644 --- a/config/alfresco/extension/language-specific-index-and-search-context.xml.sample +++ b/config/alfresco/extension/language-specific-index-and-search-context.xml.sample @@ -9,7 +9,7 @@ - @@ -20,9 +20,6 @@ - - - ${dir.indexes} diff --git a/config/alfresco/extension/new-indexer-context.xml.sample b/config/alfresco/extension/new-indexer-context.xml.sample deleted file mode 100644 index 703ada717e..0000000000 --- a/config/alfresco/extension/new-indexer-context.xml.sample +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - ${dir.indexes} - - - - - - - - - ${lucene.maxAtomicTransformationTime} - - - ${lucene.query.maxClauses} - - - ${lucene.indexer.batchSize} - - - ${lucene.indexer.minMergeDocs} - - - ${lucene.indexer.mergeFactor} - - - ${lucene.indexer.maxMergeDocs} - - - ${dir.indexes.lock} - - - ${lucene.indexer.maxFieldLength} - - - ${lucene.write.lock.timeout} - - - ${lucene.commit.lock.timeout} - - - ${lucene.lock.poll.interval} - - - - - - - - - - - - - - - - - - ${dir.root}/backup-lucene-indexes - - - - \ No newline at end of file diff --git a/config/alfresco/public-services-context.xml b/config/alfresco/public-services-context.xml index ae91b11748..c2739d4786 100644 --- a/config/alfresco/public-services-context.xml +++ b/config/alfresco/public-services-context.xml @@ -834,15 +834,41 @@ avmServiceWriteTxnAdvisor avmServiceReadTxnAdvisor + avmSnapShotTriggeredIndexingMethodInterceptor + + + + org.alfresco.service.cmr.avm.AVMService + + + + avmService + + + + avmSnapShotTriggeredIndexingMethodInterceptor + + + + + + + + + + + + + - + @@ -945,7 +971,7 @@ - + diff --git a/config/alfresco/scheduled-jobs-context.xml b/config/alfresco/scheduled-jobs-context.xml index 37a5fe1509..494fd9f17b 100644 --- a/config/alfresco/scheduled-jobs-context.xml +++ b/config/alfresco/scheduled-jobs-context.xml @@ -135,7 +135,7 @@ - org.alfresco.repo.search.impl.lucene.LuceneIndexerAndSearcherFactory2$LuceneIndexBackupJob + org.alfresco.repo.search.impl.lucene.AbstractLuceneIndexerAndSearcherFactory$LuceneIndexBackupJob diff --git a/source/java/org/alfresco/filesys/avm/AVMDiskDriver.java b/source/java/org/alfresco/filesys/avm/AVMDiskDriver.java index d767a729d8..a16ef53e23 100644 --- a/source/java/org/alfresco/filesys/avm/AVMDiskDriver.java +++ b/source/java/org/alfresco/filesys/avm/AVMDiskDriver.java @@ -81,52 +81,61 @@ import org.apache.commons.logging.LogFactory; /** * AVM Repository Filesystem Driver Class - * - *

Provides a filesystem interface for various protocols such as SMB/CIFS and FTP. + *

+ * Provides a filesystem interface for various protocols such as SMB/CIFS and FTP. * * @author GKSpencer */ -public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { +public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface +{ // Logging - + private static final Log logger = LogFactory.getLog(AVMDiskDriver.class); - + // Configuration key names - - private static final String KEY_STORE = "storePath"; - private static final String KEY_VERSION = "version"; - private static final String KEY_CREATE = "createStore"; + + private static final String KEY_STORE = "storePath"; + + private static final String KEY_VERSION = "version"; + + private static final String KEY_CREATE = "createStore"; // AVM path seperator - - public static final char AVM_SEPERATOR = '/'; - public static final String AVM_SEPERATOR_STR = "/"; - + + public static final char AVM_SEPERATOR = '/'; + + public static final String AVM_SEPERATOR_STR = "/"; + // Services and helpers - + private AVMService m_avmService; + private TransactionService m_transactionService; + private MimetypeService m_mimetypeService; - + private AuthenticationComponent m_authComponent; + private AuthenticationService m_authService; - + // AVM listeners - + private CreateStoreTxnListener m_createStoreListener; + private PurgeStoreTxnListener m_purgeStoreListener; - + private CreateVersionTxnListener m_createVerListener; + private PurgeVersionTxnListener m_purgeVerListener; - + /** * Default constructor */ public AVMDiskDriver() { } - + /** * Return the AVM service * @@ -134,9 +143,9 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { */ public final AVMService getAvmService() { - return m_avmService; + return m_avmService; } - + /** * Return the authentication service * @@ -144,9 +153,9 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { */ public final AuthenticationService getAuthenticationService() { - return m_authService; + return m_authService; } - + /** * Return the transaction service * @@ -154,23 +163,25 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { */ public final TransactionService getTransactionService() { - return m_transactionService; + return m_transactionService; } - + /** * Set the AVM service * - * @param avmService AVMService + * @param avmService + * AVMService */ public void setAvmService(AVMService avmService) { - m_avmService = avmService; + m_avmService = avmService; } - + /** * Set the transaction service * - * @param transactionService the transaction service + * @param transactionService + * the transaction service */ public void setTransactionService(TransactionService transactionService) { @@ -180,7 +191,8 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { /** * Set the authentication component * - * @param authComponent AuthenticationComponent + * @param authComponent + * AuthenticationComponent */ public void setAuthenticationComponent(AuthenticationComponent authComponent) { @@ -190,308 +202,329 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { /** * Set the authentication service * - * @param authService AuthenticationService + * @param authService + * AuthenticationService */ public void setAuthenticationService(AuthenticationService authService) { - m_authService = authService; + m_authService = authService; } - + /** * Set the mimetype service * - * @param mimetypeService MimetypeService + * @param mimetypeService + * MimetypeService */ public void setMimetypeService(MimetypeService mimetypeService) { m_mimetypeService = mimetypeService; } - + /** * Set the create store listener * - * @param createStoreListener CreateStoreTxnListener + * @param createStoreListener + * CreateStoreTxnListener */ public void setCreateStoreListener(CreateStoreTxnListener createStoreListener) { - m_createStoreListener = createStoreListener; + m_createStoreListener = createStoreListener; } - + /** * Set the purge store listener * - * @param purgeStoreListener PurgeStoreTxnListener + * @param purgeStoreListener + * PurgeStoreTxnListener */ public void setPurgeStoreListener(PurgeStoreTxnListener purgeStoreListener) { - m_purgeStoreListener = purgeStoreListener; + m_purgeStoreListener = purgeStoreListener; } - + /** * Set the create version listener * - * @param createVersionListener CreateVersionTxnListener + * @param createVersionListener + * CreateVersionTxnListener */ public void setCreateVersionListener(CreateVersionTxnListener createVersionListener) { - m_createVerListener = createVersionListener; + m_createVerListener = createVersionListener; } - + /** * Set the purge version listener * - * @param purgeVersionListener PurgeVersionTxnListener + * @param purgeVersionListener + * PurgeVersionTxnListener */ public void setPurgeVersionListener(PurgeVersionTxnListener purgeVersionListener) { - m_purgeVerListener = purgeVersionListener; + m_purgeVerListener = purgeVersionListener; } - + /** - * Parse and validate the parameter string and create a device context object for this instance - * of the shared device. + * Parse and validate the parameter string and create a device context object for this instance of the shared + * device. * - * @param devIface DeviceInterface - * @param name String - * @param cfg ConfigElement + * @param devIface + * DeviceInterface + * @param name + * String + * @param cfg + * ConfigElement * @return DeviceContext * @exception DeviceContextException */ public DeviceContext createContext(DeviceInterface devIface, String name, ConfigElement cfg) - throws DeviceContextException + throws DeviceContextException { // Use the system user as the authenticated context for the filesystem initialization - - m_authComponent.setCurrentUser( m_authComponent.getSystemUserName()); - - // Wrap the initialization in a transaction - - UserTransaction tx = m_transactionService.getUserTransaction(false); - AVMContext context = null; - + String currentUser = m_authComponent.getCurrentUserName(); try { - // Start the transaction - - if ( tx != null) - tx.begin(); - - // Check if the share is a virtualization view - - ConfigElement virtElem = cfg.getChild( "virtualView"); - if ( virtElem != null) + m_authComponent.setCurrentUser(m_authComponent.getSystemUserName()); + + // Wrap the initialization in a transaction + + UserTransaction tx = m_transactionService.getUserTransaction(false); + + AVMContext context = null; + + try { - // Check if sandboxes should be shown in the virtualization view - - boolean showSandboxes = cfg.getChild( "showAllSandboxes") != null ? true : false; - - // Create the context - - context = new AVMContext( name, showSandboxes, this); - - // Enable file state caching - - context.enableStateTable( true, getStateReaper()); - - // Plug the virtualization view context into the various store/version call back listeners - // so that store/version pseudo folders can be kept in sync with AVM - - m_createStoreListener.addCallback( context); - m_purgeStoreListener.addCallback( context); - - m_createVerListener.addCallback( context); - m_purgeVerListener.addCallback( context); + // Start the transaction + + if (tx != null) + tx.begin(); + + // Check if the share is a virtualization view + + ConfigElement virtElem = cfg.getChild("virtualView"); + if (virtElem != null) + { + // Check if sandboxes should be shown in the virtualization view + + boolean showSandboxes = cfg.getChild("showAllSandboxes") != null ? true : false; + + // Create the context + + context = new AVMContext(name, showSandboxes, this); + + // Enable file state caching + + context.enableStateTable(true, getStateReaper()); + + // Plug the virtualization view context into the various store/version call back listeners + // so that store/version pseudo folders can be kept in sync with AVM + + m_createStoreListener.addCallback(context); + m_purgeStoreListener.addCallback(context); + + m_createVerListener.addCallback(context); + m_purgeVerListener.addCallback(context); + } + else + { + // Get the store path + + ConfigElement storeElement = cfg.getChild(KEY_STORE); + if (storeElement == null + || storeElement.getValue() == null || storeElement.getValue().length() == 0) + throw new DeviceContextException("Device missing init value: " + KEY_STORE); + + String storePath = storeElement.getValue(); + + // Get the version if specified, or default to the head version + + int version = AVMContext.VERSION_HEAD; + + ConfigElement versionElem = cfg.getChild(KEY_VERSION); + if (versionElem != null) + { + // Check if the version is valid + + if (versionElem.getValue() == null || versionElem.getValue().length() == 0) + throw new DeviceContextException("Store version not specified"); + + // Validate the version id + + try + { + version = Integer.parseInt(versionElem.getValue()); + } + catch (NumberFormatException ex) + { + throw new DeviceContextException("Invalid store version specified, " + + versionElem.getValue()); + } + + // Range check the version id + + if (version < 0 && version != AVMContext.VERSION_HEAD) + throw new DeviceContextException("Invalid store version id specified, " + version); + } + + // Check if the create flag is enabled + + ConfigElement createStore = cfg.getChild(KEY_CREATE); + + // Validate the store path + + AVMNodeDescriptor rootNode = m_avmService.lookup(version, storePath); + if (rootNode == null) + { + // Check if the store should be created + + if (createStore == null || version != AVMContext.VERSION_HEAD) + throw new DeviceContextException("Invalid store path/version, " + + storePath + " (" + version + ")"); + + // Parse the store path + + String storeName = null; + String path = null; + + int pos = storePath.indexOf(":/"); + if (pos != -1) + { + storeName = storePath.substring(0, pos); + if (storePath.length() > pos) + path = storePath.substring(pos + 2); + } + else + storeName = storePath; + + // Check if the store exists + + AVMStoreDescriptor storeDesc = null; + + try + { + storeDesc = m_avmService.getStore(storeName); + } + catch (AVMNotFoundException ex) + { + } + + // Create a new store if it does not exist + + if (storeDesc == null) + m_avmService.createStore(storeName); + + // Check if there is an optional path + + if (path != null) + { + // Split the path + + StringTokenizer tokens = new StringTokenizer(path, AVMPath.AVM_SEPERATOR_STR); + StringList paths = new StringList(); + + while (tokens.hasMoreTokens()) + paths.addString(tokens.nextToken()); + + // Create the path, or folders that do not exist + + AVMPath curPath = new AVMPath(storeName, version, FileName.DOS_SEPERATOR_STR); + AVMNodeDescriptor curDesc = m_avmService.lookup(curPath.getVersion(), curPath.getAVMPath()); + + // Walk the path checking creating each folder as required + + for (int i = 0; i < paths.numberOfStrings(); i++) + { + AVMNodeDescriptor nextDesc = null; + + try + { + // Check if the child folder exists + + nextDesc = m_avmService.lookup(curDesc, paths.getStringAt(i)); + } + catch (AVMNotFoundException ex) + { + } + + // Check if the folder exists + + if (nextDesc == null) + { + // Create the new folder + + m_avmService.createDirectory(curPath.getAVMPath(), paths.getStringAt(i)); + + // Get the details of the new folder + + nextDesc = m_avmService.lookup(curDesc, paths.getStringAt(i)); + } + else if (nextDesc.isFile()) + throw new DeviceContextException("Path element error, not a folder, " + + paths.getStringAt(i)); + + // Step to the next level + + curPath.parsePath(storeName, version, curPath.getRelativePath() + + paths.getStringAt(i) + FileName.DOS_SEPERATOR_STR); + curDesc = nextDesc; + } + } + + // Validate the store path again + + rootNode = m_avmService.lookup(version, storePath); + if (rootNode == null) + throw new DeviceContextException("Failed to create new store " + storePath); + } + + // Create the context + + context = new AVMContext(name, storePath, version); + + // Enable file state caching + + context.enableStateTable(true, getStateReaper()); + } + + // Commit the transaction + + tx.commit(); + tx = null; } - else + catch (Exception ex) { - // Get the store path - - ConfigElement storeElement = cfg.getChild(KEY_STORE); - if (storeElement == null || storeElement.getValue() == null || storeElement.getValue().length() == 0) - throw new DeviceContextException("Device missing init value: " + KEY_STORE); - - String storePath = storeElement.getValue(); - - // Get the version if specified, or default to the head version - - int version = AVMContext.VERSION_HEAD; - - ConfigElement versionElem = cfg.getChild(KEY_VERSION); - if ( versionElem != null) - { - // Check if the version is valid - - if ( versionElem.getValue() == null || versionElem.getValue().length() == 0) - throw new DeviceContextException("Store version not specified"); - - // Validate the version id - - try - { - version = Integer.parseInt( versionElem.getValue()); - } - catch ( NumberFormatException ex) - { - throw new DeviceContextException("Invalid store version specified, " + versionElem.getValue()); - } - - // Range check the version id - - if ( version < 0 && version != AVMContext.VERSION_HEAD) - throw new DeviceContextException("Invalid store version id specified, " + version); - } - - // Check if the create flag is enabled - - ConfigElement createStore = cfg.getChild( KEY_CREATE); + logger.error("Error during create context", ex); - // Validate the store path - - AVMNodeDescriptor rootNode = m_avmService.lookup( version, storePath); - if ( rootNode == null) - { - // Check if the store should be created - - if ( createStore == null || version != AVMContext.VERSION_HEAD) - throw new DeviceContextException("Invalid store path/version, " + storePath + " (" + version + ")"); - - // Parse the store path - - String storeName = null; - String path = null; - - int pos = storePath.indexOf(":/"); - if ( pos != -1) - { - storeName = storePath.substring(0, pos); - if ( storePath.length() > pos) - path = storePath.substring(pos + 2); - } - else - storeName = storePath; - - // Check if the store exists - - AVMStoreDescriptor storeDesc = null; - - try - { - storeDesc = m_avmService.getStore( storeName); - } - catch (AVMNotFoundException ex) - { - } - - // Create a new store if it does not exist - - if ( storeDesc == null) - m_avmService.createStore( storeName); - - // Check if there is an optional path - - if ( path != null) - { - // Split the path - - StringTokenizer tokens = new StringTokenizer( path, AVMPath.AVM_SEPERATOR_STR); - StringList paths = new StringList(); - - while ( tokens.hasMoreTokens()) - paths.addString( tokens.nextToken()); - - // Create the path, or folders that do not exist - - AVMPath curPath = new AVMPath( storeName, version, FileName.DOS_SEPERATOR_STR); - AVMNodeDescriptor curDesc = m_avmService.lookup( curPath.getVersion(), curPath.getAVMPath()); + // Rethrow the exception - // Walk the path checking creating each folder as required - - for ( int i = 0; i < paths.numberOfStrings(); i++) - { - AVMNodeDescriptor nextDesc = null; - - try - { - // Check if the child folder exists - - nextDesc = m_avmService.lookup( curDesc, paths.getStringAt( i)); - } - catch ( AVMNotFoundException ex) - { - } - - // Check if the folder exists - - if ( nextDesc == null) - { - // Create the new folder - - m_avmService.createDirectory( curPath.getAVMPath(), paths.getStringAt( i)); - - // Get the details of the new folder - - nextDesc = m_avmService.lookup( curDesc, paths.getStringAt( i)); - } - else if ( nextDesc.isFile()) - throw new DeviceContextException("Path element error, not a folder, " + paths.getStringAt( i)); - - // Step to the next level - - curPath.parsePath( storeName, version, curPath.getRelativePath() + paths.getStringAt( i) + FileName.DOS_SEPERATOR_STR); - curDesc = nextDesc; - } - } - - // Validate the store path again - - rootNode = m_avmService.lookup( version, storePath); - if ( rootNode == null) - throw new DeviceContextException("Failed to create new store " + storePath); - } - - // Create the context - - context = new AVMContext( name, storePath, version); - - // Enable file state caching - - context.enableStateTable( true, getStateReaper()); + throw new DeviceContextException("Driver setup error, " + ex.getMessage()); } + finally + { + // If there is an active transaction then roll it back - // Commit the transaction - - tx.commit(); - tx = null; - } - catch (Exception ex) - { - logger.error("Error during create context", ex); - - // Rethrow the exception - - throw new DeviceContextException("Driver setup error, " + ex.getMessage()); + if (tx != null) + { + try + { + tx.rollback(); + } + catch (Exception ex) + { + logger.warn("Failed to rollback transaction", ex); + } + } + } + // Return the context for this shared filesystem + return context; } finally { - // If there is an active transaction then roll it back - - if ( tx != null) - { - try - { - tx.rollback(); - } - catch (Exception ex) - { - logger.warn("Failed to rollback transaction", ex); - } - } + m_authComponent.setCurrentUser(currentUser); } - // Return the context for this shared filesystem - - return context; } /** @@ -502,1200 +535,1294 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { public final StringList getAVMStoreNames() { // Use the system user as the authenticated context to get the AVM store list - - m_authComponent.setCurrentUser( m_authComponent.getSystemUserName()); - - // Wrap the service request in a transaction - - UserTransaction tx = m_transactionService.getUserTransaction(false); - StringList storeNames = new StringList(); - + String currentUser = m_authComponent.getCurrentUserName(); try { - // Start the transaction - - if ( tx != null) - tx.begin(); + m_authComponent.setCurrentUser(m_authComponent.getSystemUserName()); - // Get the list of AVM stores - - List storeList = m_avmService.getStores(); - - if ( storeList != null) + // Wrap the service request in a transaction + + UserTransaction tx = m_transactionService.getUserTransaction(false); + + StringList storeNames = new StringList(); + + try { - for ( AVMStoreDescriptor storeDesc : storeList) - storeNames.addString( storeDesc.getName()); + // Start the transaction + + if (tx != null) + tx.begin(); + + // Get the list of AVM stores + + List storeList = m_avmService.getStores(); + + if (storeList != null) + { + for (AVMStoreDescriptor storeDesc : storeList) + storeNames.addString(storeDesc.getName()); + } + + // Commit the transaction + + tx.commit(); + tx = null; + } + catch (Exception ex) + { + logger.error("Error getting store names", ex); + } + finally + { + // If there is an active transaction then roll it back + + if (tx != null) + { + try + { + tx.rollback(); + } + catch (Exception ex) + { + logger.warn("Failed to rollback transaction", ex); + } + } } - // Commit the transaction - - tx.commit(); - tx = null; + // Return the list of AVM store names + + return storeNames; } - catch (Exception ex) + finally { - logger.error("Error getting store names", ex); - } - finally - { - // If there is an active transaction then roll it back - - if ( tx != null) - { - try - { - tx.rollback(); - } - catch (Exception ex) - { - logger.warn("Failed to rollback transaction", ex); - } - } - } - - // Return the list of AVM store names - - return storeNames; + m_authComponent.setCurrentUser(currentUser); + } } - + /** * Get the properties for a store * - * @param storeName String + * @param storeName + * String * @return Map */ - protected final Map getAVMStoreProperties( String storeName) + protected final Map getAVMStoreProperties(String storeName) { // Use the system user as the authenticated context to get the AVM store properties - - m_authComponent.setCurrentUser( m_authComponent.getSystemUserName()); - - // Wrap the service request in a transaction - - UserTransaction tx = m_transactionService.getUserTransaction(false); - Map properties = null; - + String currentUser = m_authComponent.getCurrentUserName(); try { - // Start the transaction - - if ( tx != null) - tx.begin(); + m_authComponent.setCurrentUser(m_authComponent.getSystemUserName()); - // Get the list of properties for AVM store - - properties = m_avmService.getStoreProperties( storeName); + // Wrap the service request in a transaction - // Commit the transaction - - tx.commit(); - tx = null; + UserTransaction tx = m_transactionService.getUserTransaction(false); + + Map properties = null; + + try + { + // Start the transaction + + if (tx != null) + tx.begin(); + + // Get the list of properties for AVM store + + properties = m_avmService.getStoreProperties(storeName); + + // Commit the transaction + + tx.commit(); + tx = null; + } + catch (Exception ex) + { + logger.error("Error getting store properties", ex); + } + finally + { + // If there is an active transaction then roll it back + + if (tx != null) + { + try + { + tx.rollback(); + } + catch (Exception ex) + { + logger.warn("Failed to rollback transaction", ex); + } + } + } + + // Return the list of AVM store properties + + return properties; } - catch (Exception ex) + finally { - logger.error("Error getting store properties", ex); - } - finally - { - // If there is an active transaction then roll it back - - if ( tx != null) - { - try - { - tx.rollback(); - } - catch (Exception ex) - { - logger.warn("Failed to rollback transaction", ex); - } - } - } - - // Return the list of AVM store properties - - return properties; + m_authComponent.setCurrentUser(currentUser); + } } - + /** * Build the full store path for a file/folder using the share relative path * - * @param ctx AVMContext - * @param path String + * @param ctx + * AVMContext + * @param path + * String * @return AVMPath */ - protected final AVMPath buildStorePath( AVMContext ctx, String path) + protected final AVMPath buildStorePath(AVMContext ctx, String path) { - // Check if the AVM filesystem is a normal or virtualization view + // Check if the AVM filesystem is a normal or virtualization view - AVMPath avmPath = null; - - if ( ctx.isVirtualizationView()) - { - // Create a path for the virtualization view - - avmPath = new AVMPath( path); - } - else - { - // Create a path to a single store/version - - avmPath = new AVMPath( ctx.getStorePath(), ctx.isVersion(), path); - } - - // Return the path - - return avmPath; + AVMPath avmPath = null; + + if (ctx.isVirtualizationView()) + { + // Create a path for the virtualization view + + avmPath = new AVMPath(path); + } + else + { + // Create a path to a single store/version + + avmPath = new AVMPath(ctx.getStorePath(), ctx.isVersion(), path); + } + + // Return the path + + return avmPath; } - - /** + + /** * Close the file. * - * @param sess Server session - * @param tree Tree connection. - * @param file Network file context. - * @exception java.io.IOException If an error occurs. + * @param sess + * Server session + * @param tree + * Tree connection. + * @param file + * Network file context. + * @exception java.io.IOException + * If an error occurs. */ - public void closeFile(SrvSession sess, TreeConnection tree, NetworkFile file) - throws java.io.IOException + public void closeFile(SrvSession sess, TreeConnection tree, NetworkFile file) throws java.io.IOException { - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Close file " + file.getFullName()); - - // Close the file - + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("Close file " + file.getFullName()); + + // Close the file + file.closeFile(); - // Check if the file/directory is marked for delete - - if ( file.hasDeleteOnClose()) { - - // Check for a file or directory - - if ( file.isDirectory()) - deleteDirectory(sess, tree, file.getFullName()); - else - deleteFile(sess, tree, file.getFullName()); - } + // Check if the file/directory is marked for delete + + if (file.hasDeleteOnClose()) + { + + // Check for a file or directory + + if (file.isDirectory()) + deleteDirectory(sess, tree, file.getFullName()); + else + deleteFile(sess, tree, file.getFullName()); + } } /** * Create a new directory on this file system. * - * @param sess Server session - * @param tree Tree connection. - * @param params Directory create parameters - * @exception java.io.IOException If an error occurs. + * @param sess + * Server session + * @param tree + * Tree connection. + * @param params + * Directory create parameters + * @exception java.io.IOException + * If an error occurs. */ - public void createDirectory(SrvSession sess, TreeConnection tree, FileOpenParams params) - throws java.io.IOException + public void createDirectory(SrvSession sess, TreeConnection tree, FileOpenParams params) throws java.io.IOException { - // Check if the filesystem is writable - - AVMContext ctx = (AVMContext) tree.getContext(); - if ( ctx.isVersion() != AVMContext.VERSION_HEAD) - throw new AccessDeniedException("Cannot create " + params.getPath() + ", filesys not writable"); - - // Split the path to get the new folder name and relative path - - String[] paths = FileName.splitPath( params.getPath()); - - // Convert the relative path to a store path - - AVMPath storePath = buildStorePath( ctx, paths[0]); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Create directory params=" + params + ", storePath=" + storePath + ", name=" + paths[1]); - - // Check if the filesystem is the virtualization view - - if ( ctx.isVirtualizationView() && storePath.isReadOnlyPseudoPath()) - { - throw new AccessDeniedException( "Cannot create folder in store/version layer, " + params.getPath()); - } - - // Create a new file - - sess.beginWriteTransaction( m_transactionService); - - try - { - // Create the new file entry + // Check if the filesystem is writable - m_avmService.createDirectory( storePath.getAVMPath(), paths[1]); - } - catch ( AVMExistsException ex) - { - throw new FileExistsException( params.getPath()); - } - catch ( AVMNotFoundException ex) - { - throw new FileNotFoundException( params.getPath()); - } - catch ( AVMWrongTypeException ex) - { - throw new FileNotFoundException( params.getPath()); - } - catch ( AVMBadArgumentException ex) - { - throw new FileNotFoundException( params.getPath()); - } + AVMContext ctx = (AVMContext) tree.getContext(); + if (ctx.isVersion() != AVMContext.VERSION_HEAD) + throw new AccessDeniedException("Cannot create " + params.getPath() + ", filesys not writable"); + + // Split the path to get the new folder name and relative path + + String[] paths = FileName.splitPath(params.getPath()); + + // Convert the relative path to a store path + + AVMPath storePath = buildStorePath(ctx, paths[0]); + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("Create directory params=" + params + ", storePath=" + storePath + ", name=" + paths[1]); + + // Check if the filesystem is the virtualization view + + if (ctx.isVirtualizationView() && storePath.isReadOnlyPseudoPath()) + { + throw new AccessDeniedException("Cannot create folder in store/version layer, " + params.getPath()); + } + + // Create a new file + + sess.beginWriteTransaction(m_transactionService); + + try + { + // Create the new file entry + + m_avmService.createDirectory(storePath.getAVMPath(), paths[1]); + } + catch (AVMExistsException ex) + { + throw new FileExistsException(params.getPath()); + } + catch (AVMNotFoundException ex) + { + throw new FileNotFoundException(params.getPath()); + } + catch (AVMWrongTypeException ex) + { + throw new FileNotFoundException(params.getPath()); + } + catch (AVMBadArgumentException ex) + { + throw new FileNotFoundException(params.getPath()); + } } - + /** * Create a new file on the file system. * - * @param sess Server session - * @param tree Tree connection - * @param params File create parameters + * @param sess + * Server session + * @param tree + * Tree connection + * @param params + * File create parameters * @return NetworkFile - * @exception java.io.IOException If an error occurs. + * @exception java.io.IOException + * If an error occurs. */ public NetworkFile createFile(SrvSession sess, TreeConnection tree, FileOpenParams params) - throws java.io.IOException + throws java.io.IOException { - // Check if the filesystem is writable - - AVMContext ctx = (AVMContext) tree.getContext(); - - // Split the path to get the file name and relative path - - String[] paths = FileName.splitPath( params.getPath()); - - // Convert the relative path to a store path - - AVMPath storePath = buildStorePath( ctx, paths[0]); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Create file params=" + params + ", storePath=" + storePath + ", name=" + paths[1]); - - // Check if the filesystem is the virtualization view - - if ( ctx.isVirtualizationView() && storePath.isReadOnlyPseudoPath()) - { - throw new AccessDeniedException( "Cannot create file in store/version layer, " + params.getPath()); - } - else if ( storePath.getVersion() != AVMContext.VERSION_HEAD) - { - throw new AccessDeniedException("Cannot create " + params.getPath() + ", filesys not writable"); - } - - // Create a new file - - sess.beginWriteTransaction( m_transactionService); - - AVMNetworkFile netFile = null; - - try - { - // Create the new file entry + // Check if the filesystem is writable - m_avmService.createFile( storePath.getAVMPath(), paths[1]).close(); + AVMContext ctx = (AVMContext) tree.getContext(); - // Get the new file details - - AVMPath fileStorePath = buildStorePath( ctx, params.getPath()); - AVMNodeDescriptor nodeDesc = m_avmService.lookup( fileStorePath.getVersion(), fileStorePath.getAVMPath()); + // Split the path to get the file name and relative path - if ( nodeDesc != null) - { - // Create the network file object for the new file - - netFile = new AVMNetworkFile( nodeDesc, fileStorePath.getAVMPath(), fileStorePath.getVersion(), m_avmService); - netFile.setGrantedAccess(NetworkFile.READWRITE); - netFile.setFullName(params.getPath()); - - netFile.setFileId( fileStorePath.generateFileId()); - - // Set the mime-type for the new file - - netFile.setMimeType( m_mimetypeService.guessMimetype( paths[1])); - } - } - catch ( AVMExistsException ex) - { - throw new FileExistsException( params.getPath()); - } - catch ( AVMNotFoundException ex) - { - throw new FileNotFoundException( params.getPath()); - } - catch ( AVMWrongTypeException ex) - { - throw new FileNotFoundException( params.getPath()); - } - catch ( AVMBadArgumentException ex) - { - throw new FileNotFoundException( params.getPath()); - } - - // Return the file - - return netFile; + String[] paths = FileName.splitPath(params.getPath()); + + // Convert the relative path to a store path + + AVMPath storePath = buildStorePath(ctx, paths[0]); + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("Create file params=" + params + ", storePath=" + storePath + ", name=" + paths[1]); + + // Check if the filesystem is the virtualization view + + if (ctx.isVirtualizationView() && storePath.isReadOnlyPseudoPath()) + { + throw new AccessDeniedException("Cannot create file in store/version layer, " + params.getPath()); + } + else if (storePath.getVersion() != AVMContext.VERSION_HEAD) + { + throw new AccessDeniedException("Cannot create " + params.getPath() + ", filesys not writable"); + } + + // Create a new file + + sess.beginWriteTransaction(m_transactionService); + + AVMNetworkFile netFile = null; + + try + { + // Create the new file entry + + m_avmService.createFile(storePath.getAVMPath(), paths[1]).close(); + + // Get the new file details + + AVMPath fileStorePath = buildStorePath(ctx, params.getPath()); + AVMNodeDescriptor nodeDesc = m_avmService.lookup(fileStorePath.getVersion(), fileStorePath.getAVMPath()); + + if (nodeDesc != null) + { + // Create the network file object for the new file + + netFile = new AVMNetworkFile(nodeDesc, fileStorePath.getAVMPath(), fileStorePath.getVersion(), + m_avmService); + netFile.setGrantedAccess(NetworkFile.READWRITE); + netFile.setFullName(params.getPath()); + + netFile.setFileId(fileStorePath.generateFileId()); + + // Set the mime-type for the new file + + netFile.setMimeType(m_mimetypeService.guessMimetype(paths[1])); + } + } + catch (AVMExistsException ex) + { + throw new FileExistsException(params.getPath()); + } + catch (AVMNotFoundException ex) + { + throw new FileNotFoundException(params.getPath()); + } + catch (AVMWrongTypeException ex) + { + throw new FileNotFoundException(params.getPath()); + } + catch (AVMBadArgumentException ex) + { + throw new FileNotFoundException(params.getPath()); + } + + // Return the file + + return netFile; } - + /** * Delete the directory from the filesystem. * - * @param sess Server session - * @param tree Tree connection - * @param dir Directory name. - * @exception java.io.IOException The exception description. + * @param sess + * Server session + * @param tree + * Tree connection + * @param dir + * Directory name. + * @exception java.io.IOException + * The exception description. */ - public void deleteDirectory(SrvSession sess, TreeConnection tree, String dir) - throws java.io.IOException + public void deleteDirectory(SrvSession sess, TreeConnection tree, String dir) throws java.io.IOException { - // Convert the relative path to a store path - - AVMContext ctx = (AVMContext) tree.getContext(); - AVMPath storePath = buildStorePath( ctx, dir); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Delete directory, path=" + dir + ", storePath=" + storePath); - - // Check if the filesystem is the virtualization view - - if ( ctx.isVirtualizationView() && storePath.isPseudoPath()) - { - throw new AccessDeniedException( "Cannot delete pseudo folder, " + dir); - } - - // Make sure the path is to a folder before deleting it - - sess.beginWriteTransaction( m_transactionService); - - try - { - AVMNodeDescriptor nodeDesc = m_avmService.lookup( storePath.getVersion(), storePath.getAVMPath()); - if ( nodeDesc != null) - { - // Check that we are deleting a folder - - if ( nodeDesc.isDirectory()) - { - // Make sure the directory is empty - - SortedMap fileList = m_avmService.getDirectoryListing( nodeDesc); - if ( fileList != null && fileList.size() > 0) - throw new DirectoryNotEmptyException( dir); - - // Delete the folder - - m_avmService.removeNode( storePath.getAVMPath()); - } - else - throw new IOException( "Delete directory path is not a directory, " + dir); - } - } - catch ( AVMNotFoundException ex) - { - throw new IOException( "Directory not found, " + dir); - } - catch ( AVMWrongTypeException ex) - { - throw new IOException( "Invalid path, " + dir); - } + // Convert the relative path to a store path + + AVMContext ctx = (AVMContext) tree.getContext(); + AVMPath storePath = buildStorePath(ctx, dir); + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("Delete directory, path=" + dir + ", storePath=" + storePath); + + // Check if the filesystem is the virtualization view + + if (ctx.isVirtualizationView() && storePath.isPseudoPath()) + { + throw new AccessDeniedException("Cannot delete pseudo folder, " + dir); + } + + // Make sure the path is to a folder before deleting it + + sess.beginWriteTransaction(m_transactionService); + + try + { + AVMNodeDescriptor nodeDesc = m_avmService.lookup(storePath.getVersion(), storePath.getAVMPath()); + if (nodeDesc != null) + { + // Check that we are deleting a folder + + if (nodeDesc.isDirectory()) + { + // Make sure the directory is empty + + SortedMap fileList = m_avmService.getDirectoryListing(nodeDesc); + if (fileList != null && fileList.size() > 0) + throw new DirectoryNotEmptyException(dir); + + // Delete the folder + + m_avmService.removeNode(storePath.getAVMPath()); + } + else + throw new IOException("Delete directory path is not a directory, " + dir); + } + } + catch (AVMNotFoundException ex) + { + throw new IOException("Directory not found, " + dir); + } + catch (AVMWrongTypeException ex) + { + throw new IOException("Invalid path, " + dir); + } } /** * Delete the specified file. * - * @param sess Server session - * @param tree Tree connection - * @param file NetworkFile - * @exception java.io.IOException The exception description. + * @param sess + * Server session + * @param tree + * Tree connection + * @param file + * NetworkFile + * @exception java.io.IOException + * The exception description. */ - public void deleteFile(SrvSession sess, TreeConnection tree, String name) - throws java.io.IOException + public void deleteFile(SrvSession sess, TreeConnection tree, String name) throws java.io.IOException { - // Convert the relative path to a store path - - AVMContext ctx = (AVMContext) tree.getContext(); - AVMPath storePath = buildStorePath( ctx, name); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Delete file, path=" + name + ", storePath=" + storePath); - - // Check if the filesystem is the virtualization view - - if ( ctx.isVirtualizationView() && storePath.isPseudoPath()) - { - throw new AccessDeniedException( "Cannot delete pseudo file, " + name); - } - - // Make sure the path is to a file before deleting it - - sess.beginWriteTransaction( m_transactionService); - - try - { - AVMNodeDescriptor nodeDesc = m_avmService.lookup( storePath.getVersion(), storePath.getAVMPath()); - if ( nodeDesc != null) - { - // Check that we are deleting a file - - if ( nodeDesc.isFile()) - { - // Delete the file - - m_avmService.removeNode( storePath.getAVMPath()); - } - else - throw new IOException( "Delete file path is not a file, " + name); - } - } - catch ( AVMNotFoundException ex) - { - throw new IOException( "File not found, " + name); - } - catch ( AVMWrongTypeException ex) - { - throw new IOException( "Invalid path, " + name); - } + // Convert the relative path to a store path + + AVMContext ctx = (AVMContext) tree.getContext(); + AVMPath storePath = buildStorePath(ctx, name); + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("Delete file, path=" + name + ", storePath=" + storePath); + + // Check if the filesystem is the virtualization view + + if (ctx.isVirtualizationView() && storePath.isPseudoPath()) + { + throw new AccessDeniedException("Cannot delete pseudo file, " + name); + } + + // Make sure the path is to a file before deleting it + + sess.beginWriteTransaction(m_transactionService); + + try + { + AVMNodeDescriptor nodeDesc = m_avmService.lookup(storePath.getVersion(), storePath.getAVMPath()); + if (nodeDesc != null) + { + // Check that we are deleting a file + + if (nodeDesc.isFile()) + { + // Delete the file + + m_avmService.removeNode(storePath.getAVMPath()); + } + else + throw new IOException("Delete file path is not a file, " + name); + } + } + catch (AVMNotFoundException ex) + { + throw new IOException("File not found, " + name); + } + catch (AVMWrongTypeException ex) + { + throw new IOException("Invalid path, " + name); + } } /** * Check if the specified file exists, and whether it is a file or directory. * - * @param sess Server session - * @param tree Tree connection - * @param name java.lang.String + * @param sess + * Server session + * @param tree + * Tree connection + * @param name + * java.lang.String * @return int * @see FileStatus */ public int fileExists(SrvSession sess, TreeConnection tree, String name) { - // Convert the relative path to a store path - - AVMContext ctx = (AVMContext) tree.getContext(); - AVMPath storePath = buildStorePath( ctx, name); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("File exists check, path=" + name + ", storePath=" + storePath); - - // Check if the path is valid - - int status = FileStatus.NotExist; - - if ( storePath.isValid() == false) - return status; - - // Check if the filesystem is the virtualization view - - if ( ctx.isVirtualizationView() && storePath.isReadOnlyPseudoPath()) - { - // Find the file state for the pseudo folder - - FileState fstate = findPseudoState( storePath, ctx); - - if ( fstate != null) - { - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug( " Found pseudo file " + fstate); - - // Check if the pseudo file is a file or folder - - if ( fstate.isDirectory()) - status = FileStatus.DirectoryExists; - else - status = FileStatus.FileExists; - } - else - { - // Invalid pseudo file path - - status = FileStatus.NotExist; - } - - // Return the file status - - return status; - } - - // Search for the file/folder - - sess.beginReadTransaction( m_transactionService); - - AVMNodeDescriptor nodeDesc = m_avmService.lookup( storePath.getVersion(), storePath.getAVMPath()); - - if ( nodeDesc != null) - { - // Check if the path is to a file or folder - - if ( nodeDesc.isDirectory()) - status = FileStatus.DirectoryExists; - else - status = FileStatus.FileExists; - } - - // Return the file status - - return status; + // Convert the relative path to a store path + + AVMContext ctx = (AVMContext) tree.getContext(); + AVMPath storePath = buildStorePath(ctx, name); + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("File exists check, path=" + name + ", storePath=" + storePath); + + // Check if the path is valid + + int status = FileStatus.NotExist; + + if (storePath.isValid() == false) + return status; + + // Check if the filesystem is the virtualization view + + if (ctx.isVirtualizationView() && storePath.isReadOnlyPseudoPath()) + { + // Find the file state for the pseudo folder + + FileState fstate = findPseudoState(storePath, ctx); + + if (fstate != null) + { + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug(" Found pseudo file " + fstate); + + // Check if the pseudo file is a file or folder + + if (fstate.isDirectory()) + status = FileStatus.DirectoryExists; + else + status = FileStatus.FileExists; + } + else + { + // Invalid pseudo file path + + status = FileStatus.NotExist; + } + + // Return the file status + + return status; + } + + // Search for the file/folder + + sess.beginReadTransaction(m_transactionService); + + AVMNodeDescriptor nodeDesc = m_avmService.lookup(storePath.getVersion(), storePath.getAVMPath()); + + if (nodeDesc != null) + { + // Check if the path is to a file or folder + + if (nodeDesc.isDirectory()) + status = FileStatus.DirectoryExists; + else + status = FileStatus.FileExists; + } + + // Return the file status + + return status; } /** * Flush any buffered output for the specified file. * - * @param sess Server session - * @param tree Tree connection - * @param file Network file context. - * @exception java.io.IOException The exception description. + * @param sess + * Server session + * @param tree + * Tree connection + * @param file + * Network file context. + * @exception java.io.IOException + * The exception description. */ - public void flushFile(SrvSession sess, TreeConnection tree, NetworkFile file) - throws java.io.IOException + public void flushFile(SrvSession sess, TreeConnection tree, NetworkFile file) throws java.io.IOException { - // Flush the file - + // Flush the file + file.flushFile(); } /** * Get the file information for the specified file. * - * @param sess Server session - * @param tree Tree connection - * @param name File name/path that information is required for. + * @param sess + * Server session + * @param tree + * Tree connection + * @param name + * File name/path that information is required for. * @return File information if valid, else null - * @exception java.io.IOException The exception description. + * @exception java.io.IOException + * The exception description. */ - public FileInfo getFileInformation(SrvSession sess, TreeConnection tree, String name) - throws java.io.IOException + public FileInfo getFileInformation(SrvSession sess, TreeConnection tree, String name) throws java.io.IOException { - // Convert the relative path to a store path - - AVMContext ctx = (AVMContext) tree.getContext(); - AVMPath storePath = buildStorePath( ctx, name); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Get file information, path=" + name + ", storePath=" + storePath); + // Convert the relative path to a store path - // Check if hte path is valid - - if ( storePath.isValid() == false) - throw new FileNotFoundException( name); - - // Check if the filesystem is the virtualization view - - if ( ctx.isVirtualizationView() && storePath.isReadOnlyPseudoPath()) - { - // Check if the search path is for the root, a store or version folder - - if ( storePath.isRootPath()) - { - // Return dummy file informatiom for the root folder - - return new FileInfo( name, 0L, FileAttribute.Directory); - } - else - { - // Find the pseudo file for the store/version folder - - PseudoFile psFile = findPseudoFolder( storePath, ctx); - if ( psFile != null) - { - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug( " Found pseudo file " + psFile); - return psFile.getFileInfo(); - } - else - throw new FileNotFoundException( name); - } - } - - // Search for the file/folder - - sess.beginReadTransaction( m_transactionService); - - FileInfo info = null; - - try - { - AVMNodeDescriptor nodeDesc = m_avmService.lookup( storePath.getVersion(), storePath.getAVMPath()); - - if ( nodeDesc != null) - { - // Create, and fill in, the file information - - info = new FileInfo(); - - info.setFileName( nodeDesc.getName()); - - if ( nodeDesc.isFile()) - { - info.setFileSize( nodeDesc.getLength()); - info.setAllocationSize((nodeDesc.getLength() + 512L) & 0xFFFFFFFFFFFFFE00L); - } - else - info.setFileSize( 0L); - - info.setAccessDateTime( nodeDesc.getAccessDate()); - info.setCreationDateTime( nodeDesc.getCreateDate()); - info.setModifyDateTime( nodeDesc.getModDate()); - - // Build the file attributes - - int attr = 0; - - if ( nodeDesc.isDirectory()) - attr += FileAttribute.Directory; - - if ( nodeDesc.getName().startsWith( ".") || - nodeDesc.getName().equalsIgnoreCase( "Desktop.ini") || - nodeDesc.getName().equalsIgnoreCase( "Thumbs.db")) - attr += FileAttribute.Hidden; - - // Mark the file/folder as read-only if not the head version - - if ( ctx.isVersion() != AVMContext.VERSION_HEAD) - attr += FileAttribute.ReadOnly; - - info.setFileAttributes( attr); + AVMContext ctx = (AVMContext) tree.getContext(); + AVMPath storePath = buildStorePath(ctx, name); - // Set the file id - - info.setFileId( storePath.generateFileId()); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug(" File info=" + info); - } - } - catch ( AVMNotFoundException ex) - { - throw new FileNotFoundException( name); - } - catch ( AVMWrongTypeException ex) - { - throw new PathNotFoundException( name); - } - - // Return the file information - - return info; + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("Get file information, path=" + name + ", storePath=" + storePath); + + // Check if hte path is valid + + if (storePath.isValid() == false) + throw new FileNotFoundException(name); + + // Check if the filesystem is the virtualization view + + if (ctx.isVirtualizationView() && storePath.isReadOnlyPseudoPath()) + { + // Check if the search path is for the root, a store or version folder + + if (storePath.isRootPath()) + { + // Return dummy file informatiom for the root folder + + return new FileInfo(name, 0L, FileAttribute.Directory); + } + else + { + // Find the pseudo file for the store/version folder + + PseudoFile psFile = findPseudoFolder(storePath, ctx); + if (psFile != null) + { + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug(" Found pseudo file " + psFile); + return psFile.getFileInfo(); + } + else + throw new FileNotFoundException(name); + } + } + + // Search for the file/folder + + sess.beginReadTransaction(m_transactionService); + + FileInfo info = null; + + try + { + AVMNodeDescriptor nodeDesc = m_avmService.lookup(storePath.getVersion(), storePath.getAVMPath()); + + if (nodeDesc != null) + { + // Create, and fill in, the file information + + info = new FileInfo(); + + info.setFileName(nodeDesc.getName()); + + if (nodeDesc.isFile()) + { + info.setFileSize(nodeDesc.getLength()); + info.setAllocationSize((nodeDesc.getLength() + 512L) & 0xFFFFFFFFFFFFFE00L); + } + else + info.setFileSize(0L); + + info.setAccessDateTime(nodeDesc.getAccessDate()); + info.setCreationDateTime(nodeDesc.getCreateDate()); + info.setModifyDateTime(nodeDesc.getModDate()); + + // Build the file attributes + + int attr = 0; + + if (nodeDesc.isDirectory()) + attr += FileAttribute.Directory; + + if (nodeDesc.getName().startsWith(".") + || nodeDesc.getName().equalsIgnoreCase("Desktop.ini") + || nodeDesc.getName().equalsIgnoreCase("Thumbs.db")) + attr += FileAttribute.Hidden; + + // Mark the file/folder as read-only if not the head version + + if (ctx.isVersion() != AVMContext.VERSION_HEAD) + attr += FileAttribute.ReadOnly; + + info.setFileAttributes(attr); + + // Set the file id + + info.setFileId(storePath.generateFileId()); + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug(" File info=" + info); + } + } + catch (AVMNotFoundException ex) + { + throw new FileNotFoundException(name); + } + catch (AVMWrongTypeException ex) + { + throw new PathNotFoundException(name); + } + + // Return the file information + + return info; } /** * Determine if the disk device is read-only. * - * @param sess Server session - * @param ctx Device context + * @param sess + * Server session + * @param ctx + * Device context * @return boolean - * @exception java.io.IOException If an error occurs. + * @exception java.io.IOException + * If an error occurs. */ - public boolean isReadOnly(SrvSession sess, DeviceContext ctx) - throws java.io.IOException + public boolean isReadOnly(SrvSession sess, DeviceContext ctx) throws java.io.IOException { - // Check if the version indicates the head version, only the head is writable - - AVMContext avmCtx = (AVMContext) ctx; - return avmCtx.isVersion() == AVMContext.VERSION_HEAD ? true : false; + // Check if the version indicates the head version, only the head is writable + + AVMContext avmCtx = (AVMContext) ctx; + return avmCtx.isVersion() == AVMContext.VERSION_HEAD ? true : false; } /** * Open a file on the file system. * - * @param sess Server session - * @param tree Tree connection - * @param params File open parameters + * @param sess + * Server session + * @param tree + * Tree connection + * @param params + * File open parameters * @return NetworkFile - * @exception java.io.IOException If an error occurs. + * @exception java.io.IOException + * If an error occurs. */ - public NetworkFile openFile(SrvSession sess, TreeConnection tree, FileOpenParams params) - throws java.io.IOException + public NetworkFile openFile(SrvSession sess, TreeConnection tree, FileOpenParams params) throws java.io.IOException { - // Convert the relative path to a store path - - AVMContext ctx = (AVMContext) tree.getContext(); - AVMPath storePath = buildStorePath( ctx, params.getPath()); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Open file params=" + params + ", storePath=" + storePath); - - // Check if the filesystem is the virtualization view - - if ( ctx.isVirtualizationView() && storePath.isReadOnlyPseudoPath()) - { - // Check if the path is for the root, a store or version folder - - if ( storePath.isRootPath()) - { - // Return a dummy file for the root folder - - return new PseudoFolderNetworkFile( FileName.DOS_SEPERATOR_STR); - } - else - { - // Find the pseudo file for the store/version folder - - PseudoFile psFile = findPseudoFolder( storePath, ctx); - if ( psFile != null) - { - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug( " Found pseudo file " + psFile); - return psFile.getFile( params.getPath()); - } - else - return null; - } - } - - // Search for the file/folder - - sess.beginReadTransaction( m_transactionService); - - AVMNetworkFile netFile = null; - - try - { - // Get the details of the file/folder + // Convert the relative path to a store path - AVMNodeDescriptor nodeDesc = m_avmService.lookup( storePath.getVersion(), storePath.getAVMPath()); - - if ( nodeDesc != null) - { - // Check if the filesystem is read-only and write access has been requested - - if ( storePath.getVersion() != AVMContext.VERSION_HEAD && ( params.isReadWriteAccess() || params.isWriteOnlyAccess())) - throw new AccessDeniedException("File " + params.getPath() + " is read-only"); - - // Create the network file object for the opened file/folder - - netFile = new AVMNetworkFile( nodeDesc, storePath.getAVMPath(), storePath.getVersion(), m_avmService); - - if ( params.isReadOnlyAccess() || storePath.getVersion() != AVMContext.VERSION_HEAD) - netFile.setGrantedAccess(NetworkFile.READONLY); - else - netFile.setGrantedAccess(NetworkFile.READWRITE); - - netFile.setFullName(params.getPath()); - netFile.setFileId( storePath.generateFileId()); - - - // Set the mime-type for the new file - - netFile.setMimeType( m_mimetypeService.guessMimetype( params.getPath())); - } - else - throw new FileNotFoundException( params.getPath()); - } - catch ( AVMNotFoundException ex) - { - throw new FileNotFoundException( params.getPath()); - } - catch ( AVMWrongTypeException ex) - { - throw new FileNotFoundException( params.getPath()); - } - - // Return the file - - return netFile; + AVMContext ctx = (AVMContext) tree.getContext(); + AVMPath storePath = buildStorePath(ctx, params.getPath()); + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("Open file params=" + params + ", storePath=" + storePath); + + // Check if the filesystem is the virtualization view + + if (ctx.isVirtualizationView() && storePath.isReadOnlyPseudoPath()) + { + // Check if the path is for the root, a store or version folder + + if (storePath.isRootPath()) + { + // Return a dummy file for the root folder + + return new PseudoFolderNetworkFile(FileName.DOS_SEPERATOR_STR); + } + else + { + // Find the pseudo file for the store/version folder + + PseudoFile psFile = findPseudoFolder(storePath, ctx); + if (psFile != null) + { + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug(" Found pseudo file " + psFile); + return psFile.getFile(params.getPath()); + } + else + return null; + } + } + + // Search for the file/folder + + sess.beginReadTransaction(m_transactionService); + + AVMNetworkFile netFile = null; + + try + { + // Get the details of the file/folder + + AVMNodeDescriptor nodeDesc = m_avmService.lookup(storePath.getVersion(), storePath.getAVMPath()); + + if (nodeDesc != null) + { + // Check if the filesystem is read-only and write access has been requested + + if (storePath.getVersion() != AVMContext.VERSION_HEAD + && (params.isReadWriteAccess() || params.isWriteOnlyAccess())) + throw new AccessDeniedException("File " + params.getPath() + " is read-only"); + + // Create the network file object for the opened file/folder + + netFile = new AVMNetworkFile(nodeDesc, storePath.getAVMPath(), storePath.getVersion(), m_avmService); + + if (params.isReadOnlyAccess() || storePath.getVersion() != AVMContext.VERSION_HEAD) + netFile.setGrantedAccess(NetworkFile.READONLY); + else + netFile.setGrantedAccess(NetworkFile.READWRITE); + + netFile.setFullName(params.getPath()); + netFile.setFileId(storePath.generateFileId()); + + // Set the mime-type for the new file + + netFile.setMimeType(m_mimetypeService.guessMimetype(params.getPath())); + } + else + throw new FileNotFoundException(params.getPath()); + } + catch (AVMNotFoundException ex) + { + throw new FileNotFoundException(params.getPath()); + } + catch (AVMWrongTypeException ex) + { + throw new FileNotFoundException(params.getPath()); + } + + // Return the file + + return netFile; } /** * Read a block of data from the specified file. * - * @param sess Session details - * @param tree Tree connection - * @param file Network file - * @param buf Buffer to return data to - * @param bufPos Starting position in the return buffer - * @param siz Maximum size of data to return - * @param filePos File offset to read data + * @param sess + * Session details + * @param tree + * Tree connection + * @param file + * Network file + * @param buf + * Buffer to return data to + * @param bufPos + * Starting position in the return buffer + * @param siz + * Maximum size of data to return + * @param filePos + * File offset to read data * @return Number of bytes read - * @exception java.io.IOException The exception description. + * @exception java.io.IOException + * The exception description. */ public int readFile(SrvSession sess, TreeConnection tree, NetworkFile file, byte[] buf, int bufPos, int siz, - long filePos) - throws java.io.IOException + long filePos) throws java.io.IOException { - // Check if the file is a directory - - if ( file.isDirectory()) - throw new AccessDeniedException(); - - // If the content channel is not open for the file then start a transaction - - AVMNetworkFile avmFile = (AVMNetworkFile) file; - - if ( avmFile.hasContentChannel() == false) - sess.beginReadTransaction( m_transactionService); - - // Read the file + // Check if the file is a directory - int rdlen = file.readFile(buf, siz, bufPos, filePos); + if (file.isDirectory()) + throw new AccessDeniedException(); - // If we have reached end of file return a zero length read + // If the content channel is not open for the file then start a transaction - if (rdlen == -1) - rdlen = 0; + AVMNetworkFile avmFile = (AVMNetworkFile) file; - // Return the actual read length + if (avmFile.hasContentChannel() == false) + sess.beginReadTransaction(m_transactionService); - return rdlen; + // Read the file + + int rdlen = file.readFile(buf, siz, bufPos, filePos); + + // If we have reached end of file return a zero length read + + if (rdlen == -1) + rdlen = 0; + + // Return the actual read length + + return rdlen; } /** * Rename the specified file. * - * @param sess Server session - * @param tree Tree connection - * @param oldName java.lang.String - * @param newName java.lang.String - * @exception java.io.IOException The exception description. + * @param sess + * Server session + * @param tree + * Tree connection + * @param oldName + * java.lang.String + * @param newName + * java.lang.String + * @exception java.io.IOException + * The exception description. */ public void renameFile(SrvSession sess, TreeConnection tree, String oldName, String newName) - throws java.io.IOException + throws java.io.IOException { - // Split the relative paths into parent and file/folder name pairs - - AVMContext ctx = (AVMContext) tree.getContext(); - - String[] oldPaths = FileName.splitPath( oldName); - String[] newPaths = FileName.splitPath( newName); - - // Convert the parent paths to store paths - - AVMPath oldAVMPath = buildStorePath( ctx, oldPaths[0]); - AVMPath newAVMPath = buildStorePath( ctx, newPaths[0]); - - // DEBUG - - if ( logger.isDebugEnabled()) - { - logger.debug("Rename from path=" + oldPaths[0] + ", name=" + oldPaths[1]); - logger.debug(" new path=" + newPaths[0] + ", name=" + newPaths[1]); - } + // Split the relative paths into parent and file/folder name pairs - // Check if the filesystem is the virtualization view - - if ( ctx.isVirtualizationView() && oldAVMPath.isReadOnlyPseudoPath()) - { - throw new AccessDeniedException( "Cannot rename folder in store/version layer, " + oldName); - } - - // Start a transaction for the rename - - sess.beginWriteTransaction( m_transactionService); - - try - { - // Rename the file/folder - - m_avmService.rename( oldAVMPath.getAVMPath(), oldPaths[1], newAVMPath.getAVMPath(), newPaths[1]); - } - catch ( AVMNotFoundException ex) - { - throw new IOException( "Source not found, " + oldName); - } - catch ( AVMWrongTypeException ex) - { - throw new IOException( "Invalid path, " + oldName); - } - catch ( AVMExistsException ex) - { - throw new FileExistsException( "Destination exists, " + newName); - } + AVMContext ctx = (AVMContext) tree.getContext(); + + String[] oldPaths = FileName.splitPath(oldName); + String[] newPaths = FileName.splitPath(newName); + + // Convert the parent paths to store paths + + AVMPath oldAVMPath = buildStorePath(ctx, oldPaths[0]); + AVMPath newAVMPath = buildStorePath(ctx, newPaths[0]); + + // DEBUG + + if (logger.isDebugEnabled()) + { + logger.debug("Rename from path=" + oldPaths[0] + ", name=" + oldPaths[1]); + logger.debug(" new path=" + newPaths[0] + ", name=" + newPaths[1]); + } + + // Check if the filesystem is the virtualization view + + if (ctx.isVirtualizationView() && oldAVMPath.isReadOnlyPseudoPath()) + { + throw new AccessDeniedException("Cannot rename folder in store/version layer, " + oldName); + } + + // Start a transaction for the rename + + sess.beginWriteTransaction(m_transactionService); + + try + { + // Rename the file/folder + + m_avmService.rename(oldAVMPath.getAVMPath(), oldPaths[1], newAVMPath.getAVMPath(), newPaths[1]); + } + catch (AVMNotFoundException ex) + { + throw new IOException("Source not found, " + oldName); + } + catch (AVMWrongTypeException ex) + { + throw new IOException("Invalid path, " + oldName); + } + catch (AVMExistsException ex) + { + throw new FileExistsException("Destination exists, " + newName); + } } /** * Seek to the specified file position. * - * @param sess Server session - * @param tree Tree connection - * @param file Network file. - * @param pos Position to seek to. - * @param typ Seek type. + * @param sess + * Server session + * @param tree + * Tree connection + * @param file + * Network file. + * @param pos + * Position to seek to. + * @param typ + * Seek type. * @return New file position, relative to the start of file. */ public long seekFile(SrvSession sess, TreeConnection tree, NetworkFile file, long pos, int typ) - throws java.io.IOException + throws java.io.IOException { - // Check if the file is a directory - - if ( file.isDirectory()) - throw new AccessDeniedException(); - - // If the content channel is not open for the file then start a transaction - - AVMNetworkFile avmFile = (AVMNetworkFile) file; - - if ( avmFile.hasContentChannel() == false) - sess.beginReadTransaction( m_transactionService); - - // Set the file position + // Check if the file is a directory - return file.seekFile(pos, typ); + if (file.isDirectory()) + throw new AccessDeniedException(); + + // If the content channel is not open for the file then start a transaction + + AVMNetworkFile avmFile = (AVMNetworkFile) file; + + if (avmFile.hasContentChannel() == false) + sess.beginReadTransaction(m_transactionService); + + // Set the file position + + return file.seekFile(pos, typ); } /** * Set the file information for the specified file. * - * @param sess Server session - * @param tree Tree connection - * @param name java.lang.String - * @param info FileInfo - * @exception java.io.IOException The exception description. + * @param sess + * Server session + * @param tree + * Tree connection + * @param name + * java.lang.String + * @param info + * FileInfo + * @exception java.io.IOException + * The exception description. */ public void setFileInformation(SrvSession sess, TreeConnection tree, String name, FileInfo info) - throws java.io.IOException + throws java.io.IOException { // Check if the file is being marked for deletion, check if the file is writable - - if ( info.hasSetFlag(FileInfo.SetDeleteOnClose) && info.hasDeleteOnClose()) + + if (info.hasSetFlag(FileInfo.SetDeleteOnClose) && info.hasDeleteOnClose()) { - // If this is not the head version then it's not writable - - AVMContext avmCtx = (AVMContext) tree.getContext(); - if ( avmCtx.isVersion() != AVMContext.VERSION_HEAD) - throw new AccessDeniedException( "Store not writable, cannot set delete on close"); + // If this is not the head version then it's not writable + + AVMContext avmCtx = (AVMContext) tree.getContext(); + if (avmCtx.isVersion() != AVMContext.VERSION_HEAD) + throw new AccessDeniedException("Store not writable, cannot set delete on close"); } } /** - * Start a new search on the filesystem using the specified searchPath that may contain - * wildcards. + * Start a new search on the filesystem using the specified searchPath that may contain wildcards. * - * @param sess Server session - * @param tree Tree connection - * @param searchPath File(s) to search for, may include wildcards. - * @param attrib Attributes of the file(s) to search for, see class SMBFileAttribute. + * @param sess + * Server session + * @param tree + * Tree connection + * @param searchPath + * File(s) to search for, may include wildcards. + * @param attrib + * Attributes of the file(s) to search for, see class SMBFileAttribute. * @return SearchContext - * @exception java.io.FileNotFoundException If the search could not be started. + * @exception java.io.FileNotFoundException + * If the search could not be started. */ public SearchContext startSearch(SrvSession sess, TreeConnection tree, String searchPath, int attrib) - throws java.io.FileNotFoundException + throws java.io.FileNotFoundException { - // Access the AVM context - - AVMContext avmCtx = (AVMContext) tree.getContext(); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Start search path=" + searchPath); + // Access the AVM context - // Split the search path into relative path and search name - - String[] paths = FileName.splitPath( searchPath); - - // Build the store path to the folder being searched - - AVMPath storePath = buildStorePath( avmCtx, paths[0]); - - // Check if the filesystem is the virtualization view - - if ( avmCtx.isVirtualizationView()) - { - // Check for a search of a pseudo folder + AVMContext avmCtx = (AVMContext) tree.getContext(); - if (storePath.isReadOnlyPseudoPath()) - { - // Get the file state for the folder being searched - - FileState fstate = findPseudoState( storePath, avmCtx); - - if ( fstate != null) - { - // Get the pseudo file list for the parent directory - - PseudoFileList searchList = fstate.getPseudoFileList(); - - // Check if this is a single file or wildcard search - - if ( WildCard.containsWildcards( searchPath)) - { - // Check if the pseudo file list is valid - - if ( searchList == null) - searchList = new PseudoFileList(); - - // Create the search context, wildcard filter will take care of secondary filtering of the - // folder listing - - WildCard wildCardFilter = new WildCard( paths[1], false); - return new PseudoFileListSearchContext( searchList, attrib, wildCardFilter); - } - else - { - // Search the pseudo file list for the required file - - PseudoFile pseudoFile = searchList.findFile( paths[1], false); - if ( pseudoFile != null) - { - // Create a search context using the single file details - - PseudoFileList singleList = new PseudoFileList(); - singleList.addFile( pseudoFile); - - return new PseudoFileListSearchContext( singleList, attrib, null); - } - } - } - - // File not found - - throw new FileNotFoundException( searchPath); - } - else if ( storePath.isLevel() == AVMPath.LevelId.HeadMetaData || storePath.isLevel() == AVMPath.LevelId.VersionMetaData) - { - // Return an empty file list for now - - PseudoFileList metaFiles = new PseudoFileList(); - - return new PseudoFileListSearchContext( metaFiles, attrib, null); - } - } + // DEBUG - // Check if the path is a wildcard search - - sess.beginReadTransaction( m_transactionService); - SearchContext context = null; - - if ( WildCard.containsWildcards( searchPath)) - { - // Get the file listing for the folder - - AVMNodeDescriptor[] fileList = m_avmService.getDirectoryListingArray( storePath.getVersion(), storePath.getAVMPath(), false); - - // Create the search context - - if ( fileList != null) { + if (logger.isDebugEnabled()) + logger.debug("Start search path=" + searchPath); - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug(" Wildcard search returned " + fileList.length + " files"); - - // Create the search context, wildcard filter will take care of secondary filtering of the - // folder listing - - WildCard wildCardFilter = new WildCard( paths[1], false); - context = new AVMSearchContext( fileList, attrib, wildCardFilter, storePath.getRelativePath()); - } - } - else - { - // Single file/folder search, convert the path to a store path - - storePath = buildStorePath( avmCtx, searchPath); - - // Get the single file/folder details - - AVMNodeDescriptor nodeDesc = m_avmService.lookup( storePath.getVersion(), storePath.getAVMPath()); - - if ( nodeDesc != null) - { - // Create the search context for the single file/folder - - context = new AVMSingleFileSearchContext( nodeDesc, storePath.getRelativePath()); - } - - } - - // Return the search context - - return context; + // Split the search path into relative path and search name + + String[] paths = FileName.splitPath(searchPath); + + // Build the store path to the folder being searched + + AVMPath storePath = buildStorePath(avmCtx, paths[0]); + + // Check if the filesystem is the virtualization view + + if (avmCtx.isVirtualizationView()) + { + // Check for a search of a pseudo folder + + if (storePath.isReadOnlyPseudoPath()) + { + // Get the file state for the folder being searched + + FileState fstate = findPseudoState(storePath, avmCtx); + + if (fstate != null) + { + // Get the pseudo file list for the parent directory + + PseudoFileList searchList = fstate.getPseudoFileList(); + + // Check if this is a single file or wildcard search + + if (WildCard.containsWildcards(searchPath)) + { + // Check if the pseudo file list is valid + + if (searchList == null) + searchList = new PseudoFileList(); + + // Create the search context, wildcard filter will take care of secondary filtering of the + // folder listing + + WildCard wildCardFilter = new WildCard(paths[1], false); + return new PseudoFileListSearchContext(searchList, attrib, wildCardFilter); + } + else + { + // Search the pseudo file list for the required file + + PseudoFile pseudoFile = searchList.findFile(paths[1], false); + if (pseudoFile != null) + { + // Create a search context using the single file details + + PseudoFileList singleList = new PseudoFileList(); + singleList.addFile(pseudoFile); + + return new PseudoFileListSearchContext(singleList, attrib, null); + } + } + } + + // File not found + + throw new FileNotFoundException(searchPath); + } + else if (storePath.isLevel() == AVMPath.LevelId.HeadMetaData + || storePath.isLevel() == AVMPath.LevelId.VersionMetaData) + { + // Return an empty file list for now + + PseudoFileList metaFiles = new PseudoFileList(); + + return new PseudoFileListSearchContext(metaFiles, attrib, null); + } + } + + // Check if the path is a wildcard search + + sess.beginReadTransaction(m_transactionService); + SearchContext context = null; + + if (WildCard.containsWildcards(searchPath)) + { + // Get the file listing for the folder + + AVMNodeDescriptor[] fileList = m_avmService.getDirectoryListingArray(storePath.getVersion(), storePath + .getAVMPath(), false); + + // Create the search context + + if (fileList != null) + { + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug(" Wildcard search returned " + fileList.length + " files"); + + // Create the search context, wildcard filter will take care of secondary filtering of the + // folder listing + + WildCard wildCardFilter = new WildCard(paths[1], false); + context = new AVMSearchContext(fileList, attrib, wildCardFilter, storePath.getRelativePath()); + } + } + else + { + // Single file/folder search, convert the path to a store path + + storePath = buildStorePath(avmCtx, searchPath); + + // Get the single file/folder details + + AVMNodeDescriptor nodeDesc = m_avmService.lookup(storePath.getVersion(), storePath.getAVMPath()); + + if (nodeDesc != null) + { + // Create the search context for the single file/folder + + context = new AVMSingleFileSearchContext(nodeDesc, storePath.getRelativePath()); + } + + } + + // Return the search context + + return context; } /** * Truncate a file to the specified size * - * @param sess Server session - * @param tree Tree connection - * @param file Network file details - * @param siz New file length - * @exception java.io.IOException The exception description. + * @param sess + * Server session + * @param tree + * Tree connection + * @param file + * Network file details + * @param siz + * New file length + * @exception java.io.IOException + * The exception description. */ public void truncateFile(SrvSession sess, TreeConnection tree, NetworkFile file, long siz) - throws java.io.IOException + throws java.io.IOException { // Check if the file is a directory, or only has read access - if ( file.getGrantedAccess() == NetworkFile.READONLY) - throw new AccessDeniedException(); - - // If the content channel is not open for the file then start a transaction - - AVMNetworkFile avmFile = (AVMNetworkFile) file; - - if ( avmFile.hasContentChannel() == false || avmFile.isWritable() == false) - sess.beginWriteTransaction( m_transactionService); - - // Truncate or extend the file - - file.truncateFile(siz); - file.flushFile(); + if (file.getGrantedAccess() == NetworkFile.READONLY) + throw new AccessDeniedException(); + + // If the content channel is not open for the file then start a transaction + + AVMNetworkFile avmFile = (AVMNetworkFile) file; + + if (avmFile.hasContentChannel() == false || avmFile.isWritable() == false) + sess.beginWriteTransaction(m_transactionService); + + // Truncate or extend the file + + file.truncateFile(siz); + file.flushFile(); } /** * Write a block of data to the file. * - * @param sess Server session - * @param tree Tree connection - * @param file Network file details - * @param buf byte[] Data to be written - * @param bufoff Offset within the buffer that the data starts - * @param siz int Data length - * @param fileoff Position within the file that the data is to be written. + * @param sess + * Server session + * @param tree + * Tree connection + * @param file + * Network file details + * @param buf + * byte[] Data to be written + * @param bufoff + * Offset within the buffer that the data starts + * @param siz + * int Data length + * @param fileoff + * Position within the file that the data is to be written. * @return Number of bytes actually written - * @exception java.io.IOException The exception description. + * @exception java.io.IOException + * The exception description. */ public int writeFile(SrvSession sess, TreeConnection tree, NetworkFile file, byte[] buf, int bufoff, int siz, - long fileoff) - throws java.io.IOException + long fileoff) throws java.io.IOException { // Check if the file is a directory, or only has read access - if ( file.isDirectory() || file.getGrantedAccess() == NetworkFile.READONLY) - throw new AccessDeniedException(); + if (file.isDirectory() || file.getGrantedAccess() == NetworkFile.READONLY) + throw new AccessDeniedException(); - // If the content channel is not open for the file, or the channel is not writable, then start a transaction - - AVMNetworkFile avmFile = (AVMNetworkFile) file; - - if ( avmFile.hasContentChannel() == false || avmFile.isWritable() == false) - sess.beginWriteTransaction( m_transactionService); - - // Write the data to the file - - file.writeFile(buf, siz, bufoff, fileoff); + // If the content channel is not open for the file, or the channel is not writable, then start a transaction - // Return the actual write length + AVMNetworkFile avmFile = (AVMNetworkFile) file; - return siz; + if (avmFile.hasContentChannel() == false || avmFile.isWritable() == false) + sess.beginWriteTransaction(m_transactionService); + + // Write the data to the file + + file.writeFile(buf, siz, bufoff, fileoff); + + // Return the actual write length + + return siz; } - + /** * Connection opened to this disk device * - * @param sess Server session - * @param tree Tree connection + * @param sess + * Server session + * @param tree + * Tree connection */ public void treeClosed(SrvSession sess, TreeConnection tree) { @@ -1705,521 +1832,534 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface { /** * Connection closed to this device * - * @param sess Server session - * @param tree Tree connection + * @param sess + * Server session + * @param tree + * Tree connection */ public void treeOpened(SrvSession sess, TreeConnection tree) { // Nothing to do } - + /** * Find the pseudo file for a virtual path * - * @param avmPath AVMPath - * @param avmCtx AVMContext + * @param avmPath + * AVMPath + * @param avmCtx + * AVMContext * @return PseudoFile */ - private final PseudoFile findPseudoFolder( AVMPath avmPath, AVMContext avmCtx) + private final PseudoFile findPseudoFolder(AVMPath avmPath, AVMContext avmCtx) { - return findPseudoFolder( avmPath, avmCtx, true); + return findPseudoFolder(avmPath, avmCtx, true); } - + /** * Find the pseudo file for a virtual path * - * @param avmPath AVMPath - * @param avmCtx AVMContext - * @param generateStates boolean + * @param avmPath + * AVMPath + * @param avmCtx + * AVMContext + * @param generateStates + * boolean * @return PseudoFile */ - private final PseudoFile findPseudoFolder( AVMPath avmPath, AVMContext avmCtx, boolean generateStates) + private final PseudoFile findPseudoFolder(AVMPath avmPath, AVMContext avmCtx, boolean generateStates) { - // Check if the path is to a store pseudo folder + // Check if the path is to a store pseudo folder - if ( avmPath.isRootPath()) - return null; - - // Get the file state for the parent of the required folder - - FileState fstate = null; - StringBuilder str = null; - PseudoFile psFile = null; - - switch ( avmPath.isLevel()) - { - // Store root folder - - case StoreRoot: - - // Get the root folder file state - - fstate = avmCtx.getStateTable().findFileState( FileName.DOS_SEPERATOR_STR); - - if ( fstate != null && fstate.hasPseudoFiles()) - psFile = fstate.getPseudoFileList().findFile( avmPath.getStoreName(), false); - break; - - // Versions root or Head folder - - case VersionRoot: - case Head: - - // Create a path to the parent store - - str = new StringBuilder(); - - str.append( FileName.DOS_SEPERATOR); - str.append( avmPath.getStoreName()); - - // Find/create the file state for the store - - AVMPath storePath = new AVMPath( str.toString()); - fstate = findPseudoState( storePath, avmCtx); + if (avmPath.isRootPath()) + return null; - // Find the version root or head pseudo folder - - if ( fstate != null) - { - if ( avmPath.isLevel() == AVMPath.LevelId.Head) - psFile = fstate.getPseudoFileList().findFile( AVMPath.VersionNameHead, true); - else - psFile = fstate.getPseudoFileList().findFile( AVMPath.VersionsFolder, true); - } - break; - - // Version folder - - case Version: + // Get the file state for the parent of the required folder - // Create a path to the versions folder - - str = new StringBuilder(); - - str.append( FileName.DOS_SEPERATOR); - str.append( avmPath.getStoreName()); - str.append( FileName.DOS_SEPERATOR); - str.append( AVMPath.VersionsFolder); - - // Find/create the file state for the store - - AVMPath verrootPath = new AVMPath( str.toString()); - fstate = findPseudoState( verrootPath, avmCtx); + FileState fstate = null; + StringBuilder str = null; + PseudoFile psFile = null; - // Find the version pseudo file - - if ( fstate != null) - { - // Build the version folder name string - - str.setLength( 0); - - str.append( AVMPath.VersionFolderPrefix); - str.append( avmPath.getVersion()); - - // find the version folder pseduo file - - psFile = fstate.getPseudoFileList().findFile( str.toString(), true); - } - break; - - // Head data or metadata folder - - case HeadData: - case HeadMetaData: + switch (avmPath.isLevel()) + { + // Store root folder - // Create a path to the head folder - - str = new StringBuilder(); - - str.append( FileName.DOS_SEPERATOR); - str.append( avmPath.getStoreName()); - str.append( FileName.DOS_SEPERATOR); - str.append( AVMPath.VersionNameHead); - - // Find/create the file state for the store - - AVMPath headPath = new AVMPath( str.toString()); - fstate = findPseudoState( headPath, avmCtx); + case StoreRoot: - // Find the data or metadata pseudo folder - - if ( fstate != null) - { - // Find the pseudo folder - - if ( avmPath.isLevel() == AVMPath.LevelId.HeadData) - { - psFile = fstate.getPseudoFileList().findFile( AVMPath.DataFolder, true); - } - else - { - psFile = fstate.getPseudoFileList().findFile( AVMPath.MetaDataFolder, true); - } - } - break; + // Get the root folder file state - // Version data or metadata folder - - case VersionData: - case VersionMetaData: + fstate = avmCtx.getStateTable().findFileState(FileName.DOS_SEPERATOR_STR); - // Create a path to the version folder - - str = new StringBuilder(); - - str.append( FileName.DOS_SEPERATOR); - str.append( avmPath.getStoreName()); - str.append( FileName.DOS_SEPERATOR); - str.append( AVMPath.VersionFolderPrefix); - str.append( avmPath.getVersion()); - - // Find/create the file state for the store - - AVMPath verPath = new AVMPath( str.toString()); - fstate = findPseudoState( verPath, avmCtx); + if (fstate != null && fstate.hasPseudoFiles()) + psFile = fstate.getPseudoFileList().findFile(avmPath.getStoreName(), false); + break; - // Find the data or metadata pseudo folder - - if ( fstate != null) - { - // Find the pseudo folder - - if ( avmPath.isLevel() == AVMPath.LevelId.VersionData) - { - psFile = fstate.getPseudoFileList().findFile( AVMPath.DataFolder, true); - } - else - { - psFile = fstate.getPseudoFileList().findFile( AVMPath.MetaDataFolder, true); - } - } - break; - } + // Versions root or Head folder - // Check if the pseudo file was not found but file states should be generated - - if ( psFile == null && generateStates == true) - { - // Generate the file states for the path, this is required if a request is made to a path without - // walking the folder tree - - generatePseudoFolders( avmPath, avmCtx); - - // Try and find the pseudo file again - - psFile = findPseudoFolder( avmPath, avmCtx, false); - } - - // Return the pseudo file, or null if not found - - return psFile; + case VersionRoot: + case Head: + + // Create a path to the parent store + + str = new StringBuilder(); + + str.append(FileName.DOS_SEPERATOR); + str.append(avmPath.getStoreName()); + + // Find/create the file state for the store + + AVMPath storePath = new AVMPath(str.toString()); + fstate = findPseudoState(storePath, avmCtx); + + // Find the version root or head pseudo folder + + if (fstate != null) + { + if (avmPath.isLevel() == AVMPath.LevelId.Head) + psFile = fstate.getPseudoFileList().findFile(AVMPath.VersionNameHead, true); + else + psFile = fstate.getPseudoFileList().findFile(AVMPath.VersionsFolder, true); + } + break; + + // Version folder + + case Version: + + // Create a path to the versions folder + + str = new StringBuilder(); + + str.append(FileName.DOS_SEPERATOR); + str.append(avmPath.getStoreName()); + str.append(FileName.DOS_SEPERATOR); + str.append(AVMPath.VersionsFolder); + + // Find/create the file state for the store + + AVMPath verrootPath = new AVMPath(str.toString()); + fstate = findPseudoState(verrootPath, avmCtx); + + // Find the version pseudo file + + if (fstate != null) + { + // Build the version folder name string + + str.setLength(0); + + str.append(AVMPath.VersionFolderPrefix); + str.append(avmPath.getVersion()); + + // find the version folder pseduo file + + psFile = fstate.getPseudoFileList().findFile(str.toString(), true); + } + break; + + // Head data or metadata folder + + case HeadData: + case HeadMetaData: + + // Create a path to the head folder + + str = new StringBuilder(); + + str.append(FileName.DOS_SEPERATOR); + str.append(avmPath.getStoreName()); + str.append(FileName.DOS_SEPERATOR); + str.append(AVMPath.VersionNameHead); + + // Find/create the file state for the store + + AVMPath headPath = new AVMPath(str.toString()); + fstate = findPseudoState(headPath, avmCtx); + + // Find the data or metadata pseudo folder + + if (fstate != null) + { + // Find the pseudo folder + + if (avmPath.isLevel() == AVMPath.LevelId.HeadData) + { + psFile = fstate.getPseudoFileList().findFile(AVMPath.DataFolder, true); + } + else + { + psFile = fstate.getPseudoFileList().findFile(AVMPath.MetaDataFolder, true); + } + } + break; + + // Version data or metadata folder + + case VersionData: + case VersionMetaData: + + // Create a path to the version folder + + str = new StringBuilder(); + + str.append(FileName.DOS_SEPERATOR); + str.append(avmPath.getStoreName()); + str.append(FileName.DOS_SEPERATOR); + str.append(AVMPath.VersionFolderPrefix); + str.append(avmPath.getVersion()); + + // Find/create the file state for the store + + AVMPath verPath = new AVMPath(str.toString()); + fstate = findPseudoState(verPath, avmCtx); + + // Find the data or metadata pseudo folder + + if (fstate != null) + { + // Find the pseudo folder + + if (avmPath.isLevel() == AVMPath.LevelId.VersionData) + { + psFile = fstate.getPseudoFileList().findFile(AVMPath.DataFolder, true); + } + else + { + psFile = fstate.getPseudoFileList().findFile(AVMPath.MetaDataFolder, true); + } + } + break; + } + + // Check if the pseudo file was not found but file states should be generated + + if (psFile == null && generateStates == true) + { + // Generate the file states for the path, this is required if a request is made to a path without + // walking the folder tree + + generatePseudoFolders(avmPath, avmCtx); + + // Try and find the pseudo file again + + psFile = findPseudoFolder(avmPath, avmCtx, false); + } + + // Return the pseudo file, or null if not found + + return psFile; } - + /** * Find the file state for a pseudo folder path * - * @param avmPath AVMPath - * @param avmCtx AVMContext + * @param avmPath + * AVMPath + * @param avmCtx + * AVMContext * @return FileState */ - private final FileState findPseudoState( AVMPath avmPath, AVMContext avmCtx) + private final FileState findPseudoState(AVMPath avmPath, AVMContext avmCtx) { - // Make sure the is to a pseudo file/folder - - if ( avmPath.isPseudoPath() == false) - return null; - - // Check if the path is to a store pseudo folder - - FileState fstate = null; - StringBuilder str = null; + // Make sure the is to a pseudo file/folder - switch ( avmPath.isLevel()) - { - // Root of the hieararchy - - case Root: + if (avmPath.isPseudoPath() == false) + return null; - // Get the root path file state - - fstate = avmCtx.getStateTable().findFileState( FileName.DOS_SEPERATOR_STR); - - // Check if the root file state is valid - - if ( fstate == null) - { - // Create a file state for the root folder - - fstate = avmCtx.getStateTable().findFileState( FileName.DOS_SEPERATOR_STR, true, true); - fstate.setExpiryTime( FileState.NoTimeout); - - // Get a list of the available AVM stores - - List storeList = m_avmService.getStores(); - - if ( storeList != null && storeList.size() > 0) - { - // Add pseudo files for the stores - - boolean sandbox = false; - - for ( AVMStoreDescriptor storeDesc : storeList) - { - // Get the properties for the current store - - Map props = m_avmService.getStoreProperties( storeDesc.getName()); - - if ( props.containsKey( AVMContext.PROP_WORKFLOWPREVIEW) || props.containsKey( AVMContext.PROP_AUTHORPREVIEW)) - sandbox = true; - else - sandbox = false; + // Check if the path is to a store pseudo folder - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug( "Store " + storeDesc.getName() + ", sandbox=" + sandbox); - - // Add a pseudo file for the current store + FileState fstate = null; + StringBuilder str = null; - if ( sandbox == false || avmCtx.showSandboxes() == true) - fstate.addPseudoFile( new StorePseudoFile( storeDesc)); - } - } - } - break; - - // Store folder - - case StoreRoot: - - // Build the path to the parent store folder - - str = new StringBuilder(); - - str.append( FileName.DOS_SEPERATOR); - str.append( avmPath.getStoreName()); - - // Search for the file state for the store pseudo folder - - fstate = avmCtx.getStateTable().findFileState( str.toString()); - - if ( fstate == null) - { - // Create a file state for the store path - - fstate = avmCtx.getStateTable().findFileState( str.toString(), true, true); - - // Add a pseudo file for the head version - - fstate.addPseudoFile( new VersionPseudoFile( AVMPath.VersionNameHead)); - - // Add a pseudo file for the version root folder - - fstate.addPseudoFile( new DummyFolderPseudoFile( AVMPath.VersionsFolder)); - } - break; + switch (avmPath.isLevel()) + { + // Root of the hieararchy - // Head folder - - case Head: + case Root: - // Build the path to the store head version folder - - str = new StringBuilder(); - - str.append( FileName.DOS_SEPERATOR); - str.append( avmPath.getStoreName()); - str.append( FileName.DOS_SEPERATOR); - str.append( AVMPath.VersionNameHead); - - // Search for the file state for the store head version pseudo folder - - fstate = avmCtx.getStateTable().findFileState( str.toString()); - - if ( fstate == null) - { - // Create a file state for the store head folder path - - fstate = avmCtx.getStateTable().findFileState( str.toString(), true, true); - - // Add a pseudo file for the data pseudo folder - - fstate.addPseudoFile( new DummyFolderPseudoFile( AVMPath.DataFolder)); - - // Add a pseudo file for the metadata pseudo folder - - fstate.addPseudoFile( new DummyFolderPseudoFile( AVMPath.MetaDataFolder)); - } - break; - - // Version root folder - - case VersionRoot: + // Get the root path file state - // Get the list of AVM store versions + fstate = avmCtx.getStateTable().findFileState(FileName.DOS_SEPERATOR_STR); - try - { - // Build the path to the parent store folder - - str = new StringBuilder(); - - str.append( FileName.DOS_SEPERATOR); - str.append( avmPath.getStoreName()); - str.append( FileName.DOS_SEPERATOR); - str.append( AVMPath.VersionsFolder); - - // Create a file state for the store path - - fstate = avmCtx.getStateTable().findFileState( str.toString(), true, true); - - // Add pseudo folders if the list is empty - - if ( fstate.hasPseudoFiles() == false) - { - // Build the version folder name for the head version - - StringBuilder verStr = new StringBuilder( AVMPath.VersionFolderPrefix); - verStr.append( "-1"); - - // Add a pseudo file for the head version - - fstate.addPseudoFile( new VersionPseudoFile( verStr.toString())); - - // Get the list of versions for the store - - List verList = m_avmService.getStoreVersions( avmPath.getStoreName()); - - // Add pseudo files for the versions to the store state - - if ( verList.size() > 0) - { - for ( VersionDescriptor verDesc : verList) - { - // Generate the version string - - String verName = null; - - verStr.setLength( AVMPath.VersionFolderPrefix.length()); - verStr.append( verDesc.getVersionID()); - - verName = verStr.toString(); - - // Add the version pseudo folder - - fstate.addPseudoFile( new VersionPseudoFile ( verName, verDesc)); - } - } - } - } - catch ( AVMNotFoundException ex) - { - // Invalid store name - } - break; + // Check if the root file state is valid - // Version folder - - case Version: + if (fstate == null) + { + // Create a file state for the root folder - // Build the path to the store version folder - - str = new StringBuilder(); - - str.append( FileName.DOS_SEPERATOR); - str.append( avmPath.getStoreName()); - str.append( FileName.DOS_SEPERATOR); - str.append( AVMPath.VersionFolderPrefix); - str.append( avmPath.getVersion()); - - // Search for the file state for the version pseudo folder - - fstate = avmCtx.getStateTable().findFileState( str.toString()); - - if ( fstate == null) - { - // Create a file state for the version folder path - - fstate = avmCtx.getStateTable().findFileState( str.toString(), true, true); - - // Add a pseudo file for the data pseudo folder - - fstate.addPseudoFile( new DummyFolderPseudoFile( AVMPath.DataFolder)); - - // Add a pseudo file for the metadata pseudo folder - - fstate.addPseudoFile( new DummyFolderPseudoFile( AVMPath.MetaDataFolder)); - } - break; - } + fstate = avmCtx.getStateTable().findFileState(FileName.DOS_SEPERATOR_STR, true, true); + fstate.setExpiryTime(FileState.NoTimeout); - // Return the file state - - return fstate; + // Get a list of the available AVM stores + + List storeList = m_avmService.getStores(); + + if (storeList != null && storeList.size() > 0) + { + // Add pseudo files for the stores + + boolean sandbox = false; + + for (AVMStoreDescriptor storeDesc : storeList) + { + // Get the properties for the current store + + Map props = m_avmService.getStoreProperties(storeDesc.getName()); + + if (props.containsKey(AVMContext.PROP_WORKFLOWPREVIEW) + || props.containsKey(AVMContext.PROP_AUTHORPREVIEW)) + sandbox = true; + else + sandbox = false; + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("Store " + storeDesc.getName() + ", sandbox=" + sandbox); + + // Add a pseudo file for the current store + + if (sandbox == false || avmCtx.showSandboxes() == true) + fstate.addPseudoFile(new StorePseudoFile(storeDesc)); + } + } + } + break; + + // Store folder + + case StoreRoot: + + // Build the path to the parent store folder + + str = new StringBuilder(); + + str.append(FileName.DOS_SEPERATOR); + str.append(avmPath.getStoreName()); + + // Search for the file state for the store pseudo folder + + fstate = avmCtx.getStateTable().findFileState(str.toString()); + + if (fstate == null) + { + // Create a file state for the store path + + fstate = avmCtx.getStateTable().findFileState(str.toString(), true, true); + + // Add a pseudo file for the head version + + fstate.addPseudoFile(new VersionPseudoFile(AVMPath.VersionNameHead)); + + // Add a pseudo file for the version root folder + + fstate.addPseudoFile(new DummyFolderPseudoFile(AVMPath.VersionsFolder)); + } + break; + + // Head folder + + case Head: + + // Build the path to the store head version folder + + str = new StringBuilder(); + + str.append(FileName.DOS_SEPERATOR); + str.append(avmPath.getStoreName()); + str.append(FileName.DOS_SEPERATOR); + str.append(AVMPath.VersionNameHead); + + // Search for the file state for the store head version pseudo folder + + fstate = avmCtx.getStateTable().findFileState(str.toString()); + + if (fstate == null) + { + // Create a file state for the store head folder path + + fstate = avmCtx.getStateTable().findFileState(str.toString(), true, true); + + // Add a pseudo file for the data pseudo folder + + fstate.addPseudoFile(new DummyFolderPseudoFile(AVMPath.DataFolder)); + + // Add a pseudo file for the metadata pseudo folder + + fstate.addPseudoFile(new DummyFolderPseudoFile(AVMPath.MetaDataFolder)); + } + break; + + // Version root folder + + case VersionRoot: + + // Get the list of AVM store versions + + try + { + // Build the path to the parent store folder + + str = new StringBuilder(); + + str.append(FileName.DOS_SEPERATOR); + str.append(avmPath.getStoreName()); + str.append(FileName.DOS_SEPERATOR); + str.append(AVMPath.VersionsFolder); + + // Create a file state for the store path + + fstate = avmCtx.getStateTable().findFileState(str.toString(), true, true); + + // Add pseudo folders if the list is empty + + if (fstate.hasPseudoFiles() == false) + { + // Build the version folder name for the head version + + StringBuilder verStr = new StringBuilder(AVMPath.VersionFolderPrefix); + verStr.append("-1"); + + // Add a pseudo file for the head version + + fstate.addPseudoFile(new VersionPseudoFile(verStr.toString())); + + // Get the list of versions for the store + + List verList = m_avmService.getStoreVersions(avmPath.getStoreName()); + + // Add pseudo files for the versions to the store state + + if (verList.size() > 0) + { + for (VersionDescriptor verDesc : verList) + { + // Generate the version string + + String verName = null; + + verStr.setLength(AVMPath.VersionFolderPrefix.length()); + verStr.append(verDesc.getVersionID()); + + verName = verStr.toString(); + + // Add the version pseudo folder + + fstate.addPseudoFile(new VersionPseudoFile(verName, verDesc)); + } + } + } + } + catch (AVMNotFoundException ex) + { + // Invalid store name + } + break; + + // Version folder + + case Version: + + // Build the path to the store version folder + + str = new StringBuilder(); + + str.append(FileName.DOS_SEPERATOR); + str.append(avmPath.getStoreName()); + str.append(FileName.DOS_SEPERATOR); + str.append(AVMPath.VersionFolderPrefix); + str.append(avmPath.getVersion()); + + // Search for the file state for the version pseudo folder + + fstate = avmCtx.getStateTable().findFileState(str.toString()); + + if (fstate == null) + { + // Create a file state for the version folder path + + fstate = avmCtx.getStateTable().findFileState(str.toString(), true, true); + + // Add a pseudo file for the data pseudo folder + + fstate.addPseudoFile(new DummyFolderPseudoFile(AVMPath.DataFolder)); + + // Add a pseudo file for the metadata pseudo folder + + fstate.addPseudoFile(new DummyFolderPseudoFile(AVMPath.MetaDataFolder)); + } + break; + } + + // Return the file state + + return fstate; } - + /** * Generate the pseudo folders for the specified path * - * @param avmPath AVMPath - * @param avmCtx AVMContext + * @param avmPath + * AVMPath + * @param avmCtx + * AVMContext */ - private final void generatePseudoFolders( AVMPath avmPath, AVMContext avmCtx) - { - // Create the root file state - - AVMPath createPath = new AVMPath(); - StringBuilder pathStr = new StringBuilder(); - - pathStr.append( FileName.DOS_SEPERATOR); - createPath.parsePath( pathStr.toString()); - - FileState rootState = findPseudoState( createPath, avmCtx); - - // Check if the path has a store name - - if ( avmPath.getStoreName() != null) - { - // Check if the store name is valid - - if ( rootState.hasPseudoFiles() && rootState.getPseudoFileList().findFile( avmPath.getStoreName(), false) != null) - { - // Create the store file state - - pathStr.append( avmPath.getStoreName()); - pathStr.append( FileName.DOS_SEPERATOR); - - createPath.parsePath( pathStr.toString()); - - findPseudoState( createPath, avmCtx); - - // Add the head and version root pseudo folders - - createPath.parsePath( pathStr.toString() + AVMPath.VersionNameHead); - findPseudoState( createPath, avmCtx); - - createPath.parsePath( pathStr.toString() + AVMPath.VersionsFolder); - findPseudoState( createPath, avmCtx); - - // Check if the path is to a version folder - - if ( avmPath.isLevel().ordinal() >= AVMPath.LevelId.Version.ordinal()) - { - // Build the path - - pathStr.append( AVMPath.VersionsFolder); - pathStr.append( FileName.DOS_SEPERATOR); - pathStr.append( AVMPath.VersionFolderPrefix); - pathStr.append( avmPath.getVersion()); - - createPath.parsePath( pathStr.toString()); - - // Generate the version folders - - findPseudoState( createPath, avmCtx); - } - } - } - } + private final void generatePseudoFolders(AVMPath avmPath, AVMContext avmCtx) + { + // Create the root file state + + AVMPath createPath = new AVMPath(); + StringBuilder pathStr = new StringBuilder(); + + pathStr.append(FileName.DOS_SEPERATOR); + createPath.parsePath(pathStr.toString()); + + FileState rootState = findPseudoState(createPath, avmCtx); + + // Check if the path has a store name + + if (avmPath.getStoreName() != null) + { + // Check if the store name is valid + + if (rootState.hasPseudoFiles() + && rootState.getPseudoFileList().findFile(avmPath.getStoreName(), false) != null) + { + // Create the store file state + + pathStr.append(avmPath.getStoreName()); + pathStr.append(FileName.DOS_SEPERATOR); + + createPath.parsePath(pathStr.toString()); + + findPseudoState(createPath, avmCtx); + + // Add the head and version root pseudo folders + + createPath.parsePath(pathStr.toString() + AVMPath.VersionNameHead); + findPseudoState(createPath, avmCtx); + + createPath.parsePath(pathStr.toString() + AVMPath.VersionsFolder); + findPseudoState(createPath, avmCtx); + + // Check if the path is to a version folder + + if (avmPath.isLevel().ordinal() >= AVMPath.LevelId.Version.ordinal()) + { + // Build the path + + pathStr.append(AVMPath.VersionsFolder); + pathStr.append(FileName.DOS_SEPERATOR); + pathStr.append(AVMPath.VersionFolderPrefix); + pathStr.append(avmPath.getVersion()); + + createPath.parsePath(pathStr.toString()); + + // Generate the version folders + + findPseudoState(createPath, avmCtx); + } + } + } + } } diff --git a/source/java/org/alfresco/repo/avm/AVMServiceImpl.java b/source/java/org/alfresco/repo/avm/AVMServiceImpl.java index a20764fe47..d8312fb5d7 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceImpl.java @@ -33,7 +33,6 @@ import java.util.List; import java.util.Map; import java.util.SortedMap; -import org.alfresco.repo.avm.AVMRepository; import org.alfresco.repo.domain.DbAccessControlList; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; @@ -1397,6 +1396,9 @@ public class AVMServiceImpl implements AVMService { InputStream in = getFileInputStream(version, desc.getPath()); createFile(path, name, in); + ContentData cd = getContentDataForRead(version, desc.getPath()); + setEncoding(newPath, cd.getEncoding()); + setMimeType(newPath, cd.getMimetype()); } else // desc is a directory. { diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index 389473d47d..08a5e1fb92 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -47,7 +47,10 @@ import org.alfresco.repo.avm.actions.AVMUndoSandboxListAction; import org.alfresco.repo.avm.actions.SimpleAVMPromoteAction; import org.alfresco.repo.avm.actions.SimpleAVMSubmitAction; import org.alfresco.repo.avm.util.BulkLoader; +import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; +import org.alfresco.repo.search.impl.lucene.analysis.NumericEncoder; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.TransactionUtil; import org.alfresco.service.cmr.avm.AVMBadArgumentException; @@ -63,12 +66,18 @@ import org.alfresco.service.cmr.avm.deploy.DeploymentReport; import org.alfresco.service.cmr.avm.deploy.DeploymentService; import org.alfresco.service.cmr.avmsync.AVMDifference; import org.alfresco.service.cmr.avmsync.AVMSyncException; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.remote.RepoRemote; import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.CrossRepositoryCopyService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.ResultSetRow; +import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; @@ -80,6 +89,7 @@ import org.alfresco.util.Pair; /** * Big test of AVM behavior. + * * @author britt */ public class AVMServiceTest extends AVMServiceTestBase @@ -89,7 +99,7 @@ public class AVMServiceTest extends AVMServiceTestBase try { setupBasicTree(); - fService.removeNode("main:/a/b/c/foo"); + fService.removeNode("main:/a/b/c/foo"); fService.createSnapshot("main", null, null); AVMNodeDescriptor desc = fService.forceCopy("main:/a/b/c/foo"); assertTrue(desc.isDeleted()); @@ -100,21 +110,24 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + public void testLayerSnapshots() { try { + // Layers are not yet indexed setupBasicTree(); assertEquals(1, fService.createSnapshot("main", null, null)); + runQueriesAgainstBasicTree("main"); fService.createStore("layer"); fService.createLayeredDirectory("main:/a", "layer:/", "a"); fService.createSnapshot("layer", null, null); + runQueriesAgainstBasicTree("main"); fService.createFile("main:/a", "Xander"); fService.createSnapshot("layer", null, null); + runQueriesAgainstBasicTree("main"); assertEquals(2, fService.lookup(2, "layer:/a").getIndirectionVersion()); - assertEquals(fService.lookup(2, "main:/a/Xander").getId(), - fService.lookup(2, "layer:/a/Xander").getId()); + assertEquals(fService.lookup(2, "main:/a/Xander").getId(), fService.lookup(2, "layer:/a/Xander").getId()); assertNull(fService.lookup(1, "layer:/a/Xander")); } catch (Exception e) @@ -123,11 +136,12 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + public void testBranchLayerSnapshot() { try { + // layers are not ye indexed setupBasicTree(); fService.createStore("layer"); fService.createDirectory("layer:/", "root"); @@ -140,10 +154,10 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createBranch(1, "layer:/root", "branch:/", "branch"); fService.createSnapshot("branch", null, null); fService.getFileOutputStream("main:/a/b/c/foo").close(); - assertEquals(fService.lookup(1, "main:/a/b/c/foo").getId(), - fService.lookup(1, "branch:/branch/layer/b/c/foo").getId()); - assertEquals(fService.lookup(-1, "main:/a/b/c/foo").getId(), - fService.lookup(-1, "branch:/branch/layer/b/c/foo").getId()); + assertEquals(fService.lookup(1, "main:/a/b/c/foo").getId(), fService.lookup(1, + "branch:/branch/layer/b/c/foo").getId()); + assertEquals(fService.lookup(-1, "main:/a/b/c/foo").getId(), fService.lookup(-1, + "branch:/branch/layer/b/c/foo").getId()); } catch (Exception e) { @@ -151,7 +165,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test Deployment. */ @@ -159,41 +173,56 @@ public class AVMServiceTest extends AVMServiceTestBase { try { - DeploymentService depService = (DeploymentService)fContext.getBean("DeploymentService"); + DeploymentService depService = (DeploymentService) fContext.getBean("DeploymentService"); setupBasicTree(); // TestDeploymentCallback callback = new TestDeploymentCallback(); fService.createStore("target"); - DeploymentReport report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, false, false, null); + DeploymentReport report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", + "target:/a", false, false, false, null); + runQueriesAgainstBasicTreeWithAOnly("target"); System.out.println(report); - assertEquals(fService.lookup(-1, "main:/a/b/c/foo").getGuid(), - fService.lookup(-1, "target:/a/b/c/foo").getGuid()); - assertEquals(fService.lookup(-1, "main:/a/b/c/bar").getGuid(), - fService.lookup(-1, "target:/a/b/c/bar").getGuid()); + assertEquals(fService.lookup(-1, "main:/a/b/c/foo").getGuid(), fService.lookup(-1, "target:/a/b/c/foo") + .getGuid()); + assertEquals(fService.lookup(-1, "main:/a/b/c/bar").getGuid(), fService.lookup(-1, "target:/a/b/c/bar") + .getGuid()); ContentData srcCD = fService.getContentDataForRead(-1, "main:/a/b/c/foo"); ContentData dstCD = fService.getContentDataForRead(-1, "target:/a/b/c/foo"); assertEquals(srcCD.getMimetype(), dstCD.getMimetype()); fService.createFile("main:/a/b", "biz").close(); - report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, false, true, null); + report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", + false, false, true, null); + // Nothing was done + runQueriesAgainstBasicTreeWithAOnly("target"); System.out.println(report); System.out.println(recursiveList("target", -1, true)); assertNull(fService.lookup(-1, "target:/a/b/biz")); - report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, false, false, null); + report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", + false, false, false, null); System.out.println(report); - assertEquals(fService.lookup(-1, "main:/a/b/biz").getGuid(), - fService.lookup(-1, "target:/a/b/biz").getGuid()); + runQueriesForCreateAndDeploy("target"); + assertEquals(fService.lookup(-1, "main:/a/b/biz").getGuid(), fService.lookup(-1, "target:/a/b/biz") + .getGuid()); fService.removeNode("main:/a/b/c/foo"); - report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, true, false, null); + report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", + false, true, false, null); + runQueriesForCreateAndDeploy("target"); System.out.println(report); assertNotNull(fService.lookup(-1, "target:/a/b/c/foo")); - report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, false, false, null); + report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", + false, false, false, null); System.out.println(report); + runQueriesForRemoveAndDelpoy("target"); assertNull(fService.lookup(-1, "target:/a/b/c/foo")); fService.removeNode("main:/a/b/c/bar"); fService.createDirectory("main:/a/b/c", "bar"); - report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, false, false, null); + report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", + false, false, false, null); System.out.println(report); - report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, false, false, null); - depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target2:/wiggly/diggly", true, false, false, null); + runQueriesForRemoveFileAndCreateDirectoryAndDeploy("target"); + report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", + false, false, false, null); + depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target2:/wiggly/diggly", + true, false, false, null); System.out.println(report); } catch (Exception e) @@ -202,7 +231,474 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + + protected void runQueriesForCreateAndDeploy(String store) + { + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + + // Text index + SearchService searchService = fIndexerAndSearcher.getSearcher(AVMNodeConverter.ToStoreRef(store), true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"I am main\""); + assertEquals(2, results.length()); + results.close(); + + // Basic properties + + // Note "a" is a stop word and therefore not findable ... + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":\"foo\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":foo"); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":biz"); + assertEquals(1, results.length()); + results.close(); + + // TODO: Fix auth in AVMDiskDriver and more?? + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_CREATOR) + + ":admin"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_MODIFIER) + + ":admin"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_OWNER) + + ":admin"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NODE_UUID) + + ":unknown"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_PROTOCOL) + + ":avm"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_IDENTIFIER) + + ":" + store); + assertEquals(7, results.length()); + results.close(); + + // Basic paths + + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/biz\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/foo\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/bar\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + } + + protected void runQueriesForRemoveAndDelpoy(String store) + { + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + + // Text index + SearchService searchService = fIndexerAndSearcher.getSearcher(AVMNodeConverter.ToStoreRef(store), true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"I am main\""); + assertEquals(1, results.length()); + results.close(); + + // Basic properties + + // Note "a" is a stop word and therefore not findable ... + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":\"foo\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":foo"); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":biz"); + assertEquals(1, results.length()); + results.close(); + + // TODO: Fix auth in AVMDiskDriver and more?? + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_CREATOR) + + ":admin"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_MODIFIER) + + ":admin"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_OWNER) + + ":admin"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NODE_UUID) + + ":unknown"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_PROTOCOL) + + ":avm"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_IDENTIFIER) + + ":" + store); + assertEquals(6, results.length()); + results.close(); + + // Basic paths + + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/biz\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/foo\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/bar\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); + assertEquals(4, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + } + + protected void runQueriesForRemoveFileAndCreateDirectoryAndDeploy(String store) + { + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + + // Text index + SearchService searchService = fIndexerAndSearcher.getSearcher(AVMNodeConverter.ToStoreRef(store), true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"I am main\""); + assertEquals(0, results.length()); + results.close(); + + // Basic properties + + // Note "a" is a stop word and therefore not findable ... + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":\"foo\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":\"bar\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":foo"); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":biz"); + assertEquals(1, results.length()); + results.close(); + + // TODO: Fix auth in AVMDiskDriver and more?? + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_CREATOR) + + ":admin"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_MODIFIER) + + ":admin"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_OWNER) + + ":admin"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NODE_UUID) + + ":unknown"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_PROTOCOL) + + ":avm"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_IDENTIFIER) + + ":" + store); + assertEquals(6, results.length()); + results.close(); + + // Basic paths + + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/biz\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/foo\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/bar\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); + assertEquals(4, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + } + /** * Test of GUIDs on AVM Nodes. */ @@ -222,7 +718,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test the revert to version action. */ @@ -231,25 +727,51 @@ public class AVMServiceTest extends AVMServiceTestBase try { setupBasicTree(); - fService.getFileOutputStream("main:/a/b/c/foo").close(); + ContentWriter writer = fService.getContentWriter("main:/a/b/c/foo"); + writer.setEncoding("UTF-8"); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.putContent("I am main:/a/b/c/foo V1"); fService.createSnapshot("main", "v1", null); - fService.getFileOutputStream("main:/a/b/c/foo").close(); + writer = fService.getContentWriter("main:/a/b/c/foo"); + writer.setEncoding("UTF-8"); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.putContent("I am main:/a/b/c/foo V2"); fService.createSnapshot("main", "v2", null); - fService.getFileOutputStream("main:/a/b/c/foo").close(); + writer = fService.getContentWriter("main:/a/b/c/foo"); + writer.setEncoding("UTF-8"); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.putContent("I am main:/a/b/c/foo V3"); fService.createSnapshot("main", "v3", null); - fService.getFileOutputStream("main:/a/b/c/foo").close(); + writer = fService.getContentWriter("main:/a/b/c/foo"); + writer.setEncoding("UTF-8"); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.putContent("I am main:/a/b/c/foo V4"); fService.createSnapshot("main", "v4", null); - fService.getFileOutputStream("main:/a/b/c/foo").close(); + writer = fService.getContentWriter("main:/a/b/c/foo"); + writer.setEncoding("UTF-8"); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.putContent("I am main:/a/b/c/foo V5"); fService.createSnapshot("main", "v5", null); - fService.getFileOutputStream("main:/a/b/c/foo").close(); + writer = fService.getContentWriter("main:/a/b/c/foo"); + writer.setEncoding("UTF-8"); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.putContent("I am main:/a/b/c/foo HEAD"); + StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"HEAD\""); + assertEquals(0, results.length()); + results.close(); + results = searchService.query(storeRef, "lucene", "TEXT:\"V5\""); + assertEquals(1, results.length()); + results.close(); + AVMNodeDescriptor desc = fService.lookup(-1, "main:/a/b/c/foo"); List history = fService.getHistory(desc, 100); AVMNodeDescriptor toRevert = history.get(3); - final ActionImpl action = new ActionImpl(null, - GUID.generate(), - AVMRevertToVersionAction.NAME); + final ActionImpl action = new ActionImpl(null, GUID.generate(), AVMRevertToVersionAction.NAME); action.setParameterValue(AVMRevertToVersionAction.TOREVERT, toRevert); - final AVMRevertToVersionAction revert = (AVMRevertToVersionAction)fContext.getBean("avm-revert-to-version"); + final AVMRevertToVersionAction revert = (AVMRevertToVersionAction) fContext + .getBean("avm-revert-to-version"); class TxnWork implements TransactionUtil.TransactionWork { public Object doWork() throws Exception @@ -257,9 +779,32 @@ public class AVMServiceTest extends AVMServiceTestBase revert.execute(action, AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c/foo")); return null; } - }; - TransactionUtil.executeInUserTransaction((TransactionService)fContext.getBean("transactionComponent"), + } + ; + TransactionUtil.executeInUserTransaction((TransactionService) fContext.getBean("transactionComponent"), new TxnWork()); + results = searchService.query(storeRef, "lucene", "TEXT:\"HEAD\""); + assertEquals(0, results.length()); + results.close(); + results = searchService.query(storeRef, "lucene", "TEXT:\"V5\""); + assertEquals(1, results.length()); + results.close(); + results = searchService.query(storeRef, "lucene", "TEXT:\"V2\""); + assertEquals(0, results.length()); + results.close(); + + fService.createSnapshot("main", "reverted", null); + + results = searchService.query(storeRef, "lucene", "TEXT:\"HEAD\""); + assertEquals(0, results.length()); + results.close(); + results = searchService.query(storeRef, "lucene", "TEXT:\"V5\""); + assertEquals(0, results.length()); + results.close(); + results = searchService.query(storeRef, "lucene", "TEXT:\"V2\""); + assertEquals(1, results.length()); + results.close(); + } catch (Exception e) { @@ -296,7 +841,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test relinking of nodes to history. */ @@ -304,7 +849,7 @@ public class AVMServiceTest extends AVMServiceTestBase { try { - setupBasicTree(); + setupBasicTree(); fService.createStore("branch"); fService.createBranch(-1, "main:/a", "branch:/", "a"); fService.removeNode("branch:/a/b/c/foo"); @@ -329,7 +874,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test renaming a store. */ @@ -337,8 +882,12 @@ public class AVMServiceTest extends AVMServiceTestBase { try { + setupBasicTree(); + assertNotNull(fService.lookup(-1, "main:/a/b")); fService.renameStore("main", "foo"); assertNotNull(fService.getStore("foo")); + assertNotNull(fService.lookup(-1, "foo:/a/b")); + runQueriesAgainstBasicTree("foo"); } catch (Exception e) { @@ -346,7 +895,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test copy. */ @@ -359,6 +908,9 @@ public class AVMServiceTest extends AVMServiceTestBase fService.copy(-1, "main:/a/b/c/foo", "main:/d", "fooCopy"); AVMNodeDescriptor desc = fService.lookup(-1, "main:/d/fooCopy"); assertTrue(desc.isFile()); + fService.createSnapshot("main", null, null); + runQueriesAgainstBasicTreePlusFileCopy("main"); + // Copy a whole tree fService.copy(-1, "main:/a", "main:/d/e", "aCopy"); desc = fService.lookup(-1, "main:/d/e/aCopy"); @@ -367,6 +919,9 @@ public class AVMServiceTest extends AVMServiceTestBase AVMNodeDescriptor desc2 = fService.lookup(-1, "main:/d/e/aCopy/b/c/bar"); assertTrue(desc2.isFile()); assertEquals(desc.getLength(), desc2.getLength()); + fService.createSnapshot("main", null, null); + runQueriesAgainstBasicTreePlusFileCopyAndDirectoryCopy("main"); + // Check that it rejects infinite copies. try { @@ -377,17 +932,57 @@ public class AVMServiceTest extends AVMServiceTestBase { // This is a success. } - CrossRepositoryCopyService copyService = (CrossRepositoryCopyService)fContext.getBean("CrossRepositoryCopyService"); - RepoRemote remoteService = (RepoRemote)fContext.getBean("RepoRemoteService"); + + StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"tutorial\""); + assertEquals(0, results.length()); + results.close(); + + CrossRepositoryCopyService copyService = (CrossRepositoryCopyService) fContext + .getBean("CrossRepositoryCopyService"); + RepoRemote remoteService = (RepoRemote) fContext.getBean("RepoRemoteService"); Pair toCopy = remoteService.lookup(remoteService.getRoot(), "Guest Home"); copyService.copy(toCopy.getFirst(), AVMNodeConverter.ToNodeRef(-1, "main:/"), "Guest Home"); desc = fService.lookup(-1, "main:/Guest Home"); assertTrue(desc.isDirectory()); System.out.println(this.recursiveList("main", -1, true)); + + fService.createSnapshot("main", null, null); + searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + results = searchService.query(storeRef, "lucene", "TEXT:\"tutorial\""); + assertEquals(1, results.length()); + results.close(); + + StoreRef spacesStore = new StoreRef("workspace", "SpacesStore"); + + searchService = fIndexerAndSearcher.getSearcher(spacesStore, true); + results = searchService.query(spacesStore, "lucene", "PATH:\"//.\""); + int count = results.length(); + results.close(); + copyService.copy(AVMNodeConverter.ToNodeRef(-1, "main:/a"), toCopy.getFirst(), "a"); Pair theCopy = remoteService.lookup(toCopy.getFirst(), "a"); assertTrue(theCopy.getSecond()); + + results = searchService.query(spacesStore, "lucene", "PATH:\"//.\""); + assertEquals(count + 5, results.length()); + results.close(); + + results = searchService.query(spacesStore, "lucene", "PATH:\"//.\""); + assertEquals(count + 5, results.length()); + results.close(); + + results = searchService.query(spacesStore, "lucene", "@cm\\:name:foo"); + assertEquals(1, results.length()); + results.close(); + remoteService.removeNode(theCopy.getFirst()); + + results = searchService.query(spacesStore, "lucene", "PATH:\"//.\""); + assertEquals(count, results.length()); + results.close(); + } catch (Exception e) { @@ -395,6 +990,335 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } + + protected void runQueriesAgainstBasicTreePlusFileCopy(String store) + { + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + + // Text index + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"I am main\""); + assertEquals(3, results.length()); + results.close(); + + // Basic properties + + // Note "a" is a stop word and therefore not findable ... + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":\"foo\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":foo"); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":\"fooCopy\""); + assertEquals(1, results.length()); + results.close(); + + // TODO: Fix auth in AVMDiskDriver and more?? + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_CREATOR) + + ":admin"); + assertEquals(10, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_MODIFIER) + + ":admin"); + assertEquals(10, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_OWNER) + + ":admin"); + assertEquals(10, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NODE_UUID) + + ":unknown"); + assertEquals(10, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_PROTOCOL) + + ":avm"); + assertEquals(10, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_IDENTIFIER) + + ":" + store); + assertEquals(10, results.length()); + results.close(); + + // Basic paths + + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/foo\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/bar\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/fooCopy\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(10, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); + assertEquals(4, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); + assertEquals(3, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + } + + protected void runQueriesAgainstBasicTreePlusFileCopyAndDirectoryCopy(String store) + { + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + + // Text index + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"I am main\""); + assertEquals(5, results.length()); + results.close(); + + // Basic properties + + // Note "a" is a stop word and therefore not findable ... + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":\"foo\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":foo"); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":\"fooCopy\""); + assertEquals(1, results.length()); + results.close(); + + // TODO: Fix auth in AVMDiskDriver and more?? + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_CREATOR) + + ":admin"); + assertEquals(15, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_MODIFIER) + + ":admin"); + assertEquals(15, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_OWNER) + + ":admin"); + assertEquals(15, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NODE_UUID) + + ":unknown"); + assertEquals(15, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_PROTOCOL) + + ":avm"); + assertEquals(15, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_IDENTIFIER) + + ":" + store); + assertEquals(15, results.length()); + results.close(); + + // Basic paths + + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/foo\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/bar\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/fooCopy\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/aCopy\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/aCopy/b\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/aCopy/b/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/aCopy/b/c/foo\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/aCopy/b/c/bar\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(15, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); + assertEquals(14, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); + assertEquals(4, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); + assertEquals(4, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); + assertEquals(3, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); + assertEquals(3, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); + assertEquals(3, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + } + /** * Test cyclic lookup behavior. */ @@ -427,10 +1351,9 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test getting all paths for a node. - * */ public void testGetPaths() { @@ -465,7 +1388,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test partial flatten. */ @@ -479,9 +1402,7 @@ public class AVMServiceTest extends AVMServiceTestBase fService.getFileOutputStream("layer:/a/b/c/foo").close(); fService.createFile("layer:/a/b", "bing").close(); List diffs = new ArrayList(); - diffs.add(new AVMDifference(-1, "layer:/a/b/c/foo", - -1, "main:/a/b/c/foo", - AVMDifference.NEWER)); + diffs.add(new AVMDifference(-1, "layer:/a/b/c/foo", -1, "main:/a/b/c/foo", AVMDifference.NEWER)); fSyncService.update(diffs, null, false, false, false, false, null, null); fSyncService.flatten("layer:/a", "main:/a"); AVMNodeDescriptor b = fService.lookup(-1, "layer:/a/b"); @@ -496,8 +1417,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - - + /** * Test getIndirection. */ @@ -521,7 +1441,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test the revert list action. */ @@ -539,15 +1459,12 @@ public class AVMServiceTest extends AVMServiceTestBase fService.getFileOutputStream("area:/a/b/c/bar").close(); diffs = fSyncService.compare(-1, "area:/a", -1, "main:/a", null); assertEquals(1, diffs.size()); - final ActionImpl action = new ActionImpl(null, - GUID.generate(), - AVMRevertListAction.NAME); - List paths = - new ArrayList(); + final ActionImpl action = new ActionImpl(null, GUID.generate(), AVMRevertListAction.NAME); + List paths = new ArrayList(); paths.add("area:/a/b"); action.setParameterValue(AVMRevertListAction.PARAM_VERSION, fService.getLatestSnapshotID("area")); - action.setParameterValue(AVMRevertListAction.PARAM_NODE_LIST, (Serializable)paths); - final AVMRevertListAction revert = (AVMRevertListAction)fContext.getBean("avm-revert-list"); + action.setParameterValue(AVMRevertListAction.PARAM_NODE_LIST, (Serializable) paths); + final AVMRevertListAction revert = (AVMRevertListAction) fContext.getBean("avm-revert-list"); class TxnWork implements TransactionUtil.TransactionWork { public Object doWork() throws Exception @@ -555,8 +1472,9 @@ public class AVMServiceTest extends AVMServiceTestBase revert.execute(action, null); return null; } - }; - TransactionUtil.executeInUserTransaction((TransactionService)fContext.getBean("transactionComponent"), + } + ; + TransactionUtil.executeInUserTransaction((TransactionService) fContext.getBean("transactionComponent"), new TxnWork()); diffs = fSyncService.compare(-1, "area:/a", -1, "main:/a", null); assertEquals(0, diffs.size()); @@ -587,14 +1505,11 @@ public class AVMServiceTest extends AVMServiceTestBase fService.getFileOutputStream("area:/a/b/c/bar").close(); diffs = fSyncService.compare(-1, "area:/a", -1, "main:/a", null); assertEquals(1, diffs.size()); - final ActionImpl action = new ActionImpl(null, - GUID.generate(), - AVMUndoSandboxListAction.NAME); - List> versionPaths = - new ArrayList>(); + final ActionImpl action = new ActionImpl(null, GUID.generate(), AVMUndoSandboxListAction.NAME); + List> versionPaths = new ArrayList>(); versionPaths.add(new Pair(-1, "area:/a/b/c/bar")); - action.setParameterValue(AVMUndoSandboxListAction.PARAM_NODE_LIST, (Serializable)versionPaths); - final AVMUndoSandboxListAction revert = (AVMUndoSandboxListAction)fContext.getBean("avm-undo-list"); + action.setParameterValue(AVMUndoSandboxListAction.PARAM_NODE_LIST, (Serializable) versionPaths); + final AVMUndoSandboxListAction revert = (AVMUndoSandboxListAction) fContext.getBean("avm-undo-list"); class TxnWork implements TransactionUtil.TransactionWork { public Object doWork() throws Exception @@ -602,8 +1517,9 @@ public class AVMServiceTest extends AVMServiceTestBase revert.execute(action, null); return null; } - }; - TransactionUtil.executeInUserTransaction((TransactionService)fContext.getBean("transactionComponent"), + } + ; + TransactionUtil.executeInUserTransaction((TransactionService) fContext.getBean("transactionComponent"), new TxnWork()); diffs = fSyncService.compare(-1, "area:/a", -1, "main:/a", null); assertEquals(0, diffs.size()); @@ -616,7 +1532,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test the promote action. */ @@ -625,30 +1541,32 @@ public class AVMServiceTest extends AVMServiceTestBase try { setupBasicTree(); - fService.createDirectory("main:/", JNDIConstants.DIR_DEFAULT_WWW ); + fService.createDirectory("main:/", JNDIConstants.DIR_DEFAULT_WWW); fService.rename("main:/", "a", "main:/" + JNDIConstants.DIR_DEFAULT_WWW, "a"); fService.rename("main:/", "d", "main:/" + JNDIConstants.DIR_DEFAULT_WWW, "d"); fService.createSnapshot("main", null, null); fService.createStore("source"); - fService.createLayeredDirectory("main:/" + JNDIConstants.DIR_DEFAULT_WWW , "source:/", JNDIConstants.DIR_DEFAULT_WWW ); - fService.getFileOutputStream("source:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a/b/c/foo").close(); - final ActionImpl action = new ActionImpl(AVMNodeConverter.ToNodeRef(-1, "source:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a"), - GUID.generate(), - SimpleAVMPromoteAction.NAME); + fService.createLayeredDirectory("main:/" + JNDIConstants.DIR_DEFAULT_WWW, "source:/", + JNDIConstants.DIR_DEFAULT_WWW); + fService.getFileOutputStream("source:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a/b/c/foo").close(); + final ActionImpl action = new ActionImpl(AVMNodeConverter.ToNodeRef(-1, "source:/" + + JNDIConstants.DIR_DEFAULT_WWW + "/a"), GUID.generate(), SimpleAVMPromoteAction.NAME); action.setParameterValue(SimpleAVMPromoteAction.PARAM_TARGET_STORE, "main"); - final SimpleAVMPromoteAction promote = (SimpleAVMPromoteAction)fContext.getBean("simple-avm-promote"); + final SimpleAVMPromoteAction promote = (SimpleAVMPromoteAction) fContext.getBean("simple-avm-promote"); class TxnWork implements TransactionUtil.TransactionWork { public Object doWork() throws Exception { - promote.execute(action, AVMNodeConverter.ToNodeRef(-1, "source:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a")); + promote.execute(action, AVMNodeConverter.ToNodeRef(-1, "source:/" + + JNDIConstants.DIR_DEFAULT_WWW + "/a")); return null; } - }; - TransactionUtil.executeInUserTransaction((TransactionService)fContext.getBean("transactionComponent"), + } + ; + TransactionUtil.executeInUserTransaction((TransactionService) fContext.getBean("transactionComponent"), new TxnWork()); - assertEquals(0, fSyncService.compare(-1, "source:/" + JNDIConstants.DIR_DEFAULT_WWW , - -1, "main:/" + JNDIConstants.DIR_DEFAULT_WWW, null).size()); + assertEquals(0, fSyncService.compare(-1, "source:/" + JNDIConstants.DIR_DEFAULT_WWW, -1, + "main:/" + JNDIConstants.DIR_DEFAULT_WWW, null).size()); } catch (Exception e) { @@ -656,7 +1574,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test a noodle update. */ @@ -669,10 +1587,8 @@ public class AVMServiceTest extends AVMServiceTestBase List diffs = fSyncService.compare(-1, "main:/", -1, "staging:/", null); assertEquals(2, diffs.size()); List noodle = new ArrayList(); - noodle.add(new AVMDifference(-1, "main:/a/b/c/foo", -1, "staging:/a/b/c/foo", - AVMDifference.NEWER)); - noodle.add(new AVMDifference(-1, "main:/d", -1, "staging:/d", - AVMDifference.NEWER)); + noodle.add(new AVMDifference(-1, "main:/a/b/c/foo", -1, "staging:/a/b/c/foo", AVMDifference.NEWER)); + noodle.add(new AVMDifference(-1, "main:/d", -1, "staging:/d", AVMDifference.NEWER)); fSyncService.update(noodle, null, false, false, false, false, null, null); diffs = fSyncService.compare(-1, "main:/", -1, "staging:/", null); assertEquals(1, diffs.size()); @@ -684,7 +1600,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test the SimpleAVMSubmitAction. */ @@ -693,37 +1609,37 @@ public class AVMServiceTest extends AVMServiceTestBase try { fService.createStore("foo-staging"); - fService.createDirectory("foo-staging:/", JNDIConstants.DIR_DEFAULT_WWW ); - fService.createDirectory("foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW, "a"); - fService.createDirectory("foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a","b"); + fService.createDirectory("foo-staging:/", JNDIConstants.DIR_DEFAULT_WWW); + fService.createDirectory("foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW, "a"); + fService.createDirectory("foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a", "b"); fService.createDirectory("foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a/b", "c"); - fService.createFile("foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a/b/c", "foo").close(); - fService.createFile("foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a/b/c", "bar").close(); + fService.createFile("foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a/b/c", "foo").close(); + fService.createFile("foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a/b/c", "bar").close(); fService.createStore("area"); - fService.setStoreProperty("area", QName.createQName(null, ".website.name"), - new PropertyValue(null, "foo")); - fService.createLayeredDirectory("foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW , "area:/", JNDIConstants.DIR_DEFAULT_WWW ); + fService.setStoreProperty("area", QName.createQName(null, ".website.name"), new PropertyValue(null, "foo")); + fService.createLayeredDirectory("foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW, "area:/", + JNDIConstants.DIR_DEFAULT_WWW); fService.createFile("area:/" + JNDIConstants.DIR_DEFAULT_WWW, "figs").close(); - fService.getFileOutputStream("area:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a/b/c/foo").close(); + fService.getFileOutputStream("area:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a/b/c/foo").close(); fService.removeNode("area:/" + JNDIConstants.DIR_DEFAULT_WWW + "/a/b/c/bar"); - List diffs = - fSyncService.compare(-1, "area:/" + JNDIConstants.DIR_DEFAULT_WWW, -1, "foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW, null); + List diffs = fSyncService.compare(-1, "area:/" + JNDIConstants.DIR_DEFAULT_WWW, -1, + "foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW, null); assertEquals(3, diffs.size()); - final SimpleAVMSubmitAction action = (SimpleAVMSubmitAction)fContext.getBean("simple-avm-submit"); + final SimpleAVMSubmitAction action = (SimpleAVMSubmitAction) fContext.getBean("simple-avm-submit"); class TxnWork implements TransactionUtil.TransactionWork { public Object doWork() throws Exception { - action.execute(null, AVMNodeConverter.ToNodeRef(-1, "area:/" + JNDIConstants.DIR_DEFAULT_WWW )); + action.execute(null, AVMNodeConverter.ToNodeRef(-1, "area:/" + JNDIConstants.DIR_DEFAULT_WWW)); return null; } - }; + } + ; TxnWork worker = new TxnWork(); - TransactionUtil.executeInUserTransaction((TransactionService)fContext.getBean("transactionComponent"), - worker); - diffs = - fSyncService.compare(-1, "area:/" + JNDIConstants.DIR_DEFAULT_WWW, - -1, "foo-staging:/" + JNDIConstants.DIR_DEFAULT_WWW, null); + TransactionUtil.executeInUserTransaction((TransactionService) fContext.getBean("transactionComponent"), + worker); + diffs = fSyncService.compare(-1, "area:/" + JNDIConstants.DIR_DEFAULT_WWW, -1, "foo-staging:/" + + JNDIConstants.DIR_DEFAULT_WWW, null); assertEquals(0, diffs.size()); } @@ -733,7 +1649,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test one argument remove. */ @@ -744,6 +1660,155 @@ public class AVMServiceTest extends AVMServiceTestBase setupBasicTree(); fService.removeNode("main:/a/b/c/foo/"); fService.removeNode("main://d"); + fService.createSnapshot("main", null, null); + + StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); + + // Text index + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"I am main\""); + assertEquals(1, results.length()); + results.close(); + + // Basic properties + + // Note "a" is a stop word and therefore not findable ... + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":\"foo\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":foo"); + assertEquals(0, results.length()); + results.close(); + + // TODO: Fix auth in AVMDiskDriver and more?? + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_CREATOR) + + ":admin"); + if (results.length() == 6) + { + for (ResultSetRow row : results) + { + System.out.println(row.getNodeRef()); + } + } + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser + .escape("@" + ContentModel.PROP_MODIFIER) + + ":admin"); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_OWNER) + + ":admin"); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_NODE_UUID) + + ":unknown"); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_PROTOCOL) + + ":avm"); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_IDENTIFIER) + + ":" + "main"); + assertEquals(5, results.length()); + results.close(); + + // Basic paths + + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/foo\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/bar\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); + assertEquals(4, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); + assertEquals(4, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); + assertEquals(3, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + try { fService.removeNode("main://"); @@ -759,7 +1824,7 @@ public class AVMServiceTest extends AVMServiceTestBase e.printStackTrace(System.err); } } - + /** * Test that non head version sources are update correctly. */ @@ -775,8 +1840,7 @@ public class AVMServiceTest extends AVMServiceTestBase int version1 = fService.createSnapshot("source", null, null); loader.recursiveLoad("config/alfresco/extension", "source:/"); int version2 = fService.createSnapshot("source", null, null); - List diffs = - fSyncService.compare(version1, "source:/", -1, "dest:/", null); + List diffs = fSyncService.compare(version1, "source:/", -1, "dest:/", null); fService.createSnapshot("dest", null, null); assertEquals(1, diffs.size()); fSyncService.update(diffs, null, false, false, false, false, null, null); @@ -795,7 +1859,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test that an update forces a snapshot on the source. */ @@ -810,16 +1874,15 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createFile("branch:/branch/a/b", "fing").close(); fService.getFileOutputStream("branch:/branch/a/b/c/foo").close(); fService.removeNode("branch:/branch/a/b/c", "bar"); - List diffs = - fSyncService.compare(-1, "branch:/branch", -1, "main:/", null); + List diffs = fSyncService.compare(-1, "branch:/branch", -1, "main:/", null); assertEquals(3, diffs.size()); // Now update. fSyncService.update(diffs, null, false, false, false, false, null, null); diffs = fSyncService.compare(-1, "branch:/branch", -1, "main:/", null); assertEquals(0, diffs.size()); fService.getFileOutputStream("branch:/branch/a/b/fing").close(); - assertTrue(fService.lookup(-1, "branch:/branch/a/b/fing").getId() != - fService.lookup(-1, "main:/a/b/fing").getId()); + assertTrue(fService.lookup(-1, "branch:/branch/a/b/fing").getId() != fService.lookup(-1, "main:/a/b/fing") + .getId()); } catch (Exception e) { @@ -827,7 +1890,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test that branching forces a snapshot on the source repository. */ @@ -838,11 +1901,11 @@ public class AVMServiceTest extends AVMServiceTestBase setupBasicTree(); fService.getFileOutputStream("main:/a/b/c/foo").close(); fService.createBranch(-1, "main:/a", "main:/", "abranch"); - assertEquals(fService.lookup(-1, "main:/a/b/c/foo").getId(), - fService.lookup(-1, "main:/abranch/b/c/foo").getId()); + assertEquals(fService.lookup(-1, "main:/a/b/c/foo").getId(), fService.lookup(-1, "main:/abranch/b/c/foo") + .getId()); fService.getFileOutputStream("main:/a/b/c/foo").close(); - assertTrue(fService.lookup(-1, "main:/a/b/c/foo").getId() != - fService.lookup(-1, "main:/abranch/b/c/foo").getId()); + assertTrue(fService.lookup(-1, "main:/a/b/c/foo").getId() != fService.lookup(-1, "main:/abranch/b/c/foo") + .getId()); } catch (Exception e) { @@ -850,7 +1913,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test bulk update. */ @@ -900,7 +1963,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test the flatten operation, with a little bit of compare and update. */ @@ -918,8 +1981,7 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); // Do a compare. - List diffs = - fSyncService.compare(-1, "main:/layer", -1, "main:/a", null); + List diffs = fSyncService.compare(-1, "main:/layer", -1, "main:/a", null); for (AVMDifference diff : diffs) { System.out.println(diff); @@ -937,7 +1999,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test of Descriptor indirection field. */ @@ -965,7 +2027,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test AVMSyncService update. */ @@ -973,7 +2035,7 @@ public class AVMServiceTest extends AVMServiceTestBase { try { - NameMatcher excluder = (NameMatcher)fContext.getBean("globalPathExcluder"); + NameMatcher excluder = (NameMatcher) fContext.getBean("globalPathExcluder"); setupBasicTree(); // Try branch to branch update. fService.createBranch(-1, "main:/a", "main:/", "abranch"); @@ -982,60 +2044,49 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createFile("main:/abranch", "figs.tmp").close(); fService.getFileOutputStream("main:/abranch/b/c/foo").close(); System.out.println(recursiveList("main", -1, true)); - List cmp = - fSyncService.compare(-1, "main:/abranch", -1, "main:/a", excluder); + List cmp = fSyncService.compare(-1, "main:/abranch", -1, "main:/a", excluder); for (AVMDifference diff : cmp) { System.out.println(diff); } assertEquals(2, cmp.size()); List diffs = new ArrayList(); - diffs.add(new AVMDifference(-1, "main:/abranch/monkey", - -1, "main:/a/monkey", - AVMDifference.NEWER)); - diffs.add(new AVMDifference(-1, "main:/abranch/b/c/foo", - -1, "main:/a/b/c/foo", - AVMDifference.NEWER)); + diffs.add(new AVMDifference(-1, "main:/abranch/monkey", -1, "main:/a/monkey", AVMDifference.NEWER)); + diffs.add(new AVMDifference(-1, "main:/abranch/b/c/foo", -1, "main:/a/b/c/foo", AVMDifference.NEWER)); fSyncService.update(diffs, null, false, false, false, false, null, null); fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); - assertEquals(fService.lookup(-1, "main:/abranch/monkey").getId(), - fService.lookup(-1, "main:/a/monkey").getId()); - assertEquals(fService.lookup(-1, "main:/abranch/b/c/foo").getId(), - fService.lookup(-1, "main:/a/b/c/foo").getId()); + assertEquals(fService.lookup(-1, "main:/abranch/monkey").getId(), fService.lookup(-1, "main:/a/monkey") + .getId()); + assertEquals(fService.lookup(-1, "main:/abranch/b/c/foo").getId(), fService.lookup(-1, "main:/a/b/c/foo") + .getId()); // Try updating a deletion. fService.removeNode("main:/abranch", "monkey"); System.out.println(recursiveList("main", -1, true)); - cmp = - fSyncService.compare(-1, "main:/abranch", -1, "main:/a", excluder); + cmp = fSyncService.compare(-1, "main:/abranch", -1, "main:/a", excluder); for (AVMDifference diff : cmp) { System.out.println(diff); } assertEquals(1, cmp.size()); diffs.clear(); - diffs.add(new AVMDifference(-1, "main:/abranch/monkey", - -1, "main:/a/monkey", - AVMDifference.NEWER)); + diffs.add(new AVMDifference(-1, "main:/abranch/monkey", -1, "main:/a/monkey", AVMDifference.NEWER)); fSyncService.update(diffs, null, false, false, false, false, null, null); assertEquals(0, fSyncService.compare(-1, "main:/abranch", -1, "main:/a", excluder).size()); fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); - assertEquals(fService.lookup(-1, "main:/abranch/monkey", true).getId(), - fService.lookup(-1, "main:/a/monkey", true).getId()); + assertEquals(fService.lookup(-1, "main:/abranch/monkey", true).getId(), fService.lookup(-1, + "main:/a/monkey", true).getId()); // Try one that should fail. fService.createFile("main:/abranch", "monkey").close(); - cmp = - fSyncService.compare(-1, "main:/abranch", -1, "main:/a", excluder); + cmp = fSyncService.compare(-1, "main:/abranch", -1, "main:/a", excluder); for (AVMDifference diff : cmp) { System.out.println(diff); } assertEquals(1, cmp.size()); diffs.clear(); - diffs.add(new AVMDifference(-1, "main:/a/monkey", - -1, "main:/abranch/monkey", - AVMDifference.NEWER)); + diffs.add(new AVMDifference(-1, "main:/a/monkey", -1, "main:/abranch/monkey", AVMDifference.NEWER)); try { fSyncService.update(diffs, null, false, false, false, false, null, null); @@ -1048,15 +2099,13 @@ public class AVMServiceTest extends AVMServiceTestBase // Get synced again by doing an override older. System.out.println(recursiveList("main", -1, true)); diffs.clear(); - diffs.add(new AVMDifference(-1, "main:/a/monkey", - -1, "main:/abranch/monkey", - AVMDifference.NEWER)); + diffs.add(new AVMDifference(-1, "main:/a/monkey", -1, "main:/abranch/monkey", AVMDifference.NEWER)); fSyncService.update(diffs, null, false, false, false, true, null, null); assertEquals(0, fSyncService.compare(-1, "main:/abranch", -1, "main:/a", excluder).size()); fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); - assertEquals(fService.lookup(-1, "main:/a/monkey", true).getId(), - fService.lookup(-1, "main:/abranch/monkey", true).getId()); + assertEquals(fService.lookup(-1, "main:/a/monkey", true).getId(), fService.lookup(-1, + "main:/abranch/monkey", true).getId()); // Cleanup for layered tests. fService.purgeStore("main"); fService.createStore("main"); @@ -1064,8 +2113,7 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createLayeredDirectory("main:/a", "main:/", "layer"); fService.createFile("main:/layer", "monkey").close(); fService.getFileOutputStream("main:/layer/b/c/foo").close(); - cmp = - fSyncService.compare(-1, "main:/layer", -1, "main:/a", excluder); + cmp = fSyncService.compare(-1, "main:/layer", -1, "main:/a", excluder); for (AVMDifference diff : cmp) { System.out.println(diff); @@ -1073,53 +2121,43 @@ public class AVMServiceTest extends AVMServiceTestBase assertEquals(2, cmp.size()); System.out.println(recursiveList("main", -1, true)); diffs.clear(); - diffs.add(new AVMDifference(-1, "main:/layer/monkey", - -1, "main:/a/monkey", - AVMDifference.NEWER)); - diffs.add(new AVMDifference(-1, "main:/layer/b/c/foo", - -1, "main:/a/b/c/foo", - AVMDifference.NEWER)); + diffs.add(new AVMDifference(-1, "main:/layer/monkey", -1, "main:/a/monkey", AVMDifference.NEWER)); + diffs.add(new AVMDifference(-1, "main:/layer/b/c/foo", -1, "main:/a/b/c/foo", AVMDifference.NEWER)); fSyncService.update(diffs, null, false, false, false, false, null, null); assertEquals(0, fSyncService.compare(-1, "main:/layer", -1, "main:/a", excluder).size()); fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); - assertEquals(fService.lookup(-1, "main:/layer/monkey").getId(), - fService.lookup(-1, "main:/a/monkey").getId()); - assertEquals(fService.lookup(-1, "main:/layer/b/c/foo").getId(), - fService.lookup(-1, "main:/a/b/c/foo").getId()); + assertEquals(fService.lookup(-1, "main:/layer/monkey").getId(), fService.lookup(-1, "main:/a/monkey") + .getId()); + assertEquals(fService.lookup(-1, "main:/layer/b/c/foo").getId(), fService.lookup(-1, "main:/a/b/c/foo") + .getId()); // Try updating a deletion. fService.removeNode("main:/layer", "monkey"); System.out.println(recursiveList("main", -1, true)); - cmp = - fSyncService.compare(-1, "main:/layer", -1, "main:/a", excluder); + cmp = fSyncService.compare(-1, "main:/layer", -1, "main:/a", excluder); for (AVMDifference diff : cmp) { System.out.println(diff); } assertEquals(1, cmp.size()); diffs.clear(); - diffs.add(new AVMDifference(-1, "main:/layer/monkey", - -1, "main:/a/monkey", - AVMDifference.NEWER)); + diffs.add(new AVMDifference(-1, "main:/layer/monkey", -1, "main:/a/monkey", AVMDifference.NEWER)); fSyncService.update(diffs, null, false, false, false, false, null, null); assertEquals(0, fSyncService.compare(-1, "main:/layer", -1, "main:/a", excluder).size()); fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); - assertEquals(fService.lookup(-1, "main:/layer/monkey", true).getId(), - fService.lookup(-1, "main:/a/monkey", true).getId()); + assertEquals(fService.lookup(-1, "main:/layer/monkey", true).getId(), fService.lookup(-1, "main:/a/monkey", + true).getId()); // Try one that should fail. fService.createFile("main:/layer", "monkey").close(); - cmp = - fSyncService.compare(-1, "main:/layer", -1, "main:/a", excluder); + cmp = fSyncService.compare(-1, "main:/layer", -1, "main:/a", excluder); for (AVMDifference diff : cmp) { System.out.println(diff); } assertEquals(1, cmp.size()); diffs.clear(); - diffs.add(new AVMDifference(-1, "main:/a/monkey", - -1, "main:/layer/monkey", - AVMDifference.NEWER)); + diffs.add(new AVMDifference(-1, "main:/a/monkey", -1, "main:/layer/monkey", AVMDifference.NEWER)); try { fSyncService.update(diffs, null, false, false, false, false, null, null); @@ -1132,15 +2170,13 @@ public class AVMServiceTest extends AVMServiceTestBase // Get synced again by doing an override older. System.out.println(recursiveList("main", -1, true)); diffs.clear(); - diffs.add(new AVMDifference(-1, "main:/a/monkey", - -1, "main:/layer/monkey", - AVMDifference.NEWER)); + diffs.add(new AVMDifference(-1, "main:/a/monkey", -1, "main:/layer/monkey", AVMDifference.NEWER)); fSyncService.update(diffs, null, false, false, false, true, null, null); assertEquals(0, fSyncService.compare(-1, "main:/layer", -1, "main:/a", excluder).size()); fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); - assertEquals(fService.lookup(-1, "main:/a/monkey", true).getId(), - fService.lookup(-1, "main:/layer/monkey", true).getId()); + assertEquals(fService.lookup(-1, "main:/a/monkey", true).getId(), fService.lookup(-1, "main:/layer/monkey", + true).getId()); } catch (Exception e) { @@ -1148,7 +2184,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test link AVMService call. */ @@ -1159,8 +2195,7 @@ public class AVMServiceTest extends AVMServiceTestBase setupBasicTree(); // Just try linking /a/b/c/foo into /a/b fService.link("main:/a/b", "foo", fService.lookup(-1, "main:/a/b/c/foo")); - assertEquals(fService.lookup(-1, "main:/a/b/c/foo").getId(), - fService.lookup(-1, "main:/a/b/foo").getId()); + assertEquals(fService.lookup(-1, "main:/a/b/c/foo").getId(), fService.lookup(-1, "main:/a/b/foo").getId()); // Try linking /a/b/c/bar to /a/b/foo. It should fail. System.out.println(recursiveList("main", -1, true)); try @@ -1170,14 +2205,13 @@ public class AVMServiceTest extends AVMServiceTestBase } catch (AVMExistsException e) { - // Do nothing. It's OK. + // Do nothing. It's OK. } - // Delete /a/b/foo, and link /a/b/c/foo into /a/b. This checks that + // Delete /a/b/foo, and link /a/b/c/foo into /a/b. This checks that // a deleted node is no impediment. fService.removeNode("main:/a/b", "foo"); fService.link("main:/a/b", "foo", fService.lookup(-1, "main:/a/b/c/foo")); - assertEquals(fService.lookup(-1, "main:/a/b/c/foo").getId(), - fService.lookup(-1, "main:/a/b/foo").getId()); + assertEquals(fService.lookup(-1, "main:/a/b/c/foo").getId(), fService.lookup(-1, "main:/a/b/foo").getId()); // Delete /a/b/foo again in prep for layer tests. fService.removeNode("main:/a/b", "foo"); System.out.println(recursiveList("main", -1, true)); @@ -1185,13 +2219,13 @@ public class AVMServiceTest extends AVMServiceTestBase // Create a layer do a link from /layer/b/c/bar to /layer/b fService.createLayeredDirectory("main:/a", "main:/", "layer"); fService.link("main:/layer/b", "bar", fService.lookup(-1, "main:/layer/b/c/bar")); - assertEquals(fService.lookup(-1, "main:/layer/b/c/bar").getId(), - fService.lookup(-1, "main:/layer/b/bar").getId()); + assertEquals(fService.lookup(-1, "main:/layer/b/c/bar").getId(), fService.lookup(-1, "main:/layer/b/bar") + .getId()); System.out.println(recursiveList("main", -1, true)); // Now link /layer/b/c/foo into /layer/b. fService.link("main:/layer/b", "foo", fService.lookup(-1, "main:/layer/b/c/foo")); - assertEquals(fService.lookup(-1, "main:/layer/b/c/foo").getId(), - fService.lookup(-1, "main:/layer/b/foo").getId()); + assertEquals(fService.lookup(-1, "main:/layer/b/c/foo").getId(), fService.lookup(-1, "main:/layer/b/foo") + .getId()); // Make sure that the underlying layer is not mucked up. assertTrue(fService.lookup(-1, "main:/a/b/foo", true).isDeleted()); System.out.println(recursiveList("main", -1, true)); @@ -1218,8 +2252,8 @@ public class AVMServiceTest extends AVMServiceTestBase // Delete /layer/b/bar and redo. It should work. fService.removeNode("main:/layer/b", "bar"); fService.link("main:/layer/b", "bar", fService.lookup(-1, "main:/layer/b/c/bar")); - assertEquals(fService.lookup(-1, "main:/layer/b/c/bar").getId(), - fService.lookup(-1, "main:/layer/b/bar").getId()); + assertEquals(fService.lookup(-1, "main:/layer/b/c/bar").getId(), fService.lookup(-1, "main:/layer/b/bar") + .getId()); System.out.println(recursiveList("main", -1, true)); } catch (Exception e) @@ -1246,7 +2280,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test getting deleted names. */ @@ -1274,7 +2308,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test directly contained listing. */ @@ -1285,13 +2319,9 @@ public class AVMServiceTest extends AVMServiceTestBase setupBasicTree(); fService.createLayeredDirectory("main:/a", "main:/", "layer"); fService.createSnapshot("main", null, null); - Map listing = - fService.getDirectoryListingDirect(-1, - "main:/layer"); + Map listing = fService.getDirectoryListingDirect(-1, "main:/layer"); assertEquals(0, listing.size()); - listing = - fService.getDirectoryListingDirect(-1, - "main:/layer/b"); + listing = fService.getDirectoryListingDirect(-1, "main:/layer/b"); assertEquals(0, listing.size()); fService.createFile("main:/layer/b/c", "sigmoid").close(); fService.createSnapshot("main", null, null); @@ -1312,7 +2342,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test layering info. */ @@ -1357,7 +2387,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Another test of renaming in a layer. */ @@ -1507,7 +2537,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test the uncover operation. */ @@ -1580,7 +2610,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Another test of renaming in a layer. */ @@ -1642,7 +2672,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test branching within branches. */ @@ -1665,11 +2695,11 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createSnapshot("main", null, null); // History unchanged checkHistory(history, "main"); - // Everything under /abranch should be identical in this version + // Everything under /abranch should be identical in this version // and the previous. int version = fService.getNextVersionID("main"); - assertEquals(recursiveContents("main:/abranch", version - 1, true), - recursiveContents("main:/abranch", version - 2, true)); + assertEquals(recursiveContents("main:/abranch", version - 1, true), recursiveContents("main:/abranch", + version - 2, true)); // Make a branch within a branch. fService.createBranch(-1, "main:/abranch/b/c", "main:/abranch/b", "cbranch"); fService.createSnapshot("main", null, null); @@ -1677,8 +2707,8 @@ public class AVMServiceTest extends AVMServiceTestBase checkHistory(history, "main"); // Everything under /a should be unchanged between this version and the last. version = fService.getNextVersionID("main"); - assertEquals(recursiveContents("main:/a", version - 1, true), - recursiveContents("main:/a", version - 2, true)); + assertEquals(recursiveContents("main:/a", version - 1, true), recursiveContents("main:/a", version - 2, + true)); // Make a branch to something outside of a branch inside a branch. fService.createBranch(-1, "main:/d", "main:/abranch", "dbranch"); fService.createSnapshot("main", null, null); @@ -1691,8 +2721,8 @@ public class AVMServiceTest extends AVMServiceTestBase checkHistory(history, "main"); // d should not have changed since the previous version. version = fService.getNextVersionID("main"); - assertEquals(recursiveContents("main:/d", version - 1, true), - recursiveContents("main:/d", version - 2, true)); + assertEquals(recursiveContents("main:/d", version - 1, true), recursiveContents("main:/d", version - 2, + true)); for (String val : history.values()) { System.out.println(val); @@ -1703,8 +2733,8 @@ public class AVMServiceTest extends AVMServiceTestBase e.printStackTrace(System.err); fail(); } - } - + } + /** * Test layers inside of layers. */ @@ -1755,8 +2785,8 @@ public class AVMServiceTest extends AVMServiceTestBase // History unchanged. checkHistory(history, "main"); // /d/gover should be identical to /layer/under/gover - assertEquals(recursiveContents("main:/d/gover", -1, true), - recursiveContents("main:/layer/under/gover", -1, true)); + assertEquals(recursiveContents("main:/d/gover", -1, true), recursiveContents("main:/layer/under/gover", -1, + true)); // Create a file in /layer/under/gover/h/i fService.createFile("main:/layer/under/gover/h/i", "moo").close(); fService.createSnapshot("main", null, null); @@ -1766,10 +2796,10 @@ public class AVMServiceTest extends AVMServiceTestBase // and /g should be unchanged between this version and the last. int version = fService.getNextVersionID("main"); // TODO Need an equivalent test that won't mind the version number change -// assertEquals(recursiveContents("main:/d", version - 1, true), -// recursiveContents("main:/d", version - 2, true)); -// assertEquals(recursiveContents("main:/g", version - 1, true), -// recursiveContents("main:/g", version - 2, true)); + // assertEquals(recursiveContents("main:/d", version - 1, true), + // recursiveContents("main:/d", version - 2, true)); + // assertEquals(recursiveContents("main:/g", version - 1, true), + // recursiveContents("main:/g", version - 2, true)); // Add a file through /d/gover/h/i fService.createFile("main:/d/gover/h/i", "cow").close(); fService.createSnapshot("main", null, null); @@ -1777,8 +2807,8 @@ public class AVMServiceTest extends AVMServiceTestBase checkHistory(history, "main"); // /g should not have changed since its last version. version = fService.getNextVersionID("main"); - assertEquals(recursiveContents("main:/g", version - 1, true), - recursiveContents("main:/g", version - 2, true)); + assertEquals(recursiveContents("main:/g", version - 1, true), recursiveContents("main:/g", version - 2, + true)); // /layer/under/gover/h/i shows both moo and cow. listing = fService.getDirectoryListing(-1, "main:/layer/under/gover/h/i"); assertEquals(2, listing.size()); @@ -1790,7 +2820,7 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createSnapshot("main", null, null); // History unchanged. checkHistory(history, "main"); - // moo should be in /layer/b/gover/h/i + // moo should be in /layer/b/gover/h/i listing = fService.getDirectoryListing(-1, "main:/layer/b/gover/h/i"); assertEquals(1, listing.size()); list = new ArrayList(listing.keySet()); @@ -1817,7 +2847,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test behavior when one branches a layer. */ @@ -1841,8 +2871,7 @@ public class AVMServiceTest extends AVMServiceTestBase // History unchanged. checkHistory(history, "main"); // /a and /layer should have identical contents. - assertEquals(recursiveContents("main:/a", -1, true), - recursiveContents("main:/layer", -1, true)); + assertEquals(recursiveContents("main:/a", -1, true), recursiveContents("main:/layer", -1, true)); // Make a modification in /layer fService.createFile("main:/layer/b", "baz").close(); fService.createSnapshot("main", null, null); @@ -1854,8 +2883,7 @@ public class AVMServiceTest extends AVMServiceTestBase // History unchanged. checkHistory(history, "main"); // /layer/b and /branch/b should have identical contents. - assertEquals(recursiveContents("main:/layer/b", -1, true), - recursiveContents("main:/branch/b", -1, true)); + assertEquals(recursiveContents("main:/layer/b", -1, true), recursiveContents("main:/branch/b", -1, true)); // Create /branch/b/c/foo fService.createFile("main:/branch/b/c", "baz").close(); fService.createSnapshot("main", null, null); @@ -1863,8 +2891,8 @@ public class AVMServiceTest extends AVMServiceTestBase checkHistory(history, "main"); // /layer should not have changed. int version = fService.getNextVersionID("main"); - assertEquals(recursiveContents("main:/layer", version - 1, true), - recursiveContents("main:/layer", version - 2, true)); + assertEquals(recursiveContents("main:/layer", version - 1, true), recursiveContents("main:/layer", + version - 2, true)); // Change something in /layer fService.createFile("main:/layer/b/c", "fig").close(); fService.createSnapshot("main", null, null); @@ -1872,8 +2900,8 @@ public class AVMServiceTest extends AVMServiceTestBase checkHistory(history, "main"); // /branch should not have changed. version = fService.getNextVersionID("main"); - assertEquals(recursiveContents("main:/branch", version - 1, true), - recursiveContents("main:/branch", version - 2, true)); + assertEquals(recursiveContents("main:/branch", version - 1, true), recursiveContents("main:/branch", + version - 2, true)); // Create another layer on /a fService.createLayeredDirectory("main:/a", "main:/", "layer2"); fService.createSnapshot("main", null, null); @@ -1891,8 +2919,8 @@ public class AVMServiceTest extends AVMServiceTestBase checkHistory(history, "main"); // /layer2 should be unchanged. version = fService.getNextVersionID("main"); - assertEquals(recursiveContents("main:/layer2", version - 1, true), - recursiveContents("main:/layer2", version - 2, true)); + assertEquals(recursiveContents("main:/layer2", version - 1, true), recursiveContents("main:/layer2", + version - 2, true)); // Remove something from /layer2 fService.removeNode("main:/layer2/b/c", "foo"); fService.createSnapshot("main", null, null); @@ -1900,11 +2928,11 @@ public class AVMServiceTest extends AVMServiceTestBase checkHistory(history, "main"); // /branch2 is unchanged. version = fService.getNextVersionID("main"); - assertEquals(recursiveContents("main:/branch2", version - 1, true), - recursiveContents("main:/branch2", version - 2, true)); + assertEquals(recursiveContents("main:/branch2", version - 1, true), recursiveContents("main:/branch2", + version - 2, true)); // /a is unchanged. - assertEquals(recursiveContents("main:/a", version - 1, true), - recursiveContents("main:/a", version - 2, true)); + assertEquals(recursiveContents("main:/a", version - 1, true), recursiveContents("main:/a", version - 2, + true)); for (String val : history.values()) { System.out.println(val); @@ -1915,8 +2943,8 @@ public class AVMServiceTest extends AVMServiceTestBase e.printStackTrace(System.err); fail(); } - } - + } + /** * Test scenario in which something is renamed from inside one independent layer to another. */ @@ -1968,14 +2996,14 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** - * Test Nothing. Just make sure set up works. + * Test Nothing. Just make sure set up works. */ public void testNothing() { } - + /** * Test making a simple directory. */ @@ -1986,6 +3014,19 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createDirectory("main:/", "testdir"); fService.createSnapshot("main", null, null); assertEquals(AVMNodeType.PLAIN_DIRECTORY, fService.lookup(-1, "main:/").getType()); + + StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); + + // Text index + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results = searchService.query(storeRef, "lucene", "@cm\\:name:testdir"); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(2, results.length()); + results.close(); + } catch (Exception e) { @@ -1993,7 +3034,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test creating a file. */ @@ -2005,26 +3046,64 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createFile("main:/testdir", "testfile").close(); fService.createFile("main:/", "testfile2").close(); fService.createSnapshot("main", null, null); - PrintStream out = new PrintStream(fService.getFileOutputStream("main:/testdir/testfile")); + + StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); + + // Text index + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results = searchService.query(storeRef, "lucene", "@cm\\:name:testfile"); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "@cm\\:name:testfile2"); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "TEXT:\"This is testdir/testfile\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "TEXT:\"This is testfile2\""); + assertEquals(0, results.length()); + results.close(); + + ContentWriter writer = fService.getContentWriter("main:/testdir/testfile"); + writer.setEncoding("UTF-8"); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + PrintStream out = new PrintStream(writer.getContentOutputStream()); out.println("This is testdir/testfile"); out.close(); + out = new PrintStream(fService.getFileOutputStream("main:/testfile2")); + + writer = fService.getContentWriter("main:/testfile2"); + writer.setEncoding("UTF-8"); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + out = new PrintStream(writer.getContentOutputStream()); out.println("This is testfile2"); out.close(); fService.createSnapshot("main", null, null); + + results = searchService.query(storeRef, "lucene", "TEXT:\"This is testdir/testfile\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "TEXT:\"This is testfile2\""); + assertEquals(1, results.length()); + results.close(); + List versions = fService.getStoreVersions("main"); for (VersionDescriptor version : versions) { System.out.println("V:" + version.getVersionID()); System.out.println(recursiveList("main", version.getVersionID(), true)); } - BufferedReader reader = - new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/testdir/testfile"))); + BufferedReader reader = new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, + "main:/testdir/testfile"))); String line = reader.readLine(); assertEquals("This is testdir/testfile", line); reader.close(); - reader = - new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/testfile2"))); + reader = new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/testfile2"))); line = reader.readLine(); assertEquals("This is testfile2", line); } @@ -2034,7 +3113,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test creating a branch. */ @@ -2063,7 +3142,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test creating a layer. */ @@ -2076,14 +3155,13 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); assertEquals("main:/a", fService.getIndirectionPath(-1, "main:/d/e/alayer")); - assertEquals(recursiveContents("main:/a", -1, true), - recursiveContents("main:/d/e/alayer", -1, true)); + assertEquals(recursiveContents("main:/a", -1, true), recursiveContents("main:/d/e/alayer", -1, true)); PrintStream out = new PrintStream(fService.getFileOutputStream("main:/d/e/alayer/b/c/foo")); out.println("I am main:/d/e/alayer/b/c/foo"); out.close(); fService.createSnapshot("main", null, null); - BufferedReader reader = - new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/a/b/c/foo"))); + BufferedReader reader = new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, + "main:/a/b/c/foo"))); String line = reader.readLine(); reader.close(); assertEquals("I am main:/a/b/c/foo", line); @@ -2095,7 +3173,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test creating a layered file. */ @@ -2108,8 +3186,8 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); assertEquals("main:/a/b/c/foo", fService.lookup(-1, "main:/d/lfoo").getIndirection()); - BufferedReader reader = - new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/d/lfoo"))); + BufferedReader reader = new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, + "main:/d/lfoo"))); String line = reader.readLine(); reader.close(); assertEquals("I am main:/a/b/c/foo", line); @@ -2118,13 +3196,11 @@ public class AVMServiceTest extends AVMServiceTestBase out.close(); fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); - reader = - new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/a/b/c/foo"))); + reader = new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/a/b/c/foo"))); line = reader.readLine(); reader.close(); assertEquals("I am main:/a/b/c/foo", line); - reader = - new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/d/lfoo"))); + reader = new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/d/lfoo"))); line = reader.readLine(); reader.close(); assertEquals("I am main:/d/lfoo", line); @@ -2135,7 +3211,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test rename. */ @@ -2147,8 +3223,161 @@ public class AVMServiceTest extends AVMServiceTestBase fService.rename("main:/a", "b", "main:/d/e", "brenamed"); fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); - assertEquals(recursiveContents("main:/a/b", 1, true), - recursiveContents("main:/d/e/brenamed", 2, true)); + assertEquals(recursiveContents("main:/a/b", 1, true), recursiveContents("main:/d/e/brenamed", 2, true)); + + // Test inedx update + + StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); + + // Text index + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"I am main\""); + assertEquals(2, results.length()); + results.close(); + + // Basic properties + + // Note "a" is a stop word and therefore not findable ... + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":\"foo\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":foo"); + assertEquals(1, results.length()); + results.close(); + + // TODO: Fix auth in AVMDiskDriver and more?? + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_CREATOR) + + ":admin"); + + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser + .escape("@" + ContentModel.PROP_MODIFIER) + + ":admin"); + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_OWNER) + + ":admin"); + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_NODE_UUID) + + ":unknown"); + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_PROTOCOL) + + ":avm"); + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_IDENTIFIER) + + ":main" ); + assertEquals(9, results.length()); + results.close(); + + // Basic paths + + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); + assertEquals(0, results.length()); + results.close(); + + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/brenamed\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/brenamed/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/brenamed/c/foo\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/brenamed/c/bar\""); + assertEquals(1, results.length()); + results.close(); + + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); + assertEquals(8, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + } catch (Exception e) { @@ -2156,7 +3385,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test remove. */ @@ -2180,6 +3409,146 @@ public class AVMServiceTest extends AVMServiceTestBase System.out.println(history.get(2)); l = fService.getDirectoryListing(-1, "main:/d"); assertEquals(0, l.size()); + +// Text index + StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"I am main\""); + assertEquals(1, results.length()); + results.close(); + + // Basic properties + + // Note "a" is a stop word and therefore not findable ... + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":\"foo\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_NAME) + + ":foo"); + assertEquals(0, results.length()); + results.close(); + + // TODO: Fix auth in AVMDiskDriver and more?? + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_CREATOR) + + ":admin"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser + .escape("@" + ContentModel.PROP_MODIFIER) + + ":admin"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + ContentModel.PROP_OWNER) + + ":admin"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_NODE_UUID) + + ":unknown"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_PROTOCOL) + + ":avm"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@" + + ContentModel.PROP_STORE_IDENTIFIER) + + ":" + "main"); + assertEquals(6, results.length()); + results.close(); + + // Basic paths + + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/foo\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/bar\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); + assertEquals(4, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); + assertEquals(3, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + } catch (Exception e) { @@ -2187,7 +3556,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test branching from one AVMStore to another. */ @@ -2204,18 +3573,16 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createBranch(-1, "main:/", "second:/", "main"); fService.createSnapshot("second", null, null); System.out.println(recursiveList("second", -1, true)); - assertEquals(recursiveContents("main:/", -1, true), - recursiveContents("second:/main", -1, true)); + assertEquals(recursiveContents("main:/", -1, true), recursiveContents("second:/main", -1, true)); // Now make sure nothing happens to the branched from place, // if the branch is modified. - PrintStream out = - new PrintStream(fService.getFileOutputStream("second:/main/a/b/c/foo")); + PrintStream out = new PrintStream(fService.getFileOutputStream("second:/main/a/b/c/foo")); out.println("I am second:/main/a/b/c/foo"); out.close(); fService.createSnapshot("second", null, null); System.out.println(recursiveList("second", -1, true)); - BufferedReader reader = - new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/a/b/c/foo"))); + BufferedReader reader = new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, + "main:/a/b/c/foo"))); String line = reader.readLine(); reader.close(); assertEquals("I am main:/a/b/c/foo", line); @@ -2226,7 +3593,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test creating a layer across AVMStores. */ @@ -2239,8 +3606,7 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createLayeredDirectory("main:/", "second:/", "main"); fService.createSnapshot("second", null, null); System.out.println(recursiveList("second", -1, true)); - assertEquals(recursiveContents("main:/", -1, true), - recursiveContents("second:/main", -1, true)); + assertEquals(recursiveContents("main:/", -1, true), recursiveContents("second:/main", -1, true)); // Now make sure that a copy on write will occur and // that the underlying stuff doesn't get changed. PrintStream out = new PrintStream(fService.getFileOutputStream("second:/main/a/b/c/foo")); @@ -2248,13 +3614,12 @@ public class AVMServiceTest extends AVMServiceTestBase out.close(); fService.createSnapshot("second", null, null); System.out.println(recursiveList("second", -1, true)); - BufferedReader reader = - new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "second:/main/a/b/c/foo"))); + BufferedReader reader = new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, + "second:/main/a/b/c/foo"))); String line = reader.readLine(); reader.close(); assertEquals("I am second:/main/a/b/c/foo", line); - reader = - new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/a/b/c/foo"))); + reader = new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/a/b/c/foo"))); line = reader.readLine(); reader.close(); assertEquals("I am main:/a/b/c/foo", line); @@ -2264,10 +3629,10 @@ public class AVMServiceTest extends AVMServiceTestBase catch (Exception e) { e.printStackTrace(System.err); - fail(); + fail(); } } - + /** * Test rename across AVMStores. */ @@ -2285,8 +3650,7 @@ public class AVMServiceTest extends AVMServiceTestBase System.out.println(recursiveList("second", -1, true)); // Check that the moved thing has identical contents to the thing it // was moved from. - assertEquals(recursiveContents("main:/a/b/c", 1, true), - recursiveContents("second:/cmoved", -1, true)); + assertEquals(recursiveContents("main:/a/b/c", 1, true), recursiveContents("second:/cmoved", -1, true)); } catch (Exception e) { @@ -2294,7 +3658,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test COW in various circumstances. */ @@ -2333,7 +3697,7 @@ public class AVMServiceTest extends AVMServiceTestBase list = new ArrayList(listing.keySet()); assertEquals("bar.txt", list.get(0)); assertEquals("foo.txt", list.get(1)); - AVMNodeDescriptor [] arrayListing = fService.getDirectoryListingArray(-1, "main:/d/b", false); + AVMNodeDescriptor[] arrayListing = fService.getDirectoryListingArray(-1, "main:/d/b", false); assertEquals("bar.txt", arrayListing[0].getName()); assertEquals("foo.txt", arrayListing[1].getName()); fService.rename("main:/", "c", "main:/", "e"); @@ -2350,7 +3714,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test branching and layering interaction. */ @@ -2370,22 +3734,19 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createSnapshot("main", null, null); // The branch should contain exactly the same things as the thing // it branched from. - assertEquals(recursiveContents("main:/a", -1, true), - recursiveContents("main:/branch", -1, true)); + assertEquals(recursiveContents("main:/a", -1, true), recursiveContents("main:/branch", -1, true)); // Make a layer pointing to /branch/b fService.createLayeredDirectory("main:/branch/b", "main:/", "layer"); fService.createSnapshot("main", null, null); // The new layer should contain exactly the same things as the thing it is layered to. - assertEquals(recursiveContents("main:/branch/b", -1, true), - recursiveContents("main:/layer", -1, true)); + assertEquals(recursiveContents("main:/branch/b", -1, true), recursiveContents("main:/layer", -1, true)); // Make a modification in /a/b, the original branch. PrintStream out = new PrintStream(fService.getFileOutputStream("main:/a/b/c.txt")); out.println("I am c, modified in main:/a/b."); out.close(); fService.createSnapshot("main", null, null); // The layer should still have identical content to /branch/b. - assertEquals(recursiveContents("main:/branch/b", -1, true), - recursiveContents("main:/layer", -1, true)); + assertEquals(recursiveContents("main:/branch/b", -1, true), recursiveContents("main:/layer", -1, true)); // But the layer won't have contents identical to /a/b's assertFalse(recursiveContents("main:/a/b", -1, true).equals(recursiveContents("main:/layer", -1, true))); // Make a modification in /branch/b @@ -2394,8 +3755,7 @@ public class AVMServiceTest extends AVMServiceTestBase out.close(); fService.createSnapshot("main", null, null); // The layer contents should be identical to the latest contents of /branch/b. - assertEquals(recursiveContents("main:/branch/b", -1, true), - recursiveContents("main:/layer", -1, true)); + assertEquals(recursiveContents("main:/branch/b", -1, true), recursiveContents("main:/layer", -1, true)); } catch (Exception e) { @@ -2403,7 +3763,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test basic Layering. */ @@ -2417,7 +3777,7 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createDirectory("main:/a/b", "c"); fService.createDirectory("main:/a/b/c", "d"); fService.createSnapshot("main", null, null); - // Now make some layers. Three to be precise. + // Now make some layers. Three to be precise. fService.createLayeredDirectory("main:/a", "main:/", "e"); fService.createLayeredDirectory("main:/e", "main:/", "f"); fService.createLayeredDirectory("main:/f", "main:/", "g"); @@ -2471,7 +3831,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test rename within a layer. */ @@ -2489,8 +3849,7 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createLayeredDirectory("main:/a", "main:/", "layer"); fService.createSnapshot("main", null, null); // /layer should have the same contents as /a at this point. - assertEquals(recursiveContents("main:/a", -1, true), - recursiveContents("main:/layer", -1, true)); + assertEquals(recursiveContents("main:/a", -1, true), recursiveContents("main:/layer", -1, true)); // Now we will rename /layer/d to /layer/moved fService.rename("main:/layer", "d", "main:/layer", "moved"); fService.createSnapshot("main", null, null); @@ -2516,7 +3875,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test behavior of multiply layers not in register. */ @@ -2563,7 +3922,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test makePrimary. */ @@ -2591,8 +3950,7 @@ public class AVMServiceTest extends AVMServiceTestBase // History unchanged. checkHistory(history, "main"); // /a/b/c should have identical contents to /layer/c - assertEquals(recursiveContents("main:/a/b/c", -1, true), - recursiveContents("main:/layer/c", -1, true)); + assertEquals(recursiveContents("main:/a/b/c", -1, true), recursiveContents("main:/layer/c", -1, true)); // Create /layer2 to /a. fService.createLayeredDirectory("main:/a", "main:/", "layer2"); // Make a file down in /layer2/b/c @@ -2622,7 +3980,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test retargeting a directory. */ @@ -2655,8 +4013,7 @@ public class AVMServiceTest extends AVMServiceTestBase // History unchanged. checkHistory(history, "main"); // /d should have identical contents to /layer/c - assertEquals(recursiveContents("main:/d", -1, true), - recursiveContents("main:/layer/c", -1, true)); + assertEquals(recursiveContents("main:/d", -1, true), recursiveContents("main:/layer/c", -1, true)); // Create /layer2 to /a. fService.createLayeredDirectory("main:/a", "main:/", "layer2"); // Make a file down in /layer2/b/c @@ -2685,7 +4042,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test rename between branches. */ @@ -2721,19 +4078,19 @@ public class AVMServiceTest extends AVMServiceTestBase checkHistory(history, "main"); // Confirm that /a and /d are unchanged. int version = fService.getNextVersionID("main"); - assertEquals(recursiveContents("main:/a", version - 1, true), - recursiveContents("main:/a", version - 2, true)); - assertEquals(recursiveContents("main:/d", version - 1, true), - recursiveContents("main:/d", version - 2, true)); + assertEquals(recursiveContents("main:/a", version - 1, true), recursiveContents("main:/a", version - 2, + true)); + assertEquals(recursiveContents("main:/d", version - 1, true), recursiveContents("main:/d", version - 2, + true)); // Move /dbranch/f to /abranch/c/f fService.rename("main:/dbranch", "f", "main:/abranch/c", "f"); fService.createSnapshot("main", null, null); // Confirm that /a and /d are unchanged. version = fService.getNextVersionID("main"); - assertEquals(recursiveContents("main:/a", version - 1, true), - recursiveContents("main:/a", version - 2, true)); - assertEquals(recursiveContents("main:/d", version - 1, true), - recursiveContents("main:/d", version - 2, true)); + assertEquals(recursiveContents("main:/a", version - 1, true), recursiveContents("main:/a", version - 2, + true)); + assertEquals(recursiveContents("main:/d", version - 1, true), recursiveContents("main:/d", version - 2, + true)); // History unchanged. checkHistory(history, "main"); for (String val : history.values()) @@ -2803,7 +4160,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test renaming into a layer. */ @@ -2860,7 +4217,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test proper indirection behavior. */ @@ -2904,7 +4261,8 @@ public class AVMServiceTest extends AVMServiceTestBase // History unchanged. checkHistory(history, "main"); // /layer/b/c/fover/g/h/iover/j/k should contain pismo and foo. - Map listing = fService.getDirectoryListing(-1, "main:/layer/b/c/fover/g/h/iover/j/k"); + Map listing = fService.getDirectoryListing(-1, + "main:/layer/b/c/fover/g/h/iover/j/k"); assertEquals(2, listing.size()); List list = new ArrayList(listing.keySet()); assertEquals("foo", list.get(0)); @@ -2950,16 +4308,14 @@ public class AVMServiceTest extends AVMServiceTestBase out.print("version2"); out.close(); fService.createSnapshot("main", null, null); - BufferedReader reader = - new BufferedReader(new InputStreamReader(fService.getFileInputStream(1, "main:/afoo"))); + BufferedReader reader = new BufferedReader(new InputStreamReader(fService.getFileInputStream(1, + "main:/afoo"))); assertEquals("version1", reader.readLine()); reader.close(); - reader = - new BufferedReader(new InputStreamReader(fService.getFileInputStream(2, "main:/afoo"))); + reader = new BufferedReader(new InputStreamReader(fService.getFileInputStream(2, "main:/afoo"))); assertEquals("version2", reader.readLine()); reader.close(); - reader = - new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/afoo"))); + reader = new BufferedReader(new InputStreamReader(fService.getFileInputStream(-1, "main:/afoo"))); assertEquals("version2", reader.readLine()); reader.close(); } @@ -2971,8 +4327,7 @@ public class AVMServiceTest extends AVMServiceTestBase } /** - * Test rename of an overlayed directory contained in an overlayed - * directory. + * Test rename of an overlayed directory contained in an overlayed directory. */ public void testRenameLayerInLayer() { @@ -3001,7 +4356,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Yet another rename from layer to layer test. */ @@ -3017,10 +4372,13 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createDirectory("main:/d", "e"); fService.createDirectory("main:/d/e", "f"); fService.createSnapshot("main", null, null); + runQueriesForInitialRenameStructure("main"); // Make a layer over each. fService.createLayeredDirectory("main:/a", "main:/", "la"); fService.createLayeredDirectory("main:/d", "main:/", "ld"); fService.createSnapshot("main", null, null); + // TODO: Sort out paths to layers .... + //runQueriesForInitialRenameStructureAndInitialLayers("main"); // rename from down in one layer to another. fService.rename("main:/ld/e", "f", "main:/la/b", "f"); fService.createSnapshot("main", null, null); @@ -3032,7 +4390,7 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createSnapshot("main", null, null); desc = fService.lookup(-1, "main:/la/b/c/f"); assertTrue(desc.isPrimary()); - assertEquals("main:/d/e/f", desc.getIndirection()); + assertEquals("main:/d/e/f", desc.getIndirection()); // Now create a directory in the layered f. fService.createDirectory("main:/la/b/c/f", "dir"); fService.createSnapshot("main", null, null); @@ -3053,6 +4411,224 @@ public class AVMServiceTest extends AVMServiceTestBase } } + + protected void runQueriesForInitialRenameStructure(String store) + { + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + + + SearchService searchService = fIndexerAndSearcher.getSearcher(AVMNodeConverter.ToStoreRef(store), true); + + // Note "a" is a stop word and therefore not findable ... + + ResultSet results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_CREATOR)+":admin"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_MODIFIER)+":admin"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_OWNER)+":admin"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_NODE_UUID)+":unknown"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_STORE_PROTOCOL)+":avm"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_STORE_IDENTIFIER)+":"+store); + assertEquals(7, results.length()); + results.close(); + + // Basic paths + + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); + assertEquals(3, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + } + + + protected void runQueriesForInitialRenameStructureAndInitialLayers(String store) + { + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + + + SearchService searchService = fIndexerAndSearcher.getSearcher(AVMNodeConverter.ToStoreRef(store), true); + + // Note "a" is a stop word and therefore not findable ... + + ResultSet results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_CREATOR)+":admin"); + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_MODIFIER)+":admin"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_OWNER)+":admin"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_NODE_UUID)+":unknown"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_STORE_PROTOCOL)+":avm"); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_STORE_IDENTIFIER)+":"+store); + assertEquals(7, results.length()); + results.close(); + + // Basic paths + + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(7, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); + assertEquals(3, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + } + /** * Test rename behavior of an overlayed file withing a layer. */ @@ -3086,37 +4662,18 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * The random access. */ /* - public void testRandomAccess() - { - try - { - setupBasicTree(); - RandomAccessFile file = fService.getRandomAccess(1, "main:/a/b/c/foo", "r"); - byte [] buff = new byte[256]; - assertTrue(file.read(buff) >= 20); - file.close(); - file = fService.getRandomAccess(-1, "main:/a/b/c/bar", "rw"); - for (int i = 0; i < 256; i++) - { - buff[i] = (byte)i; - } - file.write(buff); - file.close(); - fService.createSnapshot("main", null, null); - } - catch (Exception e) - { - e.printStackTrace(System.err); - fail(); - } - } - */ - + * public void testRandomAccess() { try { setupBasicTree(); RandomAccessFile file = fService.getRandomAccess(1, + * "main:/a/b/c/foo", "r"); byte [] buff = new byte[256]; assertTrue(file.read(buff) >= 20); file.close(); file = + * fService.getRandomAccess(-1, "main:/a/b/c/bar", "rw"); for (int i = 0; i < 256; i++) { buff[i] = (byte)i; } + * file.write(buff); file.close(); fService.createSnapshot("main", null, null); } catch (Exception e) { + * e.printStackTrace(System.err); fail(); } } + */ + /** * Test COW during long operations. */ @@ -3137,8 +4694,8 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createFile("main:/l2/e/f/layer/b/c", "nottle").close(); fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); - assertFalse(fService.lookup(-1, "main:/d/e/f/layer/b/c").getId() == - fService.lookup(-1, "main:/l2/e/f/layer/b/c").getId()); + assertFalse(fService.lookup(-1, "main:/d/e/f/layer/b/c").getId() == fService.lookup(-1, + "main:/l2/e/f/layer/b/c").getId()); } catch (Exception e) { @@ -3146,7 +4703,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test new lookup methods. */ @@ -3171,7 +4728,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test version by date lookup. */ @@ -3194,7 +4751,7 @@ public class AVMServiceTest extends AVMServiceTestBase assertEquals(1, fService.getStoreVersions("main", null, new Date(times.get(0))).size()); assertEquals(3, fService.getStoreVersions("main", new Date(times.get(0)), null).size()); assertEquals(2, fService.getStoreVersions("main", new Date(times.get(1)), - new Date(System.currentTimeMillis())).size()); + new Date(System.currentTimeMillis())).size()); } catch (Exception e) { @@ -3202,7 +4759,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test AVMStore functions. */ @@ -3232,7 +4789,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test opacity and manipulations. */ @@ -3249,7 +4806,7 @@ public class AVMServiceTest extends AVMServiceTestBase Map listing = fService.getDirectoryListing(-1, "main:/layer/b/c"); assertEquals(4, listing.size()); System.out.println(recursiveList("main", -1, true)); - // Setting the opacity of layer to true will make no difference to what we see through + // Setting the opacity of layer to true will make no difference to what we see through // main:/layer/b/c. fService.setOpacity("main:/layer", true); fService.createSnapshot("main", null, null); @@ -3281,7 +4838,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test common ancestor. */ @@ -3316,15 +4873,27 @@ public class AVMServiceTest extends AVMServiceTestBase try { setupBasicTree(); + + StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}SillyProperty")+":\"Silly\""); + assertEquals(0, results.length()); + results.close(); + QName name = QName.createQName("silly.uri", "SillyProperty"); PropertyValue value = new PropertyValue(name, "Silly Property Value"); fService.setNodeProperty("main:/a/b/c/foo", name, value); fService.createSnapshot("main", null, null); + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}SillyProperty")+":\"Silly\""); + assertEquals(1, results.length()); + results.close(); PropertyValue returned = fService.getNodeProperty(-1, "main:/a/b/c/foo", name); assertEquals(value.toString(), returned.toString()); Map props = fService.getNodeProperties(-1, "main:/a/b/c/foo"); assertEquals(1, props.size()); assertEquals(value.toString(), props.get(name).toString()); + + props = new HashMap(); QName n1 = QName.createQName("silly.uri", "Prop1"); PropertyValue p1 = new PropertyValue(null, new Date(System.currentTimeMillis())); @@ -3342,27 +4911,58 @@ public class AVMServiceTest extends AVMServiceTestBase assertEquals(p1.toString(), props.get(n1).toString()); assertEquals(p2.toString(), props.get(n2).toString()); assertEquals(p3.toString(), props.get(n3).toString()); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop1")+":\"" + props.get(n1).getStringValue() +"\""); + assertEquals(1, results.length()); + results.close(); + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop2")+":\"" + props.get(n2).getStringValue() +"\""); + assertEquals(1, results.length()); + results.close(); + fService.deleteNodeProperty("main:/a/b/c/bar", n1); fService.createSnapshot("main", null, null); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop1")+":\"" + props.get(n1).getStringValue() +"\""); + assertEquals(0, results.length()); + results.close(); + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop2")+":\"" + props.get(n2).getStringValue() +"\""); + assertEquals(1, results.length()); + results.close(); + props = fService.getNodeProperties(-1, "main:/a/b/c/bar"); assertEquals(2, props.size()); assertEquals(p2.toString(), props.get(n2).toString()); assertEquals(p3.toString(), props.get(n3).toString()); fService.deleteNodeProperties("main:/a/b/c/bar"); fService.createSnapshot("main", null, null); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop1")+":\"" + props.get(n1).getStringValue() +"\""); + assertEquals(0, results.length()); + results.close(); + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop2")+":\"" + props.get(n2).getStringValue() +"\""); + assertEquals(0, results.length()); + results.close(); + props = fService.getNodeProperties(-1, "main:/a/b/c/bar"); assertEquals(0, props.size()); fService.removeNode("main:/a/b/c/foo"); - fService.setNodeProperty("main:/a/b/c/foo", QName.createQName("silly.uri", "Prop1"), - new PropertyValue(null, 42)); + fService.setNodeProperty("main:/a/b/c/foo", QName.createQName("silly.uri", "Prop1"), new PropertyValue( + null, 42)); assertEquals(1, fService.getNodeProperties(-1, "main:/a/b/c/foo").size()); + fService.createSnapshot("main", null, null); + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop1")+":\"" + props.get(n1).getStringValue() +"\""); + assertEquals(0, results.length()); + results.close(); + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@{silly.uri}Prop2")+":\"" + props.get(n2).getStringValue() +"\""); + assertEquals(0, results.length()); + results.close(); } catch (Exception e) { e.printStackTrace(System.err); } } - + /** * Test properties on stores. */ @@ -3384,7 +4984,7 @@ public class AVMServiceTest extends AVMServiceTestBase props.put(n2, p2); QName n3 = QName.createQName("silly.uri", "Prop3"); PropertyValue p3 = new PropertyValue(null, 42); - props.put(n3, p3); + props.put(n3, p3); fService.setStoreProperties("main", props); props = fService.getStoreProperties("main"); assertEquals(6, props.size()); @@ -3401,7 +5001,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test Aspect Name storage. */ @@ -3410,9 +5010,27 @@ public class AVMServiceTest extends AVMServiceTestBase try { setupBasicTree(); + + StoreRef storeRef = AVMNodeConverter.ToStoreRef("main"); + SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true); + ResultSet results = searchService.query(storeRef, "lucene", "ASPECT:\"" + ContentModel.ASPECT_TITLED.toString() +"\""); + assertEquals(0, results.length()); + results.close(); + results = searchService.query(storeRef, "lucene", "ASPECT:\"" + ContentModel.ASPECT_AUDITABLE.toString() +"\""); + assertEquals(0, results.length()); + results.close(); + fService.addAspect("main:/a/b/c/foo", ContentModel.ASPECT_TITLED); fService.addAspect("main:/a/b/c/foo", ContentModel.ASPECT_AUDITABLE); fService.createSnapshot("main", null, null); + + results = searchService.query(storeRef, "lucene", "ASPECT:\"" + ContentModel.ASPECT_TITLED.toString() +"\""); + assertEquals(1, results.length()); + results.close(); + results = searchService.query(storeRef, "lucene", "ASPECT:\"" + ContentModel.ASPECT_AUDITABLE.toString() +"\""); + assertEquals(1, results.length()); + results.close(); + fService.removeNode("main:/a/b/c/bar"); fService.addAspect("main:/a/b/c/bar", ContentModel.ASPECT_TITLED); List names = fService.getAspects(-1, "main:/a/b/c/foo"); @@ -3422,6 +5040,15 @@ public class AVMServiceTest extends AVMServiceTestBase assertTrue(fService.hasAspect(-1, "main:/a/b/c/foo", ContentModel.ASPECT_TITLED)); fService.removeAspect("main:/a/b/c/foo", ContentModel.ASPECT_TITLED); fService.createSnapshot("main", null, null); + + results = searchService.query(storeRef, "lucene", "ASPECT:\"" + ContentModel.ASPECT_TITLED.toString() +"\""); + assertEquals(0, results.length()); + results.close(); + results = searchService.query(storeRef, "lucene", "ASPECT:\"" + ContentModel.ASPECT_AUDITABLE.toString() +"\""); + assertEquals(1, results.length()); + results.close(); + + fService.getFileOutputStream("main:/a/b/c/foo").close(); assertFalse(fService.hasAspect(-1, "main:/a/b/c/foo", ContentModel.ASPECT_TITLED)); assertTrue(fService.hasAspect(-1, "main:/a/b/c/foo", ContentModel.ASPECT_AUDITABLE)); @@ -3432,7 +5059,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test case insensitivity. */ @@ -3457,7 +5084,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test ACLs. */ @@ -3466,17 +5093,14 @@ public class AVMServiceTest extends AVMServiceTestBase try { setupBasicTree(); - PermissionService perm = (PermissionService)fContext.getBean("PermissionService"); + PermissionService perm = (PermissionService) fContext.getBean("PermissionService"); // AuthenticationService ac = (AuthenticationService)fContext.getBean("AuthenticationService"); // ac.authenticate("admin", "admin".toCharArray()); - perm.setPermission(AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c/foo"), - PermissionService.ADMINISTRATOR_AUTHORITY, - PermissionService.ALL_PERMISSIONS, - true); + perm.setPermission(AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c/foo"), + PermissionService.ADMINISTRATOR_AUTHORITY, PermissionService.ALL_PERMISSIONS, true); fService.createSnapshot("main", null, null); fService.getFileOutputStream("main:/a/b/c/foo").close(); - Set perms = - perm.getPermissions(AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c/foo")); + Set perms = perm.getPermissions(AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c/foo")); for (AccessPermission permission : perms) { System.out.println(permission); @@ -3489,7 +5113,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test FileFolderService with AVM. */ @@ -3498,36 +5122,27 @@ public class AVMServiceTest extends AVMServiceTestBase try { setupBasicTree(); - FileFolderService ffs = (FileFolderService)fContext.getBean("FileFolderService"); + FileFolderService ffs = (FileFolderService) fContext.getBean("FileFolderService"); // AuthenticationComponent ac = (AuthenticationComponent)fContext.getBean("authenticationComponent"); // ac.authenticate("admin", "admin".toCharArray()); - assertTrue(ffs.create(AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c/"), - "banana", WCMModel.TYPE_AVM_PLAIN_CONTENT) != null); - assertTrue(ffs.create(AVMNodeConverter.ToNodeRef(-1, "main://"), - "banana", WCMModel.TYPE_AVM_PLAIN_CONTENT) != null); - assertTrue(ffs.create(AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c"), - "apples", WCMModel.TYPE_AVM_PLAIN_FOLDER) != null); - NodeService ns = (NodeService)fContext.getBean("NodeService"); + assertTrue(ffs.create(AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c/"), "banana", + WCMModel.TYPE_AVM_PLAIN_CONTENT) != null); + assertTrue(ffs.create(AVMNodeConverter.ToNodeRef(-1, "main://"), "banana", WCMModel.TYPE_AVM_PLAIN_CONTENT) != null); + assertTrue(ffs.create(AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c"), "apples", + WCMModel.TYPE_AVM_PLAIN_FOLDER) != null); + NodeService ns = (NodeService) fContext.getBean("NodeService"); Map properties = new HashMap(); - properties.put(WCMModel.PROP_AVM_DIR_INDIRECTION, - AVMNodeConverter.ToNodeRef(-1, "main:/a")); - assertTrue(ns.createNode(AVMNodeConverter.ToNodeRef(-1, "main:/"), - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "layer"), - WCMModel.TYPE_AVM_LAYERED_FOLDER, - properties) != null); - assertTrue(ns.getProperty(AVMNodeConverter.ToNodeRef(-1, "main:/layer"), - WCMModel.PROP_AVM_DIR_INDIRECTION) != null); + properties.put(WCMModel.PROP_AVM_DIR_INDIRECTION, AVMNodeConverter.ToNodeRef(-1, "main:/a")); + assertTrue(ns.createNode(AVMNodeConverter.ToNodeRef(-1, "main:/"), ContentModel.ASSOC_CONTAINS, QName + .createQName(NamespaceService.APP_MODEL_1_0_URI, "layer"), WCMModel.TYPE_AVM_LAYERED_FOLDER, + properties) != null); + assertTrue(ns.getProperty(AVMNodeConverter.ToNodeRef(-1, "main:/layer"), WCMModel.PROP_AVM_DIR_INDIRECTION) != null); properties.clear(); - properties.put(WCMModel.PROP_AVM_FILE_INDIRECTION, - AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c/foo")); - assertTrue(ns.createNode(AVMNodeConverter.ToNodeRef(-1, "main:/"), - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "foo"), - WCMModel.TYPE_AVM_LAYERED_CONTENT, - properties) != null); - assertTrue(ns.getProperty(AVMNodeConverter.ToNodeRef(-1, "main:/foo"), - WCMModel.PROP_AVM_FILE_INDIRECTION) != null); + properties.put(WCMModel.PROP_AVM_FILE_INDIRECTION, AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c/foo")); + assertTrue(ns.createNode(AVMNodeConverter.ToNodeRef(-1, "main:/"), ContentModel.ASSOC_CONTAINS, QName + .createQName(NamespaceService.APP_MODEL_1_0_URI, "foo"), WCMModel.TYPE_AVM_LAYERED_CONTENT, + properties) != null); + assertTrue(ns.getProperty(AVMNodeConverter.ToNodeRef(-1, "main:/foo"), WCMModel.PROP_AVM_FILE_INDIRECTION) != null); fService.createSnapshot("main", null, null); System.out.println(recursiveList("main", -1, true)); } @@ -3537,7 +5152,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test overwriting without snapshots in between. */ @@ -3552,7 +5167,7 @@ public class AVMServiceTest extends AVMServiceTestBase { try { - AVMService service = (AVMService)fContext.getBean("avmService"); + AVMService service = (AVMService) fContext.getBean("avmService"); service.createLayeredDirectory("main:/a", "main:/", "layer"); // Modify something in an ordinary directory 3 times. service.getFileOutputStream("main:/a/b/c/foo").close(); @@ -3592,7 +5207,7 @@ public class AVMServiceTest extends AVMServiceTestBase // Do nothing. } service.createDirectory("main:/layer/b/c", "groo"); - service.createFile("main:/layer/b/c/groo", "granistan").close(); + service.createFile("main:/layer/b/c/groo", "granistan").close(); return null; } catch (IOException e) @@ -3603,8 +5218,8 @@ public class AVMServiceTest extends AVMServiceTestBase } } } - RetryingTransactionHelper helper = - (RetryingTransactionHelper)fContext.getBean("retryingTransactionHelper"); + RetryingTransactionHelper helper = (RetryingTransactionHelper) fContext + .getBean("retryingTransactionHelper"); helper.doInTransaction(new TxnCallback(), false); assertNotNull(fService.lookup(-1, "main:/layer/b/c/groo")); } @@ -3614,7 +5229,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test creating a file over a ghost. */ @@ -3632,7 +5247,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test lookup and listing of deleted files. */ @@ -3687,7 +5302,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test Store property querying. */ @@ -3695,25 +5310,24 @@ public class AVMServiceTest extends AVMServiceTestBase { try { - fService.setStoreProperty("main", QName.createQName(null, ".dns.alice--preview"), - new PropertyValue(null, "alice-preview")); - fService.setStoreProperty("main", QName.createQName("", ".other.property"), - new PropertyValue(null, "other value")); - Map result = - fService.queryStorePropertyKey("main", QName.createQName("", ".dns.%")); + fService.setStoreProperty("main", QName.createQName(null, ".dns.alice--preview"), new PropertyValue(null, + "alice-preview")); + fService.setStoreProperty("main", QName.createQName("", ".other.property"), new PropertyValue(null, + "other value")); + Map result = fService.queryStorePropertyKey("main", QName.createQName("", ".dns.%")); assertEquals(1, result.size()); fService.createStore("second"); - fService.setStoreProperty("second", QName.createQName("", ".dns.alice"), - new PropertyValue(null, "alice-space")); - Map> matches = - fService.queryStoresPropertyKeys(QName.createQName("", ".dns.%")); + fService.setStoreProperty("second", QName.createQName("", ".dns.alice"), new PropertyValue(null, + "alice-space")); + Map> matches = fService.queryStoresPropertyKeys(QName.createQName("", + ".dns.%")); assertEquals(2, matches.size()); assertEquals(1, matches.get("main").size()); assertEquals(1, matches.get("second").size()); - assertEquals("alice-preview", matches.get("main").get(QName.createQName(null, - ".dns.alice--preview")).getStringValue()); - assertEquals("alice-space", matches.get("second").get(QName.createQName(null, ".dns.alice")). - getStringValue()); + assertEquals("alice-preview", matches.get("main").get(QName.createQName(null, ".dns.alice--preview")) + .getStringValue()); + assertEquals("alice-space", matches.get("second").get(QName.createQName(null, ".dns.alice")) + .getStringValue()); } catch (Exception e) { @@ -3721,7 +5335,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } - + /** * Test AVMSyncService resetLayer. */ @@ -3732,12 +5346,10 @@ public class AVMServiceTest extends AVMServiceTestBase setupBasicTree(); fService.createLayeredDirectory("main:/a", "main:/", "layer"); fService.createFile("main:/layer", "figs").close(); - assertFalse(recursiveContents("main:/a", -1, true).equals( - recursiveContents("main:/layer", -1, true))); + assertFalse(recursiveContents("main:/a", -1, true).equals(recursiveContents("main:/layer", -1, true))); System.out.println(recursiveList("main", -1, true)); fSyncService.resetLayer("main:/layer"); - assertEquals(recursiveContents("main:/a", -1, true), - recursiveContents("main:/layer", -1, true)); + assertEquals(recursiveContents("main:/a", -1, true), recursiveContents("main:/layer", -1, true)); System.out.println(recursiveList("main", -1, true)); } catch (Exception e) diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java b/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java index 4732ad7add..e49bc2a4eb 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java @@ -29,10 +29,21 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.search.IndexerAndSearcher; +import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avm.AVMStoreDescriptor; import org.alfresco.service.cmr.avmsync.AVMSyncService; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.ResultSetRow; +import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.AuthenticationService; import org.springframework.context.support.FileSystemXmlApplicationContext; @@ -68,6 +79,8 @@ public class AVMServiceTestBase extends TestCase */ private long fStartTime; + protected static IndexerAndSearcher fIndexerAndSearcher; + /** * Setup for AVM tests. Note that we set the polling * interval for the reaper to 4 seconds so that tests will @@ -82,6 +95,7 @@ public class AVMServiceTestBase extends TestCase fService = (AVMService)fContext.getBean("AVMService"); fReaper = (OrphanReaper)fContext.getBean("orphanReaper"); fSyncService = (AVMSyncService)fContext.getBean("AVMSyncService"); + fIndexerAndSearcher = (IndexerAndSearcher)fContext.getBean("indexerAndSearcherFactory"); AuthenticationService authService = (AuthenticationService)fContext.getBean("AuthenticationService"); authService.authenticate("admin", "admin".toCharArray()); CreateStoreTxnListener cstl = (CreateStoreTxnListener)fContext.getBean("createStoreTxnListener"); @@ -215,17 +229,295 @@ public class AVMServiceTestBase extends TestCase fService.createDirectory("main:/", "d"); fService.createDirectory("main:/d", "e"); fService.createDirectory("main:/d/e", "f"); + fService.createFile("main:/a/b/c", "foo").close(); - PrintStream out = new PrintStream(fService.getFileOutputStream("main:/a/b/c/foo")); - out.println("I am main:/a/b/c/foo"); - out.flush(); - out.close(); + ContentWriter writer = fService.getContentWriter("main:/a/b/c/foo"); + writer.setEncoding("UTF-8"); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.putContent("I am main:/a/b/c/foo"); + fService.createFile("main:/a/b/c", "bar").close(); - out = new PrintStream(fService.getFileOutputStream("main:/a/b/c/bar")); - out.println("I am main:/a/b/c/bar"); - out.flush(); - out.close(); + writer = fService.getContentWriter("main:/a/b/c/bar"); + // Force a conversion + writer.setEncoding("UTF-16"); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.putContent("I am main:/a/b/c/bar"); + fService.createSnapshot("main", null, null); + + + runQueriesAgainstBasicTree("main"); + + } + + protected void runQueriesAgainstBasicTree(String store) + { + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + + // Text index + SearchService searchService = fIndexerAndSearcher.getSearcher(AVMNodeConverter.ToStoreRef(store), true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"I am main\""); + assertEquals(2, results.length()); + results.close(); + + // Basic properties + + // Note "a" is a stop word and therefore not findable ... + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_NAME)+":\"foo\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_NAME)+":foo"); + assertEquals(1, results.length()); + results.close(); + + // TODO: Fix auth in AVMDiskDriver and more?? + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_CREATOR)+":admin"); + + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_MODIFIER)+":admin"); + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_OWNER)+":admin"); + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_NODE_UUID)+":unknown"); + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_STORE_PROTOCOL)+":avm"); + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_STORE_IDENTIFIER)+":"+store); + assertEquals(9, results.length()); + results.close(); + + // Basic paths + + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/foo\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/bar\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(9, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); + assertEquals(8, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); + assertEquals(4, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); + } + + protected void runQueriesAgainstBasicTreeWithAOnly(String store) + { + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + + // Text index + SearchService searchService = fIndexerAndSearcher.getSearcher(AVMNodeConverter.ToStoreRef(store), true); + ResultSet results = searchService.query(storeRef, "lucene", "TEXT:\"I am main\""); + assertEquals(2, results.length()); + results.close(); + + // Basic properties + + // Note "a" is a stop word and therefore not findable ... + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_NAME)+":\"foo\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_NAME)+":foo"); + assertEquals(1, results.length()); + results.close(); + + // TODO: Fix auth in AVMDiskDriver and more?? + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_CREATOR)+":admin"); + if(results.length() == 10) + { + for (ResultSetRow row : results) + { + System.out.println(row.getNodeRef()); + } + } + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_MODIFIER)+":admin"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_OWNER)+":admin"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_NODE_UUID)+":unknown"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_STORE_PROTOCOL)+":avm"); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", LuceneQueryParser.escape("@"+ContentModel.PROP_STORE_IDENTIFIER)+":"+store); + assertEquals(6, results.length()); + results.close(); + + // Basic paths + + results = searchService.query(storeRef, "lucene", "PATH:\"/\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/foo\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/b/c/bar\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/d/e/f\""); + assertEquals(0, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); + assertEquals(6, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//*\""); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//.\""); + assertEquals(5, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a//*\""); + assertEquals(4, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/a/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"//c/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*\""); + assertEquals(1, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*\""); + assertEquals(2, results.length()); + results.close(); + + results = searchService.query(storeRef, "lucene", "PATH:\"/*/*/*/*/*\""); + assertEquals(0, results.length()); + results.close(); } /** diff --git a/source/java/org/alfresco/repo/copy/CrossRepositoryCopyServiceImpl.java b/source/java/org/alfresco/repo/copy/CrossRepositoryCopyServiceImpl.java index 481105d55b..4e4d7af674 100644 --- a/source/java/org/alfresco/repo/copy/CrossRepositoryCopyServiceImpl.java +++ b/source/java/org/alfresco/repo/copy/CrossRepositoryCopyServiceImpl.java @@ -15,13 +15,17 @@ import java.util.Set; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.repo.content.MimetypeMap; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.CopyService; import org.alfresco.service.cmr.repository.CrossRepositoryCopyService; import org.alfresco.service.cmr.repository.NodeRef; @@ -32,36 +36,36 @@ import org.alfresco.util.Pair; /** * Cross Repository Copying. + * * @author britt */ -public class CrossRepositoryCopyServiceImpl implements - CrossRepositoryCopyService +public class CrossRepositoryCopyServiceImpl implements CrossRepositoryCopyService { /** * The NodeService reference. */ private NodeService fNodeService; - + /** * The FileFolderService reference. */ private FileFolderService fFileFolderService; - + /** * The regular CopyService reference. */ private CopyService fCopyService; - + /** * The AVMService. */ private AVMService fAVMService; - + /** * The ContentService. */ private ContentService fContentService; - + /** * The DictionaryService. */ @@ -73,48 +77,51 @@ public class CrossRepositoryCopyServiceImpl implements public CrossRepositoryCopyServiceImpl() { } - + // Setters for Spring. - + public void setAvmService(AVMService service) { fAVMService = service; } - + public void setContentService(ContentService service) { fContentService = service; } - + public void setCopyService(CopyService service) { fCopyService = service; } - + public void setDictionaryService(DictionaryService service) { fDictionaryService = service; } - + public void setFileFolderService(FileFolderService service) { fFileFolderService = service; } - + public void setNodeService(NodeService service) { fNodeService = service; } - + /** - * This copies recursively src, which may be a container or a content type - * to dst, which must be a container. Copied nodes will have the copied from aspect - * applied to them. - * @param src The node to copy. - * @param dst The container to copy it into. - * @param name The name to give the copy. + * This copies recursively src, which may be a container or a content type to dst, which must be a container. Copied + * nodes will have the copied from aspect applied to them. + * + * @param src + * The node to copy. + * @param dst + * The container to copy it into. + * @param name + * The name to give the copy. */ - public void copy(NodeRef src, NodeRef dst, String name) + public void copy(NodeRef src, NodeRef dst, String name) { StoreRef srcStoreRef = src.getStoreRef(); StoreRef dstStoreRef = dst.getStoreRef(); @@ -141,26 +148,33 @@ public class CrossRepositoryCopyServiceImpl implements } } } - + /** * Handle copying from AVM to AVM - * @param src Source node. - * @param dst Destination directory node. - * @param name Name to give copy. + * + * @param src + * Source node. + * @param dst + * Destination directory node. + * @param name + * Name to give copy. */ private void copyAVMToAVM(NodeRef src, NodeRef dst, String name) { Pair srcStorePath = AVMNodeConverter.ToAVMVersionPath(src); Pair dstStorePath = AVMNodeConverter.ToAVMVersionPath(dst); - fAVMService.copy(srcStorePath.getFirst(), srcStorePath.getSecond(), - dstStorePath.getSecond(), name); + fAVMService.copy(srcStorePath.getFirst(), srcStorePath.getSecond(), dstStorePath.getSecond(), name); } - + /** * Handle copying from AVM to Repo. - * @param src Source node. - * @param dst Destination Container. - * @param name The name to give the copy. + * + * @param src + * Source node. + * @param dst + * Destination Container. + * @param name + * The name to give the copy. */ private void copyAVMToRepo(NodeRef src, NodeRef dst, String name) { @@ -171,7 +185,11 @@ public class CrossRepositoryCopyServiceImpl implements FileInfo newChild = fFileFolderService.create(dst, name, ContentModel.TYPE_CONTENT); NodeRef childRef = newChild.getNodeRef(); InputStream in = fAVMService.getFileInputStream(desc); - OutputStream out = fContentService.getWriter(childRef, ContentModel.PROP_CONTENT, true).getContentOutputStream(); + ContentData cd = fAVMService.getContentDataForRead(desc.getVersionID(), desc.getPath()); + ContentWriter writer = fContentService.getWriter(childRef, ContentModel.PROP_CONTENT, true); + writer.setEncoding(cd.getEncoding()); + writer.setMimetype(cd.getMimetype()); + OutputStream out = writer.getContentOutputStream(); copyData(in, out); copyPropsAndAspectsAVMToRepo(src, childRef); } @@ -188,11 +206,14 @@ public class CrossRepositoryCopyServiceImpl implements } } } - + /** * Helper that copies aspects and properties. - * @param src The source AVM node. - * @param dst The destination Repo node. + * + * @param src + * The source AVM node. + * @param dst + * The destination Repo node. */ private void copyPropsAndAspectsAVMToRepo(NodeRef src, NodeRef dst) { @@ -217,9 +238,13 @@ public class CrossRepositoryCopyServiceImpl implements /** * Handle copying from Repo to AVM. - * @param src The source node. - * @param dst The destingation directory. - * @param name The name to give the copy. + * + * @param src + * The source node. + * @param dst + * The destingation directory. + * @param name + * The name to give the copy. */ private void copyRepoToAVM(NodeRef src, NodeRef dst, String name) { @@ -229,8 +254,20 @@ public class CrossRepositoryCopyServiceImpl implements NodeRef childNodeRef = AVMNodeConverter.ToNodeRef(-1, childPath); if (fDictionaryService.isSubClass(srcType, ContentModel.TYPE_CONTENT)) { - InputStream in = fContentService.getReader(src, ContentModel.PROP_CONTENT).getContentInputStream(); - OutputStream out = fAVMService.createFile(versionPath.getSecond(), name); + ContentReader reader = fContentService.getReader(src, ContentModel.PROP_CONTENT); + InputStream in = reader.getContentInputStream(); + try + { + fAVMService.createFile(versionPath.getSecond(), name).close(); + } + catch (IOException e) + { + throw new AlfrescoRuntimeException("I/O Error.", e); + } + ContentWriter writer = fAVMService.getContentWriter(childPath); + writer.setEncoding(reader.getEncoding()); + writer.setMimetype(reader.getMimetype()); + OutputStream out = writer.getContentOutputStream(); copyData(in, out); copyPropsAndAspectsRepoToAVM(src, childNodeRef, childPath); return; @@ -247,12 +284,16 @@ public class CrossRepositoryCopyServiceImpl implements return; } } - + /** * Helper to copy properties and aspects. - * @param src The source node. - * @param dst The destination node. - * @param dstPath The destination AVM path. + * + * @param src + * The source node. + * @param dst + * The destination node. + * @param dstPath + * The destination AVM path. */ private void copyPropsAndAspectsRepoToAVM(NodeRef src, NodeRef dst, String dstPath) { @@ -269,24 +310,28 @@ public class CrossRepositoryCopyServiceImpl implements } fNodeService.setProperty(dst, ContentModel.PROP_COPY_REFERENCE, src); } - + /** * Handle copying from Repo to Repo. - * @param src The source node. - * @param dst The destination container. - * @param name The name to give the copy. + * + * @param src + * The source node. + * @param dst + * The destination container. + * @param name + * The name to give the copy. */ private void copyRepoToRepo(NodeRef src, NodeRef dst, String name) { ChildAssociationRef assocRef = fNodeService.getPrimaryParent(src); fCopyService.copyAndRename(src, dst, ContentModel.ASSOC_CONTAINS, assocRef.getQName(), true); } - + private void copyData(InputStream in, OutputStream out) { try { - byte [] buff = new byte[8192]; + byte[] buff = new byte[8192]; int read = 0; while ((read = in.read(buff)) != -1) { diff --git a/source/java/org/alfresco/repo/node/index/MissingContentReindexComponent.java b/source/java/org/alfresco/repo/node/index/MissingContentReindexComponent.java index c79bf84f10..956c9fddfc 100644 --- a/source/java/org/alfresco/repo/node/index/MissingContentReindexComponent.java +++ b/source/java/org/alfresco/repo/node/index/MissingContentReindexComponent.java @@ -26,7 +26,7 @@ package org.alfresco.repo.node.index; import java.util.List; -import org.alfresco.repo.search.impl.lucene.AbstractLuceneIndexerImpl2; +import org.alfresco.repo.search.impl.lucene.AbstractLuceneIndexerImpl; import org.alfresco.repo.transaction.TransactionUtil; import org.alfresco.repo.transaction.TransactionUtil.TransactionWork; import org.alfresco.service.cmr.repository.NodeRef; @@ -100,7 +100,7 @@ public class MissingContentReindexComponent extends AbstractReindexComponent // search for it in the index, sorting with youngest first sp.setLanguage(SearchService.LANGUAGE_LUCENE); - sp.setQuery("TEXT:" + AbstractLuceneIndexerImpl2.NOT_INDEXED_CONTENT_MISSING); + sp.setQuery("TEXT:" + AbstractLuceneIndexerImpl.NOT_INDEXED_CONTENT_MISSING); sp.addSort(SearchParameters.SORT_IN_DOCUMENT_ORDER_DESCENDING); ResultSet results = null; try diff --git a/source/java/org/alfresco/repo/node/index/MissingContentReindexComponentTest.java b/source/java/org/alfresco/repo/node/index/MissingContentReindexComponentTest.java index 2a681fd5e3..bde362534d 100644 --- a/source/java/org/alfresco/repo/node/index/MissingContentReindexComponentTest.java +++ b/source/java/org/alfresco/repo/node/index/MissingContentReindexComponentTest.java @@ -31,7 +31,7 @@ import org.alfresco.repo.content.AbstractContentStore; import org.alfresco.repo.content.ContentStore; import org.alfresco.repo.node.db.NodeDaoService; import org.alfresco.repo.search.Indexer; -import org.alfresco.repo.search.impl.lucene.AbstractLuceneIndexerImpl2; +import org.alfresco.repo.search.impl.lucene.AbstractLuceneIndexerImpl; import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer; import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.transaction.TransactionComponent; @@ -134,7 +134,7 @@ public class MissingContentReindexComponentTest extends TestCase SearchParameters sp = new SearchParameters(); sp.addStore(rootNodeRef.getStoreRef()); sp.setLanguage(SearchService.LANGUAGE_LUCENE); - sp.setQuery("TEXT:" + AbstractLuceneIndexerImpl2.NOT_INDEXED_CONTENT_MISSING); + sp.setQuery("TEXT:" + AbstractLuceneIndexerImpl.NOT_INDEXED_CONTENT_MISSING); sp.addSort(SearchParameters.SORT_IN_DOCUMENT_ORDER_DESCENDING); ResultSet results = null; try diff --git a/source/java/org/alfresco/repo/search/AVMSnapShotTriggeredIndexingMethodInterceptor.java b/source/java/org/alfresco/repo/search/AVMSnapShotTriggeredIndexingMethodInterceptor.java new file mode 100644 index 0000000000..b6b30f51aa --- /dev/null +++ b/source/java/org/alfresco/repo/search/AVMSnapShotTriggeredIndexingMethodInterceptor.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.search; + +import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.repo.search.impl.lucene.AVMLuceneIndexer; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; + +/** + * Method interceptor for atomic indexing of AVM entries + * + * @author andyh + * + */ +public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInterceptor +{ + private AVMService avmService; + + private IndexerAndSearcher indexerAndSearcher; + + public Object invoke(MethodInvocation mi) throws Throwable + { + if(mi.getMethod().getName().equals("createSnapshot")) + { + String store = (String)mi.getArguments()[0]; + int before = avmService.getLatestSnapshotID(store); + Object returnValue = mi.proceed(); + int after = avmService.getLatestSnapshotID(store); + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + Indexer indexer = indexerAndSearcher.getIndexer(storeRef); + if(indexer instanceof AVMLuceneIndexer) + { + AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer)indexer; + avmIndexer.index(store, before, after); + } + return returnValue; + } + // TODO: Purge store + else if(mi.getMethod().getName().equals("purgeStore")) + { + String store = (String)mi.getArguments()[0]; + Object returnValue = mi.proceed(); + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + Indexer indexer = indexerAndSearcher.getIndexer(storeRef); + if(indexer instanceof AVMLuceneIndexer) + { + AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer)indexer; + avmIndexer.deleteIndex(store); + } + return returnValue; + } + else if(mi.getMethod().getName().equals("createStore")) + { + String store = (String)mi.getArguments()[0]; + Object returnValue = mi.proceed(); + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + Indexer indexer = indexerAndSearcher.getIndexer(storeRef); + if(indexer instanceof AVMLuceneIndexer) + { + AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer)indexer; + avmIndexer.createIndex(store); + } + return returnValue; + } + else if(mi.getMethod().getName().equals("renameStore")) + { + String from = (String)mi.getArguments()[0]; + String to = (String)mi.getArguments()[1]; + Object returnValue = mi.proceed(); + int after = avmService.getLatestSnapshotID(to); + + StoreRef fromRef = AVMNodeConverter.ToStoreRef(from); + StoreRef toRef = AVMNodeConverter.ToStoreRef(to); + + Indexer indexer = indexerAndSearcher.getIndexer(fromRef); + if(indexer instanceof AVMLuceneIndexer) + { + AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer)indexer; + avmIndexer.deleteIndex(from); + } + + indexer = indexerAndSearcher.getIndexer(toRef); + if(indexer instanceof AVMLuceneIndexer) + { + AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer)indexer; + avmIndexer.createIndex(to); + avmIndexer.index(to, 0, after); + } + + return returnValue; + } + else + { + return mi.proceed(); + } + + } + + /** + * Set the AVM service + * @param avmService + */ + public void setAvmService(AVMService avmService) + { + this.avmService = avmService; + } + + /** + * Set the AVM indexer and searcher + * @param indexerAndSearcher + */ + public void setIndexerAndSearcher(IndexerAndSearcher indexerAndSearcher) + { + this.indexerAndSearcher = indexerAndSearcher; + } + +} diff --git a/source/java/org/alfresco/repo/search/IndexerSPI.java b/source/java/org/alfresco/repo/search/BackgroundIndexerAware.java similarity index 92% rename from source/java/org/alfresco/repo/search/IndexerSPI.java rename to source/java/org/alfresco/repo/search/BackgroundIndexerAware.java index 2f3ff65e63..f68e7457a9 100644 --- a/source/java/org/alfresco/repo/search/IndexerSPI.java +++ b/source/java/org/alfresco/repo/search/BackgroundIndexerAware.java @@ -30,9 +30,8 @@ import org.alfresco.repo.search.impl.lucene.fts.FTSIndexerAware; * Add support for FTS indexing * * @author andyh - * */ -public interface IndexerSPI extends Indexer +public interface BackgroundIndexerAware extends SupportsBackgroundIndexing { /** * Register call back handler when the indexing chunk is done @@ -49,4 +48,5 @@ public interface IndexerSPI extends Indexer */ public int updateFullTextSearch(int i); + } diff --git a/source/java/org/alfresco/repo/search/IndexerAndSearcher.java b/source/java/org/alfresco/repo/search/IndexerAndSearcher.java index 5d7b11c386..9befc1092c 100644 --- a/source/java/org/alfresco/repo/search/IndexerAndSearcher.java +++ b/source/java/org/alfresco/repo/search/IndexerAndSearcher.java @@ -42,7 +42,7 @@ public interface IndexerAndSearcher * @return * @throws IndexerException */ - public abstract IndexerSPI getIndexer(StoreRef storeRef) throws IndexerException; + public abstract Indexer getIndexer(StoreRef storeRef) throws IndexerException; /** * Get a searcher for a store diff --git a/source/java/org/alfresco/repo/search/SupportsBackgroundIndexing.java b/source/java/org/alfresco/repo/search/SupportsBackgroundIndexing.java new file mode 100644 index 0000000000..9c159e1526 --- /dev/null +++ b/source/java/org/alfresco/repo/search/SupportsBackgroundIndexing.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.search; + +import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer; + +/** + * Interface to support backgournd indexing updates + * + * @author andyh + * + */ +public interface SupportsBackgroundIndexing +{ + /** + * Set the back ground indexer manager + * + * @param fullTextSearchIndexer + */ + public void setFullTextSearchIndexer(FullTextSearchIndexer fullTextSearchIndexer); +} diff --git a/source/java/org/alfresco/repo/search/TransactionSynchronisationAwareIndexer.java b/source/java/org/alfresco/repo/search/TransactionSynchronisationAwareIndexer.java new file mode 100644 index 0000000000..2bd246672b --- /dev/null +++ b/source/java/org/alfresco/repo/search/TransactionSynchronisationAwareIndexer.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.search; + +/** + * Indexer implementations that work with spring transactions + * @author andyh + * + */ +public interface TransactionSynchronisationAwareIndexer +{ + /** + * Commit + */ + public void commit(); + /** + * Rollback + */ + public void rollback(); + /** + * Prepare + * @return the return tx state + */ + public int prepare(); + /** + * Report if there are any chenges to commit + * @return false if read only access (by use not declaration) + */ + public boolean isModified(); +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryTest2.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java similarity index 95% rename from source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryTest2.java rename to source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java index 687f902113..e85a4f43fd 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryTest2.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java @@ -59,7 +59,12 @@ import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.ApplicationContextHelper; import org.springframework.context.ApplicationContext; -public class LuceneCategoryTest2 extends TestCase +/** + * Category tests + * @author andyh + * + */ +public class ADMLuceneCategoryTest extends TestCase { private ServiceRegistry serviceRegistry; @@ -104,12 +109,20 @@ public class LuceneCategoryTest2 extends TestCase private CategoryService categoryService; - public LuceneCategoryTest2() + /** + * Simple test constructor + * + */ + public ADMLuceneCategoryTest() { super(); } - public LuceneCategoryTest2(String arg0) + /** + * Named test constructor + * @param arg0 + */ + public ADMLuceneCategoryTest(String arg0) { super(arg0); } @@ -121,7 +134,7 @@ public class LuceneCategoryTest2 extends TestCase luceneFTS = (FullTextSearchIndexer) ctx.getBean("LuceneFullTextSearchIndexer"); dictionaryDAO = (DictionaryDAO) ctx.getBean("dictionaryDAO"); searcher = (SearchService) ctx.getBean("searchService"); - indexerAndSearcher = (LuceneIndexerAndSearcher) ctx.getBean("luceneIndexerAndSearcherFactory"); + indexerAndSearcher = (LuceneIndexerAndSearcher) ctx.getBean("admLuceneIndexerAndSearcherFactory"); categoryService = (CategoryService) ctx.getBean("categoryService"); serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); @@ -310,11 +323,11 @@ public class LuceneCategoryTest2 extends TestCase private void buildBaseIndex() { - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_" + (new Random().nextInt()), indexerAndSearcher); + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_" + (new Random().nextInt()), indexerAndSearcher); indexer.setNodeService(nodeService); //indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); //indexer.clearIndex(); indexer.createNode(new ChildAssociationRef(null, null, null, rootNodeRef)); indexer.createNode(new ChildAssociationRef(ContentModel.ASSOC_CHILDREN, rootNodeRef, QName.createQName("{namespace}one"), n1)); @@ -348,7 +361,10 @@ public class LuceneCategoryTest2 extends TestCase indexer.commit(); } - + /** + * Test multiple categories + * @throws Exception + */ public void testMulti() throws Exception { TransactionService transactionService = serviceRegistry.getTransactionService(); @@ -356,7 +372,7 @@ public class LuceneCategoryTest2 extends TestCase tx.begin(); buildBaseIndex(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); @@ -370,6 +386,11 @@ public class LuceneCategoryTest2 extends TestCase tx.rollback(); } + /** + * Test basic categories. + * + * @throws Exception + */ public void testBasic() throws Exception { TransactionService transactionService = serviceRegistry.getTransactionService(); @@ -377,7 +398,7 @@ public class LuceneCategoryTest2 extends TestCase tx.begin(); buildBaseIndex(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); @@ -533,6 +554,11 @@ public class LuceneCategoryTest2 extends TestCase tx.rollback(); } + /** + * Test the catgeory service. + * + * @throws Exception + */ public void testCategoryServiceImpl() throws Exception { TransactionService transactionService = serviceRegistry.getTransactionService(); @@ -540,7 +566,7 @@ public class LuceneCategoryTest2 extends TestCase tx.begin(); buildBaseIndex(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); @@ -611,6 +637,10 @@ public class LuceneCategoryTest2 extends TestCase return nspr; } + /** + * + * @throws Exception + */ public void testCategoryService() throws Exception { TransactionService transactionService = serviceRegistry.getTransactionService(); @@ -665,6 +695,10 @@ public class LuceneCategoryTest2 extends TestCase tx.rollback(); } + /** + * + * @throws Exception + */ public void xtestManyCategories() throws Exception { TransactionService transactionService = serviceRegistry.getTransactionService(); @@ -718,6 +752,7 @@ public class LuceneCategoryTest2 extends TestCase NodeRef fiveRef = categoryService.createCategory(fourRef, "child_"+i+"_"+j+"_"+k+"_"+l+"_"+m+"_"+n+"_"+o); for(int p = 0; p < 5; p++) { + @SuppressWarnings("unused") NodeRef sixRef = categoryService.createCategory(fiveRef, "child_"+i+"_"+j+"_"+k+"_"+l+"_"+m+"_"+n+"_"+o+"_"+p); } } @@ -748,12 +783,14 @@ public class LuceneCategoryTest2 extends TestCase tx = transactionService.getUserTransaction(); tx.begin(); start = System.nanoTime(); + @SuppressWarnings("unused") ResultSet set = searcher.query(serviceRegistry.getPersonService().getPeopleContainer().getStoreRef(), "lucene", "@"+LuceneQueryParser.escape(ContentModel.ASPECT_GEN_CLASSIFIABLE.toString())+":second*"); System.out.println("Query complete in "+(System.nanoTime()-start)/1e9f); tx.commit(); } + @SuppressWarnings("unused") private int getTotalScore(ResultSet results) { int totalScore = 0; diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexer.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexer.java new file mode 100644 index 0000000000..7a247cc58d --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexer.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.search.impl.lucene; + +import org.alfresco.repo.search.BackgroundIndexerAware; + +/** + * ADM indexer implemtations + * + * @author andyh + * + */ +public interface ADMLuceneIndexer extends LuceneIndexer, BackgroundIndexerAware +{ + +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java new file mode 100644 index 0000000000..46d1afc2f2 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.search.impl.lucene; + +import java.util.List; + +import org.alfresco.repo.search.SearcherException; +import org.alfresco.repo.search.SupportsBackgroundIndexing; +import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.NamespaceService; + +/** + * Factory for ADM indxers and searchers + * @author andyh + * + */ +public class ADMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAndSearcherFactory implements SupportsBackgroundIndexing +{ + private DictionaryService dictionaryService; + + private NamespaceService nameSpaceService; + + private NodeService nodeService; + + private FullTextSearchIndexer fullTextSearchIndexer; + + private ContentService contentService; + + /** + * Set the dictinary service + * + * @param dictionaryService + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + /** + * Set the name space service + * @param nameSpaceService + */ + public void setNameSpaceService(NamespaceService nameSpaceService) + { + this.nameSpaceService = nameSpaceService; + } + + /** + * Set the node service + * @param nodeService + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setFullTextSearchIndexer(FullTextSearchIndexer fullTextSearchIndexer) + { + this.fullTextSearchIndexer = fullTextSearchIndexer; + } + + /** + * Set the content service + * @param contentService + */ + public void setContentService(ContentService contentService) + { + this.contentService = contentService; + } + + protected LuceneIndexer createIndexer(StoreRef storeRef, String deltaId) + { + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(storeRef, deltaId, this); + indexer.setNodeService(nodeService); + indexer.setDictionaryService(dictionaryService); + // indexer.setLuceneIndexLock(luceneIndexLock); + indexer.setFullTextSearchIndexer(fullTextSearchIndexer); + indexer.setContentService(contentService); + indexer.setMaxAtomicTransformationTime(getMaxTransformationTime()); + return indexer; + } + + protected LuceneSearcher getSearcher(StoreRef storeRef, LuceneIndexer indexer) throws SearcherException + { + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(storeRef, indexer, this); + searcher.setNamespacePrefixResolver(nameSpaceService); + // searcher.setLuceneIndexLock(luceneIndexLock); + searcher.setNodeService(nodeService); + searcher.setDictionaryService(dictionaryService); + searcher.setQueryRegister(getQueryRegister()); + return searcher; + } + + + protected List getAllStores() + { + return nodeService.getStores(); + } +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexerImpl2.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java similarity index 95% rename from source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexerImpl2.java rename to source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java index ed17ab57db..e26cc04814 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexerImpl2.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java @@ -33,7 +33,6 @@ import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; @@ -88,19 +87,19 @@ import org.apache.lucene.search.BooleanClause.Occur; * * @author andyh */ -public class LuceneIndexerImpl2 extends AbstractLuceneIndexerImpl2 implements LuceneIndexer2 +public class ADMLuceneIndexerImpl extends AbstractLuceneIndexerImpl implements ADMLuceneIndexer { - private static Logger s_logger = Logger.getLogger(LuceneIndexerImpl2.class); + static Logger s_logger = Logger.getLogger(ADMLuceneIndexerImpl.class); /** * The node service we use to get information about nodes */ - private NodeService nodeService; + NodeService nodeService; /** * Content service to get content for indexing. */ - private ContentService contentService; + ContentService contentService; /** * Call back to make after doing non atomic indexing @@ -120,7 +119,7 @@ public class LuceneIndexerImpl2 extends AbstractLuceneIndexerImpl2 impl /** * Default construction */ - LuceneIndexerImpl2() + ADMLuceneIndexerImpl() { super(); } @@ -339,14 +338,14 @@ public class LuceneIndexerImpl2 extends AbstractLuceneIndexerImpl2 impl * @return - the indexer instance * @throws LuceneIndexException */ - public static LuceneIndexerImpl2 getUpdateIndexer(StoreRef storeRef, String deltaId, LuceneConfig config) + public static ADMLuceneIndexerImpl getUpdateIndexer(StoreRef storeRef, String deltaId, LuceneConfig config) throws LuceneIndexException { if (s_logger.isDebugEnabled()) { s_logger.debug("Creating indexer"); } - LuceneIndexerImpl2 indexer = new LuceneIndexerImpl2(); + ADMLuceneIndexerImpl indexer = new ADMLuceneIndexerImpl(); indexer.setLuceneConfig(config); indexer.initialise(storeRef, deltaId); return indexer; @@ -484,17 +483,30 @@ public class LuceneIndexerImpl2 extends AbstractLuceneIndexerImpl2 impl private S second; + /** + * Helper class to hold two related objects + * @param first + * @param second + */ public Pair(F first, S second) { this.first = first; this.second = second; } + /** + * Get the first + * @return - first + */ public F getFirst() { return first; } + /** + * Get the second + * @return -second + */ public S getSecond() { return second; @@ -697,6 +709,299 @@ public class LuceneIndexerImpl2 extends AbstractLuceneIndexerImpl2 impl return docs; } + /** + * @param indexAtomicPropertiesOnly + * true to ignore all properties that must be indexed non-atomically + * @return Returns true if the property was indexed atomically, or false if it should be done asynchronously + */ + protected boolean indexProperty(NodeRef nodeRef, QName propertyName, Serializable value, Document doc, boolean indexAtomicPropertiesOnly) + { + String attributeName = "@" + + QName.createQName(propertyName.getNamespaceURI(), ISO9075.encode(propertyName.getLocalName())); + + boolean store = true; + boolean index = true; + boolean tokenise = true; + boolean atomic = true; + boolean isContent = false; + boolean isMultiLingual = false; + boolean isText = false; + + PropertyDefinition propertyDef = getDictionaryService().getProperty(propertyName); + if (propertyDef != null) + { + index = propertyDef.isIndexed(); + store = propertyDef.isStoredInIndex(); + tokenise = propertyDef.isTokenisedInIndex(); + atomic = propertyDef.isIndexedAtomically(); + isContent = propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT); + isMultiLingual = propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT); + isText = propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT); + } + if (value == null) + { + // the value is null + return true; + } + else if (indexAtomicPropertiesOnly && !atomic) + { + // we are only doing atomic properties and the property is definitely non-atomic + return false; + } + + if (!indexAtomicPropertiesOnly) + { + doc.removeFields(propertyName.toString()); + } + boolean wereAllAtomic = true; + // convert value to String + for (Serializable serializableValue : DefaultTypeConverter.INSTANCE.getCollection(Serializable.class, value)) + { + String strValue = null; + try + { + strValue = DefaultTypeConverter.INSTANCE.convert(String.class, serializableValue); + } + catch (TypeConversionException e) + { + doc.add(new Field(attributeName, NOT_INDEXED_NO_TYPE_CONVERSION, Field.Store.NO, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + continue; + } + if (strValue == null) + { + // nothing to index + continue; + } + + if (isContent) + { + ContentData contentData = DefaultTypeConverter.INSTANCE.convert(ContentData.class, serializableValue); + if (!index || contentData.getMimetype() == null) + { + // no mimetype or property not indexed + continue; + } + // store mimetype in index - even if content does not index it is useful + // Added szie and locale - size needs to be tokenised correctly + doc.add(new Field(attributeName + ".mimetype", contentData.getMimetype(), Field.Store.NO, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + doc.add(new Field(attributeName + ".size", Long.toString(contentData.getSize()), Field.Store.NO, + Field.Index.TOKENIZED, Field.TermVector.NO)); + + // TODO: Use the node locale in preferanced to the system locale + Locale locale = contentData.getLocale(); + if (locale == null) + { + Serializable localeProperty = nodeService.getProperty(nodeRef, ContentModel.PROP_LOCALE); + if (localeProperty != null) + { + locale = DefaultTypeConverter.INSTANCE.convert(Locale.class, localeProperty); + } + } + if (locale == null) + { + locale = Locale.getDefault(); + } + doc.add(new Field(attributeName + ".locale", locale.toString().toLowerCase(), Field.Store.NO, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + + ContentReader reader = contentService.getReader(nodeRef, propertyName); + if (reader != null && reader.exists()) + { + boolean readerReady = true; + // transform if necessary (it is not a UTF-8 text document) + if (!EqualsHelper.nullSafeEquals(reader.getMimetype(), MimetypeMap.MIMETYPE_TEXT_PLAIN) + || !EqualsHelper.nullSafeEquals(reader.getEncoding(), "UTF-8")) + { + // get the transformer + ContentTransformer transformer = contentService.getTransformer(reader.getMimetype(), + MimetypeMap.MIMETYPE_TEXT_PLAIN); + // is this transformer good enough? + if (transformer == null) + { + // log it + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Not indexed: No transformation: \n" + + " source: " + reader + "\n" + " target: " + + MimetypeMap.MIMETYPE_TEXT_PLAIN); + } + // don't index from the reader + readerReady = false; + // not indexed: no transformation + // doc.add(new Field("TEXT", NOT_INDEXED_NO_TRANSFORMATION, Field.Store.NO, + // Field.Index.TOKENIZED, Field.TermVector.NO)); + doc.add(new Field(attributeName, NOT_INDEXED_NO_TRANSFORMATION, Field.Store.NO, + Field.Index.TOKENIZED, Field.TermVector.NO)); + } + else if (indexAtomicPropertiesOnly + && transformer.getTransformationTime() > maxAtomicTransformationTime) + { + // only indexing atomic properties + // indexing will take too long, so push it to the background + wereAllAtomic = false; + } + else + { + // We have a transformer that is fast enough + ContentWriter writer = contentService.getTempWriter(); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + // this is what the analyzers expect on the stream + writer.setEncoding("UTF-8"); + try + { + + transformer.transform(reader, writer); + // point the reader to the new-written content + reader = writer.getReader(); + } + catch (ContentIOException e) + { + // log it + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Not indexed: Transformation failed", e); + } + // don't index from the reader + readerReady = false; + // not indexed: transformation + // failed + // doc.add(new Field("TEXT", NOT_INDEXED_TRANSFORMATION_FAILED, Field.Store.NO, + // Field.Index.TOKENIZED, Field.TermVector.NO)); + doc.add(new Field(attributeName, NOT_INDEXED_TRANSFORMATION_FAILED, Field.Store.NO, + Field.Index.TOKENIZED, Field.TermVector.NO)); + } + } + } + // add the text field using the stream from the + // reader, but only if the reader is valid + if (readerReady) + { + InputStreamReader isr = null; + // InputStream ris = reader.getContentInputStream(); + // try + // { + // isr = new InputStreamReader(ris, "UTF-8"); + // } + // catch (UnsupportedEncodingException e) + // { + // isr = new InputStreamReader(ris); + // } + // doc.add(new Field("TEXT", isr, Field.TermVector.NO)); + + InputStream ris = reader.getReader().getContentInputStream(); + try + { + isr = new InputStreamReader(ris, "UTF-8"); + } + catch (UnsupportedEncodingException e) + { + isr = new InputStreamReader(ris); + } + StringBuilder builder = new StringBuilder(); + builder.append("\u0000").append(locale.toString()).append("\u0000"); + StringReader prefix = new StringReader(builder.toString()); + Reader multiReader = new MultiReader(prefix, isr); + doc.add(new Field(attributeName, multiReader, Field.TermVector.NO)); + } + } + else + // URL not present (null reader) or no content at the URL (file missing) + { + // log it + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Not indexed: Content Missing \n" + + " node: " + nodeRef + "\n" + " reader: " + reader + "\n" + " content exists: " + + (reader == null ? " --- " : Boolean.toString(reader.exists()))); + } + // not indexed: content missing + doc.add(new Field("TEXT", NOT_INDEXED_CONTENT_MISSING, Field.Store.NO, Field.Index.TOKENIZED, + Field.TermVector.NO)); + doc.add(new Field(attributeName, NOT_INDEXED_CONTENT_MISSING, Field.Store.NO, + Field.Index.TOKENIZED, Field.TermVector.NO)); + } + } + else + { + Field.Store fieldStore = store ? Field.Store.YES : Field.Store.NO; + Field.Index fieldIndex; + + if (index) + { + if (tokenise) + { + fieldIndex = Field.Index.TOKENIZED; + } + else + { + fieldIndex = Field.Index.UN_TOKENIZED; + } + } + else + { + fieldIndex = Field.Index.NO; + } + + if ((fieldIndex != Field.Index.NO) || (fieldStore != Field.Store.NO)) + { + if (isMultiLingual) + { + MLText mlText = DefaultTypeConverter.INSTANCE.convert(MLText.class, serializableValue); + for (Locale locale : mlText.getLocales()) + { + String localeString = mlText.getValue(locale); + StringBuilder builder = new StringBuilder(); + builder.append("\u0000").append(locale.toString()).append("\u0000").append(localeString); + doc.add(new Field(attributeName, builder.toString(), fieldStore, fieldIndex, + Field.TermVector.NO)); + } + } + else if (isText) + { + // Temporary special case for uids and gids + if(propertyName.equals(ContentModel.PROP_USER_USERNAME) || propertyName.equals(ContentModel.PROP_USERNAME) || propertyName.equals(ContentModel.PROP_AUTHORITY_NAME)) + { + doc.add(new Field(attributeName, strValue, fieldStore, fieldIndex, Field.TermVector.NO)); + } + + // TODO: Use the node locale in preferanced to the system locale + Locale locale = null; + + Serializable localeProperty = nodeService.getProperty(nodeRef, ContentModel.PROP_LOCALE); + if (localeProperty != null) + { + locale = DefaultTypeConverter.INSTANCE.convert(Locale.class, localeProperty); + } + + if (locale == null) + { + locale = Locale.getDefault(); + } + if (tokenise) + { + StringBuilder builder = new StringBuilder(); + builder.append("\u0000").append(locale.toString()).append("\u0000").append(strValue); + doc.add(new Field(attributeName, builder.toString(), fieldStore, fieldIndex, + Field.TermVector.NO)); + } + else + { + doc.add(new Field(attributeName, strValue, fieldStore, fieldIndex, Field.TermVector.NO)); + } + } + else + { + doc.add(new Field(attributeName, strValue, fieldStore, fieldIndex, Field.TermVector.NO)); + } + } + } + } + + return wereAllAtomic; + } + /** * Does the node type or any applied aspect allow this node to have child associations? * @@ -755,300 +1060,6 @@ public class LuceneIndexerImpl2 extends AbstractLuceneIndexerImpl2 impl } } - /** - * @param indexAtomicPropertiesOnly - * true to ignore all properties that must be indexed non-atomically - * @return Returns true if the property was indexed atomically, or false if it should be done asynchronously - */ - private boolean indexProperty(NodeRef nodeRef, QName propertyName, Serializable value, Document doc, - boolean indexAtomicPropertiesOnly) - { - String attributeName = "@" - + QName.createQName(propertyName.getNamespaceURI(), ISO9075.encode(propertyName.getLocalName())); - - boolean store = true; - boolean index = true; - boolean tokenise = true; - boolean atomic = true; - boolean isContent = false; - boolean isMultiLingual = false; - boolean isText = false; - - PropertyDefinition propertyDef = getDictionaryService().getProperty(propertyName); - if (propertyDef != null) - { - index = propertyDef.isIndexed(); - store = propertyDef.isStoredInIndex(); - tokenise = propertyDef.isTokenisedInIndex(); - atomic = propertyDef.isIndexedAtomically(); - isContent = propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT); - isMultiLingual = propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT); - isText = propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT); - } - if (value == null) - { - // the value is null - return true; - } - else if (indexAtomicPropertiesOnly && !atomic) - { - // we are only doing atomic properties and the property is definitely non-atomic - return false; - } - - if (!indexAtomicPropertiesOnly) - { - doc.removeFields(propertyName.toString()); - } - boolean wereAllAtomic = true; - // convert value to String - for (Serializable serializableValue : DefaultTypeConverter.INSTANCE.getCollection(Serializable.class, value)) - { - String strValue = null; - try - { - strValue = DefaultTypeConverter.INSTANCE.convert(String.class, serializableValue); - } - catch (TypeConversionException e) - { - doc.add(new Field(attributeName, NOT_INDEXED_NO_TYPE_CONVERSION, Field.Store.NO, - Field.Index.UN_TOKENIZED, Field.TermVector.NO)); - continue; - } - if (strValue == null) - { - // nothing to index - continue; - } - - if (isContent) - { - ContentData contentData = DefaultTypeConverter.INSTANCE.convert(ContentData.class, serializableValue); - if (!index || contentData.getMimetype() == null) - { - // no mimetype or property not indexed - continue; - } - // store mimetype in index - even if content does not index it is useful - // Added szie and locale - size needs to be tokenised correctly - doc.add(new Field(attributeName + ".mimetype", contentData.getMimetype(), Field.Store.NO, - Field.Index.UN_TOKENIZED, Field.TermVector.NO)); - doc.add(new Field(attributeName + ".size", Long.toString(contentData.getSize()), Field.Store.NO, - Field.Index.TOKENIZED, Field.TermVector.NO)); - - // TODO: Use the node locale in preferanced to the system locale - Locale locale = contentData.getLocale(); - if (locale == null) - { - Serializable localeProperty = nodeService.getProperty(nodeRef, ContentModel.PROP_LOCALE); - if (localeProperty != null) - { - locale = DefaultTypeConverter.INSTANCE.convert(Locale.class, localeProperty); - } - } - if (locale == null) - { - locale = Locale.getDefault(); - } - doc.add(new Field(attributeName + ".locale", locale.toString().toLowerCase(), Field.Store.NO, - Field.Index.UN_TOKENIZED, Field.TermVector.NO)); - - ContentReader reader = contentService.getReader(nodeRef, propertyName); - if (reader != null && reader.exists()) - { - boolean readerReady = true; - // transform if necessary (it is not a UTF-8 text document) - if (!EqualsHelper.nullSafeEquals(reader.getMimetype(), MimetypeMap.MIMETYPE_TEXT_PLAIN) - || !EqualsHelper.nullSafeEquals(reader.getEncoding(), "UTF-8")) - { - // get the transformer - ContentTransformer transformer = contentService.getTransformer(reader.getMimetype(), - MimetypeMap.MIMETYPE_TEXT_PLAIN); - // is this transformer good enough? - if (transformer == null) - { - // log it - if (s_logger.isDebugEnabled()) - { - s_logger.debug("Not indexed: No transformation: \n" - + " source: " + reader + "\n" + " target: " - + MimetypeMap.MIMETYPE_TEXT_PLAIN); - } - // don't index from the reader - readerReady = false; - // not indexed: no transformation - // doc.add(new Field("TEXT", NOT_INDEXED_NO_TRANSFORMATION, Field.Store.NO, - // Field.Index.TOKENIZED, Field.TermVector.NO)); - doc.add(new Field(attributeName, NOT_INDEXED_NO_TRANSFORMATION, Field.Store.NO, - Field.Index.TOKENIZED, Field.TermVector.NO)); - } - else if (indexAtomicPropertiesOnly - && transformer.getTransformationTime() > maxAtomicTransformationTime) - { - // only indexing atomic properties - // indexing will take too long, so push it to the background - wereAllAtomic = false; - } - else - { - // We have a transformer that is fast enough - ContentWriter writer = contentService.getTempWriter(); - writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); - // this is what the analyzers expect on the stream - writer.setEncoding("UTF-8"); - try - { - - transformer.transform(reader, writer); - // point the reader to the new-written content - reader = writer.getReader(); - } - catch (ContentIOException e) - { - // log it - if (s_logger.isDebugEnabled()) - { - s_logger.debug("Not indexed: Transformation failed", e); - } - // don't index from the reader - readerReady = false; - // not indexed: transformation - // failed - // doc.add(new Field("TEXT", NOT_INDEXED_TRANSFORMATION_FAILED, Field.Store.NO, - // Field.Index.TOKENIZED, Field.TermVector.NO)); - doc.add(new Field(attributeName, NOT_INDEXED_TRANSFORMATION_FAILED, Field.Store.NO, - Field.Index.TOKENIZED, Field.TermVector.NO)); - } - } - } - // add the text field using the stream from the - // reader, but only if the reader is valid - if (readerReady) - { - InputStreamReader isr = null; - // InputStream ris = reader.getContentInputStream(); - // try - // { - // isr = new InputStreamReader(ris, "UTF-8"); - // } - // catch (UnsupportedEncodingException e) - // { - // isr = new InputStreamReader(ris); - // } - // doc.add(new Field("TEXT", isr, Field.TermVector.NO)); - - InputStream ris = reader.getReader().getContentInputStream(); - try - { - isr = new InputStreamReader(ris, "UTF-8"); - } - catch (UnsupportedEncodingException e) - { - isr = new InputStreamReader(ris); - } - StringBuilder builder = new StringBuilder(); - builder.append("\u0000").append(locale.toString()).append("\u0000"); - StringReader prefix = new StringReader(builder.toString()); - Reader multiReader = new MultiReader(prefix, isr); - doc.add(new Field(attributeName, multiReader, Field.TermVector.NO)); - } - } - else - // URL not present (null reader) or no content at the URL (file missing) - { - // log it - if (s_logger.isDebugEnabled()) - { - s_logger.debug("Not indexed: Content Missing \n" - + " node: " + nodeRef + "\n" + " reader: " + reader + "\n" + " content exists: " - + (reader == null ? " --- " : Boolean.toString(reader.exists()))); - } - // not indexed: content missing - doc.add(new Field("TEXT", NOT_INDEXED_CONTENT_MISSING, Field.Store.NO, Field.Index.TOKENIZED, - Field.TermVector.NO)); - doc.add(new Field(attributeName, NOT_INDEXED_CONTENT_MISSING, Field.Store.NO, - Field.Index.TOKENIZED, Field.TermVector.NO)); - } - } - else - { - Field.Store fieldStore = store ? Field.Store.YES : Field.Store.NO; - Field.Index fieldIndex; - - if (index) - { - if (tokenise) - { - fieldIndex = Field.Index.TOKENIZED; - } - else - { - fieldIndex = Field.Index.UN_TOKENIZED; - } - } - else - { - fieldIndex = Field.Index.NO; - } - - if ((fieldIndex != Field.Index.NO) || (fieldStore != Field.Store.NO)) - { - if (isMultiLingual) - { - MLText mlText = DefaultTypeConverter.INSTANCE.convert(MLText.class, serializableValue); - for (Locale locale : mlText.getLocales()) - { - String localeString = mlText.getValue(locale); - StringBuilder builder = new StringBuilder(); - builder.append("\u0000").append(locale.toString()).append("\u0000").append(localeString); - doc.add(new Field(attributeName, builder.toString(), fieldStore, fieldIndex, - Field.TermVector.NO)); - } - } - else if (isText) - { - // Temporary special case for uids and gids - if(propertyName.equals(ContentModel.PROP_USER_USERNAME) || propertyName.equals(ContentModel.PROP_USERNAME) || propertyName.equals(ContentModel.PROP_AUTHORITY_NAME)) - { - doc.add(new Field(attributeName, strValue, fieldStore, fieldIndex, Field.TermVector.NO)); - } - - // TODO: Use the node locale in preferanced to the system locale - Locale locale = null; - - Serializable localeProperty = nodeService.getProperty(nodeRef, ContentModel.PROP_LOCALE); - if (localeProperty != null) - { - locale = DefaultTypeConverter.INSTANCE.convert(Locale.class, localeProperty); - } - - if (locale == null) - { - locale = Locale.getDefault(); - } - if (tokenise) - { - StringBuilder builder = new StringBuilder(); - builder.append("\u0000").append(locale.toString()).append("\u0000").append(strValue); - doc.add(new Field(attributeName, builder.toString(), fieldStore, fieldIndex, - Field.TermVector.NO)); - } - else - { - doc.add(new Field(attributeName, strValue, fieldStore, fieldIndex, Field.TermVector.NO)); - } - } - else - { - doc.add(new Field(attributeName, strValue, fieldStore, fieldIndex, Field.TermVector.NO)); - } - } - } - } - - return wereAllAtomic; - } - private Map getNodeCounts(NodeRef nodeRef) { Map nodeCounts = new HashMap(5); @@ -1348,23 +1359,13 @@ public class LuceneIndexerImpl2 extends AbstractLuceneIndexerImpl2 impl } } - FullTextSearchIndexer luceneFullTextSearchIndexer; + FullTextSearchIndexer fullTextSearchIndexer; - public void setLuceneFullTextSearchIndexer(FullTextSearchIndexer luceneFullTextSearchIndexer) + public void setFullTextSearchIndexer(FullTextSearchIndexer fullTextSearchIndexer) { - this.luceneFullTextSearchIndexer = luceneFullTextSearchIndexer; + this.fullTextSearchIndexer = fullTextSearchIndexer; } - public boolean getDeleteOnlyNodes() - { - return indexUpdateStatus == IndexUpdateStatus.ASYNCHRONOUS; - } - - public Set getDeletions() - { - return Collections.unmodifiableSet(deletions); - } - protected void doPrepare() throws IOException { saveDelta(); @@ -1382,7 +1383,7 @@ public class LuceneIndexerImpl2 extends AbstractLuceneIndexerImpl2 impl else { setInfo(docs, getDeletions(), false); - luceneFullTextSearchIndexer.requiresIndex(store); + fullTextSearchIndexer.requiresIndex(store); } if (callBack != null) { diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcherImpl2.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java similarity index 95% rename from source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcherImpl2.java rename to source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java index 3038f5469a..be338b1ef2 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcherImpl2.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java @@ -36,7 +36,6 @@ import java.util.Set; import org.alfresco.repo.search.CannedQueryDef; import org.alfresco.repo.search.EmptyResultSet; -import org.alfresco.repo.search.Indexer; import org.alfresco.repo.search.QueryRegisterComponent; import org.alfresco.repo.search.SearcherException; import org.alfresco.repo.search.impl.NodeSearcher; @@ -75,7 +74,7 @@ import com.werken.saxpath.XPathReader; * * @author andyh */ -public class LuceneSearcherImpl2 extends LuceneBase2 implements LuceneSearcher2 +public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneSearcher { /** @@ -91,7 +90,7 @@ public class LuceneSearcherImpl2 extends LuceneBase2 implements LuceneSearcher2 private QueryRegisterComponent queryRegister; - private LuceneIndexer2 indexer; + private LuceneIndexer indexer; /* * Searcher implementation @@ -101,12 +100,13 @@ public class LuceneSearcherImpl2 extends LuceneBase2 implements LuceneSearcher2 * Get an initialised searcher for the store and transaction Normally we do not search against a a store and delta. Currently only gets the searcher against the main index. * * @param storeRef - * @param deltaId - * @return + * @param indexer + * @param config + * @return - the searcher implementation */ - public static LuceneSearcherImpl2 getSearcher(StoreRef storeRef, LuceneIndexer2 indexer, LuceneConfig config) + public static ADMLuceneSearcherImpl getSearcher(StoreRef storeRef, LuceneIndexer indexer, LuceneConfig config) { - LuceneSearcherImpl2 searcher = new LuceneSearcherImpl2(); + ADMLuceneSearcherImpl searcher = new ADMLuceneSearcherImpl(); searcher.setLuceneConfig(config); try { @@ -124,9 +124,10 @@ public class LuceneSearcherImpl2 extends LuceneBase2 implements LuceneSearcher2 * Get an intialised searcher for the store. No transactional ammendsmends are searched. * * @param storeRef - * @return + * @param config + * @return the searcher */ - public static LuceneSearcherImpl2 getSearcher(StoreRef storeRef, LuceneConfig config) + public static ADMLuceneSearcherImpl getSearcher(StoreRef storeRef, LuceneConfig config) { return getSearcher(storeRef, null, config); } @@ -152,6 +153,10 @@ public class LuceneSearcherImpl2 extends LuceneBase2 implements LuceneSearcher2 this.dictionaryService = dictionaryService; } + /** + * Set the query register + * @param queryRegister + */ public void setQueryRegister(QueryRegisterComponent queryRegister) { this.queryRegister = queryRegister; @@ -608,8 +613,6 @@ public class LuceneSearcherImpl2 extends LuceneBase2 implements LuceneSearcher2 /** * @return Returns true if the pattern is present, otherwise false. - * @see #setIndexer(Indexer) - * @see #setSearcher(SearchService) */ public boolean like(NodeRef nodeRef, QName propertyQName, String sqlLikePattern, boolean includeFTS) { diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneTest2.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java similarity index 94% rename from source/java/org/alfresco/repo/search/impl/lucene/LuceneTest2.java rename to source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java index 907db0061c..087a96ec24 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneTest2.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java @@ -95,7 +95,7 @@ import org.springframework.context.ApplicationContext; * @author andyh */ @SuppressWarnings("unused") -public class LuceneTest2 extends TestCase +public class ADMLuceneTest extends TestCase { private static final String TEST_NAMESPACE = "http://www.alfresco.org/test/lucenetest"; @@ -104,7 +104,7 @@ public class LuceneTest2 extends TestCase private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(); - private static Log logger = LogFactory.getLog(LuceneTest2.class); + private static Log logger = LogFactory.getLog(ADMLuceneTest.class); QName createdDate = QName.createQName(TEST_NAMESPACE, "createdDate"); @@ -184,7 +184,10 @@ public class LuceneTest2 extends TestCase private NamespaceDAOImpl namespaceDao; - public LuceneTest2() + /** + * + */ + public ADMLuceneTest() { super(); } @@ -198,8 +201,8 @@ public class LuceneTest2 extends TestCase contentService = (ContentService) ctx.getBean("contentService"); queryRegisterComponent = (QueryRegisterComponent) ctx.getBean("queryRegisterComponent"); namespacePrefixResolver = (DictionaryNamespaceComponent) ctx.getBean("namespaceService"); - indexerAndSearcher = (LuceneIndexerAndSearcher) ctx.getBean("luceneIndexerAndSearcherFactory"); - ((LuceneIndexerAndSearcherFactory2)indexerAndSearcher).setMaxAtomicTransformationTime(1000000); + indexerAndSearcher = (LuceneIndexerAndSearcher) ctx.getBean("admLuceneIndexerAndSearcherFactory"); + ((AbstractLuceneIndexerAndSearcherFactory)indexerAndSearcher).setMaxAtomicTransformationTime(1000000); transactionService = (TransactionService) ctx.getBean("transactionComponent"); serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); @@ -412,6 +415,9 @@ public class LuceneTest2 extends TestCase private int orderIntCount = -45764576; + /** + * @return properties + */ public Map getOrderProperties() { Map testProperties = new HashMap(); @@ -440,11 +446,17 @@ public class LuceneTest2 extends TestCase super.tearDown(); } - public LuceneTest2(String arg0) + /** + * @param arg0 + */ + public ADMLuceneTest(String arg0) { super(arg0); } + /** + * @throws Exception + */ public void testAuxDataIsPresent() throws Exception { luceneFTS.pause(); @@ -454,7 +466,7 @@ public class LuceneTest2 extends TestCase testTX.begin(); runBaseTests(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -468,7 +480,7 @@ public class LuceneTest2 extends TestCase testTX = transactionService.getUserTransaction(); testTX.begin(); - searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -477,11 +489,17 @@ public class LuceneTest2 extends TestCase results.close(); } + /** + * @throws Exception + */ public void testFirst() throws Exception { testReadAgainstDelta(); } + /** + * @throws Exception + */ public void test0() throws Exception { luceneFTS.pause(); @@ -491,6 +509,9 @@ public class LuceneTest2 extends TestCase } + /** + * @throws Exception + */ public void testDeleteSecondaryAssocToContainer() throws Exception { luceneFTS.pause(); @@ -506,7 +527,7 @@ public class LuceneTest2 extends TestCase testTX = transactionService.getUserTransaction(); testTX.begin(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -740,6 +761,9 @@ public class LuceneTest2 extends TestCase } + /** + * @throws Exception + */ public void testDeleteSecondaryAssocToLeaf() throws Exception { luceneFTS.pause(); @@ -755,7 +779,7 @@ public class LuceneTest2 extends TestCase testTX = transactionService.getUserTransaction(); testTX.begin(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -979,6 +1003,9 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void testDeleteIssue() throws Exception { @@ -990,7 +1017,7 @@ public class LuceneTest2 extends TestCase .createQName("{namespace}testFind"), testSuperType); testTX.commit(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -1028,6 +1055,9 @@ public class LuceneTest2 extends TestCase tx3.commit(); } + /** + * @throws Exception + */ public void testMTDeleteIssue() throws Exception { luceneFTS.pause(); @@ -1041,7 +1071,7 @@ public class LuceneTest2 extends TestCase testTX = transactionService.getUserTransaction(); testTX.begin(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -1144,6 +1174,9 @@ public class LuceneTest2 extends TestCase } + /** + * @throws Exception + */ public void testDeltaIssue() throws Exception { luceneFTS.pause(); @@ -1274,13 +1307,16 @@ public class LuceneTest2 extends TestCase } + /** + * @throws Exception + */ public void testRepeatPerformance() throws Exception { luceneFTS.pause(); buildBaseIndex(); runBaseTests(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -1317,13 +1353,16 @@ public class LuceneTest2 extends TestCase } } + /** + * @throws Exception + */ public void testSort() throws Exception { luceneFTS.pause(); buildBaseIndex(); runBaseTests(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -1666,6 +1705,9 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void test1() throws Exception { luceneFTS.pause(); @@ -1674,6 +1716,9 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void test2() throws Exception { luceneFTS.pause(); @@ -1682,6 +1727,9 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void test3() throws Exception { luceneFTS.pause(); @@ -1690,12 +1738,15 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void test4() throws Exception { luceneFTS.pause(); buildBaseIndex(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setDictionaryService(dictionaryService); ResultSet results = searcher.query(rootNodeRef.getStoreRef(), "lucene", @@ -1704,6 +1755,9 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void test5() throws Exception { luceneFTS.pause(); @@ -1712,6 +1766,9 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void test6() throws Exception { luceneFTS.pause(); @@ -1720,16 +1777,19 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void testNoOp() throws Exception { luceneFTS.pause(); - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_1", indexerAndSearcher); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); indexer.prepare(); @@ -1739,6 +1799,7 @@ public class LuceneTest2 extends TestCase /** * Test basic index and search + * @throws Exception * * @throws InterruptedException */ @@ -1746,14 +1807,14 @@ public class LuceneTest2 extends TestCase public void testStandAloneIndexerCommit() throws Exception { luceneFTS.pause(); - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_1", indexerAndSearcher); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); // //indexer.clearIndex(); @@ -1770,7 +1831,7 @@ public class LuceneTest2 extends TestCase indexer.prepare(); indexer.commit(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -1887,12 +1948,15 @@ public class LuceneTest2 extends TestCase } } + /** + * @throws Exception + */ public void testStandAlonePathIndexer() throws Exception { luceneFTS.pause(); buildBaseIndex(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); @@ -1939,13 +2003,13 @@ public class LuceneTest2 extends TestCase private void buildBaseIndex() { - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_" + (new Random().nextInt()), indexerAndSearcher); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); // indexer.clearIndex(); indexer.createNode(new ChildAssociationRef(null, null, null, rootNodeRef)); @@ -1975,6 +2039,9 @@ public class LuceneTest2 extends TestCase indexer.commit(); } + /** + * @throws Exception + */ public void testAllPathSearch() throws Exception { luceneFTS.pause(); @@ -1986,7 +2053,7 @@ public class LuceneTest2 extends TestCase private void runBaseTests() { - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -3133,12 +3200,15 @@ public class LuceneTest2 extends TestCase } + /** + * @throws Exception + */ public void testPathSearch() throws Exception { luceneFTS.pause(); buildBaseIndex(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -3185,12 +3255,15 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void testXPathSearch() throws Exception { luceneFTS.pause(); buildBaseIndex(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -3212,11 +3285,14 @@ public class LuceneTest2 extends TestCase results.close(); } + /** + * @throws Exception + */ public void testMissingIndex() throws Exception { luceneFTS.pause(); StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "_missing_"); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(storeRef, indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(storeRef, indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -3230,6 +3306,9 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void testUpdateIndex() throws Exception { luceneFTS.pause(); @@ -3237,13 +3316,13 @@ public class LuceneTest2 extends TestCase runBaseTests(); - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); indexer.updateNode(rootNodeRef); @@ -3268,6 +3347,9 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void testDeleteLeaf() throws Exception { testTX.commit(); @@ -3292,7 +3374,7 @@ public class LuceneTest2 extends TestCase testTX = transactionService.getUserTransaction(); testTX.begin(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -3507,6 +3589,9 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void testAddEscapedChild() throws Exception { String COMPLEX_LOCAL_NAME = "\u0020\u0060\u00ac\u00a6\u0021\"\u00a3\u0024\u0025\u005e\u0026\u002a\u0028\u0029\u002d\u005f\u003d\u002b\t\n\\\u0000\u005b\u005d\u007b\u007d\u003b\u0027\u0023\u003a\u0040\u007e\u002c\u002e\u002f\u003c\u003e\u003f\\u007c\u005f\u0078\u0054\u0036\u0035\u0041\u005f"; @@ -3516,13 +3601,13 @@ public class LuceneTest2 extends TestCase buildBaseIndex(); runBaseTests(); - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); ChildAssociationRef car = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, QName @@ -3531,7 +3616,7 @@ public class LuceneTest2 extends TestCase indexer.commit(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -3541,6 +3626,9 @@ public class LuceneTest2 extends TestCase results.close(); } + /** + * @throws Exception + */ public void testNumericInPath() throws Exception { String COMPLEX_LOCAL_NAME = "Woof12"; @@ -3549,13 +3637,13 @@ public class LuceneTest2 extends TestCase buildBaseIndex(); runBaseTests(); - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); ChildAssociationRef car = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, QName @@ -3564,7 +3652,7 @@ public class LuceneTest2 extends TestCase indexer.commit(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -3574,6 +3662,9 @@ public class LuceneTest2 extends TestCase results.close(); } + /** + * @throws Exception + */ public void testDeleteContainer() throws Exception { testTX.commit(); @@ -3584,12 +3675,12 @@ public class LuceneTest2 extends TestCase runBaseTests(); testTX.commit(); - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); testTX = transactionService.getUserTransaction(); @@ -3604,7 +3695,7 @@ public class LuceneTest2 extends TestCase testTX = transactionService.getUserTransaction(); testTX.begin(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -3822,19 +3913,22 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void testDeleteAndAddReference() throws Exception { luceneFTS.pause(); buildBaseIndex(); runBaseTests(); - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); nodeService.removeChild(n2, n13); @@ -3843,7 +3937,7 @@ public class LuceneTest2 extends TestCase indexer.commit(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); @@ -4072,13 +4166,13 @@ public class LuceneTest2 extends TestCase assertEquals(1, results.length()); results.close(); - indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), + indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); nodeService.addChild(n2, n13, ASSOC_TYPE_QNAME, QName.createQName("{namespace}link")); @@ -4091,13 +4185,16 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void testRenameReference() throws Exception { luceneFTS.pause(); buildBaseIndex(); runBaseTests(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -4117,13 +4214,13 @@ public class LuceneTest2 extends TestCase assertEquals(0, results.length()); results.close(); - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis(), indexerAndSearcher); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); nodeService.removeChild(n2, n13); @@ -4137,7 +4234,7 @@ public class LuceneTest2 extends TestCase runBaseTests(); - searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); searcher.setDictionaryService(dictionaryService); @@ -4156,13 +4253,16 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void testDelayIndex() throws Exception { luceneFTS.pause(); buildBaseIndex(); runBaseTests(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); @@ -4187,19 +4287,19 @@ public class LuceneTest2 extends TestCase // Do index - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_" + (new Random().nextInt()), indexerAndSearcher); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); indexer.updateFullTextSearch(1000); indexer.prepare(); indexer.commit(); - searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); searcher.setDictionaryService(dictionaryService); @@ -4225,13 +4325,16 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void testWaitForIndex() throws Exception { luceneFTS.pause(); buildBaseIndex(); runBaseTests(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -4256,7 +4359,7 @@ public class LuceneTest2 extends TestCase // Do index - searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -4267,13 +4370,13 @@ public class LuceneTest2 extends TestCase assertEquals(1, results.length()); results.close(); - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_" + (new Random().nextInt()), indexerAndSearcher); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); indexer.updateFullTextSearch(1000); indexer.prepare(); @@ -4307,13 +4410,16 @@ public class LuceneTest2 extends TestCase return LuceneQueryParser.escape(qname.toString()); } + /** + * @throws Exception + */ public void testForKev() throws Exception { luceneFTS.pause(); buildBaseIndex(); runBaseTests(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); @@ -4338,6 +4444,9 @@ public class LuceneTest2 extends TestCase luceneFTS.resume(); } + /** + * @throws Exception + */ public void testIssueAR47() throws Exception { // This bug arose from repeated deletes and adds creating empty index @@ -4357,7 +4466,7 @@ public class LuceneTest2 extends TestCase .createQName("{namespace}testFind"), testSuperType); tx.commit(); - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); searcher.setNodeService(nodeService); searcher.setDictionaryService(dictionaryService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); @@ -4389,6 +4498,9 @@ public class LuceneTest2 extends TestCase tx3.commit(); } + /** + * @throws Exception + */ public void testReadAgainstDelta() throws Exception { testTX.commit(); @@ -4641,13 +4753,13 @@ public class LuceneTest2 extends TestCase private void runPerformanceTest(double time, boolean clear) { - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + ADMLuceneIndexerImpl indexer = ADMLuceneIndexerImpl.getUpdateIndexer(rootNodeRef.getStoreRef(), "delta" + System.currentTimeMillis() + "_" + (new Random().nextInt()), indexerAndSearcher); indexer.setMaxAtomicTransformationTime(1000000); indexer.setNodeService(nodeService); // indexer.setLuceneIndexLock(luceneIndexLock); indexer.setDictionaryService(dictionaryService); - indexer.setLuceneFullTextSearchIndexer(luceneFTS); + indexer.setFullTextSearchIndexer(luceneFTS); indexer.setContentService(contentService); if (clear) { @@ -4692,9 +4804,13 @@ public class LuceneTest2 extends TestCase return nspr; } + /** + * @param args + * @throws Exception + */ public static void main(String[] args) throws Exception { - LuceneTest2 test = new LuceneTest2(); + ADMLuceneTest test = new ADMLuceneTest(); test.setUp(); // test.testForKev(); // test.testDeleteContainer(); @@ -4715,6 +4831,10 @@ public class LuceneTest2 extends TestCase // test.dictionaryService.getType(test.nodeService.getType(test.rootNodeRef)).getDefaultAspects(); } + /** + * @author andyh + * + */ public static class UnknownDataType implements Serializable { diff --git a/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexer.java b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexer.java new file mode 100644 index 0000000000..b123deb44e --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexer.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.search.impl.lucene; + +/** + * AVM specific indxer support + * + * @author andyh + * + */ +public interface AVMLuceneIndexer extends LuceneIndexer +{ + /** + * Index a specified change to a store between two snapshots + * + * @param store - the name of the store + * @param srcVersion - the id of the snapshot before the changeset + * @param dstVersion - the id of the snapshot created by the change set + */ + public void index(String store, int srcVersion, int dstVersion); + + /** + * Delete the index for the specified store. + * + * @param store + */ + public void deleteIndex(String store); + + /** + * Create an index for the specified store. + * This makes sure that the root node for the store is indexed correctly. + * + * @param store + */ + public void createIndex(String store); +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerAndSearcherFactory.java b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerAndSearcherFactory.java new file mode 100644 index 0000000000..a06c8b2600 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerAndSearcherFactory.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.search.impl.lucene; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.repo.content.ContentStore; +import org.alfresco.repo.search.SearcherException; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avm.AVMStoreDescriptor; +import org.alfresco.service.cmr.avmsync.AVMSyncService; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.NamespaceService; + +/** + * Factory for AVM indexers and searchers + * + * @author andyh + * + */ +public class AVMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAndSearcherFactory +{ + private DictionaryService dictionaryService; + + private NamespaceService nameSpaceService; + + private ContentService contentService; + + private AVMService avmService; + + private AVMSyncService avmSyncService; + + private NodeService nodeService; + + private ContentStore contentStore; + + /** + * Set the dictionary service + * @param dictionaryService + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + /** + * Set the name space service + * @param nameSpaceService + */ + public void setNameSpaceService(NamespaceService nameSpaceService) + { + this.nameSpaceService = nameSpaceService; + } + + /** + * Set the content service + * @param contentService + */ + public void setContentService(ContentService contentService) + { + this.contentService = contentService; + } + + /** + * Set the AVM service + * @param avmService + */ + public void setAvmService(AVMService avmService) + { + this.avmService = avmService; + } + + /** + * Set the AVM sync service + * @param avmSyncService + */ + public void setAvmSyncService(AVMSyncService avmSyncService) + { + this.avmSyncService = avmSyncService; + } + + /** + * Set the node service + * @param nodeService + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + + + /** + * Set the content service + * @param contentStore + */ + public void setContentStore(ContentStore contentStore) + { + this.contentStore = contentStore; + } + + @Override + protected LuceneIndexer createIndexer(StoreRef storeRef, String deltaId) + { + AVMLuceneIndexerImpl indexer = AVMLuceneIndexerImpl.getUpdateIndexer(storeRef, deltaId, this); + indexer.setDictionaryService(dictionaryService); + indexer.setContentService(contentService); + indexer.setMaxAtomicTransformationTime(getMaxTransformationTime()); + indexer.setAvmService(avmService); + indexer.setAvmSyncService(avmSyncService); + indexer.setContentStore(contentStore); + return indexer; + } + + @Override + protected List getAllStores() + { + List stores = avmService.getStores(); + List storeRefs = new ArrayList(stores.size()); + for(AVMStoreDescriptor storeDesc : stores) + { + StoreRef storeRef = AVMNodeConverter.ToStoreRef(storeDesc.getName()); + storeRefs.add(storeRef); + } + return storeRefs; + } + + @Override + protected LuceneSearcher getSearcher(StoreRef storeRef, LuceneIndexer indexer) throws SearcherException + { + //TODO: Store overlays + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(storeRef, indexer, this); + searcher.setNamespacePrefixResolver(nameSpaceService); + // searcher.setLuceneIndexLock(luceneIndexLock); + searcher.setNodeService(nodeService); + searcher.setDictionaryService(dictionaryService); + searcher.setQueryRegister(getQueryRegister()); + return searcher; + } + +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerImpl.java new file mode 100644 index 0000000000..ff39346545 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerImpl.java @@ -0,0 +1,1016 @@ +/** + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.search.impl.lucene; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.Serializable; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.alfresco.model.ContentModel; +import org.alfresco.model.WCMModel; +import org.alfresco.repo.avm.AVMDAOs; +import org.alfresco.repo.avm.AVMNode; +import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.repo.avm.util.SimplePath; +import org.alfresco.repo.content.ContentStore; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.content.transform.ContentTransformer; +import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.repo.transaction.AlfrescoTransactionSupport; +import org.alfresco.service.cmr.avm.AVMException; +import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avmsync.AVMDifference; +import org.alfresco.service.cmr.avmsync.AVMSyncService; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentIOException; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.MLText; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.cmr.repository.datatype.TypeConversionException; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.EqualsHelper; +import org.alfresco.util.ISO9075; +import org.alfresco.util.Pair; +import org.apache.log4j.Logger; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; + +/** + * Update the index after a snap shot to an AVM store. (Revert is dealt with as a new snap shot is created) + * + * @author andyh + */ +public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl implements AVMLuceneIndexer +{ + static Logger s_logger = Logger.getLogger(AVMLuceneIndexerImpl.class); + + private AVMService avmService; + + private AVMSyncService avmSyncService; + + @SuppressWarnings("unused") + private ContentStore contentStore; + + private ContentService contentService; + + @SuppressWarnings("unused") + private int srcVersion = -1; + + private int dstVersion = -1; + + private Set indexedPaths = new HashSet(); + + /** + * Set the AVM Service + * @param avmService + */ + public void setAvmService(AVMService avmService) + { + this.avmService = avmService; + } + + /** + * Set the AVM sync service + * @param avmSyncService + */ + public void setAvmSyncService(AVMSyncService avmSyncService) + { + this.avmSyncService = avmSyncService; + } + + /** + * Set the content service + * @param contentStore + */ + public void setContentStore(ContentStore contentStore) + { + this.contentStore = contentStore; + } + + /** + * @param contentService + */ + public void setContentService(ContentService contentService) + { + this.contentService = contentService; + } + + /** + * Generate an indexer + * + * @param storeRef + * @param deltaId + * @param config + * @return - the indexer instance + * @throws LuceneIndexException + */ + public static AVMLuceneIndexerImpl getUpdateIndexer(StoreRef storeRef, String deltaId, LuceneConfig config) + throws LuceneIndexException + { + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Creating indexer"); + } + AVMLuceneIndexerImpl indexer = new AVMLuceneIndexerImpl(); + indexer.setLuceneConfig(config); + indexer.initialise(storeRef, deltaId); + return indexer; + } + + /** + * Index a specified change to a store + * + * @param store + * @param srcVersion + * @param dstVersion + */ + public void index(String store, int srcVersion, int dstVersion) + { + checkAbleToDoWork(IndexUpdateStatus.SYNCRONOUS); + this.srcVersion = srcVersion; + this.dstVersion = dstVersion; + + String path = store + ":/"; + List changeList = avmSyncService.compare(srcVersion, path, dstVersion, path, null); + for (AVMDifference difference : changeList) + { + switch (difference.getDifferenceCode()) + { + case AVMDifference.CONFLICT: + case AVMDifference.NEWER: + case AVMDifference.OLDER: + AVMNodeDescriptor srcDesc = avmService.lookup(difference.getSourceVersion(), + difference.getSourcePath(), true); + AVMNodeDescriptor dstDesc = avmService.lookup(difference.getDestinationVersion(), difference + .getDestinationPath(), true); + // New + if (srcDesc == null) + { + index(difference.getDestinationPath()); + if (dstDesc.isDirectory()) + { + indexDirectory(dstDesc); + } + } + // New Delete + else if (!srcDesc.isDeleted() && ((dstDesc == null) || dstDesc.isDeleted())) + { + delete(difference.getSourcePath()); + delete(difference.getDestinationPath()); + } + // Existing delete + else if (srcDesc.isDeleted() && dstDesc.isDeleted()) + { + // Nothing to do for this case + } + // Anything else then we reindex + else + { + // TODO: Check hen to rebuild aux paths + // Should only reindex if the path has changed - not anything on a directory + reindex(difference.getSourcePath(), srcDesc.isDirectory()); + reindex(difference.getDestinationPath(), dstDesc.isDirectory()); + } + break; + case AVMDifference.DIRECTORY: + // Never seen + break; + case AVMDifference.SAME: + // No action + break; + + } + } + } + + private void indexDirectory(AVMNodeDescriptor dir) + { + Map children = avmService.getDirectoryListing(dir); + for (AVMNodeDescriptor child : children.values()) + { + index(child.getPath()); + if (child.isDirectory()) + { + indexDirectory(child); + } + } + + } + + @Override + protected List createDocuments(String stringNodeRef, boolean isNew, boolean indexAllProperties, + boolean includeDirectoryDocuments) + { + AVMNodeDescriptor desc = avmService.lookup(dstVersion, stringNodeRef); + List docs = new ArrayList(); + if(desc == null) + { + return docs; + } + + List> paths = avmService.getHeadPaths(desc); + if(paths.size() == 0) + { + return docs; + } + for (Pair path : paths) + { + if(indexedPaths.contains(path.getSecond())) + { + return docs; + } + } + for (Pair path : paths) + { + indexedPaths.add(path.getSecond()); + } + + AVMNode node = AVMDAOs.Instance().fAVMNodeDAO.getByID(desc.getId()); + + + if (paths.size() > 0) + { + if (desc != null) + { + + NodeRef nodeRef = AVMNodeConverter.ToNodeRef(dstVersion, stringNodeRef); + + Document xdoc = new Document(); + xdoc.add(new Field("ID", nodeRef.toString(), Field.Store.YES, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + for (Pair path : paths) + { + + String[] splitPath = splitPath(path.getSecond()); + @SuppressWarnings("unused") + String pathInStore = splitPath[1]; + xdoc.add(new Field("ID", path.getSecond(), + Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + } + + + xdoc.add(new Field("TX", AlfrescoTransactionSupport.getTransactionId(), Field.Store.YES, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + + boolean isAtomic = true; + + Map properties = getIndexableProperties(desc, node, nodeRef, dstVersion, stringNodeRef); + for (QName propertyName : properties.keySet()) + { + Serializable value = properties.get(propertyName); + if (indexAllProperties) + { + indexProperty(node, nodeRef, propertyName, value, xdoc, false); + } + else + { + isAtomic &= indexProperty(node, nodeRef, propertyName, value, xdoc, true); + } + } + + StringBuilder qNameBuffer = new StringBuilder(64); + + for (Pair path : paths) + { + + if (node.getIsRoot()) + { + + } + // pseudo roots? + else + { + String[] splitPath = splitPath(path.getSecond()); + String store = splitPath[0]; + String pathInStore = splitPath[1]; + SimplePath simplePath = new SimplePath(pathInStore); + + StringBuilder xpathBuilder = new StringBuilder(); + for(int i = 0; i < simplePath.size(); i++) + { + xpathBuilder.append("/{}").append(simplePath.get(i)); + } + String xpath = xpathBuilder.toString(); + + if (qNameBuffer.length() > 0) + { + qNameBuffer.append(";/"); + } + // Get the parent + + ArrayList ancestors = new ArrayList(); + + StringBuilder pathBuilder = new StringBuilder(); + pathBuilder.append(store).append(":/"); + ancestors.add(pathBuilder.toString()); + boolean requiresSep = false; + for (int i = 0; i < simplePath.size() - 1; i++) + { + if(requiresSep) + { + pathBuilder.append("/"); + } + else + { + requiresSep = true; + } + pathBuilder.append(simplePath.get(i)); + ancestors.add(pathBuilder.toString()); + } + + qNameBuffer.append(ISO9075.getXPathName(QName.createQName("", simplePath + .get(simplePath.size() - 1)))); + xdoc.add(new Field("PARENT", + ancestors.get(ancestors.size() - 1), Field.Store.YES, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + // TODO: Categories and LINKASPECT + + if (includeDirectoryDocuments) + { + if (desc.isDirectory()) + { + // TODO: Exclude category paths + + Document directoryEntry = new Document(); + directoryEntry.add(new Field("ID", nodeRef.toString(), Field.Store.YES, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + + directoryEntry.add(new Field("ID", path.getSecond(), + Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + + + directoryEntry.add(new Field("PATH", xpath, Field.Store.YES, + Field.Index.TOKENIZED, Field.TermVector.NO)); + + // Find all parent nodes. + + for (String toAdd : ancestors) + { + directoryEntry.add(new Field("ANCESTOR", toAdd, + Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + } + directoryEntry.add(new Field("ISCONTAINER", "T", Field.Store.YES, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + + docs.add(directoryEntry); + + } + } + } + + } + + if (node.getIsRoot()) + { + // TODO: Does the root element have a QName? + xdoc.add(new Field("ISCONTAINER", "T", Field.Store.YES, Field.Index.UN_TOKENIZED, + Field.TermVector.NO)); + xdoc.add(new Field("PATH", "", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO)); + xdoc.add(new Field("QNAME", "", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO)); + xdoc.add(new Field("ISROOT", "T", Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + xdoc.add(new Field("ISNODE", "T", Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + docs.add(xdoc); + + } + else + // not a root node + { + xdoc.add(new Field("QNAME", qNameBuffer.toString(), Field.Store.YES, Field.Index.TOKENIZED, + Field.TermVector.NO)); + + QName typeQName = getType(desc); + + xdoc.add(new Field("TYPE", ISO9075.getXPathName(typeQName), Field.Store.YES, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + + for (QName classRef : avmService.getAspects(dstVersion, stringNodeRef)) + { + xdoc.add(new Field("ASPECT", ISO9075.getXPathName(classRef), Field.Store.YES, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + } + + xdoc.add(new Field("ISROOT", "F", Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + xdoc.add(new Field("ISNODE", "T", Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + + docs.add(xdoc); + } + } + } + else + { + boolean root = node.getIsRoot(); + boolean deleted = desc.isDeleted(); + System.out.println("Is Root " + root); + System.out.println("Is deleted " + deleted); + } + return docs; + } + + private String[] splitPath(String path) + { + String[] pathParts = path.split(":"); + if (pathParts.length != 2) + { + throw new AVMException("Invalid path: " + path); + } + return pathParts; + } + + private QName getType(AVMNodeDescriptor desc) + { + if (desc.isPlainDirectory()) + { + return WCMModel.TYPE_AVM_PLAIN_FOLDER; + } + else if (desc.isPlainFile()) + { + return WCMModel.TYPE_AVM_PLAIN_CONTENT; + } + else if (desc.isLayeredDirectory()) + { + return WCMModel.TYPE_AVM_LAYERED_FOLDER; + } + else + { + return WCMModel.TYPE_AVM_LAYERED_CONTENT; + } + } + + private Map getIndexableProperties(AVMNodeDescriptor desc, AVMNode node, NodeRef nodeRef, + Integer version, String path) + { + Map properties = node.getProperties(); + + Map result = new HashMap(); + for (QName qName : properties.keySet()) + { + PropertyValue value = properties.get(qName); + PropertyDefinition def = getDictionaryService().getProperty(qName); + result.put(qName, makeSerializableValue(def, value)); + } + // Now spoof properties that are built in. + result.put(ContentModel.PROP_CREATED, new Date(desc.getCreateDate())); + result.put(ContentModel.PROP_CREATOR, desc.getCreator()); + result.put(ContentModel.PROP_MODIFIED, new Date(desc.getModDate())); + result.put(ContentModel.PROP_MODIFIER, desc.getLastModifier()); + result.put(ContentModel.PROP_OWNER, desc.getOwner()); + result.put(ContentModel.PROP_NAME, desc.getName()); + result.put(ContentModel.PROP_NODE_UUID, "UNKNOWN"); + result.put(ContentModel.PROP_NODE_DBID, new Long(desc.getId())); + result.put(ContentModel.PROP_STORE_PROTOCOL, "avm"); + result.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier()); + if (desc.isLayeredDirectory()) + { + result.put(WCMModel.PROP_AVM_DIR_INDIRECTION, AVMNodeConverter.ToNodeRef(-1, desc.getIndirection())); + } + if (desc.isLayeredFile()) + { + result.put(WCMModel.PROP_AVM_FILE_INDIRECTION, AVMNodeConverter.ToNodeRef(-1, desc.getIndirection())); + } + if (desc.isFile()) + { + try + { + ContentData contentData = avmService.getContentDataForRead(version, path); + result.put(ContentModel.PROP_CONTENT, contentData); + } + catch (AVMException e) + { + // TODO For now ignore. + } + } + return result; + + } + + protected Serializable makeSerializableValue(PropertyDefinition propertyDef, PropertyValue propertyValue) + { + if (propertyValue == null) + { + return null; + } + // get property attributes + QName propertyTypeQName = null; + if (propertyDef == null) + { + // allow this for now + propertyTypeQName = DataTypeDefinition.ANY; + } + else + { + propertyTypeQName = propertyDef.getDataType().getName(); + } + try + { + Serializable value = propertyValue.getValue(propertyTypeQName); + // done + return value; + } + catch (TypeConversionException e) + { + throw new TypeConversionException( + "The property value is not compatible with the type defined for the property: \n" + + " property: " + (propertyDef == null ? "unknown" : propertyDef) + "\n" + + " property value: " + propertyValue, e); + } + } + + protected boolean indexProperty(AVMNode node, NodeRef banana, QName propertyName, Serializable value, Document doc, + boolean indexAtomicPropertiesOnly) + { + String attributeName = "@" + + QName.createQName(propertyName.getNamespaceURI(), ISO9075.encode(propertyName.getLocalName())); + + boolean store = true; + boolean index = true; + boolean tokenise = true; + @SuppressWarnings("unused") + boolean atomic = true; + boolean isContent = false; + boolean isMultiLingual = false; + boolean isText = false; + + PropertyDefinition propertyDef = getDictionaryService().getProperty(propertyName); + if (propertyDef != null) + { + index = propertyDef.isIndexed(); + store = propertyDef.isStoredInIndex(); + tokenise = propertyDef.isTokenisedInIndex(); + atomic = propertyDef.isIndexedAtomically(); + isContent = propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT); + isMultiLingual = propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT); + isText = propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT); + } + if (value == null) + { + // the value is null + return true; + } + // else if (indexAtomicPropertiesOnly && !atomic) + // { + // we are only doing atomic properties and the property is definitely non-atomic + // return false; + // } + + if (!indexAtomicPropertiesOnly) + { + doc.removeFields(propertyName.toString()); + } + // boolean wereAllAtomic = true; + // convert value to String + for (Serializable serializableValue : DefaultTypeConverter.INSTANCE.getCollection(Serializable.class, value)) + { + String strValue = null; + try + { + strValue = DefaultTypeConverter.INSTANCE.convert(String.class, serializableValue); + } + catch (TypeConversionException e) + { + doc.add(new Field(attributeName, NOT_INDEXED_NO_TYPE_CONVERSION, Field.Store.NO, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + continue; + } + if (strValue == null) + { + // nothing to index + continue; + } + + if (isContent) + { + ContentData contentData = DefaultTypeConverter.INSTANCE.convert(ContentData.class, serializableValue); + if (!index || contentData.getMimetype() == null) + { + // no mimetype or property not indexed + continue; + } + // store mimetype in index - even if content does not index it is useful + // Added szie and locale - size needs to be tokenised correctly + doc.add(new Field(attributeName + ".mimetype", contentData.getMimetype(), Field.Store.NO, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + doc.add(new Field(attributeName + ".size", Long.toString(contentData.getSize()), Field.Store.NO, + Field.Index.TOKENIZED, Field.TermVector.NO)); + + // TODO: Use the node locale in preferanced to the system locale + Locale locale = contentData.getLocale(); + // No default locale in AVM + if (locale == null) + { + locale = Locale.getDefault(); + } + doc.add(new Field(attributeName + ".locale", locale.toString().toLowerCase(), Field.Store.NO, + Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + + ContentReader reader = contentService.getReader(banana, propertyName); + if (reader != null && reader.exists()) + { + boolean readerReady = true; + // transform if necessary (it is not a UTF-8 text document) + if (!EqualsHelper.nullSafeEquals(reader.getMimetype(), MimetypeMap.MIMETYPE_TEXT_PLAIN) + || !EqualsHelper.nullSafeEquals(reader.getEncoding(), "UTF-8")) + { + // get the transformer + ContentTransformer transformer = contentService.getTransformer(reader.getMimetype(), + MimetypeMap.MIMETYPE_TEXT_PLAIN); + // is this transformer good enough? + if (transformer == null) + { + // log it + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Not indexed: No transformation: \n" + + " source: " + reader + "\n" + " target: " + + MimetypeMap.MIMETYPE_TEXT_PLAIN); + } + // don't index from the reader + readerReady = false; + // not indexed: no transformation + // doc.add(new Field("TEXT", NOT_INDEXED_NO_TRANSFORMATION, Field.Store.NO, + // Field.Index.TOKENIZED, Field.TermVector.NO)); + doc.add(new Field(attributeName, NOT_INDEXED_NO_TRANSFORMATION, Field.Store.NO, + Field.Index.TOKENIZED, Field.TermVector.NO)); + } + // else if (indexAtomicPropertiesOnly + // && transformer.getTransformationTime() > maxAtomicTransformationTime) + // { + // only indexing atomic properties + // indexing will take too long, so push it to the background + // wereAllAtomic = false; + // } + else + { + // We have a transformer that is fast enough + ContentWriter writer = contentService.getTempWriter(); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + // this is what the analyzers expect on the stream + writer.setEncoding("UTF-8"); + try + { + + transformer.transform(reader, writer); + // point the reader to the new-written content + reader = writer.getReader(); + } + catch (ContentIOException e) + { + // log it + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Not indexed: Transformation failed", e); + } + // don't index from the reader + readerReady = false; + // not indexed: transformation + // failed + // doc.add(new Field("TEXT", NOT_INDEXED_TRANSFORMATION_FAILED, Field.Store.NO, + // Field.Index.TOKENIZED, Field.TermVector.NO)); + doc.add(new Field(attributeName, NOT_INDEXED_TRANSFORMATION_FAILED, Field.Store.NO, + Field.Index.TOKENIZED, Field.TermVector.NO)); + } + } + } + // add the text field using the stream from the + // reader, but only if the reader is valid + if (readerReady) + { + InputStreamReader isr = null; + InputStream ris = reader.getReader().getContentInputStream(); + try + { + isr = new InputStreamReader(ris, "UTF-8"); + } + catch (UnsupportedEncodingException e) + { + isr = new InputStreamReader(ris); + } + StringBuilder builder = new StringBuilder(); + builder.append("\u0000").append(locale.toString()).append("\u0000"); + StringReader prefix = new StringReader(builder.toString()); + Reader multiReader = new MultiReader(prefix, isr); + doc.add(new Field(attributeName, multiReader, Field.TermVector.NO)); + } + } + else + // URL not present (null reader) or no content at the URL (file missing) + { + // log it + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Not indexed: Content Missing \n" + + " node: " + banana + "\n" + " reader: " + reader + "\n" + " content exists: " + + (reader == null ? " --- " : Boolean.toString(reader.exists()))); + } + // not indexed: content missing + doc.add(new Field("TEXT", NOT_INDEXED_CONTENT_MISSING, Field.Store.NO, Field.Index.TOKENIZED, + Field.TermVector.NO)); + doc.add(new Field(attributeName, NOT_INDEXED_CONTENT_MISSING, Field.Store.NO, + Field.Index.TOKENIZED, Field.TermVector.NO)); + } + } + else + { + Field.Store fieldStore = store ? Field.Store.YES : Field.Store.NO; + Field.Index fieldIndex; + + if (index) + { + if (tokenise) + { + fieldIndex = Field.Index.TOKENIZED; + } + else + { + fieldIndex = Field.Index.UN_TOKENIZED; + } + } + else + { + fieldIndex = Field.Index.NO; + } + + if ((fieldIndex != Field.Index.NO) || (fieldStore != Field.Store.NO)) + { + if (isMultiLingual) + { + MLText mlText = DefaultTypeConverter.INSTANCE.convert(MLText.class, serializableValue); + for (Locale locale : mlText.getLocales()) + { + String localeString = mlText.getValue(locale); + StringBuilder builder = new StringBuilder(); + builder.append("\u0000").append(locale.toString()).append("\u0000").append(localeString); + doc.add(new Field(attributeName, builder.toString(), fieldStore, fieldIndex, + Field.TermVector.NO)); + } + } + else if (isText) + { + // Temporary special case for uids and gids + if (propertyName.equals(ContentModel.PROP_USER_USERNAME) + || propertyName.equals(ContentModel.PROP_USERNAME) + || propertyName.equals(ContentModel.PROP_AUTHORITY_NAME)) + { + doc.add(new Field(attributeName, strValue, fieldStore, fieldIndex, Field.TermVector.NO)); + } + + // TODO: Use the node locale in preferanced to the system locale + Locale locale = null; + + Serializable localeProperty = node.getProperty(ContentModel.PROP_LOCALE); + if (localeProperty != null) + { + locale = DefaultTypeConverter.INSTANCE.convert(Locale.class, localeProperty); + } + + if (locale == null) + { + locale = Locale.getDefault(); + } + if (tokenise) + { + StringBuilder builder = new StringBuilder(); + builder.append("\u0000").append(locale.toString()).append("\u0000").append(strValue); + doc.add(new Field(attributeName, builder.toString(), fieldStore, fieldIndex, + Field.TermVector.NO)); + } + else + { + doc.add(new Field(attributeName, strValue, fieldStore, fieldIndex, Field.TermVector.NO)); + } + } + else + { + doc.add(new Field(attributeName, strValue, fieldStore, fieldIndex, Field.TermVector.NO)); + } + } + } + } + + // return wereAllAtomic; + return true; + } + + @Override + protected void doPrepare() throws IOException + { + saveDelta(); + flushPending(); + } + + @Override + protected void doCommit() throws IOException + { + setInfo(docs, deletions, false); + } + + @Override + protected void doRollBack() throws IOException + { + + } + + @Override + protected void doSetRollbackOnly() throws IOException + { + + } + + // The standard indexer API - although implemented it is not likely to be used at the moment + // Batch indexing makes more sense for AVM at snaphot time + + public void createNode(ChildAssociationRef relationshipRef) + { + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Create node " + relationshipRef.getChildRef()); + } + checkAbleToDoWork(IndexUpdateStatus.SYNCRONOUS); + try + { + NodeRef childRef = relationshipRef.getChildRef(); + Pair versionPath = AVMNodeConverter.ToAVMVersionPath(childRef); + index(versionPath.getSecond()); + // TODO: Deal with a create on the root node deleting the index. + } + catch (LuceneIndexException e) + { + setRollbackOnly(); + throw new LuceneIndexException("Create node failed", e); + } + } + + public void updateNode(NodeRef nodeRef) + { + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Update node " + nodeRef); + } + checkAbleToDoWork(IndexUpdateStatus.SYNCRONOUS); + try + { + Pair versionPath = AVMNodeConverter.ToAVMVersionPath(nodeRef); + reindex(versionPath.getSecond(), false); + } + catch (LuceneIndexException e) + { + setRollbackOnly(); + throw new LuceneIndexException("Update node failed", e); + } + } + + public void deleteNode(ChildAssociationRef relationshipRef) + { + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Delete node " + relationshipRef.getChildRef()); + } + checkAbleToDoWork(IndexUpdateStatus.SYNCRONOUS); + try + { + NodeRef childRef = relationshipRef.getChildRef(); + Pair versionPath = AVMNodeConverter.ToAVMVersionPath(childRef); + reindex(versionPath.getSecond(), true); + } + catch (LuceneIndexException e) + { + setRollbackOnly(); + throw new LuceneIndexException("Delete node failed", e); + } + } + + public void createChildRelationship(ChildAssociationRef relationshipRef) + { + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Create child " + relationshipRef); + } + checkAbleToDoWork(IndexUpdateStatus.SYNCRONOUS); + try + { + NodeRef childRef = relationshipRef.getChildRef(); + Pair versionPath = AVMNodeConverter.ToAVMVersionPath(childRef); + reindex(versionPath.getSecond(), true); + } + catch (LuceneIndexException e) + { + setRollbackOnly(); + throw new LuceneIndexException("Failed to create child relationship", e); + } + } + + public void updateChildRelationship(ChildAssociationRef relationshipBeforeRef, + ChildAssociationRef relationshipAfterRef) + { + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Update child " + relationshipBeforeRef + " to " + relationshipAfterRef); + } + checkAbleToDoWork(IndexUpdateStatus.SYNCRONOUS); + try + { + NodeRef childRef = relationshipBeforeRef.getChildRef(); + Pair versionPath = AVMNodeConverter.ToAVMVersionPath(childRef); + reindex(versionPath.getSecond(), true); + } + catch (LuceneIndexException e) + { + setRollbackOnly(); + throw new LuceneIndexException("Failed to update child relationship", e); + } + } + + public void deleteChildRelationship(ChildAssociationRef relationshipRef) + { + + if (s_logger.isDebugEnabled()) + { + s_logger.debug("Delete child " + relationshipRef); + } + checkAbleToDoWork(IndexUpdateStatus.SYNCRONOUS); + try + { + NodeRef childRef = relationshipRef.getChildRef(); + Pair versionPath = AVMNodeConverter.ToAVMVersionPath(childRef); + reindex(versionPath.getSecond(), true); + } + catch (LuceneIndexException e) + { + setRollbackOnly(); + throw new LuceneIndexException("Failed to delete child relationship", e); + } + + } + + public void deleteIndex(String store) + { + checkAbleToDoWork(IndexUpdateStatus.SYNCRONOUS); + try + { + deleteAll(); + } + catch (LuceneIndexException e) + { + setRollbackOnly(); + throw new LuceneIndexException("Delete index failed", e); + } + + } + + public void createIndex(String store) + { + checkAbleToDoWork(IndexUpdateStatus.SYNCRONOUS); + try + { + @SuppressWarnings("unused") + AVMNodeDescriptor rootDesc = avmService.getStoreRoot(-1, store); + index(store+":/"); + } + catch (LuceneIndexException e) + { + setRollbackOnly(); + throw new LuceneIndexException("Create index failed", e); + } + } +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneBase2.java b/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneBase.java similarity index 86% rename from source/java/org/alfresco/repo/search/impl/lucene/LuceneBase2.java rename to source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneBase.java index 3f25e1964f..ecb0bd0c05 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneBase2.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneBase.java @@ -33,7 +33,6 @@ import org.alfresco.repo.search.impl.lucene.index.IndexInfo; import org.alfresco.repo.search.impl.lucene.index.TransactionStatus; import org.alfresco.repo.search.impl.lucene.index.IndexInfo.LockWork; import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.StoreRef; import org.apache.log4j.Logger; import org.apache.lucene.index.IndexReader; @@ -64,9 +63,9 @@ import org.apache.lucene.search.IndexSearcher; * */ -public abstract class LuceneBase2 +public abstract class AbstractLuceneBase { - private static Logger s_logger = Logger.getLogger(LuceneBase2.class); + private static Logger s_logger = Logger.getLogger(AbstractLuceneBase.class); private IndexInfo indexInfo; @@ -115,13 +114,12 @@ public abstract class LuceneBase2 { throw new IndexerException("Filed to set delta as active"); } - } /** * Utility method to find the path to the base index * - * @return + * @return - the base path */ private String getBasePath() { @@ -137,7 +135,7 @@ public abstract class LuceneBase2 /** * Get a searcher for the main index TODO: Split out support for the main index. We really only need this if we want to search over the changing index before it is committed * - * @return + * @return - the searcher * @throws IOException */ @@ -154,7 +152,7 @@ public abstract class LuceneBase2 } } - protected ClosingIndexSearcher getSearcher(LuceneIndexer2 luceneIndexer) throws LuceneIndexException + protected ClosingIndexSearcher getSearcher(LuceneIndexer luceneIndexer) throws LuceneIndexException { // If we know the delta id we should do better @@ -185,7 +183,7 @@ public abstract class LuceneBase2 /** * Get a reader for the on file portion of the delta * - * @return + * @return - the index reader * @throws IOException * @throws IOException */ @@ -211,7 +209,7 @@ public abstract class LuceneBase2 /** * Get the on file writer for the delta * - * @return + * @return - the writer for the delta * @throws IOException * @throws IOException */ @@ -273,32 +271,63 @@ public abstract class LuceneBase2 return indexInfo.getMainIndexReferenceCountingReadOnlyIndexReader(); } + /** + * Set the dictionary service + * @param dictionaryService + */ public void setDictionaryService(DictionaryService dictionaryService) { this.dictionaryService = dictionaryService; } + /** + * Get the dictionary service. + * + * @return - the service + */ public DictionaryService getDictionaryService() { return dictionaryService; } + /** + * Set the lucene configuration options + * + * @param config + */ public void setLuceneConfig(LuceneConfig config) { this.config = config; } + /** + * Get the lucene configuration options. + * + * @return - the config options object. + */ public LuceneConfig getLuceneConfig() { return config; } + /** + * Get the ID for the delat we are working with. + * + * @return - the id + */ public String getDeltaId() { return deltaId; } + /** + * Excute actions while holding the write lock oin the index + * + * @param + * @param lockWork + * @return - the result returned by the action. + */ public R doWithWriteLock(LockWork lockWork) { return indexInfo.doWithWriteLock(lockWork); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexerAndSearcherFactory2.java b/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerAndSearcherFactory.java similarity index 72% rename from source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexerAndSearcherFactory2.java rename to source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerAndSearcherFactory.java index 7b9c9fc226..a92e74f61d 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexerAndSearcherFactory2.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerAndSearcherFactory.java @@ -28,6 +28,7 @@ import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import javax.transaction.RollbackException; import javax.transaction.SystemException; @@ -41,18 +42,14 @@ import org.alfresco.repo.search.IndexerException; import org.alfresco.repo.search.MLAnalysisMode; import org.alfresco.repo.search.QueryRegisterComponent; import org.alfresco.repo.search.SearcherException; -import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer; import org.alfresco.repo.search.impl.lucene.index.IndexInfo; import org.alfresco.repo.search.transaction.SimpleTransaction; import org.alfresco.repo.search.transaction.SimpleTransactionManager; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.TransactionUtil; import org.alfresco.repo.transaction.TransactionUtil.TransactionWork; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.GUID; import org.apache.commons.io.FileUtils; @@ -73,13 +70,9 @@ import org.quartz.JobExecutionException; * @author andyh */ -public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearcher, XAResource +public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneIndexerAndSearcher, XAResource { - private static Log logger = LogFactory.getLog(LuceneIndexerAndSearcherFactory2.class); - - private DictionaryService dictionaryService; - - private NamespaceService nameSpaceService; + private static Log logger = LogFactory.getLog(AbstractLuceneIndexerAndSearcherFactory.class); private int queryMaxClauses; @@ -90,18 +83,18 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche * indexer for each store within a transaction */ - private static Map> activeIndexersInGlobalTx = new HashMap>(); + private static Map> activeIndexersInGlobalTx = new HashMap>(); /** * Suspended global transactions. */ - private static Map> suspendedIndexersInGlobalTx = new HashMap>(); + private static Map> suspendedIndexersInGlobalTx = new HashMap>(); /** * Thread local indexers - used outside a global transaction */ - private static ThreadLocal> threadLocalIndexers = new ThreadLocal>(); + private static ThreadLocal> threadLocalIndexers = new ThreadLocal>(); /** * The dafault timeout for transactions TODO: Respect this @@ -118,14 +111,8 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche * The node service we use to get information about nodes */ - private NodeService nodeService; - - private FullTextSearchIndexer luceneFullTextSearchIndexer; - private String indexRootLocation; - private ContentService contentService; - private QueryRegisterComponent queryRegister; /** the maximum transformation time to allow atomically, defaulting to 20ms */ @@ -147,47 +134,42 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche * Private constructor for the singleton TODO: FIt in with IOC */ - public LuceneIndexerAndSearcherFactory2() + public AbstractLuceneIndexerAndSearcherFactory() { super(); } - /** - * Setter for getting the node service via IOC Used in the Spring container - * - * @param nodeService - */ - - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - public void setDictionaryService(DictionaryService dictionaryService) - { - this.dictionaryService = dictionaryService; - } - - public void setNameSpaceService(NamespaceService nameSpaceService) - { - this.nameSpaceService = nameSpaceService; - } - - public void setLuceneFullTextSearchIndexer(FullTextSearchIndexer luceneFullTextSearchIndexer) - { - this.luceneFullTextSearchIndexer = luceneFullTextSearchIndexer; - } + /** + * Set the directory that contains the indexes + * + * @param indexRootLocation + */ public void setIndexRootLocation(String indexRootLocation) { this.indexRootLocation = indexRootLocation; } + /** + * Set the query register + * + * @param queryRegister + */ public void setQueryRegister(QueryRegisterComponent queryRegister) { this.queryRegister = queryRegister; } + /** + * Get the query register. + * + * @return - the query register. + */ + public QueryRegisterComponent getQueryRegister() + { + return queryRegister; + } + /** * Set the maximum average transformation time allowed to a transformer in order to have the transformation * performed in the current transaction. The default is 20ms. @@ -200,10 +182,20 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche this.maxAtomicTransformationTime = maxAtomicTransformationTime; } + /** + * Get the max time for an atomic transform + * + * @return - milliseconds as a long + */ + public long getMaxTransformationTime() + { + return maxAtomicTransformationTime; + } + /** * Check if we are in a global transactoin according to the transaction manager * - * @return + * @return - true if in a global transaction */ private boolean inGlobalTransaction() @@ -221,7 +213,7 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche /** * Get the local transaction - may be null oif we are outside a transaction. * - * @return + * @return - the transaction * @throws IndexerException */ private SimpleTransaction getTransaction() throws IndexerException @@ -242,7 +234,7 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche * @param storeRef - * the id of the store */ - public LuceneIndexer2 getIndexer(StoreRef storeRef) throws IndexerException + public LuceneIndexer getIndexer(StoreRef storeRef) throws IndexerException { // register to receive txn callbacks // TODO: make this conditional on whether the XA stuff is being used @@ -253,14 +245,14 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche { SimpleTransaction tx = getTransaction(); // Only find indexers in the active list - Map indexers = activeIndexersInGlobalTx.get(tx); + Map indexers = activeIndexersInGlobalTx.get(tx); if (indexers == null) { if (suspendedIndexersInGlobalTx.containsKey(tx)) { throw new IndexerException("Trying to obtain an index for a suspended transaction."); } - indexers = new HashMap(); + indexers = new HashMap(); activeIndexersInGlobalTx.put(tx, indexers); try { @@ -280,7 +272,7 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche throw new IndexerException("", e); } } - LuceneIndexer2 indexer = indexers.get(storeRef); + LuceneIndexer indexer = indexers.get(storeRef); if (indexer == null) { indexer = createIndexer(storeRef, getTransactionId(tx, storeRef)); @@ -296,15 +288,15 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche } - private LuceneIndexer2 getThreadLocalIndexer(StoreRef storeRef) + private LuceneIndexer getThreadLocalIndexer(StoreRef storeRef) { - Map indexers = threadLocalIndexers.get(); + Map indexers = threadLocalIndexers.get(); if (indexers == null) { - indexers = new HashMap(); + indexers = new HashMap(); threadLocalIndexers.set(indexers); } - LuceneIndexer2 indexer = indexers.get(storeRef); + LuceneIndexer indexer = indexers.get(storeRef); if (indexer == null) { indexer = createIndexer(storeRef, GUID.generate()); @@ -317,7 +309,7 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche * Get the transaction identifier uised to store it in the transaction map. * * @param tx - * @return + * @return - the transaction id */ private static String getTransactionId(Transaction tx, StoreRef storeRef) { @@ -328,10 +320,10 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche } else { - Map indexers = threadLocalIndexers.get(); + Map indexers = threadLocalIndexers.get(); if (indexers != null) { - LuceneIndexer2 indexer = indexers.get(storeRef); + LuceneIndexer indexer = indexers.get(storeRef); if (indexer != null) { return indexer.getDeltaId(); @@ -346,27 +338,17 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche * * @param storeRef * @param deltaId - * @return + * @return - the indexer made by the concrete implemntation */ - private LuceneIndexerImpl2 createIndexer(StoreRef storeRef, String deltaId) - { - LuceneIndexerImpl2 indexer = LuceneIndexerImpl2.getUpdateIndexer(storeRef, deltaId, this); - indexer.setNodeService(nodeService); - indexer.setDictionaryService(dictionaryService); - // indexer.setLuceneIndexLock(luceneIndexLock); - indexer.setLuceneFullTextSearchIndexer(luceneFullTextSearchIndexer); - indexer.setContentService(contentService); - indexer.setMaxAtomicTransformationTime(maxAtomicTransformationTime); - return indexer; - } + protected abstract LuceneIndexer createIndexer(StoreRef storeRef, String deltaId); /** * Encapsulate creating a searcher over the main index */ - public LuceneSearcher2 getSearcher(StoreRef storeRef, boolean searchDelta) throws SearcherException + public LuceneSearcher getSearcher(StoreRef storeRef, boolean searchDelta) throws SearcherException { String deltaId = null; - LuceneIndexer2 indexer = null; + LuceneIndexer indexer = null; if (searchDelta) { deltaId = getTransactionId(getTransaction(), storeRef); @@ -375,7 +357,7 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche indexer = getIndexer(storeRef); } } - LuceneSearcher2 searcher = getSearcher(storeRef, indexer); + LuceneSearcher searcher = getSearcher(storeRef, indexer); return searcher; } @@ -384,19 +366,11 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche * * @param storeRef * @param deltaId - * @return + * @return - the searcher made by the concrete implementation. * @throws SearcherException */ - private LuceneSearcher2 getSearcher(StoreRef storeRef, LuceneIndexer2 indexer) throws SearcherException - { - LuceneSearcherImpl2 searcher = LuceneSearcherImpl2.getSearcher(storeRef, indexer, this); - searcher.setNamespacePrefixResolver(nameSpaceService); - // searcher.setLuceneIndexLock(luceneIndexLock); - searcher.setNodeService(nodeService); - searcher.setDictionaryService(dictionaryService); - searcher.setQueryRegister(queryRegister); - return searcher; - } + + protected abstract LuceneSearcher getSearcher(StoreRef storeRef, LuceneIndexer indexer) throws SearcherException; /* * XAResource implementation @@ -408,7 +382,7 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche { // TODO: Should be remembering overall state // TODO: Keep track of prepare responses - Map indexers = activeIndexersInGlobalTx.get(xid); + Map indexers = activeIndexersInGlobalTx.get(xid); if (indexers == null) { if (suspendedIndexersInGlobalTx.containsKey(xid)) @@ -430,7 +404,7 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche } else if (indexers.size() == 1) { - for (LuceneIndexer2 indexer : indexers.values()) + for (LuceneIndexer indexer : indexers.values()) { indexer.commit(); } @@ -444,7 +418,7 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche else // two phase { - for (LuceneIndexer2 indexer : indexers.values()) + for (LuceneIndexer indexer : indexers.values()) { indexer.commit(); } @@ -459,7 +433,7 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche public void end(Xid xid, int flag) throws XAException { - Map indexers = activeIndexersInGlobalTx.get(xid); + Map indexers = activeIndexersInGlobalTx.get(xid); if (indexers == null) { if (suspendedIndexersInGlobalTx.containsKey(xid)) @@ -501,13 +475,13 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche public boolean isSameRM(XAResource xar) throws XAException { - return (xar instanceof LuceneIndexerAndSearcherFactory2); + return (xar instanceof AbstractLuceneIndexerAndSearcherFactory); } public int prepare(Xid xid) throws XAException { // TODO: Track state OK, ReadOnly, Exception (=> rolled back?) - Map indexers = activeIndexersInGlobalTx.get(xid); + Map indexers = activeIndexersInGlobalTx.get(xid); if (indexers == null) { if (suspendedIndexersInGlobalTx.containsKey(xid)) @@ -522,7 +496,7 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche } boolean isPrepared = true; boolean isModified = false; - for (LuceneIndexer2 indexer : indexers.values()) + for (LuceneIndexer indexer : indexers.values()) { try { @@ -567,7 +541,7 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche // TODO: What to do if all do not roll back? try { - Map indexers = activeIndexersInGlobalTx.get(xid); + Map indexers = activeIndexersInGlobalTx.get(xid); if (indexers == null) { if (suspendedIndexersInGlobalTx.containsKey(xid)) @@ -580,7 +554,7 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche return; } } - for (LuceneIndexer2 indexer : indexers.values()) + for (LuceneIndexer indexer : indexers.values()) { indexer.rollback(); } @@ -599,8 +573,8 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche public void start(Xid xid, int flag) throws XAException { - Map active = activeIndexersInGlobalTx.get(xid); - Map suspended = suspendedIndexersInGlobalTx.get(xid); + Map active = activeIndexersInGlobalTx.get(xid); + Map suspended = suspendedIndexersInGlobalTx.get(xid); if (flag == XAResource.TMJOIN) { // must be active @@ -659,10 +633,10 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche { try { - Map indexers = threadLocalIndexers.get(); + Map indexers = threadLocalIndexers.get(); if (indexers != null) { - for (LuceneIndexer2 indexer : indexers.values()) + for (LuceneIndexer indexer : indexers.values()) { try { @@ -689,16 +663,16 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche /** * Prepare the transaction TODO: Store prepare results * - * @return + * @return - the tx code */ public int prepare() throws IndexerException { boolean isPrepared = true; boolean isModified = false; - Map indexers = threadLocalIndexers.get(); + Map indexers = threadLocalIndexers.get(); if (indexers != null) { - for (LuceneIndexer2 indexer : indexers.values()) + for (LuceneIndexer indexer : indexers.values()) { try { @@ -734,11 +708,11 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche */ public void rollback() { - Map indexers = threadLocalIndexers.get(); + Map indexers = threadLocalIndexers.get(); if (indexers != null) { - for (LuceneIndexer2 indexer : indexers.values()) + for (LuceneIndexer indexer : indexers.values()) { try { @@ -762,22 +736,17 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche public void flush() { // TODO: Needs fixing if we expose the indexer in JTA - Map indexers = threadLocalIndexers.get(); + Map indexers = threadLocalIndexers.get(); if (indexers != null) { - for (LuceneIndexer2 indexer : indexers.values()) + for (LuceneIndexer indexer : indexers.values()) { indexer.flushPending(); } } } - public void setContentService(ContentService contentService) - { - this.contentService = contentService; - } - public String getIndexRootLocation() { return indexRootLocation; @@ -788,11 +757,21 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche return indexerBatchSize; } + /** + * Set the batch six to use for background indexing + * + * @param indexerBatchSize + */ public void setIndexerBatchSize(int indexerBatchSize) { this.indexerBatchSize = indexerBatchSize; } + /** + * Get the directory where any lock files are written (by default there are none) + * + * @return - the path to the directory + */ public String getLockDirectory() { return lockDirectory; @@ -834,42 +813,76 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche return queryMaxClauses; } + /** + * Set the max number of queries in a llucen boolean query + * + * @param queryMaxClauses + */ public void setQueryMaxClauses(int queryMaxClauses) { this.queryMaxClauses = queryMaxClauses; BooleanQuery.setMaxClauseCount(this.queryMaxClauses); } + /** + * Set the lucene write lock timeout + * @param timeout + */ public void setWriteLockTimeout(long timeout) { this.writeLockTimeout = timeout; } + /** + * Set the lucene commit lock timeout (no longer used with lucene 2.1) + * @param timeout + */ public void setCommitLockTimeout(long timeout) { this.commitLockTimeout = timeout; } + /** + * Get the commit lock timout. + * @return - the timeout + */ public long getCommitLockTimeout() { return commitLockTimeout; } + /** + * Get the write lock timeout + * @return - the timeout in ms + */ public long getWriteLockTimeout() { return writeLockTimeout; } + /** + * Set the lock poll interval in ms + * + * @param time + */ public void setLockPollInterval(long time) { Lock.LOCK_POLL_INTERVAL = time; } + /** + * Get the max number of tokens in the field + * @return - the max tokens considered. + */ public int getIndexerMaxFieldLength() { return indexerMaxFieldLength; } + /** + * Set the max field length. + * @param indexerMaxFieldLength + */ public void setIndexerMaxFieldLength(int indexerMaxFieldLength) { this.indexerMaxFieldLength = indexerMaxFieldLength; @@ -889,12 +902,17 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche private TransactionService transactionService; - private LuceneIndexerAndSearcher factory; + private Set factories; + @SuppressWarnings("unused") private NodeService nodeService; private String targetLocation; + /** + * Default constructor + * + */ public LuceneIndexBackupComponent() { } @@ -912,12 +930,12 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche /** * Set the Lucene index factory that will be used to control the index locks * - * @param factory - * the index factory + * @param factories + * the index factories */ - public void setFactory(LuceneIndexerAndSearcher factory) + public void setFactories(Set factories) { - this.factory = factory; + this.factories = factories; } /** @@ -961,83 +979,101 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche private void backupImpl() { // create the location to copy to - final File targetDir = new File(targetLocation); + File targetDir = new File(targetLocation); if (targetDir.exists() && !targetDir.isDirectory()) { throw new AlfrescoRuntimeException("Target location is a file and not a directory: " + targetDir); } - final File targetParentDir = targetDir.getParentFile(); + File targetParentDir = targetDir.getParentFile(); if (targetParentDir == null) { throw new AlfrescoRuntimeException("Target location may not be a root directory: " + targetDir); } - final File tempDir = new File(targetParentDir, "indexbackup_temp"); + File tempDir = new File(targetParentDir, "indexbackup_temp"); - factory.doWithAllWriteLocks(new WithAllWriteLocksWork() + for (LuceneIndexerAndSearcher factory : factories) { - public Object doWork() + WithAllWriteLocksWork backupWork = new BackUpWithAllWriteLocksWork(factory, tempDir, targetDir); + factory.doWithAllWriteLocks(backupWork); + + if (logger.isDebugEnabled()) { - try - { - File indexRootDir = new File(factory.getIndexRootLocation()); - // perform the copy - backupDirectory(indexRootDir, tempDir, targetDir); - return null; - } - catch (Throwable e) - { - throw new AlfrescoRuntimeException( - "Failed to copy Lucene index root: \n" - + " Index root: " + factory.getIndexRootLocation() + "\n" + " Target: " - + targetDir, e); - } + logger.debug("Backed up Lucene indexes: \n" + " Target directory: " + targetDir); } - }); - - if (logger.isDebugEnabled()) - { - logger.debug("Backed up Lucene indexes: \n" + " Target directory: " + targetDir); } } - /** - * Makes a backup of the source directory via a temporary folder - */ - private void backupDirectory(File sourceDir, File tempDir, File targetDir) throws Exception + static class BackUpWithAllWriteLocksWork implements WithAllWriteLocksWork { - if (!sourceDir.exists()) + LuceneIndexerAndSearcher factory; + + File tempDir; + + File targetDir; + + BackUpWithAllWriteLocksWork(LuceneIndexerAndSearcher factory, File tempDir, File targetDir) { - // there is nothing to copy - return; + this.factory = factory; + this.tempDir = tempDir; + this.targetDir = targetDir; } - // delete the files from the temp directory - if (tempDir.exists()) + + public Object doWork() { - FileUtils.deleteDirectory(tempDir); - if (tempDir.exists()) + try { - throw new AlfrescoRuntimeException("Temp directory exists and cannot be deleted: " + tempDir); + File indexRootDir = new File(factory.getIndexRootLocation()); + // perform the copy + backupDirectory(indexRootDir, tempDir, targetDir); + return null; + } + catch (Throwable e) + { + throw new AlfrescoRuntimeException("Failed to copy Lucene index root: \n" + + " Index root: " + factory.getIndexRootLocation() + "\n" + " Target: " + targetDir, e); } } - // copy to the temp directory - FileUtils.copyDirectory(sourceDir, tempDir, true); - // check that the temp directory was created - if (!tempDir.exists()) + + /** + * Makes a backup of the source directory via a temporary folder + */ + private static void backupDirectory(File sourceDir, File tempDir, File targetDir) throws Exception { - throw new AlfrescoRuntimeException("Copy to temp location failed"); - } - // delete the target directory - FileUtils.deleteDirectory(targetDir); - if (targetDir.exists()) - { - throw new AlfrescoRuntimeException("Failed to delete older files from target location"); - } - // rename the temp to be the target - tempDir.renameTo(targetDir); - // make sure the rename worked - if (!targetDir.exists()) - { - throw new AlfrescoRuntimeException("Failed to rename temporary directory to target backup directory"); + if (!sourceDir.exists()) + { + // there is nothing to copy + return; + } + // delete the files from the temp directory + if (tempDir.exists()) + { + FileUtils.deleteDirectory(tempDir); + if (tempDir.exists()) + { + throw new AlfrescoRuntimeException("Temp directory exists and cannot be deleted: " + tempDir); + } + } + // copy to the temp directory + FileUtils.copyDirectory(sourceDir, tempDir, true); + // check that the temp directory was created + if (!tempDir.exists()) + { + throw new AlfrescoRuntimeException("Copy to temp location failed"); + } + // delete the target directory + FileUtils.deleteDirectory(targetDir); + if (targetDir.exists()) + { + throw new AlfrescoRuntimeException("Failed to delete older files from target location"); + } + // rename the temp to be the target + tempDir.renameTo(targetDir); + // make sure the rename worked + if (!targetDir.exists()) + { + throw new AlfrescoRuntimeException( + "Failed to rename temporary directory to target backup directory"); + } } } } @@ -1069,10 +1105,43 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche } } + public MLAnalysisMode getDefaultMLIndexAnalysisMode() + { + return defaultMLIndexAnalysisMode; + } + + /** + * Set the ML analysis mode at index time. + * + * @param mode + */ + public void setDefaultMLIndexAnalysisMode(MLAnalysisMode mode) + { + // defaultMLIndexAnalysisMode = MLAnalysisMode.getMLAnalysisMode(mode); + defaultMLIndexAnalysisMode = mode; + } + + public MLAnalysisMode getDefaultMLSearchAnalysisMode() + { + return defaultMLSearchAnalysisMode; + } + + /** + * Set the ML analysis mode at search time + * @param mode + */ + public void setDefaultMLSearchAnalysisMode(MLAnalysisMode mode) + { + // defaultMLSearchAnalysisMode = MLAnalysisMode.getMLAnalysisMode(mode); + defaultMLSearchAnalysisMode = mode; + } + + protected abstract List getAllStores(); + public R doWithAllWriteLocks(WithAllWriteLocksWork lockWork) { // get all the available stores - List storeRefs = nodeService.getStores(); + List storeRefs = getAllStores(); IndexInfo.LockWork currentLockWork = null; @@ -1119,9 +1188,9 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche { IndexInfo.LockWork lockWork; - LuceneIndexer2 indexer; + LuceneIndexer indexer; - NestingLockWork(LuceneIndexer2 indexer, IndexInfo.LockWork lockWork) + NestingLockWork(LuceneIndexer indexer, IndexInfo.LockWork lockWork) { this.indexer = indexer; this.lockWork = lockWork; @@ -1137,9 +1206,9 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche { WithAllWriteLocksWork lockWork; - LuceneIndexer2 indexer; + LuceneIndexer indexer; - CoreLockWork(LuceneIndexer2 indexer, WithAllWriteLocksWork lockWork) + CoreLockWork(LuceneIndexer indexer, WithAllWriteLocksWork lockWork) { this.indexer = indexer; this.lockWork = lockWork; @@ -1173,28 +1242,4 @@ public class LuceneIndexerAndSearcherFactory2 implements LuceneIndexerAndSearche } } - public MLAnalysisMode getDefaultMLIndexAnalysisMode() - { - return defaultMLIndexAnalysisMode; - } - - public void setDefaultMLIndexAnalysisMode(MLAnalysisMode mode) - { - //defaultMLIndexAnalysisMode = MLAnalysisMode.getMLAnalysisMode(mode); - defaultMLIndexAnalysisMode = mode; - } - - public MLAnalysisMode getDefaultMLSearchAnalysisMode() - { - return defaultMLSearchAnalysisMode; - } - - public void setDefaultMLSearchAnalysisMode(MLAnalysisMode mode) - { - //defaultMLSearchAnalysisMode = MLAnalysisMode.getMLAnalysisMode(mode); - defaultMLSearchAnalysisMode = mode; - } - - - } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerImpl2.java b/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerImpl.java similarity index 86% rename from source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerImpl2.java rename to source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerImpl.java index c06c504fbd..c2257b4811 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerImpl2.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerImpl.java @@ -27,6 +27,7 @@ package org.alfresco.repo.search.impl.lucene; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.ListIterator; @@ -38,7 +39,6 @@ import javax.transaction.xa.XAResource; import org.alfresco.repo.search.IndexerException; import org.alfresco.repo.search.impl.lucene.index.TransactionStatus; import org.alfresco.service.cmr.repository.InvalidNodeRefException; -import org.alfresco.service.cmr.repository.NodeRef; import org.apache.log4j.Logger; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexReader; @@ -50,25 +50,52 @@ import org.apache.lucene.index.TermDocs; * Common support for indexing across implementations * * @author andyh + * @param - + * the type used to generate the key in the index file */ -public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 +public abstract class AbstractLuceneIndexerImpl extends AbstractLuceneBase { /** * Enum for indexing actions against a node */ protected enum Action { - INDEX, REINDEX, DELETE, CASCADEREINDEX + /** + * An index + */ + INDEX, + /** + * A reindex + */ + REINDEX, + /** + * A delete + */ + DELETE, + /** + * A cascaded reindex (ensures directory structre is ok) + */ + CASCADEREINDEX } protected enum IndexUpdateStatus { - UNMODIFIED, SYNCRONOUS, ASYNCHRONOUS; + /** + * Inde is unchanged + */ + UNMODIFIED, + /** + * Index is being changein in TX + */ + SYNCRONOUS, + /** + * Index is eiong changed by a background upate + */ + ASYNCHRONOUS; } - protected long docs; - + // Failure codes to index when problems occur indexing content protected static class Command @@ -131,7 +158,8 @@ public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 /** * Logger */ - private static Logger s_logger = Logger.getLogger(AbstractLuceneIndexerImpl2.class); + @SuppressWarnings("unused") + private static Logger s_logger = Logger.getLogger(AbstractLuceneIndexerImpl.class); protected static Set deletePrimary(Collection nodeRefs, IndexReader reader, boolean delete) throws LuceneIndexException @@ -149,8 +177,8 @@ public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 { int doc = td.doc(); Document document = reader.document(doc); - String id = document.get("ID"); - refs.add(id); + String[] ids = document.getValues("ID"); + refs.add(ids[ids.length - 1]); if (delete) { reader.deleteDocument(doc); @@ -183,8 +211,8 @@ public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 { int doc = td.doc(); Document document = reader.document(doc); - String id = document.get("ID"); - refs.add(id); + String[] ids = document.getValues("ID"); + refs.add(ids[ids.length - 1]); if (delete) { reader.deleteDocument(doc); @@ -220,8 +248,8 @@ public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 { int doc = td.doc(); Document document = reader.document(doc); - String id = document.get("ID"); - refs.add(id); + String[] ids = document.getValues("ID"); + refs.add(ids[ids.length - 1]); if (delete) { reader.deleteDocument(doc); @@ -351,6 +379,7 @@ public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 /** * Commit this index + * @throws LuceneIndexException */ public void commit() throws LuceneIndexException { @@ -411,7 +440,8 @@ public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 * Prepare to commit At the moment this makes sure we have all the locks TODO: This is not doing proper * serialisation against the index as would a data base transaction. * - * @return + * @return the tx state + * @throws LuceneIndexException */ public int prepare() throws LuceneIndexException { @@ -459,7 +489,7 @@ public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 /** * Has this index been modified? * - * @return + * @return true if modified */ public boolean isModified() { @@ -468,6 +498,7 @@ public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 /** * Roll back the index changes (this just means they are never added) + * @throws LuceneIndexException */ public void rollback() throws LuceneIndexException { @@ -530,7 +561,7 @@ public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 protected abstract void doRollBack() throws IOException; protected abstract void doSetRollbackOnly() throws IOException; - + protected abstract List createDocuments(String stringNodeRef, boolean isNew, boolean indexAllProperties, boolean includeDirectoryDocuments); @@ -631,7 +662,7 @@ public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 addCommand(new Command(ref, Action.DELETE)); } - private void addCommand(Command command) + private void addCommand(Command command) { if (commandList.size() > 0) { @@ -693,6 +724,9 @@ public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 } } + /** + * @throws LuceneIndexException + */ public void flushPending() throws LuceneIndexException { IndexReader mainReader = null; @@ -783,4 +817,64 @@ public abstract class AbstractLuceneIndexerImpl2 extends LuceneBase2 } } + /** + * Are we deleting leaves only (not meta data) + * @return - deleting only nodes. + */ + public boolean getDeleteOnlyNodes() + { + return indexUpdateStatus == IndexUpdateStatus.ASYNCHRONOUS; + } + + /** + * Get the deletions + * @return - the ids to delete + */ + public Set getDeletions() + { + return Collections.unmodifiableSet(deletions); + } + + /** + * Delete all entries from the index. + * + */ + public void deleteAll() + { + IndexReader mainReader = null; + try + { + mainReader = getReader(); + for (int doc = 0; doc < mainReader.maxDoc(); doc++) + { + if (!mainReader.isDeleted(doc)) + { + Document document = mainReader.document(doc); + String[] ids = document.getValues("ID"); + deletions.add(ids[ids.length - 1]); + } + } + + } + catch (IOException e) + { + // If anything goes wrong we try and do a roll back + throw new LuceneIndexException("Failed to delete all entries from the index", e); + } + finally + { + if (mainReader != null) + { + try + { + mainReader.close(); + } + catch (IOException e) + { + throw new LuceneIndexException("Filed to close main reader", e); + } + } + } + } + } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/FilterIndexReaderByNodeRefs.java b/source/java/org/alfresco/repo/search/impl/lucene/FilterIndexReaderByNodeRefs.java deleted file mode 100644 index 4d3cb7ebb1..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/FilterIndexReaderByNodeRefs.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.repo.search.impl.lucene; - -import java.io.IOException; -import java.util.BitSet; -import java.util.Set; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.service.cmr.repository.NodeRef; -import org.apache.lucene.index.FilterIndexReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.index.TermDocs; -import org.apache.lucene.index.TermEnum; -import org.apache.lucene.index.TermPositions; - -public class FilterIndexReaderByNodeRefs extends FilterIndexReader -{ - BitSet deletedDocuments; - - public FilterIndexReaderByNodeRefs(IndexReader reader, Set deletions) - { - super(reader); - deletedDocuments = new BitSet(reader.maxDoc()); - - try - { - for (NodeRef nodeRef : deletions) - { - TermDocs td = reader.termDocs(new Term("ID", nodeRef.toString())); - while (td.next()) - { - deletedDocuments.set(td.doc(), true); - } - } - } - catch (IOException e) - { - throw new AlfrescoRuntimeException("Failed to construct filtering index reader", e); - } - } - - public static class FilterTermDocs implements TermDocs - { - BitSet deletedDocuments; - - protected TermDocs in; - - public FilterTermDocs(TermDocs in, BitSet deletedDocuments) - { - this.in = in; - this.deletedDocuments = deletedDocuments; - } - - public void seek(Term term) throws IOException - { - // Seek is left to the base implementation - in.seek(term); - } - - public void seek(TermEnum termEnum) throws IOException - { - // Seek is left to the base implementation - in.seek(termEnum); - } - - public int doc() - { - // The current document info is valid in the base implementation - return in.doc(); - } - - public int freq() - { - // The frequency is valid in the base implementation - return in.freq(); - } - - public boolean next() throws IOException - { - while(in.next()) - { - if(!deletedDocuments.get(in.doc())) - { - // Not masked - return true; - } - } - return false; - } - - public int read(int[] docs, int[] freqs) throws IOException - { - int[] innerDocs = new int[docs.length]; - int[] innerFreq = new int[docs.length]; - int count = in.read(innerDocs, innerFreq); - - // Is the stream exhausted - if (count == 0) - { - return 0; - } - - if(allDeleted(innerDocs, count)) - { - // Did not find anything - try again - return read(docs, freqs); - } - - // Add non deleted - - int insertPosition = 0; - for(int i = 0; i < count; i++) - { - if(!deletedDocuments.get(innerDocs[i])) - { - docs[insertPosition] = innerDocs[i]; - freqs[insertPosition] = innerFreq[i]; - insertPosition++; - } - } - - return insertPosition; - } - - private boolean allDeleted(int[] docs, int fillSize) - { - for(int i = 0; i < fillSize; i++) - { - if(!deletedDocuments.get(docs[i])) - { - return false; - } - } - return true; - } - - public boolean skipTo(int i) throws IOException - { - boolean result = in.skipTo(i); - if(result == false) - { - return false; - } - - if(deletedDocuments.get(in.doc())) - { - return skipTo(i); - } - else - { - return true; - } - } - - public void close() throws IOException - { - // Leave to internal implementation - in.close(); - } - } - - /** Base class for filtering {@link TermPositions} implementations. */ - public static class FilterTermPositions extends FilterTermDocs implements TermPositions - { - - public FilterTermPositions(TermPositions in, BitSet deletedDocuements) - { - super(in, deletedDocuements); - } - - public int nextPosition() throws IOException - { - return ((TermPositions) this.in).nextPosition(); - } - } - - @Override - public int numDocs() - { - return super.numDocs() - deletedDocuments.cardinality(); - } - - @Override - public TermDocs termDocs() throws IOException - { - return new FilterTermDocs(super.termDocs(), deletedDocuments); - } - - @Override - public TermPositions termPositions() throws IOException - { - return new FilterTermPositions(super.termPositions(), deletedDocuments); - } -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/FilterIndexReaderByNodeRefs2.java b/source/java/org/alfresco/repo/search/impl/lucene/FilterIndexReaderByStringId.java similarity index 88% rename from source/java/org/alfresco/repo/search/impl/lucene/FilterIndexReaderByNodeRefs2.java rename to source/java/org/alfresco/repo/search/impl/lucene/FilterIndexReaderByStringId.java index f0b385b46e..8424611a7d 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/FilterIndexReaderByNodeRefs2.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/FilterIndexReaderByStringId.java @@ -43,15 +43,30 @@ import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Searcher; import org.apache.lucene.search.TermQuery; -public class FilterIndexReaderByNodeRefs2 extends FilterIndexReader + +/** + * An index reader that filters documents from another. + * + * @author andyh + * + */ +public class FilterIndexReaderByStringId extends FilterIndexReader { - private static Log s_logger = LogFactory.getLog(FilterIndexReaderByNodeRefs2.class); + private static Log s_logger = LogFactory.getLog(FilterIndexReaderByStringId.class); BitSet deletedDocuments; private String id; - public FilterIndexReaderByNodeRefs2(String id, IndexReader reader, Set deletions, boolean deleteNodesOnly) + /** + * Apply the filter + * + * @param id + * @param reader + * @param deletions + * @param deleteNodesOnly + */ + public FilterIndexReaderByStringId(String id, IndexReader reader, Set deletions, boolean deleteNodesOnly) { super(reader); this.id = id; @@ -108,6 +123,12 @@ public class FilterIndexReaderByNodeRefs2 extends FilterIndexReader } } + /** + * Filter implementation + * + * @author andyh + * + */ public static class FilterTermDocs implements TermDocs { BitSet deletedDocuments; @@ -116,6 +137,11 @@ public class FilterIndexReaderByNodeRefs2 extends FilterIndexReader String id; + /** + * @param id + * @param in + * @param deletedDocuments + */ public FilterTermDocs(String id, TermDocs in, BitSet deletedDocuments) { this.in = in; @@ -242,6 +268,11 @@ public class FilterIndexReaderByNodeRefs2 extends FilterIndexReader public static class FilterTermPositions extends FilterTermDocs implements TermPositions { + /** + * @param id + * @param in + * @param deletedDocuements + */ public FilterTermPositions(String id, TermPositions in, BitSet deletedDocuements) { super(id, in, deletedDocuements); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryServiceImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryServiceImpl.java index 798e7f2403..e6dfdf174b 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryServiceImpl.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryServiceImpl.java @@ -35,6 +35,7 @@ import java.util.Set; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; +import org.alfresco.repo.search.IndexerAndSearcher; import org.alfresco.repo.search.IndexerException; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.ChildAssociationRef; @@ -49,6 +50,12 @@ import org.alfresco.service.namespace.NamespacePrefixResolver; import org.alfresco.service.namespace.QName; import org.alfresco.util.ISO9075; +/** + * Category service implementation + * + * @author andyh + * + */ public class LuceneCategoryServiceImpl implements CategoryService { private NodeService nodeService; @@ -57,8 +64,11 @@ public class LuceneCategoryServiceImpl implements CategoryService private DictionaryService dictionaryService; - private LuceneIndexerAndSearcher indexerAndSearcher; + private IndexerAndSearcher indexerAndSearcher; + /** + * + */ public LuceneCategoryServiceImpl() { super(); @@ -66,22 +76,38 @@ public class LuceneCategoryServiceImpl implements CategoryService // Inversion of control support + /** + * Set the node service + * @param nodeService + */ public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } + /** + * Set the service to map prefixes to uris + * @param namespacePrefixResolver + */ public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver) { this.namespacePrefixResolver = namespacePrefixResolver; } + /** + * Set the dictionary service + * @param dictionaryService + */ public void setDictionaryService(DictionaryService dictionaryService) { this.dictionaryService = dictionaryService; } - public void setIndexerAndSearcher(LuceneIndexerAndSearcher indexerAndSearcher) + /** + * Set the indexer and searcher + * @param indexerAndSearcher + */ + public void setIndexerAndSearcher(IndexerAndSearcher indexerAndSearcher) { this.indexerAndSearcher = indexerAndSearcher; } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexBackupComponentTest.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexBackupComponentTest.java index 06d9e97876..9342cd999a 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexBackupComponentTest.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexBackupComponentTest.java @@ -25,10 +25,11 @@ package org.alfresco.repo.search.impl.lucene; import java.io.File; +import java.util.Collections; import junit.framework.TestCase; -import org.alfresco.repo.search.impl.lucene.LuceneIndexerAndSearcherFactory2.LuceneIndexBackupComponent; +import org.alfresco.repo.search.impl.lucene.AbstractLuceneIndexerAndSearcherFactory.LuceneIndexBackupComponent; import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.transaction.TransactionService; @@ -37,7 +38,6 @@ import org.alfresco.util.TempFileProvider; import org.springframework.context.ApplicationContext; /** - * @see org.alfresco.repo.search.impl.lucene.LuceneIndexerAndSearcherFactory.LuceneIndexBackupComponent * * @author Derek Hulley */ @@ -55,7 +55,7 @@ public class LuceneIndexBackupComponentTest extends TestCase { TransactionService transactionService = (TransactionService) ctx.getBean("transactionComponent"); NodeService nodeService = (NodeService) ctx.getBean("NodeService"); - LuceneIndexerAndSearcher factory = (LuceneIndexerAndSearcher) ctx.getBean("luceneIndexerAndSearcherFactory"); + LuceneIndexerAndSearcher factory = (LuceneIndexerAndSearcher) ctx.getBean("admLuceneIndexerAndSearcherFactory"); this.authenticationComponent = (AuthenticationComponent)ctx.getBean("authenticationComponent"); this.authenticationComponent.setSystemUserAsCurrentUser(); @@ -65,7 +65,7 @@ public class LuceneIndexBackupComponentTest extends TestCase backupComponent = new LuceneIndexBackupComponent(); backupComponent.setTransactionService(transactionService); - backupComponent.setFactory(factory); + backupComponent.setFactories(Collections.singleton(factory)); backupComponent.setNodeService(nodeService); backupComponent.setTargetLocation(tempTargetDir.toString()); } @@ -77,6 +77,9 @@ public class LuceneIndexBackupComponentTest extends TestCase super.tearDown(); } + /** + * Test back up + */ public void testBackup() { backupComponent.backup(); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexer2.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexer.java similarity index 76% rename from source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexer2.java rename to source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexer.java index 682c9582ad..6e2ca16091 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexer2.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexer.java @@ -26,7 +26,9 @@ package org.alfresco.repo.search.impl.lucene; import java.util.Set; -import org.alfresco.repo.search.IndexerSPI; +import org.alfresco.repo.search.BackgroundIndexerAware; +import org.alfresco.repo.search.Indexer; +import org.alfresco.repo.search.TransactionSynchronisationAwareIndexer; import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer; import org.alfresco.repo.search.impl.lucene.index.IndexInfo; import org.alfresco.service.cmr.dictionary.DictionaryService; @@ -36,21 +38,11 @@ import org.alfresco.service.cmr.repository.NodeService; /** * @author Andy Hind */ -public interface LuceneIndexer2 extends IndexerSPI -{ - - public void commit(); - public void rollback(); - public int prepare(); - public boolean isModified(); - public void setNodeService(NodeService nodeService); - public void setDictionaryService(DictionaryService dictionaryService); - public void setLuceneFullTextSearchIndexer(FullTextSearchIndexer luceneFullTextSearchIndexer); - +public interface LuceneIndexer extends Indexer, TransactionSynchronisationAwareIndexer +{ public String getDeltaId(); public void flushPending() throws LuceneIndexException; public Set getDeletions(); - public boolean getDeleteOnlyNodes(); - + public boolean getDeleteOnlyNodes(); public R doWithWriteLock(IndexInfo.LockWork lockWork); } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcher2.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcher.java similarity index 78% rename from source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcher2.java rename to source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcher.java index 7eb9d0ae9f..406ab6a4ab 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcher2.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcher.java @@ -28,9 +28,26 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.namespace.NamespacePrefixResolver; -public interface LuceneSearcher2 extends SearchService +/** + * Lucene implementation specific entension to the seracher API + * @author andyh + * + */ +public interface LuceneSearcher extends SearchService { + /** + * Check if the index exists + * @return - true if it exists + */ public boolean indexExists(); + /** + * Ste the node service + * @param nodeService + */ public void setNodeService(NodeService nodeService); + /** + * Set the name space service + * @param namespacePrefixResolver + */ public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver); } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneXPathHandler.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneXPathHandler.java index 3d560cbc75..f879d37daa 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneXPathHandler.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneXPathHandler.java @@ -39,7 +39,12 @@ import org.saxpath.Axis; import org.saxpath.Operator; import org.saxpath.SAXPathException; import org.saxpath.XPathHandler; - +/** + * XPATH handler for lucene - currently only does basic paths + * + * @author andyh + * + */ public class LuceneXPathHandler implements XPathHandler { private PathQuery query; @@ -52,11 +57,18 @@ public class LuceneXPathHandler implements XPathHandler private DictionaryService dictionaryService; + /** + * + */ public LuceneXPathHandler() { super(); } + /** + * Get the resulting query + * @return - the query + */ public PathQuery getQuery() { return this.query; @@ -348,6 +360,7 @@ public class LuceneXPathHandler implements XPathHandler } + @SuppressWarnings("unused") private void addAbsolute(String nameSpace, String localName) { ArrayList answer = new ArrayList(2); @@ -401,6 +414,10 @@ public class LuceneXPathHandler implements XPathHandler { answer.add(new RelativeStructuredFieldPosition(PathTokenFilter.NO_NS_TOKEN_TEXT)); } + else if (namespacePrefixResolver.getNamespaceURI("").equals("")) + { + answer.add(new RelativeStructuredFieldPosition(PathTokenFilter.NO_NS_TOKEN_TEXT)); + } else { answer.add(new RelativeStructuredFieldPosition(namespacePrefixResolver.getNamespaceURI(""))); @@ -480,11 +497,19 @@ public class LuceneXPathHandler implements XPathHandler } + /** + * Set the service to resolve name space prefixes + * @param namespacePrefixResolver + */ public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver) { this.namespacePrefixResolver = namespacePrefixResolver; } + /** + * Set the dictionary service. + * @param dictionaryService + */ public void setDictionaryService(DictionaryService dictionaryService) { this.dictionaryService = dictionaryService; diff --git a/source/java/org/alfresco/repo/search/impl/lucene/analysis/NumericEncoder.java b/source/java/org/alfresco/repo/search/impl/lucene/analysis/NumericEncoder.java index 96202ef91d..7b248812af 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/analysis/NumericEncoder.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/analysis/NumericEncoder.java @@ -90,7 +90,7 @@ public class NumericEncoder * ffffffff. * * @param intToEncode - * @return + * @return the encoded string */ public static String encode(int intToEncode) { @@ -104,7 +104,7 @@ public class NumericEncoder * ffffffffffffffff. * * @param longToEncode - * @return + * @return - the encoded string */ public static String encode(long longToEncode) { @@ -112,13 +112,23 @@ public class NumericEncoder return encodeToHex(replacement); } + /** + * Secode a long + * @param hex + * @return - the decoded string + */ + public static long decodeLong(String hex) + { + return decodeFromHex(hex) ^ LONG_SIGN_MASK; + } + /** * Encode a float into a string that orders correctly according to string * comparison. Note that there is no negative NaN but there are codings that * imply this. So NaN and -Infinity may not compare as expected. * * @param floatToEncode - * @return + * @return - the encoded string */ public static String encode(float floatToEncode) { @@ -142,7 +152,7 @@ public class NumericEncoder * imply this. So NaN and -Infinity may not compare as expected. * * @param doubleToEncode - * @return + * @return the encoded string */ public static String encode(double doubleToEncode) { @@ -185,6 +195,18 @@ public class NumericEncoder while (l != 0); return new String(buf); } + + private static long decodeFromHex(String hex) + { + long l = 0; + long factor = 1; + for(int i = 15; i >= 0; i--, factor <<= 4) + { + int digit = Character.digit(hex.charAt(i), 16); + l += digit*factor; + } + return l; + } private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; diff --git a/source/java/org/alfresco/repo/search/impl/lucene/analysis/NumericEncodingTest.java b/source/java/org/alfresco/repo/search/impl/lucene/analysis/NumericEncodingTest.java index f08295458c..d50c43a3f4 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/analysis/NumericEncodingTest.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/analysis/NumericEncodingTest.java @@ -26,14 +26,27 @@ package org.alfresco.repo.search.impl.lucene.analysis; import junit.framework.TestCase; +/** + * Tests for string encoding + * @author andyh + * + */ public class NumericEncodingTest extends TestCase { + /** + * + * + */ public NumericEncodingTest() { super(); } + /** + * + * @param arg0 + */ public NumericEncodingTest(String arg0) { super(arg0); @@ -126,7 +139,7 @@ public class NumericEncodingTest extends TestCase } } - /* + /** * Sample test for int */ @@ -141,7 +154,7 @@ public class NumericEncodingTest extends TestCase assertEquals("ffffffff", NumericEncoder.encode(Integer.MAX_VALUE)); } - /* + /** * Sample test for long */ @@ -154,9 +167,17 @@ public class NumericEncodingTest extends TestCase assertEquals("8000000000000001", NumericEncoder.encode(1L)); assertEquals("fffffffffffffffe", NumericEncoder.encode(Long.MAX_VALUE - 1)); assertEquals("ffffffffffffffff", NumericEncoder.encode(Long.MAX_VALUE)); + + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(Long.MIN_VALUE)), Long.MIN_VALUE); + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(Long.MIN_VALUE + 1)),Long.MIN_VALUE + 1); + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(-1L)), -1L); + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(0L)), 0L); + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(1L)), 1L); + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(Long.MAX_VALUE - 1)),Long.MAX_VALUE - 1); + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(Long.MAX_VALUE)), Long.MAX_VALUE); } - /* + /** * Sample test for float */ @@ -174,7 +195,7 @@ public class NumericEncodingTest extends TestCase } - /* + /** * Sample test for double */ diff --git a/source/java/org/alfresco/repo/search/impl/lucene/analysis/PathTokenFilter.java b/source/java/org/alfresco/repo/search/impl/lucene/analysis/PathTokenFilter.java index fb13432b8d..2eceae6608 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/analysis/PathTokenFilter.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/analysis/PathTokenFilter.java @@ -35,9 +35,8 @@ import org.apache.lucene.analysis.Token; import org.apache.lucene.analysis.Tokenizer; /** - * @author andyh - * - * TODO To change the template for this generated type comment go to Window - Preferences - Java - Code Style - Code Templates + * @author andyh TODO To change the template for this generated type comment go to Window - Preferences - Java - Code + * Style - Code Templates */ public class PathTokenFilter extends Tokenizer { @@ -60,7 +59,7 @@ public class PathTokenFilter extends Tokenizer public final static String TOKEN_TYPE_PATH_ELEMENT_NAME = "PATH_ELEMENT_NAME"; public final static String TOKEN_TYPE_PATH_ELEMENT_NAMESPACE = "PATH_ELEMENT_NAMESPACE"; - + public final static String TOKEN_TYPE_PATH_ELEMENT_NAMESPACE_PREFIX = "PATH_ELEMENT_NAMESPACE_PREFIX"; char pathSeparator; @@ -143,10 +142,9 @@ public class PathTokenFilter extends Tokenizer if (text.length() == 0) { - continue; // Skip if we find // or /; or ;; etc + continue; // Skip if we find // or /; or ;; etc } - if (text.charAt(text.length() - 1) == pathSeparator) { text = text.substring(0, text.length() - 1); @@ -182,8 +180,8 @@ public class PathTokenFilter extends Tokenizer { namespaceToken = new Token(text.substring(0, split), t.startOffset(), t.startOffset() + split, TOKEN_TYPE_PATH_ELEMENT_NAMESPACE_PREFIX); - nameToken = new Token(text.substring(split + 1), t.startOffset() - + split + 1, t.endOffset(), TOKEN_TYPE_PATH_ELEMENT_NAME); + nameToken = new Token(text.substring(split + 1), t.startOffset() + split + 1, t.endOffset(), + TOKEN_TYPE_PATH_ELEMENT_NAME); } else { @@ -200,7 +198,15 @@ public class PathTokenFilter extends Tokenizer if (includeNamespace) { + if (namespaceToken.termText().equals("")) + { + namespaceToken = new Token(noNsTokenText, t.startOffset(), t.startOffset(), + TOKEN_TYPE_PATH_ELEMENT_NAMESPACE); + namespaceToken.setPositionIncrement(1); + } + tokens.add(namespaceToken); + } tokens.add(nameToken); @@ -271,9 +277,9 @@ public class PathTokenFilter extends Tokenizer else if (!inNameSpace && (c == ';')) { buffer.append(c); - return new Token(buffer.toString(), start, readerPosition , "LASTQNAME"); + return new Token(buffer.toString(), start, readerPosition, "LASTQNAME"); } - + buffer.append(c); } readerPosition = -1; diff --git a/source/java/org/alfresco/repo/search/impl/lucene/fts/FTSIndexerAware.java b/source/java/org/alfresco/repo/search/impl/lucene/fts/FTSIndexerAware.java index f284700ec1..e87799547a 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/fts/FTSIndexerAware.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/fts/FTSIndexerAware.java @@ -26,8 +26,19 @@ package org.alfresco.repo.search.impl.lucene.fts; import org.alfresco.service.cmr.repository.StoreRef; +/** + * Supports acll back to the FTS indexer to report what has been done + * @author andyh + * + */ public interface FTSIndexerAware { - - public void indexCompleted(StoreRef storeRef, int remaining, Exception e); + /** + * Call back used by the background indexer + * + * @param storeRef + * @param remaining + * @param e + */ + public void indexCompleted(StoreRef storeRef, int remaining, Exception e); } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/fts/FTSIndexerException.java b/source/java/org/alfresco/repo/search/impl/lucene/fts/FTSIndexerException.java index 33475b950f..49ae087401 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/fts/FTSIndexerException.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/fts/FTSIndexerException.java @@ -24,6 +24,12 @@ */ package org.alfresco.repo.search.impl.lucene.fts; +/** + * FTS indexer exception + * + * @author andyh + * + */ public class FTSIndexerException extends RuntimeException { @@ -32,21 +38,34 @@ public class FTSIndexerException extends RuntimeException */ private static final long serialVersionUID = 3258134635127912754L; + /** + * + */ public FTSIndexerException() { super(); } + /** + * @param message + */ public FTSIndexerException(String message) { super(message); } + /** + * @param message + * @param cause + */ public FTSIndexerException(String message, Throwable cause) { super(message, cause); } + /** + * @param cause + */ public FTSIndexerException(Throwable cause) { super(cause); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/fts/FTSIndexerJob.java b/source/java/org/alfresco/repo/search/impl/lucene/fts/FTSIndexerJob.java index 8c77d0c8c6..e67ecc7324 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/fts/FTSIndexerJob.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/fts/FTSIndexerJob.java @@ -28,8 +28,16 @@ import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; +/** + * Job to run the FTS indexer + * @author andyh + * + */ public class FTSIndexerJob implements Job { + /** + * + */ public FTSIndexerJob() { super(); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/fts/FullTextSearchIndexer.java b/source/java/org/alfresco/repo/search/impl/lucene/fts/FullTextSearchIndexer.java index 1ff653a64c..6e77724dfc 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/fts/FullTextSearchIndexer.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/fts/FullTextSearchIndexer.java @@ -25,19 +25,48 @@ package org.alfresco.repo.search.impl.lucene.fts; import org.alfresco.service.cmr.repository.StoreRef; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; - - -public interface FullTextSearchIndexer { - +/** + * API for full text search indexing in the background + * + * @author andyh + */ +public interface FullTextSearchIndexer extends BeanFactoryPostProcessor +{ + /** + * Mark a store as dirty, requiring a background index update to fix it up. + * + * @param storeRef + */ public abstract void requiresIndex(StoreRef storeRef); + /** + * Call back to report state back to the indexer + * + * @param storeRef + * @param remaining + * @param e + */ public abstract void indexCompleted(StoreRef storeRef, int remaining, Exception e); + /** + * Pause indexing 9no back ground indexing until a resume is called) + * @throws InterruptedException + */ public abstract void pause() throws InterruptedException; + /** + * Resume after a pause + * + * @throws InterruptedException + */ public abstract void resume() throws InterruptedException; + /** + * Do a chunk of outstanding indexing work + * + */ public abstract void index(); } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/search/impl/lucene/fts/FullTextSearchIndexerImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/fts/FullTextSearchIndexerImpl.java index 9ad2492055..66fe10aff4 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/fts/FullTextSearchIndexerImpl.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/fts/FullTextSearchIndexerImpl.java @@ -28,29 +28,36 @@ import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; -import org.alfresco.repo.search.IndexerSPI; -import org.alfresco.repo.search.impl.lucene.LuceneIndexerAndSearcher; +import org.alfresco.repo.search.BackgroundIndexerAware; +import org.alfresco.repo.search.Indexer; +import org.alfresco.repo.search.IndexerAndSearcher; +import org.alfresco.repo.search.SupportsBackgroundIndexing; import org.alfresco.service.cmr.repository.StoreRef; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; +/** + * Background index update scheduler + * @author andyh + * + */ public class FullTextSearchIndexerImpl implements FTSIndexerAware, FullTextSearchIndexer { - private enum State - { - ACTIVE, PAUSING, PAUSED - }; - private static Set requiresIndex = new LinkedHashSet(); private static Set indexing = new HashSet(); - LuceneIndexerAndSearcher luceneIndexerAndSearcherFactory; + private IndexerAndSearcher indexerAndSearcherFactory; private int pauseCount = 0; private boolean paused = false; + /** + * + */ public FullTextSearchIndexerImpl() { super(); @@ -139,6 +146,7 @@ public class FullTextSearchIndexerImpl implements FTSIndexerAware, FullTextSearc } } + @SuppressWarnings("unused") private synchronized boolean isPaused() throws InterruptedException { if (pauseCount == 0) @@ -172,9 +180,13 @@ public class FullTextSearchIndexerImpl implements FTSIndexerAware, FullTextSearc if (toIndex != null) { // System.out.println("Indexing "+toIndex+" at "+(new java.util.Date())); - IndexerSPI indexer = luceneIndexerAndSearcherFactory.getIndexer(toIndex); - indexer.registerCallBack(this); - done += indexer.updateFullTextSearch(1000); + Indexer indexer = indexerAndSearcherFactory.getIndexer(toIndex); + if(indexer instanceof BackgroundIndexerAware) + { + BackgroundIndexerAware backgroundIndexerAware = (BackgroundIndexerAware)indexer; + backgroundIndexerAware.registerCallBack(this); + done += backgroundIndexerAware.updateFullTextSearch(1000); + } } else { @@ -213,13 +225,34 @@ public class FullTextSearchIndexerImpl implements FTSIndexerAware, FullTextSearc return nextStoreRef; } - public void setLuceneIndexerAndSearcherFactory(LuceneIndexerAndSearcher luceneIndexerAndSearcherFactory) + /** + * @param indexerAndSearcherFactory + */ + public void setIndexerAndSearcherFactory(IndexerAndSearcher indexerAndSearcherFactory) { - this.luceneIndexerAndSearcherFactory = luceneIndexerAndSearcherFactory; + this.indexerAndSearcherFactory = indexerAndSearcherFactory; } + /** + * @param args + * @throws InterruptedException + */ public static void main(String[] args) throws InterruptedException { + @SuppressWarnings("unused") ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:alfresco/application-context.xml"); } + + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException + { + // Find bean implementaing SupportsBackgroundIndexing and register + for(Object bgindexable : beanFactory.getBeansOfType(SupportsBackgroundIndexing.class).values()) + { + if(bgindexable instanceof SupportsBackgroundIndexing) + { + ((SupportsBackgroundIndexing)bgindexable).setFullTextSearchIndexer(this); + } + } + + } } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/index/IndexInfo.java b/source/java/org/alfresco/repo/search/impl/lucene/index/IndexInfo.java index 80c97102db..abb3cae363 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/index/IndexInfo.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/index/IndexInfo.java @@ -55,7 +55,7 @@ import java.util.zip.CRC32; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.search.IndexerException; -import org.alfresco.repo.search.impl.lucene.FilterIndexReaderByNodeRefs2; +import org.alfresco.repo.search.impl.lucene.FilterIndexReaderByStringId; import org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser; import org.alfresco.util.GUID; import org.apache.commons.logging.Log; @@ -1068,7 +1068,7 @@ public class IndexInfo else { reader = new MultiReader(new IndexReader[] { - new FilterIndexReaderByNodeRefs2("main+id", mainIndexReader, deletions, deleteOnlyNodes), + new FilterIndexReaderByStringId("main+id", mainIndexReader, deletions, deleteOnlyNodes), deltaReader }); } reader = ReferenceCountingReadOnlyIndexReaderFactory.createReader("MainReader" + id, reader); @@ -1690,7 +1690,7 @@ public class IndexInfo try { reader = new MultiReader(new IndexReader[] { - new FilterIndexReaderByNodeRefs2(id, reader, getDeletions(entry.getName()), entry + new FilterIndexReaderByStringId(id, reader, getDeletions(entry.getName()), entry .isDeletOnlyNodes()), subReader }); } catch (IOException ioe) diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/LeafScorer.java b/source/java/org/alfresco/repo/search/impl/lucene/query/LeafScorer.java index 40ec18f93c..fcb1f63fda 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/LeafScorer.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/query/LeafScorer.java @@ -50,6 +50,11 @@ import org.apache.lucene.search.Scorer; import org.apache.lucene.search.Similarity; import org.apache.lucene.search.Weight; +/** + * Leaf scorer to complete path queries + * @author andyh + * + */ public class LeafScorer extends Scorer { static class Counter @@ -112,6 +117,23 @@ public class LeafScorer extends Scorer private TermPositions tp; + /** + * Constructor - should use an arg object ... + * + * @param weight + * @param root + * @param level0 + * @param containerScorer + * @param sfps + * @param allNodes + * @param selfIds + * @param reader + * @param similarity + * @param norms + * @param dictionaryService + * @param repeat + * @param tp + */ public LeafScorer(Weight weight, TermPositions root, TermPositions level0, ContainerScorer containerScorer, StructuredFieldPosition[] sfps, TermPositions allNodes, HashMap selfIds, IndexReader reader, Similarity similarity, byte[] norms, DictionaryService dictionaryService, @@ -157,7 +179,8 @@ public class LeafScorer extends Scorer { int doc = containerScorer.doc(); Document document = reader.document(doc); - Field id = document.getField("ID"); + Field[] fields = document.getFields("ID"); + Field id = fields[fields.length-1]; Counter counter = parentIds.get(id.stringValue()); if (counter == null) { @@ -203,7 +226,8 @@ public class LeafScorer extends Scorer { int doc = level0.doc(); Document document = reader.document(doc); - Field id = document.getField("ID"); + Field[] fields = document.getFields("ID"); + Field id = fields[fields.length-1]; if (id != null) { Counter counter = parentIds.get(id.stringValue()); @@ -701,7 +725,8 @@ public class LeafScorer extends Scorer { return; } - String id = document.getField("ID").stringValue(); + Field[] fields = document.getFields("ID"); + String id = fields[fields.length-1].stringValue(); StructuredFieldPosition last = sfps[sfps.length - 1]; if ((last.linkSelf() && selfIds.containsKey(id))) {