/*
* 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;
}
}