1
0
mirror of https://github.com/Rogiel/httpchannel synced 2025-12-05 23:22:51 +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

@@ -59,8 +59,8 @@
<groupId>org.htmlparser</groupId>
<artifactId>htmlparser</artifactId>
<version>2.1</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
</dependencies>
<name>HttpChannel/Service/Utilities</name>
<description>Module providing several utilities to service implementations. Though this module is not required to implement services, it contains several shortcuts that can help implementing services.</description>
</project>

View File

@@ -0,0 +1,47 @@
/**
*
*/
package com.rogiel.httpchannel.captcha;
import java.net.URL;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public abstract class AbstractImageCaptcha implements ImageCaptcha {
private final URL imageURL;
private final String ID;
private String answer;
private boolean automaticallyResolved;
public AbstractImageCaptcha(URL imageURL, String ID) {
this.imageURL = imageURL;
this.ID = ID;
}
@Override
public void setAnswer(String answer) {
this.answer = answer;
}
@Override
public String getAnswer() {
return answer;
}
@Override
public boolean wasAutomaticallyResolved() {
return automaticallyResolved;
}
@Override
public URL getImageURL() {
return imageURL;
}
public String getID() {
return ID;
}
}

View File

@@ -0,0 +1,54 @@
/**
*
*/
package com.rogiel.httpchannel.captcha;
import java.io.IOException;
import java.net.URL;
import com.rogiel.httpchannel.http.GetRequest;
import com.rogiel.httpchannel.http.HttpContext;
import com.rogiel.httpchannel.http.PostMultipartRequest;
import com.rogiel.httpchannel.http.PostRequest;
import com.rogiel.httpchannel.util.htmlparser.HTMLPage;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public abstract class AbstractImageCaptchaService<C extends AbstractImageCaptcha>
implements ImageCaptchaService<C> {
protected final HttpContext http = new HttpContext();
@Override
public final C create(String html) {
try {
return create(HTMLPage.parse(html));
} catch (IOException e) {
return null;
}
}
public abstract C create(HTMLPage page) throws IOException;
@Override
public boolean resolve(C captcha) {
return false;
}
public GetRequest get(String url) {
return http.get(url);
}
public GetRequest get(URL url) {
return http.get(url);
}
public PostRequest post(String url) {
return http.post(url);
}
public PostMultipartRequest multipartPost(String url) {
return http.multipartPost(url);
}
}

View File

@@ -0,0 +1,30 @@
/**
*
*/
package com.rogiel.httpchannel.http;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
public class GetRequest extends Request {
private long position = 0;
public GetRequest(HttpContext ctx, String url) {
super(ctx, url);
}
@Override
public HttpResponse request() throws IOException {
final HttpGet get = new HttpGet(url);
if (position > 0)
get.addHeader("Range", "bytes=" + position + "-");
return ctx.client.execute(get);
}
public GetRequest position(long position) {
this.position = position;
return this;
}
}

View File

@@ -0,0 +1,40 @@
/**
*
*/
package com.rogiel.httpchannel.http;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class HttpContext {
protected final ExecutorService threadPool = Executors
.newCachedThreadPool();
/**
* The {@link HttpClient} instance for this service
*/
protected DefaultHttpClient client = new DefaultHttpClient();
public GetRequest get(String url) {
return new GetRequest(this, url);
}
public GetRequest get(URL url) {
return get(url.toString());
}
public PostRequest post(String url) {
return new PostRequest(this, url);
}
public PostMultipartRequest multipartPost(String url) {
return new PostMultipartRequest(this, url);
}
}

View File

@@ -0,0 +1,48 @@
/**
*
*/
package com.rogiel.httpchannel.http;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.StringBody;
import com.rogiel.httpchannel.service.channel.LinkedUploadChannel;
import com.rogiel.httpchannel.service.channel.LinkedUploadChannelContentBody;
public class PostMultipartRequest extends PostRequest {
private final MultipartEntity entity;
public PostMultipartRequest(HttpContext ctx, String url) {
super(ctx, url);
this.entity = new MultipartEntity();
}
@Override
public HttpResponse request() throws IOException {
final HttpPost post = new HttpPost(url);
post.setEntity(entity);
return ctx.client.execute(post);
}
public PostMultipartRequest parameter(String name, ContentBody body) {
entity.addPart(name, body);
return this;
}
@Override
public PostMultipartRequest parameter(String name, String value)
throws UnsupportedEncodingException {
return parameter(name, new StringBody(value));
}
public PostMultipartRequest parameter(String name,
LinkedUploadChannel channel) {
return parameter(name, new LinkedUploadChannelContentBody(channel));
}
}

View File

