();
+
+ HTMLEditorKit.ParserCallback callback = new HTMLEditorKit.ParserCallback()
+ {
+ StringBuffer title = null;
+ boolean inHead = false;
+
+ public void handleText(char[] data, int pos)
+ {
+ if (title != null)
+ {
+ title.append(data);
+ }
+ }
+
+ public void handleComment(char[] data, int pos)
+ {
+ // Perhaps sniff for Office 9+ metadata in here?
+ }
+
+ public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos)
+ {
+ if (HTML.Tag.HEAD.equals(t))
+ {
+ inHead = true;
+ }
+ else if (HTML.Tag.TITLE.equals(t) && inHead)
+ {
+ title = new StringBuffer();
+ }
+ else
+ handleSimpleTag(t, a, pos);
+ }
+
+ public void handleEndTag(HTML.Tag t, int pos)
+ {
+ if (HTML.Tag.HEAD.equals(t))
+ {
+ inHead = false;
+ }
+ else if (HTML.Tag.TITLE.equals(t) && title != null)
+ {
+ trimPut(ContentModel.PROP_TITLE, title.toString(), tempDestination);
+ title = null;
+ }
+ }
+
+ public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos)
+ {
+ if (HTML.Tag.META.equals(t))
+ {
+ Object nameO = a.getAttribute(HTML.Attribute.NAME);
+ Object valueO = a.getAttribute(HTML.Attribute.CONTENT);
+ if (nameO == null || valueO == null)
+ return;
+
+ String name = nameO.toString();
+
+ if (name.equalsIgnoreCase("creator") || name.equalsIgnoreCase("author")
+ || name.equalsIgnoreCase("dc.creator"))
+ {
+ trimPut(ContentModel.PROP_AUTHOR, valueO, tempDestination);
+ }
+ if (name.equalsIgnoreCase("description") || name.equalsIgnoreCase("dc.description"))
+ {
+ trimPut(ContentModel.PROP_DESCRIPTION, valueO, tempDestination);
+ }
+ }
+ }
+
+ public void handleError(String errorMsg, int pos)
+ {
+ }
+ };
+
+ String charsetGuess = "UTF-8";
+ int tries = 0;
+ while (tries < 3)
+ {
+ tempDestination.clear();
+ Reader r = null;
+ InputStream cis = null;
+ try
+ {
+ cis = reader.getContentInputStream();
+ // TODO: for now, use default charset; we should attempt to map from html meta-data
+ r = new InputStreamReader(cis);
+ HTMLEditorKit.Parser parser = new ParserDelegator();
+ parser.parse(r, callback, tries > 0);
+ destination.putAll(tempDestination);
+ break;
+ }
+ catch (ChangedCharSetException ccse)
+ {
+ tries++;
+ charsetGuess = ccse.getCharSetSpec();
+ int begin = charsetGuess.indexOf("charset=");
+ if (begin > 0)
+ charsetGuess = charsetGuess.substring(begin + 8, charsetGuess.length());
+ reader = reader.getReader();
+ }
+ finally
+ {
+ if (r != null)
+ r.close();
+ if (cis != null)
+ cis.close();
+ }
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/content/metadata/HtmlMetadataExtracterTest.java b/source/java/org/alfresco/repo/content/metadata/HtmlMetadataExtracterTest.java
index 24376a1fe4..7867e8df9c 100644
--- a/source/java/org/alfresco/repo/content/metadata/HtmlMetadataExtracterTest.java
+++ b/source/java/org/alfresco/repo/content/metadata/HtmlMetadataExtracterTest.java
@@ -1,57 +1,57 @@
-/*
- * Copyright (C) 2005 Jesper Steen Møller
- *
- * Licensed under the Mozilla Public License version 1.1
- * with a permitted attribution clause. You may obtain a
- * copy of the License at
- *
- * http://www.alfresco.org/legal/license.txt
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the
- * License.
- */
-package org.alfresco.repo.content.metadata;
-
-import org.alfresco.repo.content.MimetypeMap;
-
-/**
- * @author Jesper Steen Møller
- */
-public class HtmlMetadataExtracterTest extends AbstractMetadataExtracterTest
-{
- private MetadataExtracter extracter;
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
- extracter = new HtmlMetadataExtracter();
- }
-
- /**
- * @return Returns the same transformer regardless - it is allowed
- */
- protected MetadataExtracter getExtracter()
- {
- return extracter;
- }
-
- public void testReliability() throws Exception
- {
- double reliability = 0.0;
- reliability = extracter.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN);
- assertEquals("Mimetype text should not be supported", 0.0, reliability);
-
- reliability = extracter.getReliability(MimetypeMap.MIMETYPE_HTML);
- assertEquals("HTML should be supported", 1.0, reliability);
- }
-
- public void testHtmlExtraction() throws Exception
- {
- testExtractFromMimetype(MimetypeMap.MIMETYPE_HTML);
- }
-}
+/*
+ * Copyright (C) 2005 Jesper Steen Møller
+ *
+ * Licensed under the Mozilla Public License version 1.1
+ * with a permitted attribution clause. You may obtain a
+ * copy of the License at
+ *
+ * http://www.alfresco.org/legal/license.txt
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the
+ * License.
+ */
+package org.alfresco.repo.content.metadata;
+
+import org.alfresco.repo.content.MimetypeMap;
+
+/**
+ * @author Jesper Steen Møller
+ */
+public class HtmlMetadataExtracterTest extends AbstractMetadataExtracterTest
+{
+ private MetadataExtracter extracter;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ extracter = new HtmlMetadataExtracter();
+ }
+
+ /**
+ * @return Returns the same transformer regardless - it is allowed
+ */
+ protected MetadataExtracter getExtracter()
+ {
+ return extracter;
+ }
+
+ public void testReliability() throws Exception
+ {
+ double reliability = 0.0;
+ reliability = extracter.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN);
+ assertEquals("Mimetype text should not be supported", 0.0, reliability);
+
+ reliability = extracter.getReliability(MimetypeMap.MIMETYPE_HTML);
+ assertEquals("HTML should be supported", 1.0, reliability);
+ }
+
+ public void testHtmlExtraction() throws Exception
+ {
+ testExtractFromMimetype(MimetypeMap.MIMETYPE_HTML);
+ }
+}
diff --git a/source/java/org/alfresco/repo/content/metadata/MetadataExtracter.java b/source/java/org/alfresco/repo/content/metadata/MetadataExtracter.java
index adc44e99d9..b548016e5d 100644
--- a/source/java/org/alfresco/repo/content/metadata/MetadataExtracter.java
+++ b/source/java/org/alfresco/repo/content/metadata/MetadataExtracter.java
@@ -1,72 +1,72 @@
-/*
- * Copyright (C) 2005 Jesper Steen Møller
- *
- * Licensed under the Mozilla Public License version 1.1
- * with a permitted attribution clause. You may obtain a
- * copy of the License at
- *
- * http://www.alfresco.org/legal/license.txt
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the
- * License.
- */
-package org.alfresco.repo.content.metadata;
-
-import java.io.Serializable;
-import java.util.Map;
-
-import org.alfresco.service.cmr.repository.ContentIOException;
-import org.alfresco.service.cmr.repository.ContentReader;
-import org.alfresco.service.namespace.QName;
-
-/**
- *
- * @author Jesper Steen Møller
- */
-public interface MetadataExtracter
-{
- /**
- * Provides the approximate accuracy with which this extracter can extract
- * metadata for the mimetype.
- *
- *
- * @param sourceMimetype the source mimetype
- * @return Returns a score 0.0 to 1.0. 0.0 indicates that the extraction
- * cannot be performed at all. 1.0 indicates that the extraction can
- * be performed perfectly.
- */
- public double getReliability(String sourceMimetype);
-
- /**
- * Provides an estimate, usually a worst case guess, of how long an
- * extraction will take.
- *
- * This method is used to determine, up front, which of a set of equally
- * reliant transformers will be used for a specific extraction.
- *
- * @return Returns the approximate number of milliseconds per transformation
- */
- public long getExtractionTime();
-
- /**
- * Extracts the metadata from the content provided by the reader and source
- * mimetype to the supplied map.
- *
- * The extraction viability can be determined by an up front call to
- * {@link #getReliability(String)}.
- *
- * The source mimetype must be available on the
- * {@link org.alfresco.service.cmr.repository.ContentAccessor#getMimetype()} method
- * of the reader.
- *
- * @param reader the source of the content
- * @param destination the destination of the extraction
- * @throws ContentIOException if an IO exception occurs
- */
- public void extract(ContentReader reader, Map destination) throws ContentIOException;
-
-}
+/*
+ * Copyright (C) 2005 Jesper Steen Møller
+ *
+ * Licensed under the Mozilla Public License version 1.1
+ * with a permitted attribution clause. You may obtain a
+ * copy of the License at
+ *
+ * http://www.alfresco.org/legal/license.txt
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the
+ * License.
+ */
+package org.alfresco.repo.content.metadata;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import org.alfresco.service.cmr.repository.ContentIOException;
+import org.alfresco.service.cmr.repository.ContentReader;
+import org.alfresco.service.namespace.QName;
+
+/**
+ *
+ * @author Jesper Steen Møller
+ */
+public interface MetadataExtracter
+{
+ /**
+ * Provides the approximate accuracy with which this extracter can extract
+ * metadata for the mimetype.
+ *
+ *
+ * @param sourceMimetype the source mimetype
+ * @return Returns a score 0.0 to 1.0. 0.0 indicates that the extraction
+ * cannot be performed at all. 1.0 indicates that the extraction can
+ * be performed perfectly.
+ */
+ public double getReliability(String sourceMimetype);
+
+ /**
+ * Provides an estimate, usually a worst case guess, of how long an
+ * extraction will take.
+ *
+ * This method is used to determine, up front, which of a set of equally
+ * reliant transformers will be used for a specific extraction.
+ *
+ * @return Returns the approximate number of milliseconds per transformation
+ */
+ public long getExtractionTime();
+
+ /**
+ * Extracts the metadata from the content provided by the reader and source
+ * mimetype to the supplied map.
+ *
+ * The extraction viability can be determined by an up front call to
+ * {@link #getReliability(String)}.
+ *
+ * The source mimetype must be available on the
+ * {@link org.alfresco.service.cmr.repository.ContentAccessor#getMimetype()} method
+ * of the reader.
+ *
+ * @param reader the source of the content
+ * @param destination the destination of the extraction
+ * @throws ContentIOException if an IO exception occurs
+ */
+ public void extract(ContentReader reader, Map destination) throws ContentIOException;
+
+}
diff --git a/source/java/org/alfresco/repo/content/metadata/MetadataExtracterRegistry.java b/source/java/org/alfresco/repo/content/metadata/MetadataExtracterRegistry.java
index 2365a7065e..e8302e9e76 100644
--- a/source/java/org/alfresco/repo/content/metadata/MetadataExtracterRegistry.java
+++ b/source/java/org/alfresco/repo/content/metadata/MetadataExtracterRegistry.java
@@ -1,191 +1,172 @@
-/*
- * Copyright (C) 2005 Jesper Steen Møller
- *
- * Licensed under the Mozilla Public License version 1.1
- * with a permitted attribution clause. You may obtain a
- * copy of the License at
- *
- * http://www.alfresco.org/legal/license.txt
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the
- * License.
- */
-package org.alfresco.repo.content.metadata;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import org.alfresco.error.AlfrescoRuntimeException;
-import org.alfresco.repo.content.MimetypeMap;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Holds and provides the most appropriate metadate extracter for a particular
- * mimetype.
- *
- * The extracters themselves know how well they are able to extract metadata.
- *
- * @see org.alfresco.repo.content.metadata.MetadataExtracter
- * @author Jesper Steen Møller
- */
-public class MetadataExtracterRegistry
-{
- private static final Log logger = LogFactory.getLog(MetadataExtracterRegistry.class);
-
- private List extracters;
- private Map extracterCache;
-
- private MimetypeMap mimetypeMap;
- /** Controls read access to the cache */
- private Lock extracterCacheReadLock;
- /** controls write access to the cache */
- private Lock extracterCacheWriteLock;
-
- public MetadataExtracterRegistry()
- {
- // initialise lists
- extracters = new ArrayList(10);
- extracterCache = new HashMap(17);
-
- // create lock objects for access to the cache
- ReadWriteLock extractionCacheLock = new ReentrantReadWriteLock();
- extracterCacheReadLock = extractionCacheLock.readLock();
- extracterCacheWriteLock = extractionCacheLock.writeLock();
- }
-
- /**
- * The mimetype map that will be used to check requests against
- *
- * @param mimetypeMap a map of mimetypes
- */
- public void setMimetypeMap(MimetypeMap mimetypeMap)
- {
- this.mimetypeMap = mimetypeMap;
- }
-
- /**
- * Register an instance of an extracter for use
- *
- * @param extracter an extracter
- */
- public void register(MetadataExtracter extracter)
- {
- if (logger.isDebugEnabled())
- {
- logger.debug("Registering metadata extracter: " + extracter);
- }
-
- extracterCacheWriteLock.lock();
- try
- {
- extracters.add(extracter);
- extracterCache.clear();
- }
- finally
- {
- extracterCacheWriteLock.unlock();
- }
- }
-
- /**
- * Gets the best metadata extracter. This is a combination of the most
- * reliable and the most performant extracter.
- *
- * The result is cached for quicker access next time.
- *
- * @param mimetype the source MIME of the extraction
- * @return Returns a metadata extracter that can extract metadata from the
- * chosen MIME type.
- */
- public MetadataExtracter getExtracter(String sourceMimetype)
- {
- // check that the mimetypes are valid
- if (!mimetypeMap.getMimetypes().contains(sourceMimetype))
- {
- throw new AlfrescoRuntimeException("Unknown extraction source mimetype: " + sourceMimetype);
- }
-
- MetadataExtracter extracter = null;
- extracterCacheReadLock.lock();
- try
- {
- if (extracterCache.containsKey(sourceMimetype))
- {
- // the translation has been requested before
- // it might have been null
- return extracterCache.get(sourceMimetype);
- }
- }
- finally
- {
- 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
- {
- // 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;
- }
- finally
- {
- extracterCacheWriteLock.unlock();
- }
- }
-
- /**
- * @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.
- */
- private MetadataExtracter findBestExtracter(String sourceMimetype)
- {
- double bestReliability = -1;
- long bestTime = Long.MAX_VALUE;
- logger.debug("Finding best extracter for " + sourceMimetype);
-
- MetadataExtracter bestExtracter = null;
-
- for (MetadataExtracter ext : extracters)
- {
- double r = ext.getReliability(sourceMimetype);
- if (r <= 0.0)
- {
- // extraction not achievable
- continue;
- }
- else if (r == bestReliability)
- {
- long time = ext.getExtractionTime();
- if (time < bestTime)
- {
- bestExtracter = ext;
- bestTime = time;
- }
- }
- else if (r > bestReliability)
- {
- bestExtracter = ext;
- bestReliability = r;
- bestTime = ext.getExtractionTime();
- }
- }
- return bestExtracter;
- }
+/*
+ * Copyright (C) 2005 Jesper Steen Møller
+ *
+ * Licensed under the Mozilla Public License version 1.1
+ * with a permitted attribution clause. You may obtain a
+ * copy of the License at
+ *
+ * http://www.alfresco.org/legal/license.txt
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the
+ * License.
+ */
+package org.alfresco.repo.content.metadata;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Holds and provides the most appropriate metadate extracter for a particular
+ * mimetype.
+ *
+ * The extracters themselves know how well they are able to extract metadata.
+ *
+ * @see org.alfresco.repo.content.metadata.MetadataExtracter
+ * @author Jesper Steen Møller
+ */
+public class MetadataExtracterRegistry
+{
+ private static final Log logger = LogFactory.getLog(MetadataExtracterRegistry.class);
+
+ private List extracters;
+ private Map extracterCache;
+
+ /** Controls read access to the cache */
+ private Lock extracterCacheReadLock;
+ /** controls write access to the cache */
+ private Lock extracterCacheWriteLock;
+
+ public MetadataExtracterRegistry()
+ {
+ // initialise lists
+ extracters = new ArrayList(10);
+ extracterCache = new HashMap(17);
+
+ // create lock objects for access to the cache
+ ReadWriteLock extractionCacheLock = new ReentrantReadWriteLock();
+ extracterCacheReadLock = extractionCacheLock.readLock();
+ extracterCacheWriteLock = extractionCacheLock.writeLock();
+ }
+
+ /**
+ * Register an instance of an extracter for use
+ *
+ * @param extracter an extracter
+ */
+ public void register(MetadataExtracter extracter)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Registering metadata extracter: " + extracter);
+ }
+
+ extracterCacheWriteLock.lock();
+ try
+ {
+ extracters.add(extracter);
+ extracterCache.clear();
+ }
+ finally
+ {
+ extracterCacheWriteLock.unlock();
+ }
+ }
+
+ /**
+ * Gets the best metadata extracter. This is a combination of the most
+ * reliable and the most performant extracter.
+ *
+ * The result is cached for quicker access next time.
+ *
+ * @param mimetype the source MIME of the extraction
+ * @return Returns a metadata extracter that can extract metadata from the
+ * chosen MIME type.
+ */
+ public MetadataExtracter getExtracter(String sourceMimetype)
+ {
+ MetadataExtracter extracter = null;
+ extracterCacheReadLock.lock();
+ try
+ {
+ if (extracterCache.containsKey(sourceMimetype))
+ {
+ // the translation has been requested before
+ // it might have been null
+ return extracterCache.get(sourceMimetype);
+ }
+ }
+ finally
+ {
+ 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
+ {
+ // 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;
+ }
+ finally
+ {
+ extracterCacheWriteLock.unlock();
+ }
+ }
+
+ /**
+ * @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.
+ */
+ private MetadataExtracter findBestExtracter(String sourceMimetype)
+ {
+ double bestReliability = -1;
+ long bestTime = Long.MAX_VALUE;
+ logger.debug("Finding best extracter for " + sourceMimetype);
+
+ MetadataExtracter bestExtracter = null;
+
+ for (MetadataExtracter ext : extracters)
+ {
+ double r = ext.getReliability(sourceMimetype);
+ if (r <= 0.0)
+ {
+ // extraction not achievable
+ continue;
+ }
+ else if (r == bestReliability)
+ {
+ long time = ext.getExtractionTime();
+ if (time < bestTime)
+ {
+ bestExtracter = ext;
+ bestTime = time;
+ }
+ }
+ else if (r > bestReliability)
+ {
+ bestExtracter = ext;
+ bestReliability = r;
+ bestTime = ext.getExtractionTime();
+ }
+ }
+ return bestExtracter;
+ }
}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/content/metadata/OfficeMetadataExtracter.java b/source/java/org/alfresco/repo/content/metadata/OfficeMetadataExtracter.java
index 33cec55596..bd3af493a3 100644
--- a/source/java/org/alfresco/repo/content/metadata/OfficeMetadataExtracter.java
+++ b/source/java/org/alfresco/repo/content/metadata/OfficeMetadataExtracter.java
@@ -1,101 +1,101 @@
-/*
- * Copyright (C) 2005 Jesper Steen Møller
- *
- * Licensed under the Mozilla Public License version 1.1
- * with a permitted attribution clause. You may obtain a
- * copy of the License at
- *
- * http://www.alfresco.org/legal/license.txt
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the
- * License.
- */
-package org.alfresco.repo.content.metadata;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Map;
-
-import org.alfresco.model.ContentModel;
-import org.alfresco.repo.content.MimetypeMap;
-import org.alfresco.service.cmr.repository.ContentIOException;
-import org.alfresco.service.cmr.repository.ContentReader;
-import org.alfresco.service.namespace.QName;
-import org.apache.poi.hpsf.PropertySet;
-import org.apache.poi.hpsf.PropertySetFactory;
-import org.apache.poi.hpsf.SummaryInformation;
-import org.apache.poi.poifs.eventfilesystem.POIFSReader;
-import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
-import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
-
-/**
- * Office file format Metadata Extracter
- *
- * @author Jesper Steen Møller
- */
-public class OfficeMetadataExtracter extends AbstractMetadataExtracter
-{
- public static String[] SUPPORTED_MIMETYPES = new String[] {
- MimetypeMap.MIMETYPE_WORD,
- MimetypeMap.MIMETYPE_EXCEL,
- MimetypeMap.MIMETYPE_PPT};
-
- public OfficeMetadataExtracter()
- {
- super(new HashSet(Arrays.asList(SUPPORTED_MIMETYPES)), 1.0, 1000);
- }
-
- public void extractInternal(ContentReader reader, final Map destination) throws Throwable
- {
- POIFSReaderListener readerListener = new POIFSReaderListener()
- {
- public void processPOIFSReaderEvent(final POIFSReaderEvent event)
- {
- try
- {
- PropertySet ps = PropertySetFactory.create(event.getStream());
- if (ps instanceof SummaryInformation)
- {
- SummaryInformation si = (SummaryInformation) ps;
-
- // Titled aspect
- trimPut(ContentModel.PROP_TITLE, si.getTitle(), destination);
- trimPut(ContentModel.PROP_DESCRIPTION, si.getSubject(), destination);
-
- // Auditable aspect
- trimPut(ContentModel.PROP_CREATED, si.getCreateDateTime(), destination);
- trimPut(ContentModel.PROP_MODIFIED, si.getLastSaveDateTime(), destination);
- trimPut(ContentModel.PROP_AUTHOR, si.getAuthor(), destination);
- }
- }
- catch (Exception ex)
- {
- throw new ContentIOException("Property set stream: " + event.getPath() + event.getName(), ex);
- }
- }
- };
-
- InputStream is = null;
- try
- {
- is = reader.getContentInputStream();
- POIFSReader poiFSReader = new POIFSReader();
- poiFSReader.registerListener(readerListener, SummaryInformation.DEFAULT_STREAM_NAME);
- poiFSReader.read(is);
- }
- finally
- {
- if (is != null)
- {
- try { is.close(); } catch (IOException e) {}
- }
- }
- }
-}
+/*
+ * Copyright (C) 2005 Jesper Steen Møller
+ *
+ * Licensed under the Mozilla Public License version 1.1
+ * with a permitted attribution clause. You may obtain a
+ * copy of the License at
+ *
+ * http://www.alfresco.org/legal/license.txt
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the
+ * License.
+ */
+package org.alfresco.repo.content.metadata;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.service.cmr.repository.ContentIOException;
+import org.alfresco.service.cmr.repository.ContentReader;
+import org.alfresco.service.namespace.QName;
+import org.apache.poi.hpsf.PropertySet;
+import org.apache.poi.hpsf.PropertySetFactory;
+import org.apache.poi.hpsf.SummaryInformation;
+import org.apache.poi.poifs.eventfilesystem.POIFSReader;
+import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
+import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
+
+/**
+ * Office file format Metadata Extracter
+ *
+ * @author Jesper Steen Møller
+ */
+public class OfficeMetadataExtracter extends AbstractMetadataExtracter
+{
+ public static String[] SUPPORTED_MIMETYPES = new String[] {
+ MimetypeMap.MIMETYPE_WORD,
+ MimetypeMap.MIMETYPE_EXCEL,
+ MimetypeMap.MIMETYPE_PPT};
+
+ public OfficeMetadataExtracter()
+ {
+ super(new HashSet(Arrays.asList(SUPPORTED_MIMETYPES)), 1.0, 1000);
+ }
+
+ public void extractInternal(ContentReader reader, final Map destination) throws Throwable
+ {
+ POIFSReaderListener readerListener = new POIFSReaderListener()
+ {
+ public void processPOIFSReaderEvent(final POIFSReaderEvent event)
+ {
+ try
+ {
+ PropertySet ps = PropertySetFactory.create(event.getStream());
+ if (ps instanceof SummaryInformation)
+ {
+ SummaryInformation si = (SummaryInformation) ps;
+
+ // Titled aspect
+ trimPut(ContentModel.PROP_TITLE, si.getTitle(), destination);
+ trimPut(ContentModel.PROP_DESCRIPTION, si.getSubject(), destination);
+
+ // Auditable aspect
+ trimPut(ContentModel.PROP_CREATED, si.getCreateDateTime(), destination);
+ trimPut(ContentModel.PROP_MODIFIED, si.getLastSaveDateTime(), destination);
+ trimPut(ContentModel.PROP_AUTHOR, si.getAuthor(), destination);
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new ContentIOException("Property set stream: " + event.getPath() + event.getName(), ex);
+ }
+ }
+ };
+
+ InputStream is = null;
+ try
+ {
+ is = reader.getContentInputStream();
+ POIFSReader poiFSReader = new POIFSReader();
+ poiFSReader.registerListener(readerListener, SummaryInformation.DEFAULT_STREAM_NAME);
+ poiFSReader.read(is);
+ }
+ finally
+ {
+ if (is != null)
+ {
+ try { is.close(); } catch (IOException e) {}
+ }
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/content/metadata/PdfBoxMetadataExtracter.java b/source/java/org/alfresco/repo/content/metadata/PdfBoxMetadataExtracter.java
index 10b969f3e2..d3296920de 100644
--- a/source/java/org/alfresco/repo/content/metadata/PdfBoxMetadataExtracter.java
+++ b/source/java/org/alfresco/repo/content/metadata/PdfBoxMetadataExtracter.java
@@ -1,75 +1,75 @@
-/*
- * Copyright (C) 2005 Jesper Steen Møller
- *
- * Licensed under the Mozilla Public License version 1.1
- * with a permitted attribution clause. You may obtain a
- * copy of the License at
- *
- * http://www.alfresco.org/legal/license.txt
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the
- * License.
- */
-package org.alfresco.repo.content.metadata;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Serializable;
-import java.util.Calendar;
-import java.util.Map;
-
-import org.alfresco.model.ContentModel;
-import org.alfresco.repo.content.MimetypeMap;
-import org.alfresco.service.cmr.repository.ContentReader;
-import org.alfresco.service.namespace.QName;
-import org.pdfbox.pdmodel.PDDocument;
-import org.pdfbox.pdmodel.PDDocumentInformation;
-
-/**
- *
- * @author Jesper Steen Møller
- */
-public class PdfBoxMetadataExtracter extends AbstractMetadataExtracter
-{
- public PdfBoxMetadataExtracter()
- {
- super(MimetypeMap.MIMETYPE_PDF, 1.0, 1000);
- }
-
- public void extractInternal(ContentReader reader, Map destination) throws Throwable
- {
- PDDocument pdf = null;
- InputStream is = null;
- try
- {
- is = reader.getContentInputStream();
- // stream the document in
- pdf = PDDocument.load(is);
- // Scoop out the metadata
- PDDocumentInformation docInfo = pdf.getDocumentInformation();
-
- trimPut(ContentModel.PROP_AUTHOR, docInfo.getAuthor(), destination);
- trimPut(ContentModel.PROP_TITLE, docInfo.getTitle(), destination);
- trimPut(ContentModel.PROP_DESCRIPTION, docInfo.getSubject(), destination);
-
- Calendar created = docInfo.getCreationDate();
- if (created != null)
- destination.put(ContentModel.PROP_CREATED, created.getTime());
- }
- finally
- {
- if (is != null)
- {
- try { is.close(); } catch (IOException e) {}
- }
- if (pdf != null)
- {
- try { pdf.close(); } catch (Throwable e) { e.printStackTrace(); }
- }
- }
- }
-}
+/*
+ * Copyright (C) 2005 Jesper Steen Møller
+ *
+ * Licensed under the Mozilla Public License version 1.1
+ * with a permitted attribution clause. You may obtain a
+ * copy of the License at
+ *
+ * http://www.alfresco.org/legal/license.txt
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the
+ * License.
+ */
+package org.alfresco.repo.content.metadata;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.Calendar;
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.service.cmr.repository.ContentReader;
+import org.alfresco.service.namespace.QName;
+import org.pdfbox.pdmodel.PDDocument;
+import org.pdfbox.pdmodel.PDDocumentInformation;
+
+/**
+ *
+ * @author Jesper Steen Møller
+ */
+public class PdfBoxMetadataExtracter extends AbstractMetadataExtracter
+{
+ public PdfBoxMetadataExtracter()
+ {
+ super(MimetypeMap.MIMETYPE_PDF, 1.0, 1000);
+ }
+
+ public void extractInternal(ContentReader reader, Map destination) throws Throwable
+ {
+ PDDocument pdf = null;
+ InputStream is = null;
+ try
+ {
+ is = reader.getContentInputStream();
+ // stream the document in
+ pdf = PDDocument.load(is);
+ // Scoop out the metadata
+ PDDocumentInformation docInfo = pdf.getDocumentInformation();
+
+ trimPut(ContentModel.PROP_AUTHOR, docInfo.getAuthor(), destination);
+ trimPut(ContentModel.PROP_TITLE, docInfo.getTitle(), destination);
+ trimPut(ContentModel.PROP_DESCRIPTION, docInfo.getSubject(), destination);
+
+ Calendar created = docInfo.getCreationDate();
+ if (created != null)
+ destination.put(ContentModel.PROP_CREATED, created.getTime());
+ }
+ finally
+ {
+ if (is != null)
+ {
+ try { is.close(); } catch (IOException e) {}
+ }
+ if (pdf != null)
+ {
+ try { pdf.close(); } catch (Throwable e) { e.printStackTrace(); }
+ }
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/content/metadata/PdfBoxMetadataExtracterTest.java b/source/java/org/alfresco/repo/content/metadata/PdfBoxMetadataExtracterTest.java
index 70049a7e92..83cd43f7a5 100644
--- a/source/java/org/alfresco/repo/content/metadata/PdfBoxMetadataExtracterTest.java
+++ b/source/java/org/alfresco/repo/content/metadata/PdfBoxMetadataExtracterTest.java
@@ -1,43 +1,43 @@
-package org.alfresco.repo.content.metadata;
-
-import org.alfresco.repo.content.MimetypeMap;
-
-/**
- * @see org.alfresco.repo.content.metadata.PdfBoxMetadataExtracter
- *
- * @author Jesper Steen Møller
- */
-public class PdfBoxMetadataExtracterTest extends AbstractMetadataExtracterTest
-{
- private MetadataExtracter extracter;
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
- extracter = new PdfBoxMetadataExtracter();
- }
-
- /**
- * @return Returns the same transformer regardless - it is allowed
- */
- protected MetadataExtracter getExtracter()
- {
- return extracter;
- }
-
- public void testReliability() throws Exception
- {
- double reliability = 0.0;
- reliability = extracter.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN);
- assertEquals("Mimetype should not be supported", 0.0, reliability);
-
- reliability = extracter.getReliability(MimetypeMap.MIMETYPE_PDF);
- assertEquals("Mimetype should be supported", 1.0, reliability);
- }
-
- public void testPdfExtraction() throws Exception
- {
- testExtractFromMimetype(MimetypeMap.MIMETYPE_PDF);
- }
-}
+package org.alfresco.repo.content.metadata;
+
+import org.alfresco.repo.content.MimetypeMap;
+
+/**
+ * @see org.alfresco.repo.content.metadata.PdfBoxMetadataExtracter
+ *
+ * @author Jesper Steen Møller
+ */
+public class PdfBoxMetadataExtracterTest extends AbstractMetadataExtracterTest
+{
+ private MetadataExtracter extracter;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ extracter = new PdfBoxMetadataExtracter();
+ }
+
+ /**
+ * @return Returns the same transformer regardless - it is allowed
+ */
+ protected MetadataExtracter getExtracter()
+ {
+ return extracter;
+ }
+
+ public void testReliability() throws Exception
+ {
+ double reliability = 0.0;
+ reliability = extracter.getReliability(MimetypeMap.MIMETYPE_TEXT_PLAIN);
+ assertEquals("Mimetype should not be supported", 0.0, reliability);
+
+ reliability = extracter.getReliability(MimetypeMap.MIMETYPE_PDF);
+ assertEquals("Mimetype should be supported", 1.0, reliability);
+ }
+
+ public void testPdfExtraction() throws Exception
+ {
+ testExtractFromMimetype(MimetypeMap.MIMETYPE_PDF);
+ }
+}
diff --git a/source/java/org/alfresco/repo/content/transform/AbstractContentTransformer.java b/source/java/org/alfresco/repo/content/transform/AbstractContentTransformer.java
index ee82eac135..8369e61f94 100644
--- a/source/java/org/alfresco/repo/content/transform/AbstractContentTransformer.java
+++ b/source/java/org/alfresco/repo/content/transform/AbstractContentTransformer.java
@@ -252,13 +252,13 @@ public abstract class AbstractContentTransformer implements ContentTransformer
finally
{
// check that the reader and writer are both closed
- if (!reader.isClosed())
+ if (reader.isChannelOpen())
{
logger.error("Content reader not closed by transformer: \n" +
" reader: " + reader + "\n" +
" transformer: " + this);
}
- if (!writer.isClosed())
+ if (writer.isChannelOpen())
{
logger.error("Content writer not closed by transformer: \n" +
" writer: " + writer + "\n" +
diff --git a/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistry.java b/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistry.java
index 242499ffc4..8f370dbc47 100644
--- a/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistry.java
+++ b/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistry.java
@@ -25,11 +25,8 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
-import org.alfresco.error.AlfrescoRuntimeException;
-import org.alfresco.repo.content.MimetypeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.springframework.util.Assert;
/**
* Holds and provides the most appropriate content transformer for
@@ -47,7 +44,6 @@ public class ContentTransformerRegistry
private static final Log logger = LogFactory.getLog(ContentTransformerRegistry.class);
private List transformers;
- private MimetypeMap mimetypeMap;
/** Cache of previously used transactions */
private Map> transformationCache;
/** Controls read access to the transformation cache */
@@ -58,11 +54,8 @@ public class ContentTransformerRegistry
/**
* @param mimetypeMap all the mimetypes available to the system
*/
- public ContentTransformerRegistry(MimetypeMap mimetypeMap)
+ public ContentTransformerRegistry()
{
- Assert.notNull(mimetypeMap, "The MimetypeMap is mandatory");
- this.mimetypeMap = mimetypeMap;
-
this.transformers = new ArrayList(10);
transformationCache = new HashMap>(17);
@@ -143,16 +136,6 @@ public class ContentTransformerRegistry
*/
public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype)
{
- // check that the mimetypes are valid
- if (!mimetypeMap.getMimetypes().contains(sourceMimetype))
- {
- throw new AlfrescoRuntimeException("Unknown source mimetype: " + sourceMimetype);
- }
- if (!mimetypeMap.getMimetypes().contains(targetMimetype))
- {
- throw new AlfrescoRuntimeException("Unknown target mimetype: " + targetMimetype);
- }
-
TransformationKey key = new TransformationKey(sourceMimetype, targetMimetype);
List transformers = null;
transformationCacheReadLock.lock();
diff --git a/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistryTest.java b/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistryTest.java
index 0b0ac21f98..dac9c68c14 100644
--- a/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistryTest.java
+++ b/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistryTest.java
@@ -69,7 +69,7 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe
bytes[i] = (byte)i;
}
// create the dummyRegistry
- dummyRegistry = new ContentTransformerRegistry(mimetypeMap);
+ dummyRegistry = new ContentTransformerRegistry();
// create some dummy transformers for reliability tests
new DummyTransformer(mimetypeMap, dummyRegistry, A, B, 0.3, 10L);
new DummyTransformer(mimetypeMap, dummyRegistry, A, B, 0.6, 10L);
diff --git a/source/java/org/alfresco/repo/copy/CopyServiceImpl.java b/source/java/org/alfresco/repo/copy/CopyServiceImpl.java
index 352c58cd26..660847c5fa 100644
--- a/source/java/org/alfresco/repo/copy/CopyServiceImpl.java
+++ b/source/java/org/alfresco/repo/copy/CopyServiceImpl.java
@@ -536,7 +536,13 @@ public class CopyServiceImpl implements CopyService
ClassDefinition classDefinition = this.dictionaryService.getClass(classRef);
if (classDefinition != null)
{
- // Copy the properties
+ if (classDefinition.isAspect() == true)
+ {
+ // make sure any aspects without any properties or associations are copied
+ copyDetails.addAspect(classRef);
+ }
+
+ // Copy the properties
Map propertyDefinitions = classDefinition.getProperties();
for (QName propertyName : propertyDefinitions.keySet())
{
diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java b/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java
index efc473dc4d..50306137e4 100644
--- a/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java
+++ b/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java
@@ -18,7 +18,9 @@ package org.alfresco.repo.dictionary;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
@@ -52,8 +54,8 @@ public class DictionaryDAOImpl implements DictionaryDAO
// Namespace Data Access
private NamespaceDAO namespaceDAO;
- // Map of namespace to model name
- private Map namespaceToModel = new HashMap();
+ // Map of Namespace URI usages to Models
+ private Map> uriToModels = new HashMap>();
// Map of model name to compiled model
private Map compiledModels = new HashMap();
@@ -90,7 +92,11 @@ public class DictionaryDAOImpl implements DictionaryDAO
{
namespaceDAO.removePrefix(namespace.getPrefix());
namespaceDAO.removeURI(namespace.getUri());
- namespaceToModel.remove(namespace.getUri());
+ unmapUriToModel(namespace.getUri(), previousVersion);
+ }
+ for (M2Namespace importNamespace : previousVersion.getM2Model().getImports())
+ {
+ unmapUriToModel(importNamespace.getUri(), previousVersion);
}
}
@@ -99,7 +105,11 @@ public class DictionaryDAOImpl implements DictionaryDAO
{
namespaceDAO.addURI(namespace.getUri());
namespaceDAO.addPrefix(namespace.getPrefix(), namespace.getUri());
- namespaceToModel.put(namespace.getUri(), modelName);
+ mapUriToModel(namespace.getUri(), compiledModel);
+ }
+ for (M2Namespace importNamespace : model.getImports())
+ {
+ mapUriToModel(importNamespace.getUri(), compiledModel);
}
// Publish new Model Definition
@@ -115,6 +125,7 @@ public class DictionaryDAOImpl implements DictionaryDAO
}
}
+
/**
* @see org.alfresco.repo.dictionary.DictionaryDAO#removeModel(org.alfresco.service.namespace.QName)
*/
@@ -129,7 +140,7 @@ public class DictionaryDAOImpl implements DictionaryDAO
{
namespaceDAO.removePrefix(namespace.getPrefix());
namespaceDAO.removeURI(namespace.getUri());
- namespaceToModel.remove(namespace.getUri());
+ unmapUriToModel(namespace.getUri(), compiledModel);
}
// Remove the model from the list
@@ -137,18 +148,61 @@ public class DictionaryDAOImpl implements DictionaryDAO
}
}
+
+ /**
+ * Map Namespace URI to Model
+ *
+ * @param uri namespace uri
+ * @param model model
+ */
+ private void mapUriToModel(String uri, CompiledModel model)
+ {
+ List models = uriToModels.get(uri);
+ if (models == null)
+ {
+ models = new ArrayList();
+ uriToModels.put(uri, models);
+ }
+ if (!models.contains(model))
+ {
+ models.add(model);
+ }
+ }
+
/**
- * @param uri the namespace uri
- * @return the compiled model which defines the specified namespace
+ * Unmap Namespace URI from Model
+ *
+ * @param uri namespace uri
+ * @param model model
*/
- private CompiledModel getCompiledModelForNamespace(String uri)
+ private void unmapUriToModel(String uri, CompiledModel model)
{
- QName modelName = namespaceToModel.get(uri);
- return (modelName == null) ? null : getCompiledModel(modelName);
+ List models = uriToModels.get(uri);
+ if (models != null)
+ {
+ models.remove(model);
+ }
+ }
+
+
+ /**
+ * Get Models mapped to Namespace Uri
+ *
+ * @param uri namespace uri
+ * @return mapped models
+ */
+ private List getModelsForUri(String uri)
+ {
+ List models = uriToModels.get(uri);
+ if (models == null)
+ {
+ models = Collections.emptyList();
+ }
+ return models;
}
-
+
/**
* @param modelName the model name
* @return the compiled model of the given name
@@ -170,8 +224,16 @@ public class DictionaryDAOImpl implements DictionaryDAO
*/
public DataTypeDefinition getDataType(QName typeName)
{
- CompiledModel model = getCompiledModelForNamespace(typeName.getNamespaceURI());
- return (model == null) ? null : model.getDataType(typeName);
+ List models = getModelsForUri(typeName.getNamespaceURI());
+ for (CompiledModel model : models)
+ {
+ DataTypeDefinition dataType = model.getDataType(typeName);
+ if (dataType != null)
+ {
+ return dataType;
+ }
+ }
+ return null;
}
@@ -207,8 +269,16 @@ public class DictionaryDAOImpl implements DictionaryDAO
*/
public TypeDefinition getType(QName typeName)
{
- CompiledModel model = getCompiledModelForNamespace(typeName.getNamespaceURI());
- return (model == null) ? null : model.getType(typeName);
+ List models = getModelsForUri(typeName.getNamespaceURI());
+ for (CompiledModel model : models)
+ {
+ TypeDefinition type = model.getType(typeName);
+ if (type != null)
+ {
+ return type;
+ }
+ }
+ return null;
}
@@ -217,8 +287,16 @@ public class DictionaryDAOImpl implements DictionaryDAO
*/
public AspectDefinition getAspect(QName aspectName)
{
- CompiledModel model = getCompiledModelForNamespace(aspectName.getNamespaceURI());
- return (model == null) ? null : model.getAspect(aspectName);
+ List models = getModelsForUri(aspectName.getNamespaceURI());
+ for (CompiledModel model : models)
+ {
+ AspectDefinition aspect = model.getAspect(aspectName);
+ if (aspect != null)
+ {
+ return aspect;
+ }
+ }
+ return null;
}
@@ -227,8 +305,16 @@ public class DictionaryDAOImpl implements DictionaryDAO
*/
public ClassDefinition getClass(QName className)
{
- CompiledModel model = getCompiledModelForNamespace(className.getNamespaceURI());
- return (model == null) ? null : model.getClass(className);
+ List models = getModelsForUri(className.getNamespaceURI());
+ for (CompiledModel model : models)
+ {
+ ClassDefinition classDef = model.getClass(className);
+ if (classDef != null)
+ {
+ return classDef;
+ }
+ }
+ return null;
}
@@ -237,23 +323,52 @@ public class DictionaryDAOImpl implements DictionaryDAO
*/
public PropertyDefinition getProperty(QName propertyName)
{
- CompiledModel model = getCompiledModelForNamespace(propertyName.getNamespaceURI());
- return (model == null) ? null : model.getProperty(propertyName);
+ List models = getModelsForUri(propertyName.getNamespaceURI());
+ for (CompiledModel model : models)
+ {
+ PropertyDefinition propDef = model.getProperty(propertyName);
+ if (propDef != null)
+ {
+ return propDef;
+ }
+ }
+ return null;
}
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.dictionary.ModelQuery#getConstraint(org.alfresco.service.namespace.QName)
+ */
public ConstraintDefinition getConstraint(QName constraintQName)
{
- CompiledModel model = getCompiledModelForNamespace(constraintQName.getNamespaceURI());
- return (model == null) ? null : model.getConstraint(constraintQName);
+ List models = getModelsForUri(constraintQName.getNamespaceURI());
+ for (CompiledModel model : models)
+ {
+ ConstraintDefinition constraintDef = model.getConstraint(constraintQName);
+ if (constraintDef != null)
+ {
+ return constraintDef;
+ }
+ }
+ return null;
}
+
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getAssociation(org.alfresco.repo.ref.QName)
*/
public AssociationDefinition getAssociation(QName assocName)
{
- CompiledModel model = getCompiledModelForNamespace(assocName.getNamespaceURI());
- return (model == null) ? null : model.getAssociation(assocName);
+ List models = getModelsForUri(assocName.getNamespaceURI());
+ for (CompiledModel model : models)
+ {
+ AssociationDefinition assocDef = model.getAssociation(assocName);
+ if (assocDef != null)
+ {
+ return assocDef;
+ }
+ }
+ return null;
}
diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryDAOTest.java b/source/java/org/alfresco/repo/dictionary/DictionaryDAOTest.java
index bae285a5ea..1552ef870f 100644
--- a/source/java/org/alfresco/repo/dictionary/DictionaryDAOTest.java
+++ b/source/java/org/alfresco/repo/dictionary/DictionaryDAOTest.java
@@ -36,7 +36,6 @@ import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
-import org.alfresco.service.namespace.RegexQNamePattern;
public class DictionaryDAOTest extends TestCase
@@ -186,6 +185,15 @@ public class DictionaryDAOTest extends TestCase
ClassDefinition fileClassDef = service.getClass(testFileQName);
assertTrue("File type should have the archive flag", fileClassDef.isArchive());
+ QName testFileDerivedQName = QName.createQName(TEST_URL, "file-derived");
+ ClassDefinition fileDerivedClassDef = service.getClass(testFileDerivedQName);
+ assertTrue("Direct derived File type should have the archive flag", fileDerivedClassDef.isArchive());
+
+ QName testFileDerivedNoArchiveQName = QName.createQName(TEST_URL, "file-derived-no-archive");
+ ClassDefinition fileDerivedNoArchiveClassDef = service.getClass(testFileDerivedNoArchiveQName);
+ assertFalse("Derived File with archive override type should NOT have the archive flag",
+ fileDerivedNoArchiveClassDef.isArchive());
+
QName testFolderQName = QName.createQName(TEST_URL, "folder");
ClassDefinition folderClassDef = service.getClass(testFolderQName);
assertFalse("Folder type should not have the archive flag", folderClassDef.isArchive());
diff --git a/source/java/org/alfresco/repo/dictionary/M2Class.java b/source/java/org/alfresco/repo/dictionary/M2Class.java
index 7cece04111..a08f4dd88c 100644
--- a/source/java/org/alfresco/repo/dictionary/M2Class.java
+++ b/source/java/org/alfresco/repo/dictionary/M2Class.java
@@ -32,7 +32,7 @@ public abstract class M2Class
private String title = null;
private String description = null;
private String parentName = null;
- private boolean archive = false;
+ private Boolean archive = null;
private List properties = new ArrayList();
private List propertyOverrides = new ArrayList();
@@ -92,14 +92,14 @@ public abstract class M2Class
}
- public boolean isArchive()
+ public Boolean getArchive()
{
return archive;
}
public void setArchive(boolean archive)
{
- this.archive = archive;
+ this.archive = Boolean.valueOf(archive);
}
public M2Property createProperty(String name)
diff --git a/source/java/org/alfresco/repo/dictionary/M2ClassDefinition.java b/source/java/org/alfresco/repo/dictionary/M2ClassDefinition.java
index 7b759472de..0fd69bcda6 100644
--- a/source/java/org/alfresco/repo/dictionary/M2ClassDefinition.java
+++ b/source/java/org/alfresco/repo/dictionary/M2ClassDefinition.java
@@ -46,7 +46,6 @@ import org.alfresco.service.namespace.QName;
protected M2Class m2Class;
protected QName name;
protected QName parentName = null;
- protected boolean archive = false;
private Map propertyOverrides = new HashMap();
private Map properties = new HashMap();
@@ -57,8 +56,9 @@ import org.alfresco.service.namespace.QName;
private List defaultAspects = new ArrayList();
private List defaultAspectNames = new ArrayList();
private List inheritedDefaultAspects = new ArrayList();
+ private Boolean archive = null;
+ private Boolean inheritedArchive = null;
-
/**
* Construct
*
@@ -74,7 +74,7 @@ import org.alfresco.service.namespace.QName;
// Resolve Names
this.name = QName.createQName(m2Class.getName(), resolver);
- this.archive = m2Class.isArchive();
+ this.archive = m2Class.getArchive();
if (m2Class.getParentName() != null && m2Class.getParentName().length() > 0)
{
this.parentName = QName.createQName(m2Class.getParentName(), resolver);
@@ -280,6 +280,13 @@ import org.alfresco.service.namespace.QName;
inheritedDefaultAspects.add(def);
}
}
+
+ // resolve archive inheritance
+ if (parentClass != null && archive == null)
+ {
+ // archive not explicitly set on this class and there is a parent class
+ inheritedArchive = ((M2ClassDefinition)parentClass).isArchive();
+ }
}
/* (non-Javadoc)
@@ -340,8 +347,23 @@ import org.alfresco.service.namespace.QName;
return (m2Class instanceof M2Aspect);
}
+ /**
+ * @return Returns the archive flag, which defaults to false
+ */
public boolean isArchive()
{
+ if (archive == null)
+ {
+ if (inheritedArchive != null)
+ {
+ return inheritedArchive.booleanValue();
+ }
+ else
+ {
+ // default to false
+ return false;
+ }
+ }
return archive;
}
diff --git a/source/java/org/alfresco/repo/dictionary/dictionarydaotest_model.xml b/source/java/org/alfresco/repo/dictionary/dictionarydaotest_model.xml
index 32e074b425..fc8748f662 100644
--- a/source/java/org/alfresco/repo/dictionary/dictionarydaotest_model.xml
+++ b/source/java/org/alfresco/repo/dictionary/dictionarydaotest_model.xml
@@ -150,6 +150,15 @@
+
+ test:file
+
+
+
+ test:file
+ false
+
+
test:base
diff --git a/source/java/org/alfresco/repo/importer/importercomponent_test.xml b/source/java/org/alfresco/repo/importer/importercomponent_test.xml
index 27b6dd6200..d5fd119201 100644
--- a/source/java/org/alfresco/repo/importer/importercomponent_test.xml
+++ b/source/java/org/alfresco/repo/importer/importercomponent_test.xml
@@ -15,7 +15,6 @@
System
- true
diff --git a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java
index aefc09f3e1..3fbf309946 100644
--- a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java
+++ b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java
@@ -70,7 +70,7 @@ public class FileFolderServiceImpl implements FileFolderService
"[not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" +
" and (subtypeOf('" + ContentModel.TYPE_FOLDER + "'))]";
- /** Shallow search for all files and folders */
+ /** Shallow search for files and folders with a name pattern */
private static final String XPATH_QUERY_SHALLOW_ALL =
"./*" +
"[like(@cm:name, $cm:name, false)" +
diff --git a/source/java/org/alfresco/repo/node/TemporaryAspect.java b/source/java/org/alfresco/repo/node/TemporaryAspect.java
new file mode 100644
index 0000000000..ca8a5610fb
--- /dev/null
+++ b/source/java/org/alfresco/repo/node/TemporaryAspect.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2005 Alfresco, Inc.
+ *
+ * Licensed under the Mozilla Public License version 1.1
+ * with a permitted attribution clause. You may obtain a
+ * copy of the License at
+ *
+ * http://www.alfresco.org/legal/license.txt
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the
+ * License.
+ */
+package org.alfresco.repo.node;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.copy.CopyServicePolicies;
+import org.alfresco.repo.policy.JavaBehaviour;
+import org.alfresco.repo.policy.PolicyComponent;
+import org.alfresco.repo.policy.PolicyScope;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * Registers and contains the behaviour specific to the
+ * {@link org.alfresco.model.ContentModel#ASPECT_TEMPORARY temporary aspect}.
+ *
+ * @author gavinc
+ */
+public class TemporaryAspect implements CopyServicePolicies.OnCopyNodePolicy
+{
+ // Dependencies
+ private PolicyComponent policyComponent;
+
+ /**
+ * @param policyComponent the policy component to register behaviour with
+ */
+ public void setPolicyComponent(PolicyComponent policyComponent)
+ {
+ this.policyComponent = policyComponent;
+ }
+
+ /**
+ * Initialise the Temporary Aspect
+ *
+ * Ensures that the {@link ContentModel#ASPECT_TEMPORARY temporary aspect}
+ * copy behaviour is disabled when update copies are performed.
+ */
+ public void init()
+ {
+ // disable copy for referencable aspect
+ this.policyComponent.bindClassBehaviour(
+ QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyNode"),
+ ContentModel.ASPECT_TEMPORARY,
+ new JavaBehaviour(this, "onCopyNode"));
+ }
+
+ /**
+ * Does nothing
+ */
+ public void onCopyNode(
+ QName classRef,
+ NodeRef sourceNodeRef,
+ StoreRef destinationStoreRef,
+ boolean copyToNewNode,
+ PolicyScope copyDetails)
+ {
+ if (copyToNewNode)
+ {
+ copyDetails.addAspect(ContentModel.ASPECT_TEMPORARY);
+ }
+ else
+ {
+ // don't copy if this is an update operation
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
index ab9b11dead..18a54f4682 100644
--- a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
+++ b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
@@ -645,10 +645,11 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
public void deleteNode(NodeRef nodeRef)
{
- boolean isArchivedNode = false;
+ boolean isArchivedNode = false;
+ boolean requiresDelete = false;
- // Invoke policy behaviours
- invokeBeforeDeleteNode(nodeRef);
+ // Invoke policy behaviours
+ invokeBeforeDeleteNode(nodeRef);
// get the node
Node node = getNodeNotNull(nodeRef);
@@ -659,11 +660,27 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
Set nodeAspectQNames = node.getAspects();
// check if we need to archive the node
- StoreRef storeRef = nodeRef.getStoreRef();
- StoreRef archiveStoreRef = storeArchiveMap.getArchiveMap().get(storeRef);
- // get the type and check if we need archiving
- TypeDefinition typeDef = dictionaryService.getType(node.getTypeQName());
- if (typeDef == null || !typeDef.isArchive() || archiveStoreRef == null)
+ StoreRef archiveStoreRef = null;
+ if (nodeAspectQNames.contains(ContentModel.ASPECT_TEMPORARY))
+ {
+ // the node has the temporary aspect meaning
+ // it can not be archived
+ requiresDelete = true;
+ isArchivedNode = false;
+ }
+ else
+ {
+ StoreRef storeRef = nodeRef.getStoreRef();
+ archiveStoreRef = storeArchiveMap.getArchiveMap().get(storeRef);
+ // get the type and check if we need archiving
+ TypeDefinition typeDef = dictionaryService.getType(node.getTypeQName());
+ if (typeDef == null || !typeDef.isArchive() || archiveStoreRef == null)
+ {
+ requiresDelete = true;
+ }
+ }
+
+ if (requiresDelete)
{
// perform a normal deletion
nodeDaoService.deleteNode(node, true);
diff --git a/source/java/org/alfresco/repo/security/permissions/impl/ExceptionTranslatorMethodInterceptor.java b/source/java/org/alfresco/repo/security/permissions/impl/ExceptionTranslatorMethodInterceptor.java
index ff6e421707..fc9a769f05 100644
--- a/source/java/org/alfresco/repo/security/permissions/impl/ExceptionTranslatorMethodInterceptor.java
+++ b/source/java/org/alfresco/repo/security/permissions/impl/ExceptionTranslatorMethodInterceptor.java
@@ -27,6 +27,7 @@ import org.springframework.dao.InvalidDataAccessApiUsageException;
public class ExceptionTranslatorMethodInterceptor implements MethodInterceptor
{
private static final String MSG_ACCESS_DENIED = "permissions.err_access_denied";
+ private static final String MSG_READ_ONLY = "permissions.err_read_only";
public ExceptionTranslatorMethodInterceptor()
{
@@ -46,7 +47,7 @@ public class ExceptionTranslatorMethodInterceptor implements MethodInterceptor
catch (InvalidDataAccessApiUsageException e)
{
// this usually occurs when the server is in read-only mode
- throw new AccessDeniedException(MSG_ACCESS_DENIED, e);
+ throw new AccessDeniedException(MSG_READ_ONLY, e);
}
}
}
diff --git a/source/java/org/alfresco/service/cmr/repository/ContentAccessor.java b/source/java/org/alfresco/service/cmr/repository/ContentAccessor.java
index 6d29a28f75..2100e13bd8 100644
--- a/source/java/org/alfresco/service/cmr/repository/ContentAccessor.java
+++ b/source/java/org/alfresco/service/cmr/repository/ContentAccessor.java
@@ -25,6 +25,13 @@ import org.alfresco.service.transaction.TransactionService;
*/
public interface ContentAccessor
{
+ /**
+ * Gets the open/close state of the underlying IO Channel.
+ *
+ * @return Returns true if the underlying IO Channel is open
+ */
+ public boolean isChannelOpen();
+
/**
* Use this method to register any interest in events against underlying
* content streams.