/** * Copyright (c) 2009 Juwi MacMillan Group GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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 de.juwimm.cms.common.http; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.Properties; import javax.net.ssl.SSLPeerUnverifiedException; import org.apache.commons.httpclient.Credentials; 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.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.NTCredentials; import org.apache.commons.httpclient.URIException; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.auth.InvalidCredentialsException; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory; import org.apache.log4j.Logger; import de.juwimm.cms.common.ClientDesEncrypter; import de.juwimm.cms.common.HttpMessages; /** * <p> * Title: Tizzit * </p> * <p> * Description: Enterprise Content Management * </p> * <p> * Copyright: Copyright (c) 2004 * </p> * * @author <a href="sascha.kulawik@juwimm.com">Sascha-Matthias Kulawik</a> * @version $Revision: 1.1 $ */ public class HttpClientWrapper { private static final String CQ_HTTP_PPROXY_PASSWORD_ENCRYPTED = "cqHttpPproxyPasswordEncrypted"; public static final AuthScope AUTHSCOPE_ANY = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM); private static Logger log = Logger.getLogger(HttpClientWrapper.class); private static HttpClientWrapper instance = null; private MultiThreadedHttpConnectionManager connectionManager = null; private String httpProxyHost = null; private String httpProxyPort = null; private static String httpProxyUser = null; private static String httpProxyPassword = null; private static boolean useNTproxy = false; private Properties fileProp = null; private final File propFile = new File(System.getProperty("user.home") + System.getProperty("file.separator") + ".tizzit"); private final HashMap<String, HostConfiguration> hostMap = new HashMap<String, HostConfiguration>(); public static HttpClientWrapper getInstance() { if (instance == null) { instance = new HttpClientWrapper(); } return instance; } protected HttpClientWrapper() { // Protocol.registerProtocol("https", new Protocol("https", new // EasySSLProtocolSocketFactory(), 443)); Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) new SSLProtocolSocketFactory(), 443)); System.setProperty("java.protocol.handler.pkgs", "org.apache.commons.httpclient"); connectionManager = new MultiThreadedHttpConnectionManager(); connectionManager.getParams().setDefaultMaxConnectionsPerHost(20); connectionManager.getParams().setMaxTotalConnections(40); connectionManager.getParams().setStaleCheckingEnabled(true); setHttpProxyHost(System.getProperty("https.proxyHost")); setHttpProxyPort(System.getProperty("https.proxyPort")); if (propFile.exists()) { try { FileInputStream fis = new FileInputStream(propFile); fileProp = new Properties(); fileProp.load(fis); fis.close(); setHttpProxyUser(fileProp.getProperty("http.proxyUser", "").toString()); // setHttpProxyPassword(fileProp.getProperty("http.proxyPassword", // "").toString()); setHttpProxyPassword(fileProp.getProperty(HttpClientWrapper.CQ_HTTP_PPROXY_PASSWORD_ENCRYPTED, "no").equalsIgnoreCase("no") ? fileProp.getProperty("http.proxyPassword").toString() : new ClientDesEncrypter().decrypt(fileProp.getProperty("http.proxyPassword"))); } catch (Exception exe) { log.error("Could not update the localuser properties from the .tizzit file", exe); } } } public boolean isUsingProxy() { return (getHttpProxyHost() == null || getHttpProxyHost().equalsIgnoreCase("")) ? false : true; } public String getProxyServer() { return getHttpProxyHost(); } /** * save in ${user.home}\.conquest (e.g. %USERPROFILE%\.tizzit in windows) * encrypt password always decrypt only if cqHttpPproxyPasswordEncrypted=yes * in ${user.home}\.tizzit * */ protected void saveProperties(boolean save) { if (save == true) { if (fileProp == null) { fileProp = new Properties(); } fileProp.setProperty("http.proxyUser", getHttpProxyUser()); fileProp.setProperty("http.proxyPassword", new ClientDesEncrypter().encrypt(getHttpProxyPassword())); fileProp.setProperty(HttpClientWrapper.CQ_HTTP_PPROXY_PASSWORD_ENCRYPTED, "yes"); try { if (propFile.exists()) { propFile.delete(); } propFile.createNewFile(); FileOutputStream fos = new FileOutputStream(propFile, false); fileProp.store(fos, "Local Tizzit Properties"); fos.close(); } catch (Exception exe) { log.error("Error saving to .tizzit File: ", exe); } } } public synchronized String getString(URL destUrl) throws IOException { return getString(destUrl, null, null); } public synchronized String getString(URL destUrl, String userName, String password) throws IOException { HttpMethodBase method = invoke(destUrl, userName, password); String charSet = method.getRequestCharSet(); String retString = new String(method.getResponseBodyAsString().getBytes(charSet)); method.releaseConnection(); return retString; } public synchronized String getString(String destUrl) throws IOException { return getString(destUrl, null, null); } public synchronized String getString(String destUrl, String userName, String password) throws IOException { HttpMethodBase method = invoke(destUrl, userName, password); String retString = method.getResponseBodyAsString(); method.releaseConnection(); return retString; } public synchronized byte[] getByte(String destUrl) throws IOException { return getByte(destUrl, null, null); } public synchronized byte[] getByte(String destUrl, String userName, String password) throws IOException { HttpMethodBase method = invoke(destUrl, userName, password); byte[] retArr; retArr = method.getResponseBody(); method.releaseConnection(); return retArr; } protected HttpMethodBase invoke(String destUrl, String userName, String password) throws URIException { // HttpMethodBase method = null; URL targetURL = null; try { targetURL = new URL(destUrl); } catch (MalformedURLException exe) { log.error("this url is not valid: " + destUrl, exe); } return (targetURL != null) ? invoke(targetURL, userName, password) : null; } protected HttpMethodBase invoke(URL targetURL, String userName, String password) throws URIException { HttpMethodBase method = null; if (log.isDebugEnabled()) log.debug(targetURL.toExternalForm()); method = new GetMethod(targetURL.toExternalForm()); HttpClient httpClient = getNewHttpClient(); if (userName != null) { // Credentials for destination URL Credentials cred = new UsernamePasswordCredentials(userName, password); httpClient.getParams().setAuthenticationPreemptive(true); httpClient.getState().setCredentials(AUTHSCOPE_ANY, cred); } setHostConfiguration(httpClient, targetURL); String returnMessage = null; int returnCode = 500; try { returnCode = httpClient.executeMethod(method); } catch (InvalidCredentialsException exe) { if (log.isInfoEnabled()) log.info("Invalid credentials trying to authenticate: " + exe.getMessage()); } catch (HttpException exe) { log.error("while connection to: " + targetURL.getHost() + " an unknown error occured (HttpException): " + exe.getMessage()); } catch (SSLPeerUnverifiedException exe) { returnCode = 516; returnMessage = exe.getMessage(); } catch (IOException exe) { log.error("while connection to: " + targetURL.getHost() + " using Proxy: " + this.isUsingProxy() + " host: " + this.getHttpProxyHost() + " on Port: " + this.httpProxyPort + " together: " + this.getProxyServer() + " an unknown error occured (IOException): " + targetURL.toExternalForm() + " " + exe.getMessage()); } catch (Exception exe) { log.error("while connection to: " + targetURL.getHost() + " an unknown error occured: " + exe.getMessage()); } if ((returnCode > 199) && (returnCode < 300)) { // return is OK - so fall through if (log.isDebugEnabled()) log.debug("good return code: " + returnCode); } else if (returnCode == 401) { returnMessage = HttpMessages.getString("HttpClientWrapper.401_authRequired"); } else if (returnCode == 404) { returnMessage = HttpMessages.getString("HttpClientWrapper.404_notFound"); } else if (returnCode == 407) { returnMessage = HttpMessages.getString("HttpClientWrapper.407_proxyAuthRequired"); } else if (returnCode == 403) { returnMessage = HttpMessages.getString("HttpClientWrapper.403_Forbidden"); } else if (returnCode == 503) { returnMessage = HttpMessages.getString("HttpClientWrapper.503_ServiceUnavailable"); } else if (returnCode == 504) { returnMessage = HttpMessages.getString("HttpClientWrapper.504_ProxyTimeout"); } else if (returnCode == 516) { returnMessage = HttpMessages.getString("HttpClientWrapper.516_SSLPeerUnverified", returnMessage); } else { returnMessage = "Unknown error with return code " + returnCode; } if (returnMessage != null) { throw new URIException(returnCode, returnMessage); } return method; } public HttpClient getNewHttpClient() { HttpClient client = new HttpClient(connectionManager); return client; } public void setHostConfiguration(HttpClient client, URL targetURL) { int port = targetURL.getPort(); String host = targetURL.getHost(); HostConfiguration config = hostMap.get(host + ":" + port); if (config == null) { config = new HostConfiguration(); if (port == -1) { if (targetURL.getProtocol().equalsIgnoreCase("https")) { port = 443; } else { port = 80; } } config.setHost(host, port, targetURL.getProtocol()); } // in the meantime HttpProxyUser and HttpProxyPasword might have changed // (DlgUsernamePassword) or now trying NTLM instead of BASE // authentication if (getHttpProxyHost() != null && getHttpProxyPort() != null && getHttpProxyHost().length() > 0 && getHttpProxyPort().length() > 0) { client.getParams().setAuthenticationPreemptive(true); int proxyPort = new Integer(getHttpProxyPort()).intValue(); config.setProxy(getHttpProxyHost(), proxyPort); if (getHttpProxyUser() != null && getHttpProxyUser().length() > 0) { Credentials proxyCred = null; if (isUseNTproxy()) { proxyCred = new NTCredentials(getHttpProxyUser(), getHttpProxyPassword(), getHttpProxyHost(), ""); } else { proxyCred = new UsernamePasswordCredentials(getHttpProxyUser(), getHttpProxyPassword()); } client.getState().setProxyCredentials(AUTHSCOPE_ANY, proxyCred); } } hostMap.put(host + ":" + port, config); client.setHostConfiguration(config); } /** * @param httpProxyHost * The httpProxyHost to set. */ protected void setHttpProxyHost(String httpProxyHost) { this.httpProxyHost = httpProxyHost; } /** * @return Returns the httpProxyHost. */ protected String getHttpProxyHost() { return httpProxyHost; } /** * @param httpProxyPort * The httpProxyPort to set. */ protected void setHttpProxyPort(String httpProxyPort) { this.httpProxyPort = httpProxyPort; } /** * @return Returns the httpProxyPort. */ protected String getHttpProxyPort() { return httpProxyPort; } /** * @param httpProxyUser * The httpProxyUser to set. */ protected void setHttpProxyUser(String httpProxyUser) { HttpClientWrapper.httpProxyUser = httpProxyUser; } /** * @return Returns the httpProxyUser. */ protected String getHttpProxyUser() { return httpProxyUser; } /** * @param httpProxyPassword * The httpProxyPassword to set. */ protected void setHttpProxyPassword(String httpProxyPassword) { HttpClientWrapper.httpProxyPassword = httpProxyPassword; } /** * @return Returns the httpProxyPassword. */ protected String getHttpProxyPassword() { return httpProxyPassword; } /** * @param useNTproxy * The useNTproxy to set. */ protected void setUseNTproxy(boolean useNTproxy) { this.useNTproxy = useNTproxy; } /** * @return Returns the useNTproxy. */ protected boolean isUseNTproxy() { return useNTproxy; } }