/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2005-2006, JBoss Inc.
*/
package org.jboss.soa.esb.actions.soap;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.log4j.Logger;
import org.jboss.internal.soa.esb.util.StreamUtils;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.actions.routing.http.HttpMethodFactory;
import org.jboss.soa.esb.actions.soap.adapter.JBossWSFactory;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.http.HttpClientFactory;
import org.jboss.soa.esb.util.ClassUtil;
/**
* {@link HttpClientFactory} based WSLD loader.
* <p/>
* We use this in order to support different authentication modes that
* may be required for WSDL lookup.
*
* @author <a href="mailto:tom.fennelly@jboss.com">tom.fennelly@jboss.com</a>
*/
public class RemoteWsdlLoader {
private static Logger logger = Logger.getLogger(RemoteWsdlLoader.class);
private HttpClient httpClient;
private ConfigTree config;
public RemoteWsdlLoader(Properties httpClientProps) throws ConfigurationException {
httpClient = HttpClientFactory.createHttpClient(httpClientProps);
this.config = generateConfig(httpClientProps);
}
public InputStream load(String url, String charsetNameOverride) throws IOException {
if (httpClient == null) {
throw new IOException("RemoteWsdlLoader already shutdown") ;
}
InputStream originalStream = null;
byte[] originalBytes = null;
String charsetNameDetected = null;
// file, vfs, vfsfile, vfsjar, vfsmemory, vfszip, zip
if(url.startsWith("file") || url.startsWith("vfs") || url.startsWith("zip")) {
originalStream = new URL(url).openStream();
} else if(url.startsWith(JBossWSFactory.ESB_INTERNAL_URI)) {
originalStream = JBossWSFactory.getFactory().getWsdl(url) ;
} else if(url.startsWith("classpath://")) {
originalStream = ClassUtil.getResource(url.substring(12, url.length()), getClass()).openStream();
} else {
HttpMethodBase httpMethod;
try {
HttpMethodFactory methodFactory = HttpMethodFactory.Factory.getInstance("GET", config, new URL(url));
httpMethod = methodFactory.getInstance(null);
} catch (ConfigurationException ce) {
throw (IOException)(new IOException(ce.getMessage()).initCause(ce));
}
// Authentication is not being overridden on the method. It needs
// to be present on the supplied HttpClient instance!
httpMethod.setDoAuthentication(true);
try {
int result = httpClient.executeMethod(httpMethod);
if(result != HttpStatus.SC_OK) {
if(result < 200 || result > 299) {
throw new HttpException("Received status code '" + result + "' on WSDL HTTP (GET) request: '" + url + "'.");
} else {
logger.warn("Received status code '" + result + "' on WSDL HTTP (GET) request: '" + url + "'.");
}
}
originalBytes = httpMethod.getResponseBody();
charsetNameDetected = httpMethod.getResponseCharSet();
} finally {
httpMethod.releaseConnection();
}
}
String charsetName = (charsetNameOverride != null ? charsetNameOverride : charsetNameDetected);
if (charsetName != null) {
charsetName = charsetName.trim().toUpperCase();
if (charsetName.equals("UTF-8") || charsetName.equals("UTF8")) {
// short-circuit conversion; it's already UTF-8
charsetName = null;
}
}
if (charsetName != null) {
// conversion WILL happen
if (originalStream != null) {
String read = StreamUtils.readStreamString(originalStream, charsetName);
return new ByteArrayInputStream(read.getBytes("UTF-8"));
} else if (originalBytes != null) {
String read = new String(originalBytes, charsetName);
return new ByteArrayInputStream(read.getBytes("UTF-8"));
}
} else {
// conversion will NOT happen
if (originalStream != null) {
return originalStream;
} else if (originalBytes != null) {
return new ByteArrayInputStream(originalBytes);
}
}
throw new IOException("null data; could not load url: " + url + " with charsetName: " + charsetName);
}
public void shutdown() {
HttpClientFactory.shutdown(httpClient);
httpClient = null ;
}
private static ConfigTree generateConfig(final Properties properties) {
final ConfigTree config = new ConfigTree("RemoteWsdlLoader");
final Set<Entry<Object, Object>> entrySet = properties.entrySet();
for (Entry<Object, Object> entry: entrySet) {
final Object key = entry.getKey();
final Object value = entry.getValue();
if ((key != null) && (value!=null)) {
config.setAttribute(key.toString(), value.toString());
}
}
return config;
}
}