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

thredds.cataloggen.config.LocalDatasetSource Maven / Gradle / Ivy

Go to download

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

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

package thredds.cataloggen.config;

import thredds.catalog.*;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;


/**
 * Concrete implementation of DatasetSource for local disk sources.
 *
 * @author Ethan Davis
 * @version $Id: LocalDatasetSource.java 63 2006-07-12 21:50:51Z edavis $
 */

public class LocalDatasetSource extends DatasetSource
{
  static private org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(LocalDatasetSource.class);
  // private static Log log = LogFactory.getLog( LocalDatasetSource.class);

  private File accessPointHeaderFile = null;
  private File accessPointFile = null;

  LocalDatasetSource()
  {
      this.type = DatasetSourceType.getType( "Local");
  }

  protected InvDataset createDataset( String datasetLocation, String prefixUrlPath )
          throws IOException
  {
    if ( datasetLocation == null) throw new NullPointerException( "Dataset location cannot be null.");
    this.checkAccessPoint();
    return( new LocalInvDataset( null, new File( datasetLocation), prefixUrlPath));
  }

  /**
   * Build an unnamed InvCatalog for this DatasetSource and return the
   * top-level InvDataset. The ResultService for this DatasetSource is
   * used to create the InvService for the new InvCatalog. Each InvDataset
   * in the catalog is named with the location of the object they represent
   * on the dataset source.
   *
   * @return the top-level dataset of the newly constructed InvCatalog.
   *
   * @throws IOException if top-level dataset does not exist or is not a collection dataset.
   */
  protected InvCatalog createSkeletonCatalog( String prefixUrlPath ) throws IOException
  {
    this.checkAccessPoint();

    // Create catalog.
    InvCatalogImpl catalog = new InvCatalogImpl( null, null, null );
                                                 //this.getName(), null, null);

    // Create service.
    InvService service = new InvService( this.getResultService().getName(),
                                         this.getResultService().getServiceType().toString(),
                                         this.getResultService().getBase(),
                                         this.getResultService().getSuffix(),
                                         this.getResultService().getDescription());
    for ( Iterator it = this.getResultService().getProperties().iterator(); it.hasNext(); )
    {
      service.addProperty( (InvProperty) it.next() );
    }
    for ( Iterator it = this.getResultService().getServices().iterator(); it.hasNext(); )
    {
      service.addService( (InvService) it.next() );
    }

    // Add service to catalog.
    catalog.addService( service);

    // Create top-level dataset.
    File apFile = new File( this.getAccessPoint() );
    InvDatasetImpl topDs = new LocalInvDataset( null, apFile, prefixUrlPath);

    // Set the serviceName (inherited by all datasets) in top-level dataset.
    ThreddsMetadata tm = new ThreddsMetadata( false);
    tm.setServiceName( service.getName());
    InvMetadata md = new InvMetadata( topDs, null, XMLEntityResolver.CATALOG_NAMESPACE_10, "", true, true, null, tm);
    ThreddsMetadata tm2 = new ThreddsMetadata( false);
    tm2.addMetadata( md);
    topDs.setLocalMetadata(tm2);

    // Add top-level dataset to catalog.
    catalog.addDataset( topDs);

    // Tie up any loose ends in catalog with finish().
    ((InvCatalogImpl) catalog).finish();

    return( catalog);
  }

