diff --git a/ConfigurableProperties.md b/ConfigurableProperties.md new file mode 100644 index 0000000..7fc989a --- /dev/null +++ b/ConfigurableProperties.md @@ -0,0 +1,160 @@ +## Java properties ## + +Some Java properties are exposed and can be configured using a properties file. + +You can add a _java-large-file-uploader.properties_ file to your classpath which can include: + + + +#### maximumRatePerClientInKiloBytes #### + +``` +jlfu.ratelimiter.maximumRatePerClientInKiloBytes +``` + +The maximum upload rate per client in kilo bytes. (Default is 10240 (10MB/s)) + +Exposed as MBean. + + + +#### maximumOverAllRateInKiloBytes #### + +``` +jlfu.ratelimiter.maximumOverAllRateInKiloBytes +``` + +The maximum total upload rate in kilo bytes. (Default is 10240 (10MB/s)) + +Exposed as MBean. + + +#### sliceSizeInBytes #### + +``` +jlfu.sliceSizeInBytes +``` + +The size of the slice that javascript read and send. (Default is 10485760 (10MB)) + +#### maximumInactivityInHoursBeforeDelete #### + +``` +jlfu.filecleaner.maximumInactivityInHoursBeforeDelete +``` + +The maximum time files can stay inactive on the server (Default is 48) + +Exposed as MBean. + + + +#### uploadFolder #### + +``` +jlfu.defaultUploadFolder +``` + +The folder where the files and state are stored on the server (Default is "/JavaLargeFileUploader") + + + +#### uploadFolderRelativePath #### + +``` +jlfu.uploadFolderRelativePath +``` + +Boolean specifying whether the defaultUploaderFolder described previously is a relative path (true) or an absolute path (false) (Default is `true`) + + + +#### keepOriginalFileName #### + +``` +jlfu.keepOriginalFileName +``` + +Boolean specifying whether the originalFileName should be kept while preparing the upload of a file. If set to false, a name generated from a UUID will be assigned to avoid name collision. (Default is `false`) + + + + + +--- + + + + +## javascript-attributes ## + +#### maxNumberOfConcurrentUploads #### + +_default value is **5**_ + +All browsers are limiting the number of concurrent requests that are active against a similar domain. Chrome and Firefox limit is set to 6. + +All requests are then queued but the problem is that the upload streaming requests are (as you can imagine) quite long. If that limit is more than 6, the progress poller requests would be queued and no progress would be retrieved for as long as the files are streamed. + +Also, depending of what you want to achieve, it could make sense to allow a maximum of 1 concurrent request as the bandwidth is shared anyway between all the concurrent uploads. + +It is advised to use a number between 1 and 5 so that there is always at least one request left for progress poller. + +Use [JavaLargeFileUploader#setMaxNumberOfConcurrentUploads](JavaLargeFileUploader#setMaxNumberOfConcurrentUploads.md). + +#### errorMessages #### + +The error messages can be modified and/or translated by the page using the API. +They are stored inside a map that can be modified from the page. + +The initial content of the map is: +``` +errorMessages[0] = "Request failed for an unknown reason, please contact an administrator if the problem persists."; +errorMessages[1] = "The request is not multipart."; +errorMessages[2] = "No file to upload found in the request."; +errorMessages[3] = "CRC32 Validation of the part failed."; +errorMessages[4] = "The request cannot be processed because a parameter is missing."; +errorMessages[5] = "Cannot retrieve the configuration."; +errorMessages[6] = "No files have been selected, please select at least one file!"; +errorMessages[7] = "Resuming file upload with previous slice as the last part is invalid."; +errorMessages[8] = "Error while uploading a slice of the file"; +errorMessages[9] = "Maximum number of concurrent uploads reached, the upload is queued and waiting for one to finish."; +errorMessages[10] = "An exception occurred. Retrying ..."; +errorMessages[11] = "Connection lost. Automatically retrying in a moment."; +errorMessages[12] = "You do not have the permission to perform this action."; +errorMessages[13] = "FireBug is enabled, you may experience issues if you do not disable it while uploading."; +errorMessages[14] = "File corrupted. An unknown error has occured and the file is corrupted. The usual cause is that the file has been modified during the upload. Please clear it and re-upload it."; +errorMessages[15] = "File is currently locked, retrying in a moment..."; +errorMessages[16] = "Uploads are momentarily disabled, retrying in a moment..."; +``` +You can retrieve this map using [JavaLargeFileUploader#getErrorMessages](JavaLargeFileUploader#getErrorMessages.md) and modify them directly. + +#### progressPollerRefreshRate #### + +_default value is **1000**_ + +The [progress poller](Flow#Progress-Poller.md) is sending a new request to the server every _x_ amount of milliseconds, _x_ being the value of this variable. + +Use [JavaLargeFileUploader#setProgressPollerRefreshRate](JavaLargeFileUploader#setProgressPollerRefreshRate.md) to set this value up. + +#### autoretry #### + +_default autoretry value is **true**_ + +_default autoretry delay is **5000**_ + +Whenever the connection is lost, the API can try to resume the file upload automatically. + +If the autoretry value is true, it will retry every _x_ milliseconds, _x_ being the delay. + +Use [JavaLargeFileUploader#setAutoRetry](JavaLargeFileUploader#setAutoRetry.md) to set these values up. + +#### javaLargeFileUploaderHost #### + +_default value is **empty** (same host than the server hosting the resource)_ + +If your javascript resources are hosted on a different machine, you can specify the server handling the calls with this value. + +Watch out for same origin policy ! + +Use [JavaLargeFileUploader#setJavaLargeFileUploaderHost](JavaLargeFileUploader#setJavaLargeFileUploaderHost.md) to set this value. \ No newline at end of file diff --git a/Flow.md b/Flow.md new file mode 100644 index 0000000..a63c8e8 --- /dev/null +++ b/Flow.md @@ -0,0 +1,64 @@ +The [JavaLargeFileUploader#initialize](JavaLargeFileUploader#initialize.md) step retrieves information from the server. +The information retrieved is: + * The size of the slices that will be streamed +For all the files: + * The [id](PendingFile#id.md) of the file on the server + * The [completion](PendingFile#fileCompletionInBytes.md) of the file + * The [original file size](PendingFile#originalFileSizeInBytes.md) + * The [original file name](PendingFile#originalFileName.md) + * The [number of bytes that have been validated](PendingFile#crcedBytes.md) + * The [crc32](PendingFile#firstChunkCrc.md) information related to the beginning of this file + * The [percentage of completion](PendingFile#percentageCompleted.md) +These information will be stored in a new instance of PendingFile for each of these files. + +At that point, the [#Progress-Poller](#Progress-Poller.md) is started. + +When the [JavaLargeFileUploader#fileUploadProcess](JavaLargeFileUploader#fileUploadProcess.md) method is executed, the API will extract the information related to all the files and fill a new PendingFile object without an ID for each of these files. + + +All of the files will be compared against the pending files retrieved from the server, that first validation is performed against the file name and the file size. + +If the file name and the file size are similar, the API will process a second validation processing a CRC32 of a small slice of this file on the javascript side compared to the crc32 of the same slice of the file on the server to ensure these files are the same one. +That crc32 is performed by default on the 8192 first bytes of this file or the available validated size if below this value. + +If the result of that crc32 is matching the one of the server, the file is assumed as the same, the two PendingFile objects are merged and the upload is resumed. => [#Resume-Upload](#Resume-Upload.md) + +If the crc32 differs from the server, a new upload will be processed. => [#New-Upload](#New-Upload.md) + +### New-Upload ### + +When a new upload is initiated, a first server-call is performed to prepare the upload with all the file information. An ID is generated by the server and returned to the client-side to identify the PendingFile object. + +Once this preparation step is performed, the JavaLargeFileUploader#startCallback is called for each of the files. + +The [#File-Streaming](#File-Streaming.md) is then started for the file. + +### Resume-Upload ### + +The first step when resuming a file is to check that what has been last uploaded is valid. + +On initialization, we have retrieved the [number of bytes that have been validated](PendingFile#crcedBytes.md), +if this value is below the [completion](PendingFile#fileCompletionInBytes.md) of the file, we have to perform a crc32 hash of the part of the file that has not been verified and check it against the crc32 value of that same part on the server. + +If the crc32 are matching, the [#File-Streaming](#File-Streaming.md) is started from that [completion](PendingFile#fileCompletionInBytes.md) value. +If the crc32 are not matching, the file is truncated to match the [number of bytes that have been validated](PendingFile#crcedBytes.md) and the [#File-Streaming](#File-Streaming.md) is started from there. + +### File-Streaming ### + +The file streaming process is started only if the number of files currently uploading is below the value of the [ConfigurableProperties#maxNumberOfConcurrentUploads](ConfigurableProperties#maxNumberOfConcurrentUploads.md). If this value is reached, the file is queued until another one is finished or cancelled. + +The file streaming process slices the file and stream them to the server. The size of the slice is defined by the configuration retrieved on [JavaLargeFileUploader#initialize](JavaLargeFileUploader#initialize.md). + +For each of these slice, the file is first read using the [FileReader API](http://developer.mozilla.org/en/DOM/FileReader) to generate a crc32 hash. That crc32 is sent with the actual slice and will be used to ensure that the transmitted data is correct. + +When the upload of this slice is complete, the next slice is processed using the same method. + +When the file has been completely uploaded, the [PendingFile#finishCallback](PendingFile#finishCallback.md) is executed. + +### Progress-Poller ### + +The progress poller is an infinite loop which retrieves from the server the completion and upload rate of all the pending uploads if at least one upload is currently being processed. + +It will trigger the [PendingFile#progressCallback](PendingFile#progressCallback.md) for each of them. + +The rate can be configured, see [here](ConfigurableProperties#progressPollerRefreshRate.md). \ No newline at end of file diff --git a/JavaLargeFileUploader.md b/JavaLargeFileUploader.md new file mode 100644 index 0000000..b5cbe12 --- /dev/null +++ b/JavaLargeFileUploader.md @@ -0,0 +1,318 @@ +This object is the main class of the API and provides method to interact with the server. + +``` +jlfu = new JavaLargeFileUploader(); +``` + +It has to be first initialized using [JavaLargeFileUploader#initialize](JavaLargeFileUploader#initialize.md) before any other operation. + +This object have a few attributes that are configurable, please see [ConfigurableProperties#javascript-attributes](ConfigurableProperties#javascript-attributes.md). + +You can find a complete working example in the demo project. The html/js file managing jlfu is [here](http://code.google.com/p/java-large-file-uploader/source/browse/trunk/java-large-file-uploader-demo/src/main/webapp/index.html). + +This object provides the following interaction methods: + + +--- + +### initialize ### +``` +jlfu.initialize(initializationCallback, exceptionCallback); +``` +This method has to be called before any other one and will initialize the object with the configuration defined on the server. It will also retrieve all the pending files that could potentially exist and provide some information about them (see PendingFile). + * initializationCallback: +> Callback function containing a map of the files previously uploaded as parameter. +> The key of this map is the fileIdentifier. +> The value is a pendingFile (see PendingFile object description). + * exceptionCallback: +> A callback function with a string formatted describing the exception as parameter triggered if an exception occurred. +Example: +``` +jlfu.initialize(function(pendingFiles) { + //treat pending file +}, function(message){ + //treat exception +)); +``` + +--- + +### clearFileUpload ### +``` +jlfu.clearFileUpload(callback); +``` +Clears all state on the server. +Any pending upload will be stopped and deleted on the file system. + * callback: +> A function with no parameter that will be executed once all files have been removed. +Example: +``` +jlfu.clearFileUpload(function() { + //do something when the call is complete +}); +``` + +--- + +### cancelFileUpload ### +``` +jlfu.cancelFileUpload(pendingFileId, callback); +``` +Clears the file with the specified id on the server. +This upload will be stopped and the file deleted on the file system. + * pendingFileId (string) : +> the id of the file to remove. + * callback: +> A function with that will be executed once all files have been removed which includes the following parameters: + 1. fileId (string) : the id of the file that has been removed. +Example: +``` +jlfu.cancelFileUpload("4ec798ec-eba1-4ef7-afbe-df6f4635783d", function(fileId) { + //do something when the call is complete +}); +``` + +--- + +### pauseFileUpload ### +``` +jlfu.pauseFileUpload(pendingFileId, callback); +``` +Pauses the file with the specified id on the server. +The upload can be resumed using [JavaLargeFileUploader#resumeFileUpload](JavaLargeFileUploader#resumeFileUpload.md). + * pendingFileId (string) : +> the id of the file to pause. + * callback: +> A function with that will be executed once the file has been paused containing the following parameters: + 1. pendingFile (PendingFile) : the pending file object instance that has been paused. +Example: +``` +jlfu.pauseFileUpload("4ec798ec-eba1-4ef7-afbe-df6f4635783d", function(pendingFile) { + //do something when the call is complete +}); +``` + +--- + +### pauseAllFileUploads ### +``` +jlfu.pauseAllFileUploads(callback); +``` + +_since 1.1.2_ + +Pauses all the uploads of all the files (does not start the files queued). +The uploads can be resumed independently using [JavaLargeFileUploader#resumeFileUpload](JavaLargeFileUploader#resumeFileUpload.md) or [JavaLargeFileUploader#resumeAllFileUploads](JavaLargeFileUploader#resumeAllFileUploads.md). + * callback: +> A function with that will be executed for all the files once the files have been paused containing the following parameters: + 1. pendingFile (PendingFile) : the pending file object instance that has been paused. +Example: +``` +jlfu.pauseAllFileUploads(function(pendingFile) { + //do something when the call is complete +}); +``` + +--- + +### resumeFileUpload ### +``` +jlfu.resumeFileUpload(pendingFileId, callback); +``` +Resumes the file with the specified id on the server that has been previously paused using [JavaLargeFileUploader#pauseFileUpload](JavaLargeFileUploader#pauseFileUpload.md). + * pendingFileId (string) : +> the id of the file to resume. + * callback: +> A function which will be executed once the file has been resumed containing the following parameters: + 1. pendingFile (PendingFile) : the pending file object instance that has been resumed. +Example: +``` +jlfu.resumeFileUpload("4ec798ec-eba1-4ef7-afbe-df6f4635783d", function(pendingFile) { + //do something when the call is complete +}); +``` + +--- + +### resumeAllFileUploads ### +``` +jlfu.resumeAllFileUploads(callback); +``` + +_since 1.1.2_ + +Resumes all the file that have been paused using [JavaLargeFileUploader#pauseFileUpload](JavaLargeFileUploader#pauseFileUpload.md) or [JavaLargeFileUploader#pauseAllFileUploads](JavaLargeFileUploader#pauseAllFileUploads.md). + * callback: +> A function which will be executed for all the files once the file has been resumed containing the following parameters: + 1. pendingFile (PendingFile) : the pending file object instance that has been resumed. +Example: +``` +jlfu.resumeAllFileUploads(function(pendingFile) { + //do something when the call is complete +}); +``` + +--- + +### retryFileUpload ### +``` +jlfu.retryFileUpload(pendingFileId, callback); +``` +If the connection is lost or another error occurs, you can retry to resume the upload for the file with the specified id. + * pendingFileId (string) : +> the id of the file to resume. + * callback: +> A function which will be executed once the file has been resumed containing the following parameters: + 1. success (boolean) : true if the resume is successful, false otherwise. +Example: +``` +jlfu.retryFileUpload("4ec798ec-eba1-4ef7-afbe-df6f4635783d", function(ok) { + //do something when the call is complete +}); +``` + +--- + +### setRateInKiloBytes ### +``` +jlfu.setRateInKiloBytes(pendingFileId, rate); +``` +Specifies a maximum upload rate in kilo bytes that will be applied to the PendingFile identified by the specified id. + * pendingFileId (string) : +> the id of the file on which this rate shall be applied. + * rate (long) : +> the maximum rate in kilobytes. +Example: +``` +jlfu.setRateInKiloBytes("4ec798ec-eba1-4ef7-afbe-df6f4635783d", 20); +``` + +--- + +### fileUploadProcess ### +``` +jlfu.fileUploadProcess(referenceToFileElement, startCallback, progressCallback, finishCallback, exceptionCallback); +``` +Starts or resumes the upload of all the files selected in the file input element specified as parameter. +See the Flow to get more information about how these uploads are actually processed. +Parameters: + * referenceToFileElement (file input) : +> The input type="file" html element which contains the selection of files that will be processed. + * startCallback: +> see [PendingFile#startCallback](PendingFile#startCallback.md). + * progressCallback: +> > see [PendingFile#progressCallback](PendingFile#progressCallback.md). + * finishCallback: +> > see [PendingFile#finishCallback](PendingFile#finishCallback.md). + * exceptionCallback: +> > see [PendingFile#exceptionCallback](PendingFile#exceptionCallback.md). +Example: +``` +//process the file upload +jlfu.fileUploadProcess(fileElement, + + //define a start callback + function(pendingFile, referenceToFileElement) { + }, + + //define a progressCallback + function(pendingFile, percentageCompleted, uploadRate, estimatedRemainingTime, referenceToFileElement) { + }, + + //define a finishCallback showing the completion in the em element + function(pendingFile, referenceToFileElement) { + }, + + //define an exception callback + function(message, referenceToFileElement, potentialfileIdThatCanBeUndefined) { + } +); +``` + +--- + +### setMaxNumberOfConcurrentUploads ### +``` +jlfu.setMaxNumberOfConcurrentUploads(number); +``` +Specifies the maximum number of uploads that are streamed concurrently. + * number (int) : +> > the number (between 1 and 5) + +Please see [ConfigurableProperties#maxNumberOfConcurrentUploads](ConfigurableProperties#maxNumberOfConcurrentUploads.md). + +Example: +``` +jlfu.setMaxNumberOfConcurrentUploads(1); +``` + +--- + +### getErrorMessages ### +``` +jlfu.getErrorMessages(); +``` +Retrieves the map of all the error messages. + +Please see [ConfigurableProperties#errorMessages](ConfigurableProperties#errorMessages.md). + +This map can be modified directly: + +Example: +``` +jlfu.getErrorMessages()[9] = "File queued!"; +``` + +--- + +### setProgressPollerRefreshRate ### +``` +jlfu.setProgressPollerRefreshRate(newRate); +``` +Specifies the progress poller refresh rate in milliseconds. + * newRate (int) : + +> the new rate + +Please see [ConfigurableProperties#progressPollerRefreshRate](ConfigurableProperties#progressPollerRefreshRate.md). + +Example: +``` +jlfu.setProgressPollerRefreshRate(1000); +``` + +--- + +### setAutoRetry ### +``` +jlfu.setAutoRetry(autoRetryBoolean, autoRetryDelay); +``` +Specifies the auto retry configuration + * autoRetryBoolean (boolean) : +> true to enable auto retry, false to disable. + * autoRetryDelay (int) : +> the amount of time in milliseconds between each retry. + +Please see [ConfigurableProperties#autoretry](ConfigurableProperties#autoretry.md). + +Example: +``` +jlfu.setAutoRetry(true, 5000); +``` + +--- + +### setJavaLargeFileUploaderHost ### +``` +jlfu.setJavaLargeFileUploaderHost(javaLargeFileUploaderHost); +``` +Specifies the full url of the application hosting the servlet handlers. + * javaLargeFileUploaderHost(string) : +> host url + +Please see [ConfigurableProperties#javaLargeFileUploaderHost](ConfigurableProperties#javaLargeFileUploaderHost.md). + +Example: +``` +jlfu.setJavaLargeFileUploaderHost("http://localhost:8888/demo/"); +``` \ No newline at end of file diff --git a/PendingFile.md b/PendingFile.md new file mode 100644 index 0000000..f108acb --- /dev/null +++ b/PendingFile.md @@ -0,0 +1,48 @@ +#### id #### +> (string) : identifier of the pending file upload +#### fileComplete #### +> (boolean) : specifies if the file is complete or not. +#### originalFileName #### +> (string) : the original file name. +#### fileCompletionInBytes #### +> (long) : the file completion in bytes. +#### fileCompletion #### +> (string) : the file completion formatted with its unit. +#### originalFileSizeInBytes #### +> (long) : the original file size in bytes. +#### originalFileSize #### +> (string) : the original file size formatted with its unit. +#### percentageCompleted #### +> (float) : completion of the file in percent (2 decimal places) +#### started #### +> (boolean) : true if the file is currently being uploaded, false if it is a file present on the server filesystem and can be resumed. +#### crcedBytes #### +> (long) : amount of bytes that are validated on the server +#### firstChunkCrc #### +> (object) : the crc32 information of the first bytes of the file + * value (string) : the actual crc32 value + * read (int) : number of bytes which have been used to compute firstChunkCrc +#### blob #### +> (object) : the file submitted with a file input element +#### paused #### +> (boolean) : specifies whether this upload is paused or not. +#### startCallback #### +> (function) : function that is called once the upload is pre initialized if the file id is not specified. It contains the following parameters: + 1. the PendingFile object + 1. the origin element +#### progressCallback #### +> (function) : function that will be called to monitor the progress + 1. the PendingFile object + 1. the percentage + 1. the current upload rate formatted as a String + 1. the estimated remaining time formatted as a String + 1. the origin element +#### finishCallback #### +> (function): function that will be called when the process is fully complete. + 1. the PendingFile object + 1. the origin element +#### exceptionCallback #### +> (function): function that will be called when an exception occurs. + 1. a string formatted describing the exception + 1. the origin element + 1. the optional PendingFile object. If the exception is related to the control and not a pending file, this parameter is undefined. \ No newline at end of file diff --git a/ProjectHome.md b/ProjectHome.md new file mode 100644 index 0000000..0d69ca4 --- /dev/null +++ b/ProjectHome.md @@ -0,0 +1,88 @@ +Latest stable version : 1.1.8 + + +--- + + +The goal of this project is to provide an easy way to upload large files directly from a browser without applets or external components. + +Thanks to the new html5 features including reading and slicing files, it is now possible to proceed in sending very large files over http.
+ +This library cuts the file in slices and stream them to the server. Each slice is validated using a js and java crc32 verification. + +You can see exactly how the flow is processed [here](Flow.md) + +The unfinished files can stay on the server for an amount of configurable days before an automatic removal. + +The information related to this upload are stored on the filesystem of the server. + +The writing of the files on the filesystem is optimized using servlet 3.0 asynchronous features and a rate limiter algorithm which allows the user to define a custom upload rate for each file individually. +A maximum upload rate for all the uploads of a client and a maximum overall upload rate can be configured.
+ + +**1.0** + * upload large files: + * pause/resume + * current upload rate per file + * total progress of the upload per file + * file upload state persisted on file system (user can resume an upload after an amount of configurable days) + * crc validation of all the chunks + * multiple file uploads within the same control + * clean up of the pending files after a configured time + * independent upload rate configuration per file + * master upload rate configuration (bandwidth divided per all the current uploads) + * per client upload rate configuration (bandwidth divided per all the current client uploads) + +**1.1** + * [listener system](http://code.google.com/p/java-large-file-uploader/source/browse/trunk/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListener.java) getting events when uploads are started,paused,resumed etc... + * [authorizer plugin system](http://code.google.com/p/java-large-file-uploader/source/browse/trunk/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/authorizer/Authorizer.java) (default to allow any client to perform anything) + * [identifier plugin system](http://code.google.com/p/java-large-file-uploader/source/browse/trunk/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/identifier/IdentifierProvider.java) (default to store id in cookie) + * firebug detection (having firebug enabled can cause trouble) + + + +--- + + +This project is separated in two parts: + +### Client side ### + +Written in javascript, it sends a file splitted in chunks to a java web server and provides methods to be able to monitor the progress. + +The javascript object JavaLargeFileUploader can manage multiple concurrent uploads. + +### Server side ### + +The server-side part is a Java ARchive that shall be integrated in a Web application ARchive. Using web fragments, it exposes a servlet which handles the upload. + + +--- + + +### Setup ### + +See [Setup](http://code.google.com/p/java-large-file-uploader/wiki/Setup). + + +--- + + +### Usage ### + +The client API is managed using an instance of JavaLargeFileUploader on the javascript side. Please consult [its documentation](JavaLargeFileUploader.md) to know more about how to interact with the API. + + + +--- + + +You can download the last war of the demo [here](http://code.google.com/p/java-large-file-uploader/downloads/detail?name=demo.war) to test it. (Note that your server has to support servlet 3.0) + + +--- + + +## Known issues ## + * does not work on Internet Explorer as ie does not provide an api to slice files. + * might cause chrome to crash when uploading large files veryfast (client/server over a lan or same machine)([filereader api bug](http://code.google.com/p/chromium/issues/detail?id=114548)). I recommend you to limit the maximum bandwidth to 10MB/s per client \ No newline at end of file diff --git a/Setup.md b/Setup.md new file mode 100644 index 0000000..64b78eb --- /dev/null +++ b/Setup.md @@ -0,0 +1,52 @@ +### java ### + +This project is really easy to configure as the dependencies are a war containing a simple javascript file and a jar which includes all the web configuration (using web fragment from servlet 3.0 specification). +[Some properties](ConfigurableProperties.md) are exposed as MBeans and can be changed at runtime and others can be set directly in the javascript. + +#### Maven #### + +Just define the maven dependencies: +``` + + com.am + java-large-file-uploader-war + 1.1.8 + war + + + com.am + java-large-file-uploader-jar + 1.1.8 + +``` +And the repository: +``` + + java large file uploader repository + http://java-large-file-uploader.googlecode.com/svn/mvnrepo + +``` + +#### Spring #### + +If you are not defining a `contextConfigLocation`, no action is required. +But if you are using Spring and you are defining your own `contextConfigLocation` in your web.xml, it will override the one defined in the web fragment. + +Please add '`classpath*:/META-INF/jlfu-web-fragment-context.xml`' inside the param value. + +Example: +``` + + contextConfigLocation + + classpath*:/META-INF/jlfu-web-fragment-context.xml + /WEB-INF/spring/another-spring-configuration-file.xml + + +``` + +**/!\** And do not forget to specify `version="3.0"` in the `web-app` element of your web.xml ! + +### javascript ### + +See [JavaLargeFileUploader](JavaLargeFileUploader.md) \ No newline at end of file diff --git a/Usage.md b/Usage.md new file mode 100644 index 0000000..27e4a6b --- /dev/null +++ b/Usage.md @@ -0,0 +1,44 @@ +## Javascript ## + +All the operations available on the client side are performed using a single object instance: [JavaLargeFileUploader](http://code.google.com/p/java-large-file-uploader/wiki/JavaLargeFileUploader). + +## Java ## + +On the Java side, there are two kind of possible interactions: + +### Service ### + +JLFU also provides a few methods in [JavaLargeFileUploaderService](http://code.google.com/p/java-large-file-uploader/source/browse/trunk/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/JavaLargeFileUploaderService.java) like: +``` +getProgress(clientId, fileId) +updateEntity(clientId, entity) +writeEntity(clientId, entity) +writeEntity(File, entity) +getEntityIfPresent(clientId) +clearFile(clientId, fileId) +clearClient(clientId) +enableFileUploader() +disableFileUploader() +``` +Consult the JavaDoc for more details about all these methods. + +### Listener ### + +JLFU provides a Listener system that lets you listen to pretty much everything happening on the server side: + +``` +onNewClient(clientId) +onClientBack(clientId) +onClientInactivity(clientId, inactivityTime) +onFileUploadEnd(clientId, fileId) +onFileUploadPrepared(clientId, fileId) +onAllFileUploadsPrepared(clientId, fileIds) +onFileUploadCancelled(clientId, fileId) +onFileUploadPaused(clientId, fileId) +onFileUploadResumed(clientId, fileId) +onFileUploadProgress(clientId, fileId, FileProgressStatus) +onFileUploaderDisabled() +onFileUploaderEnabled() +``` + +You can register a [JLFUListener](http://code.google.com/p/java-large-file-uploader/source/browse/trunk/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListener.java) (or an [JLFUListenerAdapter](http://code.google.com/p/java-large-file-uploader/source/browse/trunk/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListenerAdapter.java)) to the [JLFUListenerPropagator](http://code.google.com/p/java-large-file-uploader/source/browse/trunk/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListenerPropagator.java) which will propagates all the events to the registered listeners. \ No newline at end of file diff --git a/java-large-file-uploader-demo/pom.xml b/java-large-file-uploader-demo/pom.xml deleted file mode 100644 index f8fa2e2..0000000 --- a/java-large-file-uploader-demo/pom.xml +++ /dev/null @@ -1,97 +0,0 @@ - - war - Java Large File Uploader Demo - 4.0.0 - - - com.am - java-large-file-uploader-demo - 1.1.8 - - - - - javax - javaee-web-api - 6.0 - provided - - - - - com.am - java-large-file-uploader-war - 1.1.8 - war - - - - - com.am - java-large-file-uploader-jar - 1.1.8 - - - - - - - demo - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.6 - 1.6 - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.7 - - - com.google.code.maven-svn-wagon - maven-svn-wagon - 1.4 - - - - - maven-release-plugin - 2.3 - - - - - - com.google.code.maven-svn-wagon - maven-svn-wagon - 1.4 - - - - - - - - - googlecode - svn:https://java-large-file-uploader.googlecode.com/svn/mvnrepo - - - - - - scm:svn:https://java-large-file-uploader.googlecode.com/svn/trunk - - - - - java large file uploader repository - http://java-large-file-uploader.googlecode.com/svn/mvnrepo - - - diff --git a/java-large-file-uploader-demo/src/main/resources/log4j.properties b/java-large-file-uploader-demo/src/main/resources/log4j.properties deleted file mode 100644 index 954bb2b..0000000 --- a/java-large-file-uploader-demo/src/main/resources/log4j.properties +++ /dev/null @@ -1,10 +0,0 @@ -# Loggers. - -log4j.rootLogger= DEBUG, console -log4j.logger.org.springframework = WARN - -# Appenders. - -log4j.appender.console= org.apache.log4j.ConsoleAppender -log4j.appender.console.layout= org.apache.log4j.PatternLayout - diff --git a/java-large-file-uploader-demo/src/main/resources/logging.properties b/java-large-file-uploader-demo/src/main/resources/logging.properties deleted file mode 100644 index 8eb8705..0000000 --- a/java-large-file-uploader-demo/src/main/resources/logging.properties +++ /dev/null @@ -1,2 +0,0 @@ -org.apache.catalina.core.ContainerBase.[Catalina].level = INFO -org.apache.catalina.core.ContainerBase.[Catalina].handlers = java.util.logging.ConsoleHandler \ No newline at end of file diff --git a/java-large-file-uploader-demo/src/main/webapp/WEB-INF/web.xml b/java-large-file-uploader-demo/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index c77d431..0000000 --- a/java-large-file-uploader-demo/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - index.html - - - \ No newline at end of file diff --git a/java-large-file-uploader-demo/src/main/webapp/index.html b/java-large-file-uploader-demo/src/main/webapp/index.html deleted file mode 100644 index ffdc004..0000000 --- a/java-large-file-uploader-demo/src/main/webapp/index.html +++ /dev/null @@ -1,232 +0,0 @@ - - - Java Large File Uploader Demo - - - - - - - - -
-
-
-
- Pause all - Resume all - Clear all -
- - - - \ No newline at end of file diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/pom.xml b/java-large-file-uploader-parent/java-large-file-uploader-jar/pom.xml deleted file mode 100644 index a2c28a2..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/pom.xml +++ /dev/null @@ -1,167 +0,0 @@ - - - Java Large File Uploader Jar - 4.0.0 - - - com.am - java-large-file-uploader-parent - 1.1.8 - - - java-large-file-uploader-jar - jar - - - 3.0.6.RELEASE - 4.8.2 - 11.0 - - - - - glassfish-extras-repository - http://download.java.net/maven/glassfish/org/glassfish/extras - - - - - - - - org.springframework - spring-context - ${spring.version} - - - - org.springframework - spring-web - ${spring.version} - - - - org.springframework - spring-test - ${spring.version} - - - - - - junit - junit - ${junit.version} - - - - commons-fileupload - commons-fileupload - 1.2.2 - - - - commons-io - commons-io - 2.2 - - - - cglib - cglib - 2.2 - - - - com.google.code.gson - gson - 1.7.1 - - - - joda-time - joda-time - 1.6.2 - - - - commons-lang - commons-lang - 2.4 - - - - xstream - xstream - 1.2.2 - - - - - com.google.guava - guava - ${google.guava} - - - - - org.slf4j - slf4j-log4j12 - 1.6.1 - - - - - org.glassfish.extras - glassfish-embedded-all - 3.0 - test - - - javax - javaee-web-api - 6.0 - provided - - - - - commons-httpclient - commons-httpclient - 3.1 - test - - - - org.hamcrest - hamcrest-all - 1.1 - test - - - - org.unitils - unitils-easymock - test - 3.3 - - - - org.unitils - unitils-mock - test - 3.3 - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - - diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/authorizer/Authorizer.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/authorizer/Authorizer.java deleted file mode 100644 index ba3f848..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/authorizer/Authorizer.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.am.jlfu.authorizer; - - -import java.util.UUID; - -import javax.servlet.http.HttpServletRequest; - -import com.am.jlfu.fileuploader.exception.AuthorizationException; -import com.am.jlfu.fileuploader.web.UploadServletAction; - - - -/** - * Allows or not a user to perform an operation on the JLFU api. - * - * @author antoinem - * - */ -public interface Authorizer { - - /** - * @param request - * the initial servlet request - * @param action - * the action that the client wishes to perform - * @param clientId - * the identifier of the client - * @param optionalFileIds - * if available, the file id(s) - * @throws AuthorizationException - * if the client cannot perform the action on this file - */ - void getAuthorization(HttpServletRequest request, UploadServletAction action, UUID clientId, UUID... optionalFileIds) - throws AuthorizationException; - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/authorizer/impl/DefaultAuthorizer.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/authorizer/impl/DefaultAuthorizer.java deleted file mode 100644 index 24ab29b..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/authorizer/impl/DefaultAuthorizer.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.am.jlfu.authorizer.impl; - - -import java.util.UUID; - -import javax.servlet.http.HttpServletRequest; - -import org.springframework.stereotype.Component; - -import com.am.jlfu.authorizer.Authorizer; -import com.am.jlfu.fileuploader.exception.AuthorizationException; -import com.am.jlfu.fileuploader.web.UploadServletAction; - - - -/** - * Default {@link Authorizer} that never throws an {@link AuthorizationException}. - * - * @author antoinem - * - */ -@Component -public class DefaultAuthorizer - implements Authorizer { - - @Override - public void getAuthorization(HttpServletRequest request, UploadServletAction action, UUID clientId, UUID... optionalFileId) { - // by default, all calls are authorized - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/AuthorizationException.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/AuthorizationException.java deleted file mode 100644 index 12a8ccb..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/AuthorizationException.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.am.jlfu.fileuploader.exception; - - -import java.util.Arrays; -import java.util.UUID; - -import com.am.jlfu.fileuploader.web.UploadServletAction; - - - -public class AuthorizationException extends Exception { - - public AuthorizationException(UploadServletAction actionByParameterName, UUID clientId, UUID... optionalFileIds) { - super("User " + clientId + " is not authorized to perform " + actionByParameterName + (optionalFileIds != null ? " on " + Arrays.toString(optionalFileIds) : "")); - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/BadRequestException.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/BadRequestException.java deleted file mode 100644 index fdc344f..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/BadRequestException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.am.jlfu.fileuploader.exception; - - -public class BadRequestException extends Exception { - - public BadRequestException(String message) { - super(message); - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/FileCorruptedException.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/FileCorruptedException.java deleted file mode 100644 index c8daace..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/FileCorruptedException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.am.jlfu.fileuploader.exception; - - -public class FileCorruptedException extends Exception{ - - public FileCorruptedException(String string) { - super(string); - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/FileStillProcessingException.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/FileStillProcessingException.java deleted file mode 100644 index a3dce58..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/FileStillProcessingException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.am.jlfu.fileuploader.exception; - -import java.util.UUID; - - -public class FileStillProcessingException extends Exception { - - - public FileStillProcessingException(UUID fileId) { - super("The file "+fileId+" is still in a process. AsyncRequest ignored."); - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/InvalidCrcException.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/InvalidCrcException.java deleted file mode 100644 index 114bf90..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/InvalidCrcException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.am.jlfu.fileuploader.exception; - -public class InvalidCrcException extends Exception { - - public InvalidCrcException(String crc32, String crc) { - super("The file chunk is invalid. Expected "+crc32+" but received "+crc); - } - - - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/JavaFileUploaderException.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/JavaFileUploaderException.java deleted file mode 100644 index acf6562..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/JavaFileUploaderException.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.am.jlfu.fileuploader.exception; - - -import com.am.jlfu.fileuploader.web.utils.ExceptionCodeMappingHelper.ExceptionCodeMapping; - - - -/** - * This exception contains a simple identifier ({@link #exceptionIdentifier}) so that the javascript - * can identify it and i18n it. - * - * @author antoinem - * - */ -public class JavaFileUploaderException extends Exception { - - private ExceptionCodeMapping exceptionCodeMapping; - - - - public JavaFileUploaderException() { - } - - - public JavaFileUploaderException(ExceptionCodeMapping exceptionCodeMapping) { - super(); - this.exceptionCodeMapping = exceptionCodeMapping; - } - - - public ExceptionCodeMapping getExceptionCodeMapping() { - return exceptionCodeMapping; - } - - - public void setExceptionCodeMapping(ExceptionCodeMapping exceptionCodeMapping) { - this.exceptionCodeMapping = exceptionCodeMapping; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/MissingParameterException.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/MissingParameterException.java deleted file mode 100644 index 6fea3c3..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/MissingParameterException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.am.jlfu.fileuploader.exception; - - -import com.am.jlfu.fileuploader.web.UploadServletParameter; - - - -public class MissingParameterException extends BadRequestException { - - public MissingParameterException(UploadServletParameter parameter) { - super("The parameter " + parameter.name() + " is missing for this request."); - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/UploadIsCurrentlyDisabled.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/UploadIsCurrentlyDisabled.java deleted file mode 100644 index ff70cd7..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/exception/UploadIsCurrentlyDisabled.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.am.jlfu.fileuploader.exception; - -import com.am.jlfu.staticstate.JavaLargeFileUploaderService; - - -/** - * Exception thrown if the uploads are not enabled at the moment. - * @see JavaLargeFileUploaderService#enableFileUploader() - * @see JavaLargeFileUploaderService#disableFileUploader() - * @author antoinem - */ -public class UploadIsCurrentlyDisabled extends Exception { - - public UploadIsCurrentlyDisabled() { - super("All uploads are currently suspended."); - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/CRCResult.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/CRCResult.java deleted file mode 100644 index d063b20..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/CRCResult.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.am.jlfu.fileuploader.json; - - -import java.io.Serializable; - -import com.am.jlfu.fileuploader.utils.CRCHelper; - - - -/** - * This class is the result of a method of {@link CRCHelper}. - * It includes the CRC32 value as a string ({@link #value}) and the number of bytes computed ( - * {@link #read}) - * - * @author antoinem - * @see CRCHelper - * - */ -public class CRCResult - implements Serializable { - - - /** - * generated id - */ - private static final long serialVersionUID = 5435020922997235085L; - - private String value; - private int read; - - - - public CRCResult() { - } - - - public String getCrcAsString() { - return value; - } - - - public void setCrcAsString(String crcAsString) { - this.value = crcAsString; - } - - - public int getTotalRead() { - return read; - } - - - public void setTotalRead(int streamLength) { - this.read = streamLength; - } - - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + read; - result = prime * result + ((value == null) ? 0 : value.hashCode()); - return result; - } - - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - CRCResult other = (CRCResult) obj; - if (read != other.read) - return false; - if (value == null) { - if (other.value != null) - return false; - } - else if (!value.equals(other.value)) - return false; - return true; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/FileStateJson.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/FileStateJson.java deleted file mode 100644 index 3ad7bfe..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/FileStateJson.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.am.jlfu.fileuploader.json; - - -public class FileStateJson - extends FileStateJsonBase { - - /** - * generated id - */ - private static final long serialVersionUID = 5043865795253104456L; - - /** Specifies whether the file is complete or not. */ - private boolean fileComplete; - - /** Bytes which have been completed. */ - private Long fileCompletionInBytes; - - - - /** - * Default constructor. - */ - public FileStateJson() { - super(); - } - - - public Boolean getFileComplete() { - return fileComplete; - } - - - public Long getFileCompletionInBytes() { - return fileCompletionInBytes; - } - - - public void setFileCompletionInBytes(Long fileCompletionInBytes) { - this.fileCompletionInBytes = fileCompletionInBytes; - } - - - public void setFileComplete(boolean fileComplete) { - this.fileComplete = fileComplete; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/FileStateJsonBase.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/FileStateJsonBase.java deleted file mode 100644 index 4135d1f..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/FileStateJsonBase.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.am.jlfu.fileuploader.json; - - -import java.io.Serializable; -import java.util.Date; - - -/** - * Shared entity (java/javascript) containing information about a file being uploaded.
- * @author antoinem - */ -public class FileStateJsonBase - implements Serializable { - - /** - * generated id - */ - private static final long serialVersionUID = 5043865795253104456L; - - /** The original file name. */ - private String originalFileName; - - /** The original file size */ - private Long originalFileSizeInBytes; - - /** When the file was originally created */ - private Date creationDate; - - /** - * The rate of the client in kilo bytes.
- * */ - private Long rateInKiloBytes; - - /** - * Amount of bytes that were correctly validated.
- * When resuming an upload, all bytes in the file that have not been validated are revalidated. - */ - private long crcedBytes; - - /** the first chunk crc information */ - private String firstChunkCrc; - - - - /** - * Default constructor. - */ - public FileStateJsonBase() { - super(); - } - - - public String getOriginalFileName() { - return originalFileName; - } - - - public void setOriginalFileName(String originalFileName) { - this.originalFileName = originalFileName; - } - - - public Long getOriginalFileSizeInBytes() { - return originalFileSizeInBytes; - } - - - public void setOriginalFileSizeInBytes(Long originalFileSizeInBytes) { - this.originalFileSizeInBytes = originalFileSizeInBytes; - } - - - public Long getRateInKiloBytes() { - return rateInKiloBytes; - } - - - public void setRateInKiloBytes(Long rateInKiloBytes) { - this.rateInKiloBytes = rateInKiloBytes; - } - - - public Long getCrcedBytes() { - return crcedBytes; - } - - - public void setCrcedBytes(Long crcedBytes) { - this.crcedBytes = crcedBytes; - } - - - public Date getCreationDate() { - return creationDate; - } - - - public void setCreationDate(Date creationDate) { - this.creationDate = creationDate; - } - - - public String getFirstChunkCrc() { - return firstChunkCrc; - } - - - public void setFirstChunkCrc(String firstChunkCrc) { - this.firstChunkCrc = firstChunkCrc; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/InitializationConfiguration.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/InitializationConfiguration.java deleted file mode 100644 index 2d733c1..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/InitializationConfiguration.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.am.jlfu.fileuploader.json; - - -import java.io.Serializable; -import java.util.Map; - - - -/** - * The configuration. - * - * @author antoinem - * - */ -public class InitializationConfiguration - implements Serializable { - - /** - * generated id - */ - private static final long serialVersionUID = -6955613223772661218L; - - /** - * The size of the slice in bytes. - */ - private long inByte; - - /** - * The list of the pending files. - */ - private Map pendingFiles; - - - - /** - * Default constructor - */ - public InitializationConfiguration() { - super(); - } - - - public long getInByte() { - return inByte; - } - - - public void setInByte(long inByte) { - this.inByte = inByte; - } - - - public Map getPendingFiles() { - return pendingFiles; - } - - - public void setPendingFiles(Map pendingFiles) { - this.pendingFiles = pendingFiles; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/PrepareUploadJson.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/PrepareUploadJson.java deleted file mode 100644 index 68a53b4..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/PrepareUploadJson.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.am.jlfu.fileuploader.json; - - -import java.io.Serializable; - - - -public class PrepareUploadJson - implements Serializable { - - /** - * generated id - */ - private static final long serialVersionUID = -7036071811020864930L; - - private Integer tempId; - - private String fileName; - - private Long size; - - private String crc; - - - - /** - * Default constructor. - */ - public PrepareUploadJson() { - super(); - } - - - public Integer getTempId() { - return tempId; - } - - - public void setTempId(Integer tempId) { - this.tempId = tempId; - } - - - public String getFileName() { - return fileName; - } - - - public void setFileName(String fileName) { - this.fileName = fileName; - } - - - public Long getSize() { - return size; - } - - - public void setSize(Long size) { - this.size = size; - } - - - public String getCrc() { - return crc; - } - - - public void setCrc(String crc) { - this.crc = crc; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/ProgressJson.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/ProgressJson.java deleted file mode 100644 index b172b53..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/ProgressJson.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.am.jlfu.fileuploader.json; - - -import java.io.Serializable; - - - -public class ProgressJson - implements Serializable { - - /** - * generated id - */ - private static final long serialVersionUID = -8710522591230352636L; - - protected Float progress; - protected Long uploadRate; - protected Long estimatedRemainingTimeInSeconds; - - - public ProgressJson() { - } - - - /** - * @return the percentage completed. - */ - public Float getProgress() { - return progress; - } - - - public void setProgress(Float progress) { - this.progress = progress; - } - - /** - * @return current file upload rate in byte per second. - */ - public Long getUploadRate() { - return uploadRate; - } - - - public void setUploadRate(Long uploadRate) { - this.uploadRate = uploadRate; - } - - - /** - * @return the estimated remaining time in seconds. - */ - public Long getEstimatedRemainingTimeInSeconds() { - return estimatedRemainingTimeInSeconds; - } - - - - public void setEstimatedRemainingTimeInSeconds(Long estimatedRemainingTimeInSeconds) { - this.estimatedRemainingTimeInSeconds = estimatedRemainingTimeInSeconds; - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/SimpleJsonObject.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/SimpleJsonObject.java deleted file mode 100644 index 76bc7eb..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/json/SimpleJsonObject.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.am.jlfu.fileuploader.json; - -import java.io.Serializable; - - -public class SimpleJsonObject - implements Serializable { - - /** - * generated id - */ - private static final long serialVersionUID = 1815625862539981019L; - - /** - * Value. - */ - private String value; - - - - public SimpleJsonObject(String value) { - super(); - this.value = value; - } - - - public SimpleJsonObject() { - super(); - } - - - public String getValue() { - return value; - } - - - public void setValue(String value) { - this.value = value; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/RateLimiter.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/RateLimiter.java deleted file mode 100644 index d786135..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/RateLimiter.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.am.jlfu.fileuploader.limiter; - - -import java.util.Map.Entry; -import java.util.UUID; - -import org.apache.commons.lang.time.DateUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; - - - -@Component -public class RateLimiter -{ - - - private static final Logger log = LoggerFactory.getLogger(RateLimiter.class); - - @Autowired - RateLimiterConfigurationManager uploadProcessingConfigurationManager; - - @Autowired - UploadProcessingOperationManager uploadProcessingOperationManager; - - /** Number of times the bucket is filled per second. */ - public static final int NUMBER_OF_TIMES_THE_BUCKET_IS_FILLED_PER_SECOND = 10; - public static final long BUCKET_FILLED_EVERY_X_MILLISECONDS = DateUtils.MILLIS_PER_SECOND / NUMBER_OF_TIMES_THE_BUCKET_IS_FILLED_PER_SECOND; - - - - @Scheduled(fixedRate = BUCKET_FILLED_EVERY_X_MILLISECONDS) - public void fillBucket() { - - // first we need to calculate how many uploads are currently being processed - int requestsBeingProcessed = 0; - for (Entry entry : uploadProcessingConfigurationManager.getRequestEntries()) { - requestsBeingProcessed += entry.getValue().isProcessing() ? 1 : 0; - } - log.trace("refilling the upload allowance of the " + requestsBeingProcessed + " uploads being processed"); - - // if we have entries - if (requestsBeingProcessed > 0) { - - // calculate maximum limitation - // and assign it - uploadProcessingOperationManager.getMasterProcessingOperation().setDownloadAllowanceForIteration( - uploadProcessingConfigurationManager.getMaximumOverAllRateInKiloBytes() * 1024 / NUMBER_OF_TIMES_THE_BUCKET_IS_FILLED_PER_SECOND); - - // for all pending operation - for (Entry entry : uploadProcessingOperationManager.getClientsAndRequestsProcessingOperation() - .entrySet()) { - - // process - processEntry(entry); - - } - - } - } - - - private void processEntry(Entry entry) { - - // default per request is set to the maximum, so basically maximum by client - long allowedCapacityPerSecond = uploadProcessingConfigurationManager.getMaximumRatePerClientInKiloBytes() * 1024; - - // extract the configuration element - final RequestUploadProcessingConfiguration requestUploadProcessingConfiguration = - uploadProcessingConfigurationManager.getUploadProcessingConfiguration(entry.getKey()); - - // calculate from the rate in the configuration - Long rateInKiloBytes = requestUploadProcessingConfiguration.getRateInKiloBytes(); - if (rateInKiloBytes != null) { - allowedCapacityPerSecond = (int) (rateInKiloBytes * 1024); - } - - // calculate statistics - final long instantRateInBytes = entry.getValue().getAndResetBytesWritten(); - requestUploadProcessingConfiguration.setInstantRateInBytes(instantRateInBytes); - - // calculate what we can write per iteration - final long allowedCapacityPerIteration = allowedCapacityPerSecond / NUMBER_OF_TIMES_THE_BUCKET_IS_FILLED_PER_SECOND; - - // set it to the rate conf element - entry.getValue().setDownloadAllowanceForIteration(allowedCapacityPerIteration); - - log.trace("giving an allowance of " + allowedCapacityPerIteration + " bytes to " + entry.getKey() + ". (consumed " + - instantRateInBytes + " bytes during previous iteration)"); - - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/RateLimiterConfigurationManager.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/RateLimiterConfigurationManager.java deleted file mode 100644 index 62de922..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/RateLimiterConfigurationManager.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.am.jlfu.fileuploader.limiter; - - -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import javax.annotation.PostConstruct; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.jmx.export.annotation.ManagedAttribute; -import org.springframework.jmx.export.annotation.ManagedResource; -import org.springframework.stereotype.Component; - -import com.am.jlfu.notifier.JLFUListenerPropagator; -import com.am.jlfu.staticstate.JavaLargeFileUploaderService; -import com.am.jlfu.staticstate.StaticStateManager; -import com.am.jlfu.staticstate.entities.StaticFileState; -import com.am.jlfu.staticstate.entities.StaticStatePersistedOnFileSystemEntity; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.cache.RemovalCause; -import com.google.common.cache.RemovalListener; -import com.google.common.cache.RemovalNotification; - - - -@Component -@ManagedResource(objectName = "JavaLargeFileUploader:name=rateLimiterConfiguration") -public class RateLimiterConfigurationManager -{ - - private static final Logger log = LoggerFactory.getLogger(RateLimiterConfigurationManager.class); - - /** Client is evicted from the map when not accessed for that duration */ - @Value("jlfu{jlfu.rateLimiterConfiguration.evictionTimeInSeconds:120}") - public int clientEvictionTimeInSeconds; - - @Autowired - private JLFUListenerPropagator jlfuListenerPropagator; - - @Autowired - private StaticStateManager staticStateManager; - - @Autowired - private JavaLargeFileUploaderService staticStateManagerService; - - /** the cache containing all configuration for requests and clients */ - LoadingCache configurationMap; - - - - @PostConstruct - private void initMap() { - configurationMap = CacheBuilder.newBuilder() - .removalListener(new RemovalListener() { - - @Override - public void onRemoval(RemovalNotification notification) { - log.debug("removal from requestconfig of " + notification.getKey() + " because of " + notification.getCause()); - remove(notification.getCause(), notification.getKey()); - } - - - }) - .expireAfterAccess(clientEvictionTimeInSeconds, TimeUnit.SECONDS) - .build(new CacheLoader() { - - @Override - public RequestUploadProcessingConfiguration load(UUID arg0) - throws Exception { - return new RequestUploadProcessingConfiguration(); - } - }); - } - - - - private UploadProcessingConfiguration masterProcessingConfiguration = new UploadProcessingConfiguration(); - - // /////////////// - // Configuration// - // /////////////// - - // 10mb/s - @Value("jlfu{jlfu.ratelimiter.maximumRatePerClientInKiloBytes:10240}") - private volatile long maximumRatePerClientInKiloBytes; - - - // 10mb/s - @Value("jlfu{jlfu.ratelimiter.maximumOverAllRateInKiloBytes:10240}") - private volatile long maximumOverAllRateInKiloBytes; - - - - // /////////////// - - - void remove(RemovalCause cause, UUID key) { - - // if expired - if (cause.equals(RemovalCause.EXPIRED)) { - - // check if client id is in state - final StaticStatePersistedOnFileSystemEntity entityIfPresentWithIdentifier = - staticStateManagerService.getEntityIfPresent(key); - - if (entityIfPresentWithIdentifier != null) { - - // if one of the file is not complete, it is not a natural removal - // but a - // timeout!! we propagate the event - for (Entry lavds : entityIfPresentWithIdentifier.getFileStates().entrySet()) { - if (!lavds.getValue().getStaticFileStateJson().getCrcedBytes().equals(lavds.getValue().getStaticFileStateJson() - .getOriginalFileSizeInBytes())) { - log.debug("inactivity detected for client " + key); - jlfuListenerPropagator.getPropagator().onClientInactivity(key, clientEvictionTimeInSeconds); - return; - } - } - log.debug("natural removal for client " + key); - - } - } - } - - - public Set> getRequestEntries() { - return configurationMap.asMap().entrySet(); - } - - - public void reset(UUID fileId) { - final RequestUploadProcessingConfiguration unchecked = configurationMap.getUnchecked(fileId); - unchecked.setProcessing(false); - } - - - public void assignRateToRequest(UUID fileId, Long rateInKiloBytes) { - configurationMap.getUnchecked(fileId).rateInKiloBytes = rateInKiloBytes; - } - - - public Long getUploadState(UUID requestIdentifier) { - return configurationMap.getUnchecked(requestIdentifier).getInstantRateInBytes(); - } - - - public RequestUploadProcessingConfiguration getUploadProcessingConfiguration(UUID uuid) { - return configurationMap.getUnchecked(uuid); - } - - - @ManagedAttribute - public long getMaximumRatePerClientInKiloBytes() { - return maximumRatePerClientInKiloBytes; - } - - - @ManagedAttribute - public void setMaximumRatePerClientInKiloBytes(long maximumRatePerClientInKiloBytes) { - this.maximumRatePerClientInKiloBytes = maximumRatePerClientInKiloBytes; - } - - - @ManagedAttribute - public long getMaximumOverAllRateInKiloBytes() { - return maximumOverAllRateInKiloBytes; - } - - - @ManagedAttribute - public void setMaximumOverAllRateInKiloBytes(long maximumOverAllRateInKiloBytes) { - this.maximumOverAllRateInKiloBytes = maximumOverAllRateInKiloBytes; - } - - - public UploadProcessingConfiguration getMasterProcessingConfiguration() { - return masterProcessingConfiguration; - } - - - public void setClientEvictionTimeInSeconds(int clientEvictionTimeInSeconds) { - this.clientEvictionTimeInSeconds = clientEvictionTimeInSeconds; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/RequestUploadProcessingConfiguration.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/RequestUploadProcessingConfiguration.java deleted file mode 100644 index 5a2488e..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/RequestUploadProcessingConfiguration.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.am.jlfu.fileuploader.limiter; - - -public class RequestUploadProcessingConfiguration extends UploadProcessingConfiguration { - - /** - * Boolean specifying whether the upload is processing or not. - */ - private volatile boolean isProcessing; - - /** - * Boolean specifying whether the client uploading the file is telling the server that it should not process the stream read. - */ - private volatile boolean paused; - - - public boolean isProcessing() { - return isProcessing; - } - - - public void setProcessing(boolean isProcessing) { - this.isProcessing = isProcessing; - } - - - public void pause() { - this.paused = true; - } - - public void resume() { - this.paused = false; - } - - public boolean isPaused() { - return this.paused; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/UploadProcessingConfiguration.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/UploadProcessingConfiguration.java deleted file mode 100644 index 469e972..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/UploadProcessingConfiguration.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.am.jlfu.fileuploader.limiter; - - -public class UploadProcessingConfiguration { - - - /** - * The desired upload rate.
- * Can be null (the maxmimum rate is applied). - */ - volatile Long rateInKiloBytes; - - /** - * The statistics. - * - * @return - */ - long instantRateInBytes; - int instantRateInBytesCounter; - Object instantRateInBytesLock = new Object(); - - - - public Long getRateInKiloBytes() { - return rateInKiloBytes; - } - - - void setInstantRateInBytes(long instantRateInBytes) { - synchronized (instantRateInBytesLock) { - this.instantRateInBytesCounter++; - this.instantRateInBytes += instantRateInBytes; - } - } - - - long getInstantRateInBytes() { - int returnValue = 0; - synchronized (instantRateInBytesLock) { - if (instantRateInBytesCounter > 0) { - returnValue = ((int) instantRateInBytes / instantRateInBytesCounter) * RateLimiter.NUMBER_OF_TIMES_THE_BUCKET_IS_FILLED_PER_SECOND; - - // reset every second or so - if (instantRateInBytesCounter > RateLimiter.NUMBER_OF_TIMES_THE_BUCKET_IS_FILLED_PER_SECOND) { - instantRateInBytes = instantRateInBytesCounter = 0; - } - } - } - return returnValue; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/UploadProcessingOperation.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/UploadProcessingOperation.java deleted file mode 100644 index 1af5b7c..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/UploadProcessingOperation.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.am.jlfu.fileuploader.limiter; - - -public class UploadProcessingOperation { - - /** - * Specifies the amount of bytes that have been written - * */ - private long bytesWritten; - private Object bytesWrittenLock = new Object(); - - /** - * Specifies the amount of bytes that can be uploaded for an iteration of the refill process - * of {@link RateLimiter} - * */ - private long downloadAllowanceForIteration; - private Object downloadAllowanceForIterationLock = new Object(); - - - - public long getDownloadAllowanceForIteration() { - synchronized (downloadAllowanceForIterationLock) { - return downloadAllowanceForIteration; - } - } - - - void setDownloadAllowanceForIteration(long downloadAllowanceForIteration) { - synchronized (downloadAllowanceForIterationLock) { - this.downloadAllowanceForIteration = downloadAllowanceForIteration; - } - } - - - public long getAndResetBytesWritten() { - synchronized (bytesWrittenLock) { - final long temp = bytesWritten; - bytesWritten = 0; - return temp; - } - } - - - /** - * Specifies the bytes that have been read from the files. - * - * @param bytesConsumed - */ - public void bytesConsumedFromAllowance(long bytesConsumed) { - synchronized (bytesWrittenLock) { - synchronized (downloadAllowanceForIterationLock) { - bytesWritten += bytesConsumed; - downloadAllowanceForIteration -= bytesConsumed; - } - } - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/UploadProcessingOperationManager.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/UploadProcessingOperationManager.java deleted file mode 100644 index 5245fe9..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/UploadProcessingOperationManager.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.am.jlfu.fileuploader.limiter; - - -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentMap; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.am.jlfu.fileuploader.utils.ClientToFilesMap; -import com.google.common.collect.Maps; - - - -@Component -public class UploadProcessingOperationManager { - - private static final Logger log = LoggerFactory.getLogger(UploadProcessingOperationManager.class); - - @Autowired - ClientToFilesMap clientToFilesMap; - - // //////////// - // operation// - // //////////// - - /** Operation for clients and requests. */ - final ConcurrentMap clientsAndRequestsProcessingOperation = Maps.newConcurrentMap(); - - /** Operation for master. */ - final UploadProcessingOperation masterProcessingOperation = new UploadProcessingOperation(); - - - public Map getClientsAndRequestsProcessingOperation() { - return clientsAndRequestsProcessingOperation; - } - - - public void startOperation(UUID clientId, UUID fileId) { - log.debug("starting operation for client "+clientId + " and file "+fileId); - - // create the request one - // XXX are we sure that there is only one there? - clientsAndRequestsProcessingOperation.put(fileId, new UploadProcessingOperation()); - - // get or create the client one - clientsAndRequestsProcessingOperation.putIfAbsent(clientId, new UploadProcessingOperation()); - - // mapping - Set set = clientToFilesMap.get(clientId); - if (set == null) { - set = new HashSet(); - clientToFilesMap.put(clientId, set); - } - synchronized (set) { - set.add(fileId); - } - - } - - - public void stopOperation(UUID clientId, UUID fileId) { - log.debug("stopping operation for client "+clientId + " and file "+fileId); - - // remove from map - clientsAndRequestsProcessingOperation.remove(fileId); - - // remove mapping - Set set = clientToFilesMap.get(clientId); - if (set != null) { - synchronized (set) { - set.remove(fileId); - - // if client is empty, remove client - final boolean noreMoreUploadsForThisClient = set.isEmpty(); - if (noreMoreUploadsForThisClient) { - clientToFilesMap.remove(clientId); - clientsAndRequestsProcessingOperation.remove(clientId); - } - } - } - - } - - - public UploadProcessingOperation getClientProcessingOperation(UUID clientId) { - return clientsAndRequestsProcessingOperation.get(clientId); - } - - - public UploadProcessingOperation getFileProcessingOperation(UUID fileId) { - return clientsAndRequestsProcessingOperation.get(fileId); - } - - - public UploadProcessingOperation getMasterProcessingOperation() { - return masterProcessingOperation; - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/logic/UploadProcessor.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/logic/UploadProcessor.java deleted file mode 100644 index 5c73071..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/logic/UploadProcessor.java +++ /dev/null @@ -1,490 +0,0 @@ -package com.am.jlfu.fileuploader.logic; - - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.SortedMap; -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; - -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.jmx.export.annotation.ManagedAttribute; -import org.springframework.jmx.export.annotation.ManagedResource; -import org.springframework.stereotype.Component; - -import com.am.jlfu.fileuploader.exception.FileCorruptedException; -import com.am.jlfu.fileuploader.exception.FileStillProcessingException; -import com.am.jlfu.fileuploader.exception.InvalidCrcException; -import com.am.jlfu.fileuploader.json.CRCResult; -import com.am.jlfu.fileuploader.json.FileStateJson; -import com.am.jlfu.fileuploader.json.FileStateJsonBase; -import com.am.jlfu.fileuploader.json.InitializationConfiguration; -import com.am.jlfu.fileuploader.json.PrepareUploadJson; -import com.am.jlfu.fileuploader.json.ProgressJson; -import com.am.jlfu.fileuploader.limiter.RateLimiterConfigurationManager; -import com.am.jlfu.fileuploader.limiter.RequestUploadProcessingConfiguration; -import com.am.jlfu.fileuploader.utils.CRCHelper; -import com.am.jlfu.fileuploader.utils.ProgressManager; -import com.am.jlfu.fileuploader.utils.RemainingTimeEstimator; -import com.am.jlfu.notifier.JLFUListenerPropagator; -import com.am.jlfu.staticstate.JavaLargeFileUploaderService; -import com.am.jlfu.staticstate.StaticStateDirectoryManager; -import com.am.jlfu.staticstate.StaticStateIdentifierManager; -import com.am.jlfu.staticstate.StaticStateManager; -import com.am.jlfu.staticstate.entities.FileProgressStatus; -import com.am.jlfu.staticstate.entities.StaticFileState; -import com.am.jlfu.staticstate.entities.StaticStatePersistedOnFileSystemEntity; -import com.google.common.base.Functions; -import com.google.common.collect.ImmutableSortedMap; -import com.google.common.collect.Maps; -import com.google.common.collect.Maps.EntryTransformer; -import com.google.common.collect.Ordering; - - - -@Component -@ManagedResource(objectName = "JavaLargeFileUploader:name=uploadServletProcessor") -public class UploadProcessor { - - private static final Logger log = LoggerFactory.getLogger(UploadProcessor.class); - - @Autowired - CRCHelper crcHelper; - - @Autowired - RateLimiterConfigurationManager uploadProcessingConfigurationManager; - - @Autowired - StaticStateManager staticStateManager; - - @Autowired - JavaLargeFileUploaderService staticStateManagerService; - - @Autowired - StaticStateIdentifierManager staticStateIdentifierManager; - - @Autowired - StaticStateDirectoryManager staticStateDirectoryManager; - - @Autowired - ProgressManager progressManager; - - @Autowired - RemainingTimeEstimator remainingTimeEstimator; - - @Autowired - private JLFUListenerPropagator jlfuListenerPropagator; - - public static final int SIZE_OF_FIRST_CHUNK_VALIDATION = 8192; - - /** - * Size of a slice
- * Default to 10MB. - */ - @Value("jlfu{jlfu.sliceSizeInBytes:10485760}") - private long sliceSizeInBytes; - - /** - * Keeps the original name of the uploaded files.
- * If false, the name will be a {@link UUID} which will guarantee no name-collision.
- * Default to false - */ - @Value("jlfu{jlfu.keepOriginalFileName:false}") - private boolean keepOriginalFileName; - - public InitializationConfiguration getConfig(UUID clientId) { - - // specify the client id - if (clientId != null) { - staticStateIdentifierManager.setIdentifier(clientId); - } - - // prepare - InitializationConfiguration config = new InitializationConfiguration(); - StaticStatePersistedOnFileSystemEntity entity = staticStateManager.getEntity(); - - if (entity != null) { - - // order files by age - Ordering ordering = Ordering.from(new Comparator() { - - @Override - public int compare(StaticFileState o1, StaticFileState o2) { - int compareTo = o1.getStaticFileStateJson().getCreationDate().compareTo(o2.getStaticFileStateJson().getCreationDate()); - return compareTo != 0 ? compareTo : 1; - } - - }).onResultOf(Functions.forMap(entity.getFileStates())); - - // apply comparator - ImmutableSortedMap sortedMap = ImmutableSortedMap.copyOf(entity.getFileStates(), ordering); - - // fill pending files from static state - final SortedMap transformEntries = - Maps.transformEntries(sortedMap, new EntryTransformer() { - - @Override - public FileStateJson transformEntry(UUID fileId, StaticFileState value) { - return getFileStateJson(fileId, value); - } - }); - - // change keys - Map newMap = Maps.newHashMap(); - for (Entry entry : transformEntries.entrySet()) { - newMap.put(entry.getKey().toString(), entry.getValue()); - - //also, if we have a configuration existing for this file, we resume it - resume(entry.getKey()); - } - - // apply transformed map - config.setPendingFiles(newMap); - - } - - // fill configuration - config.setInByte(sliceSizeInBytes); - - return config; - } - - - - - private FileStateJson getFileStateJson(UUID fileId, StaticFileState value) { - - // process - File file = new File(value.getAbsoluteFullPathOfUploadedFile()); - Long fileSize = file.length(); - - FileStateJsonBase staticFileStateJson = value.getStaticFileStateJson(); - FileStateJson fileStateJson = new FileStateJson(); - fileStateJson.setFileComplete(staticFileStateJson.getCrcedBytes().equals(staticFileStateJson.getOriginalFileSizeInBytes())); - fileStateJson.setFileCompletionInBytes(fileSize); - fileStateJson.setOriginalFileName(staticFileStateJson.getOriginalFileName()); - fileStateJson.setOriginalFileSizeInBytes(staticFileStateJson.getOriginalFileSizeInBytes()); - fileStateJson.setRateInKiloBytes(staticFileStateJson.getRateInKiloBytes()); - fileStateJson.setCrcedBytes(staticFileStateJson.getCrcedBytes()); - fileStateJson.setFirstChunkCrc(staticFileStateJson.getFirstChunkCrc()); - fileStateJson.setCreationDate(staticFileStateJson.getCreationDate()); - log.debug("returning pending file " + fileStateJson.getOriginalFileName() + " with target size " + - fileStateJson.getOriginalFileSizeInBytes() + " out of " + fileSize + " completed which includes " + - fileStateJson.getCrcedBytes() + " bytes validated and " + (fileSize - fileStateJson.getCrcedBytes()) + " unvalidated."); - - return fileStateJson; - } - - - public UUID prepareUpload(Long size, String fileName, String crc) - throws IOException { - - // retrieve model - StaticStatePersistedOnFileSystemEntity model = staticStateManager.getEntity(); - - // extract the extension of the filename - String fileExtension = extractExtensionOfFileName(fileName); - - // create a new file for it - UUID fileId = UUID.randomUUID(); - File file = new File(staticStateDirectoryManager.getUUIDFileParent(), keepOriginalFileName ? fileName : fileId + fileExtension); - file.createNewFile(); - StaticFileState fileState = new StaticFileState(); - FileStateJsonBase jsonFileState = new FileStateJsonBase(); - fileState.setStaticFileStateJson(jsonFileState); - fileState.setAbsoluteFullPathOfUploadedFile(file.getAbsolutePath()); - model.getFileStates().put(fileId, fileState); - - // add info to the state - jsonFileState.setOriginalFileName(fileName); - jsonFileState.setOriginalFileSizeInBytes(size); - jsonFileState.setFirstChunkCrc(crc); - jsonFileState.setCreationDate(new Date()); - - // write the state - staticStateManager.updateEntity(model); - - // call listener - jlfuListenerPropagator.getPropagator().onFileUploadPrepared(staticStateIdentifierManager.getIdentifier(), fileId); - - // and returns the file identifier - log.debug("File prepared for client " + staticStateIdentifierManager.getIdentifier() + " at path " + file.getAbsolutePath()); - return fileId; - - } - - - public HashMap prepareUpload(PrepareUploadJson[] fromJson) - throws IOException { - HashMap returnMap = Maps.newHashMap(); - - // for all of them - for (PrepareUploadJson prepareUploadJson : fromJson) { - - // prepare it - UUID idOfTheFile = - prepareUpload(prepareUploadJson.getSize(), prepareUploadJson.getFileName(), prepareUploadJson.getCrc()); - - // put in map - returnMap.put(prepareUploadJson.getTempId().toString(), idOfTheFile); - - // notify listener - jlfuListenerPropagator.getPropagator().onFileUploadPrepared(staticStateIdentifierManager.getIdentifier(), idOfTheFile); - - } - - // notify that all are processed - jlfuListenerPropagator.getPropagator().onAllFileUploadsPrepared(staticStateIdentifierManager.getIdentifier(), returnMap.values()); - - return returnMap; - } - - - private String extractExtensionOfFileName(String fileName) { - String[] split = fileName.split("\\."); - String fileExtension = ""; - if (split.length > 1) { - if (split.length > 0) { - fileExtension = '.' + split[split.length - 1]; - } - } - return fileExtension; - } - - - - public void clearFile(UUID fileId) - throws InterruptedException, ExecutionException, TimeoutException { - - // specify as paused - pause(fileId); - - // delete - staticStateManager.clearFile(fileId); - - // then call listener - jlfuListenerPropagator.getPropagator().onFileUploadCancelled(staticStateIdentifierManager.getIdentifier(), fileId); - } - - - public void clearAll() - throws InterruptedException, ExecutionException, TimeoutException { - - //amorce cancellation for all the files - for (UUID fileId : staticStateManager.getEntity().getFileStates().keySet()) { - pause(fileId); - } - - // clear everything - staticStateManager.clear(); - } - - - - - public ProgressJson getProgress(UUID fileId) - throws FileNotFoundException { - - // progress - FileProgressStatus progress = progressManager.getProgress(fileId); - - //return values - ProgressJson progressJson = new ProgressJson(); - if (progress != null) { - progressJson.setProgress(progress.getProgress()); - progressJson.setEstimatedRemainingTimeInSeconds(progress.getEstimatedRemainingTimeInSeconds()); - progressJson.setUploadRate(progress.getUploadRate()); - } else { - progressJson.setProgress(0f); - progressJson.setEstimatedRemainingTimeInSeconds(0l); - progressJson.setUploadRate(0l); - } - return progressJson; - } - - - public void setUploadRate(UUID fileId, Long rate) { - - // set the rate - uploadProcessingConfigurationManager.assignRateToRequest(fileId, rate); - - // save it for the file with this file id - StaticStatePersistedOnFileSystemEntity entity = staticStateManager.getEntity(); - entity.getFileStates().get(fileId).getStaticFileStateJson().setRateInKiloBytes(rate); - - // persist changes - staticStateManager.updateEntity(entity); - } - - - public void pauseFile(List uuids) { - - // for all these files - for (UUID uuid : uuids) { - - //specifyStreamIsExpectedToClose - pause(uuid); - - // then call listener - jlfuListenerPropagator.getPropagator().onFileUploadPaused(staticStateIdentifierManager.getIdentifier(), uuid); - } - - } - - - public FileStateJson resumeFile(UUID fileId) throws FileNotFoundException { - - //check if we have this file - StaticFileState value = staticStateManager.getEntity().getFileStates().get(fileId); - if (value == null) { - throw new FileNotFoundException("File with id " + fileId + " not found"); - } - - //resume the configuration - resume(fileId); - - // then call listener - jlfuListenerPropagator.getPropagator().onFileUploadResumed(staticStateIdentifierManager.getIdentifier(), fileId); - - // and return some information about it - return getFileStateJson(fileId, value); - } - - - public void verifyCrcOfUncheckedPart(UUID fileId, String inputCrc) - throws IOException, InvalidCrcException, FileCorruptedException, FileStillProcessingException { - log.debug("validating the bytes that have not been validated from the previous interrupted upload for file " + - fileId); - - // get entity - StaticStatePersistedOnFileSystemEntity model = staticStateManager.getEntity(); - - // get the file - StaticFileState fileState = model.getFileStates().get(fileId); - if (fileState == null) { - throw new FileNotFoundException("File with id " + fileId + " not found"); - } - File file = new File(fileState.getAbsoluteFullPathOfUploadedFile()); - - - // if the file does not exist, there is an issue! - if (!file.exists()) { - throw new FileNotFoundException("File with id " + fileId + " not found"); - } - - //get request conf - RequestUploadProcessingConfiguration uploadProcessingConfiguration = uploadProcessingConfigurationManager.getUploadProcessingConfiguration(fileId); - - //unpause the file - resume(fileId, uploadProcessingConfiguration); - - //check if this file is processing - if (uploadProcessingConfiguration.isProcessing()) { - throw new FileStillProcessingException(fileId); - } - - // open the file stream - FileInputStream fileInputStream = null; - try { - fileInputStream = new FileInputStream(file); - // skip the crced part - fileInputStream.skip(fileState.getStaticFileStateJson().getCrcedBytes()); - - // read the crc - final CRCResult fileCrc = crcHelper.getBufferedCrc(fileInputStream); - - // compare them - log.debug("validating chunk crc " + fileCrc.getCrcAsString() + " against " + inputCrc); - - // if not equal, we have an issue: - if (!fileCrc.getCrcAsString().equals(inputCrc)) { - log.debug("invalid crc ... now truncating file to match validated bytes " + fileState.getStaticFileStateJson().getCrcedBytes()); - - // we are just sure now that the file before the crc validated is actually valid, and - // after that, it seems it is not - // so we get the file and remove everything after that crc validation so that user can - // resume the fileupload from there. - - // truncate the file - RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rwd"); - randomAccessFile.setLength(fileState.getStaticFileStateJson().getCrcedBytes()); - randomAccessFile.close(); - - // throw the exception - throw new InvalidCrcException(fileCrc.getCrcAsString(), inputCrc); - } - // if correct, we can add these bytes as validated inside the file - else { - staticStateManager.setCrcBytesValidated(staticStateIdentifierManager.getIdentifier(), fileId, - fileCrc.getTotalRead()); - } - - } finally { - IOUtils.closeQuietly(fileInputStream); - } - } - - - - - private void showDif(byte[] a, byte[] b) { - - log.debug("comparing " + a + " to " + b); - log.debug("size: " + a.length + " " + b.length); - for (int i = 0; i < Math.min(a.length, b.length); i++) { - if (!Byte.valueOf(a[i]).equals(Byte.valueOf(b[i]))) { - log.debug("different byte at index " + i + " : " + Byte.valueOf(a[i]) + " " + Byte.valueOf(b[i])); - } - } - if (a.length != b.length) { - log.debug("arrays do not have a similar size so i was impossible to compare " + Math.abs(a.length - b.length) + " bytes."); - } - - } - - - @ManagedAttribute - public long getSliceSizeInBytes() { - return sliceSizeInBytes; - } - - - @ManagedAttribute - public void setSliceSizeInBytes(long sliceSizeInBytes) { - this.sliceSizeInBytes = sliceSizeInBytes; - } - - - - private void resume(UUID fileId) { - resume(fileId, uploadProcessingConfigurationManager.getUploadProcessingConfiguration(fileId)); - } - - private void resume(UUID fileId, RequestUploadProcessingConfiguration uploadProcessingConfiguration) { - synchronized (uploadProcessingConfiguration) { - uploadProcessingConfiguration.resume(); - } - } - - private void pause(UUID fileId) { - RequestUploadProcessingConfiguration uploadProcessingConfiguration = uploadProcessingConfigurationManager.getUploadProcessingConfiguration(fileId); - synchronized (uploadProcessingConfiguration) { - uploadProcessingConfiguration.pause(); - } - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/logic/UploadServletAsyncProcessor.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/logic/UploadServletAsyncProcessor.java deleted file mode 100644 index 3558eec..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/logic/UploadServletAsyncProcessor.java +++ /dev/null @@ -1,409 +0,0 @@ -package com.am.jlfu.fileuploader.logic; - - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Date; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.zip.CRC32; - -import javax.annotation.PreDestroy; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jmx.export.annotation.ManagedAttribute; -import org.springframework.jmx.export.annotation.ManagedResource; -import org.springframework.stereotype.Component; - -import com.am.jlfu.fileuploader.exception.FileCorruptedException; -import com.am.jlfu.fileuploader.exception.InvalidCrcException; -import com.am.jlfu.fileuploader.exception.UploadIsCurrentlyDisabled; -import com.am.jlfu.fileuploader.json.FileStateJsonBase; -import com.am.jlfu.fileuploader.limiter.RateLimiter; -import com.am.jlfu.fileuploader.limiter.RateLimiterConfigurationManager; -import com.am.jlfu.fileuploader.limiter.RequestUploadProcessingConfiguration; -import com.am.jlfu.fileuploader.limiter.UploadProcessingOperation; -import com.am.jlfu.fileuploader.limiter.UploadProcessingOperationManager; -import com.am.jlfu.staticstate.StaticStateIdentifierManager; -import com.am.jlfu.staticstate.StaticStateManager; -import com.am.jlfu.staticstate.entities.StaticFileState; -import com.am.jlfu.staticstate.entities.StaticStatePersistedOnFileSystemEntity; - - - -@Component -@ManagedResource(objectName = "JavaLargeFileUploader:name=uploadServletAsyncProcessor") -public class UploadServletAsyncProcessor { - - /** The size of the buffer in bytes */ - public static final int SIZE_OF_THE_BUFFER_IN_BYTES = 8192;// 8KB - - private static final Logger log = LoggerFactory.getLogger(UploadServletAsyncProcessor.class); - - @Autowired - private RateLimiterConfigurationManager uploadProcessingConfigurationManager; - - @Autowired - private StaticStateManager staticStateManager; - - @Autowired - private UploadProcessingOperationManager uploadProcessingOperationManager; - - @Autowired - private StaticStateIdentifierManager staticStateIdentifierManager; - - /** The executor that process the stream */ - private ScheduledThreadPoolExecutor uploadWorkersPool = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(10); - - @PreDestroy - private void destroy() throws InterruptedException { - log.debug("destroying executor"); - uploadWorkersPool.shutdown(); - if (!uploadWorkersPool.awaitTermination(1, TimeUnit.MINUTES)) { - log.error("executor timed out"); - List shutdownNow = uploadWorkersPool.shutdownNow(); - for (Runnable runnable : shutdownNow) { - log.error(runnable + "has not been terminated"); - } - } - } - - - /** Specifies whether the uploads should be processed or not. */ - private volatile boolean enabled = true; - - public void process(StaticFileState fileState, UUID fileId, String crc, InputStream inputStream, - WriteChunkCompletionListener completionListener) - throws FileNotFoundException - { - - // get identifier - UUID clientId = staticStateIdentifierManager.getIdentifier(); - - // extract the corresponding request entity from map - final RequestUploadProcessingConfiguration requestUploadProcessingConfiguration = - uploadProcessingConfigurationManager.getUploadProcessingConfiguration(fileId); - - // get static file state - File file = new File(fileState.getAbsoluteFullPathOfUploadedFile()); - - // if there is no configuration in the map - if (requestUploadProcessingConfiguration.getRateInKiloBytes() == null) { - - // and if there is a specific configuration in the file - FileStateJsonBase staticFileStateJson = fileState.getStaticFileStateJson(); - if (staticFileStateJson != null && staticFileStateJson.getRateInKiloBytes() != null) { - - // use it - uploadProcessingConfigurationManager.assignRateToRequest(fileId, staticFileStateJson.getRateInKiloBytes()); - - } - } - - - // if the file does not exist, there is an issue! - if (!file.exists()) { - throw new FileNotFoundException("File with id " + fileId + " not found"); - } - - // initialize the streams - FileOutputStream outputStream = new FileOutputStream(file, true); - - // get all the processing operation - uploadProcessingOperationManager.startOperation(clientId, fileId); - final UploadProcessingOperation masterProcessingOperation = uploadProcessingOperationManager.getMasterProcessingOperation(); - final UploadProcessingOperation clientProcessingOperation = uploadProcessingOperationManager.getClientProcessingOperation(clientId); - final UploadProcessingOperation requestProcessingOperation = uploadProcessingOperationManager.getFileProcessingOperation(fileId); - - - // init the task - final WriteChunkToFileTask task = - new WriteChunkToFileTask(fileId, requestProcessingOperation, clientProcessingOperation, requestUploadProcessingConfiguration, - masterProcessingOperation, crc, inputStream, - outputStream, completionListener, clientId); - - // mark the file as processing - requestUploadProcessingConfiguration.setProcessing(true); - - // then submit the task to the workers pool - uploadWorkersPool.submit(task); - - } - - - - public interface WriteChunkCompletionListener { - - public void error(Exception exception); - - - public void success(); - } - - public class WriteChunkToFileTask - implements Callable { - - - private final InputStream inputStream; - private final FileOutputStream outputStream; - private final UUID fileId; - private final UUID clientId; - private final String crc; - - private final WriteChunkCompletionListener completionListener; - - private UploadProcessingOperation requestUploadProcessingOperation; - private UploadProcessingOperation clientUploadProcessingOperation; - private UploadProcessingOperation masterUploadProcessingOperation; - private RequestUploadProcessingConfiguration requestUploadProcessingConfiguration; - - private CRC32 crc32 = new CRC32(); - private long byteProcessed; - private long completionTimeTakenReference; - - - - public WriteChunkToFileTask(UUID fileId, UploadProcessingOperation requestOperation, - UploadProcessingOperation clientOperation, RequestUploadProcessingConfiguration requestUploadProcessingConfiguration, UploadProcessingOperation masterProcessingOperation, - String crc, - InputStream inputStream, - FileOutputStream outputStream, WriteChunkCompletionListener completionListener, UUID clientId) { - this.fileId = fileId; - this.requestUploadProcessingConfiguration=requestUploadProcessingConfiguration; - this.requestUploadProcessingOperation = requestOperation; - this.clientUploadProcessingOperation = clientOperation; - this.masterUploadProcessingOperation = masterProcessingOperation; - this.crc = crc; - this.inputStream = inputStream; - this.outputStream = outputStream; - this.completionListener = completionListener; - this.clientId = clientId; - } - - - @Override - public Void call() - throws Exception { - try { - // if we have not exceeded our byte to write allowance - long requestAllowance, clientAllowance, masterAllowance; - if ((requestAllowance = requestUploadProcessingOperation.getDownloadAllowanceForIteration()) > 0 && - (clientAllowance = clientUploadProcessingOperation.getDownloadAllowanceForIteration()) > 0 && - (masterAllowance = masterUploadProcessingOperation.getDownloadAllowanceForIteration()) > 0) { - - // keep first time - if (completionTimeTakenReference == 0) { - completionTimeTakenReference = new Date().getTime(); - log.trace("first write " + completionTimeTakenReference); - } - - // process - write(minOf( - (int) requestAllowance, - (int) clientAllowance, - (int) masterAllowance)); - } - // if have exceeded it - else { - - // by default, wait for default value - long delay = RateLimiter.BUCKET_FILLED_EVERY_X_MILLISECONDS; - - - // if we have a first write time - if (completionTimeTakenReference != 0) { - - // calculate the delay which is basically the iteration time minus the time - // it took to use our allowance in this iteration, so that we go directly to - // the next iteration - final long time = new Date().getTime(); - final long lastWriteWasAgo = time - completionTimeTakenReference; - delay = RateLimiter.BUCKET_FILLED_EVERY_X_MILLISECONDS - lastWriteWasAgo; - log.trace("waiting for allowance, fillbucket is expected in " + delay + "(last write was " + lastWriteWasAgo + " ago (" + - time + - " - " + completionTimeTakenReference + "))"); - completionTimeTakenReference = 0; - } - - // resubmit it - uploadWorkersPool.schedule(this, delay, TimeUnit.MILLISECONDS); - } - } - catch (Exception e) { - // forward exception - completeWithError(e); - } - return null; - } - - - private void write(int available) - throws IOException, FileCorruptedException, UploadIsCurrentlyDisabled { - - //check if uploading is enabled or not - if (!enabled) { - throw new UploadIsCurrentlyDisabled(); - } - - // init the buffer with the size of what we read - byte[] buffer = new byte[Math.min(available, SIZE_OF_THE_BUFFER_IN_BYTES)]; - - //synchronizing on file here so that pause can be assigned before actually starting to read the file - int bytesCount; - synchronized (requestUploadProcessingConfiguration) { - - // check if user wants to cancel - //firefox is waiting too long for socket timeout so we provocate a stream closure here.. - if (requestUploadProcessingConfiguration.isPaused()) { - log.debug("User cancellation detected."); - success(); - return; - } - - //read - bytesCount = inputStream.read(buffer); - } - - - // if we have something - if (bytesCount != -1) { - - // process the write for one token - log.trace("Processed bytes {} of request ({})", (byteProcessed += bytesCount), fileId); - - // write it to file - outputStream.write(buffer, 0, bytesCount); - - // and update crc32 - crc32.update(buffer, 0, bytesCount); - - // and update request allowance - requestUploadProcessingOperation.bytesConsumedFromAllowance(bytesCount); - - // and update client allowance - clientUploadProcessingOperation.bytesConsumedFromAllowance(bytesCount); - - // also update master allowance - masterUploadProcessingOperation.bytesConsumedFromAllowance(bytesCount); - - // submit again - uploadWorkersPool.submit(this); - } - // - // if we are done - else { - String calculatedChecksum = Long.toHexString(crc32.getValue()); - log.debug("Processed part for file " + fileId + " into temp file, checking written crc " + calculatedChecksum + - " against input crc " + crc); - - // compare the checksum of the chunks - if (!calculatedChecksum.equals(crc)) { - completeWithError(new InvalidCrcException(calculatedChecksum, crc)); - return; - } - - // if the crc is valid, specify the validation to the state - staticStateManager.setCrcBytesValidated(clientId, fileId, byteProcessed); - - // and specify as complete - success(); - } - } - - - public void completeWithError(Exception e) { - log.debug("error for " + fileId + ". closing file stream"); - closeFileStream(); - completionListener.error(e); - } - - - public void success() { - log.debug("completion for " + fileId + ". closing file stream"); - closeFileStream(); - completionListener.success(); - } - - - private void closeFileStream() { - log.debug("Closing FileOutputStream of " + fileId); - try { - outputStream.close(); - } - catch (Exception e) { - log.error("Error closing file output stream for id " + fileId + ": " + e.getMessage()); - } - } - - - } - - - - @ManagedAttribute - public int getAwaitingChunks() { - return uploadWorkersPool.getQueue().size(); - } - - - public void clean(UUID clientId, UUID fileId) { - log.debug("resetting token bucket for " + fileId); - - // deleting operation - uploadProcessingOperationManager.stopOperation(clientId, fileId); - - // resetting configuration - uploadProcessingConfigurationManager.reset(fileId); - - } - - - - public static int minOf(int... numbers) { - int min = -1; - if (numbers.length > 0) { - min = numbers[0]; - for (int i = 1; i < numbers.length; i++) { - min = Math.min(min, numbers[i]); - } - } - return min; - } - - - /** - * Checks if the file is paused. - * @param fileId - * @return - */ - public boolean isFilePaused(UUID fileId) { - final RequestUploadProcessingConfiguration requestUploadProcessingConfiguration = - uploadProcessingConfigurationManager.getUploadProcessingConfiguration(fileId); - synchronized (requestUploadProcessingConfiguration) { - return requestUploadProcessingConfiguration.isPaused(); - } - } - - - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - - - public boolean isEnabled() { - return enabled; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/CRCHelper.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/CRCHelper.java deleted file mode 100644 index e59d390..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/CRCHelper.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - - -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.CRC32; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import com.am.jlfu.fileuploader.json.CRCResult; -import com.am.jlfu.fileuploader.logic.UploadServletAsyncProcessor; - - - -/** - * Helper providing methods to compute crc hash. - * - * @see #getBufferedCrc(InputStream) - * @author antoinem - * - */ -@Component -public class CRCHelper { - - private static final Logger log = LoggerFactory.getLogger(CRCHelper.class); - - - - /** - * Returns a {@link CRCResult} computed with {@link CRC32} from the stream specified as - * parameter. - * - * @param inputStream - * @return {@link CRCResult} - * @throws IOException - */ - public CRCResult getBufferedCrc(InputStream inputStream) - throws IOException { - - byte[] b = new byte[UploadServletAsyncProcessor.SIZE_OF_THE_BUFFER_IN_BYTES]; - int read; - int totalRead = 0; - CRC32 crc32 = new CRC32(); - while ((read = inputStream.read(b)) != -1) { - crc32.update(b, 0, read); - totalRead += read; - } - inputStream.close(); - - CRCResult crcResult = new CRCResult(); - crcResult.setCrcAsString(Long.toHexString(crc32.getValue())); - crcResult.setTotalRead(totalRead); - - log.debug("obtained crc for stream with length " + totalRead + " : " + crcResult.getCrcAsString()); - - return crcResult; - - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ClientToFilesMap.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ClientToFilesMap.java deleted file mode 100644 index 12c0a76..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ClientToFilesMap.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentMap; - -import org.springframework.stereotype.Component; - -import com.google.common.collect.ForwardingMap; -import com.google.common.collect.Maps; - -@Component -public class ClientToFilesMap extends ForwardingMap> { - - /** Maps a client to its current requests */ - private final ConcurrentMap> clientToRequestsMapping = Maps.newConcurrentMap(); - - @Override - protected Map> delegate() { - return clientToRequestsMapping; - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ConditionProvider.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ConditionProvider.java deleted file mode 100644 index 4149b1a..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ConditionProvider.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - - -public abstract class ConditionProvider { - - public abstract boolean condition(); - - - public void onFail() { - } - - - public void onSuccess() { - - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ImportedFilesCleaner.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ImportedFilesCleaner.java deleted file mode 100644 index 342babc..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ImportedFilesCleaner.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - - -import java.io.File; - -import org.joda.time.DateTime; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.jmx.export.annotation.ManagedAttribute; -import org.springframework.jmx.export.annotation.ManagedResource; -import org.springframework.stereotype.Component; - -import com.am.jlfu.staticstate.FileDeleter; -import com.am.jlfu.staticstate.StaticStateRootFolderProvider; - - - -/** - * This cleaner shall be regularly invoked to remove files that are outdated on the system.
- * That is checked against the last modified time which shall be no more than what is configured. - * - * @author antoinem - */ -@Component -@ManagedResource(objectName = "JavaLargeFileUploader:name=importedFilesCleaner") -public class ImportedFilesCleaner { - - private static final Logger log = LoggerFactory.getLogger(ImportedFilesCleaner.class); - - @Autowired - StaticStateRootFolderProvider rootFolderProvider; - - @Autowired - FileDeleter fileDeleter; - - @Value("jlfu{jlfu.filecleaner.maximumInactivityInHoursBeforeDelete:48}") - volatile Integer maximumInactivityInHoursBeforeDelete; - - - - public void clean() { - log.trace("Started file cleaner job."); - DateTime pastTime = new DateTime().minusHours(maximumInactivityInHoursBeforeDelete); - File[] listFiles = rootFolderProvider.getRootFolder().listFiles(); - for (File file : listFiles) { - if (pastTime.isAfter(file.lastModified())) { - log.debug("Deleting outdated file: " + file.getName()); - fileDeleter.deleteFile(file); - } - } - log.trace("Finished file cleaner job."); - } - - - @ManagedAttribute - public Integer getMaximumInactivityInHoursBeforeDelete() { - return maximumInactivityInHoursBeforeDelete; - } - - - @ManagedAttribute - public void setMaximumInactivityInHoursBeforeDelete(Integer maximumInactivityInHoursBeforeDelete) { - this.maximumInactivityInHoursBeforeDelete = maximumInactivityInHoursBeforeDelete; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/LimitingList.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/LimitingList.java deleted file mode 100644 index bfe66fb..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/LimitingList.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - -import java.util.List; - -import com.google.common.collect.Lists; - -/** - * List that limits to a certain number of items. All items at the end of the list will be removed. - * @author antoinem - * - * @param - */ -public class LimitingList { - - List list = Lists.newArrayList(); - - private int limit; - - public LimitingList(int limit) { - super(); - this.limit = limit; - } - - /** - * Adds an element at the beginning of the list. - * @param element - */ - public void unshift(T element) { - - //unshift - list.add(0,element); - - //process removal - if(list.size() > limit) { - list.remove(limit); - } - } - - - public List getList() { - return list; - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ProgressCalculator.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ProgressCalculator.java deleted file mode 100644 index 63c1622..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ProgressCalculator.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.UUID; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.am.jlfu.fileuploader.limiter.RateLimiterConfigurationManager; -import com.am.jlfu.staticstate.JavaLargeFileUploaderService; -import com.am.jlfu.staticstate.entities.FileProgressStatus; -import com.am.jlfu.staticstate.entities.StaticFileState; -import com.am.jlfu.staticstate.entities.StaticStatePersistedOnFileSystemEntity; - -/** - * Component to calculate the information related to a file currently uploading. - * @author antoinem - * - */ -@Component -public class ProgressCalculator { - - private static final Logger log = LoggerFactory.getLogger(ProgressCalculator.class); - - @Autowired - JavaLargeFileUploaderService javaLargeFileUploaderService; - - @Autowired - RateLimiterConfigurationManager rateLimiterConfigurationManager; - - @Autowired - RemainingTimeEstimator remainingTimeEstimator; - - - /** - * Retrieves the progress of the specified file for the specified client.
- * - * - * @param clientId - * @param fileId - * @return - * @throws FileNotFoundException - */ - public FileProgressStatus getProgress(UUID clientId, UUID fileId) throws FileNotFoundException { - // get the file - StaticStatePersistedOnFileSystemEntity model = javaLargeFileUploaderService.getEntityIfPresent(clientId); - //if cannot find the model, return null - if (model == null) { - return null; - } - return processProgress(fileId, model); - - } - - - private FileProgressStatus processProgress(UUID fileId, StaticStatePersistedOnFileSystemEntity model) - throws FileNotFoundException { - StaticFileState fileState = model.getFileStates().get(fileId); - if (fileState == null) { - throw new FileNotFoundException("File with id " + fileId + " not found"); - } - File file = new File(fileState.getAbsoluteFullPathOfUploadedFile()); - - //init returned entity - FileProgressStatus fileProgressStatus = new FileProgressStatus(); - - // compare size of the file to the expected size - Long originalFileSizeInBytes = fileState.getStaticFileStateJson().getOriginalFileSizeInBytes(); - long currentFileSize = file.length(); - Float progress = calculateProgress(currentFileSize, originalFileSizeInBytes).floatValue(); - - //set it - fileProgressStatus.setProgress(progress); - fileProgressStatus.setTotalFileSize(originalFileSizeInBytes); - fileProgressStatus.setBytesUploaded(currentFileSize); - - //set upload rate - fileProgressStatus.setUploadRate(rateLimiterConfigurationManager.getUploadState(fileId)); - - //calculate estimated remaining time - fileProgressStatus.setEstimatedRemainingTimeInSeconds(remainingTimeEstimator.getRemainingTime(fileId, fileProgressStatus, fileProgressStatus.getUploadRate())); - - //log file progress status - log.debug("Calculated progress for file "+fileId+": "+fileProgressStatus); - - return fileProgressStatus; - } - - - - Double calculateProgress(Long currentSize, Long expectedSize) { - double percent = currentSize.doubleValue() / expectedSize.doubleValue() * 100d; - if (percent == 100 && expectedSize - currentSize != 0) { - percent = 99.99d; - } - return percent; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ProgressManager.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ProgressManager.java deleted file mode 100644 index d08e7d2..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/ProgressManager.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - - -import java.io.FileNotFoundException; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; - -import com.am.jlfu.notifier.JLFUListener; -import com.am.jlfu.notifier.JLFUListenerPropagator; -import com.am.jlfu.staticstate.entities.FileProgressStatus; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - - - -/** - * Component responsible for advertising the write progress of a specific file to - * {@link JLFUListener}s.
- * Every second, it calculates the progress of all the files being uploaded. - * - * @author antoinem - * - */ -@Component -public class ProgressManager { - private static final Logger log = LoggerFactory.getLogger(ProgressManager.class); - - @Autowired - private JLFUListenerPropagator jlfuListenerPropagator; - - @Autowired - private ClientToFilesMap clientToFilesMap; - - @Autowired - private ProgressCalculator progressCalculator; - - /** Internal map. */ - Map fileToProgressInfo = Maps.newHashMap(); - - /** Simple advertiser. */ - ProgressManagerAdvertiser progressManagerAdvertiser = new ProgressManagerAdvertiser(); - - @Scheduled(fixedRate = 1000) - public void calculateProgress() { - - synchronized (fileToProgressInfo) { - - //for all clients - for (Entry> entry : clientToFilesMap.entrySet()) { - - //for all pending upload - Set originSet = entry.getValue(); - Set copySet; - synchronized (originSet) { - copySet = Sets.newHashSet(originSet); - } - for (UUID fileId : copySet) { - - try { - - //calculate its progress - FileProgressStatus newProgress = progressCalculator.getProgress(entry.getKey(), fileId); - - //if progress has successfully been computed - if (newProgress != null) { - - //get from map - FileProgressStatus progressInMap = fileToProgressInfo.get(fileId); - - //if not present in map - //or if present in map but different from previous one - if (progressInMap == null || !progressInMap.getProgress().equals(newProgress.getProgress())) { - - //add to map - fileToProgressInfo.put(fileId, newProgress); - - // and avertise - progressManagerAdvertiser.advertise(entry.getKey(), fileId, newProgress); - - } - } - - } - catch (FileNotFoundException e) { - log.debug("cannot retrieve progress for "+fileId); - } - - } - } - - } - } - - class ProgressManagerAdvertiser { - - void advertise(UUID clientId, UUID fileId, FileProgressStatus newProgress) { - jlfuListenerPropagator.getPropagator().onFileUploadProgress(clientId, fileId, newProgress); - } - } - - /** - * Returns a calculated progress of a pending file upload.
- * @param fileId - * @return - */ - public FileProgressStatus getProgress(UUID fileId) { - synchronized (fileToProgressInfo) { - return fileToProgressInfo.get(fileId); - } - } - - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/RemainingTimeEstimator.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/RemainingTimeEstimator.java deleted file mode 100644 index 2594373..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/RemainingTimeEstimator.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.springframework.stereotype.Component; - -import com.am.jlfu.staticstate.entities.FileProgressStatus; -import com.google.common.collect.Maps; - -/** - * Component dedicated to calculate the remaining time of a pending upload. - * @author antoinem - */ -@Component -public class RemainingTimeEstimator { - - private static final int averageUploadRateOnTheLastX = 10; - - private Map> map = Maps.newConcurrentMap(); - - public Long getRemainingTime(UUID fileId, FileProgressStatus progress, Long uploadRate) { - LimitingList newArrayList; - - //if we dont have an array for this file yet - if ((newArrayList = map.get(fileId)) == null) { - - //create it and set it - newArrayList = new LimitingList(averageUploadRateOnTheLastX); - map.put(fileId, newArrayList); - - } - - //add the instant upload rate - newArrayList.unshift(uploadRate); - - //calculate the average upload rate - Long averageUploadRate = getAverageUploadRate(newArrayList); - - //return null if average upload rate is 0 - if (averageUploadRate == 0) { - return null; - } - - //calculate from average - return calculateRemainingTime(progress, averageUploadRate); - } - - private Long getAverageUploadRate(LimitingList newArrayList) { - Long totalValue = 0l; - List list = newArrayList.getList(); - for (Long value : list) { - totalValue += value; - } - return totalValue / list.size(); - } - - long calculateRemainingTime(FileProgressStatus progress, Long uploadRate) { - long calculatedTimeRemaining = (progress.getTotalFileSize() - progress.getBytesUploaded()) / uploadRate; - //set the minimum to 1second remaining - return Math.max(calculatedTimeRemaining, 1); - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/UnitConverter.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/UnitConverter.java deleted file mode 100644 index d7d5e92..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/utils/UnitConverter.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - - -/** - * Provdes static unit conversion methods.
- * A javascript method is also contained in javalargefileuploader.js - * - * @author antoinem - */ -public final class UnitConverter { - - public static String getFormattedTime(long secs) - { - if (secs < 1) { - return "-"; - } - - double hours = Math.floor(secs / (60 * 60)); - - double divisor_for_minutes = secs % (60 * 60); - double minutes = Math.floor(divisor_for_minutes / 60); - - double divisor_for_seconds = divisor_for_minutes % 60; - double seconds = Math.ceil(divisor_for_seconds); - - String returned = ""; - boolean displaySeconds = true; - if (hours > 0) { - returned += ((int)hours) + "h"; - displaySeconds = false; - } - if (minutes > 0) { - returned += ((int)minutes) + "m"; - displaySeconds &= minutes <= 10; - } - if (displaySeconds) { - returned += ((int)seconds) + "s"; - } - return returned; - } - - - public static String getFormattedSize(long size) { - if (size < 1024) { - return format(size) + "B"; - } - else if (size < 1048576) { - return format(size / 1024f) + "KB"; - } - else if (size < 1073741824) { - return format(size / 1048576f) + "MB"; - } - else if (size < 1099511627776l) { - return format(size / 1073741824f) + "GB"; - } - else if (size < 1125899906842624l) { - return format(size / 1099511627776f) + "TB"; - } - return null; - } - - - public static float format(float f) { - return ((float)Math.ceil(f * 100)) / 100f; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServlet.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServlet.java deleted file mode 100644 index fdace3c..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServlet.java +++ /dev/null @@ -1,258 +0,0 @@ -package com.am.jlfu.fileuploader.web; - - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.Serializable; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.UUID; - -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.springframework.web.HttpRequestHandler; -import org.springframework.web.context.support.HttpRequestHandlerServlet; - -import com.am.jlfu.authorizer.Authorizer; -import com.am.jlfu.fileuploader.exception.AuthorizationException; -import com.am.jlfu.fileuploader.exception.FileCorruptedException; -import com.am.jlfu.fileuploader.exception.FileStillProcessingException; -import com.am.jlfu.fileuploader.exception.InvalidCrcException; -import com.am.jlfu.fileuploader.exception.MissingParameterException; -import com.am.jlfu.fileuploader.json.PrepareUploadJson; -import com.am.jlfu.fileuploader.json.ProgressJson; -import com.am.jlfu.fileuploader.logic.UploadProcessor; -import com.am.jlfu.fileuploader.web.utils.ExceptionCodeMappingHelper; -import com.am.jlfu.fileuploader.web.utils.FileUploaderHelper; -import com.am.jlfu.staticstate.StaticStateIdentifierManager; -import com.google.common.base.Function; -import com.google.common.collect.Collections2; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.gson.Gson; - - - -/** - * Uploads the file from the jquery uploader. - * - * @author antoinem - * - */ -@Component("javaLargeFileUploaderServlet") -@WebServlet(name = "javaLargeFileUploaderServlet", urlPatterns = { "/javaLargeFileUploaderServlet" }) -public class UploadServlet extends HttpRequestHandlerServlet - implements HttpRequestHandler { - - private static final Logger log = LoggerFactory.getLogger(UploadServlet.class); - - @Autowired - UploadProcessor uploadProcessor; - - @Autowired - FileUploaderHelper fileUploaderHelper; - - @Autowired - ExceptionCodeMappingHelper exceptionCodeMappingHelper; - - @Autowired - Authorizer authorizer; - - @Autowired - StaticStateIdentifierManager staticStateIdentifierManager; - - - - @Override - public void handleRequest(HttpServletRequest request, HttpServletResponse response) - throws IOException { - log.trace("Handling request"); - - Serializable jsonObject = null; - try { - // extract the action from the request - UploadServletAction actionByParameterName = - UploadServletAction.valueOf(fileUploaderHelper.getParameterValue(request, UploadServletParameter.action)); - - // check authorization - checkAuthorization(request, actionByParameterName); - - // then process the asked action - jsonObject = processAction(actionByParameterName, request); - - - // if something has to be written to the response - if (jsonObject != null) { - fileUploaderHelper.writeToResponse(jsonObject, response); - } - - } - // If exception, write it - catch (Exception e) { - exceptionCodeMappingHelper.processException(e, response); - } - - } - - - private void checkAuthorization(HttpServletRequest request, UploadServletAction actionByParameterName) - throws MissingParameterException, AuthorizationException { - - // check authorization - // if its not get progress (because we do not really care about authorization for get - // progress and it uses an array of file ids) - if (!actionByParameterName.equals(UploadServletAction.getProgress)) { - - // extract uuid - final String fileIdFieldValue = fileUploaderHelper.getParameterValue(request, UploadServletParameter.fileId, false); - - // if this is init, the identifier is the one in parameter - UUID clientOrJobId; - String parameter = fileUploaderHelper.getParameterValue(request, UploadServletParameter.clientId, false); - if (actionByParameterName.equals(UploadServletAction.getConfig) && parameter != null) { - clientOrJobId = UUID.fromString(parameter); - } - // if not, get it from manager - else { - clientOrJobId = staticStateIdentifierManager.getIdentifier(); - } - - - // call authorizer - authorizer.getAuthorization( - request, - actionByParameterName, - clientOrJobId, - fileIdFieldValue != null ? getFileIdsFromString(fileIdFieldValue).toArray(new UUID[] {}) : null); - - } - } - - - private Serializable processAction(UploadServletAction actionByParameterName, HttpServletRequest request) - throws Exception { - log.debug("Processing action " + actionByParameterName.name()); - - Serializable returnObject = null; - switch (actionByParameterName) { - case getConfig: - String parameterValue = fileUploaderHelper.getParameterValue(request, UploadServletParameter.clientId, false); - returnObject = - uploadProcessor.getConfig( - parameterValue != null ? UUID.fromString(parameterValue) : null); - break; - case verifyCrcOfUncheckedPart: - returnObject = verifyCrcOfUncheckedPart(request); - break; - case prepareUpload: - returnObject = prepareUpload(request); - break; - case clearFile: - uploadProcessor.clearFile(UUID.fromString(fileUploaderHelper.getParameterValue(request, UploadServletParameter.fileId))); - break; - case clearAll: - uploadProcessor.clearAll(); - break; - case pauseFile: - List uuids = getFileIdsFromString(fileUploaderHelper.getParameterValue(request, UploadServletParameter.fileId)); - uploadProcessor.pauseFile(uuids); - break; - case resumeFile: - returnObject = - uploadProcessor.resumeFile(UUID.fromString(fileUploaderHelper.getParameterValue(request, UploadServletParameter.fileId))); - break; - case setRate: - uploadProcessor.setUploadRate(UUID.fromString(fileUploaderHelper.getParameterValue(request, UploadServletParameter.fileId)), - Long.valueOf(fileUploaderHelper.getParameterValue(request, UploadServletParameter.rate))); - break; - case getProgress: - returnObject = getProgress(request); - break; - } - return returnObject; - } - - - List getFileIdsFromString(String fileIds) { - String[] splittedFileIds = fileIds.split(","); - List uuids = Lists.newArrayList(); - for (int i = 0; i < splittedFileIds.length; i++) { - uuids.add(UUID.fromString(splittedFileIds[i])); - } - return uuids; - } - - - private Serializable getProgress(HttpServletRequest request) - throws MissingParameterException { - Serializable returnObject; - String[] ids = - new Gson() - .fromJson(fileUploaderHelper.getParameterValue(request, UploadServletParameter.fileId), String[].class); - Collection uuids = Collections2.transform(Arrays.asList(ids), new Function() { - - @Override - public UUID apply(String input) { - return UUID.fromString(input); - } - - }); - returnObject = Maps.newHashMap(); - for (UUID fileId : uuids) { - try { - ProgressJson progress = uploadProcessor.getProgress(fileId); - ((HashMap) returnObject).put(fileId.toString(), progress); - } - catch (FileNotFoundException e) { - log.debug("No progress will be retrieved for " + fileId + " because " + e.getMessage()); - } - } - return returnObject; - } - - - private Serializable prepareUpload(HttpServletRequest request) - throws MissingParameterException, IOException { - - // extract file information - PrepareUploadJson[] fromJson = - new Gson() - .fromJson(fileUploaderHelper.getParameterValue(request, UploadServletParameter.newFiles), PrepareUploadJson[].class); - - // prepare them - final HashMap prepareUpload = uploadProcessor.prepareUpload(fromJson); - - // return them - return Maps.newHashMap(Maps.transformValues(prepareUpload, new Function() { - - public String apply(UUID input) { - return input.toString(); - }; - })); - } - - - private Boolean verifyCrcOfUncheckedPart(HttpServletRequest request) - throws IOException, MissingParameterException, FileCorruptedException, FileStillProcessingException { - UUID fileId = UUID.fromString(fileUploaderHelper.getParameterValue(request, UploadServletParameter.fileId)); - try { - uploadProcessor.verifyCrcOfUncheckedPart(fileId, - fileUploaderHelper.getParameterValue(request, UploadServletParameter.crc)); - } - catch (InvalidCrcException e) { - // no need to log this exception, a fallback behaviour is defined in the - // throwing method. - // but we need to return something! - return Boolean.FALSE; - } - return Boolean.TRUE; - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServletAction.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServletAction.java deleted file mode 100644 index abf8e98..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServletAction.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.am.jlfu.fileuploader.web; - - -/** - * One of the possible action that the servlet handles. - * - * @author antoinem - * - */ -public enum UploadServletAction { - - getConfig, - getProgress, - prepareUpload, - clearFile, - setRate, - resumeFile, - pauseFile, - verifyCrcOfUncheckedPart, - clearAll, - upload; - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServletAsync.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServletAsync.java deleted file mode 100644 index e3fda46..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServletAsync.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.am.jlfu.fileuploader.web; - - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.UUID; - -import javax.servlet.AsyncContext; -import javax.servlet.ServletException; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang.time.DateUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.springframework.web.HttpRequestHandler; -import org.springframework.web.context.support.HttpRequestHandlerServlet; - -import com.am.jlfu.authorizer.Authorizer; -import com.am.jlfu.fileuploader.exception.UploadIsCurrentlyDisabled; -import com.am.jlfu.fileuploader.logic.UploadServletAsyncProcessor; -import com.am.jlfu.fileuploader.logic.UploadServletAsyncProcessor.WriteChunkCompletionListener; -import com.am.jlfu.fileuploader.web.utils.ExceptionCodeMappingHelper; -import com.am.jlfu.fileuploader.web.utils.FileUploadConfiguration; -import com.am.jlfu.fileuploader.web.utils.FileUploaderHelper; -import com.am.jlfu.staticstate.StaticStateIdentifierManager; -import com.am.jlfu.staticstate.StaticStateManager; -import com.am.jlfu.staticstate.entities.StaticFileState; -import com.am.jlfu.staticstate.entities.StaticStatePersistedOnFileSystemEntity; - - - -@Component("javaLargeFileUploaderAsyncServlet") -@WebServlet(name = "javaLargeFileUploaderAsyncServlet", urlPatterns = { "/javaLargeFileUploaderAsyncServlet" }, asyncSupported = true) -public class UploadServletAsync extends HttpRequestHandlerServlet - implements HttpRequestHandler { - - private static final Logger log = LoggerFactory.getLogger(UploadServletAsync.class); - - @Autowired - ExceptionCodeMappingHelper exceptionCodeMappingHelper; - - @Autowired - UploadServletAsyncProcessor uploadServletAsyncProcessor; - - @Autowired - StaticStateIdentifierManager staticStateIdentifierManager; - - @Autowired - StaticStateManager staticStateManager; - - @Autowired - FileUploaderHelper fileUploaderHelper; - - @Autowired - Authorizer authorizer; - - /** - * Maximum time that a streaming request can take.
- */ - private long taskTimeOut = DateUtils.MILLIS_PER_HOUR; - - - @Override - public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) - throws ServletException, IOException { - - // process the request - try { - - //check if uploads are allowed - if (!uploadServletAsyncProcessor.isEnabled()) { - throw new UploadIsCurrentlyDisabled(); - } - - // extract stuff from request - final FileUploadConfiguration process = fileUploaderHelper.extractFileUploadConfiguration(request); - - log.debug("received upload request with config: "+process); - - // verify authorization - final UUID clientId = staticStateIdentifierManager.getIdentifier(); - authorizer.getAuthorization(request, UploadServletAction.upload, clientId, process.getFileId()); - - //check if that file is not paused - if (uploadServletAsyncProcessor.isFilePaused(process.getFileId())) { - log.debug("file "+process.getFileId()+" is paused, ignoring async request."); - return; - } - - // get the model - StaticFileState fileState = staticStateManager.getEntityIfPresent().getFileStates().get(process.getFileId()); - if (fileState == null) { - throw new FileNotFoundException("File with id " + process.getFileId() + " not found"); - } - - // process the request asynchronously - final AsyncContext asyncContext = request.startAsync(); - asyncContext.setTimeout(taskTimeOut); - - - // add a listener to clear bucket and close inputstream when process is complete or - // with - // error - asyncContext.addListener(new UploadServletAsyncListenerAdapter(process.getFileId()) { - - @Override - void clean() { - log.debug("request " + request + " completed."); - // we do not need to clear the inputstream here. - // and tell processor to clean its shit! - uploadServletAsyncProcessor.clean(clientId, process.getFileId()); - } - }); - - // then process - uploadServletAsyncProcessor.process(fileState, process.getFileId(), process.getCrc(), process.getInputStream(), - new WriteChunkCompletionListener() { - - @Override - public void success() { - asyncContext.complete(); - } - - - @Override - public void error(Exception exception) { - // handles a stream ended unexpectedly , it just means the user has - // stopped the - // stream - if (exception.getMessage() != null) { - if (exception.getMessage().equals("Stream ended unexpectedly")) { - log.warn("User has stopped streaming for file " + process.getFileId()); - } - else if (exception.getMessage().equals("User cancellation")) { - log.warn("User has cancelled streaming for file id " + process.getFileId()); - // do nothing - } - else { - exceptionCodeMappingHelper.processException(exception, response); - } - } - else { - exceptionCodeMappingHelper.processException(exception, response); - } - - asyncContext.complete(); - } - - }); - } - catch (Exception e) { - exceptionCodeMappingHelper.processException(e, response); - } - - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServletAsyncListenerAdapter.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServletAsyncListenerAdapter.java deleted file mode 100644 index 95dc2dc..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServletAsyncListenerAdapter.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.am.jlfu.fileuploader.web; - - -import java.io.IOException; -import java.util.UUID; - -import javax.servlet.AsyncEvent; -import javax.servlet.AsyncListener; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - - -public abstract class UploadServletAsyncListenerAdapter - implements AsyncListener { - - private static final Logger log = LoggerFactory.getLogger(UploadServletAsyncListenerAdapter.class); - - private UUID id; - - - - public UploadServletAsyncListenerAdapter(UUID identifier) { - this.id = identifier; - } - - - abstract void clean(); - - - @Override - public void onComplete(AsyncEvent asyncEvent) - throws IOException { - log.debug("Done: ({})", id); - clean(); - } - - - @Override - public void onTimeout(AsyncEvent asyncEvent) - throws IOException { - log.warn("Asynchronous request timeout ({})", id); - clean(); - } - - - @Override - public void onError(AsyncEvent asyncEvent) - throws IOException { - log.error("Asynchronous request error (" + id + ")", asyncEvent.getThrowable()); - clean(); - } - - - @Override - public void onStartAsync(AsyncEvent asyncEvent) - throws IOException { - log.debug("Started: ({})", id); - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServletParameter.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServletParameter.java deleted file mode 100644 index 09f7515..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/UploadServletParameter.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.am.jlfu.fileuploader.web; - - -/** - * One of the possible parameter that the servlet handles. - * - * @author antoinem - * - */ -public enum UploadServletParameter { - - action, - fileId, - crc, - rate, - newFiles, - clientId; - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/ExceptionCodeMappingHelper.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/ExceptionCodeMappingHelper.java deleted file mode 100644 index e09ca39..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/ExceptionCodeMappingHelper.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.am.jlfu.fileuploader.web.utils; - - -import java.io.IOException; - -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.am.jlfu.fileuploader.exception.AuthorizationException; -import com.am.jlfu.fileuploader.exception.FileCorruptedException; -import com.am.jlfu.fileuploader.exception.FileStillProcessingException; -import com.am.jlfu.fileuploader.exception.InvalidCrcException; -import com.am.jlfu.fileuploader.exception.JavaFileUploaderException; -import com.am.jlfu.fileuploader.exception.MissingParameterException; -import com.am.jlfu.fileuploader.exception.UploadIsCurrentlyDisabled; - - - -/** - * Contains the mapping of exception => ids - * - * @author antoinem - * @see JavaFileUploaderException - * - */ -@Component -public class ExceptionCodeMappingHelper { - - @Autowired - private FileUploaderHelper fileUploaderHelper; - - private static final Logger log = LoggerFactory.getLogger(FileUploaderHelper.class); - - - - public enum ExceptionCodeMapping { - - unkownError (0), - requestIsNotMultipart (1), - NoFileToUploadInTheRequest (2), - InvalidCRC (3, InvalidCrcException.class), - MissingParameterException (4, MissingParameterException.class), - AuthorizationException (12, AuthorizationException.class), - FileCorruptedException (14, FileCorruptedException.class), - FileStillProcessingException (15, FileStillProcessingException.class), - UploadIsCurrentlyDisabled (16, UploadIsCurrentlyDisabled.class); - - private int exceptionIdentifier; - private Class clazz; - - - - private ExceptionCodeMapping(int exceptionIdentifier) { - this.exceptionIdentifier = exceptionIdentifier; - } - - - private ExceptionCodeMapping(int exceptionIdentifier, Class clazz) { - this(exceptionIdentifier); - this.clazz = clazz; - } - - - public int getExceptionIdentifier() { - return exceptionIdentifier; - } - - - public void setExceptionIdentifier(int exceptionIdentifier) { - this.exceptionIdentifier = exceptionIdentifier; - } - - - } - - - - public void processException(Exception e, HttpServletResponse response) { - ExceptionCodeMapping exceptionCodeMappingByType = ExceptionCodeMappingHelper.getExceptionCodeMappingByType(e); - - // log - if (exceptionCodeMappingByType.equals(ExceptionCodeMapping.unkownError)) { - // with stacktrace if it is unknown - log.error(e.getMessage(), e); - } - else { - // without stracktrace if it is managed - log.error(e.getMessage()); - } - - // write exception to response - if (exceptionCodeMappingByType != null) { - try { - log.error("managed error " + exceptionCodeMappingByType.getExceptionIdentifier() + ": " + e.getMessage()); - fileUploaderHelper.writeExceptionToResponse(new JavaFileUploaderException(exceptionCodeMappingByType), response); - } - catch (IOException ee) { - log.error(ee.getMessage()); - } - } - } - - - public static ExceptionCodeMapping getExceptionCodeMappingByType(Exception e) { - if (e instanceof JavaFileUploaderException) { - return ((JavaFileUploaderException) e).getExceptionCodeMapping(); - } - else { - for (ExceptionCodeMapping exceptionsCodeMapping : ExceptionCodeMapping.values()) { - if (exceptionsCodeMapping.clazz != null && exceptionsCodeMapping.clazz.isInstance(e)) { - return exceptionsCodeMapping; - } - } - } - return ExceptionCodeMapping.unkownError; - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/FileUploadConfiguration.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/FileUploadConfiguration.java deleted file mode 100644 index 4c77d3f..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/FileUploadConfiguration.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.am.jlfu.fileuploader.web.utils; - - -import java.io.InputStream; -import java.util.UUID; - - - -public class FileUploadConfiguration { - - private UUID fileId; - private String crc; - private InputStream inputStream; - - - - public FileUploadConfiguration() { - } - - - public UUID getFileId() { - return fileId; - } - - - public void setFileId(UUID fileId) { - this.fileId = fileId; - } - - - public String getCrc() { - return crc; - } - - - public void setCrc(String crc) { - this.crc = crc; - } - - - public InputStream getInputStream() { - return inputStream; - } - - - public void setInputStream(InputStream inputStream) { - this.inputStream = inputStream; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/FileUploadManagerFilter.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/FileUploadManagerFilter.java deleted file mode 100644 index 40bc482..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/FileUploadManagerFilter.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.am.jlfu.fileuploader.web.utils; - - -import java.io.IOException; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - - - -@Component("jlfuFilter") -public class FileUploadManagerFilter - implements Filter { - - @Autowired - RequestComponentContainer requestComponentContainer; - - - - @Override - public void destroy() { - - } - - - @Override - public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) - throws IOException, ServletException { - requestComponentContainer.populate((HttpServletRequest) req,(HttpServletResponse) resp); - chain.doFilter(req, resp); - requestComponentContainer.clear(); - } - - - @Override - public void init(FilterConfig arg0) - throws ServletException { - - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/FileUploaderHelper.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/FileUploaderHelper.java deleted file mode 100644 index dda1c8b..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/FileUploaderHelper.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.am.jlfu.fileuploader.web.utils; - - -import java.io.IOException; -import java.io.Serializable; -import java.util.UUID; - -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.fileupload.FileItemIterator; -import org.apache.commons.fileupload.FileItemStream; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.springframework.stereotype.Component; - -import com.am.jlfu.fileuploader.exception.JavaFileUploaderException; -import com.am.jlfu.fileuploader.exception.MissingParameterException; -import com.am.jlfu.fileuploader.json.SimpleJsonObject; -import com.am.jlfu.fileuploader.web.UploadServletParameter; -import com.am.jlfu.fileuploader.web.utils.ExceptionCodeMappingHelper.ExceptionCodeMapping; -import com.google.gson.Gson; - - - -/** - * Provides some common methods to deal with file upload requests. - * - * @author antoinem - * - */ -@Component -public class FileUploaderHelper { - - - public FileUploadConfiguration extractFileUploadConfiguration(HttpServletRequest request) - throws MissingParameterException, FileUploadException, IOException, JavaFileUploaderException { - final FileUploadConfiguration fileUploadConfiguration = new FileUploadConfiguration(); - - // check if the request is multipart: - if (!ServletFileUpload.isMultipartContent(request)) { - throw new JavaFileUploaderException(ExceptionCodeMapping.requestIsNotMultipart); - } - - // extract the fields - fileUploadConfiguration.setFileId(UUID.fromString(getParameterValue(request, UploadServletParameter.fileId))); - fileUploadConfiguration.setCrc(getParameterValue(request, UploadServletParameter.crc, false)); - - // Create a new file upload handler - ServletFileUpload upload = new ServletFileUpload(); - - // parse the requestuest - FileItemIterator iter = upload.getItemIterator(request); - FileItemStream item = iter.next(); - - // throw exception if item is null - if (item == null) { - throw new JavaFileUploaderException(ExceptionCodeMapping.NoFileToUploadInTheRequest); - } - - // extract input stream - fileUploadConfiguration.setInputStream(item.openStream()); - - // return conf - return fileUploadConfiguration; - - } - - - public String getParameterValue(HttpServletRequest request, UploadServletParameter parameter) - throws MissingParameterException { - return getParameterValue(request, parameter, true); - } - - - public String getParameterValue(HttpServletRequest request, UploadServletParameter parameter, boolean mandatory) - throws MissingParameterException { - String parameterValue = request.getParameter(parameter.name()); - if (parameterValue == null && mandatory) { - throw new MissingParameterException(parameter); - } - return parameterValue; - } - - - public void writeExceptionToResponse(final JavaFileUploaderException e, ServletResponse servletResponse) - throws IOException { - writeToResponse(new SimpleJsonObject(Integer.valueOf(e.getExceptionCodeMapping().getExceptionIdentifier()).toString()), servletResponse); - } - - - public void writeToResponse(Serializable jsonObject, ServletResponse servletResponse) - throws IOException { - servletResponse.setContentType("application/json"); - servletResponse.getWriter().print(new Gson().toJson(jsonObject)); - servletResponse.getWriter().close(); - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/RequestComponentContainer.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/RequestComponentContainer.java deleted file mode 100644 index b5635f4..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/web/utils/RequestComponentContainer.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.am.jlfu.fileuploader.web.utils; - - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import org.springframework.stereotype.Component; - - - -/** - * {@link HttpServletResponse} and {@link HttpServletRequest} are stored in a thread local and are - * populated by the filter. - * - * @author antoinem - * - */ -@Component -public class RequestComponentContainer { - - - private ThreadLocal responseThreadLocal = new ThreadLocal(); - private ThreadLocal requestThreadLocal = new ThreadLocal(); - - - - public void populate(HttpServletRequest request, HttpServletResponse response) { - responseThreadLocal.set(response); - requestThreadLocal.set(request); - } - - - public void clear() { - responseThreadLocal.remove(); - } - - - public HttpServletResponse getResponse() { - return responseThreadLocal.get(); - } - - - public HttpServletRequest getRequest() { - return requestThreadLocal.get(); - - } - - - public HttpSession getSession() { - return requestThreadLocal.get().getSession(); - - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/identifier/IdentifierProvider.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/identifier/IdentifierProvider.java deleted file mode 100644 index c4a986f..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/identifier/IdentifierProvider.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.am.jlfu.identifier; - - -import java.util.UUID; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.am.jlfu.identifier.impl.DefaultIdentifierProvider; - - - -/** - * Provides identification for JLFU API.
- * The default implementation ({@link DefaultIdentifierProvider}) is using a cookie to store a UUID - * generated for every client.
- * You can provide your own implementation to be able to manage this identification using a more - * complex system (if you want users to resume files from another browser or provide ids linked to a - * job instead of a client if you are providing upload in a more sequential way). - * - * @author antoinem - * @see DefaultIdentifierProvider - * - */ -public interface IdentifierProvider { - - /** - * Retrieves the client identifier.
- * - * @param httpServletRequest - * @param httpServletResponse - * - * @return the unique identifier identifying this client/job - */ - UUID getIdentifier(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse); - - - /** - * Define this method if your application supports IDs specified by the client (on - * initialization). - * - * @param httpServletRequest - * @param httpServletResponse - * @param id - * - */ - void setIdentifier(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, UUID id); - - - /** - * Removes the identifier. - * - * @param request - * @param response - */ - void clearIdentifier(HttpServletRequest request, HttpServletResponse response); - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/identifier/impl/DefaultIdentifierProvider.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/identifier/impl/DefaultIdentifierProvider.java deleted file mode 100644 index 9860e94..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/identifier/impl/DefaultIdentifierProvider.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.am.jlfu.identifier.impl; - - -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.am.jlfu.identifier.IdentifierProvider; -import com.am.jlfu.notifier.JLFUListenerPropagator; - - - -/** - * Identifier provider that provides identification based on cookie. - * - * @author antoinem - * - */ -@Component -public class DefaultIdentifierProvider - implements IdentifierProvider { - - - public static final String cookieIdentifier = "jlufStaticStateCookieName"; - - @Autowired - JLFUListenerPropagator jlfuListenerPropagator; - - - - @Override - public void setIdentifier(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, UUID id) { - - // clear any first - clearIdentifier(httpServletRequest, httpServletResponse); - - // then set in session - httpServletRequest.getSession().setAttribute(cookieIdentifier, id); - - // and cookie - setCookie(httpServletResponse, id); - - } - - - public static Cookie getCookie(Cookie[] cookies, String id) { - if (cookies != null) { - for (Cookie cookie : cookies) { - if (cookie.getName().equals(id)) { - // found it - if (cookie.getMaxAge() != 0) { - return cookie; - } - } - } - } - return null; - } - - - public static void setCookie(HttpServletResponse response, UUID uuid) { - Cookie cookie = new Cookie(cookieIdentifier, uuid.toString()); - cookie.setMaxAge((int) TimeUnit.DAYS.toSeconds(31)); - response.addCookie(cookie); - } - - - UUID getUuid() { - final UUID uuid = UUID.randomUUID(); - jlfuListenerPropagator.getPropagator().onNewClient(uuid); - return uuid; - } - - - @Override - public UUID getIdentifier(HttpServletRequest req, HttpServletResponse resp) { - - // get from session - UUID uuid = (UUID) req.getSession().getAttribute(cookieIdentifier); - - // if nothing in session - if (uuid == null) { - - // check in cookie - Cookie cookie = getCookie(req.getCookies(), cookieIdentifier); - if (cookie != null && cookie.getValue() != null) { - // set in session - uuid = UUID.fromString(cookie.getValue()); - req.getSession().setAttribute(cookieIdentifier, uuid); - jlfuListenerPropagator.getPropagator().onClientBack(uuid); - return uuid; - } - - // if not in session nor cookie, create one - // create uuid - uuid = getUuid(); - - // and set it - setIdentifier(req, resp, uuid); - - } - return uuid; - } - - - @Override - public void clearIdentifier(HttpServletRequest req, HttpServletResponse resp) { - // clear session - req.getSession().removeAttribute(cookieIdentifier); - - // remove cookie - Cookie cookie = getCookie(req.getCookies(), cookieIdentifier); - if (cookie != null) { - cookie.setMaxAge(0); - resp.addCookie(cookie); - } - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListener.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListener.java deleted file mode 100644 index f069a46..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListener.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.am.jlfu.notifier; - - -import java.util.Collection; -import java.util.UUID; - -import com.am.jlfu.fileuploader.limiter.RateLimiterConfigurationManager; -import com.am.jlfu.identifier.impl.DefaultIdentifierProvider; -import com.am.jlfu.staticstate.JavaLargeFileUploaderService; -import com.am.jlfu.staticstate.entities.FileProgressStatus; - - - -/** - * Listener to be able to monitor the JLFU API on the java side. - * Use {@link JLFUListenerPropagator} to register a listener. - * - * @author antoinem - * - */ -public interface JLFUListener { - - /** - * Fired when a new client has been attributed a new id.
- * Note that this event is sent by the {@link DefaultIdentifierProvider}. - * - * @param clientId - */ - void onNewClient(UUID clientId); - - - /** - * Fired when a client is identified with its cookie and the corresponding state is restored. - * Note that this event is sent by the {@link DefaultIdentifierProvider}. - * - * @param clientId - */ - void onClientBack(UUID clientId); - - - /** - * Fired when the uploads of a client have been inactive for duration specified.
- * Default to {@link RateLimiterConfigurationManager#clientEvictionTimeInSeconds} - * - * @param clientId - * @param inactivityDuration - */ - void onClientInactivity(UUID clientId, int inactivityDuration); - - - /** - * Fired when the upload of the file specified by the fileId is finished for the client - * specified by the clientId. - * - * @param clientId - * @param fileId - */ - void onFileUploadEnd(UUID clientId, UUID fileId); - - - /** - * Fired when the upload of the file specified by the fileId has been prepared for the client - * specified by the clientId. - * - * @param clientId - * @param fileId - */ - void onFileUploadPrepared(UUID clientId, UUID fileId); - - - /** - * Fired when all the uploads of the files specified by the fileIds have been prepared for the - * client - * specified by the clientId. - * - * @param clientId - * @param fileIds - */ - void onAllFileUploadsPrepared(UUID identifier, Collection fileIds); - - - /** - * Fired when the upload of the file specified by the fileId has been cancelled for the client - * specified by the clientId. - * - * @param clientId - * @param fileId - */ - void onFileUploadCancelled(UUID clientId, UUID fileId); - - - /** - * Fired when the upload of the file specified by the fileId has been paused for the client - * specified by the clientId. - * - * @param clientId - * @param fileId - */ - void onFileUploadPaused(UUID clientId, UUID fileId); - - - /** - * Fired when the upload of the file specified by the fileId has been resumed for the client - * specified by the clientId. - * - * @param clientId - * @param fileId - */ - void onFileUploadResumed(UUID clientId, UUID fileId); - - /** - * Fired about every second for each file currently uploading specified by the fileId for the client - * specified by the clientId whose progress has changed. - * - * @param clientId - * @param fileId - * @param progress - */ - void onFileUploadProgress(UUID clientId, UUID fileId, FileProgressStatus progress); - - /** - * Fired when the administration method {@link JavaLargeFileUploaderService#disableFileUploader()} is called. - */ - void onFileUploaderDisabled(); - - /** - * Fired when the administration method {@link JavaLargeFileUploaderService#enableFileUploader()} is called. - */ - void onFileUploaderEnabled(); - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListenerAdapter.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListenerAdapter.java deleted file mode 100644 index 913490b..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListenerAdapter.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.am.jlfu.notifier; - - -import java.util.Collection; -import java.util.UUID; - -import com.am.jlfu.staticstate.entities.FileProgressStatus; - - - -/** - * Listener adapter of {@link JLFUListener}. - * - * @author antoinem - * - */ -public class JLFUListenerAdapter - implements JLFUListener { - - @Override - public void onNewClient(UUID clientId) { - - } - - - @Override - public void onClientBack(UUID clientId) { - - } - - - @Override - public void onClientInactivity(UUID clientId, int inactivityDuration) { - - } - - - @Override - public void onFileUploadEnd(UUID clientId, UUID fileId) { - - } - - - @Override - public void onFileUploadPrepared(UUID clientId, UUID fileId) { - - } - - - @Override - public void onFileUploadCancelled(UUID clientId, UUID fileId) { - - } - - - @Override - public void onFileUploadPaused(UUID clientId, UUID fileId) { - - } - - - @Override - public void onFileUploadResumed(UUID clientId, UUID fileId) { - - } - - - @Override - public void onAllFileUploadsPrepared(UUID identifier, Collection fileIds) { - - } - - - @Override - public void onFileUploadProgress(UUID clientId, UUID fileId, FileProgressStatus progress) { - - } - - - @Override - public void onFileUploaderDisabled() { - - } - - - @Override - public void onFileUploaderEnabled() { - - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListenerPropagator.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListenerPropagator.java deleted file mode 100644 index 9b8218f..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/JLFUListenerPropagator.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.am.jlfu.notifier; - - -import org.springframework.stereotype.Component; - -import com.am.jlfu.notifier.utils.GenericPropagator; - - - -/** - * Propagates the events to the registered listeners. - * - * @author antoinem - * - */ -@Component -public class JLFUListenerPropagator extends GenericPropagator { - - @Override - protected Class getProxiedClass() { - return JLFUListener.class; - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/utils/GenericPropagator.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/utils/GenericPropagator.java deleted file mode 100644 index 67d419d..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/notifier/utils/GenericPropagator.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.am.jlfu.notifier.utils; - - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.PostConstruct; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.am.jlfu.notifier.JLFUListener; -import com.google.common.base.Joiner; -import com.google.common.collect.Lists; - - - -/** - * Propagates the methods called on {@link #proxiedElement} to all objects in {@link #propagateTo}.
- * {@link #getProxiedClass()} has to be overridden by any subclass.
- * Note that in order to not block the caller, the invocation is processed in a separate thread. - * - * @param - * @author antoinem - */ -public abstract class GenericPropagator { - - private static final Logger log = LoggerFactory.getLogger(GenericPropagator.class); - - - /** The element proxied by {@link #initProxy()} */ - private T proxiedElement; - - /** List of objects to propagate to */ - private List propagateTo = Lists.newArrayList(); - - - - /** - * @return The class of {@link #proxiedElement} - */ - protected abstract Class getProxiedClass(); - - - @PostConstruct - @SuppressWarnings("unchecked") - private void initProxy() { - - // initialize the proxy - proxiedElement = (T) Proxy.newProxyInstance( - getProxiedClass().getClassLoader(), - new Class[] { getProxiedClass() }, - new InvocationHandler() { - - @Override - public Object invoke(Object proxy, final Method method, final Object[] args) - throws Throwable { - synchronized (propagateTo) { - process(new ArrayList(propagateTo), method, args); - } - return null; - } - - - private void process(final List list, final Method method, final Object[] args) { - new Thread() { - - @Override - public void run() { - - if (log.isTraceEnabled()) { - log.trace("{propagating `" + method.getName() + "` with args `"+Joiner.on(',').join(args)+"` to `" + list.size() + "` elements}"); - } - - for (T o : list) { - try { - method.invoke(o, args); - } - catch (Exception e) { - log.error("cannot propagate " + method.getName(), e); - } - } - } - }.start(); - } - }); - - } - - - /** - * Register a propagant to {@link #propagateTo}. - * - * @param propagant - */ - public void registerListener(T propagant) { - synchronized (propagateTo) { - propagateTo.add(propagant); - } - } - - - /** - * Unregister a propagant from {@link #propagateTo}. - * - * @param propagant - */ - public void unregisterListener(JLFUListener propagant) { - synchronized (propagateTo) { - propagateTo.remove(propagant); - } - } - - - /** - * Unregister all the listeners. - */ - public void unregisterAllListeners() { - synchronized (propagateTo) { - propagateTo.clear(); - } - } - - - /** - * @return the propagator. - */ - public T getPropagator() { - return proxiedElement; - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/FileDeleter.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/FileDeleter.java deleted file mode 100644 index 25506bf..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/FileDeleter.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.am.jlfu.staticstate; - - -import java.io.File; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - -import org.apache.commons.io.FileUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; - - - -/** - * Takes care of deleting the files. - * - * @author antoinem - * - */ -@Component -public class FileDeleter - implements Runnable { - - private static final Logger log = LoggerFactory.getLogger(FileDeleter.class); - - /** The executor */ - private ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1); - - - - @PostConstruct - private void start() { - executor.schedule(this, 10, TimeUnit.SECONDS); - } - - - - /** - * List of the files to delete. - */ - private List files = Lists.newArrayList(); - - - - @Override - public void run() { - - // extract all the files to an immutable list - ImmutableList copyOf; - synchronized (this.files) { - copyOf = ImmutableList.copyOf(this.files); - } - - // log - boolean weHaveFilesToDelete = !copyOf.isEmpty(); - if (weHaveFilesToDelete) { - log.debug(copyOf.size() + " files to delete"); - } - - // and create a new list - List successfullyDeletedFiles = Lists.newArrayList(); - - // delete them - for (File file : copyOf) { - if (delete(file)) { - successfullyDeletedFiles.add(file); - log.debug(file + " successfully deleted."); - } - else { - log.debug(file + " not deleted, rescheduled for deletion."); - } - } - - // all the files have been processed - // remove the deleted files from queue - synchronized (this.files) { - Iterables.removeAll(this.files, successfullyDeletedFiles); - } - - // log - if (weHaveFilesToDelete) { - log.debug(successfullyDeletedFiles.size() + " deleted files"); - } - - // and reschedule - start(); - } - - - /** - * @param file - * @return true if the file has been deleted, false otherwise. - */ - private boolean delete(File file) { - - try { - // if file exists - if (file.exists()) { - - // if it is a file - if (file.isFile()) { - // delete it - return file.delete(); - } - // otherwise, if it is a directoy - else if (file.isDirectory()) { - FileUtils.deleteDirectory(file); - return true; - } - // if its none of them, we cannot delete them so we assume its deleted. - else { - return true; - } - - } - // if does not exist, we can remove it from list - else { - return true; - } - } - // if we have an exception - catch (Exception e) { - log.error(file + " deletion exception: " + e.getMessage()); - // the file has not been deleted - return false; - } - - } - - - public void deleteFile(File... file) { - deleteFiles(Arrays.asList(file)); - } - - - public void deleteFiles(Collection files) { - synchronized (this.files) { - this.files.addAll(files); - } - } - - - /** - * Returns true if the specified file is scheduled for deletion - * - * @param file - * @return - */ - public boolean deletionQueueContains(File file) { - synchronized (this.files) { - return files.contains(file); - } - } - - - @PreDestroy - private void destroy() throws InterruptedException { - log.debug("destroying executor"); - executor.shutdown(); - if (!executor.awaitTermination(1, TimeUnit.MINUTES)) { - log.error("executor timed out"); - List shutdownNow = executor.shutdownNow(); - for (Runnable runnable : shutdownNow) { - log.error(runnable + "has not been terminated"); - } - } - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/JavaLargeFileUploaderService.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/JavaLargeFileUploaderService.java deleted file mode 100644 index 4d7bd1d..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/JavaLargeFileUploaderService.java +++ /dev/null @@ -1,201 +0,0 @@ -package com.am.jlfu.staticstate; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FilenameFilter; -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; - -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jmx.export.annotation.ManagedOperation; -import org.springframework.jmx.export.annotation.ManagedResource; -import org.springframework.stereotype.Component; - -import com.am.jlfu.fileuploader.logic.UploadServletAsyncProcessor; -import com.am.jlfu.fileuploader.utils.ProgressManager; -import com.am.jlfu.notifier.JLFUListenerPropagator; -import com.am.jlfu.staticstate.entities.FileProgressStatus; -import com.am.jlfu.staticstate.entities.StaticStatePersistedOnFileSystemEntity; -import com.thoughtworks.xstream.XStream; - -/** - * Provides methods related to the management of information of the files for services outside the scope of a request.
- * - * @author antoinem - * @see StaticStateManager - */ -@Component -@ManagedResource(objectName = "JavaLargeFileUploader:name=operationManager") -public class JavaLargeFileUploaderService { - - @Autowired - FileDeleter fileDeleter; - - @Autowired - StaticStateManager staticStateManager; - - @Autowired - ProgressManager progressManager; - - @Autowired - StaticStateDirectoryManager staticStateDirectoryManager; - - @Autowired - UploadServletAsyncProcessor uploadServletAsyncProcessor; - - @Autowired - JLFUListenerPropagator jlfuListenerPropagator; - - private static final Logger log = LoggerFactory.getLogger(JavaLargeFileUploaderService.class); - - - /** - * Retrieves the progress of the specified file for the specified client.
- * - * - * @param clientId - * @param fileId - * @return - * @throws FileNotFoundException - */ - public FileProgressStatus getProgress(UUID clientId, UUID fileId) - throws FileNotFoundException { - return progressManager.getProgress(fileId); - } - - - - /** - * Updates an entity inside the cache and onto the filesystem. - * - * @param uuid the uuid of the client, identifying the file - * @param entity the entity to write into that file - */ - public void updateEntity(UUID uuid, T entity) { - log.debug("writing state for " + uuid); - staticStateManager.cache.put(uuid, entity); - writeEntity(new File(staticStateDirectoryManager.getUUIDFileParent(uuid), StaticStateManager.FILENAME), entity); - } - - /** - * Persists modifications onto filesystem only. - * - * @param uuid the uuid of the client, identifying the file - * @param entity the entity to write into that file - */ - public void writeEntity(UUID uuid, T entity) { - writeEntity(new File(staticStateDirectoryManager.getUUIDFileParent(uuid), StaticStateManager.FILENAME), entity); - } - - /** - * Persists modifications onto filesystem only. - * - * @param staticStateFile the file in which to write the entity - * @param entity the entity to write into that file - */ - public void writeEntity(File staticStateFile, T entity) { - write(entity, staticStateFile); - } - - private void write(T modelFromContext, File modelFile) { - XStream xStream = new XStream(); - FileOutputStream fs = null; - try { - fs = new FileOutputStream(modelFile); - xStream.toXML(modelFromContext, fs); - } - catch (FileNotFoundException e) { - log.error("cannot write to model file for " + modelFromContext.getClass().getSimpleName() + ": " + e.getMessage(), e); - } - finally { - IOUtils.closeQuietly(fs); - } - } - - - - /** - * Retrieves the entity from cache using a client identifier. - * - * @param clientIdentifier - * @return - */ - public T getEntityIfPresent(UUID clientIdentifier) { - return staticStateManager.cache.getIfPresent(clientIdentifier); - } - - /** - * Remove the pending uploaded file identifier by this id for this client. - * @param clientId - * @param fileId - */ - public void clearFile(final UUID clientId, final UUID fileId) - { - log.debug("Clearing pending uploaded file and all attributes linked to it."); - - final File uuidFileParent = staticStateDirectoryManager.getUUIDFileParent(clientId); - - // remove the uploaded file for this particular id - fileDeleter.deleteFile(uuidFileParent.listFiles(new FilenameFilter() { - - public boolean accept(File dir, String name) { - return name.startsWith(fileId.toString()); - } - })); - - // remove the file information in entity - T entity = getEntityIfPresent(clientId); - entity.getFileStates().remove(fileId); - - // and save - updateEntity(clientId, entity); - } - - /** - * Clear everything including cache, session, files for this client. - * - * @throws TimeoutException - * @throws ExecutionException - * @throws InterruptedException - */ - public void clearClient(UUID clientId) { - log.debug("Clearing everything including cache, session, files."); - - final File uuidFileParent = staticStateDirectoryManager.getUUIDFileParent(clientId); - - // schedule file for deletion - fileDeleter.deleteFile(uuidFileParent); - - // remove entity from cache - staticStateManager.cache.invalidate(clientId); - - } - - - /** - * Enables the processing of file uploads. Clients will automatically resume their upload. - * @see #disableFileUploader() - */ - @ManagedOperation - public void enableFileUploader() { - uploadServletAsyncProcessor.setEnabled(true); - jlfuListenerPropagator.getPropagator().onFileUploaderEnabled(); - } - - /** - * Disables the processing of file uploads. Clients currently uploading Files will wait and automatically resume the uploads when {@link #enableFileUploader()} is called. - * @see #enableFileUploader() - */ - @ManagedOperation - public void disableFileUploader() { - uploadServletAsyncProcessor.setEnabled(false); - jlfuListenerPropagator.getPropagator().onFileUploaderDisabled(); - } - -} - diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/StaticStateDirectoryManager.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/StaticStateDirectoryManager.java deleted file mode 100644 index 17cc7d6..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/StaticStateDirectoryManager.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.am.jlfu.staticstate; - - -import java.io.File; -import java.util.UUID; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - - - -@Component -public class StaticStateDirectoryManager { - - @Autowired - StaticStateRootFolderProvider staticStateRootFolderProvider; - - @Autowired - StaticStateIdentifierManager staticStateIdentifierManager; - - - - /** - * Retrieves the file parent of the session. - * - * @return - */ - public File getUUIDFileParent() { - return getUUIDFileParent(staticStateIdentifierManager.getIdentifier()); - } - - - /** - * Retrieves the file parent of the session context less. - * - * @param uuid - * @return - */ - public File getUUIDFileParent(UUID uuid) { - File uuidFileParent = new File(staticStateRootFolderProvider.getRootFolder(), uuid.toString()); - if (!uuidFileParent.exists()) { - uuidFileParent.mkdirs(); - } - return uuidFileParent; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/StaticStateIdentifierManager.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/StaticStateIdentifierManager.java deleted file mode 100644 index 1dd61d8..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/StaticStateIdentifierManager.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.am.jlfu.staticstate; - - -import java.util.UUID; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.am.jlfu.fileuploader.web.utils.RequestComponentContainer; -import com.am.jlfu.identifier.IdentifierProvider; - - - -@Component -public class StaticStateIdentifierManager { - - @Autowired - IdentifierProvider identifierProvider; - - @Autowired - RequestComponentContainer requestComponentContainer; - - - - public UUID getIdentifier() { - return identifierProvider.getIdentifier(requestComponentContainer.getRequest(), requestComponentContainer.getResponse()); - } - - - public void clearIdentifier() { - identifierProvider.clearIdentifier(requestComponentContainer.getRequest(), requestComponentContainer.getResponse()); - } - - - public void setIdentifier(UUID id) { - identifierProvider.setIdentifier(requestComponentContainer.getRequest(), requestComponentContainer.getResponse(), id); - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/StaticStateManager.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/StaticStateManager.java deleted file mode 100644 index b088398..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/StaticStateManager.java +++ /dev/null @@ -1,302 +0,0 @@ -package com.am.jlfu.staticstate; - - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.am.jlfu.fileuploader.exception.FileCorruptedException; -import com.am.jlfu.fileuploader.json.FileStateJsonBase; -import com.am.jlfu.notifier.JLFUListenerPropagator; -import com.am.jlfu.staticstate.entities.StaticFileState; -import com.am.jlfu.staticstate.entities.StaticStatePersistedOnFileSystemEntity; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.thoughtworks.xstream.XStream; - - - -/** - * Manages the information related to the files.
- * This information is stored locally in a cache and also persisted on the file system.
- * All of the methods used here are to be called within the scope of a request. Most of these methods (to query and update) are also available outside of such a scope in {@link JavaLargeFileUploaderService} - * This class has to be initialized with the {@link #init(Class)} method first. - * - * @author antoinem - * - * @param - */ -@Component -public class StaticStateManager { - - private static final Logger log = LoggerFactory.getLogger(StaticStateManager.class); - static final String FILENAME = "StaticState.xml"; - - @Autowired - FileDeleter fileDeleter; - - @Autowired - JLFUListenerPropagator jlfuListenerPropagator; - - @Autowired - StaticStateIdentifierManager staticStateIdentifierManager; - - @Autowired - StaticStateDirectoryManager staticStateDirectoryManager; - - @Autowired - JavaLargeFileUploaderService staticStateManagerService; - - /** - * Used to bypass generic type erasure.
- * Has to be manually specified with the {@link #init(Class)} method. - */ - Class entityType; - - - /** The executor that could write stuff asynchronously into the static state */ - private ThreadPoolExecutor fileStateUpdaterExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1); - - - - private Class getEntityType() { - // if not defined, try to init with default - if (entityType == null) { - entityType = (Class) StaticStatePersistedOnFileSystemEntity.class; - } - return entityType; - } - - - - LoadingCache cache = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.DAYS).build(new CacheLoader() { - - public T load(UUID uuid) - throws Exception { - - return createOrRestore(uuid); - - } - }); - - - - /** - * Creates or restores a new file. - * - * @param uuid - * @return - * @throws IOException - */ - private T createOrRestore(UUID uuid) - throws IOException { - - // restore cache from file: - File uuidFileParent = staticStateDirectoryManager.getUUIDFileParent(); - - // if that file is scheduled for deletion, we do not restore it - if (fileDeleter.deletionQueueContains(uuidFileParent)) { - log.debug("trying to restore from state a file that is scheduled for deletion"); - // invalidate identifier - staticStateIdentifierManager.clearIdentifier(); - // get a new one - // and recreate file - uuidFileParent = staticStateDirectoryManager.getUUIDFileParent(); - } - - File uuidFile = new File(uuidFileParent, FILENAME); - T entity = null; - - if (uuidFile.exists()) { - log.debug("No value in the cache for uuid " + uuid + ". Filling cache from file."); - try { - entity = read(uuidFile); - } - catch (Exception e) { - log.error("Cache cannot be restored from " + uuidFile.getAbsolutePath() + "." + - "The file might be empty or the model has changed since last time: " + e.getMessage(), e); - } - } - else { - log.debug("No value in the cache for uuid " + uuid + " and no value in the file. Creating a new one."); - - // create the file - try { - uuidFile.createNewFile(); - } - catch (IOException e) { - log.error("cannot create model file: " + e.getMessage(), e); - throw e; - } - - // and persist an entity - try { - entity = getEntityType().newInstance(); - } - catch (InstantiationException e) { - throw new RuntimeException(e); - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - staticStateManagerService.writeEntity(uuidFile, entity); - - } - - // then return entity - return entity; - } - - /** - * Retrieves the entity from cookie or cache if it exists or create one if it does not exists. - * - * @return - * @throws ExecutionException - */ - public T getEntity() { - return cache.getUnchecked(staticStateIdentifierManager.getIdentifier()); - } - - - /** - * Retrieves the entity from cache or null if this entity is not present. - * - * @return - */ - public StaticStatePersistedOnFileSystemEntity getEntityIfPresent() { - return staticStateManagerService.getEntityIfPresent(staticStateIdentifierManager.getIdentifier()); - } - - - /** - * Persist modifications to file and cache. - * - * @param entity - * @return - * @throws ExecutionException - */ - public void updateEntity(T entity) { - UUID uuid = staticStateIdentifierManager.getIdentifier(); - staticStateManagerService.updateEntity(uuid, entity); - } - - - /** - * Clear everything including cache, session, files. - * - * @throws TimeoutException - * @throws ExecutionException - * @throws InterruptedException - */ - public void clear() - { - //clear stuff on the server - staticStateManagerService.clearClient(staticStateIdentifierManager.getIdentifier()); - - // remove cookie and session - staticStateIdentifierManager.clearIdentifier(); - - } - - - public void clearFile(final UUID fileId) - { - staticStateManagerService.clearFile(staticStateIdentifierManager.getIdentifier(), fileId); - } - - - - T read(File f) { - XStream xStream = new XStream(); - FileInputStream fs = null; - T fromXML = null; - try { - fs = new FileInputStream(f); - fromXML = (T) xStream.fromXML(fs); - } - catch (FileNotFoundException e) { - log.error("cannot read model file: " + e.getMessage(), e); - } - finally { - IOUtils.closeQuietly(fs); - } - return fromXML; - } - - - /** - * Initializes the bean with the class of the entity. Shall be called once. Calling it more than - * once has no effect. - * - * @param clazz - */ - public void init(Class clazz) { - entityType = clazz; - } - - - /** - * Writes in the file that the last slice has been successfully uploaded. - * - * @param clientId - * @param fileId - * @return true if the file is complete - * @throws FileCorruptedException - */ - public void setCrcBytesValidated(final UUID clientId, UUID fileId, final long validated) throws FileCorruptedException { - - final T entity = cache.getIfPresent(clientId); - if (entity == null) { - return; - } - final StaticFileState staticFileState = entity.getFileStates().get(fileId); - if (staticFileState == null) { - return; - } - FileStateJsonBase staticFileStateJson = staticFileState.getStaticFileStateJson(); - if (staticFileStateJson == null) { - return; - } - Long crcredBytes = staticFileStateJson.getCrcedBytes(); - staticFileStateJson.setCrcedBytes( - crcredBytes + validated); - - log.debug(validated + " more bytes have been validated appended to the already " + crcredBytes + " bytes validated for file " + fileId + - " for client id " + clientId); - - // manage the end of file - if (staticFileStateJson.getCrcedBytes().equals(staticFileStateJson.getOriginalFileSizeInBytes())) { - jlfuListenerPropagator.getPropagator().onFileUploadEnd(clientId, fileId); - } - - //checks whether we have a file corruption exception - if (staticFileStateJson.getCrcedBytes() > staticFileStateJson.getOriginalFileSizeInBytes()) { - throw new FileCorruptedException(staticFileStateJson.getCrcedBytes() + " crced bytes are more than it should be: " + staticFileStateJson.getOriginalFileSizeInBytes()); - } - - fileStateUpdaterExecutor.submit(new Runnable() { - - @Override - public void run() { - // write this later on. - staticStateManagerService.writeEntity(clientId, entity); - } - }); - - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/StaticStateRootFolderProvider.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/StaticStateRootFolderProvider.java deleted file mode 100644 index 8b7e564..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/StaticStateRootFolderProvider.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.am.jlfu.staticstate; - - -import java.io.File; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.springframework.web.context.WebApplicationContext; - - - -/** - * Provides the root folder in which files will be uploaded.
- * - * @author antoinem - * - */ -@Component -public class StaticStateRootFolderProvider { - - @Value("jlfu{jlfu.defaultUploadFolder:/JavaLargeFileUploader}") - private String defaultUploadFolder; - - @Value("jlfu{jlfu.uploadFolderRelativePath:true}") - private Boolean uploadFolderRelativePath; - - @Autowired(required = false) - WebApplicationContext webApplicationContext; - - public File getRootFolder() { - String realPath = defaultUploadFolder; - if (uploadFolderRelativePath) { - realPath = webApplicationContext.getServletContext().getRealPath(defaultUploadFolder); - } - File file = new File(realPath); - // create if non existent - if (!file.exists()) { - file.mkdirs(); - } - // if existent but a file, runtime exception - else { - if (file.isFile()) { - throw new RuntimeException(file.getAbsolutePath() + - " is a file. The default root folder provider uses this path to store the files. Consider using a specific root folder provider or delete this file."); - } - } - return file; - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/entities/FileProgressStatus.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/entities/FileProgressStatus.java deleted file mode 100644 index 0353898..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/entities/FileProgressStatus.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.am.jlfu.staticstate.entities; - -import com.am.jlfu.fileuploader.json.ProgressJson; -import com.am.jlfu.fileuploader.utils.UnitConverter; - -/** - * Entity providing progress information about a file. - * - * @author antoinem - * - */ -public class FileProgressStatus extends ProgressJson{ - - /** - * Generated id. - */ - private static final long serialVersionUID = -6247365041854992033L; - - private long totalFileSize; - private long bytesUploaded; - - /** - * Default constructor. - */ - public FileProgressStatus() { - super(); - } - - /** - * @return total file of the size in bytes. - */ - public long getTotalFileSize() { - return totalFileSize; - } - - - public void setTotalFileSize(long totalFileSize) { - this.totalFileSize = totalFileSize; - } - - /** - * @return quantity of bytes uploaded. - */ - public long getBytesUploaded() { - return bytesUploaded; - } - - - public void setBytesUploaded(long bytesUploaded) { - this.bytesUploaded = bytesUploaded; - } - - @Override - public String toString() { - String s = ""; - s+= "Uploaded "+bytesUploaded; - s+= "/"+totalFileSize+" Bytes"; - s+= "("+progress+"%)"; - if (uploadRate != null) { - s+= "at rate: "+UnitConverter.getFormattedSize(uploadRate) +"/s."; - } - if (estimatedRemainingTimeInSeconds != null) { - s+= " Finishing in "+UnitConverter.getFormattedTime(estimatedRemainingTimeInSeconds)+"."; - } - return s; - } - - /** - * Please use {@link #getProgress()} - * @return - */ - @Deprecated - public Float getPercentageCompleted() { - return getProgress(); - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/entities/StaticFileState.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/entities/StaticFileState.java deleted file mode 100644 index 2dac372..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/entities/StaticFileState.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.am.jlfu.staticstate.entities; - - -import java.io.Serializable; - -import com.am.jlfu.fileuploader.json.FileStateJsonBase; - - -/** - * Server-side entity representing a file.
- * It contains the shared file information ({@link FileStateJsonBase}) and the url of the file. - * @author antoinem - * - */ -public class StaticFileState - implements Serializable { - - - /** generated id */ - private static final long serialVersionUID = 2196169291933051657L; - - /** The full path url of the uploaded file. */ - private String absoluteFullPathOfUploadedFile; - - /** The information related to the file upload. */ - private FileStateJsonBase staticFileStateJson; - - - - /** - * Default constructor. - */ - public StaticFileState() { - super(); - } - - - public String getAbsoluteFullPathOfUploadedFile() { - return absoluteFullPathOfUploadedFile; - } - - - public void setAbsoluteFullPathOfUploadedFile(String absoluteFullPathOfUploadedFile) { - this.absoluteFullPathOfUploadedFile = absoluteFullPathOfUploadedFile; - } - - - public FileStateJsonBase getStaticFileStateJson() { - return staticFileStateJson; - } - - - public void setStaticFileStateJson(FileStateJsonBase staticFileStateJson) { - this.staticFileStateJson = staticFileStateJson; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/entities/StaticStatePersistedOnFileSystemEntity.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/entities/StaticStatePersistedOnFileSystemEntity.java deleted file mode 100644 index 92cdf9e..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/staticstate/entities/StaticStatePersistedOnFileSystemEntity.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.am.jlfu.staticstate.entities; - - -import java.io.Serializable; -import java.util.Map; -import java.util.UUID; - -import com.am.jlfu.staticstate.StaticStateManager; -import com.google.common.collect.Maps; - - - -/** - * Abstract class that is persisted on the filesystem and contains information about the files being - * uploaded.
- * You can of course extend it if you want to persist other stuff on the filesystem. If you do so, - * you will have to call {@link StaticStateManager#init(Class)} with the type of the class you - * defined extending this one. - * - * @author antoinem - * - */ -public class StaticStatePersistedOnFileSystemEntity - implements Serializable { - - /** generated id */ - private static final long serialVersionUID = 6033009138577295466L; - - /** The states of the files being uploaded, the UUID being its identifier. */ - private Map fileStates = Maps.newHashMap(); - - - - /** - * Default constructor. - */ - public StaticStatePersistedOnFileSystemEntity() { - super(); - } - - - public Map getFileStates() { - return fileStates; - } - - - public void setFileStates(Map fileStates) { - this.fileStates = fileStates; - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/resources/META-INF/jlfu-web-fragment-context.xml b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/resources/META-INF/jlfu-web-fragment-context.xml deleted file mode 100644 index 11e9947..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/resources/META-INF/jlfu-web-fragment-context.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - classpath:java-large-file-uploader.properties - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/resources/META-INF/web-fragment.xml b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/resources/META-INF/web-fragment.xml deleted file mode 100644 index 8f01921..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/resources/META-INF/web-fragment.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - jlfuWebFragment - - - - contextConfigLocation - classpath*:/META-INF/jlfu-web-fragment-context.xml - - - - org.springframework.web.context.ContextLoaderListener - - - - jlfuFilter - org.springframework.web.filter.DelegatingFilterProxy - true - - - - - jlfuFilter - /* - - - \ No newline at end of file diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/resources/log4j.properties b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/resources/log4j.properties deleted file mode 100644 index 63da6f2..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/resources/log4j.properties +++ /dev/null @@ -1,11 +0,0 @@ -# Loggers. - -log4j.rootLogger = DEBUG, console -log4j.logger.org.springframework = WARN - - -# Appenders. - -log4j.appender.console = org.apache.log4j.ConsoleAppender -log4j.appender.console.layout = org.apache.log4j.PatternLayout -log4j.appender.console.layout.ConversionPattern = %p %d{ISO8601} %C{1} %t %m %n diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/authorizer/DefaultAuthorizerTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/authorizer/DefaultAuthorizerTest.java deleted file mode 100644 index e9eab48..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/authorizer/DefaultAuthorizerTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.am.jlfu.authorizer; - - -import java.util.UUID; - -import javax.servlet.http.HttpServletRequest; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.am.jlfu.fileuploader.exception.AuthorizationException; -import com.am.jlfu.fileuploader.web.UploadServletAction; - - - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class DefaultAuthorizerTest { - - @Autowired - Authorizer authorizer; - - - - @Test - public void test() - throws AuthorizationException { - authorizer.getAuthorization(null, null, null, null); - } - - - @Test(expected = AuthorizationException.class) - public void testException() - throws AuthorizationException { - new Authorizer() { - - @Override - public void getAuthorization(HttpServletRequest request, UploadServletAction action, UUID clientId, UUID... optionalFileId) - throws AuthorizationException { - throw new AuthorizationException(action, clientId, optionalFileId); - } - }.getAuthorization(null, null, null, null); - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/limiter/RateLimiterConfigurationManagerTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/limiter/RateLimiterConfigurationManagerTest.java deleted file mode 100644 index eafaa6e..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/limiter/RateLimiterConfigurationManagerTest.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.am.jlfu.fileuploader.limiter; - - -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import org.hamcrest.CoreMatchers; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.am.jlfu.fileuploader.json.FileStateJsonBase; -import com.am.jlfu.fileuploader.web.utils.RequestComponentContainer; -import com.am.jlfu.notifier.JLFUListenerAdapter; -import com.am.jlfu.notifier.JLFUListenerPropagator; -import com.am.jlfu.staticstate.StaticStateIdentifierManager; -import com.am.jlfu.staticstate.StaticStateManager; -import com.am.jlfu.staticstate.entities.StaticFileState; -import com.am.jlfu.staticstate.entities.StaticStatePersistedOnFileSystemEntity; -import com.google.common.cache.RemovalCause; - - - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class RateLimiterConfigurationManagerTest { - - @Autowired - RateLimiterConfigurationManager rateLimiterConfigurationManager; - - @Autowired - JLFUListenerPropagator jlfuListenerPropagator; - - @Autowired - StaticStateManager staticStateManager; - - @Autowired - StaticStateIdentifierManager staticStateIdentifierManager; - - @Autowired - RequestComponentContainer requestComponentContainer; - - private boolean assertt = false; - - - - @Before - public void init() { - - // populate request component container - requestComponentContainer.populate(new MockHttpServletRequest(), new MockHttpServletResponse()); - - } - - - @Test - public void testEvictionNotificationTrue() - throws InterruptedException { - testAssert(true); - } - - - @Test - public void testEvictionNotificationFalse() - throws InterruptedException { - testAssert(false); - } - - - private void testAssert(boolean lala) throws InterruptedException { - jlfuListenerPropagator.registerListener(new JLFUListenerAdapter() { - - @Override - public void onClientInactivity(UUID clientId, int inactivityDuration) { - assertt = true; - } - }); - - // emulate a pending upload - final StaticStatePersistedOnFileSystemEntity entity = staticStateManager.getEntity(); - final UUID identifier = staticStateIdentifierManager.getIdentifier(); - rateLimiterConfigurationManager.configurationMap - .put(identifier, new RequestUploadProcessingConfiguration()); - rateLimiterConfigurationManager.configurationMap.getUnchecked(identifier); - final StaticFileState value = new StaticFileState(); - entity.getFileStates().put(identifier, value); - final FileStateJsonBase staticFileStateJson = new FileStateJsonBase(); - value.setStaticFileStateJson(staticFileStateJson); - staticFileStateJson.setCrcedBytes(100l); - - if (lala) { - staticFileStateJson.setOriginalFileSizeInBytes(10000l); - } - else { - staticFileStateJson.setOriginalFileSizeInBytes(100l); - } - - rateLimiterConfigurationManager.remove(RemovalCause.EXPIRED, identifier); - - Thread.sleep(100); - if (lala) { - Assert.assertThat(assertt, CoreMatchers.is(true)); - } - else { - Assert.assertThat(assertt, CoreMatchers.is(false)); - } - } - - - @Test - public void testStreamExpectedToBeClosed() throws ExecutionException { - UUID randomUUID = UUID.randomUUID(); - rateLimiterConfigurationManager.configurationMap.put(randomUUID, new RequestUploadProcessingConfiguration()); - Assert.assertThat(rateLimiterConfigurationManager.configurationMap.get(randomUUID).isPaused(), CoreMatchers.is(false)); - rateLimiterConfigurationManager.configurationMap.get(randomUUID).pause(); - Assert.assertThat(rateLimiterConfigurationManager.configurationMap.get(randomUUID).isPaused(), CoreMatchers.is(true)); - Assert.assertThat(rateLimiterConfigurationManager.configurationMap.get(randomUUID).isPaused(), CoreMatchers.is(true)); - rateLimiterConfigurationManager.configurationMap.get(randomUUID).resume(); - Assert.assertThat(rateLimiterConfigurationManager.configurationMap.get(randomUUID).isPaused(), CoreMatchers.is(false)); - - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/limiter/RateLimiterTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/limiter/RateLimiterTest.java deleted file mode 100644 index 4bb2c5d..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/limiter/RateLimiterTest.java +++ /dev/null @@ -1,237 +0,0 @@ -package com.am.jlfu.fileuploader.limiter; - - -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.lessThan; - -import java.util.Date; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.am.jlfu.fileuploader.logic.UploadServletAsyncProcessor; -import com.google.common.collect.Lists; - - - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -// TODO make tests to check master and client limitations -public class RateLimiterTest { - - private static final Logger log = LoggerFactory.getLogger(RateLimiterTest.class); - - @Autowired - RateLimiterConfigurationManager uploadProcessingConfigurationManager; - - @Autowired - UploadProcessingOperationManager uploadProcessingOperationManager; - - - ExecutorService executorService = Executors.newFixedThreadPool(10); - - - - private void emulateUpload(Long requestRate, Long clientRate, Long masterRate, int uploadSizeInKB, int expectedDuration) - throws InterruptedException { - UUID fileId = UUID.randomUUID(); - UUID clientId = UUID.randomUUID(); - - // extract config - final RequestUploadProcessingConfiguration uploadProcessingConfiguration = - uploadProcessingConfigurationManager.getUploadProcessingConfiguration(fileId); - final UploadProcessingConfiguration clientProcessingConfiguration = - uploadProcessingConfigurationManager.getUploadProcessingConfiguration(clientId); - final UploadProcessingConfiguration masterProcessingConfiguration = - uploadProcessingConfigurationManager.getMasterProcessingConfiguration(); - - // extract operation - uploadProcessingOperationManager.startOperation(clientId, fileId); - final UploadProcessingOperation clientProcessingOperation = uploadProcessingOperationManager.getClientProcessingOperation(clientId); - final UploadProcessingOperation fileProcessingOperation = uploadProcessingOperationManager.getFileProcessingOperation(fileId); - final UploadProcessingOperation masterProcessingOperation = uploadProcessingOperationManager.getMasterProcessingOperation(); - - // init request rate - if (requestRate != null) { - assignRateToRequest(requestRate, fileId, uploadProcessingConfiguration, fileProcessingOperation); - } - - // perform upload - long itTookThatLong = - upload(clientId, fileId, uploadSizeInKB, uploadProcessingConfiguration, clientProcessingConfiguration, masterProcessingConfiguration, - fileProcessingOperation, clientProcessingOperation, masterProcessingOperation); - - // specify completion - uploadProcessingConfigurationManager.reset(fileId); - - // verify that it took around that duration - itTookAround(expectedDuration, itTookThatLong); - - } - - - private void itTookAround(int expectedDuration, Long itTookThatLong) { - Assert.assertThat(itTookThatLong.floatValue(), lessThan((float) expectedDuration * 1.2f)); - Assert.assertThat(itTookThatLong.floatValue(), greaterThan((float) expectedDuration * 0.8f)); - } - - - private void assignRateToRequest(Long requestRate, UUID id, final RequestUploadProcessingConfiguration uploadProcessingConfiguration, - UploadProcessingOperation fileProcessingOperation) { - - uploadProcessingConfiguration.setProcessing(true); - final long originalDownloadAllowanceForIteration = fileProcessingOperation.getDownloadAllowanceForIteration(); - uploadProcessingConfigurationManager.assignRateToRequest(id, requestRate); - - // wait for the rate modification to occur - while (fileProcessingOperation.getDownloadAllowanceForIteration() == originalDownloadAllowanceForIteration) { - } - } - - - private long upload(UUID clientId, UUID fileId, int uploadSizeInKB, - RequestUploadProcessingConfiguration requestUploadProcessingConfiguration, - UploadProcessingConfiguration clientUploadProcessingConfiguration, UploadProcessingConfiguration masterUploadProcessingConfiguration, - UploadProcessingOperation fileProcessingOperation, UploadProcessingOperation clientProcessingOperation, - UploadProcessingOperation masterProcessingOperation) { - - // set the request as processing - requestUploadProcessingConfiguration.setProcessing(true); - - // emulate an upload of a file - long totalUpload = uploadSizeInKB * 1024; - final Date reference = new Date(); - long allowance; - while (totalUpload > 0) { - - // calculate allowance - allowance = UploadServletAsyncProcessor.minOf( - (int) fileProcessingOperation.getDownloadAllowanceForIteration(), - (int) clientProcessingOperation.getDownloadAllowanceForIteration(), - (int) masterProcessingOperation.getDownloadAllowanceForIteration() - ); - - // consumption - fileProcessingOperation.bytesConsumedFromAllowance(allowance); - clientProcessingOperation.bytesConsumedFromAllowance(allowance); - masterProcessingOperation.bytesConsumedFromAllowance(allowance); - - totalUpload -= allowance; - log.debug(clientId + " " + fileId + " uploaded " + totalUpload); - } - return new Date().getTime() - reference.getTime(); - - - } - - - @Test - public void testMonoRequestLimitation() - throws ExecutionException, InterruptedException { - - // lets say we upload a 1MB file. - int upload = 1000; - - // set rate to 1MB, should have taken 1 second - log.debug("testMonoRequestLimitation 1MB"); - emulateUpload(1000l, null, null, upload, 1000); - - // set rate to 0.5MB, should have taken 2second - log.debug("testMonoRequestLimitation 2MB"); - emulateUpload(500l, null, null, upload, 2000); - - } - - - @Test - public void testClientRateLimitation() - throws InterruptedException, ExecutionException { - // client will limit - testClientMaster(10000, 100000); - - // master will limit - testClientMaster(100000, 10000); - } - - - private void testClientMaster(int client, int master) - throws InterruptedException { - - // set client rate limitation - uploadProcessingConfigurationManager.setMaximumRatePerClientInKiloBytes(client); - - // set master rate limitation - uploadProcessingConfigurationManager.setMaximumOverAllRateInKiloBytes(master); - - final UUID clientId = UUID.randomUUID(); - - // and 10 requests are gonna upload a 10MB file - int numberOfRequests = 10; - List> runnables = Lists.newArrayList(); - for (int i = 0; i < numberOfRequests; i++) { - runnables.add(new TestRunnable(clientId, UUID.randomUUID(), 10000)); - } - - // invoke - final Date reference = new Date(); - executorService.invokeAll(runnables); - - // shall have taken around 10seconds for all of them to complete - itTookAround(10000, new Date().getTime() - reference.getTime()); - } - - - - class TestRunnable - implements Callable { - - private UUID clientId; - private UUID fileId; - private int fileSize; - private RequestUploadProcessingConfiguration requestUploadProcessingConfiguration; - private UploadProcessingConfiguration clientUploadProcessingConfiguration; - private UploadProcessingConfiguration masterUploadProcessingConfiguration; - private UploadProcessingOperation fileProcessingOperation; - private UploadProcessingOperation masterProcessingOperation; - private UploadProcessingOperation clientProcessingOperation; - - - - public TestRunnable(UUID clientId, UUID fileId, int fileSize) { - this.clientId = clientId; - this.fileId = fileId; - this.fileSize = fileSize; - requestUploadProcessingConfiguration = - uploadProcessingConfigurationManager.getUploadProcessingConfiguration(fileId); - clientUploadProcessingConfiguration = - uploadProcessingConfigurationManager.getUploadProcessingConfiguration(clientId); - masterUploadProcessingConfiguration = - uploadProcessingConfigurationManager.getMasterProcessingConfiguration(); - uploadProcessingOperationManager.startOperation(clientId, fileId); - fileProcessingOperation = uploadProcessingOperationManager.getFileProcessingOperation(clientId); - clientProcessingOperation = uploadProcessingOperationManager.getClientProcessingOperation(fileId); - masterProcessingOperation = uploadProcessingOperationManager.getMasterProcessingOperation(); - } - - - @Override - public Long call() { - return upload(clientId, fileId, fileSize, requestUploadProcessingConfiguration, clientUploadProcessingConfiguration, - masterUploadProcessingConfiguration, fileProcessingOperation, clientProcessingOperation, masterProcessingOperation); - } - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/limiter/UploadProcessingOperationManagerTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/limiter/UploadProcessingOperationManagerTest.java deleted file mode 100644 index ac50e2a..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/limiter/UploadProcessingOperationManagerTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.am.jlfu.fileuploader.limiter; - - -import java.util.UUID; - -import org.hamcrest.CoreMatchers; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.am.jlfu.fileuploader.utils.ClientToFilesMap; - - - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class UploadProcessingOperationManagerTest { - - @Autowired - UploadProcessingOperationManager uploadProcessingOperationManager; - - @Autowired - ClientToFilesMap clientToFilesMap; - - - @Before - public void before() { - uploadProcessingOperationManager.clientsAndRequestsProcessingOperation.clear(); - clientToFilesMap.clear(); - } - - - @Test - public void test() { - - UUID clientId = UUID.randomUUID(); - UUID fileId = UUID.randomUUID(); - UUID fileId2 = UUID.randomUUID(); - - Assert.assertThat(uploadProcessingOperationManager.clientsAndRequestsProcessingOperation.isEmpty(), CoreMatchers.is(true)); - Assert.assertThat(clientToFilesMap.isEmpty(), CoreMatchers.is(true)); - - uploadProcessingOperationManager.startOperation(clientId, fileId); - - Assert.assertThat(uploadProcessingOperationManager.clientsAndRequestsProcessingOperation.containsKey(clientId), CoreMatchers.is(true)); - Assert.assertThat(clientToFilesMap.get(clientId).contains(fileId), CoreMatchers.is(true)); - - uploadProcessingOperationManager.startOperation(clientId, fileId2); - - Assert.assertThat(uploadProcessingOperationManager.clientsAndRequestsProcessingOperation.containsKey(clientId), CoreMatchers.is(true)); - Assert.assertThat(clientToFilesMap.get(clientId).contains(fileId), CoreMatchers.is(true)); - Assert.assertThat(clientToFilesMap.get(clientId).contains(fileId2), CoreMatchers.is(true)); - - uploadProcessingOperationManager.stopOperation(clientId, fileId2); - - Assert.assertThat(uploadProcessingOperationManager.clientsAndRequestsProcessingOperation.containsKey(clientId), CoreMatchers.is(true)); - Assert.assertThat(clientToFilesMap.get(clientId).contains(fileId), CoreMatchers.is(true)); - Assert.assertThat(clientToFilesMap.get(clientId).contains(fileId2), CoreMatchers.is(false)); - - uploadProcessingOperationManager.stopOperation(clientId, fileId); - - Assert.assertThat(uploadProcessingOperationManager.clientsAndRequestsProcessingOperation.containsKey(clientId), CoreMatchers.is(false)); - Assert.assertThat(clientToFilesMap.containsKey(clientId), CoreMatchers.is(false)); - Assert.assertThat(uploadProcessingOperationManager.clientsAndRequestsProcessingOperation.isEmpty(), CoreMatchers.is(true)); - Assert.assertThat(clientToFilesMap.isEmpty(), CoreMatchers.is(true)); - - - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/logic/UploadProcessorTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/logic/UploadProcessorTest.java deleted file mode 100644 index 381774e..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/logic/UploadProcessorTest.java +++ /dev/null @@ -1,212 +0,0 @@ -package com.am.jlfu.fileuploader.logic; - - -import static org.hamcrest.CoreMatchers.is; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; -import java.util.zip.CRC32; - -import javax.servlet.ServletException; - -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.web.multipart.MultipartFile; - -import com.am.jlfu.fileuploader.json.CRCResult; -import com.am.jlfu.fileuploader.json.InitializationConfiguration; -import com.am.jlfu.fileuploader.utils.CRCHelper; -import com.am.jlfu.fileuploader.web.UploadServletAsync; -import com.am.jlfu.fileuploader.web.utils.RequestComponentContainer; -import com.am.jlfu.staticstate.StaticStateIdentifierManager; -import com.am.jlfu.staticstate.StaticStateManager; -import com.am.jlfu.staticstate.entities.StaticFileState; -import com.am.jlfu.staticstate.entities.StaticStatePersistedOnFileSystemEntity; - - - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class UploadProcessorTest { - - private static final Logger log = LoggerFactory.getLogger(UploadProcessorTest.class); - - @Autowired - CRCHelper crcHelper; - - @Autowired - UploadProcessor uploadProcessor; - - @Autowired - UploadServletAsync uploadServletAsync; - - @Autowired - StaticStateManager staticStateManager; - - @Autowired - StaticStateIdentifierManager staticStateIdentifierManager; - - @Autowired - RequestComponentContainer requestComponentContainer; - - MockMultipartFile file; - - String fileName = "zenameofzefile.owf"; - - private Long fileSize; - - private byte[] content; - - - - @Before - public void init() - throws IOException, InterruptedException, ExecutionException, TimeoutException { - - // populate request component container - requestComponentContainer.populate(new MockHttpServletRequest(), new MockHttpServletResponse()); - - - staticStateManager.clear(); - content = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; - file = new MockMultipartFile("blob", content); - fileSize = Integer.valueOf(content.length).longValue(); - } - - - private void assertState(StaticFileState state, boolean absolutePathOfUploadedFileFilled, Boolean fileComplete, String originalFileName, - Long fileSize, - Long completion) { - Assert.assertNotNull(state); - Assert.assertNotNull(state.getStaticFileStateJson()); - if (absolutePathOfUploadedFileFilled) { - Assert.assertNotNull(state.getAbsoluteFullPathOfUploadedFile()); - } - else { - Assert.assertNull(state.getAbsoluteFullPathOfUploadedFile()); - } - Assert.assertEquals(fileName, state.getStaticFileStateJson().getOriginalFileName()); - Assert.assertEquals(fileSize, state.getStaticFileStateJson().getOriginalFileSizeInBytes()); - } - - - - public static class TestFileSplitResult { - - ByteArrayInputStream stream; - String crc; - } - - - - public static TestFileSplitResult getByteArrayFromInputStream(InputStream inputStream, long start, long length) - throws IOException { - TestFileSplitResult testFileSplitResult = new TestFileSplitResult(); - - inputStream.skip(start); - - // read file - byte[] b = new byte[Math.min((int) (length - start), inputStream.available())]; - inputStream.read(b, 0, b.length); - inputStream.close(); - testFileSplitResult.stream = new ByteArrayInputStream(b); - - // get crc - CRC32 crc32 = new CRC32(); - crc32.update(b); - testFileSplitResult.crc = Long.toHexString(crc32.getValue()); - - return testFileSplitResult; - } - - - public static TestFileSplitResult getByteArrayFromFile(MultipartFile file2, long start, long length) - throws IOException { - InputStream inputStream = file2.getInputStream(); - return getByteArrayFromInputStream(inputStream, start, length); - } - - - @Test - public void testCancelFileUpload() - throws ServletException, IOException, InterruptedException, ExecutionException, TimeoutException { - - // begin a file upload process - UUID fileId = uploadProcessor.prepareUpload(fileSize, fileName, "lala"); - - // assert that the state has what we want - StaticFileState value = staticStateManager.getEntity().getFileStates().get(fileId); - assertState(value, true, false, fileName, fileSize, 0l); - - // assert that we have it in the pending files - Assert.assertThat(uploadProcessor.getConfig(null).getPendingFiles().keySet().toArray()[0].toString(), is(fileId.toString())); - - // cancel - uploadProcessor.clearFile(fileId); - - // assert that file is reset - Assert.assertThat(staticStateManager.getEntity().getFileStates().containsKey(fileId), is(false)); - - // assert that we dont have it in the pending files anymore - Assert.assertThat(uploadProcessor.getConfig(null).getPendingFiles().containsKey(fileId), is(false)); - } - - - @Test - public void testConfig() - throws IOException { - InitializationConfiguration config = uploadProcessor.getConfig(null); - Assert.assertNotNull(config.getInByte()); - } - - - @Test - public void testIdSpecification() { - UUID randomUUID = UUID.randomUUID(); - uploadProcessor.getConfig(randomUUID); - Assert.assertThat(staticStateIdentifierManager.getIdentifier(), is(randomUUID)); - } - - - @Test - public void testIdReSpecification() { - testIdSpecification(); - UUID randomUUID = UUID.randomUUID(); - uploadProcessor.getConfig(randomUUID); - Assert.assertThat(staticStateIdentifierManager.getIdentifier(), is(randomUUID)); - } - - - @Test - public void testCrcBuffered() - throws IOException { - - // with method - CRCResult withMethod = crcHelper.getBufferedCrc(file.getInputStream()); - - // without buffer - CRC32 crc32 = new CRC32(); - crc32.update(IOUtils.toByteArray(file.getInputStream())); - String hexString = Long.toHexString(crc32.getValue()); - - Assert.assertThat(withMethod.getCrcAsString(), is(hexString)); - Assert.assertThat(withMethod.getTotalRead(), is(content.length)); - - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/logic/UploadServletAsyncProcessorTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/logic/UploadServletAsyncProcessorTest.java deleted file mode 100644 index 0771dc8..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/logic/UploadServletAsyncProcessorTest.java +++ /dev/null @@ -1,608 +0,0 @@ -package com.am.jlfu.fileuploader.logic; - - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.Matchers.lessThan; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Arrays; -import java.util.Random; -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import javax.servlet.ServletException; - -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.am.jlfu.fileuploader.exception.FileCorruptedException; -import com.am.jlfu.fileuploader.exception.InvalidCrcException; -import com.am.jlfu.fileuploader.exception.MissingParameterException; -import com.am.jlfu.fileuploader.json.CRCResult; -import com.am.jlfu.fileuploader.limiter.RateLimiterConfigurationManager; -import com.am.jlfu.fileuploader.logic.UploadProcessorTest.TestFileSplitResult; -import com.am.jlfu.fileuploader.logic.UploadServletAsyncProcessor.WriteChunkCompletionListener; -import com.am.jlfu.fileuploader.utils.CRCHelper; -import com.am.jlfu.fileuploader.utils.ProgressCalculator; -import com.am.jlfu.fileuploader.web.utils.RequestComponentContainer; -import com.am.jlfu.staticstate.StaticStateIdentifierManager; -import com.am.jlfu.staticstate.StaticStateManager; -import com.am.jlfu.staticstate.entities.StaticStatePersistedOnFileSystemEntity; - - - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class UploadServletAsyncProcessorTest { - - private static final Logger log = LoggerFactory.getLogger(UploadServletAsyncProcessorTest.class); - public static final int WAIT_THAT_TIME_FOR_LOCKS_IN_MILLISECONDS = 2000; - - @Autowired - RateLimiterConfigurationManager rateLimiterConfigurationManager; - - @Autowired - CRCHelper crcHelper; - - @Autowired - UploadServletAsyncProcessor uploadServletAsyncProcessor; - - @Autowired - UploadProcessor uploadProcessor; - - @Autowired - RequestComponentContainer requestComponentContainer; - - @Autowired - StaticStateManager staticStateManager; - - @Autowired - ProgressCalculator progressCalculator; - - @Autowired - StaticStateIdentifierManager staticStateIdentifierManager; - - MockMultipartFile tinyFile; - Long tinyFileSize; - byte[] tinyFileContent; - - String fileName = "zenameofzefile.owf"; - - - - @Before - public void init() - throws IOException, InterruptedException, ExecutionException, TimeoutException { - - // populate request component container - requestComponentContainer.populate(new MockHttpServletRequest(), new MockHttpServletResponse()); - - // clear state - staticStateManager.clear(); - - // init file - tinyFileContent = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; - tinyFile = new MockMultipartFile("blob", tinyFileContent); - tinyFileSize = Integer.valueOf(tinyFileContent.length).longValue(); - } - - - - private class Listener - implements WriteChunkCompletionListener { - - private boolean releaseOnSuccess; - private Exception e; - private UUID clientId; - private UUID fileId; - - - - public Listener(UUID clientId, UUID fileId, boolean shallSucceed) { - this.releaseOnSuccess = shallSucceed; - this.clientId = clientId; - this.fileId = fileId; - } - - - @Override - public void error(Exception exception) { - uploadServletAsyncProcessor.clean(clientId, fileId); - e = exception; - if (releaseOnSuccess) { - Assert.fail(); - } - release(); - } - - - @Override - public void success() { - uploadServletAsyncProcessor.clean(clientId, fileId); - if (!releaseOnSuccess) { - Assert.fail(); - } - release(); - } - - - void release() { - synchronized (Listener.this) { - Listener.this.notifyAll(); - } - } - - } - - - - @Test - public void testInvalidCrc() - throws IOException, MissingParameterException, FileUploadException, InvalidCrcException, InterruptedException { - - // begin a file upload process - UUID fileId = uploadProcessor.prepareUpload(tinyFileSize, fileName, "lala"); - - // upload with bad crc - TestFileSplitResult splitResult = UploadProcessorTest.getByteArrayFromFile(tinyFile, 0, 3); - splitResult.crc = "lala"; - - processWaitForCompletionAndCheck(fileId, splitResult, InvalidCrcException.class); - } - - - private void waitForListener(Listener completionListener) - throws InterruptedException { - synchronized (completionListener) { - completionListener.wait(WAIT_THAT_TIME_FOR_LOCKS_IN_MILLISECONDS); - } - } - - - @Test - public void testClassicGranular() - throws ServletException, IOException, InvalidCrcException, MissingParameterException, FileUploadException, - InterruptedException { - TestFileSplitResult splitResult; - - // begin a file upload process - UUID fileId = uploadProcessor.prepareUpload(tinyFileSize, fileName, "lala"); - CRCResult bufferedCrc = crcHelper.getBufferedCrc(new ByteArrayInputStream(tinyFileContent.clone())); - - // get progress - Assert.assertThat(0f, is(uploadProcessor.getProgress(fileId).getProgress())); - - // upload first part - splitResult = UploadProcessorTest.getByteArrayFromFile(tinyFile, 0, 3); - processWaitForCompletionAndCheck(fileId, splitResult); - - // get progress - Assert.assertThat(Math.round(progressCalculator.getProgress(staticStateIdentifierManager.getIdentifier(), fileId).getProgress()), is(3 * 100 / tinyFileSize.intValue())); - - // upload second part - splitResult = UploadProcessorTest.getByteArrayFromFile(tinyFile, 3, 5); - processWaitForCompletionAndCheck(fileId, splitResult); - - // get progress - Assert.assertThat(Math.round(progressCalculator.getProgress(staticStateIdentifierManager.getIdentifier(), fileId).getProgress()), is(Math.round(5f / tinyFileSize.floatValue() * 100f))); - - // upload last part - splitResult = UploadProcessorTest.getByteArrayFromFile(tinyFile, 5, tinyFileSize.intValue()); - processWaitForCompletionAndCheck(fileId, splitResult); - - // get progress - Assert.assertThat(Math.round(progressCalculator.getProgress(staticStateIdentifierManager.getIdentifier(), fileId).getProgress()), is(100)); - - // check crc - CRCResult fileCrc = - crcHelper.getBufferedCrc(new FileInputStream(new File(staticStateManager.getEntity().getFileStates().get(fileId) - .getAbsoluteFullPathOfUploadedFile()))); - Assert.assertThat(fileCrc, is(bufferedCrc)); - } - - - - private class RunnableInTheProcessWithStreamDisconnection extends RunnableInTheProcess { - - /** - * 1 for first
- * 2 for middle
- * 3 for last
- */ - private int sliceToFailAtCode; - private boolean invalidCrc; - - - - public RunnableInTheProcessWithStreamDisconnection(int sliceToFailAtCode, boolean invalidCrc) { - this.sliceToFailAtCode = sliceToFailAtCode; - this.invalidCrc = invalidCrc; - } - - - @Override - protected void run() - throws Exception { - - // prepare that slice - String absoluteFullPathOfUploadedFile = - staticStateManager.getEntity().getFileStates().get(fileId).getAbsoluteFullPathOfUploadedFile(); - File file = new File(absoluteFullPathOfUploadedFile); - long destination = uploadProcessor.getSliceSizeInBytes() * currentSlice + uploadProcessor.getSliceSizeInBytes(); - TestFileSplitResult byteArrayFromFile = - UploadProcessorTest.getByteArrayFromInputStream(new ByteArrayInputStream(fileContent), uploadProcessor.getSliceSizeInBytes() * - currentSlice, destination); - - int sliceToFailAt = -1; - switch (sliceToFailAtCode) { - case 0: - sliceToFailAt = 0; - break; - case 1: - sliceToFailAt = (int) (numberOfSlices / 2); - break; - case 2: - sliceToFailAt = (int) numberOfSlices; - break; - } - - // if this is slice that sould fail - if (currentSlice == sliceToFailAt) { - - // provides a stream that will fail fast - try { - byteArrayFromFile.stream = - new ByteArrayInputStreamThatFails(uploadProcessor.getSliceSizeInBytes(), IOUtils.toByteArray(byteArrayFromFile.stream)); - } - catch (IOException e) { - throw new RuntimeException(e); - } - - // and process - processWaitForCompletionAndCheck(fileId, byteArrayFromFile, Exception.class); - - // assert that the validated crc is of the size of the slices that were successfull - Long crcedBytesBeforeVerification = - staticStateManager.getEntity().getFileStates().get(fileId).getStaticFileStateJson().getCrcedBytes(); - Assert.assertThat(crcedBytesBeforeVerification, is(sliceToFailAt * uploadProcessor.getSliceSizeInBytes())); - - // assert that we have written the correct amount - long size = file.length(); - long sliceMissingSize = - ((ByteArrayInputStreamThatFails) byteArrayFromFile.stream).failAt * UploadServletAsyncProcessor.SIZE_OF_THE_BUFFER_IN_BYTES; - long completedPart = sliceMissingSize + - (currentSlice * uploadProcessor.getSliceSizeInBytes()); - Assert.assertThat(size, is(completedPart)); - - // process the crc of the part that has not been completed - byteArrayFromFile = - UploadProcessorTest.getByteArrayFromInputStream(new FileInputStream(file), crcedBytesBeforeVerification, completedPart); - - // change the crc with a fake one if invalidity check - if (invalidCrc) { - byteArrayFromFile.crc = "invalid"; - } - - Long newCrcedBytes; - // process the crc validation of the previous chunk - try { - uploadProcessor.verifyCrcOfUncheckedPart(fileId, byteArrayFromFile.crc); - // we should have an exception if we are using an invalid crc - if (invalidCrc) { - Assert.fail(); - } - - // assert that the validated amount is now more than the previous one - newCrcedBytes = staticStateManager.getEntity().getFileStates().get(fileId).getStaticFileStateJson().getCrcedBytes(); - Assert.assertThat(crcedBytesBeforeVerification, lessThan(newCrcedBytes)); - - } - catch (InvalidCrcException ee) { - - // we are invalid, the crc size shall be unchanged - newCrcedBytes = staticStateManager.getEntity().getFileStates().get(fileId).getStaticFileStateJson().getCrcedBytes(); - Assert.assertThat(newCrcedBytes, is(crcedBytesBeforeVerification)); - - // re-process the slice from beginning - - } - - // assert that the file is still matching the validated, either truncated or - // appended. - size = file.length(); - Assert.assertThat(newCrcedBytes, is(size)); - - // finish this slice - byteArrayFromFile = - UploadProcessorTest.getByteArrayFromInputStream(new ByteArrayInputStream(fileContent), newCrcedBytes, destination); - - - // process it - processWaitForCompletionAndCheck(fileId, byteArrayFromFile); - - } - // otherwise process normally - else { - - // process it - processWaitForCompletionAndCheck(fileId, byteArrayFromFile); - } - - } - } - - - - @Test - public void testStreamDisconnectionInFirstSlice() - throws Exception { - testFileComplete(new RunnableInTheProcessWithStreamDisconnection(0, false)); - } - - - @Test - public void testStreamDisconnectionInFirstSliceWithInvalidity() - throws Exception { - testFileComplete(new RunnableInTheProcessWithStreamDisconnection(0, true)); - } - - - @Test - public void testStreamDisconnectionInMiddleSlice() - throws Exception { - testFileComplete(new RunnableInTheProcessWithStreamDisconnection(1, false)); - } - - - @Test - public void testStreamDisconnectionInMiddleSliceWithInvalidity() - throws Exception { - testFileComplete(new RunnableInTheProcessWithStreamDisconnection(1, true)); - } - - - @Test - public void testStreamDisconnectionInLastSlice() - throws Exception { - testFileComplete(new RunnableInTheProcessWithStreamDisconnection(2, false)); - } - - - @Test - public void testStreamDisconnectionInLastSliceWithInvalidity() - throws Exception { - testFileComplete(new RunnableInTheProcessWithStreamDisconnection(2, true)); - } - - - @Test - public void testBigFileComplete() - throws Exception { - testFileComplete(new RunnableInTheProcess() { - - @Override - protected void run() - throws Exception { - - // prepare that slice - staticStateManager.getEntity().getFileStates().get(fileId).getAbsoluteFullPathOfUploadedFile(); - TestFileSplitResult byteArrayFromFile = - UploadProcessorTest.getByteArrayFromInputStream(new ByteArrayInputStream(fileContent), uploadProcessor.getSliceSizeInBytes() * - currentSlice, uploadProcessor.getSliceSizeInBytes() * currentSlice + - uploadProcessor.getSliceSizeInBytes()); - - // process it - processWaitForCompletionAndCheck(fileId, byteArrayFromFile); - - - } - }); - } - - - @Test - public void testBigFileWithPauseAndResume() - throws Exception { - testFileComplete(new RunnableInTheProcess() { - - @Override - public void run() - throws InterruptedException, IOException { - - // prepare that slice - String absoluteFullPathOfUploadedFile = - staticStateManager.getEntity().getFileStates().get(fileId).getAbsoluteFullPathOfUploadedFile(); - TestFileSplitResult byteArrayFromFile = - UploadProcessorTest.getByteArrayFromInputStream(new ByteArrayInputStream(fileContent), uploadProcessor.getSliceSizeInBytes() * - currentSlice, uploadProcessor.getSliceSizeInBytes() * currentSlice + - uploadProcessor.getSliceSizeInBytes()); - - - // at one point, pause it: - if (currentSlice == numberOfSlices / 2) { - - // pause - uploadProcessor.pauseFile(Arrays.asList(new UUID[] {fileId})); - - // get the file size - long length = new File(absoluteFullPathOfUploadedFile).length(); - - // wait a bit - try { - Thread.sleep(100); - } - catch (InterruptedException e) { - throw new RuntimeException(e); - } - - //process it, it should not be processed as the file is paused - processWaitForCompletionAndCheck(fileId, byteArrayFromFile); - - // assert the size is the same - Assert.assertThat(new File(absoluteFullPathOfUploadedFile).length(), is(length)); - - // then continue processing - uploadProcessor.resumeFile(fileId); - - } - - //process - processWaitForCompletionAndCheck(fileId, byteArrayFromFile); - - } - }); - } - - - - private abstract class RunnableInTheProcess - { - - protected int currentSlice; - protected long numberOfSlices; - protected UUID fileId; - protected byte[] fileContent; - - - - protected abstract void run() - throws Exception; - - - public void start(Semaphore referenceToWakeUp, int currentSlice, long numberOfSlices, UUID fileId, byte[] fileContent) - throws Exception { - this.currentSlice = currentSlice; - this.numberOfSlices = numberOfSlices; - this.fileId = fileId; - this.fileContent = fileContent; - try { - run(); - } - finally { - referenceToWakeUp.release(); - } - } - } - - - - public void testFileComplete(RunnableInTheProcess doSomethingInTheMiddle) - throws Exception { - Semaphore waitForMe = new Semaphore(0); - - // init a file which is about 115 MB (we want to check out-of-buffer - // granularity, so not an - // exact value) - long size = 121123456; - byte[] fileContent = new byte[(int) size]; - new Random().nextBytes(fileContent); - - // prepare upload - UUID fileId = uploadProcessor.prepareUpload(size, fileName, "lala"); - String absoluteFullPathOfUploadedFile = staticStateManager.getEntity().getFileStates().get(fileId).getAbsoluteFullPathOfUploadedFile(); - - // set a 100mb rate - rateLimiterConfigurationManager.setMaximumRatePerClientInKiloBytes(100 * 1024); - rateLimiterConfigurationManager.setMaximumOverAllRateInKiloBytes(100 * 1024); - - // for all the slices that we need to send - long numberOfSlices = size / uploadProcessor.getSliceSizeInBytes(); - for (int currentSlice = 0; currentSlice < numberOfSlices + 1; currentSlice++) { - - // perform treatment - if (doSomethingInTheMiddle != null) { - doSomethingInTheMiddle.start(waitForMe, currentSlice, numberOfSlices, fileId, fileContent); - Assert.assertTrue(waitForMe.tryAcquire(WAIT_THAT_TIME_FOR_LOCKS_IN_MILLISECONDS, TimeUnit.MINUTES)); - } - - } - - // now calculates the crc of sent file - String valueSource = crcHelper.getBufferedCrc(new ByteArrayInputStream(fileContent)).getCrcAsString(); - - // and the one of received file - String valueCopied = crcHelper.getBufferedCrc(new FileInputStream(new File(absoluteFullPathOfUploadedFile))).getCrcAsString(); - - // assert the same - Assert.assertThat(valueCopied, is(valueSource)); - - } - - - private void processWaitForCompletionAndCheck(UUID fileId, TestFileSplitResult byteArrayFromFile) - throws FileNotFoundException, InterruptedException { - processWaitForCompletionAndCheck(fileId, byteArrayFromFile, null); - } - - - private void processWaitForCompletionAndCheck(UUID fileId, TestFileSplitResult byteArrayFromFile, Class expectedException) - throws FileNotFoundException, InterruptedException { - Listener completionListener = new Listener(staticStateIdentifierManager.getIdentifier(), fileId, expectedException == null); - uploadServletAsyncProcessor.process(staticStateManager.getEntity().getFileStates().get(fileId), fileId, byteArrayFromFile.crc, - byteArrayFromFile.stream, completionListener); - waitForListener(completionListener); - if (expectedException == null) { - Assert.assertThat(completionListener.e, nullValue()); - } - else { - Assert.assertTrue(expectedException.isInstance(completionListener.e)); - } - } - - - - private class ByteArrayInputStreamThatFails extends ByteArrayInputStream { - - // fail in the middle of a slice - long failAt; - int i; - - - - public ByteArrayInputStreamThatFails(long sliceSizeInBytes, byte[] buf) { - super(buf); - failAt = sliceSizeInBytes / UploadServletAsyncProcessor.SIZE_OF_THE_BUFFER_IN_BYTES / 2; - } - - - @Override - public int read(byte[] b) - throws IOException { - if (i++ == failAt) { - throw new IOException("Stream ended unexpectedly"); - } - return super.read(b); - } - } - - - @Test(expected = FileCorruptedException.class) - public void testFileCorruptedException() throws IOException, InterruptedException, InvalidCrcException, FileCorruptedException { - - // begin a file upload process - UUID fileId = uploadProcessor.prepareUpload(tinyFileSize, fileName, "lala"); - staticStateManager.setCrcBytesValidated(staticStateIdentifierManager.getIdentifier(), fileId, 10); - - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/util/RootFolderProvider.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/util/RootFolderProvider.java deleted file mode 100644 index 00dbe9f..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/util/RootFolderProvider.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.am.jlfu.fileuploader.util; - - -import java.io.File; -import java.io.IOException; - -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Component; - -import com.am.jlfu.staticstate.StaticStateRootFolderProvider; - - - -@Component -@Primary -public class RootFolderProvider - extends StaticStateRootFolderProvider { - - private File file; - - - - @Override - public File getRootFolder() { - if (file == null) { - try { - file = File.createTempFile("lala", "test"); - file.delete(); - file.mkdir(); - } - catch (IOException e) { - e.printStackTrace(); - } - } - return file; - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/util/StaticStateIdentifierManagerForTestProvider.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/util/StaticStateIdentifierManagerForTestProvider.java deleted file mode 100644 index 2c3797a..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/util/StaticStateIdentifierManagerForTestProvider.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.am.jlfu.fileuploader.util; - - -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Component; - -import com.am.jlfu.staticstate.StaticStateIdentifierManager; - - - -@Component -@Primary -public class StaticStateIdentifierManagerForTestProvider extends StaticStateIdentifierManager { - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/ImportedFilesCleanerTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/ImportedFilesCleanerTest.java deleted file mode 100644 index ceba81c..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/ImportedFilesCleanerTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - - -import java.io.File; -import java.io.IOException; - -import org.joda.time.DateTime; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.am.jlfu.staticstate.FileDeleter; -import com.am.jlfu.staticstate.StaticStateRootFolderProvider; - - - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class ImportedFilesCleanerTest { - - @Autowired - StaticStateRootFolderProvider staticStateRootFolderProvider; - - @Autowired - ImportedFilesCleaner importedFilesCleaner; - - @Autowired - FileDeleter fileDeleter; - - - - @Test - public void test() - throws IOException { - // put some files - File rootFolder = staticStateRootFolderProvider.getRootFolder(); - - // old one - File oldDir = new File(rootFolder, "oldDir"); - oldDir.mkdir(); - oldDir.setLastModified(new DateTime().minusMonths(3).getMillis()); - - // recent one - File recentDir = new File(rootFolder, "recentDir"); - recentDir.mkdir(); - - // process - importedFilesCleaner.clean(); - - // call file deleter - fileDeleter.run(); - - // assume old is deleted - Assert.assertFalse(oldDir.exists()); - - // assume new os still there - Assert.assertTrue(recentDir.exists()); - - - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/LimitingListTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/LimitingListTest.java deleted file mode 100644 index b6887f7..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/LimitingListTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - -import org.hamcrest.CoreMatchers; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class LimitingListTest { - - - @Test - public void test() { - Integer a = 1; - Integer b = 2; - Integer c = 3; - Integer d = 4; - LimitingList limitingList = new LimitingList(2); - limitingList.unshift(a); - limitingList.unshift(b); - Assert.assertThat(limitingList.list.get(0), CoreMatchers.is(b)); - Assert.assertThat(limitingList.list.get(1), CoreMatchers.is(a)); - limitingList.unshift(c); - Assert.assertThat(limitingList.list.get(0), CoreMatchers.is(c)); - Assert.assertThat(limitingList.list.get(1), CoreMatchers.is(b)); - Assert.assertThat(limitingList.list.size(), CoreMatchers.is(2)); - limitingList.unshift(d); - Assert.assertThat(limitingList.list.get(0), CoreMatchers.is(d)); - Assert.assertThat(limitingList.list.get(1), CoreMatchers.is(c)); - Assert.assertThat(limitingList.list.size(), CoreMatchers.is(2)); - - - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/ProgressCalculatorTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/ProgressCalculatorTest.java deleted file mode 100644 index 5e3cd93..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/ProgressCalculatorTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class ProgressCalculatorTest { - - @Autowired - ProgressCalculator progressCalculator; - - @Test - public void progressCalculationTest() { - // check basic 30% (30/100) - Assert.assertThat(Double.valueOf(30), is(progressCalculator.calculateProgress(30l, 100l))); - Long bigValue = 1000000000000000000l; - // check that we dont return 100% if values are not exactly equals - Assert.assertThat(Double.valueOf(100), is(not(progressCalculator.calculateProgress(bigValue - 1, bigValue)))); - // check that we return 100% if values are equals - Assert.assertThat(Double.valueOf(100), is(progressCalculator.calculateProgress(bigValue, bigValue))); - // check that we return 0% when 0/x - Assert.assertThat(Double.valueOf(0), is(progressCalculator.calculateProgress(0l, 240l))); - } -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/ProgressManagerTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/ProgressManagerTest.java deleted file mode 100644 index 0813dfa..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/ProgressManagerTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - -import java.io.FileNotFoundException; -import java.util.Set; -import java.util.UUID; - -import org.hamcrest.CoreMatchers; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.util.ReflectionTestUtils; -import org.unitils.mock.Mock; -import org.unitils.mock.core.MockObject; - -import com.am.jlfu.fileuploader.utils.ProgressManager.ProgressManagerAdvertiser; -import com.am.jlfu.notifier.JLFUListenerPropagator; -import com.am.jlfu.staticstate.entities.FileProgressStatus; -import com.google.common.collect.Sets; - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class ProgressManagerTest { - - @Autowired - ClientToFilesMap clientToFilesMap; - - @Autowired - ProgressManager progressManager; - - @Autowired - JLFUListenerPropagator jlfuListenerPropagator; - - Mock progressCalculator = new MockObject(ProgressCalculator.class, new Object()); - Mock progressManagerAdvertiser = new MockObject(ProgressManagerAdvertiser.class, new Object()); - - private UUID clientId = UUID.randomUUID(); - private UUID fileId = UUID.randomUUID(); - - @Before - public void init() { - - //init client to files map - clientToFilesMap.clear(); - Set newHashSet = Sets.newHashSet(); - clientToFilesMap.put(clientId, newHashSet); - newHashSet.add(fileId); - - //reset progress manager map - progressManager.fileToProgressInfo.clear(); - - //set mock - ReflectionTestUtils.setField(progressManager, "progressCalculator", progressCalculator.getMock()); - ReflectionTestUtils.setField(progressManager, "progressManagerAdvertiser", progressManagerAdvertiser.getMock()); - - } - - @Test - public void testWithProgress() throws FileNotFoundException { - assertReturnedIsCorrect(15f, true); - assertReturnedIsCorrect(30f, true); - assertReturnedIsCorrect(30f, false); - } - - private void assertReturnedIsCorrect(float returnedValue, boolean shallBePropagated) - throws FileNotFoundException { - - //mock service - FileProgressStatus fileProgressStatus = new FileProgressStatus(); - fileProgressStatus.setProgress(returnedValue); - progressCalculator.onceReturns(fileProgressStatus).getProgress(clientId, fileId); - - //calculate progress - progressManager.calculateProgress(); - - //assert map is filled - Assert.assertThat(progressManager.fileToProgressInfo.get(fileId).getProgress(), CoreMatchers.is(returnedValue)); - - //assert that event is propagated - if (shallBePropagated) { - progressManagerAdvertiser.assertInvoked().advertise(clientId, fileId, fileProgressStatus); - } else { - progressManagerAdvertiser.assertNotInvoked().advertise(clientId, fileId, fileProgressStatus); - } - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/RemainingTimeEstimatorTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/RemainingTimeEstimatorTest.java deleted file mode 100644 index f51cd39..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/utils/RemainingTimeEstimatorTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.am.jlfu.fileuploader.utils; - -import java.util.UUID; - -import org.hamcrest.CoreMatchers; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.am.jlfu.staticstate.entities.FileProgressStatus; - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class RemainingTimeEstimatorTest { - - @Autowired - RemainingTimeEstimator remainingTimeEstimator; - - @Test - public void testGetRemainingTime() { - UUID clientId = UUID.randomUUID(); - - FileProgressStatus progress = new FileProgressStatus(); - progress.setTotalFileSize(1000); - progress.setBytesUploaded(0); - Assert.assertThat(remainingTimeEstimator.getRemainingTime(clientId, progress, 100l), CoreMatchers.is(10l)); - Assert.assertThat(remainingTimeEstimator.getRemainingTime(clientId, progress, 300l), CoreMatchers.is(5l)); - Assert.assertThat(remainingTimeEstimator.getRemainingTime(clientId, progress, 200l), CoreMatchers.is(5l)); - Assert.assertThat(remainingTimeEstimator.getRemainingTime(clientId, progress, 200l), CoreMatchers.is(5l)); - Assert.assertThat(remainingTimeEstimator.getRemainingTime(clientId, progress, 200l), CoreMatchers.is(5l)); - Assert.assertThat(remainingTimeEstimator.getRemainingTime(clientId, progress, 200l), CoreMatchers.is(5l)); - Assert.assertThat(remainingTimeEstimator.getRemainingTime(clientId, progress, 200l), CoreMatchers.is(5l)); - Assert.assertThat(remainingTimeEstimator.getRemainingTime(clientId, progress, 200l), CoreMatchers.is(5l)); - Assert.assertThat(remainingTimeEstimator.getRemainingTime(clientId, progress, 200l), CoreMatchers.is(5l)); - Assert.assertThat(remainingTimeEstimator.getRemainingTime(clientId, progress, 200l), CoreMatchers.is(5l)); - Assert.assertThat(remainingTimeEstimator.getRemainingTime(clientId, progress, 200l), CoreMatchers.not(5l)); - } - - - - @Test - public void testCalculateRemainingTime() { - processRemainingTimeTest(1000l, 0l, 100l, 10l); - processRemainingTimeTest(1000l, 500l, 100l, 5l); - processRemainingTimeTest(1000l, 1000l, 100l, 1l); - } - - - private void processRemainingTimeTest(long fileSize, long start, long rate, long expectedSeconds) { - FileProgressStatus progress = new FileProgressStatus(); - progress.setTotalFileSize(fileSize); - progress.setBytesUploaded(start); - long calculateRemainingTime = remainingTimeEstimator.calculateRemainingTime(progress, rate); - Assert.assertThat(calculateRemainingTime, CoreMatchers.is(expectedSeconds)); - } - - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/web/UploadServletTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/web/UploadServletTest.java deleted file mode 100644 index 9c2db1a..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/fileuploader/web/UploadServletTest.java +++ /dev/null @@ -1,243 +0,0 @@ -package com.am.jlfu.fileuploader.web; - - -import static org.hamcrest.CoreMatchers.is; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import javax.servlet.ServletException; - -import org.hamcrest.CoreMatchers; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.am.jlfu.fileuploader.json.FileStateJson; -import com.am.jlfu.fileuploader.json.InitializationConfiguration; -import com.am.jlfu.fileuploader.json.PrepareUploadJson; -import com.am.jlfu.fileuploader.json.ProgressJson; -import com.am.jlfu.fileuploader.json.SimpleJsonObject; -import com.am.jlfu.fileuploader.web.utils.ExceptionCodeMappingHelper.ExceptionCodeMapping; -import com.am.jlfu.fileuploader.web.utils.RequestComponentContainer; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - - - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class UploadServletTest { - - @Autowired - UploadServlet uploadServlet; - - @Autowired - UploadServletAsync uploadServletAsync; - - @Autowired - RequestComponentContainer requestComponentContainer; - - MockHttpServletRequest request; - MockHttpServletResponse response; - - private byte[] content = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; - private MockMultipartFile file = new MockMultipartFile("blob", content); - - - - @Before - public void init() { - - request = new MockHttpServletRequest(); - response = new MockHttpServletResponse(); - - // populate request component container - requestComponentContainer.populate(request, response); - - } - - - @Test - public void getConfig() - throws IOException { - - // init an upload to emulate a pending file - String fileId = prepareUpload(); - - // set action parameter - request.clearAttributes(); - response = new MockHttpServletResponse(); - request.setParameter(UploadServletParameter.action.name(), UploadServletAction.getConfig.name()); - - // handle request - uploadServlet.handleRequest(request, response); - - // extract config from response - InitializationConfiguration fromJson = new Gson().fromJson(response.getContentAsString(), InitializationConfiguration.class); - Assert.assertNotNull(fromJson.getInByte()); - Assert.assertThat(response.getStatus(), is(200)); - Map pendingFiles = fromJson.getPendingFiles(); - Assert.assertThat(pendingFiles.size(), is(1)); - Assert.assertThat(pendingFiles.keySet().iterator().next(), is(fileId)); - } - - - @Test - public void getProgressWithBadId() - throws IOException { - - // set action parameter - request.setParameter(UploadServletParameter.action.name(), UploadServletAction.getProgress.name()); - String id = "a bad id"; - request.setParameter(UploadServletParameter.fileId.name(), new Gson().toJson(new String[] { id })); - - // handle request - uploadServlet.handleRequest(request, response); - - SimpleJsonObject fromJson = new Gson().fromJson(response.getContentAsString(), SimpleJsonObject.class); - Assert.assertThat(fromJson.getValue(), is("0")); - - } - - - @Test - public void getProgress() - throws IOException { - - // init an upload to emulate a pending file - String fileId = prepareUpload(); - - // set action parameter - request.clearAttributes(); - response = new MockHttpServletResponse(); - request.setParameter(UploadServletParameter.action.name(), UploadServletAction.getProgress.name()); - request.setParameter(UploadServletParameter.fileId.name(), new Gson().toJson(new String[] { fileId })); - - // handle request - uploadServlet.handleRequest(request, response); - Assert.assertThat(response.getStatus(), is(200)); - - HashMap fromJson = new Gson().fromJson(response.getContentAsString(), new TypeToken>() { - }.getType()); - ProgressJson[] array = new ProgressJson[] {}; - array = fromJson.values().toArray(array); - Assert.assertThat(array[0].getProgress(), is(Float.valueOf(0))); - - } - - - @Test - public void uploadNotMultipartParams() - throws IOException, ServletException { - - // handle request - uploadServletAsync.handleRequest(request, response); - SimpleJsonObject fromJson = new Gson().fromJson(response.getContentAsString(), SimpleJsonObject.class); - Assert.assertThat(ExceptionCodeMapping.requestIsNotMultipart.getExceptionIdentifier(), is(Integer.valueOf(fromJson.getValue()))); - - } - - - @Test - public void prepareUploadTest() - throws IOException { - prepareUpload(); - } - - - public String prepareUpload() - throws IOException { - - return (String) prepareUpload(1).values().toArray()[0]; - - } - - - public Map prepareUpload(int size) - throws IOException { - - // set action parameter - request.setParameter(UploadServletParameter.action.name(), UploadServletAction.prepareUpload.name()); - PrepareUploadJson[] prepareUploadJsons = new PrepareUploadJson[size]; - for (int i = 0; i < size; i++) { - PrepareUploadJson j = new PrepareUploadJson(); - j.setTempId(i); - j.setFileName("file " + i); - j.setSize(123456l); - prepareUploadJsons[i] = j; - } - request.setParameter(UploadServletParameter.newFiles.name(), new Gson().toJson(prepareUploadJsons)); - - // handle request - uploadServlet.handleRequest(request, response); - Assert.assertThat(response.getStatus(), is(200)); - HashMap fromJson = new Gson().fromJson(response.getContentAsString(), new TypeToken>() { - }.getType()); - - return fromJson; - } - - - @Test - public void prepareUploadMulti() - throws IOException { - Map prepareUpload = prepareUpload(10); - Assert.assertThat(prepareUpload.size(), is(10)); - } - - - // upload, - // prepareUpload, - // clearFile, - // clearAll; - - - @Test - public void clearFileWithMissingParameter() - throws IOException { - - // set action parameter - request.setParameter(UploadServletParameter.action.name(), UploadServletAction.clearFile.name()); - - // handle request - uploadServlet.handleRequest(request, response); - - // assert that we have an error - SimpleJsonObject fromJson = new Gson().fromJson(response.getContentAsString(), SimpleJsonObject.class); - - Assert.assertThat(ExceptionCodeMapping.MissingParameterException.getExceptionIdentifier(), is(Integer.valueOf(fromJson.getValue()))); - - } - - - @Test - public void testGetMultiFileIdsFromString() { - UUID uuid1 = UUID.randomUUID(); - UUID uuid2 = UUID.randomUUID(); - List fileIdsFromString = uploadServlet.getFileIdsFromString(uuid1+","+uuid2); - Assert.assertThat(fileIdsFromString.size(), CoreMatchers.is(2)); - Assert.assertTrue(fileIdsFromString.contains(uuid1)); - Assert.assertTrue(fileIdsFromString.contains(uuid2)); - } - - @Test - public void testGetOneFileIdFromString() { - UUID uuid1 = UUID.randomUUID(); - List fileIdsFromString = uploadServlet.getFileIdsFromString(uuid1.toString()); - Assert.assertThat(fileIdsFromString.size(), CoreMatchers.is(1)); - Assert.assertTrue(fileIdsFromString.contains(uuid1)); - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/notifier/JLFUListenerPropagatorTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/notifier/JLFUListenerPropagatorTest.java deleted file mode 100644 index 28af762..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/notifier/JLFUListenerPropagatorTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.am.jlfu.notifier; - - -import java.util.UUID; - -import org.hamcrest.CoreMatchers; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.am.jlfu.staticstate.entities.FileProgressStatus; - - - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class JLFUListenerPropagatorTest { - - @Autowired - JLFUListenerPropagator jlfuListenerPropagator; - - private volatile int testCounter; - - private JLFUListenerAdapter listener; - - - - @Before - public void before() { - jlfuListenerPropagator.unregisterAllListeners(); - - testCounter = 0; - listener = new JLFUListenerAdapter() { - - @Override - public void onNewClient(UUID clientId) { - testCounter++; - } - }; - - } - - - @Test - public void test() throws InterruptedException { - - // add two listener - jlfuListenerPropagator.registerListener(listener); - jlfuListenerPropagator.registerListener(listener); - - // trigger event - jlfuListenerPropagator.getPropagator().onNewClient(UUID.randomUUID()); - Thread.sleep(100); - - // assert - Assert.assertThat(testCounter, CoreMatchers.is(2)); - - // unregister one listener - jlfuListenerPropagator.unregisterListener(listener); - - // trigger event - jlfuListenerPropagator.getPropagator().onNewClient(UUID.randomUUID()); - Thread.sleep(100); - - // assert - Assert.assertThat(testCounter, CoreMatchers.is(3)); - - } - - @Test - public void testNotBlocked() { - jlfuListenerPropagator.registerListener(new JLFUListenerAdapter() { - @Override - public void onClientBack(UUID clientId) { - try { - Thread.sleep(10000); - } - catch (InterruptedException e) { - e.printStackTrace(); - } - Assert.fail(); - } - }); - jlfuListenerPropagator.getPropagator().onClientBack(UUID.randomUUID()); - } - - @Test - public void log() { - jlfuListenerPropagator.registerListener(new JLFUListenerAdapter()); - FileProgressStatus progress = new FileProgressStatus(); - progress.setBytesUploaded(123); - progress.setProgress(1234f); - progress.setTotalFileSize(12340124); - jlfuListenerPropagator.getPropagator().onFileUploadProgress(UUID.randomUUID(),UUID.randomUUID(), progress); - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/staticstate/FileDeleterTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/staticstate/FileDeleterTest.java deleted file mode 100644 index 6bb415d..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/staticstate/FileDeleterTest.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.am.jlfu.staticstate; - - -import static org.hamcrest.CoreMatchers.is; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.google.common.collect.Lists; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.MoreExecutors; - - - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class FileDeleterTest { - - @Autowired - FileDeleter fileDeleter; - - @Autowired - StaticStateRootFolderProvider staticStateRootFolderProvider; - - private int number = 100; - private ExecutorService exec = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(20)); - private File[] files = new File[number]; - - - - @Before - public void writeFiles() - throws IOException { - for (int i = 0; i < number; i++) { - if (i % 2 == 0) { - File file = new File(staticStateRootFolderProvider.getRootFolder(), i + "testdir"); - file.mkdirs(); - files[i] = file; - } - else { - files[i] = File.createTempFile("temp", "temp"); - } - } - } - - - @Test - public void deleteMultipleFilesSubmittedConcurrently() - throws Exception { - List> futures = Lists.newArrayList(); - fileDeleter.run(); - for (int i = 0; i < number; i++) { - final File toDelete = files[i]; - futures.add((ListenableFuture) exec.submit(new Runnable() { - - @Override - public void run() { - fileDeleter.deleteFile(toDelete); - } - })); - } - fileDeleter.run(); - ListenableFuture> allAsList = Futures.allAsList(futures); - fileDeleter.run(); - Futures.get(allAsList, 2, TimeUnit.SECONDS, Exception.class); - fileDeleter.run(); - for (File file : files) { - Assert.assertThat(file.exists(), is(Boolean.FALSE)); - } - } - - - @Test - public void deleteFileThatIsOpen() - throws IOException, InterruptedException { - File file = File.createTempFile("temp", "temp"); - FileInputStream fileInputStream = new FileInputStream(file); - fileInputStream.read(); - fileDeleter.deleteFile(file); - fileDeleter.run(); - Assert.assertThat(file.exists(), is(Boolean.TRUE)); - fileInputStream.close(); - fileDeleter.run(); - Assert.assertThat(file.exists(), is(Boolean.FALSE)); - } - - - @Test - public void deleteFileThatIsOpenInADirectory() - throws IOException, InterruptedException { - File dir = new File(staticStateRootFolderProvider.getRootFolder(), "zetestdir"); - dir.mkdirs(); - File file = new File(dir, "file"); - file.createNewFile(); - Assert.assertThat(file.exists(), is(Boolean.TRUE)); - Assert.assertThat(dir.exists(), is(Boolean.TRUE)); - FileInputStream fileInputStream = new FileInputStream(file); - fileInputStream.read(); - fileDeleter.deleteFile(dir); - fileDeleter.run(); - Assert.assertThat(file.exists(), is(Boolean.TRUE)); - Assert.assertThat(dir.exists(), is(Boolean.TRUE)); - fileInputStream.close(); - fileDeleter.run(); - Assert.assertThat(file.exists(), is(Boolean.FALSE)); - Assert.assertThat(dir.exists(), is(Boolean.FALSE)); - } - - - @Test - public void deleteFileThatIsNotAFile() - throws IOException { - File fake = new File("lalala"); - File file = File.createTempFile("temp", "temp"); - Assert.assertThat(fake.exists(), is(Boolean.FALSE)); - Assert.assertThat(file.exists(), is(Boolean.TRUE)); - fileDeleter.deleteFile(fake); - fileDeleter.deleteFile(file); - fileDeleter.run(); - Assert.assertThat(fake.exists(), is(Boolean.FALSE)); - Assert.assertThat(file.exists(), is(Boolean.FALSE)); - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/staticstate/StaticStateIdentifierManagerTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/staticstate/StaticStateIdentifierManagerTest.java deleted file mode 100644 index a48a4f6..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/staticstate/StaticStateIdentifierManagerTest.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.am.jlfu.staticstate; - - -import java.util.UUID; - -import javax.servlet.http.Cookie; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.am.jlfu.fileuploader.web.utils.RequestComponentContainer; -import com.am.jlfu.identifier.impl.DefaultIdentifierProvider; - - - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class StaticStateIdentifierManagerTest { - - @Autowired - StaticStateIdentifierManager staticStateIdentifierManager; - - @Autowired - RequestComponentContainer requestComponentContainer; - - MockHttpServletRequest mockHttpServletRequest = new MockHttpServletRequest(); - MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse(); - - - - @Before - public void init() { - - // populate request component container - requestComponentContainer.populate(mockHttpServletRequest, mockHttpServletResponse); - - // clean cookie - mockHttpServletRequest.clearAttributes(); - mockHttpServletRequest.setCookies(new Cookie[] {}); - mockHttpServletResponse.reset(); - } - - - @Test - public void testNoIdInCookieOrSession() { - - // assert session is empty - Assert.assertNull(mockHttpServletRequest.getSession().getAttribute(DefaultIdentifierProvider.cookieIdentifier)); - - // assert cookie is empty - Assert.assertNull(DefaultIdentifierProvider.getCookie(mockHttpServletRequest.getCookies(), DefaultIdentifierProvider.cookieIdentifier)); - - // get id - UUID identifier = staticStateIdentifierManager.getIdentifier(); - - // copy cookies from response to request - mockHttpServletRequest.setCookies(mockHttpServletResponse.getCookies()); - - Assert.assertNotNull(identifier); - - // assert cookie filled - Assert.assertEquals(identifier, - UUID.fromString(DefaultIdentifierProvider.getCookie(mockHttpServletRequest.getCookies(), DefaultIdentifierProvider.cookieIdentifier) - .getValue())); - - // assert session filled - Assert.assertEquals(identifier, mockHttpServletRequest.getSession().getAttribute(DefaultIdentifierProvider.cookieIdentifier)); - - // then clear identifier - staticStateIdentifierManager.clearIdentifier(); - - // copy cookies from response to request - mockHttpServletRequest.setCookies(mockHttpServletResponse.getCookies()); - - // assert session is empty - Assert.assertNull(mockHttpServletRequest.getSession().getAttribute(DefaultIdentifierProvider.cookieIdentifier)); - - // assert cookie is either empty or maxage below 0 - Assert.assertNull(DefaultIdentifierProvider.getCookie(mockHttpServletRequest.getCookies(), DefaultIdentifierProvider.cookieIdentifier)); - } - - - @Test - public void testNoIdInSession() { - - // assert session is empty - Assert.assertNull(mockHttpServletRequest.getSession().getAttribute(DefaultIdentifierProvider.cookieIdentifier)); - - // assert cookie is empty - Assert.assertNull(DefaultIdentifierProvider.getCookie(mockHttpServletRequest.getCookies(), DefaultIdentifierProvider.cookieIdentifier)); - - // set cookie - UUID identifierOriginal = staticStateIdentifierManager.getIdentifier(); - DefaultIdentifierProvider.setCookie(mockHttpServletResponse, identifierOriginal); - - // copy cookies from response to request - mockHttpServletRequest.setCookies(mockHttpServletResponse.getCookies()); - - // assert cookie filled - Assert.assertEquals(identifierOriginal, - UUID.fromString(DefaultIdentifierProvider.getCookie(mockHttpServletRequest.getCookies(), DefaultIdentifierProvider.cookieIdentifier) - .getValue())); - - // get id - UUID identifier = staticStateIdentifierManager.getIdentifier(); - Assert.assertEquals(identifierOriginal, identifier); - - // assert session is filled with id - Assert.assertEquals(identifier, mockHttpServletRequest.getSession().getAttribute(DefaultIdentifierProvider.cookieIdentifier)); - - } - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/staticstate/StaticStateManagerTest.java b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/staticstate/StaticStateManagerTest.java deleted file mode 100644 index 7085ca8..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/java/com/am/jlfu/staticstate/StaticStateManagerTest.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.am.jlfu.staticstate; - - -import java.io.File; -import java.io.IOException; -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; - -import junit.framework.Assert; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.am.jlfu.fileuploader.json.FileStateJsonBase; -import com.am.jlfu.fileuploader.web.utils.RequestComponentContainer; -import com.am.jlfu.staticstate.entities.StaticFileState; -import com.am.jlfu.staticstate.entities.StaticStatePersistedOnFileSystemEntity; - - - -@ContextConfiguration(locations = { "classpath:jlfu.test.xml" }) -@RunWith(SpringJUnit4ClassRunner.class) -public class StaticStateManagerTest { - - @Autowired - FileDeleter fileDeleter; - - @Autowired - StaticStateManager staticStateManager; - - @Autowired - StaticStateDirectoryManager staticStatedDirectoryManager; - - @Autowired - StaticStateIdentifierManager staticStateIdentifierManager; - - @Autowired - RequestComponentContainer requestComponentContainer; - - - - @Before - public void init() { - - // populate request component container - requestComponentContainer.populate(new MockHttpServletRequest(), new MockHttpServletResponse()); - - staticStateManager.init(StaticStatePersistedOnFileSystemEntity.class); - } - - - @Test - public void testClear() - throws InterruptedException, ExecutionException, TimeoutException { - - // get entity - staticStateManager.getEntity(); - - // assert directory is there - File uuidFileParent = staticStatedDirectoryManager.getUUIDFileParent(); - Assert.assertTrue(uuidFileParent.exists()); - - // clear - staticStateManager.clear(); - - // force file deleter to delete stuff - fileDeleter.run(); - - // assert directory is deleted - Assert.assertFalse(uuidFileParent.exists()); - } - - - @Test - public void testClearFile() - throws IOException, InterruptedException, ExecutionException, TimeoutException { - String randomValue = "a"; - UUID fileId = UUID.randomUUID(); - - // get entity - StaticStatePersistedOnFileSystemEntity entity = staticStateManager.getEntity(); - StaticFileState value = new StaticFileState(); - FileStateJsonBase staticFileStateJson = new FileStateJsonBase(); - value.setStaticFileStateJson(staticFileStateJson); - entity.getFileStates().put(fileId, value); - - // populate it - value.setAbsoluteFullPathOfUploadedFile(randomValue); - staticFileStateJson.setOriginalFileName(randomValue); - staticFileStateJson.setOriginalFileSizeInBytes(123000l); - - // create a file - File file = new File(staticStatedDirectoryManager.getUUIDFileParent(), fileId.toString()); - file.createNewFile(); - Assert.assertTrue(file.exists()); - - // clear it - staticStateManager.clearFile(fileId); - - // reget it - StaticFileState staticFileState = staticStateManager.getEntity().getFileStates().get(fileId); - Assert.assertNull(staticFileState); - - // force file deleter to run - fileDeleter.run(); - - // assert file deleted - Assert.assertFalse(file.exists()); - } - - - @Test - public void testGetEntityFromFile() { - String absoluteFullPathOfUploadedFile = "value"; - UUID fileId = UUID.randomUUID(); - - // get entity - StaticStatePersistedOnFileSystemEntity entity = staticStateManager.getEntity(); - StaticFileState value = new StaticFileState(); - entity.getFileStates().put(fileId, value); - - // put some stuff in the file - value.setAbsoluteFullPathOfUploadedFile(absoluteFullPathOfUploadedFile); - staticStateManager.updateEntity(entity); - - // remove from cache - staticStateManager.cache.invalidate(staticStateIdentifierManager.getIdentifier()); - - // get again (it will load from file into cache) - staticStateManager.getEntity(); - - // check everything is good - Assert.assertEquals(absoluteFullPathOfUploadedFile, value.getAbsoluteFullPathOfUploadedFile()); - - - } - - -} diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/resources/jlfu.test.properties b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/resources/jlfu.test.properties deleted file mode 100644 index 3f99fd0..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/resources/jlfu.test.properties +++ /dev/null @@ -1,2 +0,0 @@ -jlfu.filecleaner.cron=0/30 * * * * ? -jlfu.filecleaner.maximumInactivityInHoursBeforeDelete=48 diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/resources/jlfu.test.xml b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/resources/jlfu.test.xml deleted file mode 100644 index bd82ac3..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/resources/jlfu.test.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - classpath:jlfu.test.properties - - - - - \ No newline at end of file diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/resources/jmeter.xml b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/resources/jmeter.xml deleted file mode 100644 index 2d23048..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/resources/jmeter.xml +++ /dev/null @@ -1,810 +0,0 @@ - - - - - - false - false - - - - - - - - continue - - false - -1 - - 100 - 1 - 1337347420000 - 1337347420000 - false - - - - - - - - - false - prepareUpload - = - true - action - - - false - [{ "fileName":"bonjour", "size":123456789, "tempId":1 }] - = - true - newFiles - - - - localhost - 8888 - - - - - /demo/javaLargeFileUploaderServlet - POST - true - false - true - false - HttpClient3.1 - false - - - - - false - fileId - {"1":"(.+?)"} - $1$ - FAILED - 1 - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - - - - - false - fileId - {"1":"(.+?)"} - $1$ - FAILED - 1 - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - - - - - - - localhost - 8888 - - - - - /demo/javaLargeFileUploaderAsyncServlet?fileId=${fileId}&crc=65c369d0 - POST - true - false - true - true - HttpClient3.1 - - - - d:/OVFImporter.java - file - - - - - false - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - - - - 100 - 50.0 - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - 500 - false - - - Active Threads Over Time - Bytes Throughput Over Time - - - Overall Active Threads - Bytes Received per Second - - - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 100 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 500 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 500 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 500 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 1000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - - - - true - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - - - - - false - - - - - - diff --git a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/resources/log4j.properties b/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/resources/log4j.properties deleted file mode 100644 index 948a61b..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-jar/src/test/resources/log4j.properties +++ /dev/null @@ -1,14 +0,0 @@ - - -# Loggers. - -log4j.rootLogger = debug, console -log4j.logger.com.am = debug -log4j.logger.org.springframework = error - - -# Appenders. - -log4j.appender.console = org.apache.log4j.ConsoleAppender -log4j.appender.console.layout = org.apache.log4j.PatternLayout -log4j.appender.console.layout.ConversionPattern = %p %d{ISO8601} %C{1} %t %m %n diff --git a/java-large-file-uploader-parent/java-large-file-uploader-war/pom.xml b/java-large-file-uploader-parent/java-large-file-uploader-war/pom.xml deleted file mode 100644 index cc35204..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-war/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - Java Large File Uploader War - 4.0.0 - - - com.am - java-large-file-uploader-parent - 1.1.8 - - - java-large-file-uploader-war - war - - diff --git a/java-large-file-uploader-parent/java-large-file-uploader-war/src/main/resources/log4j.properties b/java-large-file-uploader-parent/java-large-file-uploader-war/src/main/resources/log4j.properties deleted file mode 100644 index 63da6f2..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-war/src/main/resources/log4j.properties +++ /dev/null @@ -1,11 +0,0 @@ -# Loggers. - -log4j.rootLogger = DEBUG, console -log4j.logger.org.springframework = WARN - - -# Appenders. - -log4j.appender.console = org.apache.log4j.ConsoleAppender -log4j.appender.console.layout = org.apache.log4j.PatternLayout -log4j.appender.console.layout.ConversionPattern = %p %d{ISO8601} %C{1} %t %m %n diff --git a/java-large-file-uploader-parent/java-large-file-uploader-war/src/main/webapp/WEB-INF/web.xml b/java-large-file-uploader-parent/java-large-file-uploader-war/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 2b37299..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-war/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1 +0,0 @@ -emtpy web.xml because this project shall be used as an overlay for another war project which is defining the real web.xml. \ No newline at end of file diff --git a/java-large-file-uploader-parent/java-large-file-uploader-war/src/main/webapp/js/javalargefileuploader.js b/java-large-file-uploader-parent/java-large-file-uploader-war/src/main/webapp/js/javalargefileuploader.js deleted file mode 100644 index ce2fb0e..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-war/src/main/webapp/js/javalargefileuploader.js +++ /dev/null @@ -1,963 +0,0 @@ -/* - * Constructor - */ -function JavaLargeFileUploader() { - var globalServletMapping = "javaLargeFileUploaderServlet"; - var uploadServletMapping = "javaLargeFileUploaderAsyncServlet"; - var pendingFiles = new Object(); - var bytesPerChunk; - - javaLargeFileUploaderHost = ""; - progressPollerRefreshRate = 1000; - maxNumberOfConcurrentUploads = 5; - autoRetry = true; - autoRetryDelay = 5000; - errorMessages = new Object(); - errorMessages[0] = "Request failed for an unknown reason, please contact an administrator if the problem persists."; - errorMessages[1] = "The request is not multipart."; - errorMessages[2] = "No file to upload found in the request."; - errorMessages[3] = "CRC32 Validation of the part failed."; - errorMessages[4] = "The request cannot be processed because a parameter is missing."; - errorMessages[5] = "Cannot retrieve the configuration."; - errorMessages[6] = "No files have been selected, please select at least one file!"; - errorMessages[7] = "Resuming file upload with previous slice as the last part is invalid."; - errorMessages[8] = "Error while uploading a slice of the file"; - errorMessages[9] = "Maximum number of concurrent uploads reached, the upload is queued and waiting for one to finish."; - errorMessages[10] = "An exception occurred. Retrying ..."; - errorMessages[11] = "Connection lost. Automatically retrying in a moment."; - errorMessages[12] = "You do not have the permission to perform this action."; - errorMessages[13] = "FireBug is enabled, you may experience issues if you do not disable it while uploading."; - errorMessages[14] = "File corrupted. An unknown error has occured and the file is corrupted. The usual cause is that the file has been modified during the upload. Please clear it and re-upload it."; - errorMessages[15] = "File is currently locked, retrying in a moment..."; - errorMessages[16] = "Uploads are momentarily disabled, retrying in a moment..."; - exceptionsRetryable = [0,3,7,8,10,11,15,16]; - - this.setJavaLargeFileUploaderHost = function (javaLargeFileUploaderHostI) { - javaLargeFileUploaderHost = javaLargeFileUploaderHostI; - }; - - this.setMaxNumberOfConcurrentUploads = function (maxNumberOfConcurrentUploadsI) { - maxNumberOfConcurrentUploads = maxNumberOfConcurrentUploadsI; - }; - - this.getErrorMessages = function () { - return errorMessages; - }; - - this.setProgressPollerRefreshRate = function(progressPollerRefreshRateI) { - progressPollerRefreshRate = progressPollerRefreshRateI; - }; - - this.setAutoRetry = function (autoRetryBoolean, autoRetryDelayI) { - autoRetry = autoRetryBoolean; - autoRetryDelay = autoRetryDelayI; - }; - - this.initialize = function (initializationCallback, exceptionCallback, optionalClientOrJobIdentifier) { - - //if an id is specified - var appended = ""; - if (optionalClientOrJobIdentifier) { - appended = "&clientId="+optionalClientOrJobIdentifier; - } - - //if firebug is enabled, show exception - manageFirebug(exceptionCallback); - - // get the configuration - $.get(javaLargeFileUploaderHost + globalServletMapping + "?action=getConfig" + appended, function(data) { - if (data) { - bytesPerChunk = data.inByte; - - // adjust values to display - if (!jQuery.isEmptyObject(data.pendingFiles)) { - pendingFiles = data.pendingFiles; - $.each(data.pendingFiles, function(key, pendingFile) { - pendingFile.id = key; - pendingFile.fileCompletion = getFormattedSize(pendingFile.fileCompletionInBytes); - pendingFile.originalFileSize = getFormattedSize(pendingFile.originalFileSizeInBytes); - pendingFile.percentageCompleted = format(pendingFile.fileCompletionInBytes * 100 / pendingFile.originalFileSizeInBytes); - pendingFile.started = false; - }); - } - initializationCallback(pendingFiles); - - } else { - if (exceptionCallback) { - //cannot retrieve the configuration - exceptionCallback(errorMessages[5]); - } - } - }); - - // launch the progress poller - startProgressPoller(); - - //initialize the pause all file uploads on close - $(window).bind('unload', function() { - pauseAllFileUploadsI(false); - }); - - - }; - - this.clearFileUpload = function (callback) { - $.each(pendingFiles, function(key, pendingFile) { - pendingFile.cancelled = true; - }); - pendingFiles = new Object(); - $.get(javaLargeFileUploaderHost + globalServletMapping + "?action=clearAll", function(e) { - if (callback) { - callback(); - } - }); - }; - - this.setRateInKiloBytes = function (fileId, rate) { - if(fileId && rate) { - $.get(javaLargeFileUploaderHost + globalServletMapping + "?action=setRate&rate="+rate+"&fileId="+fileId); - } - }; - - this.cancelFileUpload = function (fileIdI, callback) { - var fileId = fileIdI; - if(fileId && pendingFiles[fileId]) { - pendingFiles[fileId].cancelled = true; - $.get(javaLargeFileUploaderHost + globalServletMapping + "?action=clearFile&fileId=" + fileId, function(e) { - abort(pendingFiles[fileId], false); - if (callback) { - callback(fileId); - } - delete pendingFiles[fileId]; - processNextInQueue(); - }); - } - }; - - this.pauseFileUpload = function (fileIdI, callback) { - pauseFileUploads(true, [fileIdI], callback); - }; - - this.pauseAllFileUploads = function (callback) { - pauseAllFileUploadsI(true, callback); - }; - - function pauseAllFileUploadsI(async, callback) { - var fileIds = []; - for (var fileId in pendingFiles) { - fileIds.push(fileId); - } - pauseFileUploads(async, fileIds, callback); - } - - function pauseFileUploads(async, fileIds, callback) { - var filesToSend = []; - for (var i in fileIds) { - var fileId = fileIds[i]; - if(fileId && pendingFiles[fileId] && isFilePaused(pendingFiles[fileId]) === false && pendingFiles[fileId].resuming === false) { - if (pendingFiles[fileId].queued === true) { - pendingFiles[fileId].paused = true; - } else { - pendingFiles[fileId].pausing = true; - filesToSend.push(fileId); - } - } - } - if (filesToSend.length > 0) { - $.ajax({ - url: javaLargeFileUploaderHost + globalServletMapping + "?action=pauseFile&fileId=" + filesToSend, - success: function() { - for (var i in fileIds) { - var fileId = fileIds[i]; - var pendingFile = pendingFiles[fileId]; - pendingFile.pausedCallback = callback; - abort(pendingFile, true); - } - }, - async: async - }); - } - } - - function abort(pendingFile, forPauseBool) { - if (pendingFile.xhr) { - pendingFile.xhr.abort(); - } - if (forPauseBool) { - setTimeout(function() { - //if still paused after a certain delay, we unblock it - if (pendingFile.paused===false) { - notifyPause(pendingFile); - } - }, 2000); - } - } - - function notifyPause(pendingFile) { - if (pendingFile.pausing) { - console.log("The file is paused."); - uploadEnd(pendingFile, false); - pendingFile.paused=true; - if (pendingFile.pausedCallback) { - pendingFile.pausedCallback(pendingFile); - } - } - } - - function isFilePaused(pendingFile) { - return pendingFile.paused || pendingFile.pausing; - } - - this.resumeFileUpload = function (fileIdI, callback) { - this.resumeFileUploads([fileIdI], callback); - }; - - this.resumeAllFileUploads = function(callback) { - var fileIds = []; - for (var fileId in pendingFiles) { - fileIds.push(fileId); - } - this.resumeFileUploads (fileIds, callback); - }; - - this.resumeFileUploads = function (fileIds, callback) { - for (var i in fileIds) { - var fileIdI = fileIds[i]; - if (fileIdI && pendingFiles[fileIdI]) { - if (pendingFiles[fileIdI].paused === true && pendingFiles[fileIdI].resuming === false) { - pendingFiles[fileIdI].resuming = true; - resumeFileUploadInternal(pendingFiles[fileIdI], callback); - } - } - } - }; - - this.retryFileUpload = function (fileIdI, callback) { - if (fileIdI && pendingFiles[fileIdI]) { - resumeFileUploadInternal(pendingFiles[fileIdI], null, callback); - } - }; - - function displayException(pendingFile, errorMessageId) { - console.log(errorMessages[errorMessageId]); - if(pendingFile.exceptionCallback) { - pendingFile.exceptionCallback(errorMessages[errorMessageId], pendingFile.referenceToFileElement, pendingFile); - } - } - - function retryStart(pendingFile) { - setTimeout(retryRecursive, autoRetryDelay, pendingFile); - } - - function retryRecursive(pendingFile) { - if (pendingFile) { - displayException(pendingFile, 10); - resumeFileUploadInternal(pendingFile, null, function(ok) { - if (ok === false) { - displayException(pendingFile, 11); - retryStart(pendingFile); - } - }); - } - } - - function resumeFileUploadInternal(pendingFile, callback, retryCallback) { - if(pendingFile) { - //and restart flow - $.get(javaLargeFileUploaderHost + globalServletMapping + "?action=resumeFile&fileId=" + pendingFile.id, function(data) { - if (callback) { - callback(pendingFile); - } - - //populate crc data - pendingFile.crcedBytes = data.crcedBytes; - pendingFile.fileCompletionInBytes = data.fileCompletionInBytes; - - //try to validate the unvalidated chunks and resume it - fileResumeProcessStarter(pendingFile); - }).success(function(e) { - if (retryCallback) { - retryCallback(true); - } - }).error(function(e) { - if (retryCallback) { - retryCallback(false); - } - }); - } - } - - this.fileUploadProcess = function (referenceToFileElement, startCallback, progressCallback, - finishCallback, exceptionCallback) { - - //read the file information from input - var allFiles = extractFilesInformation(referenceToFileElement, startCallback, progressCallback, - finishCallback, exceptionCallback); - //copy it to another array which is gonna contain the new files to process - var potentialNewFiles = allFiles.slice(0); - - //try to corrolate information with our pending files - //corrolate with filename size and crc of first chunk - //start resuming if we have a match - //if we dont have any name/size math, we process an upload - var potentialResumeCounter = new Object(); - potentialResumeCounter.counter = 0; - for (fileKey in allFiles) { - var pendingFile = allFiles[fileKey]; - - //look for a match in the pending files - for (pendingFileToCheckKey in pendingFiles) { - var pendingFileToCheck = pendingFiles[pendingFileToCheckKey]; - - if (pendingFileToCheck.originalFileName == pendingFile.originalFileName && - pendingFileToCheck.originalFileSizeInBytes == pendingFile.originalFileSizeInBytes) { - - //we might have a match, adding a match counter entry - potentialResumeCounter.counter++; - - //check the crc first slice - //that method will take care of the new files processing when all complete - processCrcFirstSlice(potentialNewFiles, pendingFile, pendingFileToCheck, potentialResumeCounter); - } - } - } - - //process if no pending to resume - if (potentialResumeCounter.counter === 0 && potentialNewFiles.length > 0) { - processNewFiles(potentialNewFiles); - } - - }; - - function extractCrcFirstSlice(blob, callback) { - - //calculate the slice - var end = 8192; - if (blob.size < 8192) { - end = blob.size; - } - - var reader = new FileReader(); - reader.onloadend = function(e) { - //if the read is complete - if (e.target.readyState == FileReader.DONE) { // DONE == 2 - callback(decimalToHexString(crc32(e.target.result)), blob); - } - }; - reader.readAsBinaryString(slice(blob, 0, end)); - - } - - - - function processCrcFirstSlice(potentialNewFiles, pendingFileI, pendingFileToCheckI, potentialResumeCounter){ - - // prepare the checksum of the slice - var pendingFile = pendingFileI; - var pendingFileToCheck = pendingFileToCheckI; - extractCrcFirstSlice(pendingFile.blob, function(crc, blob) { - - //if that pendingfile is still there - if (potentialNewFiles.indexOf(pendingFile) != -1) { - - //calculate crc of the chunk read - //compare it - //if it is the correct file - //proceed - if (crc == pendingFileToCheck.firstChunkCrc) { - - //remove it from new file ids (as we are now sure it is not a new file) - potentialNewFiles.splice(potentialNewFiles.indexOf(pendingFile), 1); - - //if that file is not already being uploaded: - if (!pendingFileToCheck.started) { - - //if that file is paused - if (isFilePaused(pendingFileToCheck)) { - - //resume it - resumeFileUploadInternal(pendingFileToCheck); - - } else { - - //fill pending file to check with new info - //populate stuff retrieved in initialization - pendingFile.fileCompletionInBytes = pendingFileToCheck.fileCompletionInBytes; - pendingFile.crcedBytes = pendingFileToCheck.crcedBytes; - pendingFile.firstChunkCrc = pendingFileToCheck.firstChunkCrc; - pendingFile.started = pendingFileToCheck.started; - pendingFile.id = pendingFileToCheck.id; - - //put it into the pending files array - pendingFiles[pendingFileToCheck.id] = pendingFile; - - // process the upload - fileResumeProcessStarter(pendingFile); - } - } - - - } else { - console.log("Invalid resume crc for "+pendingFileToCheck.originalFileName+". processing as a new file."); - } - - //if its not the correct file, it will be processed in processNewFiles - - //decrement potential resume counter - potentialResumeCounter.counter--; - - //and if it was the last one, process the new files. - if (potentialResumeCounter.counter === 0 && potentialNewFiles.length > 0) { - processNewFiles(potentialNewFiles); - } - - } - }); - } - - - - function extractFilesInformation(referenceToFileElements, startCallback, progressCallback, finishCallback, exceptionCallback){ - var retArray = []; - - if($.isArray(referenceToFileElements)) { - for (var i = 0 ; i < referenceToFileElements.length; i++){ - retArray = retArray.concat(extractSingleElementFilesInformationProcess(referenceToFileElements[i], startCallback, progressCallback, finishCallback, exceptionCallback)); - } - } else { - retArray = extractSingleElementFilesInformationProcess(referenceToFileElements, startCallback, progressCallback, finishCallback, exceptionCallback); - } - return retArray; - } - - - - function extractSingleElementFilesInformationProcess(referenceToFileElement, startCallback, progressCallback, - finishCallback, exceptionCallback) { - var newFiles = []; - - //extract files - var files = referenceToFileElement.files; - if (!files.length) { - if (exceptionCallback) { - //no file selected - console.log(errorMessages[6]); - exceptionCallback(errorMessages[6], referenceToFileElement); - } - } else { - for (fileKey in files) { - var file = files[fileKey]; - if (file.name && file.size) { - - //init the pending file object - var pendingFile = new Object(); - pendingFile.originalFileName = file.name; - pendingFile.originalFileSizeInBytes = file.size; - pendingFile.originalFileSize = getFormattedSize(pendingFile.originalFileSizeInBytes); - pendingFile.blob = file; - pendingFile.progressCallback=progressCallback; - pendingFile.referenceToFileElement= referenceToFileElement; - pendingFile.startCallback= startCallback; - pendingFile.finishCallback= finishCallback; - pendingFile.exceptionCallback= exceptionCallback; - pendingFile.paused=false; - pendingFile.pausing=false; - pendingFile.resuming = false; - - //put it into the temporary new file array as every file is potentially a new file until it is proven it is not a new file - newFiles.push(pendingFile); - } - } - } - - return newFiles; - } - - function processNewFiles(newFiles) { - - //for the new files left, prepare initiation - var jsonVersionOfNewFiles = []; - var newFilesIds = 0; - var crcsCalculated = 0; - for (pendingFileId in newFiles) { - var pendingFile = newFiles[pendingFileId]; - - // prepare the objects - var fileForPost = new Object(); - fileForPost.tempId=newFilesIds; - fileForPost.fileName=pendingFile.originalFileName; - fileForPost.size=pendingFile.originalFileSizeInBytes; - jsonVersionOfNewFiles[fileForPost.tempId]=fileForPost; - pendingFiles[fileForPost.tempId]=pendingFile; - newFilesIds++; - - //extract first chunk crc - pendingFile.blob.i = fileForPost.tempId; - extractCrcFirstSlice(pendingFile.blob, function(crc, blob) { - jsonVersionOfNewFiles[blob.i].crc = crc; - pendingFiles[blob.i].firstChunkCrc=crc; - crcsCalculated++; - if (crcsCalculated == jsonVersionOfNewFiles.length) { - $.getJSON(javaLargeFileUploaderHost + globalServletMapping + "?action=prepareUpload", {newFiles: JSON.stringify(jsonVersionOfNewFiles)}, function(data) { - - //now populate our local entries with ids - $.each(data , function(tempIdI, fileIdI) { - - //now that we have the file id, we can assign the object - fileId = fileIdI; - pendingFile = pendingFiles[tempIdI]; - pendingFile.id = fileId; - pendingFile.fileComplete = false; - pendingFile.fileCompletionInBytes = 0; - pendingFiles[fileId] = pendingFile; - delete pendingFiles[tempIdI]; - - //call callback - if (pendingFile.startCallback) { - pendingFile.startCallback(pendingFile, pendingFile.referenceToFileElement); - } - - // and process the upload - fileUploadProcessStarter(pendingFile); - }); - }); - } - }); - - } - } - - function fileResumeProcessStarter(pendingFile) { - - //we have to ensure that the last chunk update that have not been validated is correct - var bytesToValidates = pendingFile.fileCompletionInBytes - pendingFile.crcedBytes; - - //if we have bytes to validate - if (bytesToValidates > 0) { - - //slice the not validated part - var chunk = slice(pendingFile.blob, pendingFile.crcedBytes , pendingFile.fileCompletionInBytes); - - //append chunk to a formdata - var formData = new FormData(); - formData.append("file", chunk); - - // prepare the checksum of the slice - var reader = new FileReader(); - reader.onloadend = function(e) { - if (e.target.readyState == FileReader.DONE) { // DONE == 2 - //calculate crc of the chunk read - var digest = crc32(e.target.result); - - //and send it - $.get(javaLargeFileUploaderHost + globalServletMapping + "?action=verifyCrcOfUncheckedPart&fileId=" + pendingFile.id + "&crc=" + decimalToHexString(digest), function(data) { - //check if we have an exception - if (data.value) { - displayException(pendingFile, data.value); - if (autoRetry && isExceptionRetryable(data.value)) { - //submit retry - retryStart(pendingFile); - } - } else { - //verify stuff! - if (data === false) { - displayException(pendingFile, 7); - console.log("crc verification failed for unchecked chunk, filecompletion is truncated to "+pendingFile.crcedBytes+" (was "+pendingFile.fileCompletionInBytes+")"); - //and assign the completion to last verified - pendingFile.fileCompletionInBytes = pendingFile.crcedBytes; - } - //then process upload - fileUploadProcessStarter(pendingFile); - } - }); - } - - }; - //read the chunk to calculate the crc - reader.readAsBinaryString(chunk); - - } - //if we dont have bytes to validate, process - else { - - //if everything is good, resume it: - fileUploadProcessStarter(pendingFile); - - } - - - } - - function canUploadBeProcessed() { - var numberOfUploadsCurrentlyBeingProcessed = 0; - for(fileId in pendingFiles) { - var pendingFile = pendingFiles[fileId]; - if (pendingFile.started ) { - numberOfUploadsCurrentlyBeingProcessed++; - } - } - //we can process only if we are under the capacity - return numberOfUploadsCurrentlyBeingProcessed < maxNumberOfConcurrentUploads; - } - - function fileUploadProcessStarter(pendingFile) { - - //if the file is not complete - if (pendingFile.fileCompletionInBytes < pendingFile.originalFileSizeInBytes) { - - //reset some tags - pendingFile.paused = false; - pendingFile.pausing = false; - pendingFile.resuming = false; - - //check if we can process the upload - if (canUploadBeProcessed() === true) { - - - // start - pendingFile.end = pendingFile.fileCompletionInBytes + bytesPerChunk; - pendingFile.started = true; - pendingFile.queued = false; - - console.log("processing "+pendingFile.id+" for slice "+pendingFile.fileCompletionInBytes + " - "+pendingFile.end); - - // then process the recursive function - go(pendingFile); - - } else { - //queue it - pendingFile.queued = true; - - //specify to user - displayException(pendingFile, 9); - } - - } - //otherwise - else { - //mark it as complete - pendingFile.fileComplete=true; - } - - - - } - - function slice(blob, start, end) { - - if (blob.slice) { - return blob.slice(start, end); - } else if (blob.mozSlice) { - return blob.mozSlice(start, end); - } else { - return blob.webkitSlice(start, end); - } - } - - - function go(pendingFile) { - - //every time a chunk is being uplodaed, we check for firebug ! - manageFirebug(pendingFile.exceptionCallback); - - //if file id is in the pending files: - var chunk = slice(pendingFile.blob, pendingFile.fileCompletionInBytes, pendingFile.end); - - //append chunk to a formdata - var formData = new FormData(); - formData.append("file", chunk); - - // prepare the checksum of the slice - var reader = new FileReader(); - reader.onloadend = function(e) { - if (e.target.readyState == FileReader.DONE) { // DONE == 2 - //calculate crc of the chunk read - var digest = crc32(e.target.result); - - // prepare xhr request - var xhr = new XMLHttpRequest(); - pendingFile.xhr = xhr; - - //assign pause callback - xhr.addEventListener("abort", function(event) { - notifyPause(pendingFile); - }, false); - - //then open - xhr.open('POST', javaLargeFileUploaderHost + uploadServletMapping + '?action=upload&fileId=' + pendingFile.id + '&crc=' + decimalToHexString(digest), true); - - // assign callback - xhr.onreadystatechange = function() { - if (xhr.readyState == 4) { - - //if we are pausing or cancelling, we just return - if (pendingFile.pausing || pendingFile.cancelled) { - return; - } - - //if we have an exception in the call - if (xhr.status != 200) { - displayException(pendingFile, 8); - if (autoRetry) { - //submit retry - retryStart(pendingFile); - } - uploadEnd(pendingFile, true); - return; - } - - //if we have an exception in the response text - if (xhr.response) { - var resp = JSON.parse(xhr.response); - displayException(pendingFile, resp.value); - if (autoRetry && isExceptionRetryable(resp.value)) { - //submit retry - retryStart(pendingFile); - } - uploadEnd(pendingFile, true); - return; - } - - // progress - pendingFile.fileCompletionInBytes = pendingFile.end; - pendingFile.end = pendingFile.fileCompletionInBytes + bytesPerChunk; - - // check if we need to go on - if (pendingFile.fileCompletionInBytes < pendingFile.originalFileSizeInBytes) { - // recursive call - setTimeout(go, 5, pendingFile); - } else { - pendingFile.fileComplete=true; - uploadEnd(pendingFile, false); - // finish callback - if (pendingFile.finishCallback) { - pendingFile.finishCallback(pendingFile, pendingFile.referenceToFileElement); - } - } - } - }; - - // send xhr request - try { - //only send if it is pending, because it could have been asked for cancellation while we were reading the file! - if (pendingFiles[pendingFile.id]) { - //and if we are not pausing or cancelling - if (!isFilePaused(pendingFile) && !pendingFile.cancelled) { - xhr.send(formData); - } - } - } catch (e) { - uploadEnd(pendingFile, true); - displayException(pendingFile, 8); - if (autoRetry) { - //submit retry - retryStart(pendingFile); - } - return; - } - } - - }; - //read the chunk to calculate the crc - reader.readAsBinaryString(chunk); - - - } - - function uploadEnd(pendingFile, withException) { - - //the file is not started anymore - pendingFile.started=false; - - //process the queue if it was not an exception and if there is no auto retry - if (withException === false) { - processNextInQueue(); - } - } - - function processNextInQueue() { - for(fileId in pendingFiles) { - if (pendingFiles[fileId].queued && !pendingFiles[fileId].paused) { - fileUploadProcessStarter(pendingFiles[fileId]); - return; - } - } - } - - - /* - * inspired from http://codeaid.net/javascript/convert-seconds-to-hours-minutes-and-seconds-(javascript) - */ - function getFormattedTime(secs) - { - if (secs < 1) { - return "-"; - } - - var hours = Math.floor(secs / (60 * 60)); - - var divisor_for_minutes = secs % (60 * 60); - var minutes = Math.floor(divisor_for_minutes / 60); - - var divisor_for_seconds = divisor_for_minutes % 60; - var seconds = Math.ceil(divisor_for_seconds); - - var returned = ''; - var displaySeconds = true; - if (hours > 0) { - returned += hours + "h"; - displaySeconds = false; - } - if (minutes > 0) { - returned += minutes + "m"; - displaySeconds &= minutes <= 10; - } - if (displaySeconds) { - returned += seconds + "s"; - } - return returned; - } - - function getFormattedSize(size) { - if (size < 1024) { - return format(size) + 'B'; - } else if (size < 1048576) { - return format(size / 1024) + 'KB'; - } else if (size < 1073741824) { - return format(size / 1048576) + 'MB'; - } else if (size < 1099511627776) { - return format(size / 1073741824) + 'GB'; - } else if (size < 1125899906842624) { - return format(size / 1099511627776) + 'TB'; - } - } - - function format(size) { - return Math.ceil(size*100)/100; - } - - function uploadIsActive(pendingFile) { - //process only if we have this id in the pending files and if the file is incomplete and if the file is not paused and if the file is started! - return pendingFile && pendingFiles[pendingFile.id] && !isFilePaused(pendingFile) && !pendingFile.fileComplete && pendingFile.started; - } - - function isExceptionRetryable(errorId) { - return (exceptionsRetryable.indexOf(parseInt(errorId)) != -1); - } - - function manageFirebug(exceptionCallback) { - //if firebug is enabled, show exception - if (window.console && (window.console.firebug || window.console.exception)) { - if (exceptionCallback) { - exceptionCallback(errorMessages[13]); - } else { - alert(errorMessages[13]); - } - } - } - - function startProgressPoller() { - - //first fill the request array - var fileIds = []; - - //for all the pending files - for (fileId in pendingFiles) { - var pendingFile = pendingFiles[fileId]; - - //if active - //and if we have a progress listener - if(uploadIsActive(pendingFile) && pendingFile.progressCallback) { - fileIds.push(fileId); - } - - } - - if (fileIds.length > 0) { - $.getJSON(javaLargeFileUploaderHost + globalServletMapping + "?action=getProgress", {fileId: JSON.stringify(fileIds)}, function(data) { - - //now populate our local entries with ids - $.each(data, function(fileId, progress) { - var pendingFile = pendingFiles[fileId]; - - //if the pending file status has not been deleted while we querying: - if(uploadIsActive(pendingFile)) { - - //if we have information about the rate: - if (progress.uploadRate != undefined) { - var uploadRate = getFormattedSize(progress.uploadRate); - } - - //if we have information about the time remaining: - if (progress.estimatedRemainingTimeInSeconds != undefined) { - var estimatedRemainingTimeInSeconds = getFormattedTime(progress.estimatedRemainingTimeInSeconds); - } - - //keep progress - pendingFile.percentageCompleted = format(progress.progress); - - // specify progress - pendingFile.progressCallback(pendingFile, pendingFile.percentageCompleted, uploadRate, estimatedRemainingTimeInSeconds, - pendingFile.referenceToFileElement); - - } - }); - }).complete(function() { - - //reschedule when the have the answer - setTimeout(startProgressPoller, progressPollerRefreshRate); - }); - } - //reschedule immediately if there is no pending upload - else { - setTimeout(startProgressPoller, progressPollerRefreshRate); - } - - - } - - - /* - =============================================================================== - Crc32 is a JavaScript function for computing the CRC32 of a string - ............................................................................... - - Version: 1.2 - 2006/11 - http://noteslog.com/post/crc32-for-javascript/ - - ------------------------------------------------------------------------------- - Copyright (c) 2006 Andrea Ercolino - http://www.opensource.org/licenses/mit-license.php - =============================================================================== - */ - - var strTable = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D".split(' '); - - var table = new Array(); - for (var i = 0; i < strTable.length; ++i) { - table[i] = parseInt("0x" + strTable[i]); - } - - /* Number */ - function crc32( /* String */ str) { - var crc = 0; - var n = 0; //a number between 0 and 255 - var x = 0; //an hex number - - crc = crc ^ (-1); - for( var i = 0, iTop = str.length; i < iTop; i++ ) { - n = ( crc ^ str.charCodeAt( i ) ) & 0xFF; - crc = ( crc >>> 8 ) ^ table[n]; - } - return crc ^ (-1); - } - - function decimalToHexString(number) { - if (number < 0) { - number = 0xFFFFFFFF + number + 1; - } - - return number.toString(16).toLowerCase(); - } -} - - diff --git a/java-large-file-uploader-parent/java-large-file-uploader-war/src/test/resources/jmeter.xml b/java-large-file-uploader-parent/java-large-file-uploader-war/src/test/resources/jmeter.xml deleted file mode 100644 index 2d23048..0000000 --- a/java-large-file-uploader-parent/java-large-file-uploader-war/src/test/resources/jmeter.xml +++ /dev/null @@ -1,810 +0,0 @@ - - - - - - false - false - - - - - - - - continue - - false - -1 - - 100 - 1 - 1337347420000 - 1337347420000 - false - - - - - - - - - false - prepareUpload - = - true - action - - - false - [{ "fileName":"bonjour", "size":123456789, "tempId":1 }] - = - true - newFiles - - - - localhost - 8888 - - - - - /demo/javaLargeFileUploaderServlet - POST - true - false - true - false - HttpClient3.1 - false - - - - - false - fileId - {"1":"(.+?)"} - $1$ - FAILED - 1 - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - - - - - false - fileId - {"1":"(.+?)"} - $1$ - FAILED - 1 - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - - - - - - - localhost - 8888 - - - - - /demo/javaLargeFileUploaderAsyncServlet?fileId=${fileId}&crc=65c369d0 - POST - true - false - true - true - HttpClient3.1 - - - - d:/OVFImporter.java - file - - - - - false - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - - - - 100 - 50.0 - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - 500 - false - - - Active Threads Over Time - Bytes Throughput Over Time - - - Overall Active Threads - Bytes Received per Second - - - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 100 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 500 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 500 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 5000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 500 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - true - - - - 1000 - false - - - - - - false - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - - - - true - - saveConfig - - - true - true - true - - true - true - true - true - false - true - true - false - false - true - false - false - false - false - false - 0 - true - - - - - - - - false - - - - - - diff --git a/java-large-file-uploader-parent/pom.xml b/java-large-file-uploader-parent/pom.xml deleted file mode 100644 index bfafd5b..0000000 --- a/java-large-file-uploader-parent/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - 4.0.0 - - Java Large File Uploader Parent - - com.am - java-large-file-uploader-parent - pom - 1.1.8 - - - java-large-file-uploader-jar - java-large-file-uploader-war - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.4 - - 1.6 - 1.6 - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.7 - - - com.google.code.maven-svn-wagon - maven-svn-wagon - 1.4 - - - - - org.apache.maven.plugins - maven-release-plugin - 2.3 - - true - true - false - - - - - - - com.google.code.maven-svn-wagon - maven-svn-wagon - 1.4 - - - - - - scm:svn:https://java-large-file-uploader.googlecode.com/svn/branches/1.0 - - - - - - googlecode - svn:https://java-large-file-uploader.googlecode.com/svn/mvnrepo - - - - \ No newline at end of file diff --git a/java-large-file-uploader/src/main/java/com/am/jlfu/fileuploader/limiter/RateLimiter.java b/java-large-file-uploader/src/main/java/com/am/jlfu/fileuploader/limiter/RateLimiter.java deleted file mode 100644 index 8795853..0000000 --- a/java-large-file-uploader/src/main/java/com/am/jlfu/fileuploader/limiter/RateLimiter.java +++ /dev/null @@ -1,2 +0,0 @@ -moved to: -http://code.google.com/p/java-large-file-uploader/source/browse/trunk/java-large-file-uploader-parent/java-large-file-uploader-jar/src/main/java/com/am/jlfu/fileuploader/limiter/RateLimiter.java \ No newline at end of file