[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