From cd835e2064d299fb7c8c71ac8328b49c7040d440 Mon Sep 17 00:00:00 2001 From: Rogiel Date: Sun, 22 Jan 2012 21:58:01 -0200 Subject: [PATCH] Implements 2shared service and improves channel link synchronization --- .../httpchannel/service/AccountDetails.java | 17 +- .../httpchannel-service-2shared/pom.xml | 14 + .../service/twoshared/TwoSharedService.java | 241 ++++++++++++++++++ .../com.rogiel.httpchannel.service.Service | 1 + .../twoshared/TwoSharedServiceTest.java | 57 +++++ .../service/fourshared/FourSharedService.java | 2 +- .../FourSharedUploaderConfiguration.java | 48 ++++ .../src/main/java/${serviceName}Service.java | 2 +- .../depositfiles/DepositFilesService.java | 2 +- .../service/filesonic/FileSonicService.java | 2 +- .../service/hotfile/HotFileService.java | 2 +- .../service/megaupload/MegaUploadService.java | 2 +- .../multiupload/MultiUploadService.java | 2 +- .../service/uploadhere/UploadHereService.java | 2 +- .../service/uploadking/UploadKingService.java | 2 +- .../service/wupload/WUploadService.java | 2 +- .../service/zshare/ZShareService.java | 2 +- httpchannel-service/pom.xml | 1 + .../service/AbstractHttpService.java | 14 +- .../service/channel/LinkedUploadChannel.java | 37 +++ .../httpchannel/util/htmlparser/HTMLPage.java | 13 +- 21 files changed, 440 insertions(+), 25 deletions(-) create mode 100644 httpchannel-service/httpchannel-service-2shared/pom.xml create mode 100644 httpchannel-service/httpchannel-service-2shared/src/main/java/com/rogiel/httpchannel/service/twoshared/TwoSharedService.java create mode 100644 httpchannel-service/httpchannel-service-2shared/src/main/resources/META-INF/services/com.rogiel.httpchannel.service.Service create mode 100644 httpchannel-service/httpchannel-service-2shared/src/test/java/com/rogiel/httpchannel/service/twoshared/TwoSharedServiceTest.java create mode 100644 httpchannel-service/httpchannel-service-4shared/src/main/java/org/httpchannel/service/fourshared/FourSharedUploaderConfiguration.java 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;