mirror of
https://github.com/Rogiel/httpchannel
synced 2025-12-06 07:32:50 +00:00
Adds service implementation documentation
This commit is contained in:
@@ -82,6 +82,25 @@ public interface Authenticator<C extends AuthenticatorConfiguration> {
|
|||||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
*/
|
*/
|
||||||
public interface AuthenticatorConfiguration {
|
public interface AuthenticatorConfiguration {
|
||||||
|
/**
|
||||||
|
* Checks whether the configuration object can be casted to
|
||||||
|
* <code>type</code>
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the casting type
|
||||||
|
* @return <code>true</code> if this object can be casted to
|
||||||
|
* <code>type</code>
|
||||||
|
*/
|
||||||
|
boolean is(Class<? extends AuthenticatorConfiguration> type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Casts this object to <code>type</code>. If cannot be casted,
|
||||||
|
* <code>null</code> is returned.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the casting type
|
||||||
|
* @return the casted configuration
|
||||||
|
*/
|
||||||
|
<T extends AuthenticatorConfiguration> T as(Class<T> type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,6 +208,25 @@ public interface Downloader<C extends DownloaderConfiguration> {
|
|||||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
*/
|
*/
|
||||||
public interface DownloaderConfiguration {
|
public interface DownloaderConfiguration {
|
||||||
|
/**
|
||||||
|
* Checks whether the configuration object can be casted to
|
||||||
|
* <code>type</code>
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the casting type
|
||||||
|
* @return <code>true</code> if this object can be casted to
|
||||||
|
* <code>type</code>
|
||||||
|
*/
|
||||||
|
boolean is(Class<? extends DownloaderConfiguration> type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Casts this object to <code>type</code>. If cannot be casted,
|
||||||
|
* <code>null</code> is returned.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the casting type
|
||||||
|
* @return the casted configuration
|
||||||
|
*/
|
||||||
|
<T extends DownloaderConfiguration> T as(Class<T> type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,26 @@ public interface Uploader<C extends UploaderConfiguration> {
|
|||||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
*/
|
*/
|
||||||
public interface UploaderConfiguration {
|
public interface UploaderConfiguration {
|
||||||
|
/**
|
||||||
|
* Checks whether the configuration object can be casted to
|
||||||
|
* <code>type</code>
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the casting type
|
||||||
|
* @return <code>true</code> if this object can be casted to
|
||||||
|
* <code>type</code>
|
||||||
|
*/
|
||||||
|
boolean is(Class<? extends UploaderConfiguration> type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Casts this object to <code>type</code>. If cannot be casted,
|
||||||
|
* <code>null</code> is returned.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* the casting type
|
||||||
|
* @return the casted configuration
|
||||||
|
*/
|
||||||
|
<T extends UploaderConfiguration> T as(Class<T> type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -35,4 +35,14 @@ public final class NullAuthenticatorConfiguration implements
|
|||||||
|
|
||||||
private NullAuthenticatorConfiguration() {
|
private NullAuthenticatorConfiguration() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean is(Class<? extends AuthenticatorConfiguration> type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends AuthenticatorConfiguration> T as(Class<T> type) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,4 +34,14 @@ public final class NullDownloaderConfiguration implements
|
|||||||
|
|
||||||
private NullDownloaderConfiguration() {
|
private NullDownloaderConfiguration() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean is(Class<? extends DownloaderConfiguration> type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends DownloaderConfiguration> T as(Class<T> type) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,4 +33,14 @@ public final class NullUploaderConfiguration implements UploaderConfiguration {
|
|||||||
|
|
||||||
private NullUploaderConfiguration() {
|
private NullUploaderConfiguration() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean is(Class<? extends UploaderConfiguration> type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends UploaderConfiguration> T as(Class<T> type) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.util.ServiceLoader;
|
|||||||
import com.rogiel.httpchannel.service.DownloadService;
|
import com.rogiel.httpchannel.service.DownloadService;
|
||||||
import com.rogiel.httpchannel.service.Service;
|
import com.rogiel.httpchannel.service.Service;
|
||||||
import com.rogiel.httpchannel.service.ServiceID;
|
import com.rogiel.httpchannel.service.ServiceID;
|
||||||
|
import com.rogiel.httpchannel.service.UploadService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
@@ -74,6 +75,36 @@ public class Services {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to detect which service has the given <tt>id</tt>
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* the service id
|
||||||
|
* @return the matched service
|
||||||
|
*/
|
||||||
|
public static UploadService<?> getUploadService(ServiceID id) {
|
||||||
|
for (final Service service : iterate()) {
|
||||||
|
if (service.getServiceID().equals(id))
|
||||||
|
return (UploadService<?>) service;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to detect which service has the given <tt>id</tt>
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* the service id
|
||||||
|
* @return the matched service
|
||||||
|
*/
|
||||||
|
public static DownloadService<?> getDownloadService(ServiceID id) {
|
||||||
|
for (final Service service : iterate()) {
|
||||||
|
if (service.getServiceID().equals(id))
|
||||||
|
return (DownloadService<?>) service;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Iterable} instance to iterate over services
|
* Creates a new {@link Iterable} instance to iterate over services
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -18,10 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
package com.rogiel.httpchannel.service.impl;
|
package com.rogiel.httpchannel.service.impl;
|
||||||
|
|
||||||
|
import com.rogiel.httpchannel.service.AbstractDownloaderConfiguration;
|
||||||
import com.rogiel.httpchannel.service.Downloader.DownloaderConfiguration;
|
import com.rogiel.httpchannel.service.Downloader.DownloaderConfiguration;
|
||||||
|
|
||||||
public class MegaUploadDownloaderConfiguration implements
|
public class MegaUploadDownloaderConfiguration extends
|
||||||
DownloaderConfiguration {
|
AbstractDownloaderConfiguration implements DownloaderConfiguration {
|
||||||
private boolean respectWaitTime = true;
|
private boolean respectWaitTime = true;
|
||||||
|
|
||||||
public boolean getRespectWaitTime() {
|
public boolean getRespectWaitTime() {
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public class MegaUploadService extends AbstractHttpService implements Service,
|
|||||||
*/
|
*/
|
||||||
public static final ServiceID SERVICE_ID = ServiceID.create("megaupload");
|
public static final ServiceID SERVICE_ID = ServiceID.create("megaupload");
|
||||||
|
|
||||||
private static final Pattern UPLOAD_URI_PATTERN = Pattern
|
private static final Pattern UPLOAD_URL_PATTERN = Pattern
|
||||||
.compile("http://www([0-9]*)\\.megaupload\\.com/upload_done\\.php\\?UPLOAD_IDENTIFIER=[0-9]*");
|
.compile("http://www([0-9]*)\\.megaupload\\.com/upload_done\\.php\\?UPLOAD_IDENTIFIER=[0-9]*");
|
||||||
|
|
||||||
private static final Pattern DOWNLOAD_DIRECT_LINK_PATTERN = Pattern
|
private static final Pattern DOWNLOAD_DIRECT_LINK_PATTERN = Pattern
|
||||||
@@ -217,7 +217,7 @@ public class MegaUploadService extends AbstractHttpService implements Service,
|
|||||||
logger.debug("Starting upload to megaupload.com");
|
logger.debug("Starting upload to megaupload.com");
|
||||||
final HTMLPage page = get("http://www.megaupload.com/multiupload/")
|
final HTMLPage page = get("http://www.megaupload.com/multiupload/")
|
||||||
.asPage();
|
.asPage();
|
||||||
final String uri = page.findFormAction(UPLOAD_URI_PATTERN);
|
final String uri = page.findFormAction(UPLOAD_URL_PATTERN);
|
||||||
logger.debug("Upload URI is {}", uri);
|
logger.debug("Upload URI is {}", uri);
|
||||||
|
|
||||||
final LinkedUploadChannel channel = createLinkedChannel(this);
|
final LinkedUploadChannel channel = createLinkedChannel(this);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.rogiel.httpchannel.service.impl;
|
package com.rogiel.httpchannel.service.impl;
|
||||||
|
|
||||||
|
import com.rogiel.httpchannel.service.AbstractUploaderConfiguration;
|
||||||
import com.rogiel.httpchannel.service.Uploader.DescriptionableUploaderConfiguration;
|
import com.rogiel.httpchannel.service.Uploader.DescriptionableUploaderConfiguration;
|
||||||
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
|
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
|
||||||
import com.rogiel.httpchannel.service.impl.MegaUploadService.UploaderImpl;
|
import com.rogiel.httpchannel.service.impl.MegaUploadService.UploaderImpl;
|
||||||
@@ -27,7 +28,8 @@ import com.rogiel.httpchannel.service.impl.MegaUploadService.UploaderImpl;
|
|||||||
*
|
*
|
||||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
*/
|
*/
|
||||||
public class MegaUploadUploaderConfiguration implements UploaderConfiguration,
|
public class MegaUploadUploaderConfiguration extends
|
||||||
|
AbstractUploaderConfiguration implements UploaderConfiguration,
|
||||||
DescriptionableUploaderConfiguration {
|
DescriptionableUploaderConfiguration {
|
||||||
/**
|
/**
|
||||||
* The upload description
|
* The upload description
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ package com.rogiel.httpchannel.service.impl;
|
|||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
import com.rogiel.httpchannel.service.AbstractUploaderConfiguration;
|
||||||
import com.rogiel.httpchannel.service.Uploader.DescriptionableUploaderConfiguration;
|
import com.rogiel.httpchannel.service.Uploader.DescriptionableUploaderConfiguration;
|
||||||
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
|
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
|
||||||
import com.rogiel.httpchannel.service.impl.MultiUploadService.UploaderImpl;
|
import com.rogiel.httpchannel.service.impl.MultiUploadService.UploaderImpl;
|
||||||
@@ -29,7 +30,8 @@ import com.rogiel.httpchannel.service.impl.MultiUploadService.UploaderImpl;
|
|||||||
*
|
*
|
||||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
*/
|
*/
|
||||||
public class MultiUploadUploaderConfiguration implements UploaderConfiguration,
|
public class MultiUploadUploaderConfiguration extends
|
||||||
|
AbstractUploaderConfiguration implements UploaderConfiguration,
|
||||||
DescriptionableUploaderConfiguration {
|
DescriptionableUploaderConfiguration {
|
||||||
/**
|
/**
|
||||||
* The upload description
|
* The upload description
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.rogiel.httpchannel.service.impl;
|
package com.rogiel.httpchannel.service.impl;
|
||||||
|
|
||||||
|
import com.rogiel.httpchannel.service.AbstractUploaderConfiguration;
|
||||||
import com.rogiel.httpchannel.service.Uploader.DescriptionableUploaderConfiguration;
|
import com.rogiel.httpchannel.service.Uploader.DescriptionableUploaderConfiguration;
|
||||||
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
|
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
|
||||||
|
|
||||||
@@ -26,8 +27,8 @@ import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
|
|||||||
*
|
*
|
||||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
*/
|
*/
|
||||||
public class ZShareUploaderConfiguration implements UploaderConfiguration,
|
public class ZShareUploaderConfiguration extends AbstractUploaderConfiguration
|
||||||
DescriptionableUploaderConfiguration {
|
implements UploaderConfiguration, DescriptionableUploaderConfiguration {
|
||||||
/**
|
/**
|
||||||
* The upload description
|
* The upload description
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -15,11 +15,13 @@
|
|||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>httpchannel-service-megaupload</module>
|
<module>httpchannel-service-megaupload</module>
|
||||||
<module>httpchannel-service-hotfile</module>
|
|
||||||
<module>httpchannel-service-multiupload</module>
|
<module>httpchannel-service-multiupload</module>
|
||||||
<module>httpchannel-service-zshare</module>
|
<module>httpchannel-service-uploadking</module>
|
||||||
|
<module>httpchannel-service-uploadhere</module>
|
||||||
|
<module>httpchannel-service-depositfiles</module>
|
||||||
|
<module>httpchannel-service-hotfile</module>
|
||||||
<module>httpchannel-service-filesonic</module>
|
<module>httpchannel-service-filesonic</module>
|
||||||
|
<module>httpchannel-service-zshare</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|||||||
4
httpchannel-service/src/site/site.xml
Normal file
4
httpchannel-service/src/site/site.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/DECORATION/1.1.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/DECORATION/1.1.0 http://maven.apache.org/xsd/decoration-1.1.0.xsd">
|
||||||
|
</project>
|
||||||
265
httpchannel-service/src/site/xdoc/implementing-services.xml
Normal file
265
httpchannel-service/src/site/xdoc/implementing-services.xml
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||||
|
<properties>
|
||||||
|
<title>Home</title>
|
||||||
|
<author email="rogiel@rogiel.com">Rogiel Sulzbach</author>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- The body of the document contains a number of sections -->
|
||||||
|
<section name="Implementing services">
|
||||||
|
<p>Implementing services is really easy. There's a lot of abstraction
|
||||||
|
done in the service layer, that it donesn't even look that you are
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In order to implement a new service, you first need to create a
|
||||||
|
class that implements
|
||||||
|
<b>Service</b>
|
||||||
|
. This interface provides basic information about the service, such
|
||||||
|
as version and ID. This however, is not enough and you need to
|
||||||
|
implement other specific interfaces for each type of behavior you
|
||||||
|
want:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<b>UploadService</b>
|
||||||
|
: implements support for
|
||||||
|
<b>UploadChannel</b>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<b>DownloadService</b>
|
||||||
|
: implements support for
|
||||||
|
<b>DownloadChannel</b>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<b>AuthenticationService</b>
|
||||||
|
: implements support for account authentication (such as premium
|
||||||
|
accounts)
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Let's first implement an
|
||||||
|
<b>UploadService</b>
|
||||||
|
for
|
||||||
|
<a href="http://www.megaupload.com/" target="_blank">megaupload.com</a>
|
||||||
|
site:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<source><![CDATA[public class MegaUploadService extends AbstractHttpService implements Service,
|
||||||
|
UploadService<MegaUploadUploaderConfiguration>]]></source>
|
||||||
|
|
||||||
|
<small>
|
||||||
|
We extend
|
||||||
|
<b>AbstractHttpService</b>
|
||||||
|
which provides several handy methods for HTTP requests, it also
|
||||||
|
handles all the cookies for us, so we don't need to deal with
|
||||||
|
anything else but the HTML parsing.
|
||||||
|
</small>
|
||||||
|
|
||||||
|
<p>Now we add a few static fields that are gonna be used later on:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<source><![CDATA[public static final ServiceID SERVICE_ID = ServiceID.create("megaupload");
|
||||||
|
private static final Pattern UPLOAD_URL_PATTERN = Pattern
|
||||||
|
.compile("http://www([0-9]*)\\.megaupload\\.com/upload_done\\.php\\?UPLOAD_IDENTIFIER=[0-9]*");
|
||||||
|
private static final Pattern DOWNLOAD_URI_PATTERN = Pattern
|
||||||
|
.compile("http://www\\.megaupload\\.com/\\?d=([A-Za-z0-9]*)");]]></source>
|
||||||
|
|
||||||
|
<small>Those patterns will match the URLs we need to upload the file
|
||||||
|
and find the download link.
|
||||||
|
</small>
|
||||||
|
|
||||||
|
<source><![CDATA[
|
||||||
|
@Override
|
||||||
|
public ServiceID getServiceID() {
|
||||||
|
return SERVICE_ID; // thats the public static field we created before!
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMajorVersion() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinorVersion() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CapabilityMatrix<ServiceMode> getPossibleServiceModes() {
|
||||||
|
return new CapabilityMatrix<ServiceMode>(ServiceMode.UNAUTHENTICATED);
|
||||||
|
}]]></source>
|
||||||
|
|
||||||
|
<small>
|
||||||
|
This simple service implementation does not support authentication.
|
||||||
|
As such, the only supported mode is
|
||||||
|
<b>ServiceMode.UNAUTHENTICATED</b>
|
||||||
|
.
|
||||||
|
</small>
|
||||||
|
|
||||||
|
<source><![CDATA[
|
||||||
|
@Override
|
||||||
|
public Uploader<MegaUploadUploaderConfiguration> getUploader(
|
||||||
|
String filename, long filesize,
|
||||||
|
MegaUploadUploaderConfiguration configuration) {
|
||||||
|
return new UploaderImpl(filename, filesize, configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Uploader<MegaUploadUploaderConfiguration> getUploader(
|
||||||
|
String filename, long filesize) {
|
||||||
|
return getUploader(filename, filesize, newUploaderConfiguration());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MegaUploadUploaderConfiguration newUploaderConfiguration() {
|
||||||
|
return new MegaUploadUploaderConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getMaximumFilesize() {
|
||||||
|
return Filesizes.gb(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedExtensions() {
|
||||||
|
return null; // all extensions are suppoted, null need to be returned then
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CapabilityMatrix<UploaderCapability> getUploadCapabilities() {
|
||||||
|
return new CapabilityMatrix<UploaderCapability>(UploaderCapability.UNAUTHENTICATED_UPLOAD);
|
||||||
|
}]]></source>
|
||||||
|
|
||||||
|
<small>
|
||||||
|
Again, this simple service implementation does not support
|
||||||
|
authentication.
|
||||||
|
As such, the only
|
||||||
|
<b>upload capability</b>
|
||||||
|
supported is
|
||||||
|
<b>UploaderCapability.UNAUTHENTICATED</b>
|
||||||
|
.
|
||||||
|
</small>
|
||||||
|
|
||||||
|
<source><![CDATA[
|
||||||
|
protected class UploaderImpl extends
|
||||||
|
AbstractUploader<MegaUploadUploaderConfiguration> implements
|
||||||
|
Uploader<MegaUploadUploaderConfiguration>,
|
||||||
|
LinkedUploadChannelCloseCallback {
|
||||||
|
private Future<String> uploadFuture;
|
||||||
|
|
||||||
|
public UploaderImpl(String filename, long filesize,
|
||||||
|
MegaUploadUploaderConfiguration configuration) {
|
||||||
|
super(MegaUploadService.this, filename, filesize, configuration);
|
||||||
|
}]]></source>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Notice we also implement LinkedUploadChannelCloseCallback. The
|
||||||
|
single method in this interface is called to finish the upload and
|
||||||
|
return the download link. Also
|
||||||
|
<b>AbstractUploader</b>
|
||||||
|
is implemented because it provides a lot of handy methods that can
|
||||||
|
shortcut the implementation.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<source><![CDATA[
|
||||||
|
@Override
|
||||||
|
public UploadChannel openChannel() throws IOException {
|
||||||
|
logger.debug("Starting upload to megaupload.com");
|
||||||
|
final HTMLPage page = get("http://www.megaupload.com/multiupload/")
|
||||||
|
.asPage();
|
||||||
|
final String uri = page.findFormAction(UPLOAD_URL_PATTERN);
|
||||||
|
logger.debug("Upload URI is {}", uri);
|
||||||
|
final LinkedUploadChannel channel = createLinkedChannel(this);
|
||||||
|
|
||||||
|
uploadFuture = multipartPost(uri)
|
||||||
|
.parameter("multimessage_0", configuration.description())
|
||||||
|
.parameter("multifile_0", channel).asStringAsync();
|
||||||
|
return waitChannelLink(channel, uploadFuture);
|
||||||
|
}]]></source>
|
||||||
|
|
||||||
|
<p>Here is a bit implementation specific: we load the megaupload.com
|
||||||
|
page and return it as an HTNLPage. An HTMLPage is an parsed version
|
||||||
|
of the page, it contains several methods that provide methods for
|
||||||
|
finding form urls and links.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Now, once we load the page, we use the HTMLPage object to find a
|
||||||
|
form action using an Pattern with
|
||||||
|
<b>findFormAction</b>
|
||||||
|
. That is the URI we will use to do the upload.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>The a new UploadChannel is created, internally it uses an
|
||||||
|
LinkedUploadChannel which is a specific type of channel that gets
|
||||||
|
linked with another channel, and acts as some kind of "proxy"
|
||||||
|
channel.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Here the fun part, we create a new "multipart HTTP request".
|
||||||
|
Multipart requests generally contain binary data, so we need to use
|
||||||
|
those to implement the service. Upload parameters are bound to the
|
||||||
|
request using a chain method, this makes code compact and easy to
|
||||||
|
read.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Finally, we execute
|
||||||
|
<b>asStringAsync</b>
|
||||||
|
that will return the page as an java String and executes the request
|
||||||
|
asynchronously (that is, it is not going to block, but will execute
|
||||||
|
on another Thread.). The future object returned is stored into an
|
||||||
|
field, because it will be used later by the
|
||||||
|
<b>finish()</b>
|
||||||
|
method.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Finally, we wait for the channel to be effectivelly linked and
|
||||||
|
return it. Channel link may take some time until the HTTP request
|
||||||
|
estabilishes the connection and is ready to receive data, that is
|
||||||
|
why waiting for the link is of extreme importance.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Now the channel is returned to the user which will write data and
|
||||||
|
perform all kind of cool things with the channel. When the user
|
||||||
|
calls the
|
||||||
|
<b>close()</b>
|
||||||
|
method, the
|
||||||
|
<b>finish()</b>
|
||||||
|
method (defined by
|
||||||
|
<b>LinkedUploadChannelCloseCallback</b>
|
||||||
|
) is invoked and the upload is finished.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<source><![CDATA[
|
||||||
|
@Override
|
||||||
|
public String finish() throws IOException {
|
||||||
|
try {
|
||||||
|
return PatternUtils.find(DOWNLOAD_URI_PATTERN,
|
||||||
|
uploadFuture.get());
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return null;
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
throw (IOException) e.getCause();
|
||||||
|
}
|
||||||
|
}]]></source>
|
||||||
|
|
||||||
|
<p>This portion of code is fairly easy to understand, it uses the
|
||||||
|
future that we previously created to get the resulting page. This
|
||||||
|
does not need to be an string, it can be any of the supported types.
|
||||||
|
Since MegaUpload retuns a JSON string, we need to use a string to
|
||||||
|
match it against an Pattern. Once the URL is matched, it is
|
||||||
|
returned, if no link is found, null should be returned and the
|
||||||
|
channel close() method will deal will all the exception throwing.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Your service is now ready. You can starting using it!</p>
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
|
</document>
|
||||||
115
httpchannel-service/src/site/xdoc/service-table.xml
Normal file
115
httpchannel-service/src/site/xdoc/service-table.xml
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||||
|
<properties>
|
||||||
|
<title>Home</title>
|
||||||
|
<author email="rogiel@rogiel.com">Rogiel Sulzbach</author>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- The body of the document contains a number of sections -->
|
||||||
|
<section name="List of available services">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Service Name</th>
|
||||||
|
<th>Service ID</th>
|
||||||
|
<th>Authentication</th>
|
||||||
|
<th colspan="2">Upload</th>
|
||||||
|
<th colspan="2">Download</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="./httpchannel-service-depositfiles/">DepositFiles</a>
|
||||||
|
</td>
|
||||||
|
<td>depositfiles</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>up to 1GB</td>
|
||||||
|
<td colspan="2">No</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="./httpchannel-service-filesonic/">FileSonic</a>
|
||||||
|
</td>
|
||||||
|
<td>filesonic</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>up to 1GB</td>
|
||||||
|
<td colspan="2">No</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="./httpchannel-service-hotfile/">HotFile</a>
|
||||||
|
</td>
|
||||||
|
<td>hotfile</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>up to 1GB</td>
|
||||||
|
<td colspan="2">No</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="./httpchannel-service-megaupload/">MegaUpload</a>
|
||||||
|
</td>
|
||||||
|
<td>megaupload</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>
|
||||||
|
up to 1GB non-premium, 2GB premium
|
||||||
|
<br />
|
||||||
|
<b>DescriptionableUploaderConfiguration</b>
|
||||||
|
</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>resumable, extended configuration</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="./httpchannel-service-multiupload/">MultiUpload</a>
|
||||||
|
</td>
|
||||||
|
<td>multiupload</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>
|
||||||
|
up to 1GB
|
||||||
|
<br />
|
||||||
|
extended configuration,
|
||||||
|
<b>DescriptionableUploaderConfiguration</b>
|
||||||
|
</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>resumable</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="./httpchannel-service-uploadhere/">UploadHere</a>
|
||||||
|
</td>
|
||||||
|
<td>uploadhere</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>up to 1GB</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>resumable, captcha</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="./httpchannel-service-uploadking/">UploadKing</a>
|
||||||
|
</td>
|
||||||
|
<td>uploadking</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>up to 1GB</td>
|
||||||
|
<td>Yes</td>
|
||||||
|
<td>resumable, captcha</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
|
</document>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.rogiel.httpchannel.service;
|
||||||
|
|
||||||
|
import com.rogiel.httpchannel.service.Authenticator.AuthenticatorConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AbstractAuthenticatorConfiguration implements
|
||||||
|
AuthenticatorConfiguration {
|
||||||
|
@Override
|
||||||
|
public boolean is(Class<? extends AuthenticatorConfiguration> type) {
|
||||||
|
return type.isAssignableFrom(this.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends AuthenticatorConfiguration> T as(Class<T> type) {
|
||||||
|
if (!is(type))
|
||||||
|
return null;
|
||||||
|
return type.cast(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.rogiel.httpchannel.service;
|
||||||
|
|
||||||
|
import com.rogiel.httpchannel.service.Downloader.DownloaderConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AbstractDownloaderConfiguration implements DownloaderConfiguration {
|
||||||
|
@Override
|
||||||
|
public boolean is(Class<? extends DownloaderConfiguration> type) {
|
||||||
|
return type.isAssignableFrom(this.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends DownloaderConfiguration> T as(Class<T> type) {
|
||||||
|
if (!is(type))
|
||||||
|
return null;
|
||||||
|
return type.cast(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.rogiel.httpchannel.service;
|
||||||
|
|
||||||
|
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AbstractUploaderConfiguration implements UploaderConfiguration {
|
||||||
|
@Override
|
||||||
|
public boolean is(Class<? extends UploaderConfiguration> type) {
|
||||||
|
return type.isAssignableFrom(this.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends UploaderConfiguration> T as(Class<T> type) {
|
||||||
|
if (!is(type))
|
||||||
|
return null;
|
||||||
|
return type.cast(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.rogiel.httpchannel.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Filesizes {
|
||||||
|
public static long kb(long kb) {
|
||||||
|
return kb * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long mb(long mb) {
|
||||||
|
return kb(mb) * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long gb(long gb) {
|
||||||
|
return mb(gb) * 1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/site/site.xml
Normal file
32
src/site/site.xml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/DECORATION/1.1.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/DECORATION/1.1.0 http://maven.apache.org/xsd/decoration-1.1.0.xsd">
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<menu ref="parent" inherit="top" />
|
||||||
|
|
||||||
|
<menu name="API" inherit="top">
|
||||||
|
<item name="API Javadoc" href="/httpchannel-api/apidocs/"
|
||||||
|
target="_blank" />
|
||||||
|
<item name="API Sources" href="/httpchannel-api/xref/" />
|
||||||
|
</menu>
|
||||||
|
|
||||||
|
<menu name="Services" inherit="bottom">
|
||||||
|
<item name="Implementing services" href="/httpchannel-service/implementing-services.html" />
|
||||||
|
<item name="Table of supported services" href="/httpchannel-service/service-table.html" />
|
||||||
|
<item name="Supported services" collapse="true" href="/httpchannel-service/service-table.html">
|
||||||
|
<item name="DepositFiles" href="/httpchannel-service/httpchannel-service-depositfiles" />
|
||||||
|
<item name="FileSonic" href="/httpchannel-service/httpchannel-service-filesonic" />
|
||||||
|
<item name="HotFile" href="/httpchannel-service/httpchannel-service-hotfile" />
|
||||||
|
<item name="MegaUpload" href="/httpchannel-service/httpchannel-service-megaupload" />
|
||||||
|
<item name="MultiUpload" href="/httpchannel-service/httpchannel-service-multiupload" />
|
||||||
|
<item name="UploadHere" href="/httpchannel-service/httpchannel-service-uploadhere" />
|
||||||
|
<item name="UploadKing" href="/httpchannel-service/httpchannel-service-uploadking" />
|
||||||
|
</item>
|
||||||
|
</menu>
|
||||||
|
|
||||||
|
<menu ref="modules" inherit="bottom" />
|
||||||
|
|
||||||
|
<menu ref="reports" inherit="bottom" />
|
||||||
|
</body>
|
||||||
|
</project>
|
||||||
105
src/site/xdoc/index.xml
Normal file
105
src/site/xdoc/index.xml
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||||
|
<properties>
|
||||||
|
<title>Home</title>
|
||||||
|
<author email="rogiel@rogiel.com">Rogiel Sulzbach</author>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- The body of the document contains a number of sections -->
|
||||||
|
<section name="What is this?">
|
||||||
|
<p>
|
||||||
|
The HttpChannel library is a library that povides downloading and
|
||||||
|
uploading capaibilities to several share-sites (such as
|
||||||
|
<a href="http://www.megaupload.com/" target="_blank">MegaUpload</a>
|
||||||
|
and
|
||||||
|
<a href="http://www.filesonic.com/" target="_blank">FileSonic</a>
|
||||||
|
). Obviously, the API supports a lot more services, but those are
|
||||||
|
the most commonly used. Aside from that, the biggest point of the
|
||||||
|
library is its simple usage, you don't need to use any customized
|
||||||
|
API to perform download or uploads, you simply use the standard Java
|
||||||
|
NIO Channels for both upload and download.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<source><![CDATA[final UploadService<?> service = Services.getUploadService("megaupload");
|
||||||
|
final Uploader<?> uploader = UploadServices.upload(service, Path.get("test-file.txt"));
|
||||||
|
final UploadChannel channel = uploader.openChannel();
|
||||||
|
// now, you can perform any operation you want with this channel!
|
||||||
|
ChannelUtils.copy(inputChannel, channel);
|
||||||
|
// this may take some time, it will finish the upload and generate the download link
|
||||||
|
channel.close();
|
||||||
|
System.out.println("Download Link: "+channel.getDownloadLink());]]></source>
|
||||||
|
|
||||||
|
<subsection name="Really? That's it?">
|
||||||
|
<p>Yeah! This is the fastest way to start an upload, you can also
|
||||||
|
customize a bit your upload. MegaUpload supports upload
|
||||||
|
configuration, the most common configuration options has an
|
||||||
|
interface which all service that supports it should extent, see
|
||||||
|
above:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<source><![CDATA[final UploaderConfiguration config = uploader.getConfiguration();
|
||||||
|
if(config.is(DescriptionableUploaderConfiguration.class)) {
|
||||||
|
config.as(DescriptionableUploaderConfiguration.class).description("Hello world!");
|
||||||
|
}
|
||||||
|
// now, open the channel and go on!]]></source>
|
||||||
|
<p>You have two ways of setting and upload description. The way
|
||||||
|
showed previously, supports all the services which provide
|
||||||
|
description supported, howerver, if this is not intented, you can
|
||||||
|
cast it directly to the service configuration interface:
|
||||||
|
</p>
|
||||||
|
<source><![CDATA[final UploaderConfiguration config = uploader.getConfiguration();
|
||||||
|
if(config.is(MegaUploadUploaderConfiguration.class)) {
|
||||||
|
config.as(MegaUploadUploaderConfiguration.class).description("Hello world!");
|
||||||
|
}
|
||||||
|
// now, open the channel and go on!]]></source>
|
||||||
|
<small>Although this does not give any compilation error, this is
|
||||||
|
not the correct way to do. If you ever remove the MegaUpload
|
||||||
|
service, you compilation will break and you will need to fix this
|
||||||
|
manually. Also, changes to the internal service implementation
|
||||||
|
could change and your compilation would break, again!
|
||||||
|
</small>
|
||||||
|
<p>Now, only uploads to MegaUpload.com will have a description.
|
||||||
|
Aside
|
||||||
|
from that, all configuration objects have a default
|
||||||
|
description
|
||||||
|
value: "Uploaded by httpchannel". This cannot be
|
||||||
|
overriden and if
|
||||||
|
you want to, you need to set the description to all
|
||||||
|
services that
|
||||||
|
support description.
|
||||||
|
</p>
|
||||||
|
</subsection>
|
||||||
|
|
||||||
|
<subsection name="And what about CAPTCHAs?">
|
||||||
|
<p>
|
||||||
|
The library also support CAPTCHA solving, not automatically but
|
||||||
|
through
|
||||||
|
<a href="./httpchannel-captcha/">CAPTCHA solving services</a>
|
||||||
|
. To bind an
|
||||||
|
<b>CaptchaService</b>
|
||||||
|
to an HttpChannel service, all you need to do is:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<source><![CDATA[final CaptchaService captchaSercice = new CaptchaTraderService();
|
||||||
|
captchaService.authenticate("[your-captchatrader-username]", "[your-captchatrader-password or pubkey]");
|
||||||
|
service.setCaptchaService(captchaService);]]></source>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Now, all CAPTCHAs that need to be solved, will be forwarded to
|
||||||
|
<a href="http://www.captchatrader.com/">CaptchaTrader</a>
|
||||||
|
for solving.
|
||||||
|
</p>
|
||||||
|
</subsection>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section name="Implementing services">
|
||||||
|
<p>
|
||||||
|
To implement new services, you can follow
|
||||||
|
<a href="./httpchannel-service/implementing-services.html">this guide</a>
|
||||||
|
or look at the sources.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
|
</document>
|
||||||
Reference in New Issue
Block a user