@@ -0,0 +1,46 @@
/**
*
*/
package com.rogiel.httpchannel.http;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
public class PostRequest extends Request {
protected final List<NameValuePair> params = new ArrayList<NameValuePair>();
public PostRequest(HttpContext ctx, String url) {
super(ctx, url);
}
@Override
public HttpResponse request() throws IOException {
final HttpPost post = new HttpPost(url);
post.setEntity(new UrlEncodedFormEntity(params));
return ctx.client.execute(post);
}
public PostRequest parameter(String name, String value)
throws UnsupportedEncodingException {
params.add(new BasicNameValuePair(name, value));
return this;
}
public PostRequest parameter(String name, int value)
throws UnsupportedEncodingException {
return parameter(name, Integer.toString(value));
}
public PostRequest parameter(String name, boolean value)
throws UnsupportedEncodingException {
return parameter(name, (value ? "1" : "0"));
}
}

View File

@@ -0,0 +1,65 @@
/**
*
*/
package com.rogiel.httpchannel.http;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import com.rogiel.httpchannel.util.HttpClientUtils;
import com.rogiel.httpchannel.util.htmlparser.HTMLPage;
public abstract class Request {
protected final HttpContext ctx;
protected final String url;
public Request(HttpContext ctx, String url) {
this.ctx = ctx;
this.url = url;
}
public abstract HttpResponse request() throws IOException;
public Future<HttpResponse> requestAsync() throws IOException {
return ctx.threadPool.submit(new Callable<HttpResponse>() {
@Override
public HttpResponse call() throws Exception {
return request();
}
});
}
public String asString() throws ClientProtocolException, IOException {
return HttpClientUtils.toString(request());
}
public Future<String> asStringAsync() throws IOException {
return ctx.threadPool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return asString();
}
});
}
public HTMLPage asPage() throws ClientProtocolException, IOException {
return HTMLPage.parse(asString());
}
public Future<HTMLPage> asPageAsync() throws IOException {
return ctx.threadPool.submit(new Callable<HTMLPage>() {
@Override
public HTMLPage call() throws Exception {
return asPage();
}
});
}
public String getURL() {
return url;
}
}

View File

@@ -0,0 +1,39 @@
package com.rogiel.httpchannel.service;
import com.rogiel.httpchannel.service.Authenticator.AuthenticatorConfiguration;
/**
* An abstract {@link Authenticator} that implements most of the general-purpose
* methods
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
* @param <C>
* the {@link Authenticator} configuration object type
*/
public abstract class AbstractAuthenticator<C extends AuthenticatorConfiguration>
implements Authenticator<C> {
protected final Credential credential;
/**
* The {@link Authenticator} configuration
*/
protected final C configuration;
/**
* Creates a new instance
*
* @param credential
* the authentication credential
* @param configuration
* the configuration object
*/
protected AbstractAuthenticator(Credential credential, C configuration) {
this.credential = credential;
this.configuration = configuration;
}
@Override
public C getConfiguration() {
return configuration;
}
}

View File

@@ -1,52 +1,79 @@
/*
* 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;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import com.rogiel.httpchannel.util.ThreadUtils;
/**
* @author rogiel
*/
public abstract class AbstractDownloader implements Downloader {
protected int parseTimer(String stringTimer) {
int timer = 0;
if (stringTimer != null && stringTimer.length() > 0) {
timer = Integer.parseInt(stringTimer);
}
return timer;
}
protected long getContentLength(HttpResponse response) {
final Header contentLengthHeader = response
.getFirstHeader("Content-Length");
long contentLength = -1;
if (contentLengthHeader != null) {
contentLength = Long.valueOf(contentLengthHeader.getValue());
}
return contentLength;
}
protected void timer(DownloadListener listener, long timer) {
if (listener != null) {
listener.timer(timer);
}
ThreadUtils.sleep(timer);
}
}
package com.rogiel.httpchannel.service;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import com.rogiel.httpchannel.service.Downloader.DownloaderConfiguration;
import com.rogiel.httpchannel.service.channel.InputStreamDownloadChannel;
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;
/**
* An abstract {@link Downloader} that implements most of the general-purpose
* methods
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
* @param <C>
* the {@link Downloader} configuration object type
*/
public abstract class AbstractDownloader<C extends DownloaderConfiguration>
implements Downloader<C> {
/**
* The download URL
*/
protected final URL url;
/**
* The {@link Downloader} configuration
*/
protected final C configuration;
/**
* Creates a new instance
*
* @param url
* the download url
* @param configuration
* the configuration object
*/
protected AbstractDownloader(URL url, C configuration) {
this.url = url;
this.configuration = configuration;
}
@Override
public DownloadChannel openChannel(long position) throws IOException,
DownloadLinkNotFoundException, DownloadLimitExceededException,
DownloadNotAuthorizedException, DownloadNotResumableException {
return openChannel(null, position);
}
@Override
public DownloadChannel openChannel(DownloadListener listener)
throws IOException, DownloadLinkNotFoundException,
DownloadLimitExceededException, DownloadNotAuthorizedException,
DownloadNotResumableException {
return openChannel(listener, 0);
}
@Override
public DownloadChannel openChannel() throws IOException,
DownloadLinkNotFoundException, DownloadLimitExceededException,
DownloadNotAuthorizedException, DownloadNotResumableException {
return openChannel(null, 0);
}
protected InputStreamDownloadChannel createInputStreamChannel(
InputStream in, long length, String filename) {
return new InputStreamDownloadChannel(in, length, filename);
}
@Override
public C getConfiguration() {
return configuration;
}
}

