/* * RHQ Management Platform * Copyright (C) 2005-2008 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.enterprise.server.plugins.url; import java.io.InputStream; import java.net.URL; import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.HostConfiguration; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethodBase; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.HeadMethod; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.rhq.core.domain.configuration.Configuration; /** * Similiar to the {@link UrlProvider} content source, but this expects the URL to use * the HTTP protocol. This provides the ability to go through an HTTP proxy. * * @author John Mazzitelli */ public class HttpProvider extends UrlProvider { private final Log log = LogFactory.getLog(HttpProvider.class); private String username; private String password; private String proxyUrl; private int proxyPort; private String proxyUsername; private String proxyPassword; @Override protected void setRootUrl(URL url) { if (!url.getProtocol().startsWith("http")) { throw new UnsupportedOperationException( "This content source cannot support a protocol other than HTTP: url=" + url); } super.setRootUrl(url); } @Override protected void setIndexUrl(URL url) { if (!url.getProtocol().startsWith("http")) { throw new UnsupportedOperationException( "This content source cannot support a protocol other than HTTP: index-url=" + url); } super.setIndexUrl(url); } @Override public void initialize(Configuration configuration) throws Exception { this.username = configuration.getSimpleValue("username", null); this.password = configuration.getSimpleValue("password", null); this.proxyUrl = configuration.getSimpleValue("proxyUrl", null); this.proxyUsername = configuration.getSimpleValue("proxyUsername", null); this.proxyPassword = configuration.getSimpleValue("proxyPassword", null); String port = configuration.getSimpleValue("proxyPort", null); if (port != null) { this.proxyPort = Integer.parseInt(port); } super.initialize(configuration); return; } @Override public void shutdown() { this.username = null; this.password = null; this.proxyUrl = null; this.proxyUsername = null; this.proxyPassword = null; this.proxyPort = 0; super.shutdown(); return; } @Override public void testConnection() throws Exception { HttpClient client = new HttpClient(); HeadMethod method = new HeadMethod(getRootUrl().toString()); prepareHttpClient(client, method); int status = client.executeMethod(method); if (status != HttpStatus.SC_OK) { throw new Exception("Content source failed connection test with status code=" + status); } return; } @Override public InputStream getInputStream(String location) throws Exception { URL fullUrl = new URL(getRootUrl().toString() + location); InputStream stream = getInputStreamForUrl(fullUrl); return stream; } @Override protected InputStream getIndexInputStream() throws Exception { InputStream stream = getInputStreamForUrl(getIndexUrl()); return stream; } /** * Given any URL, will return a stream to that URL using the HTTP client and GET method * for the authentication as defined in this content source's configuration. * * @param url the URL whose stream of content is returned * * @return stream containing the content for the given URL * * @throws Exception if cannot get the streamed content */ protected InputStream getInputStreamForUrl(URL url) throws Exception { String fullLocation = url.toString(); HttpClient client = new HttpClient(); HttpMethodBase method = new GetMethod(fullLocation); prepareHttpClient(client, method); int status = client.executeMethod(method); switch (status) { case HttpStatus.SC_OK: { break; // good to go } case HttpStatus.SC_NOT_FOUND: { throw new Exception("Could not find the content at URL [" + fullLocation + "]. Make sure the content source defines a valid URL."); } case HttpStatus.SC_UNAUTHORIZED: case HttpStatus.SC_FORBIDDEN: { throw new Exception("Invalid login credentials specified for user [" + username + "]. Make sure " + "this user is valid and the password specified for this content source is correct."); } default: { throw new Exception("Failed to retrieve content. status code=" + status); } } InputStream stream = method.getResponseBodyAsStream(); return stream; } /** * Given a client and the method to be used by that client, this will prepare those objects * so they can be used to get the remote content. * * @param client * @param method * * @throws Exception if the client cannot be prepared successfully */ protected void prepareHttpClient(HttpClient client, HttpMethodBase method) throws Exception { // prepare the client with proxy info, if appropriate configureProxy(client); // setup the authentication method.setFollowRedirects(true); if (this.username != null) { method.setDoAuthentication(true); org.apache.commons.httpclient.URI fullUri = method.getURI(); AuthScope authScope = new AuthScope(fullUri.getHost(), fullUri.getPort(), AuthScope.ANY_REALM); Credentials credentials = new UsernamePasswordCredentials(this.username, this.password); client.getState().setCredentials(authScope, credentials); } return; } /** * If proxy information was specified, configures the client to use it. * * @param client client being used in the invocation */ protected void configureProxy(HttpClient client) { if (this.proxyUrl != null) { if (log.isDebugEnabled()) { log.debug("Configuring HTTP proxy. url [" + this.proxyUrl + "]; port [" + this.proxyPort + "]"); } HostConfiguration hostConfiguration = client.getHostConfiguration(); hostConfiguration.setProxy(this.proxyUrl, this.proxyPort); // If a proxy username was specified, indicate it as the proxy credentials if (this.proxyUsername != null) { if (log.isDebugEnabled()) { log.debug("Configuring feed for authenticating proxy. proxy-user: " + this.proxyUsername); } AuthScope proxyAuthScope = new AuthScope(this.proxyUrl, this.proxyPort, AuthScope.ANY_REALM); Credentials proxyCredentials = new UsernamePasswordCredentials(this.proxyUsername, this.proxyPassword); client.getState().setProxyCredentials(proxyAuthScope, proxyCredentials); } } return; } }