Java tutorial
/* * Copyright 2013 Sigurd Randoll <srandoll@digiway.de>. * * Licensed 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 de.digiway.rapidbreeze.server.model.storage.provider; import de.digiway.rapidbreeze.server.model.storage.AuthenticationStatus; import de.digiway.rapidbreeze.server.model.storage.FileStatus; import de.digiway.rapidbreeze.server.model.storage.StorageProviderDownloadClient; import de.digiway.rapidbreeze.server.model.storage.UrlStatus; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.PoolingClientConnectionManager; import org.apache.http.impl.cookie.BasicClientCookie; /** * {@linkplain StorageProviderDownloadClient} implementation for the * One-Click-Hoster Share-Online at http://www.share-online.biz/. An example * link to a file hosted at Share-Online looks like this: * http://www.share-online.biz/dl/KJGPO5GMLZ * * @author Sigurd Randoll <srandoll@digiway.de> */ public class ShareOnlineBiz implements StorageProviderDownloadClient { private DefaultHttpClient httpClient; private String username = null; private String password = null; private AuthenticationStatus currentAuthenticationStatus; public static final String USER_ACCOUNT_QUERY = "http://api.share-online.biz/cgi-bin?q=userdetails&username=%s&password=%s"; public static final String URL_STATUS_QUERY = "http://api.share-online.biz/linkcheck.php?links=%s"; public static final String URL_DETERMINE_QUERY = "http://api.share-online.biz/cgi-bin?q=linkdata&username=%s&password=%s&lid=%s"; public ShareOnlineBiz() { ClientConnectionManager connectionManager = new PoolingClientConnectionManager(); this.httpClient = new DefaultHttpClient(connectionManager); this.currentAuthenticationStatus = AuthenticationStatus.NOT_AUTHENTICATED; } @Override public InputStream start(URL url, long offset) throws IOException { if (!currentAuthenticationStatus.equals(AuthenticationStatus.AUTHENTICATED)) { throw new IllegalStateException("The client hasn't been authenticated at the storage provider " + this + ". Free downloading isn't supported yet."); } if (!getUrlStatus(url).getFileStatus().equals(FileStatus.OK)) { throw new IllegalStateException("The file at the location " + url + " is not available."); } Properties props = new Properties(); HttpResponse response; String query = String.format(URL_DETERMINE_QUERY, username, password, getLinkId(url)); HttpGet httpGet = new HttpGet(query); try { response = httpClient.execute(httpGet); props.load(response.getEntity().getContent()); } finally { httpGet.releaseConnection(); } httpGet = new HttpGet(props.getProperty("URL")); if (offset > 0) { httpGet.addHeader("Range", "bytes=" + offset + "-"); } response = httpClient.execute(httpGet); if (offset > 0 && response.getStatusLine().getStatusCode() != 206) { throw new IllegalArgumentException("The server does not support resuming. Returning status code:" + response.getStatusLine().getStatusCode()); } return response.getEntity().getContent(); } @Override public void authenticate(String username, String password) { this.username = username; this.password = password; InputStream is = null; try { String accountInfoUrl = String.format(USER_ACCOUNT_QUERY, username, password); HttpGet get = new HttpGet(accountInfoUrl); HttpResponse resp = httpClient.execute(get); is = resp.getEntity().getContent(); Properties props = new Properties(); props.load(is); is.close(); // Auth string String a = props.getProperty("a"); if (a == null || a.isEmpty()) { throw new IOException( "Cannot authenticate user '" + username + "' at storage provider " + toString()); } BasicClientCookie authCookie = new BasicClientCookie("a", a); authCookie.setDomain("share-online.biz"); httpClient.getCookieStore().addCookie(authCookie); currentAuthenticationStatus = AuthenticationStatus.AUTHENTICATED; } catch (IOException ex) { Logger.getLogger(ShareOnlineBiz.class.getName()).log(Level.SEVERE, null, ex); currentAuthenticationStatus = AuthenticationStatus.AUTHENTICATION_FAILED; } finally { IOUtils.closeQuietly(is); } } private String getLinkId(URL url) { if (url == null) { throw new IllegalStateException("URL is not yet set."); } String path = url.getPath(); String[] split = path.split("/dl/"); if (split.length != 2) { throw new IllegalStateException("Cannot retrieve link id from response path:" + path); } return split[1]; } @Override public UrlStatus getUrlStatus(final URL url) { if (url == null) { throw new IllegalStateException("URL has not yet been set."); } String linkId = getLinkId(url); String query = String.format(URL_STATUS_QUERY, linkId); try { HttpGet get = new HttpGet(query); HttpResponse resp = httpClient.execute(get); String content = IOUtils.toString(resp.getEntity().getContent()); final String[] split = content.split(";"); if (split.length != 3 && split.length != 4) { throw new IllegalStateException( "API of " + getName() + " has been changed. Cannot determine link status."); } final boolean ok = split.length == 4 ? true : false; return new UrlStatus() { @Override public String getFilename() { if (ok) { return split[2].trim(); } return ""; } @Override public Long getFileSize() { if (ok) { return Long.parseLong(split[3].trim()); } return 0L; } @Override public FileStatus getFileStatus() { if (ok && "OK".equals(split[1])) { return FileStatus.OK; } return FileStatus.NOT_AVAILABLE; } @Override public String getMd5() { return null; // TODO: // throw new UnsupportedOperationException("Not supported yet."); } @Override public String getUrl() { return url.toString(); } }; } catch (IOException | RuntimeException ex) { Logger.getLogger(ShareOnlineBiz.class.getName()).log(Level.SEVERE, null, ex); return new UrlStatus() { @Override public String getFilename() { return ""; } @Override public Long getFileSize() { return 0L; } @Override public FileStatus getFileStatus() { return FileStatus.NOT_AVAILABLE; } @Override public String getMd5() { return null; } @Override public String getUrl() { return url.toString(); } }; } } @Override public AuthenticationStatus getAuthenticationStatus() { return currentAuthenticationStatus; } @Override public String getName() { return "Share-Online"; } @Override public String toString() { return getName(); } @Override public boolean canHandle(URL url) { String host = url.getHost().toLowerCase(); if (host.startsWith("www.share-online.biz") || host.startsWith("share-online.biz")) { return true; } return false; } }