null if the service was not able
+ * to resolve it automatically. In such case, {@link #setAnswer(String)}
+ * must be used to set the correct answer.
+ *
+ * @return the captcha answer
+ */
+ String getAnswer();
+
+ /**
+ * @return true if, and only if, the service was able to
+ * automatically resolve the captcha result
+ */
+ boolean wasAutomaticallyResolved();
+}
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/captcha/CaptchaResolver.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/captcha/CaptchaResolver.java
new file mode 100644
index 0000000..60141e4
--- /dev/null
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/captcha/CaptchaResolver.java
@@ -0,0 +1,19 @@
+/**
+ *
+ */
+package com.rogiel.httpchannel.captcha;
+
+/**
+ * @author Rogiel
+ */
+public interface CaptchaResolver {
+ /**
+ * Tries to resolve the captcha
+ *
+ * @param captcha
+ * the captcha
+ * @return true if the captcha was resolve, false
+ * to abort
+ */
+ boolean resolve(Captcha captcha);
+}
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/captcha/CaptchaService.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/captcha/CaptchaService.java
new file mode 100644
index 0000000..6ec0439
--- /dev/null
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/captcha/CaptchaService.java
@@ -0,0 +1,11 @@
+/**
+ *
+ */
+package com.rogiel.httpchannel.captcha;
+
+/**
+ * @author Rogiel
+ *
+ */
+public interface CaptchaServicetrue if the captcha was successfully resolved
+ */
+ boolean resolve(C captcha);
+}
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/AbstractService.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/AbstractService.java
index e66d10f..d70838b 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/AbstractService.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/AbstractService.java
@@ -16,37 +16,18 @@
*/
package com.rogiel.httpchannel.service;
-import com.rogiel.httpchannel.service.config.ServiceConfiguration;
+import com.rogiel.httpchannel.captcha.Captcha;
+import com.rogiel.httpchannel.captcha.CaptchaResolver;
+import com.rogiel.httpchannel.service.exception.UnresolvedCaptchaException;
/**
* This is an abstract {@link Service} implementation.
*
- * @author Rogiel
+ * @author Rogiel
* @version 1.0
- * @param
+ * IMPORTANT NOTE: You should not modify any configuration within
+ * this configuration object once while the account is authenticated.
+ * Depending on the service, changing any setting could result in an state
+ * where the service cannot be logged out.
+ *
+ * @return this {@link Authenticator} configuration
+ */
+ C getConfiguration();
+
+ /**
+ * This interface must be implemented in order to allow authentication
+ * configuration.
+ *
+ * @author Rogiel
+ */
+ public interface AuthenticatorConfiguration {
+
+ }
}
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/AuthenticatorCapability.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/AuthenticatorCapability.java
index d9ae9c6..213a230 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/AuthenticatorCapability.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/AuthenticatorCapability.java
@@ -19,7 +19,7 @@ package com.rogiel.httpchannel.service;
/**
* Capability an certain {@link Authenticator} can have.
*
- * @author Rogiel
+ * @author Rogiel
* @since 1.0
*/
public enum AuthenticatorCapability {
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/CapabilityMatrix.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/CapabilityMatrix.java
index bbc1aa0..d31f5ff 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/CapabilityMatrix.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/CapabilityMatrix.java
@@ -19,7 +19,7 @@ package com.rogiel.httpchannel.service;
/**
* This is an utility class to help manage Capabilities of all the services.
*
- * @author Rogiel
+ * @author Rogiel
* @param
* Please note that the value returned by this method may vary based
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/Downloader.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/Downloader.java
index 1358a94..b701c41 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/Downloader.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/Downloader.java
@@ -18,18 +18,21 @@ package com.rogiel.httpchannel.service;
import java.io.IOException;
+import com.rogiel.httpchannel.captcha.CaptchaResolver;
+import com.rogiel.httpchannel.service.Downloader.DownloaderConfiguration;
import com.rogiel.httpchannel.service.exception.DownloadLimitExceededException;
import com.rogiel.httpchannel.service.exception.DownloadLinkNotFoundException;
import com.rogiel.httpchannel.service.exception.DownloadNotAuthorizedException;
import com.rogiel.httpchannel.service.exception.DownloadNotResumableException;
+import com.rogiel.httpchannel.service.exception.UnresolvedCaptchaException;
/**
* This interfaces provides downloading for an service.
*
- * @author Rogiel
+ * @author Rogiel
* @since 1.0
*/
-public interface Downloader {
+public interface Downloader
+ * IMPORTANT NOTE: You should not modify any configuration within
+ * this configuration object once the download has started. Doing so, could
+ * result in a error.
+ *
+ * @return this {@link Downloader} configuration
+ */
+ C getConfiguration();
+
+ /**
+ * This interface must be implemented in order to allow download
+ * configuration.
+ *
+ * @author Rogiel
+ */
+ public interface DownloaderConfiguration {
+
+ }
}
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/DownloaderCapability.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/DownloaderCapability.java
index c7e45a2..151ce6e 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/DownloaderCapability.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/DownloaderCapability.java
@@ -19,7 +19,7 @@ package com.rogiel.httpchannel.service;
/**
* Capability an certain {@link Downloader} can have.
*
- * @author Rogiel
+ * @author Rogiel
* @since 1.0
*/
public enum DownloaderCapability {
@@ -35,10 +35,21 @@ public enum DownloaderCapability {
* Can download files while authenticated with premium account
*/
PREMIUM_ACCOUNT_DOWNLOAD,
+
/**
- * Resume interrupted downloads are possible and supported.
+ * Can resume interrupted downloads even without authenticating
*/
- RESUME,
+ UNAUTHENTICATED_RESUME,
+ /**
+ * Can resume interrupted downloads but require to be logged with any
+ * account
+ */
+ NON_PREMIUM_ACCOUNT_RESUME,
+ /**
+ * Can resume interrupted downloads but requires an premium account
+ */
+ PREMIUM_ACCOUNT_RESUME,
+
/**
* Can check the status of the given link before starting download.
*/
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/Service.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/Service.java
index 4be10d1..ba652ed 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/Service.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/Service.java
@@ -16,7 +16,7 @@
*/
package com.rogiel.httpchannel.service;
-import com.rogiel.httpchannel.service.config.ServiceConfiguration;
+import com.rogiel.httpchannel.captcha.CaptchaResolver;
/**
* Base interface for all the services. Whenever the operation suported by the
@@ -27,7 +27,7 @@ import com.rogiel.httpchannel.service.config.ServiceConfiguration;
*
*
*
- * @author Rogiel
+ * @author Rogiel
* @since 1.0
*/
public interface Service extends Cloneable {
@@ -53,19 +53,13 @@ public interface Service extends Cloneable {
int getMinorVersion();
/**
- * Returns this {@link ServiceConfiguration} instance
+ * Sets this service captcha resolver. Resolvers are safe to be switched
+ * even after an transfer has begun.
*
- * @return the {@link ServiceConfiguration} instance
+ * @param resolver
+ * the captcha resolver
*/
- ServiceConfiguration getServiceConfiguration();
-
- /**
- * Sets this {@link ServiceConfiguration} instance
- *
- * @param configuration
- * the {@link ServiceConfiguration} instance
- */
- void setServiceConfiguration(ServiceConfiguration configuration);
+ void setCaptchaResolver(CaptchaResolver resolver);
/**
* @return a cloned version of this service
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/ServiceID.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/ServiceID.java
index 6a5ea29..499e8e0 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/ServiceID.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/ServiceID.java
@@ -18,6 +18,8 @@ package com.rogiel.httpchannel.service;
import java.io.Serializable;
+import com.rogiel.httpchannel.service.helper.Services;
+
/**
* An ID used to represent the given service
*
@@ -27,7 +29,7 @@ public class ServiceID implements Serializable, Cloneable {
/**
* This class serialization version UID
*/
- private static final long serialVersionUID = -1078456596792552200L;
+ private static final long serialVersionUID = 1L;
/**
* The raw ID
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/UploadChannel.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/UploadChannel.java
index 71b1873..f2ed303 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/UploadChannel.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/UploadChannel.java
@@ -16,7 +16,9 @@
*/
package com.rogiel.httpchannel.service;
+import java.io.Closeable;
import java.io.IOException;
+import java.net.URL;
import java.nio.channels.Channel;
import java.nio.channels.WritableByteChannel;
@@ -34,7 +36,7 @@ import com.rogiel.httpchannel.service.exception.UploadLinkNotFoundException;
*
* @author Rogiel
*/
-public interface UploadChannel extends WritableByteChannel {
+public interface UploadChannel extends WritableByteChannel, Closeable {
/**
* @return the file size
*/
@@ -52,7 +54,7 @@ public interface UploadChannel extends WritableByteChannel {
*
* @return the download link for this upload
*/
- String getDownloadLink();
+ URL getDownloadLink();
/**
* @throws UploadLinkNotFoundException
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/UploadService.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/UploadService.java
index 8300d3b..9307390 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/UploadService.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/UploadService.java
@@ -16,13 +16,16 @@
*/
package com.rogiel.httpchannel.service;
+import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
+import com.rogiel.httpchannel.service.config.NullUploaderConfiguration;
+
/**
* Implements an service capable of uploading a file.
*
- * @author Rogiel
+ * @author Rogiel
* @since 1.0
*/
-public interface UploadService extends Service {
+public interface UploadService
+ * IMPORTANT NOTE: You should not modify any configuration within
+ * this configuration object once the upload has started. Doing so, could
+ * result in a error.
+ *
+ * @return this {@link Uploader} configuration
+ */
+ C getConfiguration();
+
+ /**
+ * This interface must be implemented in order to allow upload
+ * configuration.
+ *
+ * @author Rogiel
+ */
+ public interface UploaderConfiguration {
+ }
+
+ /**
+ * Defines an {@link UploaderConfiguration} that can allow at least
+ * an description field
+ *
+ * @author Rogiel
+ */
+ public interface DescriptionableUploaderConfiguration extends
+ UploaderConfiguration {
+ public static final String DEFAULT_DESCRIPTION = "Uploaded by httpchannel";
+
+ /**
+ * @return the upload description
+ */
+ String description();
+
+ /**
+ * @param description
+ * the upload description
+ */
+ DescriptionableUploaderConfiguration description(String description);
+ }
}
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/UploaderCapability.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/UploaderCapability.java
index a96c57b..010e367 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/UploaderCapability.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/UploaderCapability.java
@@ -19,7 +19,7 @@ package com.rogiel.httpchannel.service;
/**
* Capability an certain {@link Uploader} can have.
*
- * @author Rogiel
+ * @author Rogiel
* @since 1.0
*/
public enum UploaderCapability {
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/captcha/Captcha.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/captcha/Captcha.java
deleted file mode 100644
index 9778c67..0000000
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/captcha/Captcha.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * This file is part of seedbox
+ * The input channel must be created or provided at construction time, but
+ * several output channels can be added through
+ * {@link #addOutput(UploadChannel)}, {@link #addOutput(UploadService)} or
+ * {@link #addOutput(UploadService, UploaderConfiguration)}.
+ *
+ * Once all output channels were set, {@link #call()} must be called in order to
+ * start copying data. This class implements {@link Callable} and thus can be
+ * executed inside an {@link Executor}.
+ *
+ * @author Rogiel
+ */
+public class ChannelCopy implements Callable
@@ -32,11 +35,34 @@ public interface UploadService extends Service {
* the name of the file to be uploaded
* @param filesize
* the size of the file to be uploaded. This must be exact.
- * @param description
- * the description of the upload. If supported.
+ * @param configuration
+ * the uploader configuration
* @return the new {@link Uploader} instance
*/
- Uploader getUploader(String filename, long filesize, String description);
+ Uploader
+ * Note: not all services might support description
+ *
+ * @param filename
+ * the name of the file to be uploaded
+ * @param filesize
+ * the size of the file to be uploaded. This must be exact.
+ * @return the new {@link Uploader} instance
+ */
+ Uploader
- *
- * Every service must create an interface with the configuration
- * methods, additionally an Annotation informing the default value.
- * ServiceConfiguration implementations might use reflection ({@link Proxy}),
- * hard-coding or any other way for fetching the data.
- *
- * String data stored in the annotation is converted to Java Types using the
- * {@link Transformer} class.
- *
- * @author Rogiel
- * @version 1.0
- * @see Transformer
- */
-public interface ServiceConfiguration {
-}
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/config/ServiceConfigurationHelper.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/config/ServiceConfigurationHelper.java
deleted file mode 100644
index ed92903..0000000
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/config/ServiceConfigurationHelper.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * This file is part of seedbox
- *
- * Usage example
- *
- *
- * public interface DummyServiceConfiguration extends ServiceConfiguration {
- * @ServiceConfigurationProperty(defaultValue = "true")
- * boolean retryAllowed();
- * }
- *
- *
- * The default implementation created by
- * {@link ServiceConfigurationHelper#defaultConfiguration()} will always return
- * the defaultValue.
- *
- * @author Rogiel
- * @version 1.0
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-@Documented
-public @interface ServiceConfigurationProperty {
- String key();
- String defaultValue();
-}
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/exception/DownloadInvalidCaptchaException.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/exception/InvalidCaptchaException.java
similarity index 77%
rename from httpchannel-api/src/main/java/com/rogiel/httpchannel/service/exception/DownloadInvalidCaptchaException.java
rename to httpchannel-api/src/main/java/com/rogiel/httpchannel/service/exception/InvalidCaptchaException.java
index d1e3ca8..c3b227e 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/exception/DownloadInvalidCaptchaException.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/exception/InvalidCaptchaException.java
@@ -16,7 +16,7 @@
*/
package com.rogiel.httpchannel.service.exception;
-import com.rogiel.httpchannel.service.captcha.CaptchaResolver;
+import com.rogiel.httpchannel.captcha.CaptchaResolver;
/**
* Exception thrown if the {@link CaptchaResolver} has returned an invalid
@@ -24,13 +24,13 @@ import com.rogiel.httpchannel.service.captcha.CaptchaResolver;
*
* @author Rogiel
*/
-public class DownloadInvalidCaptchaException extends DownloadServiceException {
+public class InvalidCaptchaException extends ChannelServiceException {
private static final long serialVersionUID = 1L;
/**
* Creates a new empty instance of this exception
*/
- public DownloadInvalidCaptchaException() {
+ public InvalidCaptchaException() {
super();
}
@@ -40,7 +40,7 @@ public class DownloadInvalidCaptchaException extends DownloadServiceException {
* @param cause
* the root cause
*/
- public DownloadInvalidCaptchaException(String message, Throwable cause) {
+ public InvalidCaptchaException(String message, Throwable cause) {
super(message, cause);
}
@@ -48,7 +48,7 @@ public class DownloadInvalidCaptchaException extends DownloadServiceException {
* @param message
* the message
*/
- public DownloadInvalidCaptchaException(String message) {
+ public InvalidCaptchaException(String message) {
super(message);
}
@@ -56,7 +56,7 @@ public class DownloadInvalidCaptchaException extends DownloadServiceException {
* @param cause
* the root cause
*/
- public DownloadInvalidCaptchaException(Throwable cause) {
+ public InvalidCaptchaException(Throwable cause) {
super(cause);
}
}
diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/util/transformer/TransformationException.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/exception/UnresolvedCaptchaException.java
similarity index 59%
rename from httpchannel-api/src/main/java/com/rogiel/httpchannel/util/transformer/TransformationException.java
rename to httpchannel-api/src/main/java/com/rogiel/httpchannel/service/exception/UnresolvedCaptchaException.java
index 775b7c1..da86cf0 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/util/transformer/TransformationException.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/exception/UnresolvedCaptchaException.java
@@ -14,42 +14,49 @@
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see , C extends AuthenticatorConfiguration> Authenticator, C extends AuthenticatorConfiguration> Authenticator, C extends UploaderConfiguration> Uploader, C extends UploaderConfiguration> Uploader> {
+ /**
+ * The input channel
+ */
+ private final ReadableByteChannel downloadChannel;
+ /**
+ * The filename
+ */
+ private final String filename;
+ /**
+ * The filesise
+ */
+ private final long filesize;
+
+ /**
+ * The list of all channels to write data to
+ */
+ private final List
, C extends UploaderConfiguration> void addOutput(
+ S service, C configuration) throws IOException {
+ addOutput(service.getUploader(filename, filesize, configuration)
+ .openChannel());
+ }
+
+ @Override
+ public List
true if the service is on the list
+ */
+ public boolean containsUploadService(MultiUploadMirrorService service) {
+ return uploadServices.contains(service);
+ }
+
+ /**
+ * Removes this service from the mirror list
+ *
+ * @param service
+ * the service
+ */
+ public MultiUploadUploaderConfiguration removeUploadService(
+ MultiUploadMirrorService service) {
+ uploadServices.remove(service);
+ return this;
+ }
+
+ /**
+ * Removes all services from the mirror list
+ *
+ * @return
+ */
+ public MultiUploadUploaderConfiguration clearUploadServices() {
+ uploadServices.clear();
+ return this;
+ }
+
+ /**
+ * @return the list of services of which MultiUpload should try to make
+ * mirrors
+ */
+ public EnumSetnull otherwise
+ */
+ public String findLink(final Pattern pattern) {
+ for (final LinkTag tag : filter(LinkTag.class, new LinkPatternFilter(
+ pattern))) {
+ return tag.getLink();
+ }
+ return null;
+ }
+
+ /**
+ * Tries to find a frame that has an URL following the given pattern
+ *
+ * @param pattern
+ * the pattern
+ * @return the iframe url, if found. null otherwise
+ */
+ public String findFrame(final Pattern pattern) {
+ for (final TagNode tag : filter(TagNode.class, new FramePatternFilter(
+ pattern))) {
+ return tag.getAttribute("src");
+ }
+ return null;
+ }
+
+ /**
+ * Tries to find a image that has an URL following the given pattern
+ *
+ * @param pattern
+ * the pattern
+ * @return the iframe url, if found. null otherwise
+ */
+ public String findImage(final Pattern pattern) {
+ for (final ImageTag tag : filter(ImageTag.class,
+ new ImagePatternFilter(pattern))) {
+ return tag.getImageURL();
+ }
+ return null;
+ }
+
+ /**
+ * Tries to find a form which has an location that respects the given
+ * pattern
+ *
+ * @param pattern
+ * the pattern
+ * @return the URL found, if any. null otherwise
+ */
+ public String findFormAction(final Pattern pattern) {
+ for (final FormTag tag : filter(FormTag.class,
+ new FormActionPatternFilter(pattern))) {
+ return tag.getFormLocation();
+ }
+ return null;
+ }
+
+ private String inputValue(List