All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.nc2.util.net.HTTPSession Maven / Gradle / Ivy

Go to download

The NetCDF-Java Library is a Java interface to NetCDF files, as well as to many other types of scientific data formats.

The newest version!
/*
 * Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
 *
 * Portions of this software were developed by the Unidata Program at the
 * University Corporation for Atmospheric Research.
 *
 * Access and use of this software shall impose the following obligations
 * and understandings on the user. The user is granted the right, without
 * any fee or cost, to use, copy, modify, alter, enhance and distribute
 * this software, and any derivative works thereof, and its supporting
 * documentation for any purpose whatsoever, provided that this entire
 * notice appears in all copies of the software, derivative works and
 * supporting documentation.  Further, UCAR requests that the user credit
 * UCAR/Unidata in any publications that result from the use of this
 * software or in any product that includes this software. The names UCAR
 * and/or Unidata, however, may not be used in any advertising or publicity
 * to endorse or promote any products or commercial entity unless specific
 * written permission is obtained from UCAR/Unidata. The user also
 * understands that UCAR/Unidata is not obligated to provide the user with
 * any support, consulting, training or assistance of any kind with regard
 * to the use, operation and performance of this software nor to provide
 * the user with any updates, revisions, new versions or "bug fixes."
 *
 * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package ucar.nc2.util.net;

import net.jcip.annotations.NotThreadSafe;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.auth.CredentialsProvider;
import org.apache.commons.httpclient.params.*;
import org.apache.commons.httpclient.protocol.Protocol;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * A session is encapsulated in an instance of the class
 * HTTPSession.  The encapsulation is with respect to a specific url
 * This means that once a session is
 * specified, it is tied permanently to that url.
 * 

*

* It is important to note that Session objects do NOT correspond * with the HttpClient objects of the Apache httpclient library. * A Session does, however, encapsulate an instance of an Apache HttpClient. *

* It is possible to specify a url when invoking, for example, * HTTPMethod.Get. This is because the url argument to the * HTTPSession constructor actually serves two purposes. First, if * the method is created without specifying a url, then the session * url is used to specify the data to be retrieved by the method * invocation. Second, if the method is created and specifies a * url, for example, HTTPMethod m = HTTPMethod.Get(session,url2); * this second url is used to specify the data to be retrieved by * the method invocation. This might (and does) occur if, for * example, the url given to HTTPSession represented some general * url such as http://motherlode.ucar.edu/path/file.nc and the url * given to HTTPMethod.Get was for something more specific such as * http://motherlode.ucar.edu/path/file.nc.dds. *

* The important point is that in this second method, the url must * be "compatible" with the session url. The term "compatible" * basically means that the HTTPSession url, as a string, must be a * prefix of the url given to HTTPMethod.Get. This maintains the * semantics of the Session but allows flexibility in accessing data * from the server. *

* Note that the term legalurl means that the url has reserved * characters within identifieers in escaped form. This is * particularly and issue for queries. Especially: ?x[0:5] is legal * and the square brackets need not be encoded. *

* Finally, note that if the session was created with no url then all method * constructions must specify a url. */ @NotThreadSafe public class HTTPSession { ////////////////////////////////////////////////// // Constants static final public HTTPAuthScheme BASIC = HTTPAuthScheme.BASIC; static final public HTTPAuthScheme DIGEST = HTTPAuthScheme.DIGEST; static final public HTTPAuthScheme NTLM = HTTPAuthScheme.NTLM; static final public HTTPAuthScheme SSL = HTTPAuthScheme.SSL; static public int SC_NOT_FOUND = HttpStatus.SC_NOT_FOUND; static public int SC_UNAUTHORIZED = HttpStatus.SC_UNAUTHORIZED; static public int SC_OK = HttpStatus.SC_OK; static public String CONNECTION_TIMEOUT = HttpConnectionParams.CONNECTION_TIMEOUT; static public String SO_TIMEOUT = HttpMethodParams.SO_TIMEOUT; static public String ALLOW_CIRCULAR_REDIRECTS = HttpClientParams.ALLOW_CIRCULAR_REDIRECTS; static public String MAX_REDIRECTS = HttpClientParams.MAX_REDIRECTS; static public String USER_AGENT = HttpMethodParams.USER_AGENT; static public String PROTOCOL_VERSION = HttpMethodParams.PROTOCOL_VERSION; static public String VIRTUAL_HOST = HttpMethodParams.VIRTUAL_HOST; static public String USE_EXPECT_CONTINUE = HttpMethodParams.USE_EXPECT_CONTINUE; static public String STRICT_TRANSFER_ENCODING = HttpMethodParams.STRICT_TRANSFER_ENCODING; static public String HTTP_ELEMENT_CHARSET = HttpMethodParams.HTTP_ELEMENT_CHARSET; static public String HTTP_CONTENT_CHARSET = HttpMethodParams.HTTP_CONTENT_CHARSET; /*fix:*/ static public String HTTP_CONNECTION = ""; static public String HTTP_PROXY_HOST = ""; static public String HTTP_REQ_SENT = ""; static public String HTTP_REQUEST = ""; static public String HTTP_RESPONSE = ""; static public String HTTP_TARGET_HOST = ""; static public String ORIGIN_SERVER = ""; static public String WAIT_FOR_CONTINUE = ""; static int DFALTTHREADCOUNT = 50; static int DFALTTIMEOUT = 5 * 60 * 1000; // 5 minutes (300000 milliseconds) ////////////////////////////////////////////////////////////////////////// //Type Declarations static class Proxy { String host = null; int port = -1; } static enum Methods { Get("get"), Head("head"), Put("put"), Post("post"), Options("options"); private final String name; Methods(String name) { this.name = name; } public String getName() { return name; } } // We need more powerful protocol registry. static class ProtocolEntry { public String protocol = null; public int port = 0; public Protocol handler; public ProtocolEntry(String protocol, int port, Protocol handler) { this.protocol = protocol; this.port = port; this.handler = handler; } } //////////////////////////////////////////////////////////////////////// // Static variables static public org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(HTTPSession.class); static MultiThreadedHttpConnectionManager connmgr; //fix: protected static SchemeRegistry schemes; static String globalAgent = "/NetcdfJava/HttpClient3"; static int threadcount = DFALTTHREADCOUNT; static boolean globalauthpreemptive = false; static int globalSoTimeout = 0; static int globalConnectionTimeout = 0; static Proxy globalproxy = null; static List registry; static { connmgr = new MultiThreadedHttpConnectionManager(); setGlobalThreadCount(DFALTTHREADCOUNT); registry = new ArrayList(); // Fill in the registry for our various https ports // allow self-signed certificates registerProtocol("https", 0, new Protocol("https", new EasySSLProtocolSocketFactory(), 443)); // default registerProtocol("https", 8443, new Protocol("https", new EasySSLProtocolSocketFactory(), 8443)); // std tomcat https entry setGlobalConnectionTimeout(DFALTTIMEOUT); setGlobalSoTimeout(DFALTTIMEOUT); getGlobalProxyD(); // get info from -D if possible setGlobalKeyStore(); } ////////////////////////////////////////////////////////////////////////// // Static Methods (Mostly global accessors) static synchronized public void setGlobalUserAgent(String _userAgent) { globalAgent = _userAgent; } static public String getGlobalUserAgent() { return globalAgent; } static public void setGlobalThreadCount(int nthreads) { connmgr.getParams().setMaxTotalConnections(nthreads); connmgr.getParams().setDefaultMaxConnectionsPerHost(nthreads); } // Alias static public void setGlobalMaxConnections(int nthreads) { setGlobalThreadCount(nthreads); } static public int getGlobalThreadCount() { return connmgr.getParams().getMaxTotalConnections(); } static public Cookie[] getGlobalCookies() { HttpClient client = new HttpClient(connmgr); Cookie[] cookies = client.getState().getCookies(); return cookies; } // Replace org.apache.commons.httpclient.protocol.Protocol.register() // This is done because the handler must depend on both the protocol // (e.g https) as well as the port. One hopes this is fixed // in apache httpclient v4. static synchronized public void registerProtocol(String protocol, int port, Protocol handler) throws IllegalArgumentException { if(protocol == null) throw new IllegalArgumentException(); if(port < 0) port = 0; // port == 0 is wildcard, so use standard Protocol registry if(port == 0) {// look to the standard protocol registry if(handler == null) Protocol.unregisterProtocol(protocol); else Protocol.registerProtocol(protocol, handler); } else { for(int i = 0;i < registry.size();i++) { ProtocolEntry entry = registry.get(i); if(!entry.protocol.equals(protocol)) continue; if(entry.port != port) continue; if(handler == null) registry.remove(i); //delete else entry.handler = handler; // replace return; } registry.add(new ProtocolEntry(protocol, port, handler)); } } static synchronized public Protocol getProtocol(String protocol, int port) throws IllegalArgumentException, IllegalStateException { ProtocolEntry entry = null; if(protocol == null) throw new IllegalArgumentException(); if(port < 0) port = 0; // port == 0 is wildcard if(port == 0) { return Protocol.getProtocol(protocol); // may throw exception } for(int i = 0;i < registry.size();i++) { entry = registry.get(i); if(!entry.protocol.equals(protocol)) continue; if(entry.port != port) continue; return entry.handler; } // Retry with port 0 Protocol p = Protocol.getProtocol(protocol); // may throw exception if(p == null) throw new IllegalStateException(); // no such protocol X port return p; } // Timeouts static public void setConnectionManagerTimeout(int timeout) { setGlobalConnectionTimeout(timeout); } static public void setGlobalConnectionTimeout(int timeout) { connmgr.getParams().setConnectionTimeout(timeout); } static public void setGlobalSoTimeout(int timeout) { globalSoTimeout = timeout; } // Proxy static synchronized public void setGlobalProxy(String host, int port) { if(globalproxy == null) { globalproxy = new Proxy(); globalproxy.host = host; globalproxy.port = port; } } // Authorization static synchronized public void setGlobalAuthenticationPreemptive(boolean tf) { globalauthpreemptive = tf; } static synchronized private void defineCredentialsProvider(HTTPAuthScheme scheme, String url, CredentialsProvider provider) { // Add/remove entry to AuthStore try { if(provider == null) {//remove HTTPAuthStore.remove(new HTTPAuthStore.Entry(scheme, url, provider)); } else { // add HTTPAuthStore.insert(new HTTPAuthStore.Entry(scheme, url, provider)); } } catch (HTTPException he) { log.error("HTTPSession.setCredentialsProvider failed"); } } static public void setAnyCredentialsProvider(HTTPAuthScheme scheme, String url, CredentialsProvider provider) { defineCredentialsProvider(scheme, url, provider); } static public void setGlobalCredentialsProvider(HTTPAuthScheme scheme, CredentialsProvider provider) { setAnyCredentialsProvider(scheme, HTTPAuthStore.ANY_URL, provider); } static public void setGlobalCredentialsProvider(CredentialsProvider provider) { setGlobalCredentialsProvider(HTTPAuthStore.DEFAULT_SCHEME, provider); } // Assumes that user info exists in the url and we can // use it to build a simple UsernamePasswordCredentials as our provider. static public void setGlobalCredentialsProvider(String url) { // Try to extract user info String userinfo = getUserinfo(url); if(userinfo != null) { int index = userinfo.indexOf(':'); String user = userinfo.substring(index); String pwd = userinfo.substring(index + 1, userinfo.length()); if(user != null && pwd != null) { // Create a non-interactive user+pwd handler HTTPBasicProvider bp = new HTTPBasicProvider(user, pwd); setGlobalCredentialsProvider(HTTPAuthScheme.BASIC, bp); } } } // It is convenient to be able to directly set the Credentials // (not the provider) when those credentials are fixed. static public void setGlobalCredentials(HTTPAuthScheme scheme, Credentials creds) { CredentialsProvider provider = new HTTPCredsProvider(creds); defineCredentialsProvider(scheme, HTTPAuthStore.ANY_URL, provider); } // Static Utilitiy functions static String getUserinfo(String surl) { try { URL url = new URL(surl); return url.getUserInfo(); } catch (MalformedURLException mue) { return null; } } static public String getCanonicalURL(String legalurl) { if(legalurl == null) return null; int index = legalurl.indexOf('?'); if(index >= 0) legalurl = legalurl.substring(0, index); // remove any trailing extension //index = legalurl.lastIndexOf('.'); //if(index >= 0) legalurl = legalurl.substring(0,index); return canonicalpath(legalurl); } /** * Convert path to use '/' consistently and * to remove any trailing '/' * * @param path convert this path * @return canonicalized version */ static public String canonicalpath(String path) { if(path == null) return null; path = path.replace('\\', '/'); if(path.endsWith("/")) path = path.substring(0, path.length() - 1); return path; } static public String removeprincipal(String u) { // Must be a simpler way String newurl = null; try { int index; URL url = new URL(u); String protocol = url.getProtocol() + "://"; String host = url.getHost(); int port = url.getPort(); String path = url.getPath(); String query = url.getQuery(); String ref = url.getRef(); String sport = (port <= 0 ? "" : (":" + port)); path = (path == null ? "" : path); query = (query == null ? "" : "?" + query); ref = (ref == null ? "" : "#" + ref); // rebuild the url // (and leaving encoding in place) newurl = protocol + host + sport + path + query + ref; } catch (MalformedURLException use) { newurl = u; } return newurl; } static public String getUrlAsString(String url) throws HTTPException { HTTPSession session = new HTTPSession(url); HTTPMethod m = HTTPMethod.Get(session); int status = m.execute(); String content = null; if(status == 200) { content = m.getResponseAsString(); } m.close(); return content; } static public int putUrlAsString(String content, String url) throws HTTPException { HTTPSession session = new HTTPSession(url); HTTPMethod m = HTTPMethod.Put(session); m.setRequestContentAsString(content); int status = m.execute(); m.close(); return status; } static String getstorepath(String prefix) { String path = System.getProperty(prefix + "store"); if(path != null) { path = path.trim(); if(path.length() == 0) path = null; } return path; } static String getpassword(String prefix) { String password = System.getProperty(prefix + "storepassword"); if(password != null) { password = password.trim(); if(password.length() == 0) password = null; } return password; } static String cleanproperty(String property) { String value = System.getProperty(property); if(value != null) { value = value.trim(); if(value.length() == 0) value = null; } return value; } // Provide for backward compatibility // through the -D properties static synchronized void setGlobalKeyStore() { String keypassword = cleanproperty("keystorepassword"); String keypath = cleanproperty("keystore"); String trustpassword = cleanproperty("truststorepassword"); String trustpath = cleanproperty("truststore"); if(keypath != null || trustpath != null) { // define conditionally HTTPSSLProvider sslprovider = new HTTPSSLProvider(keypath, keypassword, trustpath, trustpassword); setAnyCredentialsProvider(HTTPAuthScheme.SSL, HTTPAuthStore.ANY_URL, sslprovider); } } // For backward compatibility, provide // programmatic access for setting proxy info // Extract proxy info from command line -D parameters // extended 5/7/2012 to get NTLM domain // H/T: [email protected] static void getGlobalProxyD() { Proxy proxy = new Proxy(); String host = System.getProperty("http.proxyHost"); String port = System.getProperty("http.proxyPort"); int portno = -1; if(host != null) { host = host.trim(); if(host.length() == 0) host = null; } if(port != null) { port = port.trim(); if(port.length() > 0) { try { portno = Integer.parseInt(port); } catch (NumberFormatException nfe) { portno = -1; } } } if(host != null) { proxy.host = host; proxy.port = portno; globalproxy = proxy; } } ////////////////////////////////////////////////// // Instance variables HttpClient sessionClient = null; List methodList = new Vector(); HttpState context = null; String identifier = "Session"; String useragent = null; String legalurl = null; boolean closed = false; ////////////////////////////////////////////////// // Constructor(s) public HTTPSession(String legalurl) throws ucar.nc2.util.net.HTTPException { construct(legalurl); } public HTTPSession() throws HTTPException { this(null); } protected void construct(String legalurl) throws HTTPException { this.legalurl = legalurl; try { sessionClient = new HttpClient(connmgr); HttpClientParams clientparams = sessionClient.getParams(); // Allow (circular) redirects clientparams.setParameter(ALLOW_CIRCULAR_REDIRECTS, true); clientparams.setParameter(MAX_REDIRECTS, 25); if(globalSoTimeout > 0) setSoTimeout(globalSoTimeout); if(globalConnectionTimeout > 0) setConnectionTimeout(globalConnectionTimeout); if(globalAgent != null) setUserAgent(globalAgent); // May get overridden by setUserAgent setAuthenticationPreemptive(globalauthpreemptive); setProxy(); if(TESTING) HTTPSession.track(this); } catch (Exception e) { throw new HTTPException("url=" + legalurl, e); } } public String getURL() { return this.legalurl; } public void setUserAgent(String agent) { useragent = agent; if(useragent != null && sessionClient != null) sessionClient.getParams().setParameter(USER_AGENT, useragent); } public void setAuthenticationPreemptive(boolean tf) { if(sessionClient != null) sessionClient.getParams().setAuthenticationPreemptive(tf); } public void setSoTimeout(int timeout) { sessionClient.getParams().setSoTimeout(timeout); } public void setConnectionTimeout(int timeout) { sessionClient.setConnectionTimeout(timeout); } //fix: public void setStateX(HttpState cxt) {sessionState = cxt;} /** * Close the session. This implies closing * any open methods. */ synchronized public void close() { if(closed) return; // multiple calls ok while(methodList.size() > 0) { HTTPMethod m = methodList.get(0); m.close(); // forcibly close; will invoke removemethod(). } closed = true; } public String getCookiePolicy() { return sessionClient == null ? null : sessionClient.getParams().getCookiePolicy(); } public Cookie[] getCookies() { if(sessionClient == null) return null; Cookie[] cookies = sessionClient.getState().getCookies(); return cookies; } synchronized void addMethod(HTTPMethod m) { if(!methodList.contains(m)) methodList.add(m); } synchronized void removeMethod(HTTPMethod m) { methodList.remove(m); } public void setMaxRedirects(int n) { HttpClientParams clientparams = sessionClient.getParams(); clientparams.setParameter(MAX_REDIRECTS, n); } public void setContext(HttpState cxt) { context = cxt; } public HttpState getContext() { return context; } public void clearState() { sessionClient.getState().clearCookies(); sessionClient.getState().clearCredentials(); } ////////////////////////////////////////////////// // Possibly authenticating proxy // All proxy activity goes thru here void setProxy(Proxy proxy) { if(sessionClient == null) return; if(proxy != null && proxy.host != null) sessionClient.getHostConfiguration().setProxy(proxy.host, proxy.port); } void setProxy() { if(globalproxy == null) return; setProxy(globalproxy); } // These are externally visible public void setProxy(String host, int port) { Proxy proxy = new Proxy(); proxy.host = host; proxy.port = port; setProxy(proxy); } ////////////////////////////////////////////////// // Authorization // per-session versions of the global accessors public void setCredentialsProvider(HTTPAuthScheme scheme, CredentialsProvider provider) { defineCredentialsProvider(scheme, legalurl, provider); } public void setCredentialsProvider(CredentialsProvider provider) { setCredentialsProvider(HTTPAuthStore.DEFAULT_SCHEME, provider); } // Assumes that user info exists in the url and we can // use it to build a simple UsernamePasswordCredentials as our provider. // Also assume this is a compatible url to the Session url public void setCredentialsProvider(String url) { // Try to extract user info String userinfo = getUserinfo(url); if(userinfo != null) { int index = userinfo.indexOf(':'); String user = userinfo.substring(index); String pwd = userinfo.substring(index + 1, userinfo.length()); if(user != null && pwd != null) { // Create a non-interactive user+pwd handler CredentialsProvider bp = new HTTPBasicProvider(user, pwd); setCredentialsProvider(HTTPAuthScheme.BASIC, bp); } } } public void setCredentials(HTTPAuthScheme scheme, Credentials creds) { CredentialsProvider provider = new HTTPCredsProvider(creds); defineCredentialsProvider(scheme, legalurl, provider); } ////////////////////////////////////////////////// // Testing support // Expose the state for testing purposes public boolean isClosed() { return this.closed; } public int getMethodcount() { return methodList.size(); } // Provide a way to kill everything at the end of a Test // When testing, we need to be able to clean up // all existing sessions because JUnit can run all // test within a single jvm. static List sessionList = null; // List of all HTTPSession instances // only used when testing flag is set static public boolean TESTING = false; // set to true during testing, should be false otherwise static private synchronized void kill() { if(sessionList != null) { for(HTTPSession session : sessionList) { session.close(); } sessionList.clear(); // Rebuild the connection manager connmgr.shutdown(); connmgr = new MultiThreadedHttpConnectionManager(); setGlobalThreadCount(DFALTTHREADCOUNT); } } // If we are testing, then track the sessions for kill static private synchronized void track(HTTPSession session) { if(sessionList == null) sessionList = new ArrayList(); sessionList.add(session); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy