]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-6679: Added a Nuxeo listener to delete the original image file from media...
authorremillet <remillet@yahoo.com>
Mon, 1 Jun 2015 22:07:48 +0000 (15:07 -0700)
committerremillet <remillet@yahoo.com>
Mon, 1 Jun 2015 22:07:48 +0000 (15:07 -0700)
21 files changed:
3rdparty/nuxeo/nuxeo-platform-collectionspace/src/main/resources/OSGI-INF/core-types-contrib.xml
3rdparty/nuxeo/nuxeo-platform-listener/build.xml
3rdparty/nuxeo/nuxeo-platform-listener/pom.xml
3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/build.properties [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/build.xml [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/pom.xml [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/java/org/collectionspace/services/listener/UpdateImageDerivatives.java [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/META-INF/MANIFEST.MF [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/core-types-contrib.xml [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/default-life-cycle-contrib.xml [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/deployment-fragment.xml [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/ecm-types-contrib.xml [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/layouts-contrib.xml [new file with mode: 0644]
services/blob/service/src/main/java/org/collectionspace/services/blob/BlobResource.java
services/blob/service/src/main/java/org/collectionspace/services/blob/nuxeo/BlobDocumentModelHandler.java
services/citation/.gitignore [new file with mode: 0644]
services/citation/3rdparty/.gitignore [new file with mode: 0644]
services/common-api/src/main/java/org/collectionspace/services/common/api/CommonAPI.java
services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoBlobUtils.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocumentModelHandler.java
services/common/src/main/java/org/collectionspace/services/nuxeo/util/NuxeoUtils.java

index 7ef7f07d6649c042aa986b0a4aba45e596c9038e..a9c9cbcd711ba547d6ab4561ef987d253ff9b721 100644 (file)
@@ -1,21 +1,24 @@
 <?xml version="1.0"?>
 <component name="org.collectionspace.shared.core.types">
        <!-- A common ancestor for all CollectionSpace document types -->
-       <extension target="org.nuxeo.ecm.core.schema.TypeService"
-               point="doctype">
+       <extension target="org.nuxeo.ecm.core.schema.TypeService" point="doctype">
                <doctype name="CollectionSpaceDocument" extends="Document">
                        <schema name="common" />
                        <schema name="dublincore" />
                        <schema name="collectionspace_core" />
                </doctype>
+               
+               <!-- A facet for marking blobs/images that came from extern URLs -->
+           <facet name="URLSourcedPicture">
+           </facet>            
        </extension>
+       
        <!-- A schema def and doctype def for the "Subitem" document type. -->
-       <extension target="org.nuxeo.ecm.core.schema.TypeService"
-               point="schema">
+       <extension target="org.nuxeo.ecm.core.schema.TypeService" point="schema">
                <schema name="subitem" prefix="subitem" src="schemas/subitem.xsd" />
        </extension>
-       <extension target="org.nuxeo.ecm.core.schema.TypeService"
-               point="doctype">
+       
+       <extension target="org.nuxeo.ecm.core.schema.TypeService" point="doctype">
                <doctype name="Subitem" extends="CollectionSpaceDocument">
                        <schema name="common" />
                        <schema name="dublincore" />
index 7a0e8b1c4d5a4c57235e1a8e6c74cad22d54b6dd..c18b2b0db817c2c8ae296b8e4eb515b39dd14ee3 100644 (file)
             description="deploy nuxeo server libs to ${jee.server.cspace}">
         <ant antfile="updateobjectlocationonmove/build.xml" target="deploy" inheritall="false"/>
         <ant antfile="updaterelationsondelete/build.xml" target="deploy" inheritall="false"/>
+        <ant antfile="updateimagederivatives/build.xml" target="deploy" inheritall="false"/>
     </target>
 
     <target name="undeploy"
             description="undeploy nuxeo server libs from ${jee.server.cspace}">
         <ant antfile="updateobjectlocationonmove/build.xml" target="undeploy" inheritall="false"/>
         <ant antfile="updaterelationsondelete/build.xml" target="undeploy" inheritall="false"/>
+        <ant antfile="updateimagederivatives/build.xml" target="undeploy" inheritall="false"/>
     </target>
 
     <target name="dist"
             description="generate distribution for nuxeo server libs" depends="package">
         <ant antfile="updateobjectlocationonmove/build.xml" target="dist" inheritall="false"/>
         <ant antfile="updaterelationsondelete/build.xml" target="dist" inheritall="false"/>
+        <ant antfile="updateimagederivatives/build.xml" target="dist" inheritall="false"/>
     </target>
 
 </project>
index 0ca65fb730136f00124a43c474ba71356ab4b3d7..ff686aaf624fffd6325ffe264072c4a9f59858c1 100644 (file)
@@ -15,6 +15,7 @@
     <modules>
         <module>updateobjectlocationonmove</module>
         <module>updaterelationsondelete</module>
+        <module>updateimagederivatives</module>
     </modules>
 
     <dependencies>
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/build.properties b/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/build.properties
new file mode 100644 (file)
index 0000000..f4b4162
--- /dev/null
@@ -0,0 +1 @@
+listener.module.name=updateimagederivatives
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/build.xml b/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/build.xml
new file mode 100644 (file)
index 0000000..337cca2
--- /dev/null
@@ -0,0 +1,104 @@
+<project name="org.collectionspace.services.3rdparty.nuxeo.listener.updateimagederivatives">
+  <description>
+    CollectionSpace Nuxeo listener component type
+  </description>
+  <!-- Set global properties for this build -->
+  <property name="services.trunk" value="../../../.."/>
+  <!-- Environment should be declared before reading build.properties -->
+  <property environment="env" />
+  <!-- Set global properties for this build -->
+  <property file="${services.trunk}/build.properties" />
+  <!-- Set local properties for this build -->
+  <property file="build.properties" />
+  <property name="mvn.opts" value="-V" />
+  <property name="src" location="src"/>
+  <property name="build" location="build"/>
+  <property name="dist"  location="dist"/>
+
+  <!-- module.name variable is set in the local properties file -->
+  <property name="jar.name"
+    value="org.collectionspace.services.listener.${listener.module.name}-${cspace.release}.jar"/>
+
+  <property name="jar.all"
+    value="org.collectionspace.services.listener.${listener.module.name}-*.jar"/>
+  
+  <condition property="osfamily-unix">
+    <os family="unix" />
+  </condition>
+  <condition property="osfamily-windows">
+    <os family="windows" />
+  </condition>
+  
+  <target name="init" >
+    <!-- Create the time stamp -->
+    <tstamp/>
+    <!-- Create the build directory structure used by compile -->
+    <mkdir dir="${build}"/>
+  </target>
+  
+  <target name="package" depends="package-unix,package-windows"
+    description="Package CollectionSpace Services" />
+  <target name="package-unix" if="osfamily-unix">
+    <exec executable="mvn" failonerror="true">
+      <arg value="package" />
+      <arg value="-Dmaven.test.skip=true" />
+      <arg value="-f" />
+      <arg value="${basedir}/pom.xml" />
+      <arg value="-N" />
+      <arg value="${mvn.opts}" />
+    </exec>
+  </target>
+  <target name="package-windows" if="osfamily-windows">
+    <exec executable="cmd" failonerror="true">
+      <arg value="/c" />
+      <arg value="mvn.bat" />
+      <arg value="package" />
+      <arg value="-Dmaven.test.skip=true" />
+      <arg value="-f" />
+      <arg value="${basedir}/pom.xml" />
+      <arg value="-N" />
+      <arg value="${mvn.opts}" />
+    </exec>
+  </target>
+  
+  <target name="install" depends="install-unix,install-windows"
+    description="Install" />
+  <target name="install-unix" if="osfamily-unix">
+    <exec executable="mvn" failonerror="true">
+      <arg value="install" />
+      <arg value="-Dmaven.test.skip=true" />
+      <arg value="-f" />
+      <arg value="${basedir}/pom.xml" />
+      <arg value="-N" />
+      <arg value="${mvn.opts}" />
+    </exec>
+  </target>
+  <target name="install-windows" if="osfamily-windows">
+    <exec executable="cmd" failonerror="true">
+      <arg value="/c" />
+      <arg value="mvn.bat" />
+      <arg value="install" />
+      <arg value="-Dmaven.test.skip=true" />
+      <arg value="-f" />
+      <arg value="${basedir}/pom.xml" />
+      <arg value="-N" />
+      <arg value="${mvn.opts}" />
+    </exec>
+  </target>
+  
+  <target name="deploy" depends="install"
+    description="deploy collectionspace core doctype in ${jee.server.nuxeo}">
+    <copy file="${basedir}/target/${jar.name}"
+      todir="${jee.deploy.nuxeo.plugins}"/>
+  </target>
+  
+  <target name="undeploy"
+    description="undeploy collectionspace Thumbnail service from ${jee.server.nuxeo}">
+    <delete>
+      <fileset dir="${jee.deploy.nuxeo.plugins}">
+        <include name="${jar.all}"/>
+      </fileset>
+    </delete>
+  </target>
+  
+</project>
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/pom.xml b/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/pom.xml
new file mode 100644 (file)
index 0000000..4a490c5
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<project
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+    xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>org.collectionspace.services.3rdparty.nuxeo.listener</artifactId>
+        <groupId>org.collectionspace.services</groupId>
+        <version>4.2-SNAPSHOT</version>
+    </parent>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <artifactId>org.collectionspace.services.listener.updateimagederivatives</artifactId>
+    <name>org.collectionspace.services.listener.updateimagederivatives</name>
+    <url>http://maven.apache.org</url>
+
+        
+   <dependencies>
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.movement.service</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.client</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+       
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile> src/main/resources/META-INF/MANIFEST.MF </manifestFile>
+                        <manifestEntries>
+                            <Bundle-Version>${eclipseVersion}</Bundle-Version>
+                            <Bundle-ManifestVersion>2</Bundle-ManifestVersion>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+       
+</project>
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/java/org/collectionspace/services/listener/UpdateImageDerivatives.java b/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/java/org/collectionspace/services/listener/UpdateImageDerivatives.java
new file mode 100644 (file)
index 0000000..b73f7cc
--- /dev/null
@@ -0,0 +1,125 @@
+package org.collectionspace.services.listener;
+
+import java.io.Serializable;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.collectionspace.services.common.api.CommonAPI;
+import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
+import org.collectionspace.services.nuxeo.client.java.CoreSessionWrapper;
+import org.collectionspace.services.nuxeo.util.NuxeoUtils;
+import org.nuxeo.ecm.core.api.Blob;
+import org.nuxeo.ecm.core.api.ClientException;
+import org.nuxeo.ecm.core.api.DocumentModel;
+import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
+import org.nuxeo.ecm.core.api.blobholder.DocumentBlobHolder;
+//import org.nuxeo.ecm.core.api.event.DocumentEventTypes;
+import org.nuxeo.ecm.core.event.Event;
+import org.nuxeo.ecm.core.event.EventContext;
+import org.nuxeo.ecm.core.event.EventListener;
+import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
+//import org.nuxeo.ecm.platform.picture.api.ImagingDocumentConstants;
+import org.nuxeo.ecm.platform.picture.api.ImagingDocumentConstants;
+
+public class UpdateImageDerivatives implements EventListener {
+
+       // All Nuxeo sessions that get passed around to CollectionSpace code need to
+       // be wrapped inside of a CoreSessionWrapper. For example:
+       //              CoreSessionInterface coreSession = new
+       //              CoreSessionWrapper(docEventContext.getCoreSession());
+
+       // FIXME: We might experiment here with using log4j instead of Apache
+       // Commons Logging; am using the latter to follow Ray's pattern for now
+       private final static Log logger = LogFactory.getLog(UpdateImageDerivatives.class);
+
+       @Override
+       public void handleEvent(Event event) throws ClientException {
+               if (logger.isTraceEnabled()) {
+                       logger.trace(String.format("Entering handleEvent in '%s'...", getClass().getName()));
+               }
+
+               if (shouldProcessEvent(event) == true) {
+                       DocumentEventContext docEventContext = (DocumentEventContext) event.getContext();
+                       DocumentModel docModel = docEventContext.getSourceDocument();
+
+                       String eventType = event.getName();
+                       if (logger.isTraceEnabled()) {
+                               logger.trace(String.format("A(n) '%s' event was received by the %s event listener.",
+                                                               eventType, getClass().getName()));
+                               //logg
+                       }
+
+                       String source = (String)docModel.getProperty(CommonAPI.NUXEO_DUBLINCORE_SCHEMANAME,
+                                       CommonAPI.NUXEO_DUBLINCORE_SOURCE);
+
+                       if (source != null && source.equalsIgnoreCase(CommonAPI.URL_SOURCED_PICTURE)) {
+                               CoreSessionInterface nuxeoSession = new CoreSessionWrapper(docEventContext.getCoreSession());
+                               purgeOriginalImage(docModel, nuxeoSession);
+                               nuxeoSession.save();
+                       } else {
+                               if (logger.isTraceEnabled()) {
+                                       logger.trace(String.format("The Nuxeo document titled '%s' did not need processing by the '%s' Nuxeo listener.",
+                                                                       docModel.getTitle(), getClass().getName()));
+                               }
+                       }
+               }
+
+               if (logger.isTraceEnabled()) {
+                       logger.trace(String.format("Exiting handleEvent in '%s'.", getClass().getName()));
+               }
+       }
+
+       private void purgeOriginalImage(DocumentModel docModel, CoreSessionInterface nuxeoSession) {
+               //
+               // Empty the document model's "content" property -this does not delete the actual file/blob it
+               // just disassociates the blob content (aka, the orginal image) from the document.
+               //
+               docModel.setPropertyValue("file:content", (Serializable) null);
+               
+               //
+               // Removing this facet ensures the original derivatives are unchanged when
+               // we call the save method.  If we didn't remove the face, then all the
+               // image derivatives would be disassociated with the document.  We want to keep
+               // the derivatives.
+               //
+               NuxeoUtils.removeFacet(docModel, ImagingDocumentConstants.PICTURE_FACET);
+               nuxeoSession.saveDocument(docModel); // persist the disassociation of the original blob/image
+               //
+               // Now that we've emptied the document model's content field, we can add back the Picture facet so
+               // Nuxeo will still tread this document as a Picture document.
+               //
+               NuxeoUtils.addFacet(docModel, ImagingDocumentConstants.PICTURE_FACET);
+               
+               //
+               // Finally, we need to remove the actual blob/image bits that are store on disk.
+               //
+               DocumentBlobHolder docBlobHolder = (DocumentBlobHolder) docModel.getAdapter(BlobHolder.class);
+               Blob blob = docBlobHolder.getBlob();            
+               if (blob == null) {
+                       logger.error(String.format("Could not get blob for original image. Trying to delete original for: '%s'",
+                                                       docModel.getTitle()));
+               } else {
+                       Thread thread = NuxeoUtils.deleteFileOfBlobAsync(blob);
+                       logger.debug(String.format("Started thread '%s' to delete file of blob '%s'.",
+                                       thread.getId(), blob.getFilename()));
+               }
+               
+               if (logger.isTraceEnabled()) {
+                       logger.trace(String.format("Exiting handleEvent in '%s'.", getClass().getName()));                      
+               }       
+       }
+       
+       private boolean shouldProcessEvent(Event event) {
+               boolean result = false;
+
+               EventContext eventContext = event.getContext();
+               if (eventContext != null) {
+                       if (eventContext instanceof DocumentEventContext) {
+                               result = true;
+                       }
+               }
+
+               return result;
+       }
+
+}
\ No newline at end of file
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/META-INF/MANIFEST.MF b/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..3b949c5
--- /dev/null
@@ -0,0 +1,16 @@
+Manifest-Version: 1.0 
+Bundle-ManifestVersion: 1 
+Bundle-Name: org.collectionspace.services.listener.updateimagederivatives
+Bundle-SymbolicName: org.collectionspace.services.listener.updateimagederivatives;singleton:=true 
+Bundle-Version: 1.0.0
+Bundle-Localization: plugin
+Bundle-Vendor: Nuxeo
+Require-Bundle: org.nuxeo.runtime, 
+ org.nuxeo.ecm.core.api,
+ org.nuxeo.ecm.core,
+ org.nuxeo.ecm.webapp.core
+Provide-Package: org.collectionspace.services.listener.updateimagederivatives
+Nuxeo-Component: OSGI-INF/core-types-contrib.xml,
+ OSGI-INF/default-life-cycle-contrib.xml,
+ OSGI-INF/ecm-types-contrib.xml,
+ OSGI-INF/layouts-contrib.xml
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/core-types-contrib.xml b/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/core-types-contrib.xml
new file mode 100644 (file)
index 0000000..0ed2760
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<component name="org.collectionspace.services.listener.updateimagederivatives.core.types">
+    <!-- This page intentionally left blank -->
+</component>
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/default-life-cycle-contrib.xml b/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/default-life-cycle-contrib.xml
new file mode 100644 (file)
index 0000000..6c33c2a
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<component name="org.collectionspace.services.listener.updateimagederivatives.LifeCycle">
+    <!-- This page intentionally left blank -->
+</component>
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/deployment-fragment.xml b/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/deployment-fragment.xml
new file mode 100644 (file)
index 0000000..270abbd
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<fragment>
+
+  <extension target="application#MODULE">
+    <module>
+      <java>${bundle.fileName}</java>
+    </module>
+  </extension>
+  
+</fragment>
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/ecm-types-contrib.xml b/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/ecm-types-contrib.xml
new file mode 100644 (file)
index 0000000..2d650fe
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<component     name="org.collectionspace.services.listener.updateimagederivatives.ecm.types">
+       <extension target="org.nuxeo.ecm.core.event.EventServiceComponent"
+               point="listener">
+               <listener name="updateimagederivativeslistener" async="true"
+                       postCommit="true"
+                       class="org.collectionspace.services.listener.UpdateImageDerivatives">
+                       <event>pictureViewsGenerationDone</event>
+               </listener>
+       </extension>
+</component>
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/layouts-contrib.xml b/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/resources/OSGI-INF/layouts-contrib.xml
new file mode 100644 (file)
index 0000000..e7bab84
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<component name="org.collectionspace.services.listener.updateimagederivatives.layouts.webapp">
+       <!-- This page intentionally left blank -->
+</component>
index be4121244b24ee80c7a87d16894a1db85a20d78a..185f4b32d8f5c9c4983a4987d59e32b165d2b5cc 100644 (file)
@@ -145,9 +145,10 @@ public class BlobResource extends NuxeoBasedResource {
        }
        
        if (result == null) {
+               String errMsg = String.format("Index failed. Could not get the contents for the Blob with CSID = '%s'.",
+                               csid);
                Response response = Response.status(
-                       Response.Status.INTERNAL_SERVER_ERROR).entity(
-                                       "Index failed. Could not get the contents for the Blob.").type("text/plain").build();
+                       Response.Status.INTERNAL_SERVER_ERROR).entity(errMsg).type("text/plain").build();
                throw new CSWebApplicationException(response);
        }
        
index 679dce1b8d5814e67cfd03e5e9b653a8ca5c4cd0..63162ed3efcdf3d712eea309fe4e33cafbb75e94 100644 (file)
@@ -166,9 +166,7 @@ extends NuxeoDocumentModelHandler<BlobsCommon> {
                                if (blobOutput != null) {
                                        blobInput.setContentStream(blobOutput.getBlobInputStream());
                                } else {
-                                       // If we can't find the blob's content, we'll return a "missing document" image
-                                       blobInput.setContentStream(NuxeoBlobUtils.getResource(NuxeoBlobUtils.DOCUMENT_MISSING_PLACEHOLDER_IMAGE));
-                                       mimeTypeBuffer.append(NuxeoBlobUtils.MIME_JPEG);
+                                       blobInput.setContentStream(null);
                                }
                        }
        
diff --git a/services/citation/.gitignore b/services/citation/.gitignore
new file mode 100644 (file)
index 0000000..ae3c172
--- /dev/null
@@ -0,0 +1 @@
+/bin/
diff --git a/services/citation/3rdparty/.gitignore b/services/citation/3rdparty/.gitignore
new file mode 100644 (file)
index 0000000..ae3c172
--- /dev/null
@@ -0,0 +1 @@
+/bin/
index 0e8819ff5a306ec735e99481e77b213fd67fa53e..263fe5efed62c1253b95795b0501986e204ed2b0 100644 (file)
@@ -18,6 +18,15 @@ public class CommonAPI {
     
        public static final String GENERATE_BUNDLES = "core";
        public static final String GENERATE_BINDINGS = "delta";
-
+       
+       //
+       // A Nuxeo facet that let's us know whether or not the image/picture was sourced
+       // from an external URL.
+       //
+    public static final String URL_SOURCED_PICTURE = "URLSourcedPicture";
+    public static final String NUXEO_DUBLINCORE_SCHEMANAME = "dublincore";
+    public static final String NUXEO_DUBLINCORE_TITLE = "title";
+    public static final String NUXEO_DUBLINCORE_SOURCE = "source";
+    
 }
 
index 2a537c2578289c70ae2351059622a3371aae7691..0ff0988c46bfbacb4fa4583bd98a9d1451a3c244 100644 (file)
@@ -38,7 +38,6 @@ import java.util.List;
 import java.util.Map;
 
 import org.nuxeo.runtime.api.Framework;
-
 import org.nuxeo.ecm.platform.picture.api.ImageInfo;
 import org.nuxeo.ecm.platform.picture.api.ImagingDocumentConstants;
 import org.nuxeo.ecm.platform.picture.api.ImagingService;
@@ -51,7 +50,6 @@ import org.nuxeo.ecm.platform.filemanager.service.FileManagerService;
 import org.nuxeo.ecm.platform.filemanager.service.extension.FileImporter;
 import org.nuxeo.ecm.platform.filemanager.utils.FileManagerUtils;
 import org.nuxeo.ecm.platform.types.TypeManager;
-
 import org.nuxeo.ecm.core.api.CoreSession;
 import org.nuxeo.ecm.core.api.IdRef;
 import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
@@ -62,12 +60,10 @@ import org.nuxeo.ecm.core.api.Blob;
 import org.nuxeo.ecm.core.api.ClientException;
 import org.nuxeo.ecm.core.api.DocumentModel;
 import org.nuxeo.ecm.core.api.DocumentRef;
-
+import org.nuxeo.ecm.core.api.VersioningOption;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
 import org.apache.commons.io.IOUtils;
-
 import org.collectionspace.services.client.PoxPayloadIn;
 import org.collectionspace.services.client.PoxPayloadOut;
 import org.collectionspace.services.common.FileUtils;
@@ -76,6 +72,7 @@ import org.collectionspace.services.common.blob.BlobInput;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.TransactionException;
 import org.collectionspace.services.common.repository.RepositoryClient;
+import org.collectionspace.services.common.api.CommonAPI;
 import org.collectionspace.services.common.api.GregorianCalendarDateTimeUtils;
 import org.collectionspace.services.common.blob.BlobOutput;
 import org.collectionspace.services.blob.BlobsCommon;
@@ -106,6 +103,8 @@ public class NuxeoBlobUtils {
        //
        private static final int MAX_IMAGE_BUFFER = 256 * 1024; // REM: 11/26/2013 - This should be set in a config/property file.
        
+
+       
        //
        // File name constants
        //
@@ -607,7 +606,7 @@ public class NuxeoBlobUtils {
                        // image derivatives.
                        //
                        result = getFileManager().createDocumentFromBlob(
-                                       repoSession.getCoreSession(), inputStreamBlob, blobLocation, true, blobName);
+                                       repoSession.getCoreSession(), inputStreamBlob, blobLocation, overwrite, blobName);
                } else {
                        //
                        // User Nuxeo's default file importer/adapter explicitly.  This avoids specialized functionality from happening like
@@ -620,7 +619,7 @@ public class NuxeoBlobUtils {
 
                        FileImporter defaultFileImporter = fileManagerService.getPluginByName("DefaultFileImporter");
                        result = defaultFileImporter.create(
-                                       repoSession.getCoreSession(), inputStreamBlob, blobLocation, true, blobName, getTypeService());                 
+                                       repoSession.getCoreSession(), inputStreamBlob, blobLocation, overwrite, blobName, getTypeService());                    
                }
                
                return result;
@@ -652,7 +651,7 @@ public class NuxeoBlobUtils {
                                        repoSession,
                            inputStreamBlob, 
                            blobLocation.getPathAsString(), 
-                           true, 
+                           false, 
                            blobName,
                            useNuxeoAdaptors);
                        result = createBlobsCommon(documentModel, inputStreamBlob); // Now create the metadata about the Nuxeo blob document
@@ -778,42 +777,62 @@ public class NuxeoBlobUtils {
 
                try {
                        Blob fileBlob = createNuxeoFileBasedBlob(file);
-                       
                        DocumentModel documentModel = createDocumentFromBlob(
                                        nuxeoSession, fileBlob,
                                        blobLocation.getPathAsString(),
-                                       true,
+                                       false,
                                        file.getName(),
                                        useNuxeoAdaptors);
 
                        result = createBlobsCommon(documentModel, fileBlob); // Now create our metadata resource document
 
-                       // If the sender wanted us to generate only derivatives, we need to purge/clear the original contents
+                       // If the requester wants us to generate only derivatives, we need to purge/clear the original image file
                        if (purgeOriginal == true && isPurgeAllowed(documentModel) == true) {
+                               
                                // Empty the document model's "content" property -this does not delete the actual file/blob
-                               documentModel.setPropertyValue("file:content", (Serializable) null);
+                               //documentModel.setPropertyValue("file:content", (Serializable) null);
                                
                                if (documentModel.hasFacet(ImagingDocumentConstants.PICTURE_FACET)) {
+                                       //
+                                       // We're going to use the "source" property field of the Dublin Core schema as a way of indicating to
+                                       // our event listener (See UpdateImageDerivatives.java) that the original image needs to be
+                                       // purged.  The "source" property does not seem to be used by Nuxeo for Picture documents as of v6.0.  However, this might
+                                       // break in future releases of Nuxeo, so we'll emit a warning to the logs if we find a value in this
+                                       // property.
+                                       //
+                                       String source = (String)documentModel.getProperty(CommonAPI.NUXEO_DUBLINCORE_SCHEMANAME,
+                                                       CommonAPI.NUXEO_DUBLINCORE_SOURCE);
+                                       if (source != null) {
+                                               logger.warn(String.format("The Nuxeo dublin core property '%s' is set to '%s'.  We expected it to be empty. See JIRA issue CSPACE-6679 for details.",
+                                                               CommonAPI.NUXEO_DUBLINCORE_SOURCE, source));
+                                       }
+                                       documentModel.setProperty(CommonAPI.NUXEO_DUBLINCORE_SCHEMANAME,
+                                                       CommonAPI.NUXEO_DUBLINCORE_SOURCE, CommonAPI.URL_SOURCED_PICTURE);
+                                       
                                        // Now with no content, the derivative listener wants to update the derivatives. So to
                                        // prevent the listener, we remove the "Picture" facet from the document
-                                       NuxeoUtils.removeFacet(documentModel, ImagingDocumentConstants.PICTURE_FACET); // Removing this facet ensures the original derivatives are unchanged.
-                                       nuxeoSession.saveDocument(documentModel);
+                                       //NuxeoUtils.removeFacet(documentModel, ImagingDocumentConstants.PICTURE_FACET); // Removing this facet ensures the original derivatives are unchanged.
                                        // Now that we've emptied the document model's content field, we can add back the Picture facet
-                                       NuxeoUtils.addFacet(documentModel, ImagingDocumentConstants.PICTURE_FACET);
+                                       //NuxeoUtils.addFacet(documentModel, ImagingDocumentConstants.PICTURE_FACET);
                                }
                                
-                               nuxeoSession.saveDocument(documentModel);
+                               //nuxeoSession.saveDocument(documentModel);
                                // Next, we need to remove the actual file from Nuxeo's data directory
-                               DocumentBlobHolder docBlobHolder = (DocumentBlobHolder) documentModel
-                                               .getAdapter(BlobHolder.class);
-                               Blob blob = docBlobHolder.getBlob();
-                               if(blob == null) {
-                                       logger.error("Could not get blob for original image. Trying to delete original for: {}",
-                                                       file.getName());
-                               } else {
-                                       boolean deleteSuccess = NuxeoUtils.deleteFileOfBlob(docBlobHolder.getBlob());
-                               }
+//                             Blob blob = docBlobHolder.getBlob();
+//                             if(blob == null) {
+//                                     logger.error("Could not get blob for original image. Trying to delete original for: {}",
+//                                                     file.getName());
+//                             } else {
+//                                     boolean deleteSuccess = NuxeoUtils.deleteFileOfBlob(docBlobHolder.getBlob());
+//                             }
                        }
+                       
+                       //
+                       // Persist/save any changes.
+                       //
+                       nuxeoSession.saveDocument(documentModel);
+                       nuxeoSession.save();
+
                } catch (Exception e) {
                        result = null;
                        logger.error("Could not create new Nuxeo blob document.", e); //FIXME: REM - This should probably be re-throwing the exception?
index 14977bac49a5f85e8532d1b23ffcc4c0701f144d..b451aaa4bfefb760908bb81f480066a33fe5912b 100644 (file)
@@ -29,13 +29,13 @@ import java.util.List;
 import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.commons.lang.StringUtils;
-
 import org.collectionspace.services.client.Profiler;
 import org.collectionspace.services.client.CollectionSpaceClient;
 import org.collectionspace.services.client.IQueryManager;
 import org.collectionspace.services.client.IRelationsManager;
 import org.collectionspace.services.client.PoxPayloadIn;
 import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.common.api.CommonAPI;
 import org.collectionspace.services.common.api.GregorianCalendarDateTimeUtils;
 import org.collectionspace.services.common.api.RefName;
 import org.collectionspace.services.common.api.RefName.RefNameInterface;
@@ -59,14 +59,12 @@ import org.collectionspace.services.lifecycle.StateList;
 import org.collectionspace.services.lifecycle.TransitionDef;
 import org.collectionspace.services.lifecycle.TransitionDefList;
 import org.collectionspace.services.lifecycle.TransitionList;
-
 import org.nuxeo.ecm.core.NXCore;
 import org.nuxeo.ecm.core.api.ClientException;
 import org.nuxeo.ecm.core.api.DocumentModel;
 import org.nuxeo.ecm.core.api.DocumentModelList;
 import org.nuxeo.ecm.core.api.model.PropertyException;
 import org.nuxeo.ecm.core.lifecycle.LifeCycleService;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -358,7 +356,7 @@ public abstract class DocumentModelHandler<T, TL>
                // Nuxeo webapp.
                //
                try {
-               documentModel.setProperty("dublincore", "title",
+               documentModel.setProperty(CommonAPI.NUXEO_DUBLINCORE_SCHEMANAME, CommonAPI.NUXEO_DUBLINCORE_TITLE,
                        documentModel.getName());
                } catch (Exception x) {
                        if (logger.isWarnEnabled() == true) {
index 15da22d1c5279ccca0d13d3132634b4987130604..205a0ec4f7a26cccd4819855e1bcf675d1411ef1 100644 (file)
@@ -42,10 +42,9 @@ import org.collectionspace.services.common.document.DocumentUtils;
 import org.collectionspace.services.common.query.QueryContext;
 import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentException;
 import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
-
 import org.dom4j.Document;
 import org.dom4j.io.SAXReader;
-
+import org.mortbay.log.Log;
 import org.nuxeo.ecm.core.api.DocumentModel;
 import org.nuxeo.ecm.core.api.DocumentModelList;
 import org.nuxeo.ecm.core.api.ClientException;
@@ -54,6 +53,7 @@ import org.nuxeo.ecm.core.api.CoreSession;
 import org.nuxeo.ecm.core.api.DocumentRef;
 import org.nuxeo.ecm.core.api.IdRef;
 import org.nuxeo.ecm.core.api.PathRef;
+import org.nuxeo.ecm.core.api.impl.blob.BlobWrapper;
 import org.nuxeo.ecm.core.api.model.PropertyException;
 import org.nuxeo.ecm.core.io.DocumentPipe;
 import org.nuxeo.ecm.core.io.DocumentReader;
@@ -62,10 +62,10 @@ import org.nuxeo.ecm.core.io.impl.DocumentPipeImpl;
 import org.nuxeo.ecm.core.io.impl.plugins.SingleDocumentReader;
 import org.nuxeo.ecm.core.io.impl.plugins.XMLDocumentWriter;
 import org.nuxeo.ecm.core.schema.SchemaManager;
+import org.nuxeo.ecm.core.storage.StorageBlob;
 import org.nuxeo.ecm.core.storage.binary.Binary;
 import org.nuxeo.ecm.core.storage.sql.coremodel.SQLBlob;
 import org.nuxeo.runtime.api.Framework;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -92,15 +92,31 @@ public class NuxeoUtils {
     private static final String ORDER_BY_CLAUSE_REGEX = "\\w+(_\\w+)?:\\w+(/(\\*|\\w+))*( ASC| DESC)?(, \\w+(_\\w+)?:\\w+(/(\\*|\\w+))*( ASC| DESC)?)*";
        
     /* 
-     * Keep this method private.  This method uses reflection to gain access to a protected field in Nuxeo's "Binary" class.  Once we learn how
+     * Keep this method private.  This method uses reflection to gain access to a protected field in Nuxeo's "Binary" class.  If and when we learn how
      * to locate the "file" field of a Binary instance without breaking our "contract" with this class, we should minimize
      * our use of this method.
      */
     private static File getFileOfBlob(Blob blob) {
        File result = null;
        
-       if (blob instanceof SQLBlob) {
-               SQLBlob sqlBlob = (SQLBlob)blob;
+       if (blob instanceof BlobWrapper) {
+               BlobWrapper blobWrapper = (BlobWrapper)blob;
+                       try {
+                               Field blobField;
+                               blobField = blobWrapper.getClass().getDeclaredField("blob");
+                               boolean accessibleState = blobField.isAccessible();
+                               if (accessibleState == false) {
+                                       blobField.setAccessible(true);
+                               }
+                       blob = (StorageBlob)blobField.get(blobWrapper);
+                       blobField.setAccessible(accessibleState); // set it back to its original access state                           
+                       } catch (Exception e) {
+                               logger.error("blob field of BlobWrapper is not accessible.", e);
+                       }
+       }
+       
+       if (blob instanceof StorageBlob) {
+               StorageBlob sqlBlob = (StorageBlob)blob;
                Binary binary = sqlBlob.getBinary();
                try {
                        Field fileField = binary.getClass().getDeclaredField("file");
@@ -118,13 +134,77 @@ public class NuxeoUtils {
        return result;
     }
     
-    static public boolean deleteFileOfBlob(Blob blob) {
-       boolean result = false;
+    static public Thread deleteFileOfBlobAsync(Blob blob) {
+       Thread result = null;
+       
+       //
+       // Define a new thread that will try to delete the file of the blob.  We
+       // need this to happen on a separate thread because our current thread seems
+       // to still have an active handle to the file so our non-thread delete calls
+       // are failing.  The new thread will make 10 attempts, separated by 1 second, to
+       // delete the file.  If after 10 attempts, it still can't delete the file, it will
+       // log an error.
+       //
+       final File fileToDelete = getFileOfBlob(blob);
+       final String blobName = blob.getFilename();
+       Thread deleteFileThread = new Thread() {
+               @Override public void run() {
+                       boolean deleteSuccess = false;
+                       int attempts = 0;
+                       while (attempts++ < 10 && deleteSuccess != true) {
+                               deleteSuccess = deleteFile(fileToDelete);
+                               if (deleteSuccess == false) {
+                                       //
+                                       // We couldn't delete the file, so some other thread might still
+                                       // have a handle to it.  Let's put this thread to sleep for 1 second
+                                       // before trying to delete it again.
+                                       //
+                                       try {
+                                                       Thread.sleep(1000);
+                                               } catch (InterruptedException e) {
+                                                       logger.error(String.format("Unable to delete file '%s' of blob '%s'.",
+                                                       fileToDelete.getAbsoluteFile(), blobName), e);
+                                               }
+                               }
+                       }
+                       //
+                       // Now log the result.
+                       //
+                       if (deleteSuccess) {
+                               logger.debug(String.format("Successfully deleted file '%s' of blob '%s'.",
+                                               fileToDelete.getAbsoluteFile(), blobName));
+                       } else {
+                               logger.error(String.format("Unable to delete file '%s' of blob '%s'.",
+                                               fileToDelete.getAbsoluteFile(), blobName));
+                       }
+               }
+       };
+       deleteFileThread.start();
+       result = deleteFileThread;
        
+       return result;
+    }
+    
+    static public boolean deleteFileOfBlob(Blob blob) {
        File fileToDelete = getFileOfBlob(blob);
-       result = fileToDelete.delete();
+       return deleteFile(fileToDelete);
+    }
+    
+    static public boolean deleteFile(File fileToDelete) {
+       boolean result = true;
+       
+       Exception deleteException = null;
+       try {
+                       java.nio.file.Files.delete(fileToDelete.toPath());
+                       Log.debug(String.format("Deleted file '%s'.", fileToDelete.getCanonicalPath()));
+               } catch (IOException e) {
+                       deleteException = e;
+                       result = false;
+               }
+       
                if (result == false) {
-                       logger.warn("Could not delete the blob file at: " + fileToDelete.getAbsolutePath());
+                       logger.warn("Could not delete the file at: " + fileToDelete.getAbsolutePath(),
+                                       deleteException);
                }
        
        return result;