1
0
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:
2012-01-18 17:13:36 -02:00
parent f8d5303f70
commit 35e2c2fc56
22 changed files with 754 additions and 11 deletions

View File

@@ -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);
} }
} }

View File

@@ -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);
} }
} }

View File

@@ -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);
} }
/** /**

View File

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

View File

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

View File

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

View File

@@ -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>
@@ -73,6 +74,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

View File

@@ -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() {

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

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

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

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