package org.springframework.roo.url.stream; import java.io.IOException; import java.io.InputStream; import java.net.Authenticator; import java.net.HttpURLConnection; import java.net.Proxy; import java.net.ProxySelector; import java.net.URISyntaxException; import java.net.URL; import java.util.List; import java.util.logging.Level; import org.apache.commons.lang3.Validate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Service; import org.springframework.roo.shell.osgi.AbstractFlashingObject; import org.springframework.roo.url.stream.UrlInputStreamService; /** * Simple implementation of {@link UrlInputStreamService} that uses the JDK. * * @author Ben Alex * @since 1.1 */ @Component @Service public class JdkUrlInputStreamService extends AbstractFlashingObject implements UrlInputStreamService { private class ProgressIndicatingInputStream extends InputStream { private final InputStream delegate; private long lastNotified; private int lastPercentageIndicated = -1; private float readSoFar; private String text; private final float totalSize; /** * Constructor * * @param connection * @throws IOException */ public ProgressIndicatingInputStream(final HttpURLConnection connection) throws IOException { Validate.notNull(connection, "URL Connection required"); totalSize = connection.getContentLength(); delegate = connection.getInputStream(); text = connection.getURL().getPath(); if ("".equals(text)) { // Fall back to the host name text = connection.getURL().getHost(); } else { // We only want the filename final int lastSlash = text.lastIndexOf("/"); if (lastSlash > -1) { text = text.substring(lastSlash + 1); } } } @Override public void close() throws IOException { flash(Level.FINE, "", MY_SLOT); delegate.close(); } @Override public int read() throws IOException { readSoFar++; if (totalSize > 0) { // Total size is known final int percentageDownloaded = Math.round(readSoFar / totalSize * 100); if (System.currentTimeMillis() > lastNotified + 1000) { if (lastPercentageIndicated != percentageDownloaded) { flash(Level.FINE, "Downloaded " + percentageDownloaded + "% of " + text, MY_SLOT); lastPercentageIndicated = percentageDownloaded; lastNotified = System.currentTimeMillis(); } } } else { // Total size is not known, rely on time-based updates instead if (System.currentTimeMillis() > lastNotified + 1000) { flash(Level.FINE, "Downloaded " + Math.round(readSoFar / 1024) + " kB of " + text, MY_SLOT); lastNotified = System.currentTimeMillis(); } } final int result = delegate.read(); if (result == -1) { if (totalSize > 0) { flash(Level.FINE, "Downloaded 100% of " + text, MY_SLOT); } else { flash(Level.FINE, "Downloaded " + Math.round(readSoFar / 1024) + " kB of " + text, MY_SLOT); } flash(Level.FINE, "", MY_SLOT); } return result; } } public String getUrlCannotBeOpenedMessage(final URL httpUrl) { return null; } public InputStream openConnection(final URL httpUrl) throws IOException { Validate.notNull(httpUrl, "HTTP URL is required"); Validate.isTrue(httpUrl.getProtocol().equals("http"), "Only HTTP is supported (not %s)", httpUrl); final HttpURLConnection connection = prepareHttpUrlConnection(httpUrl); return new ProgressIndicatingInputStream(connection); } public HttpURLConnection prepareHttpUrlConnection(URL url) throws IOException { // Prepare proxy and proxy authentication Proxy proxy = setupProxy(url); Authenticator proxyAuthentication = setupProxyAuthentication(url, proxy); if (proxyAuthentication != null) { Authenticator.setDefault(proxyAuthentication); } HttpURLConnection connection = (HttpURLConnection) (proxy != null ? url.openConnection(proxy) : url.openConnection()); connection.setConnectTimeout(5000); connection.setReadTimeout(5000); connection.setUseCaches(false); return connection; } public Proxy setupProxy(URL url) { List<Proxy> proxies = null; try { proxies = ProxySelector.getDefault().select(url.toURI()); } catch (URISyntaxException e) { // this can't happen } if (proxies != null) { for (Proxy proxy : proxies) { if (proxy.type().equals(Proxy.Type.HTTP)) { return proxy; } } } return null; } public Authenticator setupProxyAuthentication(URL url, Proxy proxy) { return null; } }