View File

@@ -0,0 +1,66 @@
/*
* 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;
import java.io.IOException;
import java.net.URL;
import org.apache.commons.io.FilenameUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import com.rogiel.httpchannel.http.Request;
import com.rogiel.httpchannel.service.Downloader.DownloaderConfiguration;
import com.rogiel.httpchannel.service.channel.InputStreamDownloadChannel;
import com.rogiel.httpchannel.util.ThreadUtils;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public abstract class AbstractHttpDownloader<C extends DownloaderConfiguration>
extends AbstractDownloader<C> implements Downloader<C> {
protected AbstractHttpDownloader(URL url, C configuration) {
super(url, configuration);
}
protected long getContentLength(HttpResponse response) {
final Header contentLengthHeader = response
.getFirstHeader("Content-Length");
long contentLength = -1;
if (contentLengthHeader != null) {
contentLength = Long.valueOf(contentLengthHeader.getValue());
}
return contentLength;
}
protected void timer(DownloadListener listener, long timer) {
if (listener != null) {
if (!listener.timer(timer))
return;
}
ThreadUtils.sleep(timer);
}
protected InputStreamDownloadChannel download(Request request)
throws IOException {
final HttpResponse response = request.request();
final String filename = FilenameUtils.getName(request.getURL());
final long contentLength = getContentLength(response);
return createInputStreamChannel(response.getEntity().getContent(),
contentLength, filename);
}
}

View File

@@ -16,151 +16,47 @@
*/
package com.rogiel.httpchannel.service;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.net.URL;
import java.util.concurrent.Future;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import com.rogiel.httpchannel.service.captcha.CaptchaResolver;
import com.rogiel.httpchannel.service.config.ServiceConfiguration;
import com.rogiel.httpchannel.util.AlwaysRedirectStrategy;
import com.rogiel.httpchannel.util.HttpClientUtils;
import com.rogiel.httpchannel.util.htmlparser.HTMLPage;
import com.rogiel.httpchannel.http.GetRequest;
import com.rogiel.httpchannel.http.HttpContext;
import com.rogiel.httpchannel.http.PostMultipartRequest;
import com.rogiel.httpchannel.http.PostRequest;
import com.rogiel.httpchannel.service.channel.LinkedUploadChannel;
import com.rogiel.httpchannel.util.ThreadUtils;
/**
* Abstract base service for HTTP enabled services.
*
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public abstract class AbstractHttpService<T extends ServiceConfiguration>
extends AbstractService<T> implements Service {
private static final ExecutorService threadPool = Executors
.newCachedThreadPool();
public abstract class AbstractHttpService extends AbstractService implements
Service {
protected final HttpContext http = new HttpContext();
/**
* The {@link HttpClient} instance for this service
*/
protected DefaultHttpClient client = new DefaultHttpClient();
/**
* The captcha resolver
*/
protected CaptchaResolver captchaResolver;
protected AbstractHttpService(T configuration) {
super(configuration);
client.setRedirectStrategy(new AlwaysRedirectStrategy());
// client.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS,
// true);
// client.getParams().setIntParameter(ClientPNames.MAX_REDIRECTS, 10);
// client.setRedirectStrategy(new DefaultRedirectStrategy());
protected LinkedUploadChannel waitChannelLink(LinkedUploadChannel channel,
Future<?> future) {
while (!channel.isLinked() && !future.isDone()) {
ThreadUtils.sleep(100);
}
return channel;
}
protected HttpResponse get(String url) throws ClientProtocolException,
IOException {
final HttpGet request = new HttpGet(url);
return client.execute(request);
public GetRequest get(String url) {
return http.get(url);
}
protected HttpResponse get(String url, long rangeStart)
throws ClientProtocolException, IOException {
final HttpGet request = new HttpGet(url);
if (rangeStart >= 0)
request.addHeader("Range", "bytes=" + rangeStart + "-");
return client.execute(request);
public GetRequest get(URL url) {
return http.get(url);
}
protected String getAsString(String url) throws ClientProtocolException,
IOException {
return HttpClientUtils.toString(get(url));
public PostRequest post(String url) {
return http.post(url);
}
protected HTMLPage getAsPage(String url) throws ClientProtocolException,
IOException {
return HTMLPage.parse(getAsString(url));
}
public Future<HttpResponse> getAsync(final String url) throws IOException {
return threadPool.submit(new Callable<HttpResponse>() {
@Override
public HttpResponse call() throws Exception {
return get(url);
}
});
}
public Future<String> getAsStringAsync(final String url) throws IOException {
return threadPool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return getAsString(url);
}
});
}
public Future<HTMLPage> getAsPageAsync(final String url) throws IOException {
return threadPool.submit(new Callable<HTMLPage>() {
@Override
public HTMLPage call() throws Exception {
return getAsPage(url);
}
});
}
protected HttpResponse post(String url, HttpEntity entity)
throws ClientProtocolException, IOException {
final HttpPost request = new HttpPost(url);
request.setEntity(entity);
return client.execute(request);
}
protected String postAsString(String url, HttpEntity entity)
throws ClientProtocolException, IOException {
return HttpClientUtils.toString(post(url, entity));
}
protected HTMLPage postAsPage(String url, HttpEntity entity)
throws ClientProtocolException, IOException {
return HTMLPage.parse(postAsString(url, entity));
}
protected Future<HttpResponse> postAsync(final String url,
final HttpEntity entity) throws IOException {
return threadPool.submit(new Callable<HttpResponse>() {
@Override
public HttpResponse call() throws Exception {
return post(url, entity);
}
});
}
protected Future<String> postAsStringAsync(final String url,
final HttpEntity entity) throws IOException {
return threadPool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return postAsString(url, entity);
}
});
}
protected Future<HTMLPage> postAsPageAsync(final String url,
final HttpEntity entity) throws IOException {
return threadPool.submit(new Callable<HTMLPage>() {
@Override
public HTMLPage call() throws Exception {
return postAsPage(url, entity);
}
});
public PostMultipartRequest multipartPost(String url) {
return http.multipartPost(url);
}
}

View File

@@ -0,0 +1,58 @@
package com.rogiel.httpchannel.service;
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
import com.rogiel.httpchannel.service.channel.LinkedUploadChannel;
import com.rogiel.httpchannel.service.channel.LinkedUploadChannel.LinkedUploadChannelCloseCallback;
/**
* An abstract {@link Uploader} that implements most of the general-purpose
* methods
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
* @param <C>
* the {@link Uploader} configuration object type
*/
public abstract class AbstractUploader<C extends UploaderConfiguration>
implements Uploader<C> {
protected final String filename;
protected final long filesize;
/**
* The {@link Uploader} configuration
*/
protected final C configuration;
/**
* Creates a new instance
*
* @param filename
* the file name
* @param filesize
* the file size
* @param configuration
* the configuration object
*/
public AbstractUploader(String filename, long filesize, C configuration) {
this.filename = filename;
this.filesize = filesize;
this.configuration = configuration;
}
/**
* Creates a new linked channel
*
* @param closeCallback
* the close callback
* @return a newly created {@link LinkedUploadChannel}
*/
protected LinkedUploadChannel createLinkedChannel(
LinkedUploadChannelCloseCallback closeCallback) {
return new LinkedUploadChannel(closeCallback, filesize, filename);
}
@Override
public C getConfiguration() {
return configuration;
}
}

View File

