[thredds] Initial import (#978569).
gil
gil at fedoraproject.org
Sat Oct 19 22:40:17 UTC 2013
commit 3eb714a54ceb1702aa64261b6a41c8c6b8f778e0
Author: gil <puntogil at libero.it>
Date: Sun Oct 20 00:40:05 2013 +0200
Initial import (#978569).
.gitignore | 1 +
sources | 1 +
thredds-4.3.16-cdm-jna35.patch | 20 +
thredds-4.3.18-cdm-http4.patch | 7877 ++++++++++++++++++++
...m-use-proper-system-environment-variables.patch | 86 +
thredds-create-tarball.sh | 46 +
thredds.spec | 205 +
7 files changed, 8236 insertions(+), 0 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index e69de29..3c4fbb9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/thredds-4.3.19-clean.tar.xz
diff --git a/sources b/sources
index e69de29..edf0c0d 100644
--- a/sources
+++ b/sources
@@ -0,0 +1 @@
+22db7d87fd2f7d70632fcc8e8e1476b1 thredds-4.3.19-clean.tar.xz
diff --git a/thredds-4.3.16-cdm-jna35.patch b/thredds-4.3.16-cdm-jna35.patch
new file mode 100644
index 0000000..59e5195
--- /dev/null
+++ b/thredds-4.3.16-cdm-jna35.patch
@@ -0,0 +1,20 @@
+--- cdm/src/main/java/ucar/nc2/jni/netcdf/Nc4prototypes.java 2013-03-19 20:51:13.000000000 +0100
++++ cdm/src/main/java/ucar/nc2/jni/netcdf/Nc4prototypes.java-gil 2013-08-16 00:34:49.555818432 +0200
+@@ -41,6 +41,7 @@
+ import com.sun.jna.ptr.FloatByReference;
+ import com.sun.jna.ptr.NativeLongByReference;
+
++import java.util.List;
+ import java.nio.ByteBuffer;
+
+ /**
+@@ -103,6 +104,9 @@
+ //public int p; /* Length of VL data (in base type units) */
+ //public NativeLong len; /* Length of VL data (in base type units) */
+ public Pointer p; /* Pointer to VL data */
++ public List getFieldOrder() {
++ throw new UnsupportedOperationException("Not supported.");
++ }
+ }
+
+ // library
diff --git a/thredds-4.3.18-cdm-http4.patch b/thredds-4.3.18-cdm-http4.patch
new file mode 100644
index 0000000..20fc2f0
--- /dev/null
+++ b/thredds-4.3.18-cdm-http4.patch
@@ -0,0 +1,7877 @@
+diff -Nru thredds-4.3.18/cdm/pom.xml thredds-4.3.18-gil/cdm/pom.xml
+--- thredds-4.3.18/cdm/pom.xml 2013-09-16 07:46:40.731501204 +0200
++++ thredds-4.3.18-gil/cdm/pom.xml 2013-09-16 07:48:00.294303813 +0200
+@@ -36,8 +36,16 @@
+
+ <!-- HTTP client -->
+ <dependency>
+- <groupId>commons-httpclient</groupId>
+- <artifactId>commons-httpclient</artifactId>
++ <groupId>org.apache.httpcomponents</groupId>
++ <artifactId>httpclient</artifactId>
++ </dependency>
++ <dependency>
++ <groupId>org.apache.httpcomponents</groupId>
++ <artifactId>httpcore</artifactId>
++ </dependency>
++ <dependency>
++ <groupId>org.apache.httpcomponents</groupId>
++ <artifactId>httpmime</artifactId>
+ </dependency>
+
+ <dependency> <!-- replace commons-logging -->
+diff -Nru thredds-4.3.18/cdm/src/main/java/thredds/util/HttpUriResolver.java thredds-4.3.18-gil/cdm/src/main/java/thredds/util/HttpUriResolver.java
+--- thredds-4.3.18/cdm/src/main/java/thredds/util/HttpUriResolver.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/thredds/util/HttpUriResolver.java 2013-09-16 06:58:52.563136337 +0200
+@@ -1,181 +1,179 @@
+-/*
+- * 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 thredds.util;
+-
+-import ucar.nc2.util.net.HTTPException;
+-import ucar.nc2.util.net.HTTPMethod;
+-import ucar.nc2.util.net.HTTPSession;
+-import org.apache.commons.httpclient.Header;
+-
+-import java.io.*;
+-import java.net.URI;
+-import java.util.zip.GZIPInputStream;
+-import java.util.zip.InflaterInputStream;
+-import java.util.Map;
+-import java.util.HashMap;
+-
+-/**
+- * _more_
+- *
+- * @author edavis
+- * @since 4.0
+- */
+-public class HttpUriResolver
+-{
+- private org.slf4j.Logger logger =
+- org.slf4j.LoggerFactory.getLogger( HttpUriResolver.class );
+-
+- private URI uri;
+- private int connectionTimeout;
+- private int socketTimeout;
+- private String contentEncoding = "gzip,deflate";
+- private boolean allowContentEncoding;
+- private boolean followRedirects;
+-
+- private HTTPMethod method = null;
+- private Map<String,String> respHeaders;
+-
+- HttpUriResolver( URI uri, int connectionTimeout, int socketTimeout,
+- boolean allowContentEncoding,
+- boolean followRedirects )
+- {
+- if ( ! uri.getScheme().equalsIgnoreCase( "http" ) )
+- throw new IllegalArgumentException( "Given a Non-HTTP URI [" + uri.toString() + "].");
+-
+- this.uri = uri;
+- this.connectionTimeout = connectionTimeout;
+- this.socketTimeout = socketTimeout;
+- this.allowContentEncoding = allowContentEncoding;
+- this.followRedirects = followRedirects;
+- }
+-
+- public void close()
+- {
+- if(method != null) method.close();
+- }
+- public URI getUri() { return this.uri; }
+- public long getConnectionTimeout() { return this.connectionTimeout; }
+- public int getSocketTimeout() { return this.socketTimeout; }
+- public String getContentEncoding() { return this.contentEncoding; }
+- public boolean getAllowContentEncoding() { return this.allowContentEncoding; }
+- public boolean getFollowRedirects() { return this.followRedirects; }
+-
+- public void makeRequest()
+- throws IOException
+- {
+- if ( method != null )
+- throw new IllegalStateException( "Request already made.");
+-
+- this.method = getHttpResponse( uri );
+- }
+-
+- public int getResponseStatusCode()
+- {
+- if ( method == null )
+- throw new IllegalStateException( "Request has not been made." );
+- return this.method.getStatusCode();
+- }
+-
+- public String getResponseStatusText()
+- {
+- if ( method == null )
+- throw new IllegalStateException( "Request has not been made." );
+- return this.method.getStatusText();
+- }
+-
+- public Map<String,String> getResponseHeaders()
+- {
+- if ( method == null )
+- throw new IllegalStateException( "Request has not been made." );
+-
+- if ( this.respHeaders == null )
+- {
+- this.respHeaders = new HashMap<String,String>();
+- Header[] headers = this.method.getResponseHeaders();
+- for ( Header h : headers )
+- this.respHeaders.put( h.getName(), h.getValue() );
+- }
+-
+- return respHeaders;
+- }
+-
+- public String getResponseHeaderValue( String name )
+- {
+- if ( method == null )
+- throw new IllegalStateException( "Request has not been made." );
+-
+- Header responseHeader = this.method.getResponseHeader( name );
+- return responseHeader == null ? null : responseHeader.getValue();
+- }
+-
+- public InputStream getResponseBodyAsInputStream()
+- throws IOException
+- {
+- if ( method == null )
+- throw new IllegalStateException( "Request has not been made." );
+-
+- InputStream is = method.getResponseAsStream();
+- Header contentEncodingHeader = method.getResponseHeader( "Content-Encoding" );
+- if ( contentEncodingHeader != null )
+- {
+- String contentEncoding = contentEncodingHeader.getValue();
+- if ( contentEncoding != null )
+- {
+- if ( contentEncoding.equalsIgnoreCase( "gzip" ) )
+- return new GZIPInputStream( is );
+- else if ( contentEncoding.equalsIgnoreCase( "deflate" ) )
+- return new InflaterInputStream( is );
+- }
+- }
+- return is;
+- }
+-
+- private HTTPMethod getHttpResponse( URI uri )
+- throws IOException, HTTPException
+- {
+- HTTPMethod method = HTTPMethod.Get(uri.toString() );
+- method.getSession().setConnectionTimeout( this.connectionTimeout );
+- method.getSession().setSoTimeout( this.socketTimeout );
+- method.setFollowRedirects( this.followRedirects );
+- method.setRequestHeader( "Accept-Encoding", this.contentEncoding );
+-
+- method.execute();
+- int statusCode = method.getStatusCode();
+- if ( statusCode == 200 || statusCode == 201 )
+- {
+- return method;
+- }
+-
+- return null; // ToDo throw exception with some informative inforamtion.
+- }
+-}
++/*
++ * 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 thredds.util;
++
++import ucar.nc2.util.net.*;
++import org.apache.http.Header;
++
++import java.io.*;
++import java.net.URI;
++import java.util.zip.GZIPInputStream;
++import java.util.zip.InflaterInputStream;
++import java.util.Map;
++import java.util.HashMap;
++
++/**
++ * _more_
++ *
++ * @author edavis
++ * @since 4.0
++ */
++public class HttpUriResolver
++{
++ private org.slf4j.Logger logger =
++ org.slf4j.LoggerFactory.getLogger( HttpUriResolver.class );
++
++ private URI uri;
++ private int connectionTimeout;
++ private int socketTimeout;
++ private String contentEncoding = "gzip,deflate";
++ private boolean allowContentEncoding;
++ private boolean followRedirects;
++
++ private HTTPMethod method = null;
++ private Map<String,String> respHeaders;
++
++ HttpUriResolver( URI uri, int connectionTimeout, int socketTimeout,
++ boolean allowContentEncoding,
++ boolean followRedirects )
++ {
++ if ( ! uri.getScheme().equalsIgnoreCase( "http" ) )
++ throw new IllegalArgumentException( "Given a Non-HTTP URI [" + uri.toString() + "].");
++
++ this.uri = uri;
++ this.connectionTimeout = connectionTimeout;
++ this.socketTimeout = socketTimeout;
++ this.allowContentEncoding = allowContentEncoding;
++ this.followRedirects = followRedirects;
++ }
++
++ public void close()
++ {
++ if(method != null) method.close();
++ }
++ public URI getUri() { return this.uri; }
++ public long getConnectionTimeout() { return this.connectionTimeout; }
++ public int getSocketTimeout() { return this.socketTimeout; }
++ public String getContentEncoding() { return this.contentEncoding; }
++ public boolean getAllowContentEncoding() { return this.allowContentEncoding; }
++ public boolean getFollowRedirects() { return this.followRedirects; }
++
++ public void makeRequest()
++ throws IOException
++ {
++ if ( method != null )
++ throw new IllegalStateException( "Request already made.");
++
++ this.method = getHttpResponse( uri );
++ }
++
++ public int getResponseStatusCode()
++ {
++ if ( method == null )
++ throw new IllegalStateException( "Request has not been made." );
++ return this.method.getStatusCode();
++ }
++
++ public String getResponseStatusText()
++ {
++ if ( method == null )
++ throw new IllegalStateException( "Request has not been made." );
++ return this.method.getStatusText();
++ }
++
++ public Map<String,String> getResponseHeaders()
++ {
++ if ( method == null )
++ throw new IllegalStateException( "Request has not been made." );
++
++ if ( this.respHeaders == null )
++ {
++ this.respHeaders = new HashMap<String,String>();
++ Header[] headers = this.method.getResponseHeaders();
++ for ( Header h : headers )
++ this.respHeaders.put( h.getName(), h.getValue() );
++ }
++
++ return respHeaders;
++ }
++
++ public String getResponseHeaderValue( String name )
++ {
++ if ( method == null )
++ throw new IllegalStateException( "Request has not been made." );
++
++ Header responseHeader = this.method.getResponseHeader( name );
++ return responseHeader == null ? null : responseHeader.getValue();
++ }
++
++ public InputStream getResponseBodyAsInputStream()
++ throws IOException
++ {
++ if ( method == null )
++ throw new IllegalStateException( "Request has not been made." );
++
++ InputStream is = method.getResponseAsStream();
++ Header contentEncodingHeader = method.getResponseHeader( "Content-Encoding" );
++ if ( contentEncodingHeader != null )
++ {
++ String contentEncoding = contentEncodingHeader.getValue();
++ if ( contentEncoding != null )
++ {
++ if ( contentEncoding.equalsIgnoreCase( "gzip" ) )
++ return new GZIPInputStream( is );
++ else if ( contentEncoding.equalsIgnoreCase( "deflate" ) )
++ return new InflaterInputStream( is );
++ }
++ }
++ return is;
++ }
++
++ private HTTPMethod getHttpResponse( URI uri )
++ throws IOException, HTTPException
++ {
++ HTTPMethod method = HTTPFactory.Get(uri.toString());
++ method.getSession().setConnectionTimeout( this.connectionTimeout );
++ method.getSession().setSoTimeout( this.socketTimeout );
++ method.setFollowRedirects( this.followRedirects );
++ method.setRequestHeader( "Accept-Encoding", this.contentEncoding );
++
++ method.execute();
++ int statusCode = method.getStatusCode();
++ if ( statusCode == 200 || statusCode == 201 )
++ {
++ return method;
++ }
++
++ return null; // ToDo throw exception with some informative inforamtion.
++ }
++}
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/dataset/NetcdfDataset.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/dataset/NetcdfDataset.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/dataset/NetcdfDataset.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/dataset/NetcdfDataset.java 2013-09-16 07:19:34.501934905 +0200
+@@ -57,8 +57,9 @@
+ import java.net.*;
+ import java.util.*;
+
+-import org.apache.commons.httpclient.Header;
++import org.apache.http.Header;
+ import thredds.catalog.ServiceType;
++import ucar.nc2.util.net.HTTPFactory;
+ import ucar.unidata.util.StringUtil2;
+ import ucar.unidata.util.Urlencoded;
+
+@@ -119,7 +120,13 @@
+
+ public class NetcdfDataset extends ucar.nc2.NetcdfFile {
+
+- /**
++
++ /**
++ * Define the legal Winoows drive letters
++ */
++ static final String DRIVE_LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
++
++ /**
+ * Possible enhancements for a NetcdfDataset
+ */
+ static public enum Enhance {
+@@ -647,17 +654,75 @@
+ location = location.trim();
+ location = StringUtil2.replace(location, '\\', "/");
+
+- // Some URLS have multiple prefixed protocols (e.g. thredds:resolve)
+- // so, we cannot use URI or URL classes to parse.
+- String[] prefixes = location.split("[:]");
++ // Start by breaking off any leading protocols;
++ // there may be more than one.
++ // Watch out for Windows paths starting with a drive letter.
++
++ List<String> allprotocols = new ArrayList<String>(); // all leading protocols upto path or host
++
++ // Note, we cannot use split because of the context sensitivity
++ StringBuilder buf = new StringBuilder(location);
++ for(;;) {
++ int index = buf.indexOf(":");
++ if(index < 0) break; // no more protocols
++ String protocol = buf.substring(0,index);
++ // Check for windows drive letter
++ if(index == 1 //=>|protocol| == 1
++ && DRIVE_LETTERS.indexOf(buf.charAt(0)) >= 0) break;
++ allprotocols.add(protocol);
++ buf.delete(0,index+1); // remove the leading protocol
++ if(buf.indexOf("/") == 0)break; // anything after this is not a protocol
++ }
++
++ String trueurl = location;
++ String leadprotocol = null;
++ if(allprotocols.size() == 0) {
++ // The location has no lead protocols, assume file:
++ leadprotocol = "file";
++ } else {
++ leadprotocol = allprotocols.get(0);
++ }
++
++ // Priority in deciding
++ // the service type is as follows.
++ // 1. "protocol" tag in fragment
++ // 2. lead protocol
++ // 3. path extension
++ // 4. contact the server (if defined)
++
++ // remove any trailing query or fragment
++ String fragment = null;
++ int pos = trueurl.lastIndexOf('#');
++ if(pos >= 0) {
++ fragment = trueurl.substring(pos+1,trueurl.length());
++ trueurl = trueurl.substring(0,pos);
++ }
++ String query = null;
++ pos = location.lastIndexOf('?');
++ if(pos >= 0) {
++ query = trueurl.substring(pos+1,trueurl.length());
++ trueurl = trueurl.substring(0,pos);
++ }
++
+ ServiceType svctype = null;
+- if(prefixes.length > 1) {
+- // "switch" based on the leading protocol
+- String protocol = prefixes[0]; //
+- if(protocol.equals("file"))
+- svctype = disambiguateFile(location);
+- else
+- svctype = disambiguateURL(protocol,location);
++
++ if(fragment != null)
++ svctype = searchFragment(fragment);
++
++ if(svctype == null) // See if lead protocol tells us how to interpret
++ svctype = decodeLeadProtocol(leadprotocol);
++
++ if(svctype == null) // Look at the path file extension
++ svctype = decodePathExtension(trueurl);
++
++ if(svctype == null) {
++ //There are several possibilities at this point; all of which
++ // require further info to disambiguate
++ // - we have file://<path> or file:<path>; without more help, we cannot
++ // determine the service type
++ // - we have a simple url: e.g. http://... ; contact the server
++ if(!leadprotocol.equals("file"))
++ svctype = disambiguateHttp(trueurl);
+ }
+
+ if(svctype == ServiceType.OPENDAP)
+@@ -669,9 +734,13 @@
+ else if(svctype == ServiceType.DAP4)
+ return acquireDap4(cache, factory, hashKey, location,
+ buffer_size, cancelTask, spiObject);
+- else if(svctype == ServiceType.NCML)
+- return acquireNcml(cache, factory, hashKey, location, buffer_size, cancelTask, spiObject);
+- else if(svctype == ServiceType.THREDDS) {
++ else if(svctype == ServiceType.NCML) {
++ // If lead protocol was null and then pretend it was a file
++ // Note that technically, this should be 'file://'
++ String url = (allprotocols.size() == 0 ? "file:"+trueurl : trueurl);
++ return acquireNcml(cache, factory, hashKey, url,
++ buffer_size, cancelTask, spiObject);
++ } else if(svctype == ServiceType.THREDDS) {
+ Formatter log = new Formatter();
+ ThreddsDataFactory tdf = new ThreddsDataFactory();
+ NetcdfFile ncfile = tdf.openDataset(location, false, cancelTask, log); // LOOK acquire ??
+@@ -679,15 +748,8 @@
+ throw new IOException(log.toString());
+ return ncfile;
+ } else if(svctype != null)
+- throw new IOException("Unknown service type: "+svctype.toString());
++ throw new IOException("Unknown service type: "+svctype.toString());
+
+- // Apparently not a url, see if it looks like an ncml request
+- if(location.endsWith(".xml") || location.endsWith(".ncml")) {
+- // Pretend it was a file: url
+- // Note that technically, this should be 'file://'
+- return acquireNcml(cache, factory, hashKey, "file:"+location,
+- buffer_size, cancelTask, spiObject);
+- }
+ // Next to last resort: look in the cache
+ if(cache != null) {
+ if(factory == null)
+@@ -699,30 +761,14 @@
+ return NetcdfFile.open(location, buffer_size, cancelTask, spiObject);
+ }
+
+- /*
+- * Attempt to map a file: url to a service type
+- * (see thredds.catalog.ServiceType).
+- *
+- * @param location The file: url to disambiguate
+- * @return ServiceType indicating how to handle the url
+- */
+- @Urlencoded
++ /**
++ * Check path extension; assumes no query or fragment
++ * @param path the path to examine for extension
++ * @return ServiceType inferred from the extension or null
++ */
+ static ServiceType
+- disambiguateFile(String location)
++ decodePathExtension(String path)
+ {
+- // This should parse as a URL
+- URL urx = null;
+- boolean parses = true;
+- try {urx = new URL(location);} catch (MalformedURLException e) {parses = false;}
+- String path = null;
+- if(parses) {
+- path = urx.getPath();
+- if(path == null || path.length()==0) parses = false;
+- }
+- if(!parses)
+- return null;
+-
+- assert urx.getProtocol().equals("file");
+ // Look at the path extensions
+ if(path.endsWith(".dds")
+ || path.endsWith(".das")
+@@ -735,12 +781,11 @@
+ if(path.endsWith(".xml")
+ || path.endsWith(".ncml"))
+ return ServiceType.NCML;
+- // See if the fragment gives a clue
+- return searchFragment(location);
++ return null;
+ }
+
+ /*
+- * Attempt to map a (non-file:) url to a service type
++ * Attempt to map a lead url protocol url to a service type
+ * (see thredds.catalog.ServiceType).
+ * Possible service types should include at least the following.
+ * <ol>
+@@ -748,16 +793,13 @@
+ * <li> DAP4 (DAP4 protocol)
+ * <li> CdmRemote (remote ncstream)
+ * </ol>
+- * The mapping from url -> ServiceType is many to one, where for example,
+- * the url protocol of dap4 and file might both map to ServiceType.DAP4.
+ *
+ * @param protocol The leading protocol
+- * @param location the url to disambiguate
+- * @return ServiceType indicating how to handle the url
++ * @return ServiceType indicating how to handle the url, or null.
+ */
+ @Urlencoded
+ static ServiceType
+- disambiguateURL(String protocol, String location)
++ decodeLeadProtocol(String protocol)
+ throws IOException
+ {
+ if(protocol.equals("dods"))
+@@ -768,78 +810,9 @@
+ return ServiceType.CdmRemote;
+ else if(protocol.equals(ThreddsDataFactory.PROTOCOL)) //thredds
+ return ServiceType.THREDDS;
+- else if(protocol.equals("http") || protocol.equals("https"))
+- return disambiguateHttp(location); // Actually contact the server
+- return searchFragment(location);
+- }
+-
+- /**
+- * Given a fragment, look for
+- * markers indicated which protocol to use
+- * @param location the url whose fragment is to be examined
+- * @return The discovered ServiceType, or null
+- */
+- static ServiceType
+- searchFragment(String location)
+- {
+- int pos = location.lastIndexOf('#');
+- if(pos < 0) return null;
+- String fragment = location.substring(pos+1,location.length());
+- Map<String,String> map = parseFragment(fragment);
+- String protocol = map.get("protocol");
+- if(protocol != null) {
+- if(protocol.equalsIgnoreCase("dap")
+- || protocol.equalsIgnoreCase("dods"))
+- return ServiceType.OPENDAP;
+- if(protocol.equalsIgnoreCase("dap4"))
+- return ServiceType.DAP4;
+- if(protocol.equalsIgnoreCase("cdmremote"))
+- return ServiceType.CdmRemote;
+- if(protocol.equalsIgnoreCase("thredds"))
+- return ServiceType.THREDDS;
+- if(protocol.equalsIgnoreCase("ncmdl"))
+- return ServiceType.NCML;
+- }
+ return null;
+ }
+
+- /**
+- * Given the fragment part of a url, see if it
+- * parses as name=value pairs separated by '&'
+- * (same as query part).
+- * @param fragment the fragment part of a url
+- * @return a map of the name value pairs (possibly empty),
+- * or null if the fragment does not parse.
+- */
+-
+- static Map<String,String>
+- parseFragment(String fragment)
+- {
+- Map<String,String> map = new HashMap<String,String>();
+- if(fragment != null && fragment.length() >= 0) {
+- if(fragment.charAt(0) == '#')
+- fragment = fragment.substring(1);
+- String[] pairs = fragment.split("[ \t]*[&][ \t]*");
+- for(String pair: pairs) {
+- String[] pieces = fragment.split("[ \t]*[=][ \t]*");
+- switch (pieces.length) {
+- case 1:
+- map.put(EscapeStrings.unescapeURL(pieces[0]).toLowerCase(),
+- "true");
+- break;
+- case 2:
+- map.put(EscapeStrings.unescapeURL(pieces[0]).toLowerCase(),
+- EscapeStrings.unescapeURL(pieces[1]).toLowerCase());
+- break;
+- default:
+- return null; // does not parse
+- }
+- }
+- }
+- return map;
+- }
+-
+-
+ /**
+ * If the URL alone is not sufficient to disambiguate the location,
+ * then this method will attempt to do a specific kind of request on
+@@ -848,6 +821,7 @@
+ * and uses it value (e.g. "ncstream" or "dods", etc)
+ * in order to disambiguate.
+ * @param location the url to disambiguate
++ * @param location the original url string
+ * @return ServiceType indicating how to handle the url
+ */
+ @Urlencoded
+@@ -858,11 +832,6 @@
+ // aggregation cache files are of form
+ // http://www.esrl.noaa.gov/psd/thredds/dodsC/Datasets/ncep.reanalysis2.dailyavgs/pressure/air.1981.nc#320092027
+
+- // remove any fragment
+- int pos = location.lastIndexOf("#");
+- if(pos >= 0)
+- location = location.substring(0,pos);
+-
+ ServiceType result = checkIfDods(location); // dods
+ if(result != null)
+ return result;
+@@ -872,7 +841,7 @@
+
+ HTTPMethod method = null;
+ try {
+- method = HTTPMethod.Head(location);
++ method = HTTPFactory.Head(location);
+ int statusCode = method.execute();
+ if(statusCode >= 300) {
+ if(statusCode == 401)
+@@ -895,22 +864,19 @@
+ // not sure what other opendap servers do, so fall back on check for dds
+ static private ServiceType checkIfDods(String location) throws IOException {
+ HTTPMethod method = null;
+- // Strip off any trailing constraints
+- if (location.indexOf('?') >= 0) {
+- location = location.substring(0, location.indexOf('?'));
+- }
++ int len = location.length();
+ // Strip off any trailing .dds, .das, or .dods
+ if (location.endsWith(".dds"))
+- location = location.substring(0, location.length() - ".dds".length());
++ location = location.substring(0, len - ".dds".length());
+ if (location.endsWith(".das"))
+- location = location.substring(0, location.length() - ".das".length());
++ location = location.substring(0, len - ".das".length());
+ if (location.endsWith(".dods"))
+- location = location.substring(0, location.length() - ".dods".length());
++ location = location.substring(0, len - ".dods".length());
+ // Opendap assumes that the caller has properly escaped the url
+ try {
+ // For some reason, the head method is not using credentials
+ // method = session.newMethodHead(location + ".dds");
+- method = HTTPMethod.Get(location + ".dds");
++ method = HTTPFactory.Get(location + ".dds");
+
+ int status = method.execute();
+ if (status == 200) {
+@@ -937,10 +903,6 @@
+ // check for dmr
+ static private ServiceType checkIfDap4(String location) throws IOException {
+ HTTPMethod method = null;
+- // Strip off any trailing constraints
+- if (location.indexOf('?') >= 0) {
+- location = location.substring(0, location.indexOf('?'));
+- }
+ // Strip off any trailing DAP4 prefix
+ if (location.endsWith(".dap"))
+ location = location.substring(0, location.length() - ".dap".length());
+@@ -949,7 +911,7 @@
+ else if (location.endsWith(".dsr"))
+ location = location.substring(0, location.length() - ".dsr".length());
+ try {
+- method = HTTPMethod.Get(location + ".dmr");
++ method = HTTPFactory.Get(location + ".dmr");
+
+ int status = method.execute();
+ if (status == 200) {
+@@ -971,6 +933,73 @@
+ }
+ }
+
++ /**
++ * Given a location look for
++ * markers indicated which protocol to use
++ * @param fragment the fragment is to be examined
++ * @return The discovered ServiceType, or null
++ */
++ static ServiceType
++ searchFragment(String fragment)
++ {
++ if(fragment.length() == 0)
++ return null;
++ Map<String,String> map = parseFragment(fragment);
++ String protocol = map.get("protocol");
++ if(protocol != null) {
++ if(protocol.equalsIgnoreCase("dap")
++ || protocol.equalsIgnoreCase("dods"))
++ return ServiceType.OPENDAP;
++ if(protocol.equalsIgnoreCase("dap4"))
++ return ServiceType.DAP4;
++ if(protocol.equalsIgnoreCase("cdmremote"))
++ return ServiceType.CdmRemote;
++ if(protocol.equalsIgnoreCase("thredds"))
++ return ServiceType.THREDDS;
++ if(protocol.equalsIgnoreCase("ncmdl"))
++ return ServiceType.NCML;
++ }
++ return null;
++ }
++
++ /**
++ * Given the fragment part of a url, see if it
++ * parses as name=value pairs separated by '&'
++ * (same as query part).
++ * @param fragment the fragment part of a url
++ * @return a map of the name value pairs (possibly empty),
++ * or null if the fragment does not parse.
++ */
++
++ static Map<String,String>
++ parseFragment(String fragment)
++ {
++ Map<String,String> map = new HashMap<String,String>();
++ if(fragment != null && fragment.length() >= 0) {
++ if(fragment.charAt(0) == '#')
++ fragment = fragment.substring(1);
++ String[] pairs = fragment.split("[ \t]*[&][ \t]*");
++ for(String pair: pairs) {
++ String[] pieces = fragment.split("[ \t]*[=][ \t]*");
++ switch (pieces.length) {
++ case 1:
++ map.put(EscapeStrings.unescapeURL(pieces[0]).toLowerCase(),
++ "true");
++ break;
++ case 2:
++ map.put(EscapeStrings.unescapeURL(pieces[0]).toLowerCase(),
++ EscapeStrings.unescapeURL(pieces[1]).toLowerCase());
++ break;
++ default:
++ return null; // does not parse
++ }
++ }
++ }
++ return map;
++ }
++
++
++ //////////////////////////////////////////////////
+
+ private static boolean isexternalclient = false;
+
+@@ -1290,9 +1319,8 @@
+ /* @Override
+ public Object sendIospMessage(Object message) {
+ if (orgFile != null)
+- return orgFile.sendIospMessage(message);
+- else
+- return false;
++ orgFile.sendIospMessage(message);
++ return false;
+ } */
+
+ /*
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/stream/CdmRemote.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/stream/CdmRemote.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/stream/CdmRemote.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/stream/CdmRemote.java 2013-09-16 07:21:21.097338895 +0200
+@@ -1,339 +1,337 @@
+-/*
+- * Copyright 2009-2012 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.stream;
+-
+-import ucar.nc2.util.net.HTTPException;
+-import ucar.nc2.util.net.HTTPMethod;
+-import ucar.nc2.util.net.HTTPSession;
+-import org.apache.commons.httpclient.Header;
+-
+-import ucar.ma2.*;
+-import ucar.nc2.Structure;
+-import ucar.nc2.Variable;
+-import ucar.nc2.util.IO;
+-
+-import java.io.*;
+-import java.net.URLEncoder;
+-import java.util.Formatter;
+-
+-/**
+- * A remote CDM dataset (extends NetcdfFile), using cdmremote protocol to communicate.
+- * Similar to Opendap in that it is a remote access protocol.
+- * Supports full CDM / netcdf-4 data model.
+- *
+- * @author caron
+- * @since Feb 7, 2009
+- */
+-public class CdmRemote extends ucar.nc2.NetcdfFile {
+- static public final String PROTOCOL = "cdmremote";
+- static public final String SCHEME = PROTOCOL+":";
+-
+- static private org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CdmRemote.class);
+- static private boolean showRequest = false;
+-
+- static public void setDebugFlags(ucar.nc2.util.DebugFlags debugFlag) {
+- showRequest = debugFlag.isSet("CdmRemote/showRequest");
+- }
+-
+- /**
+- * Create the canonical form of the URL.
+- * If the urlName starts with "http:", change it to start with "cdmremote:", otherwise
+- * leave it alone.
+- *
+- * @param urlName the url string
+- * @return canonical form
+- */
+- public static String canonicalURL(String urlName) {
+- if (urlName.startsWith("http:"))
+- return SCHEME + urlName.substring(5);
+- return urlName;
+- }
+-
+- /* IGNORE
+- static synchronized void initHttpClient() {
+- if (httpClient != null) return;
+- try {
+- httpClient = new HTTPSession();
+- } catch (HTTPException he) {
+- httpClient = null;
+- }
+- }
+- */
+-
+- //////////////////////////////////////////////////////
+-
+- private HTTPSession httpClient;
+-
+- private final String remoteURI;
+-
+- public CdmRemote(String _remoteURI) throws IOException {
+- long start = System.currentTimeMillis();
+-
+- // get http URL
+- String temp = _remoteURI;
+- try {
+- if (temp.startsWith(SCHEME))
+- temp = temp.substring(SCHEME.length());
+- if (!temp.startsWith("http:"))
+- temp = "http:" + temp;
+- } catch (Exception e) {
+- }
+- remoteURI = temp;
+-
+- httpClient = new HTTPSession(remoteURI);
+-
+- // get the header
+- HTTPMethod method = null;
+- try {
+- String url = remoteURI + "?req=header";
+- method = HTTPMethod.Get(httpClient,url);
+- method.setFollowRedirects(true);
+- if (showRequest) System.out.printf("CdmRemote request %s %n", url);
+- int statusCode = method.execute();
+-
+- if (statusCode == 404)
+- throw new FileNotFoundException(method.getURL() + " " + method.getStatusLine());
+-
+- if (statusCode >= 300)
+- throw new IOException(method.getURL() + " " + method.getStatusLine());
+-
+- InputStream is = method.getResponseAsStream();
+- NcStreamReader reader = new NcStreamReader();
+- reader.readStream(is, this);
+- this.location = SCHEME + remoteURI;
+-
+- } finally {
+- if (method != null) method.close();
+- }
+- long took = System.currentTimeMillis() - start;
+- if (showRequest) System.out.printf(" took %d msecs %n", took);
+- }
+-
+- @Override
+- protected Array readData(ucar.nc2.Variable v, Section section) throws IOException, InvalidRangeException {
+- //if (unlocked)
+- // throw new IllegalStateException("File is unlocked - cannot use");
+-
+- if (v.getDataType() == DataType.SEQUENCE) {
+- Structure s = (Structure) v;
+- StructureDataIterator siter = getStructureIterator(s, -1);
+- return new ArraySequence(s.makeStructureMembers(), siter, -1);
+- }
+-
+- StringBuilder sbuff = new StringBuilder(remoteURI);
+- sbuff.append("?var=");
+- Formatter f = new Formatter();
+- f.format("%s", v.getFullNameEscaped()); // full name
+- if (section != null && v.getDataType() != DataType.SEQUENCE) {
+- f.format("(%s)", section.toString());
+- }
+- sbuff.append( URLEncoder.encode(f.toString(), "UTF-8")); // % escape entire thing varname and section
+-
+- if (showRequest)
+- System.out.println(" CdmRemote data request for variable: " + v.getFullName() + " section= " + section + " url=" + sbuff);
+-
+- HTTPMethod method = null;
+- try {
+- method = HTTPMethod.Get(httpClient,sbuff.toString());
+- int statusCode = method.execute();
+-
+- if (statusCode == 404)
+- throw new FileNotFoundException(method.getPath() + " " + method.getStatusLine());
+-
+- if (statusCode >= 300)
+- throw new IOException(method.getPath() + " " + method.getStatusLine());
+-
+- Header h = method.getResponseHeader("Content-Length");
+- if (h != null) {
+- String s = h.getValue();
+- int readLen = Integer.parseInt(s);
+- if (showRequest)
+- System.out.printf(" content-length = %d%n", readLen);
+- if (v.getDataType() != DataType.SEQUENCE) {
+- int wantSize = (int) (v.getElementSize() * (section == null ? v.getSize() : section.computeSize()));
+- if (readLen != wantSize)
+- throw new IOException("content-length= " + readLen + " not equal expected Size= " + wantSize); // LOOK
+- }
+- }
+-
+- InputStream is = method.getResponseAsStream();
+- NcStreamReader reader = new NcStreamReader();
+- NcStreamReader.DataResult result = reader.readData(is, this);
+-
+- assert v.getFullNameEscaped().equals(result.varNameFullEsc);
+- result.data.setUnsigned(v.isUnsigned());
+- return result.data;
+-
+- } finally {
+- if (method != null) method.close();
+- }
+- }
+-
+- protected StructureDataIterator getStructureIterator(Structure s, int bufferSize) throws java.io.IOException {
+- try {
+- InputStream is = sendQuery(remoteURI, s.getFullNameEscaped());
+- NcStreamReader reader = new NcStreamReader();
+- return reader.getStructureIterator(is, this);
+-
+- } catch (Throwable e) {
+- e.printStackTrace();
+- throw new IllegalStateException(e);
+- }
+- }
+-
+- public static InputStream sendQuery(String remoteURI, String query) throws IOException {
+- long start = System.currentTimeMillis();
+-
+- HTTPSession session = null;
+- HTTPMethod method = null;
+- InputStream stream = null;
+- int statusCode = 0;
+-
+- StringBuilder sbuff = new StringBuilder(remoteURI);
+- sbuff.append("?");
+- sbuff.append(query);
+-
+- if (showRequest)
+- System.out.printf(" CdmRemote sendQuery= %s", sbuff);
+-
+- try {
+-
+- try {
+- session = new HTTPSession(sbuff.toString());
+- method = HTTPMethod.Get(session);
+- statusCode = method.execute();
+- } catch (HTTPException he) {
+- throw new IOException(he);
+- }
+-
+- if (statusCode == 404)
+- throw new FileNotFoundException(method.getPath() + " " + method.getStatusLine());
+-
+- if (statusCode >= 300)
+- throw new IOException(method.getPath() + " " + method.getStatusLine());
+-
+- stream = method.getResponseBodyAsStream();
+- if (showRequest) System.out.printf(" took %d msecs %n", System.currentTimeMillis() - start);
+- return stream;
+-
+- } catch (IOException ioe) {
+- if (session != null) session.close();
+- throw ioe;
+- }
+- }
+-
+- @Override
+- public String getFileTypeId() {
+- return "ncstreamRemote";
+- }
+-
+- @Override
+- public String getFileTypeDescription() {
+- return "ncstreamRemote";
+- }
+-
+- public void writeToFile(String filename) throws IOException {
+- File file = new File(filename);
+- FileOutputStream fos = new FileOutputStream(file);
+- // WritableByteChannel wbc = fos.getChannel();
+-
+- long size = 4;
+- fos.write(NcStream.MAGIC_START);
+-
+- // header
+- HTTPMethod method = null;
+- try {
+- // get the header
+- String url = remoteURI + "?req=header";
+- method = HTTPMethod.Get(httpClient,url);
+- if (showRequest) System.out.printf("CdmRemote request %s %n", url);
+- int statusCode = method.execute();
+-
+- if (statusCode == 404)
+- throw new FileNotFoundException(method.getURL() + " " + method.getStatusLine());
+-
+- if (statusCode >= 300)
+- throw new IOException(method.getURL() + " " + method.getStatusLine());
+-
+- InputStream is = method.getResponseBodyAsStream();
+- size += IO.copyB(is, fos, IO.default_socket_buffersize);
+-
+- } finally {
+- if (method != null) method.close();
+- }
+-
+- for (Variable v : getVariables()) {
+- StringBuilder sbuff = new StringBuilder(remoteURI);
+- sbuff.append("?var=");
+- sbuff.append(URLEncoder.encode(v.getShortName(), "UTF-8"));
+-
+- if (showRequest)
+- System.out.println(" CdmRemote data request for variable: " + v.getFullName() + " url=" + sbuff);
+-
+- try {
+- method = HTTPMethod.Get(httpClient,sbuff.toString());
+- int statusCode = method.execute();
+-
+- if (statusCode == 404)
+- throw new FileNotFoundException(method.getPath() + " " + method.getStatusLine());
+-
+- if (statusCode >= 300)
+- throw new IOException(method.getPath() + " " + method.getStatusLine());
+-
+- int wantSize = (int) (v.getSize());
+- Header h = method.getResponseHeader("Content-Length");
+- if (h != null) {
+- String s = h.getValue();
+- int readLen = Integer.parseInt(s);
+- if (readLen != wantSize)
+- throw new IOException("content-length= " + readLen + " not equal expected Size= " + wantSize);
+- }
+-
+- InputStream is = method.getResponseBodyAsStream();
+- size += IO.copyB(is, fos, IO.default_socket_buffersize);
+-
+- } finally {
+- if (method != null) method.close();
+- }
+- }
+-
+- fos.flush();
+- fos.close();
+- }
+-
+- @Override
+- public synchronized void close() throws java.io.IOException {
+- if (httpClient != null) httpClient.close();
+- }
+-
+-}
++/*
++ * Copyright 2009-2012 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.stream;
++
++import ucar.nc2.util.net.*;
++import org.apache.http.Header;
++
++import ucar.ma2.*;
++import ucar.nc2.Structure;
++import ucar.nc2.Variable;
++import ucar.nc2.util.IO;
++
++import java.io.*;
++import java.net.URLEncoder;
++import java.util.Formatter;
++
++/**
++ * A remote CDM dataset (extends NetcdfFile), using cdmremote protocol to communicate.
++ * Similar to Opendap in that it is a remote access protocol.
++ * Supports full CDM / netcdf-4 data model.
++ *
++ * @author caron
++ * @since Feb 7, 2009
++ */
++public class CdmRemote extends ucar.nc2.NetcdfFile {
++ static public final String PROTOCOL = "cdmremote";
++ static public final String SCHEME = PROTOCOL+":";
++
++ static private org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(CdmRemote.class);
++ static private boolean showRequest = false;
++
++ static public void setDebugFlags(ucar.nc2.util.DebugFlags debugFlag) {
++ showRequest = debugFlag.isSet("CdmRemote/showRequest");
++ }
++
++ /**
++ * Create the canonical form of the URL.
++ * If the urlName starts with "http:", change it to start with "cdmremote:", otherwise
++ * leave it alone.
++ *
++ * @param urlName the url string
++ * @return canonical form
++ */
++ public static String canonicalURL(String urlName) {
++ if (urlName.startsWith("http:"))
++ return SCHEME + urlName.substring(5);
++ return urlName;
++ }
++
++ /* IGNORE
++ static synchronized void initHttpClient() {
++ if (httpClient != null) return;
++ try {
++ httpClient = HTTPFactory.newSession();
++ } catch (HTTPException he) {
++ httpClient = null;
++ }
++ }
++ */
++
++ //////////////////////////////////////////////////////
++
++ private HTTPSession httpClient;
++
++ private final String remoteURI;
++
++ public CdmRemote(String _remoteURI) throws IOException {
++ long start = System.currentTimeMillis();
++
++ // get http URL
++ String temp = _remoteURI;
++ try {
++ if (temp.startsWith(SCHEME))
++ temp = temp.substring(SCHEME.length());
++ if (!temp.startsWith("http:"))
++ temp = "http:" + temp;
++ } catch (Exception e) {
++ }
++ remoteURI = temp;
++
++ httpClient = HTTPFactory.newSession(remoteURI);
++
++ // get the header
++ HTTPMethod method = null;
++ try {
++ String url = remoteURI + "?req=header";
++ method = HTTPFactory.Get(httpClient, url);
++ method.setFollowRedirects(true);
++ if (showRequest) System.out.printf("CdmRemote request %s %n", url);
++ int statusCode = method.execute();
++
++ if (statusCode == 404)
++ throw new FileNotFoundException(method.getURL() + " " + method.getStatusLine());
++
++ if (statusCode >= 300)
++ throw new IOException(method.getURL() + " " + method.getStatusLine());
++
++ InputStream is = method.getResponseAsStream();
++ NcStreamReader reader = new NcStreamReader();
++ reader.readStream(is, this);
++ this.location = SCHEME + remoteURI;
++
++ } finally {
++ if (method != null) method.close();
++ }
++ long took = System.currentTimeMillis() - start;
++ if (showRequest) System.out.printf(" took %d msecs %n", took);
++ }
++
++ @Override
++ protected Array readData(ucar.nc2.Variable v, Section section) throws IOException, InvalidRangeException {
++ //if (unlocked)
++ // throw new IllegalStateException("File is unlocked - cannot use");
++
++ if (v.getDataType() == DataType.SEQUENCE) {
++ Structure s = (Structure) v;
++ StructureDataIterator siter = getStructureIterator(s, -1);
++ return new ArraySequence(s.makeStructureMembers(), siter, -1);
++ }
++
++ StringBuilder sbuff = new StringBuilder(remoteURI);
++ sbuff.append("?var=");
++ Formatter f = new Formatter();
++ f.format("%s", v.getFullNameEscaped()); // full name
++ if (section != null && v.getDataType() != DataType.SEQUENCE) {
++ f.format("(%s)", section.toString());
++ }
++ sbuff.append( URLEncoder.encode(f.toString(), "UTF-8")); // % escape entire thing varname and section
++
++ if (showRequest)
++ System.out.println(" CdmRemote data request for variable: " + v.getFullName() + " section= " + section + " url=" + sbuff);
++
++ HTTPMethod method = null;
++ try {
++ method = HTTPFactory.Get(httpClient, sbuff.toString());
++ int statusCode = method.execute();
++
++ if (statusCode == 404)
++ throw new FileNotFoundException(method.getPath() + " " + method.getStatusLine());
++
++ if (statusCode >= 300)
++ throw new IOException(method.getPath() + " " + method.getStatusLine());
++
++ Header h = method.getResponseHeader("Content-Length");
++ if (h != null) {
++ String s = h.getValue();
++ int readLen = Integer.parseInt(s);
++ if (showRequest)
++ System.out.printf(" content-length = %d%n", readLen);
++ if (v.getDataType() != DataType.SEQUENCE) {
++ int wantSize = (int) (v.getElementSize() * (section == null ? v.getSize() : section.computeSize()));
++ if (readLen != wantSize)
++ throw new IOException("content-length= " + readLen + " not equal expected Size= " + wantSize); // LOOK
++ }
++ }
++
++ InputStream is = method.getResponseAsStream();
++ NcStreamReader reader = new NcStreamReader();
++ NcStreamReader.DataResult result = reader.readData(is, this);
++
++ assert v.getFullNameEscaped().equals(result.varNameFullEsc);
++ result.data.setUnsigned(v.isUnsigned());
++ return result.data;
++
++ } finally {
++ if (method != null) method.close();
++ }
++ }
++
++ protected StructureDataIterator getStructureIterator(Structure s, int bufferSize) throws java.io.IOException {
++ try {
++ InputStream is = sendQuery(remoteURI, s.getFullNameEscaped());
++ NcStreamReader reader = new NcStreamReader();
++ return reader.getStructureIterator(is, this);
++
++ } catch (Throwable e) {
++ e.printStackTrace();
++ throw new IllegalStateException(e);
++ }
++ }
++
++ public static InputStream sendQuery(String remoteURI, String query) throws IOException {
++ long start = System.currentTimeMillis();
++
++ HTTPSession session = null;
++ HTTPMethod method = null;
++ InputStream stream = null;
++ int statusCode = 0;
++
++ StringBuilder sbuff = new StringBuilder(remoteURI);
++ sbuff.append("?");
++ sbuff.append(query);
++
++ if (showRequest)
++ System.out.printf(" CdmRemote sendQuery= %s", sbuff);
++
++ try {
++
++ try {
++ session = HTTPFactory.newSession(sbuff.toString());
++ method = HTTPFactory.Get(session);
++ statusCode = method.execute();
++ } catch (HTTPException he) {
++ throw new IOException(he);
++ }
++
++ if (statusCode == 404)
++ throw new FileNotFoundException(method.getPath() + " " + method.getStatusLine());
++
++ if (statusCode >= 300)
++ throw new IOException(method.getPath() + " " + method.getStatusLine());
++
++ stream = method.getResponseBodyAsStream();
++ if (showRequest) System.out.printf(" took %d msecs %n", System.currentTimeMillis() - start);
++ return stream;
++
++ } catch (IOException ioe) {
++ if (session != null) session.close();
++ throw ioe;
++ }
++ }
++
++ @Override
++ public String getFileTypeId() {
++ return "ncstreamRemote";
++ }
++
++ @Override
++ public String getFileTypeDescription() {
++ return "ncstreamRemote";
++ }
++
++ public void writeToFile(String filename) throws IOException {
++ File file = new File(filename);
++ FileOutputStream fos = new FileOutputStream(file);
++ // WritableByteChannel wbc = fos.getChannel();
++
++ long size = 4;
++ fos.write(NcStream.MAGIC_START);
++
++ // header
++ HTTPMethod method = null;
++ try {
++ // get the header
++ String url = remoteURI + "?req=header";
++ method = HTTPFactory.Get(httpClient, url);
++ if (showRequest) System.out.printf("CdmRemote request %s %n", url);
++ int statusCode = method.execute();
++
++ if (statusCode == 404)
++ throw new FileNotFoundException(method.getURL() + " " + method.getStatusLine());
++
++ if (statusCode >= 300)
++ throw new IOException(method.getURL() + " " + method.getStatusLine());
++
++ InputStream is = method.getResponseBodyAsStream();
++ size += IO.copyB(is, fos, IO.default_socket_buffersize);
++
++ } finally {
++ if (method != null) method.close();
++ }
++
++ for (Variable v : getVariables()) {
++ StringBuilder sbuff = new StringBuilder(remoteURI);
++ sbuff.append("?var=");
++ sbuff.append(URLEncoder.encode(v.getShortName(), "UTF-8"));
++
++ if (showRequest)
++ System.out.println(" CdmRemote data request for variable: " + v.getFullName() + " url=" + sbuff);
++
++ try {
++ method = HTTPFactory.Get(httpClient, sbuff.toString());
++ int statusCode = method.execute();
++
++ if (statusCode == 404)
++ throw new FileNotFoundException(method.getPath() + " " + method.getStatusLine());
++
++ if (statusCode >= 300)
++ throw new IOException(method.getPath() + " " + method.getStatusLine());
++
++ int wantSize = (int) (v.getSize());
++ Header h = method.getResponseHeader("Content-Length");
++ if (h != null) {
++ String s = h.getValue();
++ int readLen = Integer.parseInt(s);
++ if (readLen != wantSize)
++ throw new IOException("content-length= " + readLen + " not equal expected Size= " + wantSize);
++ }
++
++ InputStream is = method.getResponseBodyAsStream();
++ size += IO.copyB(is, fos, IO.default_socket_buffersize);
++
++ } finally {
++ if (method != null) method.close();
++ }
++ }
++
++ fos.flush();
++ fos.close();
++ }
++
++ @Override
++ public synchronized void close() throws java.io.IOException {
++ if (httpClient != null) httpClient.close();
++ }
++
++}
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/EasySSLProtocolSocketFactory.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/EasySSLProtocolSocketFactory.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/EasySSLProtocolSocketFactory.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/EasySSLProtocolSocketFactory.java 2013-09-16 06:41:34.650672256 +0200
+@@ -1,339 +1,231 @@
+-/*
+- * 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.
+- */
+-
+-/*
+- * ====================================================================
+- *
+- * Copyright 2002-2004 The Apache Software Foundation
+- *
+- * 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.
+- * ====================================================================
+- *
+- * This software consists of voluntary contributions made by many
+- * individuals on behalf of the Apache Software Foundation. For more
+- * information on the Apache Software Foundation, please see
+- * <http://www.apache.org/>.
+- *
+- */
+-
+-package ucar.nc2.util.net;
+-
+-import java.io.File;
+-import java.io.FileInputStream;
+-import java.io.IOException;
+-import java.io.InputStream;
+-import java.net.InetAddress;
+-import java.net.Socket;
+-import java.net.UnknownHostException;
+-import java.security.*;
+-
+-import org.apache.commons.httpclient.ConnectTimeoutException;
+-import org.apache.commons.httpclient.Credentials;
+-import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
+-import org.apache.commons.httpclient.params.HttpConnectionParams;
+-import org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory;
+-import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
+-import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
+-import org.apache.commons.httpclient.auth.CredentialsProvider;
+-
+-import javax.net.ssl.*;
+-
+-/**
+- * <p/>
+- * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s
+- * that accept self-signed certificates.
+- * </p>
+- * <p/>
+- * This socket factory SHOULD NOT be used for productive systems
+- * due to security reasons, unless it is a concious decision and
+- * you are perfectly aware of security implications of accepting
+- * self-signed certificates
+- * </p>
+- * <p/>
+- * <p/>
+- * Example of using custom protocol socket factory for a specific host:
+- * <pre>
+- * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+- * <p/>
+- * HttpClient client = new HttpClient();
+- * client.getHostConfiguration().setHost("localhost", 443, easyhttps);
+- * // use relative url only
+- * GetMethod httpget = new GetMethod("/");
+- * client.executeMethod(httpget);
+- * </pre>
+- * </p>
+- * <p/>
+- * Example of using custom protocol socket factory per default instead of the standard one:
+- * <pre>
+- * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+- * Protocol.registerProtocol("https", easyhttps);
+- * <p/>
+- * HttpClient client = new HttpClient();
+- * GetMethod httpget = new GetMethod("https://localhost/");
+- * client.executeMethod(httpget);
+- * </pre>
+- * </p>
+- *
+- * @author <a href="mailto:oleg -at- ural.ru">Oleg Kalnichevski</a>
+- * <p/>
+- * <p/>
+- * DISCLAIMER: HttpClient developers DO NOT actively support this component.
+- * The component is provided as a reference material, which may be inappropriate
+- * for use without additional customization.
+- * </p>
+- */
+-
+-public class EasySSLProtocolSocketFactory implements ProtocolSocketFactory {
+-
+-//////////////////////////////////////////////////
+-
+- private SSLContext sslcontext = null;
+-
+- /**
+- * Constructor for EasySSLProtocolSocketFactory.
+- */
+- public EasySSLProtocolSocketFactory() {
+- super();
+- }
+-
+-
+- /**
+- * @see SecureProtocolSocketFactory#createSocket(java.net.Socket, java.lang.String, int, boolean)
+- */
+- public Socket createSocket(
+- Socket socket,
+- String host,
+- int port,
+- boolean autoClose)
+- throws IOException, UnknownHostException {
+-
+- return getSSLContext(null, host, port).getSocketFactory().createSocket(
+- socket,
+- host,
+- port,
+- autoClose);
+- }
+-
+- /**
+- * @see SecureProtocolSocketFactory#createSocket(java.lang.String, int)
+- */
+- public Socket createSocket(String host, int port)
+- throws IOException, UnknownHostException {
+- return getSSLContext(null, host, port).getSocketFactory().createSocket(host, port);
+- }
+-
+- /**
+- * @see SecureProtocolSocketFactory#createSocket(java.lang.String, int, java.net.InetAddress, int)
+- */
+- public Socket createSocket(
+- String host,
+- int port,
+- InetAddress clientHost,
+- int clientPort)
+- throws IOException, UnknownHostException {
+- return createSocket(
+- host,
+- port,
+- clientHost,
+- clientPort,
+- new HttpConnectionParams());
+- }
+-
+- /**
+- * Attempts to get a new socket connection to the given host within the given time limit.
+- * <p/>
+- * To circumvent the limitations of older JREs that do not support connect timeout a
+- * controller thread is executed. The controller thread attempts to create a new socket
+- * within the given limit of time. If socket constructor does not return until the
+- * timeout expires, the controller terminates and throws an {@link ConnectTimeoutException}
+- * </p>
+- *
+- * @param host the host name/IP
+- * @param port the port on the host
+- * @param localAddress the local host name/IP to bind the socket to
+- * @param localPort the port on the local machine
+- * @param params {@link HttpConnectionParams Http connection parameters}
+- * @return Socket a new socket
+- * @throws IOException if an I/O error occurs while creating the socket
+- * @throws UnknownHostException if the IP address of the host cannot be
+- * determined
+- */
+- public Socket createSocket(
+- final String host,
+- final int port,
+- final InetAddress localAddress,
+- final int localPort,
+- final HttpConnectionParams params)
+- throws IOException, UnknownHostException, ConnectTimeoutException {
+- if (params == null) {
+- throw new IllegalArgumentException("Parameters may not be null");
+- }
+- int timeout = params.getConnectionTimeout();
+- if (true) {
+- return getSSLContext(params, host, port).getSocketFactory().createSocket(host, port);
+- } else {
+- if (timeout == 0) {
+- return getSSLContext(params, host, port).getSocketFactory().createSocket(host, port);
+- } else {
+- // To be eventually deprecated when migrated to Java 1.4 or above
+- return ControllerThreadSocketFactory.createSocket(this, host, port, localAddress, localPort, timeout);
+- }
+- }
+-
+- }
+-
+- private SSLContext getSSLContext(HttpConnectionParams params, String host, int port) throws HTTPException {
+- if (this.sslcontext == null) {
+- this.sslcontext = createSSLContext(params, host, port);
+- }
+- return this.sslcontext;
+- }
+-
+- private SSLContext createSSLContext(HttpConnectionParams params, String host, int port) throws HTTPException {
+- SSLContext sslcontext = null;
+- KeyManager[] keymanagers = null;
+- KeyStore keystore = null;
+- KeyStore truststore = null;
+- TrustManager[] trustmanagers = null;
+-
+- String keypassword = null;
+- String keypath = null;
+- String trustpassword = null;
+- String trustpath = null;
+-
+- try {
+-
+- // Get the HTTPAuthProvider
+- HTTPAuthProvider provider;
+- provider = (HTTPAuthProvider) params.getParameter(CredentialsProvider.PROVIDER);
+- if (provider == null) return stdauthenticate();
+-
+- // Abuse the getCredentials() api
+- Credentials creds = null;
+- try {
+- creds = provider.getCredentials(HTTPSSLScheme.Default, null, 0, false);
+- if (creds == null) return stdauthenticate();
+- } catch (CredentialsNotAvailableException e) {
+- return stdauthenticate();
+- }
+-
+- HTTPSSLProvider sslprovider = (creds == null ? null : (HTTPSSLProvider) creds);
+- if (sslprovider == null)
+- return stdauthenticate();
+-
+- keypath = (String) sslprovider.getKeystore();
+- keypassword = (String) sslprovider.getKeypassword();
+- trustpath = (String) sslprovider.getTruststore();
+- trustpassword = (String) sslprovider.getTrustpassword();
+-
+- keystore = buildstore(keypath, keypassword, "key");
+- if (keystore != null) {
+- KeyManagerFactory kmfactory = KeyManagerFactory.getInstance("SunX509");
+- kmfactory.init(keystore, keypassword.toCharArray());
+- keymanagers = kmfactory.getKeyManagers();
+- }
+-
+- truststore = buildstore(trustpath, trustpassword, "trust");
+- if (truststore != null) {
+- //TrustManagerFactory trfactory = TrustManagerFactory.getInstance("SunX509");
+- //trfactory.init(truststore, trustpassword.toCharArray());
+- //trustmanagers = trfactory.getTrustManagers();
+- trustmanagers = new TrustManager[]{new EasyX509TrustManager(truststore)};
+- } else {
+- trustmanagers = new TrustManager[]{new EasyX509TrustManager(null)};
+- }
+-
+- sslcontext = SSLContext.getInstance("SSL");
+- sslcontext.init(keymanagers, trustmanagers, null);
+-
+- return sslcontext;
+-
+- } catch (KeyManagementException e) {
+- throw new HTTPException("Key Management exception: " + e.getMessage());
+- } catch (NoSuchAlgorithmException e) {
+- throw new HTTPException("Unsupported algorithm exception: " + e.getMessage());
+- } catch (KeyStoreException e) {
+- throw new HTTPException("Keystore exception: " + e.getMessage());
+- } catch (GeneralSecurityException e) {
+- throw new HTTPException("Key management exception: " + e.getMessage());
+- } catch (IOException e) {
+- throw new HTTPException("I/O error reading keystore/truststore file: " + e.getMessage());
+- }
+- }
+-
+- // Do no authentication
+- static private SSLContext
+- stdauthenticate()
+- throws KeyManagementException,NoSuchAlgorithmException, KeyStoreException
+- {
+- TrustManager[] trustmanagers = new TrustManager[]{new EasyX509TrustManager(null)};
+- SSLContext sslcontext = SSLContext.getInstance("SSL");
+- sslcontext.init(null, trustmanagers, null);
+- return sslcontext;
+- }
+-
+- static KeyStore
+- buildstore(String path, String password, String prefix) throws HTTPException {
+- KeyStore store = null;
+- try {
+- if (path != null && password != null) {
+- File storefile = new File(path);
+- if (!storefile.canRead())
+- throw new HTTPException("Cannot read specified " + prefix + "store:" + storefile.getAbsolutePath());
+- store = KeyStore.getInstance("JKS");
+- InputStream is = null;
+- try {
+- is = new FileInputStream(storefile);
+- store.load(is, password.toCharArray());
+- } finally {
+- if (is != null) is.close();
+- }
+- }
+- } catch (Exception e) {
+- throw new HTTPException(e);
+- }
+- return store;
+- }
+-
+-
+-}
++/*
++ * 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.
++ */
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements. See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership. The ASF licenses this file
++ * to you 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 ucar.nc2.util.net;
++
++import org.apache.http.conn.ConnectTimeoutException;
++import org.apache.http.conn.scheme.*;
++import org.apache.http.params.HttpConnectionParams;
++import org.apache.http.params.HttpParams;
++
++import javax.net.ssl.*;
++import java.io.*;
++import java.net.*;
++import java.security.*;
++import java.io.IOException;
++
++public class EasySSLProtocolSocketFactory implements SchemeLayeredSocketFactory
++{
++
++ private SSLContext sslcontext = null;
++
++ private SSLContext createSSLContext(HttpParams params)
++ throws IOException
++ {
++ if(this.sslcontext == null)
++ try {
++ // Get the Desired kind of authentication
++ this.sslcontext = trustedauthentication(params);
++ if(this.sslcontext == null)
++ this.sslcontext = stdauthentication();
++ } catch (KeyManagementException e) {
++ throw new HTTPException("Key Management exception: " + e.getMessage());
++ } catch (NoSuchAlgorithmException e) {
++ throw new HTTPException("Unsupported algorithm exception: " + e.getMessage());
++ } catch (KeyStoreException e) {
++ throw new HTTPException("Keystore exception: " + e.getMessage());
++ } catch (GeneralSecurityException e) {
++ throw new HTTPException("Key management exception: " + e.getMessage());
++ } catch (IOException e) {
++ throw new HTTPException("I/O error reading keystore/truststore file: " + e.getMessage());
++ } catch (Exception e) {
++ throw new IOException(e.getMessage(), e);
++ }
++ return this.sslcontext;
++ }
++
++ // Default is to try self-signed certificates
++ private SSLContext
++ stdauthentication()
++ throws Exception
++ {
++ SSLContext context = SSLContext.getInstance("TLS");
++ context.init(null, new TrustManager[]{new EasyX509TrustManager(null)}, null);
++ return context;
++ }
++
++ private SSLContext
++ trustedauthentication(HttpParams params)
++ throws Exception
++ {
++ String keypath = null;
++ String keypassword = null;
++ String trustpath = null;
++ String trustpassword = null;
++ HTTPSSLProvider provider = null;
++ if(params == null) return null;
++ Object o = params.getParameter(HTTPAuthScheme.PROVIDER);
++ if(o == null) return null;
++ if(!(o instanceof HTTPSSLProvider))
++ throw new HTTPException("EasySSLProtocolSocketFactory: provide is not SSL provider");
++ provider = (HTTPSSLProvider)o;
++ keypath = provider.getKeystore();
++ keypassword = provider.getKeypassword();
++ trustpath = provider.getTruststore();
++ trustpassword = provider.getTrustpassword();
++
++ TrustManager[] trustmanagers = null;
++ KeyManager[] keymanagers = null;
++
++ KeyStore keystore = buildstore(keypath, keypassword, "key");
++ if(keystore != null) {
++ KeyManagerFactory kmfactory = KeyManagerFactory.getInstance("SunX509");
++ kmfactory.init(keystore, keypassword.toCharArray());
++ keymanagers = kmfactory.getKeyManagers();
++ }
++ KeyStore truststore = buildstore(trustpath, trustpassword, "trust");
++ if(truststore != null) {
++ //todo: TrustManagerFactory trfactory = TrustManagerFactory.getInstance("SunX509");
++ //trfactory.init(truststore, trustpassword.toCharArray());
++ //trustmanagers = trfactory.getTrustManagers();
++ trustmanagers = new TrustManager[]{new EasyX509TrustManager(truststore)};
++ }
++ if(trustmanagers == null)
++ trustmanagers = new TrustManager[]{new EasyX509TrustManager(null)};
++
++ SSLContext sslcontext = SSLContext.getInstance("TSL");
++ sslcontext.init(keymanagers, trustmanagers, null);
++ return sslcontext;
++ }
++
++ static KeyStore
++ buildstore(String path, String password, String prefix)
++ throws HTTPException
++ {
++ KeyStore store = null;
++ try {
++ if(path != null && password != null) {
++ File storefile = new File(path);
++ if(!storefile.canRead())
++ throw new HTTPException("Cannot read specified " + prefix + "store:" + storefile.getAbsolutePath());
++ store = KeyStore.getInstance("JKS");
++ InputStream is = null;
++ try {
++ is = new FileInputStream(storefile);
++ store.load(is, password.toCharArray());
++ } finally {
++ if(is != null) is.close();
++ }
++ }
++ } catch (Exception e) {
++ throw new HTTPException(e);
++ }
++ return store;
++ }
++
++ // -------------------------------------------------------------------
++ // javadoc in org.apache.http.conn.scheme.SocketFactory says :
++ // Both Object.equals() and Object.hashCode() must be overridden
++ // for the correct operation of some connection managers
++ // -------------------------------------------------------------------
++
++ public boolean equals(Object obj)
++ {
++ return ((obj != null) && obj.getClass().equals(
++ EasySSLProtocolSocketFactory.class));
++ }
++
++ public int hashCode()
++ {
++ return EasySSLProtocolSocketFactory.class.hashCode();
++ }
++
++ //SchemeLayeredSocketFactory API
++
++ @Override
++ public boolean isSecure(Socket socket)
++ throws IllegalArgumentException
++ {
++ return true;
++ }
++
++ @Override
++ public Socket createLayeredSocket(Socket socket, String s, int i, HttpParams httpParams)
++ throws IOException
++ {
++ return createSSLContext(httpParams).getSocketFactory().createSocket();
++ }
++
++ public Socket createSocket(HttpParams httpParams)
++ throws IOException
++ {
++ return createSSLContext(httpParams).getSocketFactory().createSocket();
++ }
++
++ public Socket connectSocket(Socket sock,
++ InetSocketAddress remoteAddress,
++ InetSocketAddress localAddress,
++ HttpParams params)
++ throws IOException
++ {
++ int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
++ int soTimeout = HttpConnectionParams.getSoTimeout(params);
++ SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket(params));
++ if(localAddress != null) {
++ // we need to bind explicitly
++ sslsock.bind(localAddress);
++ }
++ sslsock.connect(remoteAddress, connTimeout);
++ sslsock.setSoTimeout(soTimeout);
++ return sslsock;
++ }
++
++}
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPAuthProvider.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPAuthProvider.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPAuthProvider.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPAuthProvider.java 2013-09-16 07:14:23.852243471 +0200
+@@ -33,15 +33,12 @@
+
+ package ucar.nc2.util.net;
+
++import org.apache.http.auth.AuthScope;
++import org.apache.http.auth.Credentials;
++import org.apache.http.client.CredentialsProvider;
++
+ import java.io.IOException;
+-import java.io.NotSerializableException;
+ import java.io.Serializable;
+-import java.util.HashMap;
+-import java.util.Set;
+-
+-import org.apache.commons.httpclient.Credentials;
+-import org.apache.commons.httpclient.HttpMethod;
+-import org.apache.commons.httpclient.auth.*;
+
+ /**
+ * HTTPAuthProvider contains the necessary information to support a given
+@@ -54,138 +51,142 @@
+ * store implementing the HttpParams Interface. The contents of the pair
+ * store depends on the particular auth scheme (HTTP Basic, ESG Keystore,
+ * etc.)
+- *
++ * <p/>
+ * HTTPAuthProvider implements the CredentialsProvider interface.
+ */
+
+ public class HTTPAuthProvider implements Serializable, CredentialsProvider
+ {
+-static final int MAX_RETRIES = 3;
++ static final int MAX_RETRIES = 3;
+
+ //////////////////////////////////////////////////
+ // Predefined keys (Used local to the package)
+
+-static final String PRINCIPAL = "ucar.nc2.principal";
+-static final String URI = "ucar.nc2.url";
+-static final String CREDENTIALSPROVIDER = "ucar.nc2.credentialsprovider";
+-static final String KEYSTOREPATH = "ucar.nc2.keystore";
+-static final String KEYSTOREPASSWORD = "ucar.nc2.keystorepassword";
+-static final String TRUSTSTOREPATH = "ucar.nc2.truststore";
+-static final String TRUSTSTOREPASSWORD = "ucar.nc2.truststorepassword";
+-static final String CREDENTIALS = "ucar.nc2.credentials";
+-static final String AUTHSTRING = "ucar.nc2.authstring";
+-static String SCHEME = "ucar.nc2.scheme";
+-static String PASSWORD = "ucar.nc2.password";
+-static String USER = "ucar.nc2.user";
+-static public final String WWW_AUTH_RESP = "Authorization"; // from HttpMethodDirector
+-static public final String PROXY_AUTH_RESP = "Proxy-Authorization"; // from HttpMethodDirector
++ static final String PRINCIPAL = "ucar.nc2.principal";
++ static final String URI = "ucar.nc2.url";
++ static final String CREDENTIALSPROVIDER = "ucar.nc2.credentialsprovider";
++ static final String KEYSTOREPATH = "ucar.nc2.keystore";
++ static final String KEYSTOREPASSWORD = "ucar.nc2.keystorepassword";
++ static final String TRUSTSTOREPATH = "ucar.nc2.truststore";
++ static final String TRUSTSTOREPASSWORD = "ucar.nc2.truststorepassword";
++ static final String CREDENTIALS = "ucar.nc2.credentials";
++ static final String AUTHSTRING = "ucar.nc2.authstring";
++ static String SCHEME = "ucar.nc2.scheme";
++ static String PASSWORD = "ucar.nc2.password";
++ static String USER = "ucar.nc2.user";
++ static public final String WWW_AUTH_RESP = "Authorization"; // from HttpMethodDirector
++ static public final String PROXY_AUTH_RESP = "Proxy-Authorization"; // from HttpMethodDirector
+
+-static private org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(HTTPAuthProvider.class);
++ static private org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(HTTPAuthProvider.class);
+
+ //////////////////////////////////////////////////
+ // Instance variables
+
+-String url = null;
+-HTTPMethod method = null;
+-int retryCount;
++ String url = null;
++ HTTPMethod method = null;
++ int retryCount;
+
+ //////////////////////////////////////////////////
+ // Constructor(s)
+
+-public HTTPAuthProvider(String url, HTTPMethod method)
+-{
+- this.url = url;
+- this.method = method;
+- this.retryCount = MAX_RETRIES;
+-}
++ public HTTPAuthProvider(String url, HTTPMethod method)
++ {
++ this.url = url;
++ this.method = method;
++ this.retryCount = MAX_RETRIES;
++ }
+
+-//////////////////////////////////////////////////
+-// Credentials Provider Interface
++ //////////////////////////////////////////////////
++ // Credentials Provider Interface
+
+-public Credentials
+-getCredentials(AuthScheme authscheme,
+- String host,
+- int port,
+- boolean isproxy)
+- throws CredentialsNotAvailableException
+-{
+- // There appears to be a bug in HttpMethodDirector such that
+- // as long as bad credentials are provided, it will keep on
+- // calling the credentials provider. We fix by checking for
+- // retry in same way as HttpMethodDirector.processWWWAuthChallenge.
+- // After MAX_RETRIES, we force retries to stop.
+- AuthState authstate = method.getMethod().getHostAuthState();
+- if(retryCount == 0 && authstate.isAuthAttempted() && authscheme.isComplete()) {
+- return null; // Stop the retry.
+- }
+- retryCount--;
+-
+- // Figure out what scheme is being used
+- HTTPAuthScheme scheme;
+- Credentials credentials = null;
+-
+- scheme = HTTPAuthScheme.schemeForName(authscheme.getSchemeName());
+-
+- if(scheme == null) {
+- LOG.error("HTTPAuthProvider: unsupported scheme: "+authscheme.getSchemeName());
+- //throw new CredentialsNotAvailableException();
+- return null;
+- }
+-
+- // search for matching authstore entries
+- HTTPAuthStore.Entry[] matches = HTTPAuthStore.search(new HTTPAuthStore.Entry(scheme,url,null));
+- if(matches.length == 0) {
+- LOG.debug("HTTPAuthProvider: no match for ("+scheme+","+url+")");
+- //throw new CredentialsNotAvailableException();
+- return null;
+- }
+-
+- HTTPAuthStore.Entry entry = matches[0];
+- LOG.debug("HTTPAuthProvider: AuthStore row: "+entry.toString());
+- CredentialsProvider provider = entry.creds;
+-
+- if(provider == null) {
+- LOG.debug("HTTPAuthProvider: no credentials provider provided");
+- //throw new CredentialsNotAvailableException();
+- return null;
+- }
+-
+- // invoke the (real) credentials provider
+- // Use the incoming parameters
+- credentials = provider.getCredentials(authscheme,host,port,isproxy);
+- if(credentials == null) {
+- LOG.debug("HTTPAuthProvider: cannot obtain credentials");
+- //throw new CredentialsNotAvailableException();
+- return null;
++ public Credentials
++ getCredentials(AuthScope scope)//AuthScheme authscheme,String host,int port,boolean isproxy)
++ {
++ // There appears to be a bug in HttpMethodDirector such that
++ // as long as bad credentials are provided, it will keep on
++ // calling the credentials provider. We fix by checking for
++ // retry in same way as HttpMethodDirector.processWWWAuthChallenge.
++ // After MAX_RETRIES, we force retries to stop.
++ //todo: AuthState authstate = method.getMethod().getHostAuthState();
++ //if(retryCount == 0 && authstate.isAuthAttempted() && authscheme.isComplete()) {
++ // return null; // Stop the retry.
++ //}
++ //retryCount--;
++
++ // Figure out what scheme is being used
++ HTTPAuthScheme scheme;
++ Credentials credentials = null;
++
++ scheme = HTTPAuthScheme.schemeForName(scope.getScheme());
++
++ if(scheme == null) {
++ LOG.error("HTTPAuthProvider: unsupported scheme: " + scope.getScheme());
++ //throw new CredentialsNotAvailableException();
++ return null;
++ }
++
++ // search for matching authstore entries
++ HTTPAuthStore.Entry[] matches = HTTPAuthStore.search(new HTTPAuthStore.Entry(scheme, url, null));
++ if(matches.length == 0) {
++ LOG.debug("HTTPAuthProvider: no match for (" + scheme + "," + url + ")");
++ //throw new CredentialsNotAvailableException();
++ return null;
++ }
++
++ HTTPAuthStore.Entry entry = matches[0];
++ LOG.debug("HTTPAuthProvider: AuthStore row: " + entry.toString());
++ CredentialsProvider provider = entry.creds;
++
++ if(provider == null) {
++ LOG.debug("HTTPAuthProvider: no credentials provider provided");
++ //throw new CredentialsNotAvailableException();
++ return null;
++ }
++
++ // invoke the (real) credentials provider
++ // Use the incoming parameters
++ credentials = provider.getCredentials(scope);
++ if(credentials == null) {
++ LOG.debug("HTTPAuthProvider: cannot obtain credentials");
++ //throw new CredentialsNotAvailableException();
++ return null;
++ }
++
++ return credentials;
++ }
++
++ public void setCredentials(AuthScope scope, Credentials creds)
++ {
+ }
+
+- return credentials;
+-}
++ public void clear()
++ {
++ }
+
+ ///////////////////////////////////////////////////
+ // toString
+
+-public String
+-toString()
+-{
+- return "HTTPAuthProvider("+url+")";
+-}
++ public String
++ toString()
++ {
++ return "HTTPAuthProvider(" + url + ")";
++ }
+
+ ///////////////////////////////////////////////////
+ // (De-)Serialization support
+
+-private void writeObject(java.io.ObjectOutputStream ostream)
++ private void writeObject(java.io.ObjectOutputStream ostream)
+ throws IOException
+-{
+- ostream.writeObject(url);
+-}
++ {
++ ostream.writeObject(url);
++ }
++
++ private void readObject(java.io.ObjectInputStream istream)
++ throws IOException, ClassNotFoundException
++ {
++ url = (String) istream.readObject();
++ }
+
+-private void readObject(java.io.ObjectInputStream istream)
+- throws IOException, ClassNotFoundException
+-{
+- url = (String)istream.readObject();
+-}
+
+-
+ }//HTTPAuthProvider
+
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPAuthScheme.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPAuthScheme.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPAuthScheme.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPAuthScheme.java 2013-09-16 07:15:50.182711244 +0200
+@@ -1,79 +1,84 @@
+-/*
+- * 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;
+-
+-/**
+- * HTTPAuthScheme defines an enum about the currently supported schemes.
+- */
+-
+-public enum HTTPAuthScheme
+-{
+- BASIC("BASIC"),
+- DIGEST("DIGEST"),
+- SSL("SSL"),
+- NTLM("NTLM"),
+- ANY("ANY");
+-
+- // Define the associated standard name
+- private final String name;
+-
+- HTTPAuthScheme(String name)
+- {
+- this.name = name;
+- }
+-
+- public String getSchemeName() { return name; }
+-
+- static public HTTPAuthScheme schemeForName(String name)
+- {
+- if(name != null) {
+- for(HTTPAuthScheme s: HTTPAuthScheme.values()) {
+- if(name.equalsIgnoreCase(s.name())) return s;
+- }
+- }
+- return null;
+- }
+-
+- static public HTTPAuthScheme fromAuthScope(String scheme)
+- {
+- if(scheme == null) return null;
+- if(scheme.equals(org.apache.commons.httpclient.auth.AuthPolicy.BASIC))
+- return BASIC;
+- if(scheme.equals(org.apache.commons.httpclient.auth.AuthPolicy.DIGEST))
+- return DIGEST;
+- if(scheme.equals(org.apache.commons.httpclient.auth.AuthPolicy.NTLM))
+- return NTLM;
+- return null;
+- }
+-}
++/*
++ * 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 org.apache.http.client.params.AuthPolicy;
++
++/**
++ * HTTPAuthScheme defines an enum about the currently supported schemes.
++ */
++
++public enum HTTPAuthScheme
++{
++ BASIC("BASIC"),
++ DIGEST("DIGEST"),
++ SSL("SSL"),
++ NTLM("NTLM"),
++ ANY("ANY");
++
++ // Define parameter names
++ static public final String PROVIDER = "HTTP.provider";
++
++ // Define the associated standard name
++ private final String name;
++
++ HTTPAuthScheme(String name)
++ {
++ this.name = name;
++ }
++
++ public String getSchemeName() { return name; }
++
++ static public HTTPAuthScheme schemeForName(String name)
++ {
++ if(name != null) {
++ for(HTTPAuthScheme s: HTTPAuthScheme.values()) {
++ if(name.equalsIgnoreCase(s.name())) return s;
++ }
++ }
++ return null;
++ }
++
++ static public HTTPAuthScheme fromAuthScope(String scheme)
++ {
++ if(scheme == null) return null;
++ if(scheme.equals(AuthPolicy.BASIC))
++ return BASIC;
++ if(scheme.equals(AuthPolicy.DIGEST))
++ return DIGEST;
++ if(scheme.equals(AuthPolicy.NTLM))
++ return NTLM;
++ return null;
++ }
++}
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPAuthStore.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPAuthStore.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPAuthStore.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPAuthStore.java 2013-09-16 06:54:44.698149816 +0200
+@@ -38,7 +38,8 @@
+ import java.util.*;
+ import java.io.*;
+
+-import org.apache.commons.httpclient.auth.*;
++import org.apache.http.auth.*;
++import org.apache.http.client.CredentialsProvider;
+
+ import javax.crypto.*;
+ import javax.crypto.spec.*;
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPBasicProvider.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPBasicProvider.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPBasicProvider.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPBasicProvider.java 2013-09-16 07:10:52.770325065 +0200
+@@ -1,85 +1,108 @@
+-/*
+- * 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 org.apache.commons.httpclient.Credentials;
+-import org.apache.commons.httpclient.UsernamePasswordCredentials;
+-import org.apache.commons.httpclient.auth.AuthScheme;
+-import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
+-import org.apache.commons.httpclient.auth.CredentialsProvider;
+-
+-import java.io.IOException;
+-import java.io.Serializable;
+-
+-
+-//////////////////////////////////////////////////
+-// Provide a non-interactive CredentialsProvider to hold
+-// a username + password that might have been taken from e.g.
+-// the user info part of a URL.
+-
+-public class HTTPBasicProvider implements CredentialsProvider, Credentials, Serializable
+-{
+- String username = null;
+- String password = null;
+-
+- public HTTPBasicProvider(String username, String password)
+- {
+- this.username = username;
+- this.password = password;
+- }
+-
+- // Credentials Provider Interface
+- public Credentials
+- getCredentials(AuthScheme authscheme, String host, int port, boolean isproxy)
+- throws CredentialsNotAvailableException
+- {
+- UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
+- return creds;
+- }
+-
+- // Serializable Interface
+- private void writeObject(java.io.ObjectOutputStream oos)
+- throws IOException
+- {
+- oos.writeObject(this.username);
+- oos.writeObject(this.password);
+- }
+-
+- private void readObject(java.io.ObjectInputStream ois)
+- throws IOException, ClassNotFoundException
+- {
+- this.username = (String) ois.readObject();
+- this.password = (String) ois.readObject();
+- }
+-}
++/*
++ * 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 org.apache.http.auth.*;
++import org.apache.http.client.CredentialsProvider;
++
++import java.io.IOException;
++import java.io.Serializable;
++import java.security.Principal;
++
++
++//////////////////////////////////////////////////
++// Provide a non-interactive CredentialsProvider to hold
++// a username + password that might have been taken from e.g.
++// the user info part of a URL.
++
++public class HTTPBasicProvider implements CredentialsProvider, Credentials, Serializable
++{
++ String username = null;
++ String password = null;
++
++ public HTTPBasicProvider(String username, String password)
++ {
++ this.username = username;
++ this.password = password;
++ }
++
++ // Credentials Provider Interface
++ public Credentials
++ getCredentials(AuthScope scope) //AuthScheme authscheme, String host, int port, boolean isproxy)
++ {
++ UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
++ return creds;
++ }
++
++ public void
++ setCredentials(AuthScope authscope, Credentials credentials)
++ {
++
++ }
++
++ public void
++ clear()
++ {
++
++ }
++
++ // Credentials Interface
++ public Principal
++ getUserPrincipal()
++ {
++ return null;
++ }
++
++ public String
++ getPassword()
++ {
++ return null;
++ }
++
++
++ // Serializable Interface
++ private void writeObject(java.io.ObjectOutputStream oos)
++ throws IOException
++ {
++ oos.writeObject(this.username);
++ oos.writeObject(this.password);
++ }
++
++ private void readObject(java.io.ObjectInputStream ois)
++ throws IOException, ClassNotFoundException
++ {
++ this.username = (String) ois.readObject();
++ this.password = (String) ois.readObject();
++ }
++}
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HttpClientManager.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HttpClientManager.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HttpClientManager.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HttpClientManager.java 2013-09-16 07:13:05.281368349 +0200
+@@ -1,374 +1,372 @@
+-/*
+- * 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 org.apache.commons.httpclient.Header;
+-import org.apache.commons.httpclient.HttpMethodBase;
+-import org.apache.commons.httpclient.params.HttpMethodParams;
+-import org.apache.commons.httpclient.auth.CredentialsProvider;
+-
+-import java.io.*;
+-import java.util.zip.InflaterInputStream;
+-import java.util.zip.GZIPInputStream;
+-import java.util.Formatter;
+-
+-import ucar.nc2.util.IO;
+-import ucar.unidata.util.Urlencoded;
+-
+-/**
+- * Convenience routines that wrap HTTPSession.
+- *
+- * @author caron
+- */
+-public class HttpClientManager
+-{
+- static private boolean debug = false;
+- static private int timeout = 0;
+-
+- /**
+- * initialize the HttpClient layer.
+- *
+- * @param provider CredentialsProvider.
+- * @param userAgent Content of User-Agent header, may be null
+- */
+- static public void init(CredentialsProvider provider, String userAgent)
+- {
+- if(provider != null)
+- HTTPSession.setGlobalCredentialsProvider(provider);
+-
+- if(userAgent != null)
+- HTTPSession.setGlobalUserAgent(userAgent + "/NetcdfJava/HttpClient");
+- else
+- HTTPSession.setGlobalUserAgent("NetcdfJava/HttpClient");
+-
+- }
+-
+- public static void clearState()
+- {
+- }
+-
+- /**
+- * Get the content from a url. For large returns, its better to use getResponseAsStream.
+- *
+- * @param urlencoded url as a String
+- * @return contents of url as a String
+- * @throws java.io.IOException on error
+- */
+- @Urlencoded
+- public static String getContentAsString(String urlencoded)
+- throws IOException
+- {
+- return getContentAsString(null,urlencoded);
+- }
+-
+- /**
+- * Get the content from a url. For large returns, its better to use getResponseAsStream.
+- *
+- * @param session use this session, if null, create a new one
+- * @param urlencoded url as a String
+- * @return contents of url as a String
+- * @throws java.io.IOException on error
+- */
+- @Urlencoded @Deprecated
+- public static String getContentAsString(HTTPSession session, String urlencoded) throws IOException
+- {
+- HTTPSession useSession = session;
+- try {
+- if(useSession == null)
+- useSession = new HTTPSession();
+- HTTPMethod m = HTTPMethod.Get(useSession);
+- m.execute(urlencoded);
+- return m.getResponseAsString();
+- } finally {
+- if((session == null) && (useSession != null))
+- useSession.close();
+- }
+- }
+-
+- /**
+- * Put content to a url, using HTTP PUT. Handles one level of 302 redirection.
+- *
+- * @param urlencoded url as a String
+- * @param content PUT this content at the given url.
+- * @return the HTTP status return code
+- * @throws java.io.IOException on error
+- */
+- public static int putContent(String urlencoded, String content) throws IOException
+- {
+- HTTPSession session = null;
+-
+- try {
+-
+- session = new HTTPSession();
+- HTTPMethod m = HTTPMethod.Put(session);
+-
+- m.setRequestContentAsString(content);
+-
+- m.execute(urlencoded);
+-
+- int resultCode = m.getStatusCode();
+-
+- // followRedirect wont work for PUT
+- if(resultCode == 302) {
+- String redirectLocation;
+- Header locationHeader = m.getResponseHeader("location");
+- if(locationHeader != null) {
+- redirectLocation = locationHeader.getValue();
+- resultCode = putContent(redirectLocation, content);
+- }
+- }
+-
+- return resultCode;
+-
+- } finally {
+- if(session != null) session.close();
+- }
+- }
+-
+- //////////////////////
+-
+- static public String getUrlContentsAsString(String urlencoded, int maxKbytes)
+- {
+- return getUrlContentsAsString(null,urlencoded,maxKbytes);
+- }
+-
+- @Deprecated
+- static public String getUrlContentsAsString(HTTPSession session, String urlencoded, int maxKbytes)
+- {
+- HTTPSession useSession = session;
+- try {
+- if(useSession == null)
+- useSession = new HTTPSession();
+-
+- HTTPMethod m = HTTPMethod.Get(useSession);
+- m.setFollowRedirects(true);
+- m.setRequestHeader("Accept-Encoding", "gzip,deflate");
+-
+- int status = m.execute(urlencoded);
+- if(status != 200) {
+- throw new RuntimeException("failed status = " + status);
+- }
+-
+- String charset = m.getResponseCharSet();
+- if(charset == null) charset = "UTF-8";
+-
+- // check for deflate and gzip compression
+- Header h = m.getResponseHeader("content-encoding");
+- String encoding = (h == null) ? null : h.getValue();
+-
+- if(encoding != null && encoding.equals("deflate")) {
+- byte[] body = m.getResponseAsBytes();
+- InputStream is = new BufferedInputStream(new InflaterInputStream(new ByteArrayInputStream(body)), 10000);
+- return readContents(is, charset, maxKbytes);
+-
+- } else if(encoding != null && encoding.equals("gzip")) {
+- byte[] body = m.getResponseAsBytes();
+- InputStream is = new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(body)), 10000);
+- return readContents(is, charset, maxKbytes);
+-
+- } else {
+- byte[] body = m.getResponseAsBytes(maxKbytes * 1000);
+- return new String(body, charset);
+- }
+-
+- } catch (Exception e) {
+- if(debug) e.printStackTrace();
+- return null;
+-
+- } finally {
+- if((session == null) && (useSession != null))
+- useSession.close();
+- }
+- }
+-
+- static private String readContents(InputStream is, String charset, int maxKbytes) throws IOException
+- {
+- ByteArrayOutputStream bout = new ByteArrayOutputStream(1000 * maxKbytes);
+- IO.copy(is, bout, 1000 * maxKbytes);
+- return bout.toString(charset);
+- }
+-
+- static public void copyUrlContentsToFile(String urlencoded, File file)
+- throws HTTPException
+- {
+- copyUrlContentsToFile(null,urlencoded,file);
+- }
+-
+- @Deprecated
+- static public void copyUrlContentsToFile(HTTPSession session, String urlencoded, File file)
+- throws HTTPException
+- {
+- HTTPSession useSession = session;
+- try {
+- if(useSession == null)
+- useSession = new HTTPSession();
+-
+- HTTPMethod m = HTTPMethod.Get(useSession);
+- m.setRequestHeader("Accept-Encoding", "gzip,deflate");
+-
+- int status = m.execute(urlencoded);
+-
+- if(status != 200) {
+- throw new RuntimeException("failed status = " + status);
+- }
+-
+- String charset = m.getResponseCharSet();
+- if(charset == null) charset = "UTF-8";
+-
+- // check for deflate and gzip compression
+- Header h = m.getResponseHeader("content-encoding");
+- String encoding = (h == null) ? null : h.getValue();
+-
+- if(encoding != null && encoding.equals("deflate")) {
+- InputStream is = new BufferedInputStream(new InflaterInputStream(m.getResponseAsStream()), 10000);
+- IO.writeToFile(is, file.getPath());
+-
+- } else if(encoding != null && encoding.equals("gzip")) {
+- InputStream is = new BufferedInputStream(new GZIPInputStream(m.getResponseAsStream()), 10000);
+- IO.writeToFile(is, file.getPath());
+-
+- } else {
+- IO.writeToFile(m.getResponseAsStream(), file.getPath());
+- }
+-
+- } catch (Exception e) {
+- if(debug) e.printStackTrace();
+-
+- } finally {
+- if((session == null) && (useSession != null))
+- useSession.close();
+- }
+- }
+-
+- static public long appendUrlContentsToFile(String urlencoded, File file, long start, long end)
+- throws HTTPException
+- {
+- return appendUrlContentsToFile(null,urlencoded,file,start,end);
+- }
+-
+- @Deprecated
+- static public long appendUrlContentsToFile(HTTPSession session, String urlencoded, File file, long start, long end)
+- throws HTTPException
+- {
+- HTTPSession useSession = session;
+- long nbytes = 0;
+-
+- try {
+- if(useSession == null)
+- useSession = new HTTPSession();
+-
+- HTTPMethod m = HTTPMethod.Get(useSession);
+- m.setRequestHeader("Accept-Encoding", "gzip,deflate");
+- m.setRequestHeader("Range", "bytes=" + start + "-" + end);
+-
+- int status = m.execute(urlencoded);
+- if((status != 200) && (status != 206)) {
+- throw new RuntimeException("failed status = " + status);
+- }
+-
+- String charset = m.getResponseCharSet();
+- if(charset == null) charset = "UTF-8";
+-
+- // check for deflate and gzip compression
+- Header h = m.getResponseHeader("content-encoding");
+- String encoding = (h == null) ? null : h.getValue();
+-
+- if(encoding != null && encoding.equals("deflate")) {
+- InputStream is = new BufferedInputStream(new InflaterInputStream(m.getResponseAsStream()), 10000);
+- nbytes = IO.appendToFile(is, file.getPath());
+-
+- } else if(encoding != null && encoding.equals("gzip")) {
+- InputStream is = new BufferedInputStream(new GZIPInputStream(m.getResponseAsStream()), 10000);
+- nbytes = IO.appendToFile(is, file.getPath());
+-
+- } else {
+- nbytes = IO.appendToFile(m.getResponseAsStream(), file.getPath());
+- }
+-
+- } catch (Exception e) {
+- if(debug) e.printStackTrace();
+-
+- } finally {
+- if((session == null) && (useSession != null))
+- session.close();
+- }
+-
+- return nbytes;
+- }
+-
+- static public void showHttpRequestInfo(Formatter f, HttpMethodBase m)
+- {
+- f.format("HttpClient request %s %s %n", m.getName(), m.getPath());
+- f.format(" do Authentication=%s%n", m.getDoAuthentication());
+- f.format(" follow Redirects =%s%n", m.getFollowRedirects());
+- f.format(" effectiveVersion =%s%n", m.getEffectiveVersion());
+- f.format(" hostAuthState =%s%n", m.getHostAuthState());
+-
+- HttpMethodParams p = m.getParams();
+- f.format(" cookie policy =%s%n", p.getCookiePolicy());
+- f.format(" http version =%s%n", p.getVersion());
+- f.format(" timeout (msecs) =%d%n", p.getSoTimeout());
+- f.format(" virtual host =%s%n", p.getVirtualHost());
+-
+- f.format("Request Headers = %n");
+- Header[] heads = m.getRequestHeaders();
+- for(int i = 0;i < heads.length;i++)
+- f.format(" %s", heads[i]);
+-
+- f.format("%n");
+- }
+-
+- static public void showHttpResponseInfo(Formatter f, HttpMethodBase m)
+- {
+- f.format("HttpClient response status = %s%n", m.getStatusLine());
+- f.format("Reponse Headers = %n");
+- Header[] heads = m.getResponseHeaders();
+- for(int i = 0;i < heads.length;i++)
+- f.format(" %s", heads[i]);
+- f.format("%n");
+- }
+-
+- /*
+- public static void main(String[] args) throws IOException
+- {
+- HTTPSession.setGlobalUserAgent("TestUserAgent123global");
+- HttpClientManager.getContentAsString(null, "http://motherlode.ucar.edu:9080/thredds/catalog.html");
+-
+- HTTPSession sess = new HTTPSession("http://motherlode.ucar.edu:9080/thredds/catalog.html");
+- sess.setUserAgent("TestUserAgent123session");
+- HttpClientManager.getContentAsString(sess, "http://motherlode.ucar.edu:9080/thredds/catalog.html");
+-
+- } */
+-
+-}
++/*
++ * 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 org.apache.http.Header;
++
++import java.io.*;
++import java.util.zip.InflaterInputStream;
++import java.util.zip.GZIPInputStream;
++
++import org.apache.http.client.CredentialsProvider;
++import ucar.nc2.util.IO;
++import ucar.unidata.util.Urlencoded;
++
++/**
++ * Convenience routines that wrap HTTPSession.
++ *
++ * @author caron
++ */
++public class HttpClientManager
++{
++ static private boolean debug = false;
++ static private int timeout = 0;
++
++ /**
++ * initialize the HttpClient layer.
++ *
++ * @param provider CredentialsProvider.
++ * @param userAgent Content of User-Agent header, may be null
++ */
++ static public void init(CredentialsProvider provider, String userAgent)
++ {
++ if(provider != null)
++ HTTPSession.setGlobalCredentialsProvider(provider);
++
++ if(userAgent != null)
++ HTTPSession.setGlobalUserAgent(userAgent + "/NetcdfJava/HttpClient");
++ else
++ HTTPSession.setGlobalUserAgent("NetcdfJava/HttpClient");
++
++ }
++
++ public static void clearState()
++ {
++ }
++
++ /**
++ * Get the content from a url. For large returns, its better to use getResponseAsStream.
++ *
++ * @param urlencoded url as a String
++ * @return contents of url as a String
++ * @throws java.io.IOException on error
++ */
++ @Urlencoded
++ public static String getContentAsString(String urlencoded)
++ throws IOException
++ {
++ return getContentAsString(null,urlencoded);
++ }
++
++ /**
++ * Get the content from a url. For large returns, its better to use getResponseAsStream.
++ *
++ * @param session use this session, if null, create a new one
++ * @param urlencoded url as a String
++ * @return contents of url as a String
++ * @throws java.io.IOException on error
++ */
++ @Urlencoded @Deprecated
++ public static String getContentAsString(HTTPSession session, String urlencoded) throws IOException
++ {
++ HTTPSession useSession = session;
++ try {
++ if(useSession == null)
++ useSession = HTTPFactory.newSession();
++ HTTPMethod m = HTTPFactory.Get(useSession);
++ m.execute(urlencoded);
++ return m.getResponseAsString();
++ } finally {
++ if((session == null) && (useSession != null))
++ useSession.close();
++ }
++ }
++
++ /**
++ * Put content to a url, using HTTP PUT. Handles one level of 302 redirection.
++ *
++ * @param urlencoded url as a String
++ * @param content PUT this content at the given url.
++ * @return the HTTP status return code
++ * @throws java.io.IOException on error
++ */
++ public static int putContent(String urlencoded, String content) throws IOException
++ {
++ HTTPSession session = null;
++
++ try {
++
++ session = HTTPFactory.newSession();
++ HTTPMethod m = HTTPFactory.Put(session);
++
++ m.setRequestContentAsString(content);
++
++ m.execute(urlencoded);
++
++ int resultCode = m.getStatusCode();
++
++ // followRedirect wont work for PUT
++ if(resultCode == 302) {
++ String redirectLocation;
++ Header locationHeader = m.getResponseHeader("location");
++ if(locationHeader != null) {
++ redirectLocation = locationHeader.getValue();
++ resultCode = putContent(redirectLocation, content);
++ }
++ }
++
++ return resultCode;
++
++ } finally {
++ if(session != null) session.close();
++ }
++ }
++
++ //////////////////////
++
++ static public String getUrlContentsAsString(String urlencoded, int maxKbytes)
++ {
++ return getUrlContentsAsString(null,urlencoded,maxKbytes);
++ }
++
++ @Deprecated
++ static public String getUrlContentsAsString(HTTPSession session, String urlencoded, int maxKbytes)
++ {
++ HTTPSession useSession = session;
++ try {
++ if(useSession == null)
++ useSession = HTTPFactory.newSession();
++
++ HTTPMethod m = HTTPFactory.Get(useSession);
++ m.setFollowRedirects(true);
++ m.setRequestHeader("Accept-Encoding", "gzip,deflate");
++
++ int status = m.execute(urlencoded);
++ if(status != 200) {
++ throw new RuntimeException("failed status = " + status);
++ }
++
++ String charset = m.getResponseCharSet();
++ if(charset == null) charset = "UTF-8";
++
++ // check for deflate and gzip compression
++ Header h = m.getResponseHeader("content-encoding");
++ String encoding = (h == null) ? null : h.getValue();
++
++ if(encoding != null && encoding.equals("deflate")) {
++ byte[] body = m.getResponseAsBytes();
++ InputStream is = new BufferedInputStream(new InflaterInputStream(new ByteArrayInputStream(body)), 10000);
++ return readContents(is, charset, maxKbytes);
++
++ } else if(encoding != null && encoding.equals("gzip")) {
++ byte[] body = m.getResponseAsBytes();
++ InputStream is = new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(body)), 10000);
++ return readContents(is, charset, maxKbytes);
++
++ } else {
++ byte[] body = m.getResponseAsBytes(maxKbytes * 1000);
++ return new String(body, charset);
++ }
++
++ } catch (Exception e) {
++ if(debug) e.printStackTrace();
++ return null;
++
++ } finally {
++ if((session == null) && (useSession != null))
++ useSession.close();
++ }
++ }
++
++ static private String readContents(InputStream is, String charset, int maxKbytes) throws IOException
++ {
++ ByteArrayOutputStream bout = new ByteArrayOutputStream(1000 * maxKbytes);
++ IO.copy(is, bout, 1000 * maxKbytes);
++ return bout.toString(charset);
++ }
++
++ static public void copyUrlContentsToFile(String urlencoded, File file)
++ throws HTTPException
++ {
++ copyUrlContentsToFile(null,urlencoded,file);
++ }
++
++ @Deprecated
++ static public void copyUrlContentsToFile(HTTPSession session, String urlencoded, File file)
++ throws HTTPException
++ {
++ HTTPSession useSession = session;
++ try {
++ if(useSession == null)
++ useSession = HTTPFactory.newSession();
++
++ HTTPMethod m = HTTPFactory.Get(useSession);
++ m.setRequestHeader("Accept-Encoding", "gzip,deflate");
++
++ int status = m.execute(urlencoded);
++
++ if(status != 200) {
++ throw new RuntimeException("failed status = " + status);
++ }
++
++ String charset = m.getResponseCharSet();
++ if(charset == null) charset = "UTF-8";
++
++ // check for deflate and gzip compression
++ Header h = m.getResponseHeader("content-encoding");
++ String encoding = (h == null) ? null : h.getValue();
++
++ if(encoding != null && encoding.equals("deflate")) {
++ InputStream is = new BufferedInputStream(new InflaterInputStream(m.getResponseAsStream()), 10000);
++ IO.writeToFile(is, file.getPath());
++
++ } else if(encoding != null && encoding.equals("gzip")) {
++ InputStream is = new BufferedInputStream(new GZIPInputStream(m.getResponseAsStream()), 10000);
++ IO.writeToFile(is, file.getPath());
++
++ } else {
++ IO.writeToFile(m.getResponseAsStream(), file.getPath());
++ }
++
++ } catch (Exception e) {
++ if(debug) e.printStackTrace();
++
++ } finally {
++ if((session == null) && (useSession != null))
++ useSession.close();
++ }
++ }
++
++ static public long appendUrlContentsToFile(String urlencoded, File file, long start, long end)
++ throws HTTPException
++ {
++ return appendUrlContentsToFile(null,urlencoded,file,start,end);
++ }
++
++ @Deprecated
++ static public long appendUrlContentsToFile(HTTPSession session, String urlencoded, File file, long start, long end)
++ throws HTTPException
++ {
++ HTTPSession useSession = session;
++ long nbytes = 0;
++
++ try {
++ if(useSession == null)
++ useSession = HTTPFactory.newSession();
++
++ HTTPMethod m = HTTPFactory.Get(useSession);
++ m.setRequestHeader("Accept-Encoding", "gzip,deflate");
++ m.setRequestHeader("Range", "bytes=" + start + "-" + end);
++
++ int status = m.execute(urlencoded);
++ if((status != 200) && (status != 206)) {
++ throw new RuntimeException("failed status = " + status);
++ }
++
++ String charset = m.getResponseCharSet();
++ if(charset == null) charset = "UTF-8";
++
++ // check for deflate and gzip compression
++ Header h = m.getResponseHeader("content-encoding");
++ String encoding = (h == null) ? null : h.getValue();
++
++ if(encoding != null && encoding.equals("deflate")) {
++ InputStream is = new BufferedInputStream(new InflaterInputStream(m.getResponseAsStream()), 10000);
++ nbytes = IO.appendToFile(is, file.getPath());
++
++ } else if(encoding != null && encoding.equals("gzip")) {
++ InputStream is = new BufferedInputStream(new GZIPInputStream(m.getResponseAsStream()), 10000);
++ nbytes = IO.appendToFile(is, file.getPath());
++
++ } else {
++ nbytes = IO.appendToFile(m.getResponseAsStream(), file.getPath());
++ }
++
++ } catch (Exception e) {
++ if(debug) e.printStackTrace();
++
++ } finally {
++ if((session == null) && (useSession != null))
++ session.close();
++ }
++
++ return nbytes;
++ }
++
++ /* todo:
++ static public void showHttpRequestInfo(Formatter f, HttpRequestBase m)
++ {
++ f.format("HttpClient request %s %s %n", m.getName(), m.getPath());
++ f.format(" do Authentication=%s%n", m.getDoAuthentication());
++ f.format(" follow Redirects =%s%n", m.getFollowRedirects());
++ f.format(" effectiveVersion =%s%n", m.getEffectiveVersion());
++ f.format(" hostAuthState =%s%n", m.getHostAuthState());
++
++ HttpMethodParams p = m.getParams();
++ f.format(" cookie policy =%s%n", p.getCookiePolicy());
++ f.format(" http version =%s%n", p.getVersion());
++ f.format(" timeout (msecs) =%d%n", p.getSoTimeout());
++ f.format(" virtual host =%s%n", p.getVirtualHost());
++
++ f.format("Request Headers = %n");
++ Header[] heads = m.getRequestHeaders();
++ for(int i = 0;i < heads.length;i++)
++ f.format(" %s", heads[i]);
++
++ f.format("%n");
++ }
++
++ static public void showHttpResponseInfo(Formatter f, HttpRequest m)
++ {
++ f.format("HttpClient response status = %s%n", m.getStatusLine());
++ f.format("Reponse Headers = %n");
++ Header[] heads = m.getResponseHeaders();
++ for(int i = 0;i < heads.length;i++)
++ f.format(" %s", heads[i]);
++ f.format("%n");
++ } */
++
++ /*
++ public static void main(String[] args) throws IOException
++ {
++ HTTPSession.setGlobalUserAgent("TestUserAgent123global");
++ HttpClientManager.getContentAsString(null, "http://motherlode.ucar.edu:9080/thredds/catalog.html");
++
++ HTTPSession sess = HTTPFactory.newSession("http://motherlode.ucar.edu:9080/thredds/catalog.html");
++ sess.setUserAgent("TestUserAgent123session");
++ HttpClientManager.getContentAsString(sess, "http://motherlode.ucar.edu:9080/thredds/catalog.html");
++
++ } */
++
++}
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPCredsProvider.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPCredsProvider.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPCredsProvider.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPCredsProvider.java 2013-09-16 07:05:07.959427605 +0200
+@@ -1,96 +1,122 @@
+-/*
+- * 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 org.apache.commons.httpclient.Credentials;
+-import org.apache.commons.httpclient.auth.AuthScheme;
+-import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
+-import org.apache.commons.httpclient.auth.CredentialsProvider;
+-
+-import java.io.IOException;
+-import java.io.Serializable;
+-
+-
+-//////////////////////////////////////////////////
+-// Provide a non-interactive CredentialsProvider to hold
+-// an arbitrary credentials object provided by the user.
+-
+-public class HTTPCredsProvider implements CredentialsProvider, Credentials, Serializable
+-{
+- Credentials creds = null;
+-
+- public HTTPCredsProvider(Credentials creds)
+- {
+- this.creds = creds;
+- }
+-
+- // Credentials Provider Interface
+- public Credentials
+- getCredentials(AuthScheme authscheme, String host, int port, boolean isproxy)
+- throws CredentialsNotAvailableException
+- {
+- return creds;
+- }
+-
+- // Serializable Interface
+- private void writeObject(java.io.ObjectOutputStream oos)
+- throws IOException
+- {
+- boolean isser = (this.creds instanceof Serializable);
+- oos.writeObject(isser);
+- if(isser)
+- oos.writeObject(this.creds);
+- else {
+- oos.writeObject(this.creds.getClass());
+- }
+- }
+-
+- private void readObject(java.io.ObjectInputStream ois)
+- throws IOException, ClassNotFoundException
+- {
+- // serializing the credentials is a bit tricky
+- // since it might not support the serializable interface.
+- boolean isser = (Boolean)ois.readObject();
+- Object o = ois.readObject();
+- if(isser)
+- this.creds = (Credentials)o;
+- else {
+- try {
+- this.creds = (Credentials)((Class)o).newInstance();
+- } catch (Exception e) {
+- throw new ClassNotFoundException("HTTPCredsProvider: Cannot create Credentials instance",e);
+- }
+- }
+- }
+-}
++/*
++ * 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 org.apache.http.auth.*;
++import org.apache.http.client.CredentialsProvider;
++
++import java.io.IOException;
++import java.io.Serializable;
++import java.security.Principal;
++
++
++/**
++Provide a non-interactive CredentialsProvider to hold
++an arbitrary credentials object provided by the user.
++This is used in the case when the credentials (not the provider)
++are fixed. (see e.g. HTTPSession.setGlobalCredentials).
++*/
++
++public class HTTPCredsProvider implements CredentialsProvider, Credentials, Serializable
++{
++ Credentials creds = null;
++
++ public HTTPCredsProvider(Credentials creds)
++ {
++ this.creds = creds;
++ }
++
++ // Credentials Provider Interface
++ public Credentials
++ getCredentials(AuthScope scope) //AuthScheme authscheme, String host, int port, boolean isproxy)
++ {
++ return creds;
++ }
++
++ public void
++ setCredentials(AuthScope authscope, Credentials credentials)
++ {
++
++ }
++
++ public void
++ clear()
++ {
++
++ }
++
++ // Credentials Interface
++ public Principal
++ getUserPrincipal()
++ {
++ return null;
++ }
++
++ public String
++ getPassword()
++ {
++ return null;
++ }
++
++ // Serializable Interface
++ private void writeObject(java.io.ObjectOutputStream oos)
++ throws IOException
++ {
++ boolean isser = (this.creds instanceof Serializable);
++ oos.writeObject(isser);
++ if(isser)
++ oos.writeObject(this.creds);
++ else {
++ oos.writeObject(this.creds.getClass());
++ }
++ }
++
++ private void readObject(java.io.ObjectInputStream ois)
++ throws IOException, ClassNotFoundException
++ {
++ // serializing the credentials is a bit tricky
++ // since it might not support the serializable interface.
++ boolean isser = (Boolean) ois.readObject();
++ Object o = ois.readObject();
++ if(isser)
++ this.creds = (Credentials) o;
++ else {
++ try {
++ this.creds = (Credentials) ((Class) o).newInstance();
++ } catch (Exception e) {
++ throw new ClassNotFoundException("HTTPCredsProvider: Cannot create Credentials instance", e);
++ }
++ }
++ }
++}
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPFactory.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPFactory.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPFactory.java 1970-01-01 01:00:00.000000000 +0100
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPFactory.java 2013-09-16 07:24:06.604650208 +0200
+@@ -0,0 +1,174 @@
++/*
++ * 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 java.io.*;
++import java.net.MalformedURLException;
++import java.net.URISyntaxException;
++import java.net.URL;
++import java.util.*;
++
++import net.jcip.annotations.NotThreadSafe;
++import org.apache.http.*;
++import org.apache.http.client.methods.*;
++import org.apache.http.client.params.AllClientPNames;
++import org.apache.http.params.HttpParams;
++import org.apache.http.protocol.HttpContext;
++import ucar.nc2.util.EscapeStrings;
++
++/**
++ * HTTPFactory creates method instance.
++ * This code was originally in HttpMethod.
++ */
++
++public class HTTPFactory
++{
++
++ //////////////////////////////////////////////////////////////////////////
++ // Static factory methods for creating HTTPSession instances
++
++ static public HTTPSession newSession() throws HTTPException
++ {
++ return new HTTPSession();
++ }
++
++ static public HTTPSession newSession(String legalurl) throws HTTPException
++ {
++ return new HTTPSession(legalurl);
++ }
++
++ //////////////////////////////////////////////////////////////////////////
++ // Static factory methods for creating HTTPMethod instances
++
++ static public HTTPMethod Get(HTTPSession session) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Get, session, null);
++ }
++
++ static public HTTPMethod Head(HTTPSession session) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Head, session, null);
++ }
++
++ static public HTTPMethod Put(HTTPSession session) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Put, session, null);
++ }
++
++ static public HTTPMethod Post(HTTPSession session) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Post, session, null);
++ }
++
++ static public HTTPMethod Options(HTTPSession session) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Options, session, null);
++ }
++
++ static public HTTPMethod Get(HTTPSession session, String legalurl) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Get, session, legalurl);
++ }
++
++ static public HTTPMethod Head(HTTPSession session, String legalurl) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Head, session, legalurl);
++ }
++
++ static public HTTPMethod Put(HTTPSession session, String legalurl) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Put, session, legalurl);
++ }
++
++ static public HTTPMethod Post(HTTPSession session, String legalurl) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Post, session, legalurl);
++ }
++
++ static public HTTPMethod Options(HTTPSession session, String legalurl) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Options, session, legalurl);
++ }
++
++ static public HTTPMethod Get(String legalurl) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Get, legalurl);
++ }
++
++ static public HTTPMethod Head(String legalurl) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Head, legalurl);
++ }
++
++ static public HTTPMethod Put(String legalurl) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Put, legalurl);
++ }
++
++ static public HTTPMethod Post(String legalurl) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Post, legalurl);
++ }
++
++ static public HTTPMethod Options(String legalurl) throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Options, legalurl);
++ }
++
++ static public HTTPMethod Get() throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Get);
++ }
++
++ static public HTTPMethod Head() throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Head);
++ }
++
++ static public HTTPMethod Put() throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Put);
++ }
++
++ static public HTTPMethod Post() throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Post);
++ }
++
++ static public HTTPMethod Options() throws HTTPException
++ {
++ return new HTTPMethod(HTTPSession.Methods.Options);
++ }
++
++}
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPMethod.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPMethod.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPMethod.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPMethod.java 2013-09-16 06:44:59.065924414 +0200
+@@ -37,22 +37,25 @@
+ import java.net.MalformedURLException;
+ import java.net.URISyntaxException;
+ import java.net.URL;
++import java.nio.charset.Charset;
+ import java.util.*;
+
+-import com.sun.org.apache.xerces.internal.util.*;
+ import net.jcip.annotations.NotThreadSafe;
+-import org.apache.commons.httpclient.*;
+-import org.apache.commons.httpclient.URI;
+-import org.apache.commons.httpclient.methods.*;
+-import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+-import org.apache.commons.httpclient.methods.multipart.Part;
+-import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
+-import org.apache.commons.httpclient.params.HttpMethodParams;
+-import org.apache.commons.httpclient.auth.*;
+-
+-import org.apache.commons.httpclient.protocol.Protocol;
++import org.apache.http.*;
++import org.apache.http.client.CredentialsProvider;
++import org.apache.http.client.methods.*;
++import org.apache.http.client.params.AllClientPNames;
++import org.apache.http.entity.StringEntity;
++import org.apache.http.message.BasicHeader;
++import org.apache.http.message.BasicHttpResponse;
++import org.apache.http.params.BasicHttpParams;
++import org.apache.http.params.HttpParams;
++import org.apache.http.protocol.HttpContext;
++import org.apache.http.util.EntityUtils;
+ import ucar.nc2.util.EscapeStrings;
+
++import javax.print.URIException;
++
+
+ /**
+ * HTTPMethod is the encapsulation of specific
+@@ -60,9 +63,9 @@
+ * The general processing sequence is as follows.
+ * <ol>
+ * <li> Create an HTTPMethod object using one of the
+- * factory methods (e.g. HTTPMethod.Get()).
++ * methods of HTTPFactory (e.g. HTTPFactory.Get()).
+ * <p/>
+- * <li> Set parameters and headers.
++ * <li> Set parameters and headers of the returned HTTPMethod instance.
+ * <p/>
+ * <li> Invoke the execute() method to actually make
+ * the request.
+@@ -128,7 +131,7 @@
+ * To support this use case, HTTPMethod supports what amounts
+ * to a one-shot use. The steps are as follows:
+ * <ol>
+- * <li> HTTPMethod method = HTTPMethod.Get(<url string>); note
++ * <li> HTTPMethod method = HTTPFactory.Get(<url string>); note
+ * that this implicitly creates a session internal to the
+ * method instance.
+ * <p/>
+@@ -161,149 +164,6 @@
+ public class HTTPMethod
+ {
+ //////////////////////////////////////////////////////////////////////////
+- // Static factory methods
+-
+- static public HTTPMethod Get(HTTPSession session) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Get, session, null);
+- }
+-
+- static public HTTPMethod Head(HTTPSession session) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Head, session, null);
+- }
+-
+- static public HTTPMethod Put(HTTPSession session) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Put, session, null);
+- }
+-
+- static public HTTPMethod Post(HTTPSession session) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Post, session, null);
+- }
+-
+- static public HTTPMethod Options(HTTPSession session) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Options, session, null);
+- }
+-
+- static public HTTPMethod Get(HTTPSession session, String legalurl) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Get, session, legalurl);
+- }
+-
+- static public HTTPMethod Head(HTTPSession session, String legalurl) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Head, session, legalurl);
+- }
+-
+- static public HTTPMethod Put(HTTPSession session, String legalurl) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Put, session, legalurl);
+- }
+-
+- static public HTTPMethod Post(HTTPSession session, String legalurl) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Post, session, legalurl);
+- }
+-
+- static public HTTPMethod Options(HTTPSession session, String legalurl) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Options, session, legalurl);
+- }
+-
+- static public HTTPMethod Get(String legalurl) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Get, legalurl);
+- }
+-
+- static public HTTPMethod Head(String legalurl) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Head, legalurl);
+- }
+-
+- static public HTTPMethod Put(String legalurl) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Put, legalurl);
+- }
+-
+- static public HTTPMethod Post(String legalurl) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Post, legalurl);
+- }
+-
+- static public HTTPMethod Options(String legalurl) throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Options, legalurl);
+- }
+-
+- static public HTTPMethod Get() throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Get);
+- }
+-
+- static public HTTPMethod Head() throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Head);
+- }
+-
+- static public HTTPMethod Put() throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Put);
+- }
+-
+- static public HTTPMethod Post() throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Post);
+- }
+-
+- static public HTTPMethod Options() throws HTTPException
+- {
+- return new HTTPMethod(HTTPSession.Methods.Options);
+- }
+-
+- //////////////////////////////////////////////////////////////////////////
+- // Constants
+-
+- //////////////////////////////////////////////////
+- // Type declarations
+-
+- // Define a Retry Handler that supports specifiable retries
+- // and is optionally verbose.
+- static public class RetryHandler
+- extends org.apache.commons.httpclient.DefaultHttpMethodRetryHandler
+- {
+- static final int DFALTRETRIES = 5;
+- static int retries = DFALTRETRIES;
+- static boolean verbose = false;
+-
+- public RetryHandler()
+- {
+- super(retries, false);
+- }
+-
+- public boolean retryMethod(final org.apache.commons.httpclient.HttpMethod method,
+- final IOException exception,
+- int executionCount)
+- {
+- if(verbose) {
+- HTTPSession.log.debug(String.format("Retry: count=%d exception=%s\n", executionCount, exception.toString()));
+- }
+- return super.retryMethod(method, exception, executionCount);
+- }
+-
+- static public int getRetries() {return RetryHandler.retries;}
+- static public void setRetries(int retries)
+- {
+- if(retries > 0)
+- RetryHandler.retries = retries;
+- }
+- static public boolean getVerbose() {return RetryHandler.verbose;}
+- static public void setVerbose(boolean tf) {RetryHandler.verbose = tf;}
+- }
+-
+- //////////////////////////////////////////////////////////////////////////
+ // Static variables
+
+ static HashMap<String, Object> globalparams = new HashMap<String, Object>();
+@@ -317,25 +177,23 @@
+ globalparams.put(name, value);
+ }
+
+- static public int getRetryCount() {return RetryHandler.getRetries();}
+- static public void setRetryCount(int count)
+- {RetryHandler.setRetries(count);}
+-
+ //////////////////////////////////////////////////
+ // Instance fields
+
+ HTTPSession session = null;
+ boolean localsession = false;
+- HttpMethodBase method = null; // Current method
+ String legalurl = null;
+ List<Header> headers = new ArrayList<Header>();
+ HashMap<String, Object> params = new HashMap<String, Object>();
+- HttpState context = null;
+- RequestEntity content = null;
++ HttpContext context = null;
++ HttpEntity content = null;
+ HTTPSession.Methods methodclass = null;
+- Part[] multiparts = null;
+ HTTPMethodStream methodstream = null; // wrapper for strm
+ boolean closed = false;
++ HttpRequestBase method = null;
++ HttpResponse response = null;
++ //todo: List<org.apache.http.entity.mime.FormBodyPart> multiparts = null;
++
+
+
+ //////////////////////////////////////////////////
+@@ -357,7 +215,7 @@
+ throws HTTPException
+ {
+ if(session == null) {
+- session = new HTTPSession();
++ session = HTTPFactory.newSession();
+ localsession = true;
+ }
+ this.session = session;
+@@ -373,37 +231,37 @@
+ this.methodclass = m;
+ }
+
+- HttpMethodBase
++ HttpRequestBase
+ create()
+ {
+- HttpMethodBase method = null;
++ HttpRequestBase method = null;
+ // Unfortunately, the apache httpclient 3 code has a restrictive
+ // notion of a legal url, so we need to encode it before use
+ String urlencoded = EscapeStrings.escapeURL(this.legalurl);
+
+ switch (this.methodclass) {
+ case Put:
+- method = new PutMethod(urlencoded);
++ method = new HttpPut(urlencoded);
+ break;
+ case Post:
+- method = new PostMethod(urlencoded);
++ method = new HttpPost(urlencoded);
+ break;
+ case Get:
+- method = new GetMethod(urlencoded);
++ method = new HttpGet(urlencoded);
+ break;
+ case Head:
+- method = new HeadMethod(urlencoded);
++ method = new HttpHead(urlencoded);
+ break;
+ case Options:
+- method = new OptionsMethod(urlencoded);
++ method = new HttpOptions(urlencoded) ;
+ break;
+ default:
+ break;
+ }
+ // Force some actions
+ if(method != null) {
+- method.setFollowRedirects(true);
+- method.setDoAuthentication(true);
++ method.getParams().setParameter(AllClientPNames.HANDLE_REDIRECTS,true);
++ method.getParams().setParameter(AllClientPNames.HANDLE_AUTHENTICATION, true);
+ }
+ return method;
+ }
+@@ -413,14 +271,16 @@
+ switch (this.methodclass) {
+ case Put:
+ if(this.content != null)
+- ((PutMethod) method).setRequestEntity(this.content);
++ ((HttpPut)method).setEntity(this.content);
+ break;
+ case Post:
+- if(multiparts != null && multiparts.length > 0) {
+- MultipartRequestEntity mre = new MultipartRequestEntity(multiparts, method.getParams());
+- ((PostMethod) method).setRequestEntity(mre);
+- } else if(this.content != null)
+- ((PostMethod) method).setRequestEntity(this.content);
++ //todo: if(multiparts != null && multiparts.length > 0) {
++ // MultipartEntity mre = new MultipartEntity();
++ // for()
++ // ((PostMethod) method).setRequestEntity(mre);
++ //} else
++ if(this.content != null)
++ ((HttpPost) method).setEntity(this.content);
+ break;
+ case Head:
+ case Get:
+@@ -429,7 +289,7 @@
+ break;
+ }
+ this.content = null; // do not reuse
+- this.multiparts = null;
++ //todo: this.multiparts = null;
+ }
+
+ public int execute(String url) throws HTTPException
+@@ -448,51 +308,46 @@
+ if(!localsession && !sessionCompatible(this.legalurl))
+ throw new HTTPException("HTTPMethod: session incompatible url: " + this.legalurl);
+
+- if(this.method != null)
+- this.method.releaseConnection();
+- this.method = create();
++ if(method != null)
++ method.releaseConnection();
++ method = create();
+
+ try {
+ if(headers.size() > 0) {
+ for(Header h : headers) {
+- method.addRequestHeader(h);
++ method.addHeader(h);
+ }
+ }
+ if(globalparams != null) {
+- HttpMethodParams hmp = method.getParams();
++ HttpParams hmp = method.getParams();
+ for(String key : globalparams.keySet()) {
+ hmp.setParameter(key, globalparams.get(key));
+ }
+ }
+ if(params != null) {
+- HttpMethodParams hmp = method.getParams();
++ HttpParams hmp = method.getParams();
+ for(String key : params.keySet()) {
+ hmp.setParameter(key, params.get(key));
+ }
+ }
+
+- // Change the retry handler
+- method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new RetryHandler());
++ //todo: Change the retry handler
++ //httpclient.setHttpRequestRetryHandler(myRetryHandler);
++ //method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new RetryHandler());
+
+ setcontent();
+
+ setAuthentication(session, this);
+
+- // WARNING; DANGER WILL ROBINSION
+- // httpclient3 only allows one registered https protocol, so
+- // we built our own protocol registry to also take port into account
+- // (see HTTPSession.registerProtocol())
+-
+- // get the protocol and port
+- URL hack = new URL(this.legalurl);
+- Protocol handler = session.getProtocol(hack.getProtocol(),
+- hack.getPort());
+-
+- HostConfiguration hc = session.sessionClient.getHostConfiguration();
+- hc = new HostConfiguration(hc);
+- hc.setHost(hack.getHost(), hack.getPort(), handler);
+- session.sessionClient.executeMethod(hc, method);
+- int code = getStatusCode();
++ //todo: get the protocol and port
++ //URL hack = new URL(this.legalurl);
++ //Protocol handler = session.getProtocol(hack.getProtocol(),
++ // hack.getPort());
++ //HostConfiguration hc = session.sessionClient.getHostConfiguration();
++ //hc = new HostConfiguration(hc);
++ //hc.setHost(hack.getHost(), hack.getPort(), handler);
++ response = session.sessionClient.execute(method);
++ int code = response.getStatusLine().getStatusCode();
+ return code;
+ } catch (Exception ie) {
+ throw new HTTPException(ie);
+@@ -532,46 +387,42 @@
+ //////////////////////////////////////////////////
+ // Accessors
+
+- public void setContext(HttpState cxt)
++ public void setContext(HttpContext cxt)
+ {
+ session.setContext(cxt);
+ }
+
+- public HttpState getContext()
++ public HttpContext getContext()
+ {
+ return session.getContext();
+ }
+
+ public int getStatusCode()
+ {
+- return method == null ? 0 : method.getStatusCode();
++ return response == null ? 0 : response.getStatusLine().getStatusCode();
+ }
+
+ public String getStatusLine()
+ {
+- return method == null ? null : method.getStatusLine().toString();
++ return response == null ? null : response.getStatusLine().toString();
+ }
+
+ public String getRequestLine()
+ {
+ //fix: return (method == null ? null : method.getRequestLine().toString());
+- return "getrequestline not implemented";
++ throw new UnsupportedOperationException("getrequestline not implemented");
+ }
+
+ public String getPath()
+ {
+- try {
+- return (method == null ? null : method.getURI().toString());
+- } catch (URIException e) {
+- return null;
+- }
++ return (method == null ? null : method.getURI().toString());
+ }
+
+ public boolean canHoldContent()
+ {
+ if(method == null)
+ return false;
+- return !(method instanceof HeadMethod);
++ return !(method instanceof HttpHead);
+ }
+
+ public InputStream getResponseBodyAsStream()
+@@ -588,8 +439,8 @@
+ } else { // first time
+ HTTPMethodStream stream = null;
+ try {
+- if(method == null) return null;
+- stream = new HTTPMethodStream(method.getResponseBodyAsStream(), this);
++ if(response == null) return null;
++ stream = new HTTPMethodStream(response.getEntity().getContent(), this);
+ } catch (Exception e) {
+ stream = null;
+ }
+@@ -598,37 +449,40 @@
+ return this.methodstream;
+ }
+
++ public byte[] getResponseAsBytes(int maxbytes)
++ {
++ byte[] contents = getResponseAsBytes();
++ if(contents.length > maxbytes) {
++ byte[] result = new byte[maxbytes];
++ System.arraycopy(contents,0,result,0,maxbytes);
++ contents = result;
++ }
++ return contents;
++ }
++
+ public byte[] getResponseAsBytes()
+ {
+ if(closed)
+ throw new IllegalStateException("HTTPMethod: method is closed") ;
+ byte[] content = null;
++ if(response != null)
+ try {
+- content = method.getResponseBody();
++ content = EntityUtils.toByteArray(response.getEntity());
+ } catch (Exception e) {/*ignore*/}
+ return content;
+ }
+
+- public byte[] getResponseAsBytes(int maxsize)
+- {
+- byte[] content = getResponseAsBytes();
+- if(content != null && content.length > maxsize) {
+- byte[] limited = new byte[maxsize];
+- System.arraycopy(content, 0, limited, 0, maxsize);
+- content = limited;
+- }
+- return content;
+- }
+-
+ public String getResponseAsString(String charset)
+ {
+ if(closed)
+ throw new IllegalStateException("HTTPMethod: method is closed") ;
+- /*charset argument currently unused ?*/
+ String content = null;
++ if(response != null)
+ try {
+- content = method.getResponseBodyAsString();
++ Charset cset = Charset.forName(charset);
++ content = EntityUtils.toString(response.getEntity(),cset);
+ } catch (Exception e) {/*ignore*/}
++ close();//getting the response will disallow later stream
+ return content;
+ }
+
+@@ -650,7 +504,7 @@
+
+ public void setRequestHeader(String name, String value) throws HTTPException
+ {
+- setRequestHeader(new Header(name, value));
++ setRequestHeader(new BasicHeader(name, value));
+ }
+
+ public void setRequestHeader(Header h) throws HTTPException
+@@ -667,7 +521,7 @@
+ if(this.method == null)
+ return null;
+ try {
+- return (this.method.getRequestHeader(name));
++ return (this.method.getFirstHeader(name));
+ } catch (Exception e) {
+ return null;
+ }
+@@ -678,7 +532,7 @@
+ if(this.method == null)
+ return null;
+ try {
+- Header[] hs = this.method.getRequestHeaders();
++ Header[] hs = this.method.getAllHeaders();
+ return hs;
+ } catch (Exception e) {
+ return null;
+@@ -688,22 +542,7 @@
+ public Header getResponseHeader(String name)
+ {
+ try {
+- return this.method.getResponseHeader(name);
+- } catch (Exception e) {
+- return null;
+- }
+- }
+-
+- public Header getResponseHeaderdmh(String name)
+- {
+- try {
+-
+- Header[] headers = getResponseHeaders();
+- for(Header h : headers) {
+- if(h.getName().equals(name))
+- return h;
+- }
+- return null;
++ return this.response.getFirstHeader(name);
+ } catch (Exception e) {
+ return null;
+ }
+@@ -712,17 +551,7 @@
+ public Header[] getResponseHeaders()
+ {
+ try {
+- Header[] hs = this.method.getResponseHeaders();
+- return hs;
+- } catch (Exception e) {
+- return null;
+- }
+- }
+-
+- public Header[] getResponseFooters()
+- {
+- try {
+- Header[] hs = this.method.getResponseFooters();
++ Header[] hs = this.response.getAllHeaders();
+ return hs;
+ } catch (Exception e) {
+ return null;
+@@ -738,39 +567,40 @@
+ {
+ if(this.method == null)
+ return null;
+- return this.method.getParams().getParameter(key);
++ return method.getParams().getParameter(key);
+ }
+
+- public HttpMethodParams getMethodParameters()
++ public HttpParams getMethodParameters()
+ {
+- if(this.method == null)
++ if(method == null)
+ return null;
+- return this.method.getParams();
++ return method.getParams();
+ }
+
+ public Object getResponseParameter(String name)
+ {
+- if(this.method == null)
++ if(method == null)
+ return null;
+- return this.method.getParams().getParameter(name);
++ return method.getParams().getParameter(name);
+ }
+
+
+ public void setRequestContentAsString(String content) throws HTTPException
+ {
+ try {
+- this.content = new StringRequestEntity(content, "application/text", "UTF-8");
++ this.content = new StringEntity(content, "application/text", "UTF-8");
+ } catch (UnsupportedEncodingException ue) {
+ }
+ }
+
+- public void setMultipartRequest(Part[] parts) throws HTTPException
+- {
+- multiparts = new Part[parts.length];
+- for(int i = 0;i < parts.length;i++) {
+- multiparts[i] = parts[i];
+- }
+- }
++ //todo:
++ // public void setMultipartRequest(Part[] parts) throws HTTPException
++ //{
++ // multiparts = new Part[parts.length];
++ // for(int i = 0;i < parts.length;i++) {
++ // multiparts[i] = parts[i];
++ // }
++ //}
+
+ public String getCharSet()
+ {
+@@ -779,59 +609,45 @@
+
+ public String getName()
+ {
+- return this.method == null ? null : this.method.getName();
++ return method == null ? null : method.getMethod();
+ }
+
+ public String getURL()
+ {
+- return this.method == null ? null : this.method.getPath().toString();
++ return method == null ? null : method.getURI().toString();
+ }
+
+- public String getEffectiveVersion()
++ public String getProtocolVersion()
+ {
+ String ver = null;
+- if(this.method != null) {
+- ver = this.method.getEffectiveVersion().toString();
++ if(method != null) {
++ ver = method.getProtocolVersion().toString();
+ }
+ return ver;
+ }
+
+-
+- public String getProtocolVersion()
+- {
+- return getEffectiveVersion();
+- }
+-
+ public String getSoTimeout()
+ {
+- return this.method == null ? null : "" + this.method.getParams().getSoTimeout();
++ return method == null ? null : "" + method.getParams().getParameter(AllClientPNames.SO_TIMEOUT);
+ }
+
+- public String getVirtualHost()
+- {
+- return this.method == null ? null : this.method.getParams().getVirtualHost();
+- }
+-
+-/*public HeaderIterator headerIterator() {
+- return new BasicHeaderIterator(getResponseHeaders(), null);
+-}*/
+-
+ public String getStatusText()
+ {
+ return getStatusLine();
+ }
+
+- public static Enumeration getAllowedMethods()
++ public static Set<String> getAllowedMethods()
+ {
+- Enumeration e = new OptionsMethod().getAllowedMethods();
+- return e;
++ HttpResponse rs = new BasicHttpResponse(new ProtocolVersion("http",1,1),0,"");
++ Set<String> set = new HttpOptions().getAllowedMethods(rs);
++ return set;
+ }
+
+ // Convenience methods to minimize changes elsewhere
+
+ public void setFollowRedirects(boolean tf)
+ {
+- return; //ignore ; always done
++ //ignore ; always done
+ }
+
+ public String getResponseCharSet()
+@@ -852,15 +668,15 @@
+ return this.localsession;
+ }
+
+- public HttpMethodBase
++ public HttpRequest
+ getMethod()
+ {
+- return this.method;
++ return method;
+ }
+
+ public boolean hasStreamOpen()
+ {
+- return this.methodstream != null;
++ return methodstream != null;
+ }
+
+ public boolean isClosed()
+@@ -892,7 +708,7 @@
+ * We do not know, necessarily,
+ * which scheme(s) will be
+ * encountered, so most testing
+- * occurs in HTTPAuthCreds.
++ * occurs in HTTPAuthProvider
+ */
+
+ static synchronized private void
+@@ -903,13 +719,12 @@
+
+ // Provide a credentials (provider) to enact the process
+ CredentialsProvider cp = new HTTPAuthProvider(url, method);
+-
+ // Since we not know where this will get called, do everywhere
+- session.sessionClient.getParams().setParameter(CredentialsProvider.PROVIDER, cp);
+-
+- // Pass down info to the socket factory
+- HttpConnectionManagerParams hcp = session.sessionClient.getHttpConnectionManager().getParams();
+- hcp.setParameter(CredentialsProvider.PROVIDER, cp);
++ if(session != null && session.sessionClient != null) {
++ session.sessionClient.setCredentialsProvider(cp);
++ }
++ //HttpParams hcp = session.sessionClient.getConnectionManager().getParams();
++ //hcp.setParameter(CredentialsProvider.PROVIDER, cp);
+
+ }
+
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPSession.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPSession.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPSession.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPSession.java 2013-09-16 06:46:44.531379394 +0200
+@@ -34,13 +34,24 @@
+ 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 org.apache.http.*;
++import org.apache.http.auth.Credentials;
++import org.apache.http.client.CredentialsProvider;
++import org.apache.http.client.params.AllClientPNames;
++import org.apache.http.conn.params.ConnRoutePNames;
++import org.apache.http.conn.scheme.Scheme;
++import org.apache.http.cookie.Cookie;
++import org.apache.http.impl.client.AbstractHttpClient;
++import org.apache.http.impl.client.DefaultHttpClient;
++import org.apache.http.impl.conn.PoolingClientConnectionManager;
++import org.apache.http.params.*;
++import org.apache.http.protocol.ExecutionContext;
++import org.apache.http.protocol.HttpContext;
++
++import javax.net.ssl.SSLException;
++import java.io.IOException;
++import java.io.InterruptedIOException;
++import java.net.*;
+ import java.util.ArrayList;
+ import java.util.List;
+ import java.util.Vector;
+@@ -57,23 +68,23 @@
+ * A Session does, however, encapsulate an instance of an Apache HttpClient.
+ * <p/>
+ * It is possible to specify a url when invoking, for example,
+- * HTTPMethod.Get. This is because the url argument to the
++ * HTTPFactory.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);
++ * url, for example, HTTPMethod m = HTTPFactory.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
++ * given to HTTPFactory.Get was for something more specific such as
+ * http://motherlode.ucar.edu/path/file.nc.dds.
+ * <p/>
+ * 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
++ * prefix of the url given to HTTPFactory.Get. This maintains the
+ * semantics of the Session but allows flexibility in accessing data
+ * from the server.
+ * <p/>
+@@ -101,17 +112,17 @@
+ 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 SO_TIMEOUT = AllClientPNames.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;
++ static public String ALLOW_CIRCULAR_REDIRECTS = AllClientPNames.ALLOW_CIRCULAR_REDIRECTS;
++ static public String MAX_REDIRECTS = AllClientPNames.MAX_REDIRECTS;
++ static public String USER_AGENT = AllClientPNames.USER_AGENT;
++ static public String PROTOCOL_VERSION = AllClientPNames.PROTOCOL_VERSION;
++ static public String VIRTUAL_HOST = AllClientPNames.VIRTUAL_HOST;
++ static public String USE_EXPECT_CONTINUE = AllClientPNames.USE_EXPECT_CONTINUE;
++ static public String STRICT_TRANSFER_ENCODING = AllClientPNames.STRICT_TRANSFER_ENCODING;
++ static public String HTTP_ELEMENT_CHARSET = AllClientPNames.HTTP_ELEMENT_CHARSET;
++ static public String HTTP_CONTENT_CHARSET = AllClientPNames.HTTP_CONTENT_CHARSET;
+
+ /*fix:*/
+ static public String HTTP_CONNECTION = "<undefined>";
+@@ -131,8 +142,8 @@
+
+ static class Proxy
+ {
+- String host = null;
+- int port = -1;
++ public String host = null;
++ public int port = -1;
+ }
+
+ static enum Methods
+@@ -151,18 +162,62 @@
+ }
+ }
+
+- // We need more powerful protocol registry.
+- static class ProtocolEntry
+- {
+- public String protocol = null;
+- public int port = 0;
+- public Protocol handler;
++ // Define a Retry Handler that supports specifiable retries
++ // and is optionally verbose.
++ static public class RetryHandler
++ implements org.apache.http.client.HttpRequestRetryHandler
++ {
++ static final int DFALTRETRIES = 5;
++ static int retries = DFALTRETRIES;
++ static boolean verbose = false;
++
++ public RetryHandler()
++ {
++ }
++
++ public boolean
++ retryRequest(IOException exception,
++ int executionCount,
++ HttpContext context)
++ {
++ if(verbose) {
++ HTTPSession.log.debug(String.format("Retry: count=%d exception=%s\n", executionCount, exception.toString()));
++ }
++ if(executionCount >= retries)
++ return false;
++ if((exception instanceof InterruptedIOException) // Timeout
++ || (exception instanceof UnknownHostException)
++ || (exception instanceof ConnectException) // connection refused
++ || (exception instanceof SSLException)) // ssl handshake problem
++ return false;
++ HttpRequest request
++ = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
++ boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
++ if(idempotent) // Retry if the request is considered idempotent
++ return true;
++
++ return false;
++ }
+
+- public ProtocolEntry(String protocol, int port, Protocol handler)
++ static public synchronized int getRetries()
+ {
+- this.protocol = protocol;
+- this.port = port;
+- this.handler = handler;
++ return RetryHandler.retries;
++ }
++
++ static public synchronized void setRetries(int retries)
++ {
++ if(retries > 0)
++ RetryHandler.retries = retries;
++ }
++
++ static public synchronized boolean getVerbose()
++ {
++ return RetryHandler.verbose;
++ }
++
++ static public synchronized void setVerbose(boolean tf)
++ {
++ RetryHandler.verbose = tf;
+ }
+ }
+
+@@ -172,9 +227,7 @@
+ static public org.slf4j.Logger log
+ = org.slf4j.LoggerFactory.getLogger(HTTPSession.class);
+
+- static MultiThreadedHttpConnectionManager connmgr;
+-
+- //fix: protected static SchemeRegistry schemes;
++ static PoolingClientConnectionManager connmgr;
+
+ static String globalAgent = "/NetcdfJava/HttpClient3";
+ static int threadcount = DFALTTHREADCOUNT;
+@@ -182,23 +235,18 @@
+ static int globalSoTimeout = 0;
+ static int globalConnectionTimeout = 0;
+ static Proxy globalproxy = null;
+- static List<ProtocolEntry> registry;
++ static int localSoTimeout = 0;
++ static int localConnectionTimeout = 0;
+
+ static {
+- connmgr = new MultiThreadedHttpConnectionManager();
++ connmgr = new PoolingClientConnectionManager();
++ connmgr.getSchemeRegistry().register(
++ new Scheme("https", 8443,
++ new EasySSLProtocolSocketFactory()));
++ connmgr.getSchemeRegistry().register(
++ new Scheme("https", 443,
++ new EasySSLProtocolSocketFactory()));
+ setGlobalThreadCount(DFALTTHREADCOUNT);
+- registry = new ArrayList<ProtocolEntry>();
+- // 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
+@@ -220,8 +268,8 @@
+
+ static public void setGlobalThreadCount(int nthreads)
+ {
+- connmgr.getParams().setMaxTotalConnections(nthreads);
+- connmgr.getParams().setDefaultMaxConnectionsPerHost(nthreads);
++ connmgr.setMaxTotal(nthreads);
++ connmgr.setDefaultMaxPerRoute(nthreads);
+ }
+
+ // Alias
+@@ -232,86 +280,22 @@
+
+ static public int getGlobalThreadCount()
+ {
+- return connmgr.getParams().getMaxTotalConnections();
++ return connmgr.getMaxTotal();
+ }
+
+
+- static public Cookie[] getGlobalCookies()
++ static public List<Cookie> getGlobalCookies()
+ {
+- HttpClient client = new HttpClient(connmgr);
+- Cookie[] cookies = client.getState().getCookies();
++ AbstractHttpClient client = new DefaultHttpClient(connmgr);
++ List<Cookie> cookies = client.getCookieStore().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);
+-
++ if(timeout >= 0) globalConnectionTimeout = timeout;
+ }
+
+ static public void setGlobalSoTimeout(int timeout)
+@@ -400,6 +384,19 @@
+ defineCredentialsProvider(scheme, HTTPAuthStore.ANY_URL, provider);
+ }
+
++ static public int
++ getRetryCount()
++ {
++ return RetryHandler.getRetries();
++ }
++
++ static public void
++ setRetryCount(int count)
++ {
++ RetryHandler.setRetries(count);
++ }
++
++
+ // Static Utilitiy functions
+
+ static String
+@@ -473,8 +470,8 @@
+ static public String
+ getUrlAsString(String url) throws HTTPException
+ {
+- HTTPSession session = new HTTPSession(url);
+- HTTPMethod m = HTTPMethod.Get(session);
++ HTTPSession session = HTTPFactory.newSession(url);
++ HTTPMethod m = HTTPFactory.Get(session);
+ int status = m.execute();
+ String content = null;
+ if(status == 200) {
+@@ -487,8 +484,8 @@
+ static public int
+ putUrlAsString(String content, String url) throws HTTPException
+ {
+- HTTPSession session = new HTTPSession(url);
+- HTTPMethod m = HTTPMethod.Put(session);
++ HTTPSession session = HTTPFactory.newSession(url);
++ HTTPMethod m = HTTPFactory.Put(session);
+ m.setRequestContentAsString(content);
+ int status = m.execute();
+ m.close();
+@@ -584,9 +581,9 @@
+ //////////////////////////////////////////////////
+ // Instance variables
+
+- HttpClient sessionClient = null;
++ AbstractHttpClient sessionClient = null;
+ List<ucar.nc2.util.net.HTTPMethod> methodList = new Vector<HTTPMethod>();
+- HttpState context = null;
++ HttpContext context = null;
+ String identifier = "Session";
+ String useragent = null;
+ String legalurl = null;
+@@ -612,21 +609,21 @@
+ {
+ this.legalurl = legalurl;
+ try {
+- sessionClient = new HttpClient(connmgr);
+- HttpClientParams clientparams = sessionClient.getParams();
++ sessionClient = new DefaultHttpClient(connmgr);
++ HttpParams clientparams = sessionClient.getParams();
+
+ // Allow (circular) redirects
+ clientparams.setParameter(ALLOW_CIRCULAR_REDIRECTS, true);
+ clientparams.setParameter(MAX_REDIRECTS, 25);
+
+ if(globalSoTimeout > 0)
+- setSoTimeout(globalSoTimeout);
++ clientparams.setParameter(AllClientPNames.SO_TIMEOUT, globalSoTimeout);
+
+ if(globalConnectionTimeout > 0)
+- setConnectionTimeout(globalConnectionTimeout);
++ clientparams.setParameter(AllClientPNames.CONN_MANAGER_TIMEOUT, (long) globalConnectionTimeout);
+
+ if(globalAgent != null)
+- setUserAgent(globalAgent); // May get overridden by setUserAgent
++ clientparams.setParameter(AllClientPNames.USER_AGENT, globalAgent);
+
+ setAuthenticationPreemptive(globalauthpreemptive);
+
+@@ -653,23 +650,21 @@
+
+ public void setAuthenticationPreemptive(boolean tf)
+ {
+- if(sessionClient != null)
+- sessionClient.getParams().setAuthenticationPreemptive(tf);
++ //fix if(sessionClient != null)
++ //sessionClient.getParams().setAuthenticationPreemptive(tf);
+ }
+
+ public void setSoTimeout(int timeout)
+ {
+- sessionClient.getParams().setSoTimeout(timeout);
++ if(timeout >= 0) localSoTimeout = timeout;
+ }
+
+ public void setConnectionTimeout(int timeout)
+ {
+- sessionClient.setConnectionTimeout(timeout);
++ if(timeout >= 0) localConnectionTimeout = timeout;
+ }
+
+
+- //fix: public void setStateX(HttpState cxt) {sessionState = cxt;}
+-
+ /**
+ * Close the session. This implies closing
+ * any open methods.
+@@ -677,25 +672,26 @@
+
+ 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;
++ 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();
++ return sessionClient == null ? null
++ : (String) sessionClient.getParams().getParameter(AllClientPNames.COOKIE_POLICY);
+ }
+
+- public Cookie[] getCookies()
++ public List<Cookie> getCookies()
+ {
+ if(sessionClient == null)
+ return null;
+- Cookie[] cookies = sessionClient.getState().getCookies();
++ List<Cookie> cookies = sessionClient.getCookieStore().getCookies();
+ return cookies;
+ }
+
+@@ -712,16 +708,16 @@
+
+ public void setMaxRedirects(int n)
+ {
+- HttpClientParams clientparams = sessionClient.getParams();
++ HttpParams clientparams = sessionClient.getParams();
+ clientparams.setParameter(MAX_REDIRECTS, n);
+ }
+
+- public void setContext(HttpState cxt)
++ public void setContext(HttpContext cxt)
+ {
+ context = cxt;
+ }
+
+- public HttpState getContext()
++ public HttpContext getContext()
+ {
+ return context;
+ }
+@@ -729,8 +725,8 @@
+
+ public void clearState()
+ {
+- sessionClient.getState().clearCookies();
+- sessionClient.getState().clearCredentials();
++ sessionClient.getCredentialsProvider().clear();
++ sessionClient.getCookieStore().clear();
+ }
+
+
+@@ -742,8 +738,10 @@
+ setProxy(Proxy proxy)
+ {
+ if(sessionClient == null) return;
+- if(proxy != null && proxy.host != null)
+- sessionClient.getHostConfiguration().setProxy(proxy.host, proxy.port);
++ if(proxy != null && proxy.host != null) {
++ HttpHost httpproxy = new HttpHost(proxy.host, proxy.port);
++ sessionClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, httpproxy);
++ }
+ }
+
+ void
+@@ -840,7 +838,7 @@
+ sessionList.clear();
+ // Rebuild the connection manager
+ connmgr.shutdown();
+- connmgr = new MultiThreadedHttpConnectionManager();
++ connmgr = new PoolingClientConnectionManager();
+ setGlobalThreadCount(DFALTTHREADCOUNT);
+ }
+ }
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPSSLProvider.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPSSLProvider.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPSSLProvider.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPSSLProvider.java 2013-09-16 07:06:34.183900791 +0200
+@@ -1,116 +1,136 @@
+-/*
+- * 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 org.apache.commons.httpclient.Credentials;
+-import org.apache.commons.httpclient.auth.AuthScheme;
+-import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
+-import org.apache.commons.httpclient.auth.CredentialsProvider;
+-
+-import java.io.IOException;
+-import java.io.Serializable;
+-
+-/**
+- * Provide an HTTP SSL CredentialsProvider
+- * The getCredentials method is used in a
+- * non-standard way
+- */
+-
+-public class HTTPSSLProvider implements CredentialsProvider, Credentials, Serializable
+-{
+- String keystore = null;
+- String keypass = null;
+- String truststore = null;
+- String trustpass = null;
+-
+- public HTTPSSLProvider()
+- {
+- this(null,"",null,"");
+- }
+-
+- public HTTPSSLProvider(String keystore,String keypass,
+- String truststore,String trustpass)
+- {
+- this.keystore = keystore;
+- this.keypass = keypass;
+- this.truststore = truststore;
+- this.trustpass = trustpass;
+- }
+-
+- public HTTPSSLProvider(String keystore, String keypass)
+- {
+- this(keystore,keypass,null,null);
+- }
+-
+- // Provide accessors
+- public String getKeystore() {return keystore;}
+- public String getKeypassword() {return keypass;}
+- public String getTruststore() {return truststore;}
+- public String getTrustpassword() {return trustpass;}
+-
+- // Credentials Provider Interface is abused
+-
+- public Credentials
+- getCredentials(AuthScheme authscheme,
+- String host,
+- int port,
+- boolean isproxy)
+- throws CredentialsNotAvailableException
+- {
+- return (Credentials) this;
+- }
+-
+-
+- // Serializable Interface
+- private void writeObject(java.io.ObjectOutputStream oos)
+- throws IOException
+- {
+- oos.writeObject(this.keystore);
+- oos.writeObject(this.keypass);
+- oos.writeObject(this.truststore);
+- oos.writeObject(this.trustpass);
+- }
+-
+- private void readObject(java.io.ObjectInputStream ois)
+- throws IOException, ClassNotFoundException
+- {
+- this.keystore = (String)ois.readObject();
+- this.keypass = (String)ois.readObject();
+- this.truststore = (String)ois.readObject();
+- this.trustpass = (String)ois.readObject();
+- }
+-
+-
+-
+-}
++/*
++ * 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 org.apache.http.auth.*;
++import org.apache.http.client.CredentialsProvider;
++
++import java.io.IOException;
++import java.io.Serializable;
++import java.security.Principal;
++
++/**
++ * Provide an HTTP SSL CredentialsProvider
++ * The getCredentials method is used in a
++ * non-standard way
++ */
++
++public class HTTPSSLProvider implements CredentialsProvider, Credentials, Serializable
++{
++ String keystore = null;
++ String keypass = null;
++ String truststore = null;
++ String trustpass = null;
++
++ public HTTPSSLProvider()
++ {
++ this(null,"",null,"");
++ }
++
++ public HTTPSSLProvider(String keystore,String keypass,
++ String truststore,String trustpass)
++ {
++ this.keystore = keystore;
++ this.keypass = keypass;
++ this.truststore = truststore;
++ this.trustpass = trustpass;
++ }
++
++ public HTTPSSLProvider(String keystore, String keypass)
++ {
++ this(keystore,keypass,null,null);
++ }
++
++ // Provide accessors
++ public String getKeystore() {return keystore;}
++ public String getKeypassword() {return keypass;}
++ public String getTruststore() {return truststore;}
++ public String getTrustpassword() {return trustpass;}
++
++ // Credentials Provider Interface is abused
++
++ public Credentials
++ getCredentials(AuthScope scope) //AuthScheme authscheme,String host,int port,boolean isproxy)
++ {
++ return (Credentials) this;
++ }
++
++ public void
++ setCredentials(AuthScope scope, Credentials creds)
++ {
++
++ }
++
++ public void
++ clear()
++ {
++
++ }
++
++ // Credentials Interface
++ public Principal
++ getUserPrincipal()
++ {
++ return null;
++ }
++
++ public String
++ getPassword()
++ {
++ return null;
++ }
++
++
++ // Serializable Interface
++ private void writeObject(java.io.ObjectOutputStream oos)
++ throws IOException
++ {
++ oos.writeObject(this.keystore);
++ oos.writeObject(this.keypass);
++ oos.writeObject(this.truststore);
++ oos.writeObject(this.trustpass);
++ }
++
++ private void readObject(java.io.ObjectInputStream ois)
++ throws IOException, ClassNotFoundException
++ {
++ this.keystore = (String)ois.readObject();
++ this.keypass = (String)ois.readObject();
++ this.truststore = (String)ois.readObject();
++ this.trustpass = (String)ois.readObject();
++ }
++
++
++
++}
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPSSLScheme.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPSSLScheme.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/net/HTTPSSLScheme.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/net/HTTPSSLScheme.java 2013-09-16 07:09:21.105137441 +0200
+@@ -1,112 +1,94 @@
+-/*
+- * 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 org.apache.commons.httpclient.Credentials;
+-import org.apache.commons.httpclient.HttpMethod;
+-import org.apache.commons.httpclient.auth.AuthScheme;
+-import org.apache.commons.httpclient.auth.AuthScope;
+-import org.apache.commons.httpclient.auth.AuthenticationException;
+-import org.apache.commons.httpclient.auth.MalformedChallengeException;
+-
+-public class HTTPSSLScheme implements AuthScheme
+-{
+-
+-static public final HTTPSSLScheme Default = new HTTPSSLScheme();
+-
+-public
+-HTTPSSLScheme()
+-{
+-}
+-
+-public String
+-getSchemeName()
+-{
+- return "SSL";
+-}
+-
+-
+-public void
+-processChallenge(String url)
+- throws MalformedChallengeException
+-{
+-}
+-
+-public String
+-getParameter(String key)
+-{
+- return null;
+-}
+-
+-public String
+-getRealm()
+-{
+- return AuthScope.ANY_REALM;
+-}
+-
+- at Deprecated
+-public String
+-getID()
+-{
+- return null;
+-}
+-
+-public boolean
+-isConnectionBased()
+-{
+- return false;
+-}
+-
+-public boolean
+-isComplete()
+-{
+- return true;
+-}
+-
+- at Deprecated
+-public String
+-authenticate(Credentials credentials, String url, String url1)
+- throws AuthenticationException
+-{
+- return null;
+-}
+-
+-public String
+-authenticate(Credentials credentials, HttpMethod httpMethod)
+- throws AuthenticationException
+-{
+- return null;
+-}
+-
+-}
++/*
++ * 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 org.apache.http.Header;
++import org.apache.http.HttpRequest;
++import org.apache.http.auth.*;
++
++public class HTTPSSLScheme implements AuthScheme
++{
++
++static public final HTTPSSLScheme Default = new HTTPSSLScheme();
++
++public
++HTTPSSLScheme()
++{
++}
++
++public String
++getSchemeName()
++{
++ return "SSL";
++}
++
++public void
++processChallenge(Header header)
++ throws MalformedChallengeException
++{
++}
++
++public String
++getParameter(String key)
++{
++ return null;
++}
++
++public String
++getRealm()
++{
++ return AuthScope.ANY_REALM;
++}
++
++public boolean
++isConnectionBased()
++{
++ return false;
++}
++
++public boolean
++isComplete()
++{
++ return true;
++}
++
++ at Deprecated
++public Header
++authenticate(Credentials credentials, HttpRequest request)
++ throws AuthenticationException
++{
++ return null;
++}
++
++}
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/URLnaming.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/URLnaming.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/URLnaming.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/URLnaming.java 2013-09-16 06:52:51.175110116 +0200
+@@ -1,361 +1,359 @@
+-/*
+- * 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;
+-
+-import ucar.nc2.util.EscapeStrings;
+-import org.apache.commons.httpclient.URIException;
+-import org.apache.commons.httpclient.util.URIUtil;
+-
+-import java.io.UnsupportedEncodingException;
+-import java.net.*;
+-import java.io.File;
+-
+-/**
+- * Networking utilities.
+- *
+- * @author caron
+- */
+-public class URLnaming {
+-
+- @Deprecated
+- public static String escapeQuery(String urlString) {
+- urlString = urlString.trim();
+- String[] split = urlString.split("[?]");
+- return (split[0] == null ? "" : split[0])
+- + (split[1] == null ? "" : '?' + EscapeStrings.escapeURLQuery(split[1]));
+- }
+-
+- @Deprecated
+- private static String escapeQueryNew(String urlString) {
+- urlString = urlString.trim();
+- URI uri = null;
+- try {
+- uri = new URI(urlString);
+- return uri.toASCIIString();
+- } catch (URISyntaxException e) {
+- e.printStackTrace();
+- return "";
+- }
+- }
+-
+- @Deprecated
+- private static String escapeQueryURIUtil(String urlString) {
+- urlString = urlString.trim();
+- int posQ = urlString.indexOf("?");
+- if ((posQ > 0) && (posQ < urlString.length() - 2)) {
+- String query = urlString.substring(posQ + 1);
+- if (query.indexOf("%") < 0) { // assume that its not already encoded...
+- String path = urlString.substring(0, posQ);
+- try {
+- urlString = path + "?" + URIUtil.encodeQuery(query);
+- } catch (URIException e) {
+- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+- }
+- }
+- }
+- return urlString;
+- }
+-
+- @Deprecated
+- private static String escapeQueryEncoder(String urlString) {
+- urlString = urlString.trim();
+- int posQ = urlString.indexOf("?");
+- if ((posQ > 0) && (posQ < urlString.length() - 2)) {
+- String query = urlString.substring(posQ + 1);
+- if (!query.contains("%")) { // skip if already encoded
+- String path = urlString.substring(0, posQ);
+- try {
+- urlString = path + "?" + URLEncoder.encode(query, "UTF-8");
+- } catch (UnsupportedEncodingException e) {
+- e.printStackTrace();
+- }
+- }
+- }
+- return urlString;
+- }
+-
+- @Deprecated
+- private static String unescapeQueryDODS(String urlString) {
+- urlString = urlString.trim();
+- int posQ = urlString.indexOf("?");
+- if ((posQ >= 0) && (posQ < urlString.length() - 2)) {
+- String path = urlString.substring(0, posQ);
+- String query = urlString.substring(posQ + 1);
+- return path + "?" + EscapeStrings.unescapeURLQuery(query);
+- }
+- return urlString;
+- }
+-
+-
+- @Deprecated
+- private static String unescapeQueryDecoder(String urlString) {
+-
+- urlString = urlString.trim();
+- int posQ = urlString.indexOf("?");
+- if ((posQ >= 0) && (posQ < urlString.length() - 2)) {
+- String path = urlString.substring(0, posQ);
+- String query = urlString.substring(posQ + 1);
+- try {
+- return path + "?" + URLDecoder.decode(query, "UTF-8");
+- } catch (UnsupportedEncodingException e) {
+- e.printStackTrace();
+- }
+- }
+- return urlString;
+- }
+-
+-
+- /// try to figure out if we need to add file: to the location when writing
+- static public String canonicalizeWrite(String location) {
+- try {
+- URI refURI = URI.create(location);
+- if (refURI.isAbsolute())
+- return location;
+- } catch (Exception e) {
+- //return "file:" + location;
+- }
+- return "file:" + location;
+- }
+-
+- /**
+- * This augments URI.resolve(), by also dealing with file: URIs.
+- * If baseURi is not a file: scheme, then URI.resolve is called.
+- * Otherwise the last "/" is found in the base, and the ref is appended to it.
+- * <p> For file: baseURLS: only reletive URLS not starting with / are supported. This is
+- * apparently different from the behavior of URI.resolve(), so may be trouble,
+- * but it allows NcML absolute location to be specified without the file: prefix.
+- * <p/>
+- * Example : <pre>
+- * base: file://my/guide/collections/designfaq.ncml
+- * ref: sub/my.nc
+- * resolved: file://my/guide/collections/sub/my.nc
+- * </pre>
+- *
+- * @param baseUri base URI as a Strng
+- * @param relativeUri reletive URI, as a String
+- * @return the resolved URI as a String
+- */
+- public static String resolve(String baseUri, String relativeUri) {
+- if ((baseUri == null) || (relativeUri == null))
+- return relativeUri;
+-
+- if (relativeUri.startsWith("file:"))
+- return relativeUri;
+-
+- // deal with a base file URL
+- if (baseUri.startsWith("file:")) {
+-
+- // the case where the reletiveURL is absolute.
+- // unfortunately, we may get an Exception
+- try {
+- URI uriRelative = URI.create(relativeUri);
+- if (uriRelative.isAbsolute())
+- return relativeUri;
+- } catch (Exception e) {
+- // empty
+- }
+-
+- if ((relativeUri.length() > 0) && (relativeUri.charAt(0) == '#'))
+- return baseUri + relativeUri;
+-
+- if ((relativeUri.length() > 0) && (relativeUri.charAt(0) == '/'))
+- return relativeUri;
+-
+- int pos = baseUri.lastIndexOf('/');
+- if (pos > 0) {
+- return baseUri.substring(0, pos + 1) + relativeUri;
+- }
+- }
+-
+- // non-file URLs
+-
+- //relativeUri = canonicalizeRead(relativeUri);
+- try {
+- URI reletiveURI = URI.create(relativeUri);
+- if (reletiveURI.isAbsolute())
+- return relativeUri;
+-
+- //otherwise let the URI class resolve it
+- URI baseURI = URI.create(baseUri);
+- URI resolvedURI = baseURI.resolve(reletiveURI);
+- return resolvedURI.toASCIIString();
+-
+- } catch (IllegalArgumentException e) {
+- return relativeUri;
+- }
+- }
+-
+- /// try to figure out if we need to add file: to the location when reading
+- static public String canonicalizeRead(String location) {
+- try {
+- URI refURI = URI.create(location);
+- if (refURI.isAbsolute())
+- return location;
+- } catch (Exception e) {
+- return "file:" + location;
+- }
+- return location;
+- }
+-
+-
+- public static String resolveFile(String baseDir, String filepath) {
+- if (baseDir == null) return filepath;
+- if (filepath == null) return filepath;
+- File file = new File(filepath);
+- if (file.isAbsolute()) return filepath;
+-
+- if (baseDir.startsWith("file:"))
+- baseDir = baseDir.substring(5);
+-
+- File base = new File(baseDir);
+- if (!base.isDirectory())
+- base = base.getParentFile();
+- if (base == null) return filepath;
+- return base.getAbsolutePath() + "/" + filepath;
+- }
+-
+- ///////////////////////////////////////////////////////////////////
+-
+- /* private static void initProtocolHandler() {
+- // test setting the http protocol handler
+- try {
+- new java.net.URL(null, "http://motherlode.ucar.edu:8080/", new sun.net.www.protocol.http.Handler());
+- } catch (java.net.MalformedURLException e) {
+- e.printStackTrace();
+- }
+-
+- } */
+-
+- private static void test(String uriS) {
+- System.out.println(uriS);
+- //uriS = URLEncoder.encode(uriS, "UTF-8");
+- //System.out.println(uriS);
+-
+- URI uri = URI.create(uriS);
+- System.out.println(" scheme=" + uri.getScheme());
+- System.out.println(" getSchemeSpecificPart=" + uri.getSchemeSpecificPart());
+- System.out.println(" getAuthority=" + uri.getAuthority());
+- System.out.println(" getPath=" + uri.getPath());
+- System.out.println(" getQuery=" + uri.getQuery());
+- System.out.println();
+- }
+-
+- public static void main1(String args[]) {
+- testResolve("file:/test/me/", "blank in dir", "file:/test/me/blank in dir");
+- }
+-
+- public static void main2(String args[]) {
+- test("file:test/dir");
+- test("file:/test/dir");
+- test("file://test/dir");
+- test("file:///test/dir");
+-
+- test("file:C:/Program Files (x86)/Apache Software Foundation/Tomcat 5.0/content/thredds/cache");
+- test("file:C:\\Program Files (x86)\\Apache Software Foundation\\Tomcat 5.0\\content\\thredds\\cache");
+- test("http://localhost:8080/thredds/catalog.html?hi=lo");
+- }
+-
+- private static void testResolve(String base, String rel, String result) {
+- System.out.println("\nbase= " + base);
+- System.out.println("rel= " + rel);
+- System.out.println("resolve= " + resolve(base, rel));
+- if (result != null)
+- assert resolve(base, rel).equals(result);
+- }
+-
+- public static void main3(String args[]) {
+- testResolve("http://test/me/", "wanna", "http://test/me/wanna");
+- testResolve("http://test/me/", "/wanna", "http://test/wanna");
+- testResolve("file:/test/me/", "wanna", "file:/test/me/wanna");
+- testResolve("file:/test/me/", "/wanna", "/wanna"); // LOOK doesnt work for URI.resolve() directly.
+-
+- testResolve("file://test/me/", "http:/wanna", "http:/wanna");
+- testResolve("file://test/me/", "file:/wanna", "file:/wanna");
+- testResolve("file://test/me/", "C:/wanna", "C:/wanna");
+- testResolve("http://test/me/", "file:wanna", "file:wanna");
+- }
+-
+-
+- public static void main4(String args[]) {
+- try {
+- URL url = new URL("file:src/test/data/ncml/nc/");
+- URI uri = new URI("file:src/test/data/ncml/nc/");
+- File f = new File(uri);
+- } catch (Exception e) {
+- e.printStackTrace();
+- }
+- }
+-
+- public static void main5(String args[]) throws URISyntaxException {
+- String uriString = "http://motherlode.ucar.edu:8081/dts/test.53.dods?types[0:1:9]";
+- URI uri = new URI(uriString);
+- }
+-
+- private static void checkEsc(String s) {
+- System.out.printf("org = %s%n", s);
+- System.out.printf("escapeQuery = %s%n", escapeQuery(s));
+- System.out.printf("escapeQueryNew = %s%n", escapeQueryNew(s));
+- System.out.printf("escQueryURIUtil= %s%n", escapeQueryURIUtil(s));
+- System.out.printf("escQueryEncoder= %s%n", escapeQueryEncoder(s));
+- System.out.printf("unescQueryDODS = %s%n", unescapeQueryDODS(escapeQuery(s)));
+- System.out.printf("%n");
+- }
+-
+- private static void checkUnEsc(String esc) {
+- System.out.printf("esc = %s%n", esc);
+- System.out.printf("unescQueryDODS = %s%n", unescapeQueryDODS(esc));
+- System.out.printf("unescapeDecoder = %s%n", unescapeQueryDecoder(esc));
+- System.out.printf("escapeQuery = %s%n", escapeQuery(unescapeQueryDODS(esc)));
+- System.out.printf("%n");
+- }
+-
+- private static void decode(String esc) {
+- System.out.printf("esc = %s%n", esc);
+- System.out.printf("URLDecoder.decode = %s%n", URLDecoder.decode(esc));
+- System.out.printf("%n");
+- }
+-
+-
+-
+- public static void main(String args[]) throws URISyntaxException {
+- if (args.length > 0) {
+- checkUnEsc(args[0]);
+- } else {
+- String s = "/thredds/dodsC/grib/NCEP/NAM/CONUS_12km/best.dods?Relative_humidity_pressure%5b0:1:0%5d%5b0:1:24%5d%5b0:10:420%5d%5b0:10:610%5d";
+- decode(s);
+- }
+-
+- }
+-
+-
++/*
++ * 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;
++
++
++import javax.print.URIException;
++import java.io.UnsupportedEncodingException;
++import java.net.*;
++import java.io.File;
++
++/**
++ * Networking utilities.
++ *
++ * @author caron
++ */
++public class URLnaming {
++
++ @Deprecated
++ public static String escapeQuery(String urlString) {
++ urlString = urlString.trim();
++ String[] split = urlString.split("[?]");
++ return (split[0] == null ? "" : split[0])
++ + (split[1] == null ? "" : '?' + EscapeStrings.escapeURLQuery(split[1]));
++ }
++
++ @Deprecated
++ private static String escapeQueryNew(String urlString) {
++ urlString = urlString.trim();
++ URI uri = null;
++ try {
++ uri = new URI(urlString);
++ return uri.toASCIIString();
++ } catch (URISyntaxException e) {
++ e.printStackTrace();
++ return "";
++ }
++ }
++
++ @Deprecated
++ private static String escapeQueryURIUtil(String urlString) {
++ urlString = urlString.trim();
++ int posQ = urlString.indexOf("?");
++ if ((posQ > 0) && (posQ < urlString.length() - 2)) {
++ String query = urlString.substring(posQ + 1);
++ if (query.indexOf("%") < 0) { // assume that its not already encoded...
++ String path = urlString.substring(0, posQ);
++ try {
++ urlString = path + "?" + URLEncoder.encode(query,"UTF-8");
++ } catch (UnsupportedEncodingException e) {
++ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
++ }
++ }
++ }
++ return urlString;
++ }
++
++ @Deprecated
++ private static String escapeQueryEncoder(String urlString) {
++ urlString = urlString.trim();
++ int posQ = urlString.indexOf("?");
++ if ((posQ > 0) && (posQ < urlString.length() - 2)) {
++ String query = urlString.substring(posQ + 1);
++ if (!query.contains("%")) { // skip if already encoded
++ String path = urlString.substring(0, posQ);
++ try {
++ urlString = path + "?" + URLEncoder.encode(query, "UTF-8");
++ } catch (UnsupportedEncodingException e) {
++ e.printStackTrace();
++ }
++ }
++ }
++ return urlString;
++ }
++
++ @Deprecated
++ private static String unescapeQueryDODS(String urlString) {
++ urlString = urlString.trim();
++ int posQ = urlString.indexOf("?");
++ if ((posQ >= 0) && (posQ < urlString.length() - 2)) {
++ String path = urlString.substring(0, posQ);
++ String query = urlString.substring(posQ + 1);
++ return path + "?" + EscapeStrings.unescapeURLQuery(query);
++ }
++ return urlString;
++ }
++
++
++ @Deprecated
++ private static String unescapeQueryDecoder(String urlString) {
++
++ urlString = urlString.trim();
++ int posQ = urlString.indexOf("?");
++ if ((posQ >= 0) && (posQ < urlString.length() - 2)) {
++ String path = urlString.substring(0, posQ);
++ String query = urlString.substring(posQ + 1);
++ try {
++ return path + "?" + URLDecoder.decode(query, "UTF-8");
++ } catch (UnsupportedEncodingException e) {
++ e.printStackTrace();
++ }
++ }
++ return urlString;
++ }
++
++
++ /// try to figure out if we need to add file: to the location when writing
++ static public String canonicalizeWrite(String location) {
++ try {
++ URI refURI = URI.create(location);
++ if (refURI.isAbsolute())
++ return location;
++ } catch (Exception e) {
++ //return "file:" + location;
++ }
++ return "file:" + location;
++ }
++
++ /**
++ * This augments URI.resolve(), by also dealing with file: URIs.
++ * If baseURi is not a file: scheme, then URI.resolve is called.
++ * Otherwise the last "/" is found in the base, and the ref is appended to it.
++ * <p> For file: baseURLS: only reletive URLS not starting with / are supported. This is
++ * apparently different from the behavior of URI.resolve(), so may be trouble,
++ * but it allows NcML absolute location to be specified without the file: prefix.
++ * <p/>
++ * Example : <pre>
++ * base: file://my/guide/collections/designfaq.ncml
++ * ref: sub/my.nc
++ * resolved: file://my/guide/collections/sub/my.nc
++ * </pre>
++ *
++ * @param baseUri base URI as a Strng
++ * @param relativeUri reletive URI, as a String
++ * @return the resolved URI as a String
++ */
++ public static String resolve(String baseUri, String relativeUri) {
++ if ((baseUri == null) || (relativeUri == null))
++ return relativeUri;
++
++ if (relativeUri.startsWith("file:"))
++ return relativeUri;
++
++ // deal with a base file URL
++ if (baseUri.startsWith("file:")) {
++
++ // the case where the reletiveURL is absolute.
++ // unfortunately, we may get an Exception
++ try {
++ URI uriRelative = URI.create(relativeUri);
++ if (uriRelative.isAbsolute())
++ return relativeUri;
++ } catch (Exception e) {
++ // empty
++ }
++
++ if ((relativeUri.length() > 0) && (relativeUri.charAt(0) == '#'))
++ return baseUri + relativeUri;
++
++ if ((relativeUri.length() > 0) && (relativeUri.charAt(0) == '/'))
++ return relativeUri;
++
++ int pos = baseUri.lastIndexOf('/');
++ if (pos > 0) {
++ return baseUri.substring(0, pos + 1) + relativeUri;
++ }
++ }
++
++ // non-file URLs
++
++ //relativeUri = canonicalizeRead(relativeUri);
++ try {
++ URI reletiveURI = URI.create(relativeUri);
++ if (reletiveURI.isAbsolute())
++ return relativeUri;
++
++ //otherwise let the URI class resolve it
++ URI baseURI = URI.create(baseUri);
++ URI resolvedURI = baseURI.resolve(reletiveURI);
++ return resolvedURI.toASCIIString();
++
++ } catch (IllegalArgumentException e) {
++ return relativeUri;
++ }
++ }
++
++ /// try to figure out if we need to add file: to the location when reading
++ static public String canonicalizeRead(String location) {
++ try {
++ URI refURI = URI.create(location);
++ if (refURI.isAbsolute())
++ return location;
++ } catch (Exception e) {
++ return "file:" + location;
++ }
++ return location;
++ }
++
++
++ public static String resolveFile(String baseDir, String filepath) {
++ if (baseDir == null) return filepath;
++ if (filepath == null) return filepath;
++ File file = new File(filepath);
++ if (file.isAbsolute()) return filepath;
++
++ if (baseDir.startsWith("file:"))
++ baseDir = baseDir.substring(5);
++
++ File base = new File(baseDir);
++ if (!base.isDirectory())
++ base = base.getParentFile();
++ if (base == null) return filepath;
++ return base.getAbsolutePath() + "/" + filepath;
++ }
++
++ ///////////////////////////////////////////////////////////////////
++
++ /* private static void initProtocolHandler() {
++ // test setting the http protocol handler
++ try {
++ new java.net.URL(null, "http://motherlode.ucar.edu:8080/", new sun.net.www.protocol.http.Handler());
++ } catch (java.net.MalformedURLException e) {
++ e.printStackTrace();
++ }
++
++ } */
++
++ private static void test(String uriS) {
++ System.out.println(uriS);
++ //uriS = URLEncoder.encode(uriS, "UTF-8");
++ //System.out.println(uriS);
++
++ URI uri = URI.create(uriS);
++ System.out.println(" scheme=" + uri.getScheme());
++ System.out.println(" getSchemeSpecificPart=" + uri.getSchemeSpecificPart());
++ System.out.println(" getAuthority=" + uri.getAuthority());
++ System.out.println(" getPath=" + uri.getPath());
++ System.out.println(" getQuery=" + uri.getQuery());
++ System.out.println();
++ }
++
++ public static void main1(String args[]) {
++ testResolve("file:/test/me/", "blank in dir", "file:/test/me/blank in dir");
++ }
++
++ public static void main2(String args[]) {
++ test("file:test/dir");
++ test("file:/test/dir");
++ test("file://test/dir");
++ test("file:///test/dir");
++
++ test("file:C:/Program Files (x86)/Apache Software Foundation/Tomcat 5.0/content/thredds/cache");
++ test("file:C:\\Program Files (x86)\\Apache Software Foundation\\Tomcat 5.0\\content\\thredds\\cache");
++ test("http://localhost:8080/thredds/catalog.html?hi=lo");
++ }
++
++ private static void testResolve(String base, String rel, String result) {
++ System.out.println("\nbase= " + base);
++ System.out.println("rel= " + rel);
++ System.out.println("resolve= " + resolve(base, rel));
++ if (result != null)
++ assert resolve(base, rel).equals(result);
++ }
++
++ public static void main3(String args[]) {
++ testResolve("http://test/me/", "wanna", "http://test/me/wanna");
++ testResolve("http://test/me/", "/wanna", "http://test/wanna");
++ testResolve("file:/test/me/", "wanna", "file:/test/me/wanna");
++ testResolve("file:/test/me/", "/wanna", "/wanna"); // LOOK doesnt work for URI.resolve() directly.
++
++ testResolve("file://test/me/", "http:/wanna", "http:/wanna");
++ testResolve("file://test/me/", "file:/wanna", "file:/wanna");
++ testResolve("file://test/me/", "C:/wanna", "C:/wanna");
++ testResolve("http://test/me/", "file:wanna", "file:wanna");
++ }
++
++
++ public static void main4(String args[]) {
++ try {
++ URL url = new URL("file:src/test/data/ncml/nc/");
++ URI uri = new URI("file:src/test/data/ncml/nc/");
++ File f = new File(uri);
++ } catch (Exception e) {
++ e.printStackTrace();
++ }
++ }
++
++ public static void main5(String args[]) throws URISyntaxException {
++ String uriString = "http://motherlode.ucar.edu:8081/dts/test.53.dods?types[0:1:9]";
++ URI uri = new URI(uriString);
++ }
++
++ private static void checkEsc(String s) {
++ System.out.printf("org = %s%n", s);
++ System.out.printf("escapeQuery = %s%n", escapeQuery(s));
++ System.out.printf("escapeQueryNew = %s%n", escapeQueryNew(s));
++ System.out.printf("escQueryURIUtil= %s%n", escapeQueryURIUtil(s));
++ System.out.printf("escQueryEncoder= %s%n", escapeQueryEncoder(s));
++ System.out.printf("unescQueryDODS = %s%n", unescapeQueryDODS(escapeQuery(s)));
++ System.out.printf("%n");
++ }
++
++ private static void checkUnEsc(String esc) {
++ System.out.printf("esc = %s%n", esc);
++ System.out.printf("unescQueryDODS = %s%n", unescapeQueryDODS(esc));
++ System.out.printf("unescapeDecoder = %s%n", unescapeQueryDecoder(esc));
++ System.out.printf("escapeQuery = %s%n", escapeQuery(unescapeQueryDODS(esc)));
++ System.out.printf("%n");
++ }
++
++ private static void decode(String esc) {
++ System.out.printf("esc = %s%n", esc);
++ System.out.printf("URLDecoder.decode = %s%n", URLDecoder.decode(esc));
++ System.out.printf("%n");
++ }
++
++
++
++ public static void main(String args[]) throws URISyntaxException {
++ if (args.length > 0) {
++ checkUnEsc(args[0]);
++ } else {
++ String s = "/thredds/dodsC/grib/NCEP/NAM/CONUS_12km/best.dods?Relative_humidity_pressure%5b0:1:0%5d%5b0:1:24%5d%5b0:10:420%5d%5b0:10:610%5d";
++ decode(s);
++ }
++
++ }
++
++
+ }
+\ Manca newline alla fine del file
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/unidata/io/http/HTTPRandomAccessFile.java thredds-4.3.18-gil/cdm/src/main/java/ucar/unidata/io/http/HTTPRandomAccessFile.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/unidata/io/http/HTTPRandomAccessFile.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/unidata/io/http/HTTPRandomAccessFile.java 2013-09-16 07:30:57.722067952 +0200
+@@ -33,9 +33,8 @@
+
+ package ucar.unidata.io.http;
+
+-import ucar.nc2.util.net.HTTPMethod;
+-import ucar.nc2.util.net.HTTPSession;
+-import org.apache.commons.httpclient.Header;
++import ucar.nc2.util.net.*;
++import org.apache.http.Header;
+ import ucar.unidata.util.Urlencoded;
+
+ import java.io.FileNotFoundException;
+@@ -77,13 +76,13 @@
+ if (debugLeaks)
+ allFiles.add(location);
+
+- session = new HTTPSession(url);
++ session = HTTPFactory.newSession(url);
+
+ boolean needtest = true;
+
+ HTTPMethod method = null;
+ try {
+- method = HTTPMethod.Head(session);
++ method = HTTPFactory.Head(session);
+
+ doConnect(method);
+
+@@ -137,7 +136,7 @@
+ private boolean rangeOk(String url) {
+ HTTPMethod method = null;
+ try {
+- method = HTTPMethod.Get(session,url);
++ method = HTTPFactory.Get(session,url);
+ method.setRequestHeader("Range", "bytes=" + 0 + "-" + 1);
+ doConnect(method);
+
+@@ -204,7 +203,7 @@
+
+ HTTPMethod method = null;
+ try {
+- method = HTTPMethod.Get(session);
++ method = HTTPFactory.Get(session);
+ method.setFollowRedirects(true);
+ method.setRequestHeader("Range", "bytes=" + pos + "-" + end);
+ doConnect(method);
+diff -Nru thredds-4.3.18/cdm/src/test/java/ucar/nc2/util/net/NoTestAuth2.java thredds-4.3.18-gil/cdm/src/test/java/ucar/nc2/util/net/NoTestAuth2.java
+--- thredds-4.3.18/cdm/src/test/java/ucar/nc2/util/net/NoTestAuth2.java 2013-09-16 02:10:49.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/test/java/ucar/nc2/util/net/NoTestAuth2.java 2013-09-16 07:36:04.853944841 +0200
+@@ -1,107 +1,101 @@
+-/*
+- * Copyright (c) 1998 - 2011. 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 junit.framework.TestCase;
+-import org.apache.commons.httpclient.UsernamePasswordCredentials;
+-import org.apache.commons.httpclient.auth.CredentialsProvider;
+-import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
+-import org.apache.commons.httpclient.auth.AuthScheme;
+-import org.apache.commons.httpclient.Credentials;
+-
+-import org.junit.Test;
+-import ucar.nc2.util.net.HTTPException;
+-import ucar.nc2.util.net.HTTPMethod;
+-import ucar.nc2.util.net.HTTPSession;
+-
+-import java.io.ByteArrayOutputStream;
+-import java.io.PrintStream;
+-
+-public class NoTestAuth2 extends TestCase
+-{
+- static class Data
+- {
+- String url;
+- CredentialsProvider provider;
+- public Data(String u,CredentialsProvider p) {this.url=u; this.provider=p;}
+- }
+- static private Data[] cases = new Data[] {
+- new Data("http://thredds-test.ucar.edu:8080/thredds/dodsC/restrict/testdata/testData.nc.html",
+- new CredentialsProvider() {
+- public Credentials getCredentials(AuthScheme sch, String h, int p, boolean pr)
+- throws CredentialsNotAvailableException {
+- UsernamePasswordCredentials creds
+- = new UsernamePasswordCredentials("tiggeUser","tigge");
+- System.out.printf("getCredentials called: creds=|%s| host=%s port=%d isproxy=%b authscheme=%s%n",
+- creds.toString(),h,p,pr,sch);
+- return creds;
+- }
+- }),
+- new Data("https://thredds-test.ucar.edu:8443/dts/b31.dds",null),
+- };
+-
+-
+- public void testAuth2() throws Exception
+- {
+- boolean pass = true;
+- for(Data data: cases) {
+- HTTPSession session = new HTTPSession(data.url);
+- if(data.provider != null)
+- session.setCredentialsProvider(data.provider);
+- session.setUserAgent("tdmRunner");
+- HTTPSession.setGlobalUserAgent("TDM v4.3");
+- HTTPMethod m = null;
+- try {
+- System.out.printf("url %s%n", data.url);
+- m = HTTPMethod.Get(session);
+- int status = m.execute();
+- String s = m.getResponseAsString();
+- System.out.printf("Trigger response = %d == %s%n", status, s);
+- if(status != 200 && status != 404)
+- pass = false;
+- } catch (HTTPException e) {
+- System.err.println("Fail: "+data.url);
+- ByteArrayOutputStream bos = new ByteArrayOutputStream(10000);
+- e.printStackTrace(new PrintStream(bos));
+- e.printStackTrace();
+- pass = false;
+- } finally {
+- if (session != null) session.close();
+- }
+- }
+- if(pass)
+- assertTrue("testAuth2", true);
+- else
+- assertTrue("testAuth2", false);
+- }
+-
+-}
++/*
++ * Copyright (c) 1998 - 2011. 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 junit.framework.TestCase;
++import org.apache.http.auth.*;
++import org.apache.http.client.CredentialsProvider;
++
++import java.io.ByteArrayOutputStream;
++import java.io.PrintStream;
++
++public class NoTestAuth2 extends TestCase
++{
++ static class Data
++ {
++ String url;
++ CredentialsProvider provider;
++ public Data(String u,CredentialsProvider p) {this.url=u; this.provider=p;}
++ }
++ static private Data[] cases = new Data[] {
++ new Data("http://thredds-test.ucar.edu:8080/thredds/dodsC/restrict/testdata/testData.nc.html",
++ new CredentialsProvider() {
++ public Credentials getCredentials(AuthScope scope) //AuthScheme sch, String h, int p, boolean pr)
++ {
++ UsernamePasswordCredentials creds
++ = new UsernamePasswordCredentials("tiggeUser","tigge");
++ System.out.printf("getCredentials called: creds=|%s| host=%s port=%d%n",
++ creds.toString(),scope.getHost(),scope.getPort());
++ return creds;
++ }
++ public void setCredentials(AuthScope scope, Credentials creds) {}
++ public void clear() {}
++ }),
++ new Data("https://thredds-test.ucar.edu:8443/dts/b31.dds",null),
++ };
++
++
++ public void testAuth2() throws Exception
++ {
++ boolean pass = true;
++ for(Data data: cases) {
++ HTTPSession session = HTTPFactory.newSession(data.url);
++ if(data.provider != null)
++ session.setCredentialsProvider(data.provider);
++ session.setUserAgent("tdmRunner");
++ HTTPSession.setGlobalUserAgent("TDM v4.3");
++ HTTPMethod m = null;
++ try {
++ System.out.printf("url %s%n", data.url);
++ m = HTTPFactory.Get(session);
++ int status = m.execute();
++ String s = m.getResponseAsString();
++ System.out.printf("Trigger response = %d == %s%n", status, s);
++ if(status != 200 && status != 404)
++ pass = false;
++ } catch (HTTPException e) {
++ System.err.println("Fail: "+data.url);
++ ByteArrayOutputStream bos = new ByteArrayOutputStream(10000);
++ e.printStackTrace(new PrintStream(bos));
++ e.printStackTrace();
++ pass = false;
++ } finally {
++ if (session != null) session.close();
++ }
++ }
++ if(pass)
++ assertTrue("testAuth2", true);
++ else
++ assertTrue("testAuth2", false);
++ }
++
++}
+diff -Nru thredds-4.3.18/cdm/src/test/java/ucar/nc2/util/net/TestAuth.java thredds-4.3.18-gil/cdm/src/test/java/ucar/nc2/util/net/TestAuth.java
+--- thredds-4.3.18/cdm/src/test/java/ucar/nc2/util/net/TestAuth.java 2013-09-16 02:10:49.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/test/java/ucar/nc2/util/net/TestAuth.java 2013-09-16 07:37:28.160571635 +0200
+@@ -1,452 +1,455 @@
+-/*
+- * 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 org.apache.commons.httpclient.UsernamePasswordCredentials;
+-import org.apache.commons.httpclient.auth.CredentialsProvider;
+-import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
+-import org.apache.commons.httpclient.auth.AuthScheme;
+-import org.apache.commons.httpclient.Credentials;
+-import org.apache.commons.httpclient.protocol.Protocol;
+-import org.junit.Test;
+-import ucar.nc2.TestLocal;
+-import ucar.nc2.util.UnitTestCommon;
+-
+-import java.io.*;
+-import java.util.List;
+-import java.io.Serializable;
+-
+-public class TestAuth extends UnitTestCommon
+-{
+- // Add a temporary control for remote versus localhost
+- static boolean remote = false;
+-
+- // TODO: add proxy and digest tests
+-
+- // Assuming we have thredds root, then the needed keystores
+- // are located in this directory
+- static final String KEYDIR = "/cdm/src/test/resources";
+-
+- static final String CLIENTKEY = "clientkey.jks";
+- static final String CLIENTPWD = "changeit";
+-
+- // Mnemonics for xfail
+- static final boolean MUSTFAIL = true;
+- static final boolean MUSTPASS = false;
+-
+- static {
+- // Register the 8843 protocol to test client side keys
+- HTTPSession.registerProtocol("https", 8843,
+- new Protocol("https",
+- new EasySSLProtocolSocketFactory(),
+- 8843));
+- HTTPSession.TESTING = true;
+- }
+-
+- //////////////////////////////////////////////////
+- // Provide a non-interactive CredentialsProvider to hold
+- // the user+pwd; used in several places
+- static class BasicProvider implements CredentialsProvider, Serializable
+- {
+- String username = null;
+- String password = null;
+-
+- public BasicProvider(String username, String password)
+- {
+- this.username = username;
+- this.password = password;
+- }
+-
+- // Credentials Provider Interface
+- public Credentials
+- getCredentials(AuthScheme authscheme, String host, int port, boolean isproxy)
+- throws CredentialsNotAvailableException
+- {
+- UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
+- System.out.printf("getCredentials called: creds=|%s| host=%s port=%d isproxy=%b authscheme=%s%n",
+- creds.toString(), host, port, isproxy, authscheme);
+- return creds;
+- }
+-
+- // Serializable Interface
+- private void writeObject(java.io.ObjectOutputStream oos)
+- throws IOException
+- {
+- oos.writeObject(this.username);
+- oos.writeObject(this.password);
+- }
+-
+- private void readObject(java.io.ObjectInputStream ois)
+- throws IOException, ClassNotFoundException
+- {
+- this.username = (String) ois.readObject();
+- this.password = (String) ois.readObject();
+- }
+- }
+-
+- //////////////////////////////////////////////////
+- //////////////////////////////////////////////////
+-
+- // Define the test sets
+-
+- int passcount = 0;
+- int xfailcount = 0;
+- int failcount = 0;
+- boolean verbose = true;
+- boolean pass = false;
+-
+- String datadir = null;
+- String threddsroot = null;
+-
+- public TestAuth(String name, String testdir)
+- {
+- super(name);
+- setTitle("DAP Authorization tests");
+- }
+-
+- public TestAuth(String name)
+- {
+- this(name, null);
+- }
+-
+- public TestAuth()
+- {
+- this("TestAuth", null);
+- }
+- @Test
+- public void
+- testSSH() throws Exception
+- {
+- String[] sshurls = {
+- "https://thredds-test.ucar.edu:8444/dts/b31.dds"
+- };
+-
+- System.out.println("*** Testing: Simple Https");
+- for (String url : sshurls) {
+- System.out.println("*** URL: " + url);
+- HTTPSession session = new HTTPSession(url);
+- HTTPMethod method = HTTPMethod.Get(session);
+- int status = method.execute();
+- System.out.printf("\tstatus code = %d\n", status);
+- pass = (status == 200);
+- assertTrue("testSSH", pass);
+- }
+- }
+-
+- //////////////////////////////////////////////////
+-
+- static class AuthDataBasic
+- {
+- String url;
+- String user = null;
+- String password = null;
+- boolean xfail = false; // failure expected
+-
+- public AuthDataBasic(String url, String usr, String pwd, boolean xfail)
+- {
+- this.url = url;
+- this.user = usr;
+- this.password = pwd;
+- this.xfail = xfail;
+- }
+- }
+-
+- static AuthDataBasic[] basictests = {
+- new AuthDataBasic("http://motherlode.ucar.edu:8081/thredds/dodsC/restrict/testData.nc.html",
+- "tiggeUser", "tigge", MUSTPASS),
+- new AuthDataBasic("http://motherlode.ucar.edu:8081/thredds/dodsC/restrict/testData.nc.html",
+- "", "", MUSTFAIL)
+- };
+-
+-
+- @Test
+- public void
+- testBasic() throws Exception
+- {
+- System.out.println("*** Testing: Http Basic Password Authorization");
+-
+- for (AuthDataBasic data : basictests) {
+- CredentialsProvider provider = new BasicProvider(data.user, data.password);
+- System.out.println("*** URL: " + data.url);
+- // Test local credentials provider
+- HTTPSession session = new HTTPSession(data.url);
+- session.setCredentialsProvider(provider);
+- HTTPMethod method = HTTPMethod.Get(session);
+- int status = method.execute();
+- System.out.printf("\tlocal provider: status code = %d\n", status);
+- System.out.flush();
+- pass = (status == 200 || status == 404); // non-existence is ok
+- String msg;
+- if (data.xfail) {
+- msg = pass ? "Local test failed to fail (xfail)" : "Local test passed (xfail)";
+- pass = !pass;
+- } else {
+- msg = pass ? "Local test passed" : "Local test failed";
+- }
+- System.out.println("\t" + msg);
+- if (pass) {
+- // Test global credentials provider
+- HTTPSession.setGlobalCredentialsProvider(provider);
+- session = new HTTPSession(data.url);
+- method = HTTPMethod.Get(session);
+- status = method.execute();
+- System.out.printf("\tglobal provider test: status code = %d\n", status);
+- System.out.flush();
+- pass = (status == 200 || status == 404); // non-existence is ok
+- if (data.xfail) {
+- msg = pass ? "Local test failed to fail (xfail)" : "Local test passed (xfail)";
+- pass = !pass;
+- } else {
+- msg = pass ? "Local test passed" : "Local test failed";
+- }
+- System.out.println("\t" + msg);
+- }
+- if (pass)
+- assertTrue("testBasic", true);
+- else
+- assertTrue("testBasic", false);
+- }
+- }
+-
+- @Test
+- public void
+- testBasic2() throws Exception
+- {
+- System.out.println("*** Testing: Http Basic Password Authorization Using direct credentials");
+-
+- for (AuthDataBasic data : basictests) {
+- Credentials cred = new UsernamePasswordCredentials(data.user, data.password);
+- System.out.println("*** URL: " + data.url);
+- // Test local credentials provider
+- HTTPSession session = new HTTPSession(data.url);
+- session.setCredentials(HTTPAuthScheme.BASIC,cred);
+- HTTPMethod method = HTTPMethod.Get(session);
+- int status = method.execute();
+- System.out.printf("\tlocal provider: status code = %d\n", status);
+- System.out.flush();
+- pass = (status == 200 || status == 404); // non-existence is ok
+- String msg;
+- if (data.xfail) {
+- msg = pass ? "Local test failed to fail (xfail)" : "Local test passed (xfail)";
+- pass = !pass;
+- } else {
+- msg = pass ? "Local test passed" : "Local test failed";
+- }
+- System.out.println("\t" + msg);
+- if (pass) {
+- // Test global credentials provider
+- HTTPSession.setGlobalCredentials(HTTPAuthScheme.BASIC,cred);
+- session = new HTTPSession(data.url);
+- method = HTTPMethod.Get(session);
+- status = method.execute();
+- System.out.printf("\tglobal provider test: status code = %d\n", status);
+- System.out.flush();
+- pass = (status == 200 || status == 404); // non-existence is ok
+- if (data.xfail) {
+- msg = pass ? "Local test failed to fail (xfail)" : "Local test passed (xfail)";
+- pass = !pass;
+- } else {
+- msg = pass ? "Local test passed" : "Local test failed";
+- }
+- System.out.println("\t" + msg);
+- }
+- if (pass)
+- assertTrue("testBasic", true);
+- else
+- assertTrue("testBasic", false);
+- }
+- }
+-
+- // This test is turned off until such time as thredds-test is properly set up
+- @Test
+- public void
+- testKeystore() throws Exception
+- {
+- if (false) {
+- System.out.println("*** Testing: Client-side Key based Authorization");
+-
+- String server;
+- String path;
+- if (remote) {
+- server = "thredds-test.ucar.edu:8843";
+- path = "/dts/b31.dds";
+- } else {
+- server = "localhost:8843";
+- path = "/thredds/dodsC/testStandardTdsScan/1day.nc.dds";
+- }
+-
+- String url = "https://" + server + path;
+- System.out.println("*** URL: " + url);
+-
+- // See if the client keystore exists
+- String keystore = threddsRoot + KEYDIR + "/" + CLIENTKEY;
+- File tmp = new File(keystore);
+- if (!tmp.exists() || !tmp.canRead())
+- throw new Exception("Cannot read client key store: " + keystore);
+-
+- CredentialsProvider provider = new HTTPSSLProvider(keystore, CLIENTPWD);
+- HTTPSession.setGlobalCredentialsProvider(HTTPAuthScheme.SSL, provider);
+-
+- HTTPSession session = new HTTPSession(url);
+-
+- //session.setCredentialsProvider(provider);
+-
+- HTTPMethod method = HTTPMethod.Get(session);
+-
+- int status = method.execute();
+- System.out.printf("Execute: status code = %d\n", status);
+- pass = (status == 200);
+- if (pass)
+- assertTrue("testKeystore", true);
+- else
+- assertTrue("testKeystore", false);
+- }
+- }
+-
+- @Test
+- public void
+- testSerialize() throws Exception
+- {
+- System.out.println("*** Testing: HTTPAuthStore (de-)serialization");
+-
+- boolean ok = true;
+- CredentialsProvider creds1 = new BasicProvider("p1", "pwd");
+- CredentialsProvider creds2 = new HTTPSSLProvider("keystore", "keystorepwd");
+- CredentialsProvider creds3 = new BasicProvider("p3", "pwd3");
+-
+- // Add some entries to HTTPAuthStore
+- HTTPAuthStore.clear();
+- HTTPAuthStore.insert(new HTTPAuthStore.Entry(
+- HTTPAuthScheme.BASIC,
+- "http://ceda.ac.uk/dap/neodc/casix/seawifs_plankton/data/monthly/PSC_monthly_1998.nc.dds",
+- creds1)
+- );
+- HTTPAuthStore.insert(new HTTPAuthStore.Entry(
+- HTTPAuthScheme.SSL,
+- "http://ceda.ac.uk",
+- creds2)
+- );
+- HTTPAuthStore.insert(new HTTPAuthStore.Entry(
+- HTTPAuthScheme.BASIC,
+- "http://ceda.ac.uk",
+- creds3)
+- );
+-
+- // Remove any old file
+- File target1 = new File(TestLocal.temporaryDataDir + "serial1");
+- target1.delete();
+-
+- // serialize out
+- OutputStream ostream = new FileOutputStream(target1);
+- HTTPAuthStore.serialize(ostream, "password1");
+- // Read in
+- InputStream istream = new FileInputStream(target1);
+- List<HTTPAuthStore.Entry> entries = HTTPAuthStore.getDeserializedEntries(istream, "password1");
+-
+- // compare
+- List<HTTPAuthStore.Entry> rows = HTTPAuthStore.getAllRows();
+- for (HTTPAuthStore.Entry row : rows) {
+- HTTPAuthStore.Entry match = null;
+- for (HTTPAuthStore.Entry e : entries) {
+- block:
+- {
+- if (!HTTPAuthStore.Entry.identical(row, e)) break block;
+- if (match == null)
+- match = e;
+- else {
+- System.out.println("ambigous match");
+- ok = false;
+- }
+- }
+- }
+- if (match == null) {
+- System.out.println("no match for: " + row.toString());
+- ok = false;
+- }
+- }
+- assertTrue("test(De-)Serialize", ok);
+- }
+-
+-
+- // This test actually is does nothing because I have no way to test it
+- // since it requires a firwall proxy that requires username+pwd
+- @Test
+- public void
+- testFirewall() throws Exception
+- {
+- String user = null;
+- String pwd = null;
+- String host = null;
+- int port = -1;
+- String url = null;
+-
+- System.out.println("*** Testing: Http Firewall Proxy (with authentication)");
+- if(false) {
+- CredentialsProvider provider = new BasicProvider(user,pwd);
+- System.out.println("*** URL: " + url);
+- // Test local credentials provider
+- HTTPSession session = new HTTPSession(url);
+- session.setProxy(host,port);
+- session.setCredentialsProvider(provider);
+- HTTPMethod method = HTTPMethod.Get(session);
+- int status = method.execute();
+- System.out.printf("\tlocal provider: status code = %d\n", status);
+- System.out.flush();
+- pass = (status == 200 || status == 404); // non-existence is ok
+- String msg = pass ? "Local test passed" : "Local test failed";
+- System.out.println("\t" + msg);
+- if (pass) {
+- // Test global credentials provider
+- HTTPSession.setGlobalCredentialsProvider(provider);
+- HTTPSession.setGlobalProxy(host,port);
+- session = new HTTPSession(url);
+- method = HTTPMethod.Get(session);
+- status = method.execute();
+- System.out.printf("\tglobal provider test: status code = %d\n", status);
+- System.out.flush();
+- pass = (status == 200 || status == 404); // non-existence is ok
+- msg = pass ? "Local test passed" : "Local test failed";
+- System.out.println("\t" + msg);
+- }
+- if (pass)
+- assertTrue("testProxy", true);
+- else
+- assertTrue("testProxy", false);
+- }
+- assertTrue("testProxy",true);
+- }
+-
+-
+-}
+-
++/*
++ * 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 org.apache.http.auth.*;
++import org.apache.http.client.CredentialsProvider;
++import org.junit.Test;
++import ucar.nc2.TestLocal;
++import ucar.nc2.util.UnitTestCommon;
++
++import java.io.*;
++import java.util.List;
++
++public class TestAuth extends UnitTestCommon
++{
++ // Add a temporary control for remote versus localhost
++ static boolean remote = false;
++
++ // TODO: add proxy and digest tests
++
++ // Assuming we have thredds root, then the needed keystores
++ // are located in this directory
++ static final String KEYDIR = "/cdm/src/test/resources";
++
++ static final String CLIENTKEY = "clientkey.jks";
++ static final String CLIENTPWD = "changeit";
++
++ // Mnemonics for xfail
++ static final boolean MUSTFAIL = true;
++ static final boolean MUSTPASS = false;
++
++ static {
++ //todo: Register the 8843 protocol to test client side keys
++ // HTTPSession.registerProtocol("https", 8843,
++ // new Protocol("https",
++ // new EasySSLProtocolSocketFactory(),
++ // 8843));
++ HTTPSession.TESTING = true;
++ }
++
++ //////////////////////////////////////////////////
++ // Provide a non-interactive CredentialsProvider to hold
++ // the user+pwd; used in several places
++ static class BasicProvider implements CredentialsProvider, Serializable
++ {
++ String username = null;
++ String password = null;
++
++ public BasicProvider(String username, String password)
++ {
++ this.username = username;
++ this.password = password;
++ }
++
++ // Credentials Provider Interface
++ public Credentials
++ getCredentials(AuthScope scope) //AuthScheme authscheme, String host, int port, boolean isproxy)
++ {
++ UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
++ System.out.printf("getCredentials called: creds=|%s| host=%s port=%d%n",
++ creds.toString(), scope.getHost(), scope.getPort());
++ return creds;
++ }
++
++ public void setCredentials(AuthScope scope, Credentials creds)
++ {
++ }
++
++ public void clear()
++ {
++ }
++
++ // Serializable Interface
++ private void writeObject(java.io.ObjectOutputStream oos)
++ throws IOException
++ {
++ oos.writeObject(this.username);
++ oos.writeObject(this.password);
++ }
++
++ private void readObject(java.io.ObjectInputStream ois)
++ throws IOException, ClassNotFoundException
++ {
++ this.username = (String) ois.readObject();
++ this.password = (String) ois.readObject();
++ }
++ }
++
++ //////////////////////////////////////////////////
++ //////////////////////////////////////////////////
++
++ // Define the test sets
++
++ int passcount = 0;
++ int xfailcount = 0;
++ int failcount = 0;
++ boolean verbose = true;
++ boolean pass = false;
++
++ String datadir = null;
++ String threddsroot = null;
++
++ public TestAuth(String name, String testdir)
++ {
++ super(name);
++ setTitle("DAP Authorization tests");
++ }
++
++ public TestAuth(String name)
++ {
++ this(name, null);
++ }
++
++ public TestAuth()
++ {
++ this("TestAuth", null);
++ }
++
++ @Test
++ public void
++ testSSH() throws Exception
++ {
++ String[] sshurls = {
++ "https://thredds-test.ucar.edu:8444/dts/b31.dds"
++ };
++
++ System.out.println("*** Testing: Simple Https");
++ for(String url : sshurls) {
++ System.out.println("*** URL: " + url);
++ HTTPSession session = HTTPFactory.newSession(url);
++ HTTPMethod method = HTTPFactory.Get(session);
++ int status = method.execute();
++ System.out.printf("\tstatus code = %d\n", status);
++ pass = (status == 200);
++ assertTrue("testSSH", pass);
++ }
++ }
++
++ //////////////////////////////////////////////////
++
++ static class AuthDataBasic
++ {
++ String url;
++ String user = null;
++ String password = null;
++ boolean xfail = false; // failure expected
++
++ public AuthDataBasic(String url, String usr, String pwd, boolean xfail)
++ {
++ this.url = url;
++ this.user = usr;
++ this.password = pwd;
++ this.xfail = xfail;
++ }
++ }
++
++ static AuthDataBasic[] basictests = {
++ new AuthDataBasic("http://motherlode.ucar.edu:8081/thredds/dodsC/restrict/testData.nc.html",
++ "tiggeUser", "tigge", MUSTPASS),
++ new AuthDataBasic("http://motherlode.ucar.edu:8081/thredds/dodsC/restrict/testData.nc.html",
++ "", "", MUSTFAIL)
++ };
++
++
++ @Test
++ public void
++ testBasic() throws Exception
++ {
++ System.out.println("*** Testing: Http Basic Password Authorization");
++
++ for(AuthDataBasic data : basictests) {
++ CredentialsProvider provider = new BasicProvider(data.user, data.password);
++ System.out.println("*** URL: " + data.url);
++ // Test local credentials provider
++ HTTPSession session = HTTPFactory.newSession(data.url);
++ session.setCredentialsProvider(provider);
++ HTTPMethod method = HTTPFactory.Get(session);
++ int status = method.execute();
++ System.out.printf("\tlocal provider: status code = %d\n", status);
++ System.out.flush();
++ pass = (status == 200 || status == 404); // non-existence is ok
++ String msg;
++ if(data.xfail) {
++ msg = pass ? "Local test failed to fail (xfail)" : "Local test passed (xfail)";
++ pass = !pass;
++ } else {
++ msg = pass ? "Local test passed" : "Local test failed";
++ }
++ System.out.println("\t" + msg);
++ if(pass) {
++ // Test global credentials provider
++ HTTPSession.setGlobalCredentialsProvider(provider);
++ session = HTTPFactory.newSession(data.url);
++ method = HTTPFactory.Get(session);
++ status = method.execute();
++ System.out.printf("\tglobal provider test: status code = %d\n", status);
++ System.out.flush();
++ pass = (status == 200 || status == 404); // non-existence is ok
++ if(data.xfail) {
++ msg = pass ? "Local test failed to fail (xfail)" : "Local test passed (xfail)";
++ pass = !pass;
++ } else {
++ msg = pass ? "Local test passed" : "Local test failed";
++ }
++ System.out.println("\t" + msg);
++ }
++ if(pass)
++ assertTrue("testBasic", true);
++ else
++ assertTrue("testBasic", false);
++ }
++ }
++
++ @Test
++ public void
++ testBasic2() throws Exception
++ {
++ System.out.println("*** Testing: Http Basic Password Authorization Using direct credentials");
++
++ for(AuthDataBasic data : basictests) {
++ Credentials cred = new UsernamePasswordCredentials(data.user, data.password);
++ System.out.println("*** URL: " + data.url);
++ // Test local credentials provider
++ HTTPSession session = HTTPFactory.newSession(data.url);
++ session.setCredentials(HTTPAuthScheme.BASIC, cred);
++ HTTPMethod method = HTTPFactory.Get(session);
++ int status = method.execute();
++ System.out.printf("\tlocal provider: status code = %d\n", status);
++ System.out.flush();
++ pass = (status == 200 || status == 404); // non-existence is ok
++ String msg;
++ if(data.xfail) {
++ msg = pass ? "Local test failed to fail (xfail)" : "Local test passed (xfail)";
++ pass = !pass;
++ } else {
++ msg = pass ? "Local test passed" : "Local test failed";
++ }
++ System.out.println("\t" + msg);
++ if(pass) {
++ // Test global credentials provider
++ HTTPSession.setGlobalCredentials(HTTPAuthScheme.BASIC, cred);
++ session = HTTPFactory.newSession(data.url);
++ method = HTTPFactory.Get(session);
++ status = method.execute();
++ System.out.printf("\tglobal provider test: status code = %d\n", status);
++ System.out.flush();
++ pass = (status == 200 || status == 404); // non-existence is ok
++ if(data.xfail) {
++ msg = pass ? "Local test failed to fail (xfail)" : "Local test passed (xfail)";
++ pass = !pass;
++ } else {
++ msg = pass ? "Local test passed" : "Local test failed";
++ }
++ System.out.println("\t" + msg);
++ }
++ if(pass)
++ assertTrue("testBasic", true);
++ else
++ assertTrue("testBasic", false);
++ }
++ }
++
++ // This test is turned off until such time as thredds-test is properly set up
++ @Test
++ public void
++ testKeystore() throws Exception
++ {
++ if(false) {
++ System.out.println("*** Testing: Client-side Key based Authorization");
++
++ String server;
++ String path;
++ if(remote) {
++ server = "thredds-test.ucar.edu:8843";
++ path = "/dts/b31.dds";
++ } else {
++ server = "localhost:8843";
++ path = "/thredds/dodsC/testStandardTdsScan/1day.nc.dds";
++ }
++
++ String url = "https://" + server + path;
++ System.out.println("*** URL: " + url);
++
++ // See if the client keystore exists
++ String keystore = threddsRoot + KEYDIR + "/" + CLIENTKEY;
++ File tmp = new File(keystore);
++ if(!tmp.exists() || !tmp.canRead())
++ throw new Exception("Cannot read client key store: " + keystore);
++
++ CredentialsProvider provider = new HTTPSSLProvider(keystore, CLIENTPWD);
++ HTTPSession.setGlobalCredentialsProvider(HTTPAuthScheme.SSL, provider);
++
++ HTTPSession session = HTTPFactory.newSession(url);
++
++ //session.setCredentialsProvider(provider);
++
++ HTTPMethod method = HTTPFactory.Get(session);
++
++ int status = method.execute();
++ System.out.printf("Execute: status code = %d\n", status);
++ pass = (status == 200);
++ if(pass)
++ assertTrue("testKeystore", true);
++ else
++ assertTrue("testKeystore", false);
++ }
++ }
++
++ @Test
++ public void
++ testSerialize() throws Exception
++ {
++ System.out.println("*** Testing: HTTPAuthStore (de-)serialization");
++
++ boolean ok = true;
++ CredentialsProvider creds1 = new BasicProvider("p1", "pwd");
++ CredentialsProvider creds2 = new HTTPSSLProvider("keystore", "keystorepwd");
++ CredentialsProvider creds3 = new BasicProvider("p3", "pwd3");
++
++ // Add some entries to HTTPAuthStore
++ HTTPAuthStore.clear();
++ HTTPAuthStore.insert(new HTTPAuthStore.Entry(
++ HTTPAuthScheme.BASIC,
++ "http://ceda.ac.uk/dap/neodc/casix/seawifs_plankton/data/monthly/PSC_monthly_1998.nc.dds",
++ creds1)
++ );
++ HTTPAuthStore.insert(new HTTPAuthStore.Entry(
++ HTTPAuthScheme.SSL,
++ "http://ceda.ac.uk",
++ creds2)
++ );
++ HTTPAuthStore.insert(new HTTPAuthStore.Entry(
++ HTTPAuthScheme.BASIC,
++ "http://ceda.ac.uk",
++ creds3)
++ );
++
++ // Remove any old file
++ File target1 = new File(TestLocal.temporaryDataDir + "serial1");
++ target1.delete();
++
++ // serialize out
++ OutputStream ostream = new FileOutputStream(target1);
++ HTTPAuthStore.serialize(ostream, "password1");
++ // Read in
++ InputStream istream = new FileInputStream(target1);
++ List<HTTPAuthStore.Entry> entries = HTTPAuthStore.getDeserializedEntries(istream, "password1");
++
++ // compare
++ List<HTTPAuthStore.Entry> rows = HTTPAuthStore.getAllRows();
++ for(HTTPAuthStore.Entry row : rows) {
++ HTTPAuthStore.Entry match = null;
++ for(HTTPAuthStore.Entry e : entries) {
++ block:
++ {
++ if(!HTTPAuthStore.Entry.identical(row, e)) break block;
++ if(match == null)
++ match = e;
++ else {
++ System.out.println("ambigous match");
++ ok = false;
++ }
++ }
++ }
++ if(match == null) {
++ System.out.println("no match for: " + row.toString());
++ ok = false;
++ }
++ }
++ assertTrue("test(De-)Serialize", ok);
++ }
++
++
++ // This test actually is does nothing because I have no way to test it
++ // since it requires a firwall proxy that requires username+pwd
++ @Test
++ public void
++ testFirewall() throws Exception
++ {
++ String user = null;
++ String pwd = null;
++ String host = null;
++ int port = -1;
++ String url = null;
++
++ System.out.println("*** Testing: Http Firewall Proxy (with authentication)");
++ if(false) {
++ CredentialsProvider provider = new BasicProvider(user, pwd);
++ System.out.println("*** URL: " + url);
++ // Test local credentials provider
++ HTTPSession session = HTTPFactory.newSession(url);
++ session.setProxy(host, port);
++ session.setCredentialsProvider(provider);
++ HTTPMethod method = HTTPFactory.Get(session);
++ int status = method.execute();
++ System.out.printf("\tlocal provider: status code = %d\n", status);
++ System.out.flush();
++ pass = (status == 200 || status == 404); // non-existence is ok
++ String msg = pass ? "Local test passed" : "Local test failed";
++ System.out.println("\t" + msg);
++ if(pass) {
++ // Test global credentials provider
++ HTTPSession.setGlobalCredentialsProvider(provider);
++ HTTPSession.setGlobalProxy(host, port);
++ session = HTTPFactory.newSession(url);
++ method = HTTPFactory.Get(session);
++ status = method.execute();
++ System.out.printf("\tglobal provider test: status code = %d\n", status);
++ System.out.flush();
++ pass = (status == 200 || status == 404); // non-existence is ok
++ msg = pass ? "Local test passed" : "Local test failed";
++ System.out.println("\t" + msg);
++ }
++ if(pass)
++ assertTrue("testProxy", true);
++ else
++ assertTrue("testProxy", false);
++ }
++ assertTrue("testProxy", true);
++ }
++
++
++}
++
+diff -Nru thredds-4.3.18/cdm/src/test/java/ucar/nc2/util/net/TestHTTPMethod.java thredds-4.3.18-gil/cdm/src/test/java/ucar/nc2/util/net/TestHTTPMethod.java
+--- thredds-4.3.18/cdm/src/test/java/ucar/nc2/util/net/TestHTTPMethod.java 2013-09-16 02:10:49.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/test/java/ucar/nc2/util/net/TestHTTPMethod.java 2013-09-16 07:41:12.550792277 +0200
+@@ -86,8 +86,8 @@
+ System.out.println("*** URL: " + url);
+
+ System.out.println("*** Testing: HTTPMethod.getResponseBodyAsStream");
+- session = new HTTPSession(url);
+- method = HTTPMethod.Get(session);
++ session = HTTPFactory.newSession(url);
++ method = HTTPFactory.Get(session);
+ method.execute();
+ InputStream stream = method.getResponseBodyAsStream();
+ // Read the whole thing
+@@ -116,8 +116,8 @@
+ System.out.println("*** URL: " + url);
+
+ System.out.println("*** Testing: HTTPMethod.getResponseBodyAsStream partial read");
+- session = new HTTPSession(url);
+- method = HTTPMethod.Get(session);
++ session = HTTPFactory.newSession(url);
++ method = HTTPFactory.Get(session);
+ method.execute();
+ InputStream stream = method.getResponseBodyAsStream();
+ byte[] buffer = new byte[EXPECTED];
+diff -Nru thredds-4.3.18/cdm/src/test/java/ucar/nc2/util/net/TestHTTPSession.java thredds-4.3.18-gil/cdm/src/test/java/ucar/nc2/util/net/TestHTTPSession.java
+--- thredds-4.3.18/cdm/src/test/java/ucar/nc2/util/net/TestHTTPSession.java 2013-09-16 02:10:49.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/test/java/ucar/nc2/util/net/TestHTTPSession.java 2013-09-16 07:38:53.471093249 +0200
+@@ -1,87 +1,87 @@
+-/*
+- * Copyright (c) 1998 - 2012. 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 org.junit.Test;
+-import ucar.nc2.util.UnitTestCommon;
+-
+-import static junit.framework.Assert.assertTrue;
+-
+-public class TestHTTPSession extends UnitTestCommon
+-{
+- //////////////////////////////////////////////////
+-
+- // Define the test sets
+-
+- int passcount = 0;
+- int xfailcount = 0;
+- int failcount = 0;
+- boolean verbose = true;
+- boolean pass = false;
+-
+- String datadir = null;
+- String threddsroot = null;
+-
+- public TestHTTPSession()
+- {
+- super();
+- setTitle("HTTP Session tests");
+- HTTPSession.TESTING = true;
+- }
+-
+- @Test
+- public void
+- testAgent() throws Exception {
+- String globalagent = "TestUserAgent123global";
+- String sessionagent = "TestUserAgent123session";
+- String url =
+- "http://thredds-test.ucar.edu:8081/dts/test.01.dds";
+-
+- System.out.println("*** Testing: User Agent");
+- System.out.println("*** URL: " + url);
+- System.out.println("Test: HTTPSession.setGlobalUserAgent(" + globalagent + ")");
+- HTTPSession.setGlobalUserAgent(globalagent);
+- HTTPSession session = new HTTPSession(url);
+- HTTPMethod method = HTTPMethod.Get(session);
+- method.execute();
+- System.out.println("Validate by examining localserver log output");
+-
+- System.out.println("Test: HTTPSession.setUserAgent(" + sessionagent + ")");
+- session.setUserAgent(sessionagent);
+- method = HTTPMethod.Get(session);
+- method.execute();
+- System.out.println("Validate by examining localserver log output");
+-
+- assertTrue("TestHTTPSession.testAgent", true);
+- }
+-}
++/*
++ * Copyright (c) 1998 - 2012. 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 org.junit.Test;
++import ucar.nc2.util.UnitTestCommon;
++
++import static junit.framework.Assert.assertTrue;
++
++public class TestHTTPSession extends UnitTestCommon
++{
++ //////////////////////////////////////////////////
++
++ // Define the test sets
++
++ int passcount = 0;
++ int xfailcount = 0;
++ int failcount = 0;
++ boolean verbose = true;
++ boolean pass = false;
++
++ String datadir = null;
++ String threddsroot = null;
++
++ public TestHTTPSession()
++ {
++ super();
++ setTitle("HTTP Session tests");
++ HTTPSession.TESTING = true;
++ }
++
++ @Test
++ public void
++ testAgent() throws Exception {
++ String globalagent = "TestUserAgent123global";
++ String sessionagent = "TestUserAgent123session";
++ String url =
++ "http://thredds-test.ucar.edu:8081/dts/test.01.dds";
++
++ System.out.println("*** Testing: User Agent");
++ System.out.println("*** URL: " + url);
++ System.out.println("Test: HTTPSession.setGlobalUserAgent(" + globalagent + ")");
++ HTTPSession.setGlobalUserAgent(globalagent);
++ HTTPSession session = HTTPFactory.newSession(url);
++ HTTPMethod method = HTTPFactory.Get(session);
++ method.execute();
++ System.out.println("Validate by examining localserver log output");
++
++ System.out.println("Test: HTTPSession.setUserAgent(" + sessionagent + ")");
++ session.setUserAgent(sessionagent);
++ method = HTTPFactory.Get(session);
++ method.execute();
++ System.out.println("Validate by examining localserver log output");
++
++ assertTrue("TestHTTPSession.testAgent", true);
++ }
++}
+diff -Nru thredds-4.3.18/cdm/src/test/java/ucar/nc2/util/net/TestState.java thredds-4.3.18-gil/cdm/src/test/java/ucar/nc2/util/net/TestState.java
+--- thredds-4.3.18/cdm/src/test/java/ucar/nc2/util/net/TestState.java 2013-09-16 02:10:49.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/test/java/ucar/nc2/util/net/TestState.java 2013-09-16 07:42:37.343341121 +0200
+@@ -81,11 +81,11 @@
+ throws Exception
+ {
+
+- HTTPSession session = new HTTPSession(SESSIONURL);
++ HTTPSession session = HTTPFactory.newSession(SESSIONURL);
+ assertFalse(session.isClosed());
+
+ // Check state transitions for open and execute
+- HTTPMethod method = HTTPMethod.Get(session, TESTSOURCE1);
++ HTTPMethod method = HTTPFactory.Get(session, TESTSOURCE1);
+ assertFalse(method.isClosed());
+ int methodcount = session.getMethodcount();
+ assertTrue(methodcount == 1);
+@@ -101,7 +101,7 @@
+ assertTrue(methodcount == 0);
+
+ // Check that method close forcibly closes streams
+- method = HTTPMethod.Get(session, TESTSOURCE1);
++ method = HTTPFactory.Get(session, TESTSOURCE1);
+ methodcount = session.getMethodcount();
+ assertTrue(methodcount == 1);
+ method.execute();
+@@ -113,7 +113,7 @@
+
+ // Check that session close closes methods and streams
+ // and transitively until stream close
+- method = HTTPMethod.Get(session);
++ method = HTTPFactory.Get(session);
+ methodcount = session.getMethodcount();
+ assertTrue(methodcount == 1);
+ method.execute();
+@@ -126,37 +126,25 @@
+ assertTrue(session.isClosed());
+
+ // Test Local session
+- method = HTTPMethod.Get();
++ method = HTTPFactory.Get();
+ assertTrue(method.isSessionLocal());
+ session = method.getSession();
+ methodcount = session.getMethodcount();
+ assertTrue(methodcount == 1);
+ method.execute(TESTSOURCE1);
+- String body = method.getResponseAsString();
+- stream = (HTTPMethodStream) method.getResponseBodyAsStream();
+- byte[] bbody = readbinaryfile(stream);
+- method.close();
+- assertTrue(stream.isClosed());
+- assertFalse(method.hasStreamOpen());
++ String body = method.getResponseAsString();// will close stream
++ try {
++ stream = (HTTPMethodStream) method.getResponseBodyAsStream();
++ readbinaryfile(stream);
++ System.err.println("Stream not closed.");
++ assertFalse(stream.isClosed());
++ } catch (Exception e) {
++ assertFalse(method.hasStreamOpen());
++ }
+ assertTrue(method.isClosed());
+ methodcount = session.getMethodcount();
+ assertTrue(methodcount == 0);
+ assertTrue(session.isClosed());
+-
+- // Finally, do a content comparison
+- String s = new String(bbody,UTF8);
+- if(verbose) {
+- System.err.println("Body as String:\n"+body);
+- System.err.println("Body as Bytes:\n"+s);
+- }
+-
+- String compare = compare("TestState",body,s);
+- if(compare != null) {
+- System.out.println(compare);
+- pass = false;
+- } else
+- pass = true;
+- assertTrue(pass);
+ }
+
+ static public byte[]
+diff -Nru thredds-4.3.18/pom.xml thredds-4.3.18-gil/pom.xml
+--- thredds-4.3.18/pom.xml 2013-09-16 07:46:40.701502787 +0200
++++ thredds-4.3.18-gil/pom.xml 2013-09-16 07:53:21.421366395 +0200
+@@ -410,9 +410,31 @@
+
+ <!-- client -->
+ <dependency>
+- <groupId>commons-httpclient</groupId>
+- <artifactId>commons-httpclient</artifactId>
+- <version>${commons-httpclient.version}</version>
++ <groupId>org.apache.httpcomponents</groupId>
++ <artifactId>httpclient</artifactId>
++ <version>${org.apache.httpcomponents.httpclient.version}</version>
++ <exclusions>
++ <exclusion>
++ <groupId>commons-logging</groupId> <!-- replace with jcl-over-slf4j -->
++ <artifactId>commons-logging</artifactId>
++ </exclusion>
++ </exclusions>
++ </dependency>
++ <dependency>
++ <groupId>org.apache.httpcomponents</groupId>
++ <artifactId>httpcore</artifactId>
++ <version>${org.apache.httpcomponents.httpcore.version}</version>
++ <exclusions>
++ <exclusion>
++ <groupId>commons-logging</groupId> <!-- replace with jcl-over-slf4j -->
++ <artifactId>commons-logging</artifactId>
++ </exclusion>
++ </exclusions>
++ </dependency>
++ <dependency>
++ <groupId>org.apache.httpcomponents</groupId>
++ <artifactId>httpmime</artifactId>
++ <version>${org.apache.httpcomponents.httpmime.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId> <!-- replace with jcl-over-slf4j -->
+@@ -884,7 +906,9 @@
+ <com.sleepycat.version>4.0.92</com.sleepycat.version>
+ <commons-dbcp.version>1.4</commons-dbcp.version>
+ <commons-fileupload.version>1.2.2</commons-fileupload.version>
+- <commons-httpclient.version>3.1</commons-httpclient.version>
++ <org.apache.httpcomponents.httpcore.version>4.2.4</org.apache.httpcomponents.httpcore.version>
++ <org.apache.httpcomponents.httpclient.version>4.2.5</org.apache.httpcomponents.httpclient.version>
++ <org.apache.httpcomponents.httpmime.version>4.2.5</org.apache.httpcomponents.httpmime.version>
+ <commons-io.version>2.4</commons-io.version>
+ <derby.version>10.9.1.0</derby.version>
+ <javax.activation.version>1.1.1</javax.activation.version>
diff --git a/thredds-4.3.18-cdm-use-proper-system-environment-variables.patch b/thredds-4.3.18-cdm-use-proper-system-environment-variables.patch
new file mode 100644
index 0000000..087c8b9
--- /dev/null
+++ b/thredds-4.3.18-cdm-use-proper-system-environment-variables.patch
@@ -0,0 +1,86 @@
+diff -Nru thredds-4.3.18/cdm/src/main/java/thredds/inventory/bdb/MetadataManager.java thredds-4.3.18-gil/cdm/src/main/java/thredds/inventory/bdb/MetadataManager.java
+--- thredds-4.3.18/cdm/src/main/java/thredds/inventory/bdb/MetadataManager.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/thredds/inventory/bdb/MetadataManager.java 2013-09-17 21:04:34.062342674 +0200
+@@ -68,10 +68,10 @@
+ //private static boolean debugDelete = false;
+
+ static {
+- String home = System.getProperty("user.home");
++ String home = System.getenv("user.home");
+
+ if (home == null)
+- home = System.getProperty("user.dir");
++ home = System.getProperty("user.home");
+
+ if (home == null)
+ home = ".";
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/DiskCache2.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/DiskCache2.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/DiskCache2.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/DiskCache2.java 2013-09-17 21:06:09.203383664 +0200
+@@ -86,10 +86,10 @@
+ String root = System.getProperty("nj22.cache");
+
+ if (root == null) {
+- String home = System.getProperty("user.home");
++ String home = System.getenv("user.home");
+
+ if (home == null)
+- home = System.getProperty("user.dir");
++ home = System.getProperty("user.home");
+
+ if (home == null)
+ home = ".";
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/DiskCache.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/DiskCache.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/DiskCache.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/DiskCache.java 2013-09-17 21:05:33.610234279 +0200
+@@ -102,10 +102,10 @@
+ root = System.getProperty("nj22.cache");
+
+ if (root == null) {
+- String home = System.getProperty("user.home");
++ String home = System.getenv("user.home");
+
+ if (home == null)
+- home = System.getProperty("user.dir");
++ home = System.getProperty("user.home");
+
+ if (home == null)
+ home = ".";
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/Misc.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/Misc.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/Misc.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/Misc.java 2013-09-17 21:08:27.485190713 +0200
+@@ -210,7 +210,7 @@
+ testdataDirPath = System.getProperty(testdataDirPropName); // Check for system property
+
+ if (testdataDirPath == null) {
+- File userHomeDirFile = new File(System.getProperty("user.home"));
++ File userHomeDirFile = new File(System.getenv("user.home"));
+ File userThreddsPropsFile = new File(userHomeDirFile, threddsPropFileName);
+ if (userThreddsPropsFile.exists() && userThreddsPropsFile.canRead()) {
+ Properties userThreddsProps = new Properties();
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/rc/RC.java thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/rc/RC.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/nc2/util/rc/RC.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/nc2/util/rc/RC.java 2013-09-17 21:07:15.653927753 +0200
+@@ -277,8 +277,8 @@
+ {
+ RC rc0 = new RC();
+ String[] locations = new String[] {
+- System.getProperty("user.home"),
+- System.getProperty("user.dir"),
++ System.getenv("user.home"),
++ System.getProperty("user.home"),
+ };
+
+ boolean found1 = false;
+diff -Nru thredds-4.3.18/cdm/src/main/java/ucar/util/prefs/XMLStore.java thredds-4.3.18-gil/cdm/src/main/java/ucar/util/prefs/XMLStore.java
+--- thredds-4.3.18/cdm/src/main/java/ucar/util/prefs/XMLStore.java 2013-09-16 02:10:48.000000000 +0200
++++ thredds-4.3.18-gil/cdm/src/main/java/ucar/util/prefs/XMLStore.java 2013-09-17 21:13:32.603302912 +0200
+@@ -325,7 +325,7 @@
+ // the directory
+ String userHome = null;
+ try {
+- userHome = System.getProperty("user.home");
++ userHome = System.getenv("user.home");
+ } catch (Exception e) {
+ System.out.println( "XMLStore.makeStandardFilename: error System.getProperty(user.home) "+e);
+ }
diff --git a/thredds-create-tarball.sh b/thredds-create-tarball.sh
new file mode 100644
index 0000000..995e6b6
--- /dev/null
+++ b/thredds-create-tarball.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+if [ $# -ne 1 ]; then
+ echo "Usage: ./create-sources VERSION"
+ exit 1
+fi
+
+VERSION=${1}
+NAME="thredds"
+
+git clone git://github.com/Unidata/${NAME}
+
+(
+ cd ${NAME}
+ git checkout -b v${VERSION}
+)
+
+mv ./${NAME} ./${NAME}-${VERSION}
+find ./${NAME}-${VERSION} -name "*.jar" -delete
+find ./${NAME}-${VERSION} -name "*.class" -delete
+find ./${NAME}-${VERSION} -name "*.dll" -delete
+find ./${NAME}-${VERSION} -name "*.zip" -delete
+
+# Remove unused files
+rm -Rf ./${NAME}-${VERSION}/docs/*
+rm -Rf ./${NAME}-${VERSION}/lib
+rm -Rf ./${NAME}-${VERSION}/cdm/doc
+rm -Rf ./${NAME}-${VERSION}/opendap/doc/*
+# Unwanted ... for now
+rm -Rf ./${NAME}-${VERSION}/cdm-test
+rm -Rf ./${NAME}-${VERSION}/opendap
+rm -Rf ./${NAME}-${VERSION}/ldm
+rm -Rf ./${NAME}-${VERSION}/ui
+rm -Rf ./${NAME}-${VERSION}/ncIdv
+rm -Rf ./${NAME}-${VERSION}/visad
+rm -Rf ./${NAME}-${VERSION}/tds
+rm -Rf ./${NAME}-${VERSION}/it
+rm -Rf ./${NAME}-${VERSION}/cdmvalidator
+rm -Rf ./${NAME}-${VERSION}/dts
+rm -Rf ./${NAME}-${VERSION}/grib
+rm -Rf ./${NAME}-${VERSION}/tdm
+rm -Rf ./${NAME}-${VERSION}/wmotables
+rm -Rf ./${NAME}-${VERSION}/wmoTablesOld
+rm -Rf ./${NAME}-${VERSION}/.git
+find ./${NAME}-${VERSION} -name ".git*" -delete
+tar cJf ${NAME}-${VERSION}-clean.tar.xz ./${NAME}-${VERSION}
\ No newline at end of file
diff --git a/thredds.spec b/thredds.spec
new file mode 100644
index 0000000..2121aa1
--- /dev/null
+++ b/thredds.spec
@@ -0,0 +1,205 @@
+Name: thredds
+Version: 4.3.19
+Release: 3%{?dist}
+Summary: Thematic Realtime Environmental Distributed Data Services (TDS)
+# GPLv3: opendap/src/main/java/opendap/dap/parsers/DapParser.java
+# LGPLv3: opendap/src/main/java/opendap/servlet/AsciiWriter.java
+# visad/src/main/java/ucar/nc2/iosp/mcidas/V5DStruct.java
+# grib/src/main/java/ucar/jpeg
+# ASL: tds/src/main/java/thredds/servlet/URLEncoder.java
+License: ASL 2.0 and BSD
+URL: http://www.unidata.ucar.edu/software/tds/
+# sh thredds-create-tarball.sh < VERSION >
+Source0: %{name}-%{version}-clean.tar.xz
+Source1: %{name}-create-tarball.sh
+
+# build fix for jna 3.5.0
+Patch0: thredds-4.3.16-cdm-jna35.patch
+# Replace commons-httpclient with org.apache.httpcomponents support
+# see https://github.com/Unidata/thredds/tree/http4/
+Patch1: thredds-4.3.18-cdm-http4.patch
+Patch2: thredds-4.3.18-cdm-use-proper-system-environment-variables.patch
+
+BuildRequires: java-devel
+
+BuildRequires: mvn(com.google.protobuf:protobuf-java)
+BuildRequires: mvn(com.sleepycat:je)
+BuildRequires: mvn(joda-time:joda-time) >= 2.0
+BuildRequires: mvn(log4j:log4j)
+BuildRequires: mvn(net.java.dev.jna:jna)
+BuildRequires: mvn(net.jcip:jcip-annotations)
+BuildRequires: mvn(net.sf.ehcache:ehcache-core)
+BuildRequires: mvn(org.apache.httpcomponents:httpclient)
+BuildRequires: mvn(org.apache.httpcomponents:httpcore)
+BuildRequires: mvn(org.apache.httpcomponents:httpmime)
+BuildRequires: mvn(org.jdom:jdom2)
+BuildRequires: mvn(org.quartz-scheduler:quartz)
+BuildRequires: mvn(org.slf4j:jcl-over-slf4j)
+BuildRequires: mvn(org.slf4j:slf4j-api)
+BuildRequires: mvn(org.slf4j:slf4j-log4j12)
+
+# TODO: opendap, grib, tdm, and tds modules
+%if 0
+BuildRequires: mvn(com.lexicalscope.jewelcli:jewelcli)
+BuildRequires: mvn(commons-httpclient:commons-httpclient)
+BuildRequires: mvn(edu.wisc.ssec:visad)
+BuildRequires: mvn(javax.servlet:servlet-api)
+BuildRequires: mvn(javax.servlet:jstl)
+BuildRequires: mvn(org.jdom:jdom)
+BuildRequires: mvn(org.jsoup:jsoup)
+BuildRequires: mvn(org.springframework:spring-beans)
+BuildRequires: mvn(org.springframework:spring-context)
+BuildRequires: mvn(org.springframework:spring-core)
+BuildRequires: mvn(org.springframework:spring-webmvc)
+%endif
+
+BuildRequires: maven-local
+
+# test deps
+BuildRequires: mvn(junit:junit)
+BuildRequires: mvn(org.slf4j:slf4j-jdk14)
+
+BuildArch: noarch
+
+%description
+The THREDDS (Thematic Realtime Environmental Distributed
+Data Services) project is developing middle-ware to bridge the
+gap between data providers and data users. The goal is to
+simplify the discovery and use of scientific data and to allow
+scientific publications and educational materials to reference
+scientific data. The mission of THREDDS is for students,
+educators and researchers to publish, contribute, find, and
+interact with data relating to the Earth system in a convenient,
+effective, and integrated fashion. Just as the World Wide Web and
+digital-library technologies have simplified the process of
+publishing and accessing multimedia documents, THREDDS is building
+infrastructure needed for publishing and accessing scientific data
+in a similarly convenient fashion.
+
+%package -n netcdf-java
+Summary: Java interface to NetCDF files
+
+%description -n netcdf-java
+The NetCDF-Java Library is a Java interface to NetCDF files,
+as well as to many other types of scientific data formats.
+
+%if 0
+%package -n bufr
+Summary: BUFR IOSP
+
+%description -n bufr
+Reading BUFR files with the NetCDF-java library.
+
+%package -n grib
+Summary: GRIB IOSP and Feature Collection
+
+%description -n grib
+Decoder for the GRIB format.
+
+%package -n tdm
+Summary: THREDDS Data Manager (TDM)
+
+%description -n tdm
+THREDDS Data Manager (TDM).
+%endif
+
+%package -n java-udunits
+Summary: Java package for decoding and encoding unit specifications
+
+%description -n java-udunits
+The ucar.units Java package is for decoding and encoding
+formatted unit specifications (e.g. "m/s"), converting numeric values
+between compatible units (e.g. between "m/s" and "knot"), and for
+performing arithmetic operations on units (e.g. dividing one unit by
+another, raising a unit to a power).
+
+%package javadoc
+Summary: Javadoc for %{name}
+
+%description javadoc
+This package contains javadoc for %{name}.
+
+%prep
+%setup -q
+%patch0 -p0
+%patch1 -p1
+%patch2 -p1
+
+# Disable unavailable build deps
+%pom_disable_module visad
+%pom_disable_module ncIdv
+%pom_disable_module ui
+%pom_disable_module tds
+%pom_disable_module cdmvalidator
+%pom_disable_module cdm-test
+%pom_disable_module it
+# thredds use customized opendap == 0.0.7 http://www.opendap.org/
+%pom_disable_module opendap
+# require opendap module
+%pom_disable_module dts
+# Unwanted ... for now ... it bundled customizzation of jj2000 see http://code.google.com/p/jj2000/
+%pom_disable_module grib
+%pom_disable_module tdm
+%pom_disable_module wmotables
+%pom_disable_module bufr
+%pom_disable_module tdcommon
+
+# Unwanted
+%pom_remove_plugin :maven-source-plugin cdm
+
+# Disable class-path in manifest
+%pom_xpath_set "pom:build/pom:pluginManagement/pom:plugins/pom:plugin[pom:artifactId = 'maven-jar-plugin' ]/pom:configuration/pom:archive/pom:manifest/pom:addClasspath" false
+# jna 3.0.9
+%pom_xpath_set "pom:dependencies/pom:dependency[pom:artifactId = 'jna']/pom:groupId" net.java.dev.jna cdm
+
+sed -i 's/\r//' cdm/CHANGES.txt cdm/license.txt
+
+%build
+
+%mvn_build -s
+
+%install
+%mvn_install
+
+install -pm 644 cdm/target/netcdf-%{version}-tests.jar %{buildroot}%{_javadir}/%{name}/netcdf-tests.jar
+
+%files -f .mfiles-%{name}-parent
+%dir %{_javadir}/%{name}
+%doc README.md cdm/license.txt
+
+%files -n netcdf-java -f .mfiles-netcdf
+%{_javadir}/%{name}/netcdf-tests.jar
+%doc cdm/CHANGES.txt cdm/license.txt
+
+%if 0
+%files -n bufr -f .mfiles-bufr
+%doc cdm/license.txt
+
+%files -n grib -f .mfiles-grib
+%doc cdm/license.txt
+
+%files -n tdm -f .mfiles-tdm
+%doc cdm/license.txt
+%endif
+
+%files -n java-udunits -f .mfiles-udunits
+%doc cdm/license.txt
+
+%files javadoc -f .mfiles-javadoc
+%doc cdm/license.txt
+
+%changelog
+* Sat Oct 19 2013 gil cattaneo <puntogil at libero.it> 4.3.19-3
+- renamed sub package udunits
+
+* Sat Oct 19 2013 gil cattaneo <puntogil at libero.it> 4.3.19-2
+- fix license field
+
+* Wed Oct 16 2013 gil cattaneo <puntogil at libero.it> 4.3.19-1
+- update to 4.3.19
+
+* Mon Sep 16 2013 gil cattaneo <puntogil at libero.it> 4.3.18-1
+- update to 4.3.18
+
+* Mon Jun 24 2013 gil cattaneo <puntogil at libero.it> 4.3.16-1
+- initial rpm
\ No newline at end of file
More information about the scm-commits
mailing list