/** * Licensed to JumpMind Inc under one or more contributor * license agreements. See the NOTICE file distributed * with this work for additional information regarding * copyright ownership. JumpMind Inc licenses this file * to you under the GNU General Public License, version 3.0 (GPLv3) * (the "License"); you may not use this file except in compliance * with the License. * * You should have received a copy of the GNU General Public License, * version 3.0 (GPLv3) along with this library; if not, see * <http://www.gnu.org/licenses/>. * * 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.jumpmind.symmetric.transport.http; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import org.apache.commons.io.IOUtils; import org.jumpmind.symmetric.common.ParameterConstants; import org.jumpmind.symmetric.service.IParameterService; import org.jumpmind.symmetric.service.RegistrationNotOpenException; import org.jumpmind.symmetric.service.RegistrationRequiredException; import org.jumpmind.symmetric.transport.AuthenticationException; import org.jumpmind.symmetric.transport.ConnectionRejectedException; import org.jumpmind.symmetric.transport.IIncomingTransport; import org.jumpmind.symmetric.transport.ServiceUnavailableException; import org.jumpmind.symmetric.transport.SyncDisabledException; import org.jumpmind.symmetric.transport.TransportUtils; import org.jumpmind.symmetric.web.WebConstants; public class HttpIncomingTransport implements IIncomingTransport { private HttpURLConnection connection; private BufferedReader reader; private InputStream is; private IParameterService parameterService; private int httpTimeout; private String redirectionUrl; public HttpIncomingTransport(HttpURLConnection connection, IParameterService parameterService) { this.connection = connection; this.parameterService = parameterService; this.httpTimeout = parameterService.getInt(ParameterConstants.TRANSPORT_HTTP_TIMEOUT); } public String getUrl() { return this.connection.getURL().toExternalForm(); } public void close() { if (reader != null) { IOUtils.closeQuietly(reader); reader = null; } if (is != null) { IOUtils.closeQuietly(is); is = null; } } public boolean isOpen() { return reader != null; } public String getRedirectionUrl() { return redirectionUrl; } public InputStream openStream() throws IOException { boolean manualRedirects = parameterService.is(ParameterConstants.TRANSPORT_HTTP_MANUAL_REDIRECTS_ENABLED, true); if (manualRedirects) { connection = this.openConnectionCheckRedirects(connection); } switch (connection.getResponseCode()) { case WebConstants.REGISTRATION_NOT_OPEN: throw new RegistrationNotOpenException(); case WebConstants.REGISTRATION_REQUIRED: throw new RegistrationRequiredException(); case WebConstants.SYNC_DISABLED: throw new SyncDisabledException(); case WebConstants.SC_SERVICE_BUSY: throw new ConnectionRejectedException(); case WebConstants.SC_SERVICE_UNAVAILABLE: throw new ServiceUnavailableException(); case WebConstants.SC_FORBIDDEN: throw new AuthenticationException(); default: is = HttpTransportManager.getInputStreamFrom(connection); return is; } } public BufferedReader openReader() throws IOException { InputStream is = openStream(); reader = TransportUtils.toReader(is); return reader; } /** * This method support redirection from an http connection to an https connection. * See {@link http://java.sun.com/j2se/1.4.2/docs/guide/deployment/deployment-guide/upgrade-guide/article-17.html} * for more information. * * @param connection * @return * @throws IOException */ private HttpURLConnection openConnectionCheckRedirects(HttpURLConnection connection) throws IOException { boolean redir; int redirects = 0; do { connection.setInstanceFollowRedirects(false); redir = false; int stat = connection.getResponseCode(); if (stat >= 300 && stat <= 307 && stat != 306 && stat != HttpURLConnection.HTTP_NOT_MODIFIED) { URL base = connection.getURL(); redirectionUrl = connection.getHeaderField("Location"); URL target = null; if (redirectionUrl != null) { target = new URL(base, redirectionUrl); } connection.disconnect(); // Redirection should be allowed only for HTTP and HTTPS // and should be limited to 5 redirections at most. if (target == null || !(target.getProtocol().equals("http") || target.getProtocol().equals("https")) || redirects >= 5) { throw new SecurityException("illegal URL redirect"); } redir = true; connection = HttpTransportManager.openConnection(target, getBasicAuthUsername(), getBasicAuthPassword()); connection.setConnectTimeout(httpTimeout); connection.setReadTimeout(httpTimeout); redirects++; } } while (redir); return connection; } protected String getBasicAuthUsername() { return parameterService.getString(ParameterConstants.TRANSPORT_HTTP_BASIC_AUTH_USERNAME); } protected String getBasicAuthPassword() { return parameterService.getString(ParameterConstants.TRANSPORT_HTTP_BASIC_AUTH_PASSWORD); } }