package org.collectionspace.services.client.test;
import java.io.File;
+import java.net.URL;
import java.util.List;
import javax.ws.rs.core.MediaType;
* @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();
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));
@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
--- /dev/null
+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
\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
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
\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
* 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