  private void checkAccessPoint()
          throws IOException
  {
    if ( accessPointHeaderFile == null )
    {
      // Check that the accessPointHeader local file exists.
      File aphFile = new File( this.getResultService().getAccessPointHeader() );
      if ( !aphFile.exists() ) throw new IOException( "The accessPointHeader local file does not exist <" + aphFile.getPath() + ">." );

      // Check that the accessPoint local file exists.
      File apFile = new File( this.getAccessPoint() );
      if ( !apFile.exists() ) throw new IOException( "The accessPoint local file does not exist <" + apFile.getPath() + ">." );
      if ( !apFile.isDirectory() ) throw new IOException( "The accessPoint local file is not a directory <" + apFile.getPath() + ">." );

      // Check that accessPoint file starts with accessPointHeader.
      if ( ! apFile.getPath().startsWith( aphFile.getPath() )
           && ! apFile.getCanonicalPath().startsWith( aphFile.getCanonicalPath() ) )
      {
        String tmpMsg = "The accessPoint <" + apFile.getPath() + " or " + apFile.getCanonicalPath() + "> must start with the accessPointHeader <" + aphFile.getPath() + " or " + aphFile.getCanonicalPath() + ">.";
        logger.debug( "checkAccessPoint(): {}", tmpMsg );
        throw new IOException( tmpMsg );
      }

      // Save the accessPointHeader as a URI so encodings and "/" vs "\" issues are handled.
      accessPointHeaderFile = aphFile;
      accessPointFile = apFile;
    }
  }

  /**
   * Return true if the given dataset is a collection dataset, false otherwise.
   *
   * @param dataset - the InvDataset to test for being a collection dataset.
   * @return true if the given dataset is a collection dataset, false otherwise.
   * @throws NullPointerException if the given InvDataset is null.
   * @throws ClassCastException if the given InvDataset is not a LocalInvDataset.
   */
  protected boolean isCollection( InvDataset dataset)
  {
    return( ((LocalInvDataset) dataset).isDirectory());
  }

  /**
   * Return a list of the InvDatasets contained in the given collection dataset
   * on this DatasetSource.
   *
   * @param dataset - the collection dataset to be expanded.
   * @return A list of the InvDatasets contained in the given collection dataset.
   * @throws IllegalArgumentException when given dataset is not a collection dataset.
   * @throws NullPointerException if given dataset is null.
   * @throws ClassCastException if the given InvDataset is not a LocalInvDataset.
   */
  protected List expandThisLevel( InvDataset dataset, String prefixUrlPath )
  {
    if ( dataset == null) throw new NullPointerException( "Given dataset cannot be null.");
    if ( ! isCollection( dataset)) throw new IllegalArgumentException( "Dataset \"" + dataset.getName() + "\" is not a collection dataset.");

    // Deal with all files in this directory.
    File theDir = new File( ((LocalInvDataset) dataset).getLocalPath() );
    File[] allFiles = theDir.listFiles();
    InvDataset curDs = null;
    ArrayList list = new ArrayList();
    for ( int i = 0; i < allFiles.length; i++)
    {
      try
      {
        curDs = new LocalInvDataset( dataset, allFiles[ i], prefixUrlPath );
      }
      catch ( IOException e )
      {
        // Given file doesn't exist or is not under the accessPointHeader directory, skip.
        continue;
      }

      list.add( curDs);
    }

    return( list);
  }

  /**
   * An InvDatasetImpl subclass to deal with datasets on local disk.
   */
  private class LocalInvDataset extends InvDatasetImpl
  {
    private String relativePath;
    private String catRelativePath;
    private String localPath;
    private boolean directory;

