diff --git a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/AccountDetails.java b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/AccountDetails.java
index e2fed88..f848a3f 100644
--- a/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/AccountDetails.java
+++ b/httpchannel-api/src/main/java/com/rogiel/httpchannel/service/AccountDetails.java
@@ -1,5 +1,20 @@
-/**
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package com.rogiel.httpchannel.service;
diff --git a/httpchannel-service/httpchannel-service-2shared/pom.xml b/httpchannel-service/httpchannel-service-2shared/pom.xml
new file mode 100644
index 0000000..0bab680
--- /dev/null
+++ b/httpchannel-service/httpchannel-service-2shared/pom.xml
@@ -0,0 +1,14 @@
+
+
+ 4.0.0
+
+ httpchannel-service
+ com.rogiel.httpchannel
+ 1.0.1-SNAPSHOT
+ ../pom.xml
+
+ httpchannel-service-2shared
+ com.rogiel.httpchannel.service
+ HttpChannel/Service/TwoShared
+ Provides download and upload access for 2shared.com
+
diff --git a/httpchannel-service/httpchannel-service-2shared/src/main/java/com/rogiel/httpchannel/service/twoshared/TwoSharedService.java b/httpchannel-service/httpchannel-service-2shared/src/main/java/com/rogiel/httpchannel/service/twoshared/TwoSharedService.java
new file mode 100644
index 0000000..cfd6843
--- /dev/null
+++ b/httpchannel-service/httpchannel-service-2shared/src/main/java/com/rogiel/httpchannel/service/twoshared/TwoSharedService.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.rogiel.httpchannel.service.twoshared;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.regex.Pattern;
+
+import com.rogiel.httpchannel.captcha.exception.UnsolvableCaptchaServiceException;
+import com.rogiel.httpchannel.service.AbstractHttpDownloader;
+import com.rogiel.httpchannel.service.AbstractHttpService;
+import com.rogiel.httpchannel.service.AbstractUploader;
+import com.rogiel.httpchannel.service.CapabilityMatrix;
+import com.rogiel.httpchannel.service.DownloadChannel;
+import com.rogiel.httpchannel.service.DownloadListener;
+import com.rogiel.httpchannel.service.DownloadService;
+import com.rogiel.httpchannel.service.Downloader;
+import com.rogiel.httpchannel.service.DownloaderCapability;
+import com.rogiel.httpchannel.service.Service;
+import com.rogiel.httpchannel.service.ServiceID;
+import com.rogiel.httpchannel.service.ServiceMode;
+import com.rogiel.httpchannel.service.UploadChannel;
+import com.rogiel.httpchannel.service.UploadService;
+import com.rogiel.httpchannel.service.Uploader;
+import com.rogiel.httpchannel.service.UploaderCapability;
+import com.rogiel.httpchannel.service.channel.LinkedUploadChannel;
+import com.rogiel.httpchannel.service.channel.LinkedUploadChannel.LinkedUploadChannelCloseCallback;
+import com.rogiel.httpchannel.service.config.NullDownloaderConfiguration;
+import com.rogiel.httpchannel.service.config.NullUploaderConfiguration;
+import com.rogiel.httpchannel.service.exception.DownloadLimitExceededException;
+import com.rogiel.httpchannel.service.exception.DownloadLinkNotFoundException;
+import com.rogiel.httpchannel.service.exception.DownloadNotAuthorizedException;
+import com.rogiel.httpchannel.service.exception.DownloadNotResumableException;
+import com.rogiel.httpchannel.service.exception.NoCaptchaServiceException;
+import com.rogiel.httpchannel.util.ExceptionUtils;
+import com.rogiel.httpchannel.util.htmlparser.HTMLPage;
+
+/**
+ * This service handles uploads to TwoShared.
+ *
+ * @author Rogiel
+ * @since 1.0
+ */
+public class TwoSharedService extends AbstractHttpService implements Service,
+ UploadService,
+ DownloadService {
+ /**
+ * This service ID
+ */
+ public static final ServiceID SERVICE_ID = ServiceID.create("twoshared");
+
+ private static final Pattern UPLOAD_URL_PATTERN = Pattern
+ .compile("http://dc[0-9]*\\.2shared\\.com/main/upload2\\.jsp\\?sId=[A-z0-9]*");
+ private static final Pattern UPLOAD_ID_PATTERN = Pattern
+ .compile("sId=([A-z0-9]*)");
+
+ private static final Pattern DOWNLOAD_URL_PATTERN = Pattern
+ .compile("http://(www\\.)?2shared\\.com/document/[A-z0-9]*/.*");
+ private static final Pattern DIRECT_DOWNLOAD_URL_PATTERN = Pattern
+ .compile("http://dc[0-9]+\\.2shared\\.com/download/[A-z0-9]+/.+\\?tsid=[0-9]{8}-[0-9]{6}-[A-z0-9]{8}");
+
+ @Override
+ public ServiceID getServiceID() {
+ return SERVICE_ID;
+ }
+
+ @Override
+ public int getMajorVersion() {
+ return 1;
+ }
+
+ @Override
+ public int getMinorVersion() {
+ return 0;
+ }
+
+ @Override
+ public CapabilityMatrix getPossibleServiceModes() {
+ return new CapabilityMatrix(ServiceMode.UNAUTHENTICATED);
+ }
+
+ @Override
+ public Uploader getUploader(String filename,
+ long filesize, NullUploaderConfiguration configuration) {
+ return new UploaderImpl(filename, filesize, configuration);
+ }
+
+ @Override
+ public Uploader getUploader(String filename,
+ long filesize) {
+ return getUploader(filename, filesize, newUploaderConfiguration());
+ }
+
+ @Override
+ public NullUploaderConfiguration newUploaderConfiguration() {
+ // no configuration
+ return NullUploaderConfiguration.SHARED_INSTANCE;
+ }
+
+ @Override
+ public long getMaximumFilesize() {
+ // no filesize limit
+ return -1;
+ }
+
+ @Override
+ public String[] getSupportedExtensions() {
+ // no extension restriction
+ return null;
+ }
+
+ @Override
+ public CapabilityMatrix getUploadCapabilities() {
+ return new CapabilityMatrix(
+ UploaderCapability.UNAUTHENTICATED_UPLOAD);
+ }
+
+ @Override
+ public Downloader getDownloader(URI uri,
+ NullDownloaderConfiguration configuration) {
+ return new DownloaderImpl(uri, configuration);
+ }
+
+ @Override
+ public Downloader getDownloader(URI uri) {
+ return getDownloader(uri, newDownloaderConfiguration());
+ }
+
+ @Override
+ public NullDownloaderConfiguration newDownloaderConfiguration() {
+ return NullDownloaderConfiguration.SHARED_INSTANCE;
+ }
+
+ @Override
+ public boolean matchURI(URI uri) {
+ return DOWNLOAD_URL_PATTERN.matcher(uri.toString()).matches();
+ }
+
+ @Override
+ public CapabilityMatrix getDownloadCapabilities() {
+ return new CapabilityMatrix(
+ DownloaderCapability.UNAUTHENTICATED_DOWNLOAD,
+ DownloaderCapability.UNAUTHENTICATED_RESUME);
+ }
+
+ private class UploaderImpl extends
+ AbstractUploader implements
+ Uploader,
+ LinkedUploadChannelCloseCallback {
+ private Future uploadFuture;
+ private String uploadID;
+
+ public UploaderImpl(String filename, long filesize,
+ NullUploaderConfiguration configuration) {
+ super(TwoSharedService.this, filename, filesize, configuration);
+ }
+
+ @Override
+ public UploadChannel openChannel() throws IOException {
+ logger.debug("Starting upload to TwoShared");
+ final HTMLPage page = get("http://www.2shared.com/").asPage();
+
+ // locate upload uri
+ final String uri = page.findFormAction(UPLOAD_URL_PATTERN);
+ final String mainDC = page.getInputValue("mainDC");
+ uploadID = page.find(UPLOAD_ID_PATTERN, 1);
+
+ logger.debug("Upload URI: {}, DC: {}", uri, mainDC);
+
+ // create a new channel
+ final LinkedUploadChannel channel = createLinkedChannel(this);
+ uploadFuture = multipartPost(uri).parameter("fff", channel)
+ .parameter("mainDC", mainDC).asPageAsync();
+
+ // wait for channel link
+ return waitChannelLink(channel);
+ }
+
+ @Override
+ public String finish() throws IOException {
+ try {
+ uploadFuture.get();
+ final HTMLPage page = get(
+ "http://www.2shared.com/uploadComplete.jsp?sId="
+ + uploadID).asPage();
+ return page.getTextareaValueById("downloadLink");
+ } catch (InterruptedException e) {
+ return null;
+ } catch (ExecutionException e) {
+ ExceptionUtils.asIOException(e);
+ return null;
+ }
+ }
+ }
+
+ private class DownloaderImpl extends
+ AbstractHttpDownloader implements
+ Downloader {
+ /**
+ * @param uri
+ * the download uri
+ * @param configuration
+ * the downloader configuration
+ */
+ protected DownloaderImpl(URI uri,
+ NullDownloaderConfiguration configuration) {
+ super(TwoSharedService.this, uri, configuration);
+
+ }
+
+ @Override
+ public DownloadChannel openChannel(DownloadListener listener,
+ long position) throws IOException,
+ DownloadLinkNotFoundException, DownloadLimitExceededException,
+ DownloadNotAuthorizedException, DownloadNotResumableException,
+ UnsolvableCaptchaServiceException, NoCaptchaServiceException {
+ final HTMLPage page = get(uri).asPage();
+ final String downloadUri = page.findScript(
+ DIRECT_DOWNLOAD_URL_PATTERN, 0);
+ return download(get(downloadUri));
+ }
+ }
+}
diff --git a/httpchannel-service/httpchannel-service-2shared/src/main/resources/META-INF/services/com.rogiel.httpchannel.service.Service b/httpchannel-service/httpchannel-service-2shared/src/main/resources/META-INF/services/com.rogiel.httpchannel.service.Service
new file mode 100644
index 0000000..f928e5c
--- /dev/null
+++ b/httpchannel-service/httpchannel-service-2shared/src/main/resources/META-INF/services/com.rogiel.httpchannel.service.Service
@@ -0,0 +1 @@
+com.rogiel.httpchannel.service.twoshared.TwoSharedService
\ No newline at end of file
diff --git a/httpchannel-service/httpchannel-service-2shared/src/test/java/com/rogiel/httpchannel/service/twoshared/TwoSharedServiceTest.java b/httpchannel-service/httpchannel-service-2shared/src/test/java/com/rogiel/httpchannel/service/twoshared/TwoSharedServiceTest.java
new file mode 100644
index 0000000..b97000a
--- /dev/null
+++ b/httpchannel-service/httpchannel-service-2shared/src/test/java/com/rogiel/httpchannel/service/twoshared/TwoSharedServiceTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.rogiel.httpchannel.service.twoshared;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+import com.rogiel.httpchannel.service.Downloader;
+import com.rogiel.httpchannel.util.ChannelUtils;
+
+/**
+ * @author Rogiel
+ *
+ */
+public class TwoSharedServiceTest {
+ private final TwoSharedService service = new TwoSharedService();
+
+ @Test
+ public void testUpload() throws IOException {
+ final Path path = Paths
+ .get("../src/test/resources/upload-test-file.txt");
+ final URI uri = ChannelUtils.upload(service, path);
+
+ Assert.assertNotNull(uri);
+ System.out.println(uri);
+ }
+
+ @Test
+ public void testDownload() throws IOException {
+ final Downloader> downloader = service
+ .getDownloader(URI
+ .create("http://www.2shared.com/document/04tjgnAr/upload-test-file.html"));
+ System.out.println(new String(ChannelUtils.toByteArray(downloader.openChannel())));
+ }
+}
diff --git a/httpchannel-service/httpchannel-service-4shared/src/main/java/org/httpchannel/service/fourshared/FourSharedService.java b/httpchannel-service/httpchannel-service-4shared/src/main/java/org/httpchannel/service/fourshared/FourSharedService.java
index 09ab43b..96390ee 100644
--- a/httpchannel-service/httpchannel-service-4shared/src/main/java/org/httpchannel/service/fourshared/FourSharedService.java
+++ b/httpchannel-service/httpchannel-service-4shared/src/main/java/org/httpchannel/service/fourshared/FourSharedService.java
@@ -201,7 +201,7 @@ public class FourSharedService extends AbstractHttpService implements Service,
.parameter("FilePart", channel).asPageAsync();
// wait for channel link
- return waitChannelLink(channel, uploadFuture);
+ return waitChannelLink(channel);
} catch (ApiException e) {
throw new ChannelServiceException(e);
}
diff --git a/httpchannel-service/httpchannel-service-4shared/src/main/java/org/httpchannel/service/fourshared/FourSharedUploaderConfiguration.java b/httpchannel-service/httpchannel-service-4shared/src/main/java/org/httpchannel/service/fourshared/FourSharedUploaderConfiguration.java
new file mode 100644
index 0000000..9b8c87a
--- /dev/null
+++ b/httpchannel-service/httpchannel-service-4shared/src/main/java/org/httpchannel/service/fourshared/FourSharedUploaderConfiguration.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.httpchannel.service.fourshared;
+
+import com.rogiel.httpchannel.service.AbstractUploaderConfiguration;
+import com.rogiel.httpchannel.service.Uploader.DescriptionableUploaderConfiguration;
+import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
+
+/**
+ * Describes an configuration for an {@link UploaderImpl}
+ *
+ * @author Rogiel
+ */
+public class FourSharedUploaderConfiguration extends
+ AbstractUploaderConfiguration implements UploaderConfiguration,
+ DescriptionableUploaderConfiguration {
+ /**
+ * The upload description
+ */
+ private String description = DescriptionableUploaderConfiguration.DEFAULT_DESCRIPTION;
+
+ @Override
+ public String description() {
+ return description;
+ }
+
+ @Override
+ public FourSharedUploaderConfiguration description(String description) {
+ this.description = description;
+ return this;
+ }
+}
diff --git a/httpchannel-service/httpchannel-service-archetype/src/main/resources/archetype-resources/src/main/java/${serviceName}Service.java b/httpchannel-service/httpchannel-service-archetype/src/main/resources/archetype-resources/src/main/java/${serviceName}Service.java
index 0d0e29f..c29ceaa 100644
--- a/httpchannel-service/httpchannel-service-archetype/src/main/resources/archetype-resources/src/main/java/${serviceName}Service.java
+++ b/httpchannel-service/httpchannel-service-archetype/src/main/resources/archetype-resources/src/main/java/${serviceName}Service.java
@@ -135,7 +135,7 @@ public class ${serviceName}Service extends AbstractHttpService implements
uploadFuture = multipartPost(uri).parameter("[file-parameter]", channel).asPageAsync();
// wait for channel link
- return waitChannelLink(channel, uploadFuture);
+ return waitChannelLink(channel);
}
@Override
diff --git a/httpchannel-service/httpchannel-service-depositfiles/src/main/java/com/rogiel/httpchannel/service/depositfiles/DepositFilesService.java b/httpchannel-service/httpchannel-service-depositfiles/src/main/java/com/rogiel/httpchannel/service/depositfiles/DepositFilesService.java
index 6f596f5..3ba3a33 100644
--- a/httpchannel-service/httpchannel-service-depositfiles/src/main/java/com/rogiel/httpchannel/service/depositfiles/DepositFilesService.java
+++ b/httpchannel-service/httpchannel-service-depositfiles/src/main/java/com/rogiel/httpchannel/service/depositfiles/DepositFilesService.java
@@ -183,7 +183,7 @@ public class DepositFilesService extends AbstractHttpService implements
.parameter("UPLOAD_IDENTIFIER", uploadID)
.parameter("agree", true)
.parameter("MAX_FILE_SIZE", maxFileSize).asPageAsync();
- return waitChannelLink(channel, uploadFuture);
+ return waitChannelLink(channel);
}
@Override
diff --git a/httpchannel-service/httpchannel-service-filesonic/src/main/java/com/rogiel/httpchannel/service/filesonic/FileSonicService.java b/httpchannel-service/httpchannel-service-filesonic/src/main/java/com/rogiel/httpchannel/service/filesonic/FileSonicService.java
index 8de8480..338afae 100644
--- a/httpchannel-service/httpchannel-service-filesonic/src/main/java/com/rogiel/httpchannel/service/filesonic/FileSonicService.java
+++ b/httpchannel-service/httpchannel-service-filesonic/src/main/java/com/rogiel/httpchannel/service/filesonic/FileSonicService.java
@@ -174,7 +174,7 @@ public class FileSonicService extends AbstractHttpService implements Service,
final LinkedUploadChannel channel = createLinkedChannel(this);
uploadFuture = multipartPost(api.getUploadURI().toString())
.parameter("files[]", channel).asStringAsync();
- return waitChannelLink(channel, uploadFuture);
+ return waitChannelLink(channel);
}
@Override
diff --git a/httpchannel-service/httpchannel-service-hotfile/src/main/java/com/rogiel/httpchannel/service/hotfile/HotFileService.java b/httpchannel-service/httpchannel-service-hotfile/src/main/java/com/rogiel/httpchannel/service/hotfile/HotFileService.java
index c7903b9..2ae9da6 100644
--- a/httpchannel-service/httpchannel-service-hotfile/src/main/java/com/rogiel/httpchannel/service/hotfile/HotFileService.java
+++ b/httpchannel-service/httpchannel-service-hotfile/src/main/java/com/rogiel/httpchannel/service/hotfile/HotFileService.java
@@ -220,7 +220,7 @@ public class HotFileService extends AbstractHttpService implements Service,
uploadFuture = multipartPost(action)
.parameter("uploads[]", channel).asPageAsync();
- return waitChannelLink(channel, uploadFuture);
+ return waitChannelLink(channel);
}
@Override
diff --git a/httpchannel-service/httpchannel-service-megaupload/src/main/java/com/rogiel/httpchannel/service/megaupload/MegaUploadService.java b/httpchannel-service/httpchannel-service-megaupload/src/main/java/com/rogiel/httpchannel/service/megaupload/MegaUploadService.java
index 113f750..bdef075 100644
--- a/httpchannel-service/httpchannel-service-megaupload/src/main/java/com/rogiel/httpchannel/service/megaupload/MegaUploadService.java
+++ b/httpchannel-service/httpchannel-service-megaupload/src/main/java/com/rogiel/httpchannel/service/megaupload/MegaUploadService.java
@@ -232,7 +232,7 @@ public class MegaUploadService extends AbstractHttpService implements Service,
uploadFuture = multipartPost(uri)
.parameter("multimessage_0", configuration.description())
.parameter("multifile_0", channel).asStringAsync();
- return waitChannelLink(channel, uploadFuture);
+ return waitChannelLink(channel);
}
@Override
diff --git a/httpchannel-service/httpchannel-service-multiupload/src/main/java/com/rogiel/httpchannel/service/multiupload/MultiUploadService.java b/httpchannel-service/httpchannel-service-multiupload/src/main/java/com/rogiel/httpchannel/service/multiupload/MultiUploadService.java
index 9643205..ca3372d 100644
--- a/httpchannel-service/httpchannel-service-multiupload/src/main/java/com/rogiel/httpchannel/service/multiupload/MultiUploadService.java
+++ b/httpchannel-service/httpchannel-service-multiupload/src/main/java/com/rogiel/httpchannel/service/multiupload/MultiUploadService.java
@@ -239,7 +239,7 @@ public class MultiUploadService extends AbstractHttpService implements Service,
}
uploadFuture = request.asStringAsync();
- return waitChannelLink(channel, uploadFuture);
+ return waitChannelLink(channel);
}
@Override
diff --git a/httpchannel-service/httpchannel-service-uploadhere/src/main/java/com/rogiel/httpchannel/service/uploadhere/UploadHereService.java b/httpchannel-service/httpchannel-service-uploadhere/src/main/java/com/rogiel/httpchannel/service/uploadhere/UploadHereService.java
index 12f78ba..3e886c6 100644
--- a/httpchannel-service/httpchannel-service-uploadhere/src/main/java/com/rogiel/httpchannel/service/uploadhere/UploadHereService.java
+++ b/httpchannel-service/httpchannel-service-uploadhere/src/main/java/com/rogiel/httpchannel/service/uploadhere/UploadHereService.java
@@ -228,7 +228,7 @@ public class UploadHereService extends AbstractHttpService implements Service,
uploadFuture = multipartPost(uri).parameter("file_0", channel)
.parameter("u", userCookie)
.parameter("UPLOAD_IDENTIFIER", uploadID).asStringAsync();
- return waitChannelLink(channel, uploadFuture);
+ return waitChannelLink(channel);
}
@Override
diff --git a/httpchannel-service/httpchannel-service-uploadking/src/main/java/com/rogiel/httpchannel/service/uploadking/UploadKingService.java b/httpchannel-service/httpchannel-service-uploadking/src/main/java/com/rogiel/httpchannel/service/uploadking/UploadKingService.java
index c8ca826..8753cfb 100644
--- a/httpchannel-service/httpchannel-service-uploadking/src/main/java/com/rogiel/httpchannel/service/uploadking/UploadKingService.java
+++ b/httpchannel-service/httpchannel-service-uploadking/src/main/java/com/rogiel/httpchannel/service/uploadking/UploadKingService.java
@@ -228,7 +228,7 @@ public class UploadKingService extends AbstractHttpService implements Service,
uploadFuture = multipartPost(uri).parameter("file", channel)
.parameter("u", userCookie)
.parameter("UPLOAD_IDENTIFIER", uploadID).asStringAsync();
- return waitChannelLink(channel, uploadFuture);
+ return waitChannelLink(channel);
}
@Override
diff --git a/httpchannel-service/httpchannel-service-wupload/src/main/java/com/rogiel/httpchannel/service/wupload/WUploadService.java b/httpchannel-service/httpchannel-service-wupload/src/main/java/com/rogiel/httpchannel/service/wupload/WUploadService.java
index b854ceb..c8ae1f5 100644
--- a/httpchannel-service/httpchannel-service-wupload/src/main/java/com/rogiel/httpchannel/service/wupload/WUploadService.java
+++ b/httpchannel-service/httpchannel-service-wupload/src/main/java/com/rogiel/httpchannel/service/wupload/WUploadService.java
@@ -175,7 +175,7 @@ public class WUploadService extends AbstractHttpService implements Service,
final LinkedUploadChannel channel = createLinkedChannel(this);
uploadFuture = multipartPost(api.getUploadURI().toString())
.parameter("files[]", channel).asStringAsync();
- return waitChannelLink(channel, uploadFuture);
+ return waitChannelLink(channel);
}
@Override
diff --git a/httpchannel-service/httpchannel-service-zshare/src/main/java/com/rogiel/httpchannel/service/zshare/ZShareService.java b/httpchannel-service/httpchannel-service-zshare/src/main/java/com/rogiel/httpchannel/service/zshare/ZShareService.java
index bfe0c71..e644097 100644
--- a/httpchannel-service/httpchannel-service-zshare/src/main/java/com/rogiel/httpchannel/service/zshare/ZShareService.java
+++ b/httpchannel-service/httpchannel-service-zshare/src/main/java/com/rogiel/httpchannel/service/zshare/ZShareService.java
@@ -202,7 +202,7 @@ public class ZShareService extends AbstractHttpService implements Service/*
// .parameter("descr", configuration.description())
// .parameter("TOS", true).parameter("is_private", false)
// .asStringAsync();
- // return waitChannelLink(channel, uploadFuture);
+ // return waitChannelLink(channel);
// }
//
// @Override
diff --git a/httpchannel-service/pom.xml b/httpchannel-service/pom.xml
index 368a71f..45ddfe8 100644
--- a/httpchannel-service/pom.xml
+++ b/httpchannel-service/pom.xml
@@ -24,6 +24,7 @@
httpchannel-service-wupload
httpchannel-service-zshare
httpchannel-service-4shared
+ httpchannel-service-2shared
diff --git a/httpchannel-util/src/main/java/com/rogiel/httpchannel/service/AbstractHttpService.java b/httpchannel-util/src/main/java/com/rogiel/httpchannel/service/AbstractHttpService.java
index 398e01a..d3d275a 100644
--- a/httpchannel-util/src/main/java/com/rogiel/httpchannel/service/AbstractHttpService.java
+++ b/httpchannel-util/src/main/java/com/rogiel/httpchannel/service/AbstractHttpService.java
@@ -19,14 +19,14 @@
package com.rogiel.httpchannel.service;
import java.net.URI;
-import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
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;
+import com.rogiel.httpchannel.service.exception.UploadServiceException;
/**
* Abstract base service for HTTP enabled services.
@@ -38,13 +38,9 @@ public abstract class AbstractHttpService extends AbstractService implements
Service {
protected final HttpContext http = new HttpContext();
- protected LinkedUploadChannel waitChannelLink(LinkedUploadChannel channel,
- Future> future) {
- logger.debug("Waiting channel {} to link", channel);
- while (!channel.isLinked() && !future.isDone()) {
- ThreadUtils.sleep(100);
- }
- return channel;
+ protected LinkedUploadChannel waitChannelLink(LinkedUploadChannel channel)
+ throws UploadServiceException {
+ return channel.waitLink(20, TimeUnit.SECONDS);
}
public GetRequest get(String uri) {
diff --git a/httpchannel-util/src/main/java/com/rogiel/httpchannel/service/channel/LinkedUploadChannel.java b/httpchannel-util/src/main/java/com/rogiel/httpchannel/service/channel/LinkedUploadChannel.java
index 65b8681..cac98de 100644
--- a/httpchannel-util/src/main/java/com/rogiel/httpchannel/service/channel/LinkedUploadChannel.java
+++ b/httpchannel-util/src/main/java/com/rogiel/httpchannel/service/channel/LinkedUploadChannel.java
@@ -24,6 +24,9 @@ import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.WritableByteChannel;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,6 +35,7 @@ import com.rogiel.httpchannel.service.UploadChannel;
import com.rogiel.httpchannel.service.UploadService;
import com.rogiel.httpchannel.service.Uploader;
import com.rogiel.httpchannel.service.exception.UploadLinkNotFoundException;
+import com.rogiel.httpchannel.service.exception.UploadServiceException;
/**
* This channel is linked onto another {@link Channel} that actually writes data
@@ -45,6 +49,11 @@ public class LinkedUploadChannel implements UploadChannel {
*/
private final Logger logger = LoggerFactory.getLogger(this.getClass());
+ /**
+ * The synchronization phaser
+ */
+ private final Phaser phaser = new Phaser();
+
/**
* The upload service
*/
@@ -90,6 +99,9 @@ public class LinkedUploadChannel implements UploadChannel {
this.closeCallback = closeCallback;
this.filename = filename;
this.length = filesize;
+
+ // register on the phaser
+ phaser.register();
}
@Override
@@ -167,6 +179,7 @@ public class LinkedUploadChannel implements UploadChannel {
if (!channel.isOpen())
throw new IOException("The destination channel is closed");
this.channel = channel;
+ phaser.arrive();
}
/**
@@ -176,4 +189,28 @@ public class LinkedUploadChannel implements UploadChannel {
public boolean isLinked() {
return channel != null;
}
+
+ /**
+ * Waits for the channels to get linked
+ *
+ * @param timeout
+ * the amount of time to wait
+ * @param unit
+ * the time unit for the wait
+ *
+ * @throws UploadServiceException
+ * if the channel has not been linked after the timeout has
+ * expired
+ */
+ public LinkedUploadChannel waitLink(int timeout, TimeUnit unit)
+ throws UploadServiceException {
+ logger.debug("Waiting channel {} to link", this);
+ try {
+ phaser.awaitAdvanceInterruptibly(phaser.getPhase(), timeout, unit);
+ } catch (InterruptedException | TimeoutException e) {
+ throw new UploadServiceException("Channel has not linked in "
+ + timeout + " " + unit);
+ }
+ return this;
+ }
}
diff --git a/httpchannel-util/src/main/java/com/rogiel/httpchannel/util/htmlparser/HTMLPage.java b/httpchannel-util/src/main/java/com/rogiel/httpchannel/util/htmlparser/HTMLPage.java
index 41898a6..4f67f8d 100644
--- a/httpchannel-util/src/main/java/com/rogiel/httpchannel/util/htmlparser/HTMLPage.java
+++ b/httpchannel-util/src/main/java/com/rogiel/httpchannel/util/htmlparser/HTMLPage.java
@@ -35,6 +35,7 @@ import org.htmlparser.tags.ImageTag;
import org.htmlparser.tags.InputTag;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.tags.ScriptTag;
+import org.htmlparser.tags.TextareaTag;
import org.htmlparser.util.NodeIterator;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
@@ -184,17 +185,21 @@ public class HTMLPage {
public String getInputValueById(final String id) {
return inputValue(filter(InputTag.class, new InputIDFilter(id)));
}
-
- public int getInputValueByIdInt(final String id) {
- return Integer.parseInt(inputValue(filter(InputTag.class, new InputIDFilter(id))));
- }
+ public int getInputValueByIdInt(final String id) {
+ return Integer.parseInt(inputValue(filter(InputTag.class,
+ new InputIDFilter(id))));
+ }
public String getInputValue(final Pattern pattern) {
return inputValue(filter(InputTag.class, new InputValuePatternFilter(
pattern)));
}
+ public String getTextareaValueById(String id) {
+ return ((TextareaTag) getTagByID(id)).getStringText();
+ }
+
public Tag getTagByID(final String id) {
for (final Tag tag : filter(Tag.class, new IDFilter(id))) {
return tag;