]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-3698: Post to Blob service with URL query param to external image now supported.
authorRichard Millet <richard.millet@berkeley.edu>
Thu, 5 May 2011 08:46:01 +0000 (08:46 +0000)
committerRichard Millet <richard.millet@berkeley.edu>
Thu, 5 May 2011 08:46:01 +0000 (08:46 +0000)
services/blob/client/src/test/java/org/collectionspace/services/client/test/BlobServiceTest.java
services/common/src/main/java/org/collectionspace/services/common/Download.java [new file with mode: 0644]
services/common/src/main/java/org/collectionspace/services/common/FileUtils.java
services/common/src/main/java/org/collectionspace/services/common/blob/BlobInput.java
services/jaxb/src/main/resources/blobs_common.xsd
services/media/client/src/test/java/org/collectionspace/services/client/test/MediaServiceTest.java

index b9c732cb00464f82685a0dac47437e2bbc1a0e78..421daa058610a491b9b765bae46a312e4fe7bbf7 100644 (file)
@@ -23,6 +23,7 @@
 package org.collectionspace.services.client.test;
 
 import java.io.File;
+import java.net.URL;
 import java.util.List;
 
 import javax.ws.rs.core.MediaType;
@@ -125,7 +126,7 @@ public class BlobServiceTest extends AbstractServiceTestImpl {
      * @param fromUri - if 'false' then send the service a multipart/form-data POST from which to create the blob.
      * @throws Exception the exception
      */
-    protected void createBlob(String testName, boolean fromUri) throws Exception {
+    protected void createBlob(String testName, boolean fromUri, String uri) throws Exception {
         setupCreate();
         BlobClient client = new BlobClient();
         
@@ -142,7 +143,13 @@ public class BlobServiceTest extends AbstractServiceTestImpl {
                                        logger.debug("Processing file URI: " + child.getAbsolutePath());
                                        logger.debug("MIME type is: " + mimeType);
                                        if (fromUri == true) {
-                                               res = client.createBlobFromURI(child.getAbsolutePath());
+                                               if (uri != null) {
+                                                       res = client.createBlobFromURI(uri);
+                                                       break;
+                                               } else {
+                                                       URL childUrl = child.toURI().toURL();
+                                                       res = client.createBlobFromURI(childUrl.toString());
+                                               }
                                        } else {
                                            MultipartFormDataOutput form = new MultipartFormDataOutput();
                                            OutputPart outputPart = form.addFormData("file", child, MediaType.valueOf(mimeType));
@@ -165,14 +172,20 @@ public class BlobServiceTest extends AbstractServiceTestImpl {
     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class, dependsOnMethods = {"create"})
     public void createBlobWithURI(String testName) throws Exception {
         logger.debug(testBanner(testName, CLASS_NAME));
-       createBlob(testName, true /*with URI*/);
+       createBlob(testName, true /*with URI*/, null);
     }
     
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class, dependsOnMethods = {"create"})
+    public void createBlobWithURL(String testName) throws Exception {
+        logger.debug(testBanner(testName, CLASS_NAME));
+       createBlob(testName, true /*with URI*/, "http://farm6.static.flickr.com/5289/5688023100_15e00cde47_o.jpg");
+    }    
+    
     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
                dependsOnMethods = {"createBlobWithURI"})
     public void createBlobWithPost(String testName) throws Exception {
         logger.debug(testBanner(testName, CLASS_NAME));
-       createBlob(testName, false /*with POST*/);
+       createBlob(testName, false /*with POST*/, null);
     }
 
     @Override
diff --git a/services/common/src/main/java/org/collectionspace/services/common/Download.java b/services/common/src/main/java/org/collectionspace/services/common/Download.java
new file mode 100644 (file)
index 0000000..ef6fd81
--- /dev/null
@@ -0,0 +1,274 @@
+package org.collectionspace.services.common;\r
+import java.io.*;\r
+import java.net.*;\r
+import java.util.*;\r
+\r
+// This class downloads a file from a URL.\r
+public class Download extends Observable implements Runnable {\r
+    \r
+    public static URL verifyUrl(String url) {\r
+        // Only allow HTTP URLs.\r
+        if (!url.toLowerCase().startsWith("http://"))\r
+            return null;\r
+        \r
+        // Verify format of URL.\r
+        URL verifiedUrl = null;\r
+        try {\r
+            verifiedUrl = new URL(url);\r
+        } catch (Exception e) {\r
+            return null;\r
+        }\r
+        \r
+        // Make sure URL specifies a file.\r
+        if (verifiedUrl.getFile().length() < 2)\r
+            return null;\r
+        \r
+        return verifiedUrl;\r
+    }\r
+    \r
+    // Max size of download buffer.\r
+    private static final int MAX_BUFFER_SIZE = 1024;\r
+    \r
+    // These are the status names.\r
+    public static final String STATUSES[] = {"Downloading",\r
+    "Paused", "Complete", "Cancelled", "Error"};\r
+    \r
+    // These are the status codes.\r
+    public static final int DOWNLOADING = 0;\r
+    public static final int PAUSED = 1;\r
+    public static final int COMPLETE = 2;\r
+    public static final int CANCELLED = 3;\r
+    public static final int ERROR = 4;\r
+    \r
+    private String errorMessage = null;\r
+    private String filePath = null;\r
+    private File downloadedFile = null;\r
+    private String destDir = null; // the location of the downloaded file\r
+    private URL url; // download URL\r
+    private int size; // size of download in bytes\r
+    private int downloaded; // number of bytes downloaded\r
+    private int status; // current status of download\r
+    \r
+    public Download(URL url, String destDir) {\r
+        size = -1;\r
+        downloaded = 0;\r
+        status = DOWNLOADING;\r
+        this.url = url;\r
+        setDestDir(destDir);\r
+       \r
+        // Begin the download.\r
+        download();\r
+    }\r
+\r
+    // Constructor for Download.\r
+    public Download(URL url) {\r
+       this(url, System.getProperty("java.io.tmpdir") + UUID.randomUUID() + File.separator);           \r
+    }\r
+    \r
+    private void setDestDir(String destDir) {\r
+        if (destDir.endsWith(File.separator) != true) {\r
+               destDir = destDir + File.separator;\r
+        }\r
+        //\r
+        // Check if the destDir exists, if not try to create it.\r
+        //\r
+        File destDirFile = new File(destDir);\r
+        boolean destDirExists = destDirFile.exists();\r
+        if (destDirExists == false) {\r
+               destDirExists = destDirFile.mkdir();\r
+        } else {\r
+               destDirExists = destDirFile.isDirectory();\r
+        }\r
+        //\r
+        // If we couldn't create the directory or if it is already a file then fail.\r
+        //\r
+        if (destDirExists = true) {\r
+               this.destDir = destDir;\r
+        } else {\r
+               error("Could not download file to: " + destDir);\r
+        }\r
+    }\r
+    \r
+    \r
+    public File getFile() {\r
+       return this.downloadedFile;\r
+    }\r
+    \r
+    public String getFilePath() {\r
+       return this.filePath;\r
+    }\r
+    \r
+    public String getDestDir() {\r
+       return this.destDir;\r
+    }\r
+    \r
+    // Get this download's URL.\r
+    public String getUrl() {\r
+        return url.toString();\r
+    }\r
+    \r
+    // Get this download's size.\r
+    public int getSize() {\r
+        return size;\r
+    }\r
+    \r
+    // Get this download's progress.\r
+    public float getProgress() {\r
+        return ((float) downloaded / size) * 100;\r
+    }\r
+    \r
+    // Get this download's status.\r
+    public int getStatus() {\r
+        return status;\r
+    }\r
+    \r
+    // Pause this download.\r
+    public void pause() {\r
+        status = PAUSED;\r
+        stateChanged();\r
+    }\r
+    \r
+    // Resume this download.\r
+    public void resume() {\r
+        status = DOWNLOADING;\r
+        stateChanged();\r
+        download();\r
+    }\r
+    \r
+    // Cancel this download.\r
+    public void cancel() {\r
+        status = CANCELLED;\r
+        stateChanged();\r
+    }\r
+    \r
+    // Mark this download as having an error.\r
+    private void error() {\r
+        status = ERROR;\r
+        stateChanged();\r
+    }\r
+    \r
+    // Mark this download as having an error.\r
+    private void error(String message) {\r
+        this.errorMessage = message;\r
+        error();\r
+    }    \r
+    \r
+    // Start or resume downloading.\r
+    private void download() {\r
+//        Thread thread = new Thread(this);\r
+//        thread.start();\r
+       run();\r
+    }\r
+    \r
+    // Get file name portion of URL.\r
+    private String getFileName(URL url) {\r
+       String result = null;\r
+       \r
+       String destDir = this.getDestDir();\r
+        String fileName = url.getFile();\r
+        fileName = fileName.substring(fileName.lastIndexOf('/') + 1);\r
+        result = filePath = destDir + fileName;\r
+        \r
+        return result;\r
+    }\r
+    \r
+    // Download file.\r
+    public void run() {\r
+        RandomAccessFile file = null;\r
+        InputStream stream = null;\r
+        \r
+        try {\r
+            // Open connection to URL.\r
+            HttpURLConnection connection =\r
+                    (HttpURLConnection) url.openConnection();\r
+            \r
+            // Specify what portion of file to download.\r
+            connection.setRequestProperty("Range",\r
+                    "bytes=" + downloaded + "-");\r
+            \r
+            // Connect to server.\r
+            connection.connect();\r
+            \r
+            // Make sure response code is in the 200 range.\r
+            int responseCode = connection.getResponseCode();\r
+            if (responseCode / 100 != 2) {\r
+                error();\r
+            }\r
+            \r
+            // Check for valid content length.\r
+            int contentLength = connection.getContentLength();\r
+            if (contentLength < 1) {\r
+                error();\r
+            }\r
+            \r
+      /* Set the size for this download if it\r
+         hasn't been already set. */\r
+            if (size == -1) {\r
+                size = contentLength;\r
+                stateChanged();\r
+            }\r
+            \r
+            // Open file and seek to the end of it.\r
+            File javaFile = new File(getFileName(url));\r
+            file = new RandomAccessFile(javaFile, "rw");\r
+            file.seek(downloaded);\r
+            \r
+            stream = connection.getInputStream();\r
+            while (status == DOWNLOADING) {\r
+        /* Size buffer according to how much of the\r
+           file is left to download. */\r
+                byte buffer[];\r
+                if (size - downloaded > MAX_BUFFER_SIZE) {\r
+                    buffer = new byte[MAX_BUFFER_SIZE];\r
+                } else {\r
+                    buffer = new byte[size - downloaded];\r
+                }\r
+                \r
+                // Read from server into buffer.\r
+                int read = stream.read(buffer);\r
+                if (read == -1)\r
+                    break;\r
+                \r
+                // Write buffer to file.\r
+                file.write(buffer, 0, read);\r
+                downloaded += read;\r
+                stateChanged();\r
+            }\r
+            \r
+      /* Change status to complete if this point was\r
+         reached because downloading has finished. */\r
+            if (status == DOWNLOADING) {\r
+                status = COMPLETE;\r
+                downloadedFile = new File(this.getFilePath());\r
+                stateChanged();\r
+            }\r
+        } catch (Exception e) {\r
+               e.printStackTrace();\r
+            error();\r
+        } finally {\r
+            // Close file.\r
+            if (file != null) {\r
+                try {\r
+                    file.close();\r
+                } catch (Exception e) {\r
+                       e.printStackTrace();\r
+                }\r
+            }\r
+            \r
+            // Close connection to server.\r
+            if (stream != null) {\r
+                try {\r
+                    stream.close();\r
+                } catch (Exception e) {\r
+                       e.printStackTrace();\r
+                }\r
+            }\r
+        }\r
+    }\r
+    \r
+    // Notify observers that this download's status has changed.\r
+    private void stateChanged() {\r
+        setChanged();\r
+        notifyObservers();\r
+    }\r
+}
\ No newline at end of file
index 6c85676afe7ad699ccf430227149d3098215030d..5d085a1829ed049c817288b5f084c2ac7e99fc5e 100644 (file)
@@ -34,9 +34,9 @@ import java.util.UUID;
 \r
 //import java.io.IOException;\r
 \r
-import java.util.UUID;\r
-import java.util.regex.Pattern;\r
-import java.util.regex.Matcher;\r
+//import java.util.UUID;\r
+//import java.util.regex.Pattern;\r
+//import java.util.regex.Matcher;\r
 \r
 //import javax.servlet.ServletException;\r
 //import javax.servlet.http.HttpServlet;\r
@@ -129,13 +129,30 @@ public class FileUtils {
                                        if (fileName == null) {\r
                                                fileName = DEFAULT_BLOB_NAME; //if there's no file name then set it to an empty string\r
                                                logger.warn("File was posted to the services without a file name.");\r
-                                       }                                       \r
+                                       }\r
+                                       //\r
+                                       // To avoid name collisions and to preserve the posted file name, create a temp directory for the\r
+                                       // file.\r
+                                       //\r
                                        File tmpDir = new File(System.getProperty("java.io.tmpdir"));\r
-                                       File savedFile = File.createTempFile(TMP_BLOB_PREFIX, fileName, tmpDir);\r
-\r
-                                       item.write(savedFile);\r
+                                       String fileTmpDirPath = tmpDir.getPath() + File.separatorChar + UUID.randomUUID();\r
+                                       File fileTmpDir = new File(fileTmpDirPath);\r
+                                       File savedFile = null;\r
+                                       if (fileTmpDir.mkdir() == true) {\r
+                                               savedFile = new File(fileTmpDirPath + File.separatorChar + fileName);\r
+                                               if (savedFile.createNewFile() == false) {\r
+                                                       savedFile = null;\r
+                                               }\r
+                                       }\r
+                                       \r
+                                       if (savedFile != null) {\r
+                                               item.write(savedFile);\r
 //                                             item.getInputStream();//FIXME: REM - We should make a version of this method that returns the input stream\r
-                                       result = savedFile;\r
+                                               result = savedFile;\r
+                                       } else {\r
+                                               logger.error("Could not create temporary file: " + fileTmpDirPath +\r
+                                                               File.separatorChar + fileName);                                         \r
+                                       }\r
                                }\r
                        }\r
                } catch (Exception e) {\r
index 70b871aff76aaa1c8b566cf4a413640ebad79f74..56f06f11fa2113dc566b876d3f249e2acb9e607e 100644 (file)
@@ -2,15 +2,26 @@ package org.collectionspace.services.common.blob;
 \r
 import java.io.File;\r
 import java.io.InputStream;\r
+import java.net.MalformedURLException;\r
+import java.net.URL;\r
+\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
 \r
 import javax.servlet.http.HttpServletRequest;\r
 \r
 //import org.collectionspace.services.blob.BlobsCommonList; \r
-import org.collectionspace.services.jaxb.AbstractCommonList;\r
+//import org.collectionspace.services.jaxb.AbstractCommonList;\r
 import org.collectionspace.services.nuxeo.client.java.CommonList;\r
-import org.collectionspace.services.common.FileUtils;\r
+//import org.collectionspace.services.blob.nuxeo.BlobDocumentModelHandler;\r
+//import org.collectionspace.services.common.FileUtils;\r
+import org.collectionspace.services.common.Download;\r
+import org.slf4j.LoggerFactory;\r
+import org.apache.commons.io.FileUtils;\r
 \r
 public class BlobInput {\r
+       private final Logger logger = LoggerFactory.getLogger(BlobInput.class);\r
+       \r
        private String blobCsid = null;\r
        private File blobFile = null;\r
        private String blobUri = null;\r
@@ -117,14 +128,35 @@ public class BlobInput {
         * End of setters and getters\r
         */\r
        \r
+       //\r
+       // FIXME: REM - The callers of this method are sending us a multipart form-data post, so why\r
+       // are we also receiving the blobUri?\r
+       //\r
        public void createBlobFile(HttpServletRequest req, String blobUri) {\r
-       File tmpFile = FileUtils.createTmpFile(req);\r
+       File tmpFile = org.collectionspace.services.common.FileUtils.createTmpFile(req);\r
        this.setBlobFile(tmpFile);\r
        this.setBlobUri(blobUri);\r
        }\r
        \r
-       public void createBlobFile(String theBlobUri) {\r
-       File theBlobFile = new File(theBlobUri);\r
+       public void createBlobFile(String theBlobUri) throws MalformedURLException, Exception {\r
+               URL blobUrl = new URL(theBlobUri);\r
+       File theBlobFile = null;\r
+\r
+               if (blobUrl.getProtocol().equalsIgnoreCase("http")) {\r
+                       Download fetchedFile = new Download(blobUrl);\r
+                       while (fetchedFile.getStatus() == Download.DOWNLOADING) {\r
+                               // Do nothing while we wait for the file to download\r
+                       }\r
+                       int status = fetchedFile.getStatus();\r
+                       if (status == Download.COMPLETE) {\r
+                               theBlobFile = fetchedFile.getFile();\r
+                       }\r
+               } else if (blobUrl.getProtocol().equalsIgnoreCase("file")) {\r
+                       theBlobFile = FileUtils.toFile(blobUrl);\r
+//                     theBlobFile = new File(theBlobUri);\r
+               } else {\r
+                       \r
+               }\r
        this.setBlobFile(theBlobFile);\r
        this.setBlobUri(blobUri);\r
        }       \r
index 8dc7186def4d52520be5ed72b8937ec66248ffef..1ac4adc5b5765e53cd35da483445e8ab156f8da8 100644 (file)
@@ -50,6 +50,7 @@
                 maxOccurs="unbounded"/>
         </xs:sequence>
     </xs:complexType>
+    
     <xs:complexType name="dimensionGroup"> <!-- //FIXME: The "dimensionGroup" type should be declared in one place since other services use it -->
         <xs:sequence>
             <xs:element name="measuredPart" type="xs:string"/>
index a3d87e112b1838b139e69b9ad12a92d3b46ad0da..3253d4bda26f05105e4106438207f8d4eee34e90 100644 (file)
@@ -23,6 +23,7 @@
 package org.collectionspace.services.client.test;
 
 import java.io.File;
+import java.net.URL;
 import java.util.List;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
@@ -157,7 +158,8 @@ public class MediaServiceTest extends AbstractServiceTestImpl {
                                logger.debug("Processing file URI: " + blobFile.getAbsolutePath());
                                logger.debug("MIME type is: " + mimeType);
                                if (fromUri == true) {
-                                       res = client.createBlobFromUri(mediaCsid, blobFile.getAbsolutePath());
+                                       URL childUrl = blobFile.toURI().toURL();
+                                       res = client.createBlobFromUri(mediaCsid, childUrl.toString());
                                } else {
                                    MultipartFormDataOutput formData = new MultipartFormDataOutput();
                                    OutputPart outputPart = formData.addFormData("file", blobFile, MediaType.valueOf(mimeType));