1
0
mirror of https://github.com/Rogiel/httpchannel synced 2025-12-06 07:32:50 +00:00

Implements several services and improves API

This commit is contained in:
2012-01-15 18:31:50 -02:00
parent f210afd16a
commit 23f80b50e6
117 changed files with 3741 additions and 1335 deletions

View File

@@ -0,0 +1,33 @@
/**
*
*/
package com.rogiel.httpchannel.captcha;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public interface Captcha {
/**
* Sets the captcha answer
*
* @param answer
* the captcha answer
*/
void setAnswer(String answer);
/**
* Returns the captcha answer. <code>null</code> 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 <code>true</code> if, and only if, the service was able to
* automatically resolve the captcha result
*/
boolean wasAutomaticallyResolved();
}

View File

@@ -0,0 +1,19 @@
/**
*
*/
package com.rogiel.httpchannel.captcha;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface CaptchaResolver {
/**
* Tries to resolve the captcha
*
* @param captcha
* the captcha
* @return <code>true</code> if the captcha was resolve, <code>false</code>
* to abort
*/
boolean resolve(Captcha captcha);
}

View File

@@ -0,0 +1,11 @@
/**
*
*/
package com.rogiel.httpchannel.captcha;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public interface CaptchaService<C extends Captcha> {
}

View File

@@ -0,0 +1,22 @@
/**
*
*/
package com.rogiel.httpchannel.captcha;
import java.net.URL;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public interface ImageCaptcha extends Captcha {
/**
* @return the captcha identifier
*/
String getID();
/**
* @return the captcha image {@link URL}
*/
URL getImageURL();
}

View File

@@ -0,0 +1,31 @@
/**
*
*/
package com.rogiel.httpchannel.captcha;
import java.net.URL;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public interface ImageCaptchaService<C extends ImageCaptcha> extends
CaptchaService<C> {
/**
* Creates a new captcha from the given HTML content
*
* @param image
* the image {@link URL}
* @return a new captcha
*/
C create(String html);
/**
* Tries to automatically resolve the captcha
*
* @param captcha
* the captcha to be resolved
* @return <code>true</code> if the captcha was successfully resolved
*/
boolean resolve(C captcha);
}

View File

@@ -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 <a href="http://www.rogiel.com">Rogiel</a>
* @version 1.0
* @param <T>
* The {@link ServiceConfiguration} <b>interface</b> type used by the
* {@link Service}. Note that this <b>must</b> be an interface!s
* @see ServiceConfiguration ServiceConfiguration for details on the
* configuration interface.
*/
public abstract class AbstractService<T extends ServiceConfiguration>
implements Service {
protected T configuration;
protected AbstractService(T configuration) {
this.configuration = configuration;
}
@Override
public T getServiceConfiguration() {
return configuration;
}
@Override
@SuppressWarnings("unchecked")
public void setServiceConfiguration(ServiceConfiguration configuration) {
this.configuration = (T) configuration;
}
public abstract class AbstractService implements Service {
protected CaptchaResolver captchaResolver;
@Override
public Service clone() {
@@ -56,4 +37,20 @@ public abstract class AbstractService<T extends ServiceConfiguration>
return null;
}
}
@Override
public void setCaptchaResolver(CaptchaResolver captchaResolver) {
this.captchaResolver = captchaResolver;
}
protected boolean resolveCaptcha(Captcha captcha)
throws UnresolvedCaptchaException {
if (captchaResolver == null)
throw new UnresolvedCaptchaException();
if (!captchaResolver.resolve(captcha))
throw new UnresolvedCaptchaException();
if (captcha.getAnswer() == null)
throw new UnresolvedCaptchaException();
return true;
}
}

View File