@@ -17,11 +17,12 @@
package com.rogiel.httpchannel.service.channel;
import java.io.IOException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import com.rogiel.httpchannel.service.UploadChannel;
import com.rogiel.httpchannel.service.exception.UploadLinkNotFoundException;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
@@ -33,7 +34,7 @@ public class LinkedUploadChannel implements UploadChannel {
private final long length;
private final String filename;
private String downloadLink;
private URL downloadLink;
private boolean open = true;
@@ -59,7 +60,10 @@ public class LinkedUploadChannel implements UploadChannel {
@Override
public void close() throws IOException {
open = false;
downloadLink = closeCallback.finish();
final String downloadLink = closeCallback.finish();
if (downloadLink == null)
throw new UploadLinkNotFoundException();
this.downloadLink = new URL(downloadLink);
}
public interface LinkedUploadChannelCloseCallback {
@@ -77,12 +81,12 @@ public class LinkedUploadChannel implements UploadChannel {
}
@Override
public String getDownloadLink() {
public URL getDownloadLink() {
return downloadLink;
}
public void linkChannel(WritableByteChannel channel) throws IOException {
if(this.channel != null)
if (this.channel != null)
throw new IOException("This channel is already linked.");
this.channel = channel;
}

View File

@@ -29,7 +29,7 @@ import com.rogiel.httpchannel.service.Uploader;
/**
* {@link ContentBody} used to upload files in {@link Uploader} implementations.
*
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public class LinkedUploadChannelContentBody extends AbstractContentBody {

View File

@@ -16,14 +16,23 @@
*/
package com.rogiel.httpchannel.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import com.rogiel.httpchannel.service.UploadChannel;
import com.rogiel.httpchannel.service.UploadService;
import com.rogiel.httpchannel.service.helper.UploadServices;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class ChannelUtils {
public static void copy(ReadableByteChannel in, WritableByteChannel out)
@@ -48,4 +57,24 @@ public class ChannelUtils {
buffer.compact();
}
}
public static byte[] toByteArray(ReadableByteChannel channel)
throws IOException {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
copy(channel, Channels.newChannel(out));
return out.toByteArray();
}
public static URL upload(UploadService<?> service, Path path)
throws IOException {
final UploadChannel uploadChannel = UploadServices
.upload(service, path).openChannel();
try {
copy(Files.newByteChannel(path, StandardOpenOption.READ),
uploadChannel);
} finally {
uploadChannel.close();
}
return uploadChannel.getDownloadLink();
}
}

View File

@@ -18,7 +18,7 @@
package com.rogiel.httpchannel.util;
/**
* @author Rogiel
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public class ThreadUtils {

View File

@@ -0,0 +1,20 @@
package com.rogiel.httpchannel.util.htmlparser;
import java.util.regex.Pattern;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
public class ContainsFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final Pattern content;
public ContainsFilter(Pattern content) {
this.content = content;
}
@Override
public boolean accept(Node node) {
return content.matcher(node.getText()).find();
}
}

View File

@@ -0,0 +1,20 @@
package com.rogiel.httpchannel.util.htmlparser;
import java.util.regex.Pattern;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
public class ContainsInLowerCaseFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final Pattern content;
public ContainsInLowerCaseFilter(Pattern content) {
this.content = content;
}
@Override
public boolean accept(Node node) {
return content.matcher(node.getText().toLowerCase()).find();
}
}

View File

@@ -0,0 +1,24 @@
package com.rogiel.httpchannel.util.htmlparser;
import java.util.regex.Pattern;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.tags.FormTag;
public class FormActionPatternFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final Pattern pattern;
public FormActionPatternFilter(Pattern pattern) {
this.pattern = pattern;
}
@Override
public boolean accept(Node node) {
if (!(node instanceof FormTag))
return false;
final FormTag form = (FormTag) node;
return pattern.matcher(form.getFormLocation()).matches();
}
}

View File

@@ -0,0 +1,26 @@
package com.rogiel.httpchannel.util.htmlparser;
import java.util.regex.Pattern;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.nodes.TagNode;
public class FramePatternFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final Pattern pattern;
public FramePatternFilter(Pattern pattern) {
this.pattern = pattern;
}
@Override
public boolean accept(Node node) {
if (!(node instanceof TagNode))
return false;
final TagNode frame = (TagNode) node;
if (frame.getAttribute("src") == null)
return false;
return pattern.matcher(frame.getAttribute("src")).matches();
}
}

View File

@@ -16,6 +16,9 @@
*/
package com.rogiel.httpchannel.util.htmlparser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -23,7 +26,10 @@ import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.Tag;
import org.htmlparser.filters.AndFilter;
import org.htmlparser.nodes.TagNode;
import org.htmlparser.tags.FormTag;
import org.htmlparser.tags.ImageTag;
import org.htmlparser.tags.InputTag;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.tags.ScriptTag;
@@ -35,214 +41,208 @@ import org.htmlparser.util.ParserException;
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class HTMLPage {
private final Parser parser;
private final NodeList nodes;
private HTMLPage(Parser parser) {
this.parser = parser;
private HTMLPage(Parser parser) throws ParserException {
this.nodes = parser.parse(null);
}
public String getLink(final Pattern pattern) {
NodeList nodes;
private <T extends Node> List<T> filter(final Class<T> nodeType,
NodeFilter... filters) {
final NodeFilter filter;
if (filters.length == 1)
filter = filters[0];
else
filter = new AndFilter(filters);
try {
nodes = parser.extractAllNodesThatMatch(new NodeFilter() {
private static final long serialVersionUID = 1L;
@Override
public boolean accept(Node node) {
if (!(node instanceof LinkTag))
return false;
final LinkTag link = (LinkTag) node;
return pattern.matcher(link.getLink()).matches();
}
});
return list(nodes.extractAllNodesThatMatch(filter, true));
} catch (ParserException e) {
return null;
return Collections.emptyList();
}
if (nodes.size() >= 1)
return ((LinkTag) nodes.elements().nextNode()).getLink();
return null;
}
public String getFormAction(final Pattern pattern) {
NodeList nodes;
try {
nodes = parser.extractAllNodesThatMatch(new NodeFilter() {
private static final long serialVersionUID = 1L;
@Override
public boolean accept(Node node) {
if (!(node instanceof FormTag))
return false;
final FormTag form = (FormTag) node;
return pattern.matcher(form.getFormLocation()).matches();
}
});
} catch (ParserException e) {
return null;
@SuppressWarnings("unchecked")
private <T extends Node> List<T> list(final NodeList list)
throws ParserException {
final List<T> filtered = new ArrayList<>();
final NodeIterator iterator = list.elements();
while (iterator.hasMoreNodes()) {
filtered.add((T) iterator.nextNode());
}
if (nodes.size() >= 1)
return ((FormTag) nodes.elements().nextNode()).getFormLocation();
return null;
return filtered;
}
public String getInputValue(final String inputName) {
NodeList nodes;
try {
nodes = parser.extractAllNodesThatMatch(new NodeFilter() {
private static final long serialVersionUID = 1L;
@Override
public boolean accept(Node node) {
if (!(node instanceof InputTag))
return false;
final InputTag input = (InputTag) node;
if (!input.getAttribute("name").equals(inputName))
return false;
return true;
}
});
} catch (ParserException e) {
return null;
}
if (nodes.size() >= 1)
return ((InputTag) nodes.elements().nextNode())
.getAttribute("value");
return null;
}
public int getIntegerInputValue(final String inputName) {
return Integer.parseInt(getInputValue(inputName));
}
public String getInputValue(final Pattern pattern) {
NodeList nodes;
try {
nodes = parser.extractAllNodesThatMatch(new NodeFilter() {
private static final long serialVersionUID = 1L;
@Override
public boolean accept(Node node) {
if (!(node instanceof InputTag))
return false;
final InputTag input = (InputTag) node;
if (input.getAttribute("value") == null)
return false;
if (!pattern.matcher(input.getAttribute("value")).matches())
return false;
return true;
}
});
} catch (ParserException e) {
return null;
}
if (nodes.size() >= 1)
return ((InputTag) nodes.elements().nextNode())
.getAttribute("value");
return null;
}
public Tag getTagByID(final String id) {
NodeList nodes;
try {
nodes = parser.extractAllNodesThatMatch(new NodeFilter() {
private static final long serialVersionUID = 1L;
@Override
public boolean accept(Node node) {
if (!(node instanceof Tag))
return false;
if (((Tag) node).getAttribute("id") == null)
return false;
return ((Tag) node).getAttribute("id").equals(id);
}
});
} catch (ParserException e) {
return null;
}
if (nodes.size() >= 1)
return ((Tag) nodes.elements().nextNode());
return null;
}
public Tag getTagByName(final String name) {
NodeList nodes;
try {
nodes = parser.extractAllNodesThatMatch(new NodeFilter() {
private static final long serialVersionUID = 1L;
@Override
public boolean accept(Node node) {
if (!(node instanceof Tag))
return false;
return ((Tag) node).getAttribute("name").equals(name);
}
});
} catch (ParserException e) {
return null;
}
if (nodes.size() >= 1)
return ((Tag) nodes.elements().nextNode());
return null;
public boolean contains(final Pattern pattern) {
return !filter(Node.class, new ContainsFilter(pattern)).isEmpty();
}
public boolean contains(final String text) {
try {
for (NodeIterator e = parser.elements(); e.hasMoreNodes();) {
if (e.nextNode().toPlainTextString().contains(text))
return true;
}
} catch (ParserException e) {
return false;
}
return false;
return contains(Pattern.compile(Pattern.quote(text)));
}
public String findInScript(final Pattern pattern, int n) {
NodeList nodes;
try {
nodes = parser.extractAllNodesThatMatch(new NodeFilter() {
private static final long serialVersionUID = 1L;
public boolean containsIgnoreCase(final String text) {
return !filter(
Node.class,
new ContainsInLowerCaseFilter(Pattern.compile(Pattern
.quote(text.toLowerCase())))).isEmpty();
}
@Override
public boolean accept(Node node) {
if (!(node instanceof ScriptTag))
return false;
final ScriptTag script = (ScriptTag) node;
return pattern.matcher(script.getScriptCode()).find();
}
});
} catch (ParserException e) {
return null;
}
if (nodes.size() >= 1) {
final ScriptTag script = (ScriptTag) nodes.elements().nextNode();
final Matcher matcher = pattern.matcher(script.getScriptCode());
public String find(final Pattern pattern, int n) {
for (final Node tag : filter(Tag.class, new ContainsFilter(pattern))) {
final Matcher matcher = pattern.matcher(tag.getText());
if (matcher.find())
return matcher.group(n);
}
return null;
}
public int findIntegerInScript(final Pattern pattern, int n) {
String found = findInScript(pattern, n);
if(found == null)
public int findAsInt(final Pattern pattern, int n) {
String found = find(pattern, n);
if (found == null)
return 0;
return Integer.parseInt(findInScript(pattern, n));
return Integer.parseInt(findScript(pattern, n));
}
/**
* Tries to find a link that has an URL following the given pattern
*
* @param pattern
* the pattern
* @return the link content, if found. <code>null</code> otherwise
*/
public String findLink(final Pattern pattern) {
for (final LinkTag tag : filter(LinkTag.class, new LinkPatternFilter(
pattern))) {
return tag.getLink();
}
return null;
}
/**
* Tries to find a frame that has an URL following the given pattern
*
* @param pattern
* the pattern
* @return the iframe url, if found. <code>null</code> otherwise
*/
public String findFrame(final Pattern pattern) {
for (final TagNode tag : filter(TagNode.class, new FramePatternFilter(
pattern))) {
return tag.getAttribute("src");
}
return null;
}
/**
* Tries to find a image that has an URL following the given pattern
*
* @param pattern
* the pattern
* @return the iframe url, if found. <code>null</code> otherwise
*/
public String findImage(final Pattern pattern) {
for (final ImageTag tag : filter(ImageTag.class,
new ImagePatternFilter(pattern))) {
return tag.getImageURL();
}
return null;
}
/**
* Tries to find a form which has an location that respects the given
* pattern
*
* @param pattern
* the pattern
* @return the URL found, if any. <code>null</code> otherwise
*/
public String findFormAction(final Pattern pattern) {
for (final FormTag tag : filter(FormTag.class,
new FormActionPatternFilter(pattern))) {
return tag.getFormLocation();
}
return null;
}
private String inputValue(List<InputTag> tags) {
for (final InputTag tag : tags) {
return tag.getAttribute("value");
}
return null;
}
public String getInputValue(final String inputName) {
return inputValue(filter(InputTag.class, new InputNameFilter(inputName)));
}
public int getInputValueAsInt(final String inputName) {
return Integer.parseInt(getInputValue(inputName));
}
public String getInputValueById(final String id) {
return inputValue(filter(InputTag.class, new InputIDFilter(id)));
}
public String getInputValue(final Pattern pattern) {
return inputValue(filter(InputTag.class, new InputValuePatternFilter(
pattern)));
}
public Tag getTagByID(final String id) {
for (final Tag tag : filter(Tag.class, new IDFilter(id))) {
return tag;
}
return null;
}
public Tag getTagByName(final String name) {
for (final Tag tag : filter(Tag.class, new NameFilter(name))) {
return tag;
}
return null;
}
public String findScript(final Pattern pattern, int n) {
for (final ScriptTag tag : filter(ScriptTag.class,
new ScriptContainsFilter(pattern))) {
final Matcher matcher = pattern.matcher(tag.getScriptCode());
if (matcher.find())
return matcher.group(n);
}
return null;
}
public String findScriptSrc(final Pattern pattern) {
for (final ScriptTag tag : filter(ScriptTag.class, new ScriptSrcFilter(
pattern))) {
final Matcher matcher = pattern.matcher(tag.getAttribute("src"));
if (matcher.matches())
return matcher.group();
}
return null;
}
public int findScriptAsInt(final Pattern pattern, int n) {
String found = findScript(pattern, n);
if (found == null)
return 0;
return Integer.parseInt(found);
}
public String toString() {
final StringBuilder builder = new StringBuilder();
try {
for (NodeIterator i = parser.elements(); i.hasMoreNodes();) {
builder.append(i.nextNode().toHtml(true));
}
} catch (ParserException e) {
return null;
}
return builder.toString();
// try {
// return parser.parse(null).toHtml(false);
// } catch (ParserException e1) {
// return null;
// }
return nodes.toHtml(false);
}
public static HTMLPage parse(String html) {
return new HTMLPage(Parser.createParser(html, null));
try {
return new HTMLPage(Parser.createParser(html, null));
} catch (ParserException e) {
return null;
}
}
}

View File

@@ -0,0 +1,26 @@
package com.rogiel.httpchannel.util.htmlparser;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Tag;
public class IDFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final String id;
public IDFilter(String id) {
this.id = id;
}
@Override
public boolean accept(Node node) {
if (!(node instanceof Tag))
return false;
final Tag tag = (Tag) node;
if (tag.getAttribute("id") == null)
return false;
if (!tag.getAttribute("id").equals(id))
return false;
return true;
}
}

View File

@@ -0,0 +1,24 @@
package com.rogiel.httpchannel.util.htmlparser;
import java.util.regex.Pattern;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.tags.ImageTag;
public class ImagePatternFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final Pattern pattern;
public ImagePatternFilter(Pattern pattern) {
this.pattern = pattern;
}
@Override
public boolean accept(Node node) {
if (!(node instanceof ImageTag))
return false;
final ImageTag frame = (ImageTag) node;
return pattern.matcher(frame.getImageURL()).matches();
}
}

View File

@@ -0,0 +1,26 @@
package com.rogiel.httpchannel.util.htmlparser;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.tags.InputTag;
public class InputIDFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final String id;
public InputIDFilter(String id) {
this.id = id;
}
@Override
public boolean accept(Node node) {
if (!(node instanceof InputTag))
return false;
final InputTag input = (InputTag) node;
if (input.getAttribute("id") == null)
return false;
if (!input.getAttribute("id").equals(id))
return false;
return true;
}
}

View File

@@ -0,0 +1,26 @@
package com.rogiel.httpchannel.util.htmlparser;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.tags.InputTag;
public class InputNameFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final String name;
public InputNameFilter(String name) {
this.name = name;
}
@Override
public boolean accept(Node node) {
if (!(node instanceof InputTag))
return false;
final InputTag input = (InputTag) node;
if(input.getAttribute("name") == null)
return false;
if (!input.getAttribute("name").equals(name))
return false;
return true;
}
}

View File

@@ -0,0 +1,28 @@
package com.rogiel.httpchannel.util.htmlparser;
import java.util.regex.Pattern;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.tags.InputTag;
public class InputValuePatternFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final Pattern pattern;
public InputValuePatternFilter(Pattern pattern) {
this.pattern = pattern;
}
@Override
public boolean accept(Node node) {
if (!(node instanceof InputTag))
return false;
final InputTag input = (InputTag) node;
if (input.getAttribute("value") == null)
return false;
if (!pattern.matcher(input.getAttribute("value")).matches())
return false;
return true;
}
}

View File

@@ -0,0 +1,24 @@
package com.rogiel.httpchannel.util.htmlparser;
import java.util.regex.Pattern;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.tags.LinkTag;
public class LinkPatternFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final Pattern pattern;
public LinkPatternFilter(Pattern pattern) {
this.pattern = pattern;
}
@Override
public boolean accept(Node node) {
if (!(node instanceof LinkTag))
return false;
final LinkTag link = (LinkTag) node;
return pattern.matcher(link.getLink()).matches();
}
}

View File

@@ -0,0 +1,26 @@
package com.rogiel.httpchannel.util.htmlparser;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Tag;
public class NameFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final String name;
public NameFilter(String name) {
this.name = name;
}
@Override
public boolean accept(Node node) {
if (!(node instanceof Tag))
return false;
final Tag tag = (Tag) node;
if (tag.getAttribute("name") == null)
return false;
if (!tag.getAttribute("name").equals(name))
return false;
return true;
}
}

View File

@@ -0,0 +1,24 @@
package com.rogiel.httpchannel.util.htmlparser;
import java.util.regex.Pattern;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.tags.ScriptTag;
public class ScriptContainsFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final Pattern pattern;
public ScriptContainsFilter(Pattern pattern) {
this.pattern = pattern;
}
@Override
public boolean accept(Node node) {
if (!(node instanceof ScriptTag))
return false;
final ScriptTag script = (ScriptTag) node;
return pattern.matcher(script.getScriptCode()).find();
}
}

View File

@@ -0,0 +1,26 @@
package com.rogiel.httpchannel.util.htmlparser;
import java.util.regex.Pattern;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.tags.ScriptTag;
public class ScriptSrcFilter implements NodeFilter {
private static final long serialVersionUID = 1L;
private final Pattern pattern;
public ScriptSrcFilter(Pattern pattern) {
this.pattern = pattern;
}
@Override
public boolean accept(Node node) {
if (!(node instanceof ScriptTag))
return false;
final ScriptTag script = (ScriptTag) node;
if (script.getAttribute("src") == null)
return false;
return pattern.matcher(script.getAttribute("src")).matches();
}
}