From 1f3aabc6a02bb0df77f5b307190498f0525f9ac5 Mon Sep 17 00:00:00 2001 From: Derek Hulley Date: Mon, 10 Sep 2007 22:41:44 +0000 Subject: [PATCH] Merged V2.1 to HEAD 6455: OpenOffice transformer and extractor register regardless of the initial connection state. 6456: Fix for WCM-636 (Clicking OK twice while deleting web project results in exception) 6457: Updated installers and associated config 6458: AR-1669 Add getQnamePath to Javascript 6459: Fix for AWC-1456 - Word and Excel documents were being stored as octet streams rather than their correct mimetype 6460: Reverse order of reject & approve transitions, so that approve appears first in list of ui actions. 6461: Removed Process.exe (often detected as a virus) and updated config wizard. 6462: Switch to synchronous indexing for AVM by default 6463: Better support to query the state of AVM indexes 6464: Added Office 2007 document mimetypes and icons 6465: Added Office 2007 icons without the typo this time git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6736 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- ...nchronous-avm-indexing-context.xml.sample} | 2 +- config/alfresco/mimetype/mimetype-map.xml | 9 ++ config/alfresco/public-services-context.xml | 4 +- .../workflow/review_processdefinition.xml | 2 +- .../workflow/submit_processdefinition.xml | 4 +- .../org/alfresco/repo/avm/AVMServiceTest.java | 51 +++++++++ .../alfresco/repo/avm/AVMServiceTestBase.java | 5 + .../AbstractMetadataExtracterTest.java | 2 +- .../metadata/MetadataExtracterRegistry.java | 67 +++++++----- .../metadata/OpenOfficeMetadataExtracter.java | 100 +++++++----------- .../OpenOfficeMetadataExtracterTest.java | 2 +- .../OpenOfficeContentTransformer.java | 54 +--------- .../org/alfresco/repo/jscript/ScriptNode.java | 13 +++ .../filefolder/FileFolderServiceImpl.java | 13 +++ .../index/AVMFullIndexRecoveryComponent.java | 6 ++ ...hotTriggeredIndexingMethodInterceptor.java | 70 +++++++++++- .../impl/lucene/AVMLuceneIndexerImpl.java | 19 ++-- 17 files changed, 265 insertions(+), 158 deletions(-) rename config/alfresco/extension/{synchronous-avm-indexing-context.xml.sample => asynchronous-avm-indexing-context.xml.sample} (95%) diff --git a/config/alfresco/extension/synchronous-avm-indexing-context.xml.sample b/config/alfresco/extension/asynchronous-avm-indexing-context.xml.sample similarity index 95% rename from config/alfresco/extension/synchronous-avm-indexing-context.xml.sample rename to config/alfresco/extension/asynchronous-avm-indexing-context.xml.sample index dd2cb08d78..e057aec635 100644 --- a/config/alfresco/extension/synchronous-avm-indexing-context.xml.sample +++ b/config/alfresco/extension/asynchronous-avm-indexing-context.xml.sample @@ -24,7 +24,7 @@ - SYNCHRONOUS:TYPE:STAGING + ASYNCHRONOUS:TYPE:STAGING UNINDEXED:TYPE:STAGING_PREVIEW UNINDEXED:TYPE:AUTHOR UNINDEXED:TYPE:AUTHOR_PREVIEW diff --git a/config/alfresco/mimetype/mimetype-map.xml b/config/alfresco/mimetype/mimetype-map.xml index 7b43ada79f..d5683bdb6f 100644 --- a/config/alfresco/mimetype/mimetype-map.xml +++ b/config/alfresco/mimetype/mimetype-map.xml @@ -306,6 +306,15 @@ msg + + docx + + + xlsx + + + pptx + diff --git a/config/alfresco/public-services-context.xml b/config/alfresco/public-services-context.xml index 0fc7ce3680..eef4296cf1 100644 --- a/config/alfresco/public-services-context.xml +++ b/config/alfresco/public-services-context.xml @@ -572,7 +572,7 @@ org.alfresco.service.cmr.security.AuthenticationService - + @@ -938,7 +938,7 @@ - ASYNCHRONOUS:TYPE:STAGING + SYNCHRONOUS:TYPE:STAGING UNINDEXED:TYPE:STAGING_PREVIEW UNINDEXED:TYPE:AUTHOR UNINDEXED:TYPE:AUTHOR_PREVIEW diff --git a/config/alfresco/workflow/review_processdefinition.xml b/config/alfresco/workflow/review_processdefinition.xml index cba8bbaa36..9866fe2e52 100644 --- a/config/alfresco/workflow/review_processdefinition.xml +++ b/config/alfresco/workflow/review_processdefinition.xml @@ -24,8 +24,8 @@ - + diff --git a/config/alfresco/workflow/submit_processdefinition.xml b/config/alfresco/workflow/submit_processdefinition.xml index 0a17899baf..96a6ed3ab8 100644 --- a/config/alfresco/workflow/submit_processdefinition.xml +++ b/config/alfresco/workflow/submit_processdefinition.xml @@ -100,7 +100,6 @@ - + @@ -136,7 +136,6 @@ - + diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index be342a431a..ffd2ae9c40 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -358,7 +358,14 @@ public class AVMServiceTest extends AVMServiceTestBase tx.begin(); if(fService.getStore("avmAsynchronousTest") != null) { + assertTrue(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest")); fService.purgeStore("avmAsynchronousTest"); + assertTrue(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest")); + assertFalse(fIndexingInterceptor.hasIndexBeenCreated("bananaStoreWoof")); + } + else + { + assertFalse(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest")); } StoreRef storeRef = AVMNodeConverter.ToStoreRef("avmAsynchronousTest"); Indexer indexer = fIndexerAndSearcher.getIndexer(storeRef); @@ -368,6 +375,12 @@ public class AVMServiceTest extends AVMServiceTestBase avmIndexer.deleteIndex("avmAsynchronousTest", IndexMode.SYNCHRONOUS); } tx.commit(); + + tx = fTransactionService.getUserTransaction(); + tx.begin(); + assertEquals(-1, fIndexingInterceptor.getLastIndexedSnapshot("bananaStoreWoof")); + assertEquals(-1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); + tx.commit(); // TODO: Suspend and resume indexing in case we are really unlucky and hit an index before we expect it. @@ -379,8 +392,19 @@ public class AVMServiceTest extends AVMServiceTestBase results.close(); fService.createStore("avmAsynchronousTest"); + + tx = fTransactionService.getUserTransaction(); + tx.begin(); + assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); + tx.commit(); + fService.createSnapshot("avmAsynchronousTest", null, null); + tx = fTransactionService.getUserTransaction(); + tx.begin(); + assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); + tx.commit(); + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); assertEquals(1, results.length()); results.close(); @@ -388,8 +412,27 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createDirectory("avmAsynchronousTest:/", "a"); fService.createDirectory("avmAsynchronousTest:/a", "b"); fService.createDirectory("avmAsynchronousTest:/a/b", "c"); + + tx = fTransactionService.getUserTransaction(); + tx.begin(); + assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); + assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest")); + tx.commit(); + fService.createSnapshot("avmAsynchronousTest", null, null); + tx = fTransactionService.getUserTransaction(); + tx.begin(); + assertEquals(1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); + assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest")); + assertFalse(fIndexingInterceptor.isIndexUpToDateAndSearchable("avmAsynchronousTest")); + assertEquals(IndexMode.ASYNCHRONOUS, fIndexingInterceptor.getIndexMode("avmAsynchronousTest")); + assertEquals(IndexMode.SYNCHRONOUS, fIndexingInterceptor.getIndexMode("main")); + assertTrue(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 0)); + assertTrue(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 1)); + assertFalse(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 2)); + tx.commit(); + results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); assertEquals(1, results.length()); results.close(); @@ -400,6 +443,14 @@ public class AVMServiceTest extends AVMServiceTestBase assertEquals(4, results.length()); results.close(); + + tx = fTransactionService.getUserTransaction(); + tx.begin(); + assertEquals(1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest")); + assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest")); + assertTrue(fIndexingInterceptor.isIndexUpToDateAndSearchable("avmAsynchronousTest")); + tx.commit(); + fService.purgeStore("avmAsynchronousTest"); results = searchService.query(storeRef, "lucene", "PATH:\"//.\""); diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java b/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java index 79046ae5bc..6449c72d35 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java @@ -31,6 +31,7 @@ import java.util.TreeMap; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor; import org.alfresco.repo.search.IndexerAndSearcher; import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; import org.alfresco.service.cmr.avm.AVMNodeDescriptor; @@ -81,6 +82,8 @@ public class AVMServiceTestBase extends TestCase */ private long fStartTime; + protected static AVMSnapShotTriggeredIndexingMethodInterceptor fIndexingInterceptor; + protected static TransactionService fTransactionService; protected static IndexerAndSearcher fIndexerAndSearcher; @@ -104,6 +107,8 @@ public class AVMServiceTestBase extends TestCase fIndexerAndSearcher = (IndexerAndSearcher)fContext.getBean("indexerAndSearcherFactory"); fTransactionService = (TransactionService)fContext.getBean("transactionComponent"); fLockingService = (AVMLockingService)fContext.getBean("AVMLockingService"); + fIndexingInterceptor = (AVMSnapShotTriggeredIndexingMethodInterceptor)fContext.getBean("avmSnapShotTriggeredIndexingMethodInterceptor"); + AuthenticationService authService = (AuthenticationService)fContext.getBean("AuthenticationService"); authService.authenticate("admin", "admin".toCharArray()); CreateStoreTxnListener cstl = (CreateStoreTxnListener)fContext.getBean("createStoreTxnListener"); diff --git a/source/java/org/alfresco/repo/content/metadata/AbstractMetadataExtracterTest.java b/source/java/org/alfresco/repo/content/metadata/AbstractMetadataExtracterTest.java index 249c5fc709..4bf7a04d73 100644 --- a/source/java/org/alfresco/repo/content/metadata/AbstractMetadataExtracterTest.java +++ b/source/java/org/alfresco/repo/content/metadata/AbstractMetadataExtracterTest.java @@ -50,7 +50,7 @@ import org.springframework.context.ApplicationContext; */ public abstract class AbstractMetadataExtracterTest extends TestCase { - private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(); + protected static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(); protected static final String QUICK_TITLE = "The quick brown fox jumps over the lazy dog"; protected static final String QUICK_DESCRIPTION = "Gym class featuring a brown fox and lazy dog"; diff --git a/source/java/org/alfresco/repo/content/metadata/MetadataExtracterRegistry.java b/source/java/org/alfresco/repo/content/metadata/MetadataExtracterRegistry.java index 65945c2427..01aadbde22 100644 --- a/source/java/org/alfresco/repo/content/metadata/MetadataExtracterRegistry.java +++ b/source/java/org/alfresco/repo/content/metadata/MetadataExtracterRegistry.java @@ -49,7 +49,7 @@ public class MetadataExtracterRegistry private static final Log logger = LogFactory.getLog(MetadataExtracterRegistry.class); private List extracters; - private Map extracterCache; + private Map> extracterCache; /** Controls read access to the cache */ private Lock extracterCacheReadLock; @@ -60,7 +60,7 @@ public class MetadataExtracterRegistry { // initialise lists extracters = new ArrayList(10); - extracterCache = new HashMap(17); + extracterCache = new HashMap>(17); // create lock objects for access to the cache ReadWriteLock extractionCacheLock = new ReentrantReadWriteLock(); @@ -104,7 +104,7 @@ public class MetadataExtracterRegistry */ public MetadataExtracter getExtracter(String sourceMimetype) { - MetadataExtracter extracter = null; + List extractors = null; extracterCacheReadLock.lock(); try { @@ -112,7 +112,7 @@ public class MetadataExtracterRegistry { // the translation has been requested before // it might have been null - return extracterCache.get(sourceMimetype); + extractors = extracterCache.get(sourceMimetype); } } finally @@ -120,44 +120,59 @@ public class MetadataExtracterRegistry extracterCacheReadLock.unlock(); } - // the translation has not been requested before - // get a write lock on the cache - // no double check done as it is not an expensive task - extracterCacheWriteLock.lock(); - try + if (extractors == null) { - // find the most suitable transformer - may be empty list - extracter = findBestExtracter(sourceMimetype); - // store the result even if it is null - extracterCache.put(sourceMimetype, extracter); - return extracter; + // No request has been made before + // Get a write lock on the cache + // No double check done as it is not an expensive task + extracterCacheWriteLock.lock(); + try + { + // find the most suitable transformer - may be empty list + extractors = findBestExtracters(sourceMimetype); + // store the result even if it is null + extracterCache.put(sourceMimetype, extractors); + } + finally + { + extracterCacheWriteLock.unlock(); + } } - finally + + // We have the list of extractors that supposedly work (as registered). + // Take the first one that still claims to work + MetadataExtracter liveExtractor = null; + for (MetadataExtracter extractor : extractors) { - extracterCacheWriteLock.unlock(); + // An extractor may dynamically become unavailable + if (!extractor.isSupported(sourceMimetype)) + { + continue; + } + liveExtractor = extractor; } + return liveExtractor; } /** - * @param sourceMimetype The MIME type under examination - * @return The fastest of the most reliable extracters in extracters - * for the given MIME type, or null if none is available. + * @param sourceMimetype The MIME type under examination + * @return Returns a set of extractors that will work for the given mimetype */ - private MetadataExtracter findBestExtracter(String sourceMimetype) + private List findBestExtracters(String sourceMimetype) { - logger.debug("Finding best extracter for " + sourceMimetype); + logger.debug("Finding extractors for " + sourceMimetype); - MetadataExtracter bestExtracter = null; + List extractors = new ArrayList(1); - for (MetadataExtracter ext : extracters) + for (MetadataExtracter extractor : extracters) { - if (!ext.isSupported(sourceMimetype)) + if (!extractor.isSupported(sourceMimetype)) { // extraction not achievable continue; } - bestExtracter = ext; + extractors.add(extractor); } - return bestExtracter; + return extractors; } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracter.java b/source/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracter.java index f0463863c8..1b3b438973 100644 --- a/source/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracter.java +++ b/source/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracter.java @@ -80,25 +80,6 @@ public class OpenOfficeMetadataExtracter extends AbstractMappingMetadataExtracte this.connection = connection; } - private synchronized void connect() - { - if (isConnected()) - { - // just leave it - } - else - { - try - { - connection.connect(); - } - catch (ConnectException e) - { - logger.warn(e.getMessage()); - } - } - } - /** * Initialises the bean by establishing an UNO connection */ @@ -109,15 +90,6 @@ public class OpenOfficeMetadataExtracter extends AbstractMappingMetadataExtracte // Base initialization super.init(); - - // attempt a connection - connect(); - // Only allow registration if the connection is good - if (!isConnected()) - { - // Reconnections are only supported if the server is able to connection initially. - super.setRegistry(null); - } } /** @@ -129,6 +101,19 @@ public class OpenOfficeMetadataExtracter extends AbstractMappingMetadataExtracte return connection.isConnected(); } + /** + * Perform the default check, but also check if the OpenOffice connection is good. + */ + @Override + public boolean isSupported(String sourceMimetype) + { + if (!isConnected()) + { + return false; + } + return super.isSupported(sourceMimetype); + } + @Override public Map extractRaw(ContentReader reader) throws Throwable { @@ -146,35 +131,32 @@ public class OpenOfficeMetadataExtracter extends AbstractMappingMetadataExtracte String sourceUrl = toUrl(tempFromFile, connection); // UNO Interprocess Bridge *should* be thread-safe, but... - synchronized (connection) + XComponentLoader desktop = connection.getDesktop(); + XComponent document = desktop.loadComponentFromURL( + sourceUrl, + "_blank", + 0, + new PropertyValue[] { property("Hidden", Boolean.TRUE) }); + if (document == null) { - XComponentLoader desktop = connection.getDesktop(); - XComponent document = desktop.loadComponentFromURL( - sourceUrl, - "_blank", - 0, - new PropertyValue[] { property("Hidden", Boolean.TRUE) }); - if (document == null) - { - throw new FileNotFoundException("could not open source document: " + sourceUrl); - } - try - { - XDocumentInfoSupplier infoSupplier = (XDocumentInfoSupplier) UnoRuntime.queryInterface( - XDocumentInfoSupplier.class, document); - XPropertySet propSet = (XPropertySet) UnoRuntime.queryInterface( - XPropertySet.class, - infoSupplier - .getDocumentInfo()); + throw new FileNotFoundException("could not open source document: " + sourceUrl); + } + try + { + XDocumentInfoSupplier infoSupplier = (XDocumentInfoSupplier) UnoRuntime.queryInterface( + XDocumentInfoSupplier.class, document); + XPropertySet propSet = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, + infoSupplier + .getDocumentInfo()); - putRawValue(KEY_TITLE, propSet.getPropertyValue("Title").toString(), rawProperties); - putRawValue(KEY_DESCRIPTION, propSet.getPropertyValue("Subject").toString(), rawProperties); - putRawValue(KEY_AUTHOR, propSet.getPropertyValue("Author").toString(), rawProperties); - } - finally - { - document.dispose(); - } + putRawValue(KEY_TITLE, propSet.getPropertyValue("Title").toString(), rawProperties); + putRawValue(KEY_DESCRIPTION, propSet.getPropertyValue("Subject").toString(), rawProperties); + putRawValue(KEY_AUTHOR, propSet.getPropertyValue("Author").toString(), rawProperties); + } + finally + { + document.dispose(); } // Done return rawProperties; @@ -188,14 +170,6 @@ public class OpenOfficeMetadataExtracter extends AbstractMappingMetadataExtracte return fic.getFileURLFromSystemPath("", file.getAbsolutePath()); } - public double getReliability(String sourceMimetype) - { - if (isConnected()) - return super.getReliability(sourceMimetype); - else - return 0.0; - } - private static PropertyValue property(String name, Object value) { PropertyValue property = new PropertyValue(); diff --git a/source/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracterTest.java b/source/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracterTest.java index fae4e49e7e..c336a89b94 100644 --- a/source/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracterTest.java +++ b/source/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracterTest.java @@ -38,7 +38,7 @@ public class OpenOfficeMetadataExtracterTest extends AbstractMetadataExtracterTe { super.setUp(); - OpenOfficeConnection connection = new SocketOpenOfficeConnection(); + OpenOfficeConnection connection = (OpenOfficeConnection) ctx.getBean("openOfficeConnection"); extracter = new OpenOfficeMetadataExtracter(); extracter.setMimetypeService(mimetypeMap); diff --git a/source/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformer.java b/source/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformer.java index f951cdf2b1..9a34a6e693 100644 --- a/source/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformer.java +++ b/source/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformer.java @@ -27,7 +27,6 @@ package org.alfresco.repo.content.transform; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.net.ConnectException; import java.util.Map; import net.sf.jooreports.converter.DocumentFamily; @@ -46,8 +45,6 @@ import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.MimetypeService; import org.alfresco.util.PropertyCheck; import org.alfresco.util.TempFileProvider; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.core.io.DefaultResourceLoader; /** @@ -58,11 +55,7 @@ import org.springframework.core.io.DefaultResourceLoader; */ public class OpenOfficeContentTransformer extends AbstractContentTransformer { - private static Log logger = LogFactory.getLog(OpenOfficeContentTransformer.class); - private OpenOfficeConnection connection; - /** Keep track of the initial connection state */ - private boolean initiallyConnected; private OpenOfficeDocumentConverter converter; private String documentFormatsConfiguration; private DocumentFormatRegistry formatRegistry; @@ -91,30 +84,6 @@ public class OpenOfficeContentTransformer extends AbstractContentTransformer return connection.isConnected(); } - private synchronized boolean connect() - { - boolean success = false; - if (isConnected()) - { - // just leave it - success = true; - } - else - { - try - { - connection.connect(); - success = true; - } - catch (ConnectException e) - { - logger.warn(e.getMessage()); - } - } - // Done - return success; - } - @Override public void register() { @@ -140,18 +109,11 @@ public class OpenOfficeContentTransformer extends AbstractContentTransformer formatRegistry = new XmlDocumentFormatRegistry(); } - // attempt to establish a connection - initiallyConnected = connect(); - // set up the converter converter = new OpenOfficeDocumentConverter(connection); - if (initiallyConnected) - { - // If the server starts with OO running, then it will attempt reconnections. Otherwise it will - // just be wasting time trying to see if a connection is available all the time. - super.register(); - } + // Register + super.register(); } /** @@ -161,16 +123,8 @@ public class OpenOfficeContentTransformer extends AbstractContentTransformer { if (!isConnected()) { - if (!initiallyConnected) - { - // It wasn't there to start with, so we won't bother trying to connect - return 0.0; - } - // The connection may have gone away, so attempt to get it again - if (!connect()) - { - return 0.0; - } + // The connection management is must take care of this + return 0.0; } // there are some conversions that fail, despite the converter believing them possible diff --git a/source/java/org/alfresco/repo/jscript/ScriptNode.java b/source/java/org/alfresco/repo/jscript/ScriptNode.java index ddffb3d6eb..b3456b4f6b 100644 --- a/source/java/org/alfresco/repo/jscript/ScriptNode.java +++ b/source/java/org/alfresco/repo/jscript/ScriptNode.java @@ -642,6 +642,19 @@ public class ScriptNode implements Serializable, Scopeable return getAspects().contains(createQName(aspect)); } + /** + * @return QName path to this node. This can be used for Lucene PATH: style queries + */ + public String getQnamePath() + { + return this.services.getNodeService().getPath(getNodeRef()).toPrefixString(this.services.getNamespaceService()); + } + + public String jsGet_qnamePath() + { + return getQnamePath(); + } + /** * @return Display path to this node */ diff --git a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java index b8f19d74c8..1db139777b 100644 --- a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java +++ b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java @@ -638,6 +638,19 @@ public class FileFolderServiceImpl implements FileFolderService { // changed the name property nodeService.setProperty(targetNodeRef, ContentModel.PROP_NAME, newName); + + // May need to update the mimetype, to support apps using .tmp files when saving + ContentData contentData = (ContentData)nodeService.getProperty(targetNodeRef, ContentModel.PROP_CONTENT); + if (contentData != null) + { + String targetMimetype = contentData.getMimetype(); + String newMimetype = mimetypeService.guessMimetype(newName); + if (!targetMimetype.equalsIgnoreCase(newMimetype)) + { + contentData = ContentData.setMimetype(contentData, newMimetype); + nodeService.setProperty(targetNodeRef, ContentModel.PROP_CONTENT, contentData); + } + } } catch (DuplicateChildNodeNameException e) { diff --git a/source/java/org/alfresco/repo/node/index/AVMFullIndexRecoveryComponent.java b/source/java/org/alfresco/repo/node/index/AVMFullIndexRecoveryComponent.java index e0e10b65c4..145bf1183e 100644 --- a/source/java/org/alfresco/repo/node/index/AVMFullIndexRecoveryComponent.java +++ b/source/java/org/alfresco/repo/node/index/AVMFullIndexRecoveryComponent.java @@ -4,6 +4,7 @@ import java.util.List; import org.alfresco.repo.node.index.FullIndexRecoveryComponent.RecoveryMode; import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor; +import org.alfresco.repo.search.IndexMode; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avm.AVMStoreDescriptor; @@ -116,6 +117,11 @@ public class AVMFullIndexRecoveryComponent extends AbstractReindexComponent else // validate first { + if(avmSnapShotTriggeredIndexingMethodInterceptor.getIndexMode(store) == IndexMode.UNINDEXED) + { + return; + } + int lastActualSnapshotId = avmService.getLatestSnapshotID(store); if (lastActualSnapshotId <= 0) { diff --git a/source/java/org/alfresco/repo/search/AVMSnapShotTriggeredIndexingMethodInterceptor.java b/source/java/org/alfresco/repo/search/AVMSnapShotTriggeredIndexingMethodInterceptor.java index 76a2f4b82c..7fc067a77d 100644 --- a/source/java/org/alfresco/repo/search/AVMSnapShotTriggeredIndexingMethodInterceptor.java +++ b/source/java/org/alfresco/repo/search/AVMSnapShotTriggeredIndexingMethodInterceptor.java @@ -230,7 +230,7 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte avmIndexer.index(store, before, after, getIndexMode(store)); } } - + public void indexSnapshot(String store, int after) { StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); @@ -279,7 +279,73 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte return false; } - private synchronized IndexMode getIndexMode(String store) + /** + * Check if the index is up to date according to its index defintion and that all asynchronous work is done. + * + * @param store + * @return + */ + public boolean isIndexUpToDateAndSearchable(String store) + { + + switch (getIndexMode(store)) + { + case UNINDEXED: + return false; + case SYNCHRONOUS: + case ASYNCHRONOUS: + int last = avmService.getLatestSnapshotID(store); + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + Indexer indexer = indexerAndSearcher.getIndexer(storeRef); + if (indexer instanceof AVMLuceneIndexer) + { + AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer; + avmIndexer.flushPending(); + return avmIndexer.isSnapshotSearchable(store, last); + } + return false; + default: + return false; + } + } + + /** + * Check if the index is up to date according to its index defintion i it does not check that all asynchronous work is done. + * + * @param store + * @return + */ + public boolean isIndexUpToDate(String store) + { + + switch (getIndexMode(store)) + { + case UNINDEXED: + return true; + case SYNCHRONOUS: + case ASYNCHRONOUS: + int last = avmService.getLatestSnapshotID(store); + StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); + Indexer indexer = indexerAndSearcher.getIndexer(storeRef); + if (indexer instanceof AVMLuceneIndexer) + { + AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer; + avmIndexer.flushPending(); + return avmIndexer.getLastIndexedSnapshot(store) == last; + } + return false; + default: + return false; + } + } + + /** + * Given an avm store name determine if it is indexed and if so how. + * + * @param store + * @return + */ + public synchronized IndexMode getIndexMode(String store) { IndexMode mode = modeCache.get(store); if (mode == null) diff --git a/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerImpl.java index 60bd5c0ac2..7c55933a7f 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerImpl.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerImpl.java @@ -51,6 +51,7 @@ import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.transform.ContentTransformer; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.search.IndexMode; +import org.alfresco.repo.search.Indexer; import org.alfresco.repo.search.impl.lucene.fts.FTSIndexerAware; import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; @@ -379,16 +380,16 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl impl if (desc != null) { - + NodeRef nodeRef = AVMNodeConverter.ToNodeRef(endVersion, stringNodeRef); - + Document xdoc = new Document(); xdoc.add(new Field("ID", nodeRef.toString(), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); xdoc.add(new Field("ID", stringNodeRef, 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, nodeRef, endVersion, stringNodeRef); for (QName propertyName : properties.keySet()) { @@ -402,11 +403,11 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl impl isAtomic &= indexProperty(nodeRef, propertyName, value, xdoc, true, properties); } } - + StringBuilder qNameBuffer = new StringBuilder(64); if (node.getIsRoot()) { - + } // pseudo roots? else @@ -492,7 +493,7 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl impl } else - // not a root node + // not a root node { xdoc.add(new Field("QNAME", qNameBuffer.toString(), Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO)); @@ -1375,7 +1376,7 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl impl { String[] split = term.text().split(":"); int test = Integer.parseInt(split[3]); - if(test > end) + if (test > end) { end = test; } @@ -1485,7 +1486,7 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl impl { String[] split = term.text().split(":"); int test = Integer.parseInt(split[4]); - if(test > end) + if (test > end) { end = test; }