@@ -16,13 +16,29 @@
*/
package com.rogiel.httpchannel.service;
import com.rogiel.httpchannel.service.Authenticator.AuthenticatorConfiguration;
import com.rogiel.httpchannel.service.config.NullAuthenticatorConfiguration;
/**
* Implements an service capable of authenticating into an account.
*
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public interface AuthenticationService extends Service {
public interface AuthenticationService<C extends AuthenticatorConfiguration>
extends Service {
/**
* Creates {@link Authenticator} instance for this service. This instance is
* attached to an {@link Credential} and to its parent {@link Service}.
*
* @param credential
* the credential
* @param configuration
* the authenticator configuration
* @return an new {@link Authenticator} instance
*/
Authenticator<C> getAuthenticator(Credential credential, C configuration);
/**
* Creates {@link Authenticator} instance for this service. This instance is
* attached to an {@link Credential} and to its parent {@link Service}.
@@ -31,7 +47,17 @@ public interface AuthenticationService extends Service {
* the credential
* @return an new {@link Authenticator} instance
*/
Authenticator getAuthenticator(Credential credential);
Authenticator<C> getAuthenticator(Credential credential);
/**
* Creates a new configuration object. If a service does not support or
* require configuration, {@link NullAuthenticatorConfiguration} should be
* returned.
*
* @return a new configuration object or
* {@link NullAuthenticatorConfiguration}
*/
C newAuthenticatorConfiguration();
/**
* Return the matrix of capabilities for this {@link Authenticator}.

View File

@@ -18,15 +18,18 @@ package com.rogiel.httpchannel.service;
import java.io.IOException;
import com.rogiel.httpchannel.captcha.CaptchaResolver;
import com.rogiel.httpchannel.service.Authenticator.AuthenticatorConfiguration;
import com.rogiel.httpchannel.service.exception.AuthenticationInvalidCredentialException;
import com.rogiel.httpchannel.service.exception.UnresolvedCaptchaException;
/**
* This interfaces provides authentication for an service.
*
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public interface Authenticator {
public interface Authenticator<C extends AuthenticatorConfiguration> {
/**
* Login into the {@link Service}. Once the authentication is done, it is
* persistent for the entire service's operation.<br>
@@ -37,8 +40,13 @@ public interface Authenticator {
* if any IO error occur
* @throws AuthenticationInvalidCredentialException
* if the credentials are not valid or cannot be used
* @throws UnresolvedCaptchaException
* if the service required captcha resolving but no
* {@link CaptchaResolver} was available or the resolver did not
* solve the challenge
*/
void login() throws IOException, AuthenticationInvalidCredentialException;
void login() throws IOException, AuthenticationInvalidCredentialException,
UnresolvedCaptchaException;
/**
* Logout into the {@link Service}. The session is restored to an not
@@ -48,4 +56,26 @@ public interface Authenticator {
* if any IO error occur
*/
void logout() throws IOException;
/**
* Returns this {@link Authenticator} configuration.
* <p>
* <b>IMPORTANT NOTE</b>: 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 <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface AuthenticatorConfiguration {
}
}

View File

@@ -19,7 +19,7 @@ package com.rogiel.httpchannel.service;
/**
* Capability an certain {@link Authenticator} can have.
*
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public enum AuthenticatorCapability {

View File

@@ -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 <a href="http://www.rogiel.com">Rogiel</a>
* @param <T>
* the capability enumeration
* @since 1.0

View File

@@ -19,7 +19,7 @@ package com.rogiel.httpchannel.service;
/**
* Pair of username-password used for authenticating into services.
*
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public class Credential {

View File

@@ -16,6 +16,7 @@
*/
package com.rogiel.httpchannel.service;
import java.io.Closeable;
import java.nio.channels.Channel;
import java.nio.channels.ReadableByteChannel;
@@ -31,7 +32,7 @@ import java.nio.channels.ReadableByteChannel;
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface DownloadChannel extends ReadableByteChannel {
public interface DownloadChannel extends ReadableByteChannel, Closeable {
/**
* @return the file size
*/

View File

@@ -20,7 +20,7 @@ package com.rogiel.httpchannel.service;
* This listener keeps an track on the progress on an {@link Downloader}
* service.
*
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public interface DownloadListener {

View File

@@ -20,13 +20,17 @@ import java.net.URL;
import javax.tools.FileObject;
import com.rogiel.httpchannel.service.Downloader.DownloaderConfiguration;
import com.rogiel.httpchannel.service.config.NullDownloaderConfiguration;
/**
* Implements an service capable of downloading a file.
*
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public interface DownloadService extends Service {
public interface DownloadService<C extends DownloaderConfiguration> extends
Service {
/**
* Creates a new instance of the {@link Downloader}. This instance will be
* attached to the {@link URL}, {@link FileObject} provided through the the
@@ -34,14 +38,34 @@ public interface DownloadService extends Service {
*
* @param url
* the url to be downloaded
* @param file
* the destination file
* @param configuration
* the downloader configurationf
* @return an new instance of {@link Downloader}
*/
Downloader getDownloader(URL url);
Downloader<C> getDownloader(URL url, C configuration);
/**
* Check if this {@link Service} can download from this URL. Implemtations
* Creates a new instance of the {@link Downloader}. This instance will be
* attached to the {@link URL}, {@link FileObject} provided through the the
* arguments and the parent {@link Service} instance.
*
* @param url
* the url to be downloaded
* @return an new instance of {@link Downloader}
*/
Downloader<C> getDownloader(URL url);
/**
* Creates a new configuration object. If a service does not support or
* require configuration, {@link NullDownloaderConfiguration} should be
* returned.
*
* @return a new configuration object or {@link NullDownloaderConfiguration}
*/
C newDownloaderConfiguration();
/**
* Check if this {@link Service} can download from this URL. Implementations
* might or might not perform network activity.
* <p>
* <b>Please note</b> that the value returned by this method may vary based

View File

@@ -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 <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public interface Downloader {
public interface Downloader<C extends DownloaderConfiguration> {
/**
* Opens a new {@link DownloadChannel} that will be immediately ready to
* read data from the download stream.
@@ -67,9 +70,105 @@ public interface Downloader {
* @throws DownloadNotResumableException
* if the download cannot be started at <tt>position</tt>. Will
* only be thrown if <tt>position > 0</tt>.
* @throws UnresolvedCaptchaException
* if the service required captcha resolving but no
* {@link CaptchaResolver} was available or the resolver did not
* solve the challenge
*/
DownloadChannel download(DownloadListener listener, long position)
DownloadChannel openChannel(DownloadListener listener, long position)
throws IOException, DownloadLinkNotFoundException,
DownloadLimitExceededException, DownloadNotAuthorizedException,
DownloadNotResumableException;
DownloadNotResumableException, UnresolvedCaptchaException;
/**
* Opens a new {@link DownloadChannel} with not listener. For more details,
* see {@link #openChannel(DownloadListener, long)}
*
* @param position
* the download start position. If seek is supported by service.
* If zero, download will start from the beginning.
* @return the {@link DownloadChannel} instance
* @throws IOException
* if any IO error occur
* @throws DownloadLinkNotFoundException
* if the direct download link cannot be found (the file could
* have been deleted)
* @throws DownloadLimitExceededException
* if the download limit has been exceed, most times thrown when
* downloading as a non-premium user
* @throws DownloadNotAuthorizedException
* if the user (or guest) account does not have necessary rights
* to download the file
* @throws DownloadNotResumableException
* if the download cannot be started at <tt>position</tt>. Will
* only be thrown if <tt>position > 0</tt>.
*/
DownloadChannel openChannel(long position) throws IOException,
DownloadLinkNotFoundException, DownloadLimitExceededException,
DownloadNotAuthorizedException, DownloadNotResumableException;
/**
* Opens a new {@link DownloadChannel} positioned at start. For more
* details, see {@link #openChannel(DownloadListener, long)}
*
* @param listener
* the listener to keep a track on the download progress
* @return the {@link DownloadChannel} instance
* @throws IOException
* if any IO error occur
* @throws DownloadLinkNotFoundException
* if the direct download link cannot be found (the file could
* have been deleted)
* @throws DownloadLimitExceededException
* if the download limit has been exceed, most times thrown when
* downloading as a non-premium user
* @throws DownloadNotAuthorizedException
* if the user (or guest) account does not have necessary rights
* to download the file
*/
DownloadChannel openChannel(DownloadListener listener) throws IOException,
DownloadLinkNotFoundException, DownloadLimitExceededException,
DownloadNotAuthorizedException;
/**
* Opens a new {@link DownloadChannel} with not listener and positioned at
* start. For more details, see {@link #openChannel(DownloadListener, long)}
*
* @return the {@link DownloadChannel} instance
* @throws IOException
* if any IO error occur
* @throws DownloadLinkNotFoundException
* if the direct download link cannot be found (the file could
* have been deleted)
* @throws DownloadLimitExceededException
* if the download limit has been exceed, most times thrown when
* downloading as a non-premium user
* @throws DownloadNotAuthorizedException
* if the user (or guest) account does not have necessary rights
* to download the file
*/
DownloadChannel openChannel() throws IOException,
DownloadLinkNotFoundException, DownloadLimitExceededException,
DownloadNotAuthorizedException;
/**
* Returns this {@link Downloader} configuration.
* <p>
* <b>IMPORTANT NOTE</b>: 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 <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface DownloaderConfiguration {
}
}

View File

@@ -19,7 +19,7 @@ package com.rogiel.httpchannel.service;
/**
* Capability an certain {@link Downloader} can have.
*
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @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.
*/

View File

@@ -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;
* </li>
* </ul>
*
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @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

View File

@@ -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

View File

@@ -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 <a href="http://www.rogiel.com">Rogiel</a>
*/
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

View File

@@ -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 <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public interface UploadService extends Service {
public interface UploadService<C extends UploaderConfiguration> extends Service {
/**
* Creates a new instance of {@link Uploader}. This instance is attached
* with the parent {@link Service} instance.<br>
@@ -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<C> getUploader(String filename, long filesize, C configuration);
/**
* Creates a new instance of {@link Uploader}. This instance is attached
* with the parent {@link Service} instance.<br>
* <b>Note</b>: not all services might support <tt>description</tt>
*
* @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<C> getUploader(String filename, long filesize);
/**
* Creates a new configuration object. If a service does not support or
* require configuration, {@link NullUploaderConfiguration} should be
* returned.
*
* @return a new configuration object or
* {@link NullUploaderConfiguration}
*/
C newUploaderConfiguration();
/**
* Get the maximum upload file size supported by this service.

View File

@@ -18,13 +18,17 @@ package com.rogiel.httpchannel.service;
import java.io.IOException;
import com.rogiel.httpchannel.captcha.CaptchaResolver;
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
import com.rogiel.httpchannel.service.exception.UnresolvedCaptchaException;
/**
* This interfaces provides uploading for an service.
*
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public interface Uploader {
public interface Uploader<C extends UploaderConfiguration> {
/**
* Opens a new {@link UploadChannel} that will be immediately ready to
* receive data to be sent to the upload stream.
@@ -44,6 +48,52 @@ public interface Uploader {
* @return the {@link UploadChannel} instance
* @throws IOException
* if any IO error occur
* @throws UnresolvedCaptchaException
* if the service required captcha resolving but no
* {@link CaptchaResolver} was available or the resolver did not
* solve the challenge
*/
UploadChannel upload() throws IOException;
UploadChannel openChannel() throws IOException, UnresolvedCaptchaException;
/**
* Returns this {@link Uploader} configuration.
* <p>
* <b>IMPORTANT NOTE</b>: 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 <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface UploaderConfiguration {
}
/**
* Defines an {@link UploaderConfiguration} that can allow <b>at least</b>
* an description field
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
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);
}
}

View File

@@ -19,7 +19,7 @@ package com.rogiel.httpchannel.service;
/**
* Capability an certain {@link Uploader} can have.
*
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public enum UploaderCapability {

View File

@@ -1,26 +0,0 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.service.captcha;
/**
* @author Rogiel
* @since 1.0
*/
public interface Captcha {
String getAnswer();
void setAnswer(String answer);
}

View File

@@ -1,47 +0,0 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.service.captcha;
import java.net.URL;
/**
* @author Rogiel
* @since 1.0
*/
public class ImageCaptcha implements Captcha {
private URL url;
private String answer;
public URL getUrl() {
return url;
}
public void setUrl(URL url) {
this.url = url;
}
@Override
public String getAnswer() {
return answer;
}
@Override
public void setAnswer(String answer) {
this.answer = answer;
}
}

View File

@@ -0,0 +1,17 @@
package com.rogiel.httpchannel.service.config;
import com.rogiel.httpchannel.service.AuthenticationService;
import com.rogiel.httpchannel.service.Authenticator.AuthenticatorConfiguration;
/**
* An default {@link AuthenticatorConfiguration} implementation that is
* generally returned by
* {@link AuthenticationService#newAuthenticatorConfiguration()} when the
* service does not support or require any kind of configuration.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public final class NullAuthenticatorConfiguration implements
AuthenticatorConfiguration {
public static final NullAuthenticatorConfiguration SHARED_INSTANCE = new NullAuthenticatorConfiguration();
}

View File

@@ -0,0 +1,16 @@
package com.rogiel.httpchannel.service.config;
import com.rogiel.httpchannel.service.DownloadService;
import com.rogiel.httpchannel.service.Downloader.DownloaderConfiguration;
/**
* An default {@link DownloaderConfiguration} implementation that is generally
* returned by {@link DownloadService#newDownloaderConfiguration()} when the
* service does not support or require any kind of configuration.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public final class NullDownloaderConfiguration implements
DownloaderConfiguration {
public static final NullDownloaderConfiguration SHARED_INSTANCE = new NullDownloaderConfiguration();
}

View File

@@ -0,0 +1,15 @@
package com.rogiel.httpchannel.service.config;
import com.rogiel.httpchannel.service.UploadService;
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
/**
* An default {@link UploaderConfiguration} implementation that is generally
* returned by {@link UploadService#newUploaderConfiguration()} when the service
* does not support or require any kind of configuration.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public final class NullUploaderConfiguration implements UploaderConfiguration {
public static final NullUploaderConfiguration SHARED_INSTANCE = new NullUploaderConfiguration();
}

View File

@@ -1,41 +0,0 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.service.config;
import java.lang.reflect.Proxy;
import com.rogiel.httpchannel.util.transformer.Transformer;
/**
* This is an flag interface to indicate that an certain Interface is the
* configuration for the service.<br>
* <br>
* Every service must create an <tt>interface</tt> 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.<br>
* <br>
* 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 {
}

View File

@@ -1,113 +0,0 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.service.config;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;
import com.rogiel.httpchannel.util.transformer.TransformerFactory;
/**
* Helper class for {@link ServiceConfiguration} system.
*
* @author Rogiel
* @since 1.0
*/
public class ServiceConfigurationHelper {
/**
* Creates a Proxy Class that returns all the default values of
* configuration interfaces. The values are mapped by
* {@link ServiceConfigurationProperty} annotation.
*
* @param <T>
* the interface extending {@link ServiceConfiguration}. Service
* specific.
* @param type
* the type Class representing T.
* @return the proxied {@link ServiceConfiguration} instance.
*/
@SuppressWarnings("unchecked")
public static <T extends ServiceConfiguration> T defaultConfiguration(
Class<T> type) {
return (T) Proxy.newProxyInstance(
ServiceConfiguration.class.getClassLoader(),
new Class<?>[] { type }, new InvocationHandler() {
@Override
public Object invoke(Object object, Method method,
Object[] arguments) throws Throwable {
final ServiceConfigurationProperty property = method
.getAnnotation(ServiceConfigurationProperty.class);
if (property != null)
return TransformerFactory.getTransformer(
method.getReturnType()).transform(
property.defaultValue());
return null;
}
});
}
/**
* Creates a Proxy Class that returns all the default values of
* configuration interfaces. The values are mapped by
* {@link ServiceConfigurationProperty} annotation.
*
* @param <T>
* the interface extending {@link ServiceConfiguration}. Service
* specific.
* @param type
* the type Class representing T.
* @return the proxied {@link ServiceConfiguration} instance.
* @throws IOException
* @throws FileNotFoundException
*/
@SuppressWarnings("unchecked")
public static <T extends ServiceConfiguration> T file(Class<T> type,
File file) throws FileNotFoundException, IOException {
final Properties properties = new Properties();
properties.load(new FileInputStream(file));
return (T) Proxy.newProxyInstance(
ServiceConfiguration.class.getClassLoader(),
new Class<?>[] { type }, new InvocationHandler() {
@Override
public Object invoke(Object object, Method method,
Object[] arguments) throws Throwable {
final ServiceConfigurationProperty property = method
.getAnnotation(ServiceConfigurationProperty.class);
if (property != null)
return TransformerFactory.getTransformer(
method.getReturnType()).transform(
get(property));
return null;
}
private String get(ServiceConfigurationProperty property) {
String value = properties.getProperty(property.key());
if (value == null)
value = property.defaultValue();
return value;
}
});
}
}

View File

@@ -1,51 +0,0 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.service.config;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation that defines the default value for an {@link ServiceConfiguration}
* method.<br>
* <br>
* <h1>Usage example</h1>
*
* <pre>
* public interface DummyServiceConfiguration extends ServiceConfiguration {
* &#064;ServiceConfigurationProperty(defaultValue = &quot;true&quot;)
* boolean retryAllowed();
* }
* </pre>
*
* The default implementation created by
* {@link ServiceConfigurationHelper#defaultConfiguration()} will always return
* the <tt>defaultValue</tt>.
*
* @author Rogiel
* @version 1.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface ServiceConfigurationProperty {
String key();
String defaultValue();
}

View File

@@ -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 <a href="http://www.rogiel.com">Rogiel</a>
*/
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);
}
}

View File

@@ -14,42 +14,49 @@
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.util.transformer;
package com.rogiel.httpchannel.service.exception;
import com.rogiel.httpchannel.captcha.CaptchaResolver;
/**
* @author Rogiel
* @since 1.0
* Exception thrown if the {@link CaptchaResolver} has returned an invalid
* captcha
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class TransformationException extends Exception {
public class UnresolvedCaptchaException extends ChannelServiceException {
private static final long serialVersionUID = 1L;
public TransformationException() {
/**
* Creates a new empty instance of this exception
*/
public UnresolvedCaptchaException() {
super();
}
/**
* @param message
* the message
* @param cause
* the root cause
*/
public UnresolvedCaptchaException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
* the message
*/
public TransformationException(String message) {
public UnresolvedCaptchaException(String message) {
super(message);
}
/**
* @param cause
* the cause
* the root cause
*/
public TransformationException(Throwable cause) {
public UnresolvedCaptchaException(Throwable cause) {
super(cause);
}
/**
* @param message
* the message
* @param cause
* the cause
*/
public TransformationException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,38 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.service.helper;
import com.rogiel.httpchannel.service.AuthenticationService;
import com.rogiel.httpchannel.service.Authenticator;
import com.rogiel.httpchannel.service.Authenticator.AuthenticatorConfiguration;
import com.rogiel.httpchannel.service.Credential;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class AuthenticationServices {
public static <S extends AuthenticationService<C>, C extends AuthenticatorConfiguration> Authenticator<C> authenticate(
S service, C configuration, String username, String password) {
return service.getAuthenticator(new Credential(username, password),
configuration);
}
public static <S extends AuthenticationService<C>, C extends AuthenticatorConfiguration> Authenticator<C> authenticate(
S service, String username, String password) {
return service.getAuthenticator(new Credential(username, password));
}
}

View File

@@ -14,19 +14,19 @@
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.service.captcha;
package com.rogiel.httpchannel.service.helper;
import java.io.IOException;
import java.net.URL;
import com.rogiel.httpchannel.service.DownloadService;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public interface CaptchaResolver {
/**
* Passes an captcha by parameter and waits for the response of the
* challenge.
*
* @param captcha
* the captcha challenge
*/
String resolve(Captcha captcha);
public class DownloadServices {
public static boolean canDownload(DownloadService<?> service, URL url)
throws IOException {
return service.matchURL(url);
}
}

View File

@@ -14,12 +14,16 @@
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.service;
package com.rogiel.httpchannel.service.helper;
import java.net.URL;
import java.util.Iterator;
import java.util.ServiceLoader;
import com.rogiel.httpchannel.service.DownloadService;
import com.rogiel.httpchannel.service.Service;
import com.rogiel.httpchannel.service.ServiceID;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
@@ -43,12 +47,12 @@ public class Services {
* the URL
* @return the matched service
*/
public static DownloadService matchURL(URL url) {
public static DownloadService<?> matchURL(URL url) {
for (final Service service : iterate()) {
if (!(service instanceof DownloadService))
continue;
if (((DownloadService) service).matchURL(url))
return (DownloadService) service;
if (((DownloadService<?>) service).matchURL(url))
return (DownloadService<?>) service;
}
return null;
}

View File

@@ -14,37 +14,34 @@
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.service;
package com.rogiel.httpchannel.service.helper;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import com.rogiel.httpchannel.service.UploadService;
import com.rogiel.httpchannel.service.Uploader;
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class ServiceHelper {
private final Service service;
/**
* @param service
* the service
*/
public ServiceHelper(Service service) {
this.service = service;
public class UploadServices {
public static <S extends UploadService<C>, C extends UploaderConfiguration> Uploader<C> upload(
S service, C configuration, Path path) throws IOException {
return service.getUploader(path.getFileName().toString(),
Files.size(path), configuration);
}
public UploadChannel upload(Path path, String description)
throws IOException {
return ((UploadService) service).getUploader(
path.getFileName().toString(), Files.size(path), description)
.upload();
public static <S extends UploadService<C>, C extends UploaderConfiguration> Uploader<C> upload(
S service, Path path) throws IOException {
return service.getUploader(path.getFileName().toString(),
Files.size(path));
}
public UploadChannel upload(File file, String description)
public static boolean canUpload(UploadService<?> service, Path path)
throws IOException {
return ((UploadService) service).getUploader(file.getName(),
file.length(), description).upload();
return service.getMaximumFilesize() >= Files.size(path);
}
}

View File

@@ -1,25 +0,0 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.util.transformer;
/**
* @author rogiel
*
*/
public interface Transformer<O> {
O transform(String data) throws TransformationException;
}

View File

@@ -1,48 +0,0 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.util.transformer;
import java.net.URL;
import com.rogiel.httpchannel.util.transformer.impl.BooleanTransformer;
import com.rogiel.httpchannel.util.transformer.impl.IntegerTransformer;
import com.rogiel.httpchannel.util.transformer.impl.LongTransformer;
import com.rogiel.httpchannel.util.transformer.impl.StringTransformer;
import com.rogiel.httpchannel.util.transformer.impl.URLTransformer;
/**
* @author Rogiel
* @since 1.0
*/
public class TransformerFactory {
@SuppressWarnings("unchecked")
public static <T> Transformer<T> getTransformer(Class<T> type) {
if (String.class.isAssignableFrom(type)) {
return (Transformer<T>) new StringTransformer();
} else if (Boolean.class.isAssignableFrom(type) || type == Boolean.TYPE) {
return (Transformer<T>) new BooleanTransformer();
} else if (Integer.class.isAssignableFrom(type) || type == Integer.TYPE) {
return (Transformer<T>) new IntegerTransformer();
} else if (Long.class.isAssignableFrom(type) || type == Long.TYPE) {
return (Transformer<T>) new LongTransformer();
} else if (URL.class.isAssignableFrom(type)) {
return (Transformer<T>) new URLTransformer();
}
return null;
}
}

View File

@@ -1,30 +0,0 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.util.transformer.impl;
import com.rogiel.httpchannel.util.transformer.Transformer;
/**
* @author rogiel
*
*/
public class BooleanTransformer implements Transformer<Boolean> {
@Override
public Boolean transform(String data) {
return Boolean.parseBoolean(data);
}
}

View File

@@ -1,30 +0,0 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.util.transformer.impl;
import com.rogiel.httpchannel.util.transformer.Transformer;
/**
* @author rogiel
*
*/
public class IntegerTransformer implements Transformer<Integer> {
@Override
public Integer transform(String data) {
return Integer.parseInt(data);
}
}

View File

@@ -1,30 +0,0 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.util.transformer.impl;
import com.rogiel.httpchannel.util.transformer.Transformer;
/**
* @author rogiel
*
*/
public class LongTransformer implements Transformer<Long> {
@Override
public Long transform(String data) {
return Long.parseLong(data);
}
}

View File

@@ -1,30 +0,0 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.util.transformer.impl;
import com.rogiel.httpchannel.util.transformer.Transformer;
/**
* @author rogiel
*
*/
public class StringTransformer implements Transformer<String> {
@Override
public String transform(String data) {
return data;
}
}

View File

@@ -1,39 +0,0 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.util.transformer.impl;
import java.net.MalformedURLException;
import java.net.URL;
import com.rogiel.httpchannel.util.transformer.TransformationException;
import com.rogiel.httpchannel.util.transformer.Transformer;
/**
* @author rogiel
*
*/
public class URLTransformer implements Transformer<URL> {
@Override
public URL transform(String data) throws TransformationException {
try {
return new URL(data);
} catch (MalformedURLException e) {
throw new TransformationException(e);
}
}
}