    LocalInvDataset( InvDataset parent, File file, String prefixUrlPath) throws IOException
    {
      super( (InvDatasetImpl) parent, null, null, null, null );
      if (logger.isDebugEnabled())
        logger.debug( "LocalInvDataset(): parent=" + ( parent == null ? "" : parent.getName() ) + "; file=" + file.getPath());

      if ( ! file.exists()) throw new IOException( "File <" + file.getPath() + "> does not exist.");
      this.directory = file.isDirectory();

      // Determine the datasets urlPath by removing accessPointHeader from localPath.
      // (Use URIs to handle encoding and slash vs backslash issues.)
      String uriStringFromFile = file.toURI().toString();
      String uriStringFromCanonicalFile = file.getCanonicalFile().toURI().toString();
      String aphUriStringFromFile = accessPointHeaderFile.toURI().toString();
      String aphUriStringFromCanonicalFile = accessPointHeaderFile.getCanonicalFile().toURI().toString();
      String apUriStringFromFile = accessPointFile.toURI().toString();
      String apUriStringFromCanonicalFile = accessPointFile.getCanonicalFile().toURI().toString();
      relativePath = null;

      if (logger.isDebugEnabled()) {
        logger.debug( "LocalInvDataset():               file URI=" + uriStringFromFile );
        logger.debug( "LocalInvDataset():     canonical file URI=" + uriStringFromCanonicalFile );
        logger.debug( "LocalInvDataset():           aph file URI=" + aphUriStringFromFile );
        logger.debug( "LocalInvDataset(): aph canonical file URI=" + aphUriStringFromCanonicalFile );
      }

      // NOTE: Started using File.getCanonicalFile() to deal with comparisons containing this (".") or parent ("..") directories.
      //       But that caused caused comparison problems for symbolic links (e.g., on motherlode "/usr/local/apache/htdocs/motherlode/dods/model"
      //       does not start with "/usr/local/apache/htdocs/motherlode" because "model" is a link to "/data/ldm/pub/decoded/netcdf/GRIB").
      if ( ! uriStringFromFile.startsWith( aphUriStringFromFile ) )
      {
        if ( ! uriStringFromCanonicalFile.startsWith( aphUriStringFromCanonicalFile ) )
        {
          String tmpMsg = "File <" + uriStringFromFile + " or " + uriStringFromCanonicalFile + "> must start with accessPointHeader <" + aphUriStringFromFile + " or " + aphUriStringFromCanonicalFile + ">.";
          throw new IOException( tmpMsg );
        }
        else
        {
          relativePath = uriStringFromCanonicalFile.substring( aphUriStringFromCanonicalFile.length() );
          catRelativePath = uriStringFromCanonicalFile.substring( apUriStringFromCanonicalFile.length());
          localPath = file.getCanonicalPath();
        }
      }
      else
      {
        relativePath = uriStringFromFile.substring( aphUriStringFromFile.length() );
        catRelativePath = uriStringFromFile.substring( apUriStringFromFile.length() );
        localPath = file.getAbsolutePath();
      }

      if (logger.isDebugEnabled()) {
        logger.debug( "LocalInvDataset():           relativePath=" + relativePath );
        logger.debug( "LocalInvDataset():              localPath=" + localPath );
      }

      if ( ! this.directory )
      {
        // Check if service base is relative to the catalog URL the accessPointHeader.
        if ( LocalDatasetSource.this.getResultService().getBase().equals( "" )
             && ! LocalDatasetSource.this.getResultService().getServiceType().equals( ServiceType.COMPOUND) )
        {
//          String tmpUrlPath = prefixUrlPath == null || prefixUrlPath.equals( "")
//                              ? catRelativePath
//                              : prefixUrlPath + "/" + catRelativePath;
          this.setUrlPath( catRelativePath  );
        }
        else
        {
          String tmpUrlPath = prefixUrlPath == null || prefixUrlPath.equals( "" )
                              ? relativePath
                              : prefixUrlPath + "/" + relativePath;
          this.setUrlPath( tmpUrlPath );
        }

        // @todo Should make this optional, maybe with DatasetEnhancer1 (but by then only have dataset, not file).
        if ( LocalDatasetSource.this.isAddDatasetSize() )
        {
          this.setDataSize( file.length());
        }
      }
      String dsName = relativePath.endsWith( "/")
                      ? relativePath.substring( 0, relativePath.length() - 1)
                      : relativePath;
      int index = dsName.lastIndexOf('/');
      if ( index != -1 ) dsName = dsName.substring( index + 1);
      this.setName( dsName);
    }

    String getLocalPath() { return( this.localPath); }
    void setLocalPath( String localPath ) { this.localPath = localPath; }

    public boolean isDirectory() { return( this.directory); }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy