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

gov.nasa.pds.tools.util.Utility Maven / Gradle / Ivy

// Copyright 2006-2017, by the California Institute of Technology.
// ALL RIGHTS RESERVED. United States Government Sponsorship acknowledged.
// Any commercial use must be negotiated with the Office of Technology Transfer
// at the California Institute of Technology.
//
// This software is subject to U. S. export control laws and regulations
// (22 C.F.R. 120-130 and 15 C.F.R. 730-774). To the extent that the software
// is subject to U.S. export control laws and regulations, the recipient has
// the responsibility to obtain export licenses or other export authority as
// may be required before exporting such information to foreign countries or
// providing access to foreign nationals.
//
// $Id$
package gov.nasa.pds.tools.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;
import gov.nasa.pds.tools.validate.TargetExaminer;
import gov.nasa.pds.tools.validate.TargetType;
import gov.nasa.pds.tools.validate.ValidationTarget;

/**
 * Utility class.
 *
 * @author mcayanan
 *
 */
public class Utility {
  private static final Logger LOG = LoggerFactory.getLogger(Utility.class);

  // A static cache of the ValidationTargets.
  // There is no need to re-evaluate and/or create these
  // as validation proceeds, as they are static things like
  // a file or a URL.
  public static HashMap cachedTargets;
  static {
    cachedTargets = new HashMap<>();
  }

  // Implementation is needed since pds.nasa.gov currently uses SNI
  // which is not supported in Java 6, but is supported in Java 7.
  static {
    javax.net.ssl.HttpsURLConnection
        .setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {
          @Override
          public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
            if (hostname.equals("pds.nasa.gov") && hostname.equals(sslSession.getPeerHost())) {
              return true;
            }
            return false;
          }
        });
  }

  /**
   * Returns a ValidationTarget for the specified target URL.
   *
   * If a cached target already exists in the cache, then that is returned, otherwise a new
   * ValidationTarget is returned.
   *
   */
  public static ValidationTarget getValidationTarget(URL target) {
    if (target == null) {
      // for backwards-compatability with previous code, supporting the null case.
      // This seems to be null in the additional context products case.
      return new ValidationTarget(null);
    }
    ValidationTarget valTarget = cachedTargets.get(target.toString());
    if (valTarget == null) {
      valTarget = new ValidationTarget(target);
      cachedTargets.put(target.toString(), valTarget);
    }
    return valTarget;
  }
  public static ValidationTarget getValidationTarget(URL source, URL label) {
    if (source == null) {
      // for backwards-compatability with previous code, supporting the null case.
      // This seems to be null in the additional context products case.
      return new ValidationTarget(null);
    }
    ValidationTarget valTarget = cachedTargets.get(source.toString());
    if (valTarget == null) {
      valTarget = new ValidationTarget(source, label);
      cachedTargets.put(source.toString(), valTarget);
    }
    return valTarget;
  }

  /**
   * Method that opens a connection. Supports redirects.
   *
   * @param conn URL Connection
   *
   * @return input stream.
   * @throws IOException If an error occurred while opening the stream.
   */
  public static InputStream openConnection(URLConnection conn) throws IOException {
    boolean redir;
    int redirects = 0;
    InputStream in = null;
    do {
      if (conn instanceof HttpURLConnection) {
        ((HttpURLConnection) conn).setInstanceFollowRedirects(false);
      }
      // This code can go away when we move to Java 8
      if (conn instanceof HttpsURLConnection) {
        try {
          SSLContext context = SSLContext.getInstance("TLSv1.2");
          context.init(null, null, new java.security.SecureRandom());
          HttpsURLConnection test = (HttpsURLConnection) conn;
          SSLSocketFactory sf = test.getSSLSocketFactory();
          SSLSocketFactory d = HttpsURLConnection.getDefaultSSLSocketFactory();
          ((HttpsURLConnection) conn).setSSLSocketFactory(context.getSocketFactory());
        } catch (Exception e) {
          throw new IOException(e.getMessage());
        }
      }

      // We want to open the input stream before getting headers
      // because getHeaderField() et al swallow IOExceptions.
      try {
        in = conn.getInputStream();
        redir = false;
        if (conn instanceof HttpURLConnection) {
          HttpURLConnection http = (HttpURLConnection) conn;
          int stat = http.getResponseCode();
          if (stat >= 300 && stat <= 307 && stat != 306
              && stat != HttpURLConnection.HTTP_NOT_MODIFIED) {
            URL base = http.getURL();
            String loc = http.getHeaderField("Location");
            URL target = null;
            if (loc != null) {
              target = new URL(base, loc);
            }
            http.disconnect();
            // Redirection should be allowed only for HTTP and HTTPS
            // and should be limited to 5 redirections at most.
            if (target == null
                || !(target.getProtocol().equals("http") || target.getProtocol().equals("https"))
                || redirects >= 5) {
              throw new SecurityException("illegal URL redirect");
            }
            redir = true;
            conn = target.openConnection();
            redirects++;
          }
        }
      } catch (IOException io) {
        throw new IOException(io.getMessage());
      }
    } while (redir);
    return in;
  }

  public static InputSource getInputSourceByURL(URL url) throws IOException {
    InputSource inputSource = new InputSource(Utility.openConnection(url.openConnection()));
    URI uri = null;
    try {
      uri = url.toURI();
    } catch (URISyntaxException e) {
      // Ignore. Shouldn't happen!
    }
    inputSource.setSystemId(uri.toString());
    return inputSource;
  }

  public static List toURL(List targets) throws MalformedURLException {
    List results = new ArrayList<>();
    for (String t : targets) {
      results.add(toURL(t));
    }
    return results;
  }

  public static URL toURL(String target) throws MalformedURLException {
    URL url = null;
    try {
      url = new URL(target);
    } catch (MalformedURLException u) {
      File file = new File(target);
      url = file.toURI().normalize().toURL();
    }
    return url;
  }

  public static boolean isDir(String url) {
    try {
      return isDir(new URL(url));
    } catch (MalformedURLException e) {
      return false;
    }
  }

  public static boolean isDir(URL url) {
    File file = FileUtils.toFile(url);
    LOG.debug("isDir.file: {}, url:{}", file, url);
    LOG.debug("isDir.extension length: {}, url: {}",
        FilenameUtils.getExtension(url.toString()).length(), url);

    if (file == null || !file.exists()) {
      return false;
    }

    return file.isDirectory();
  }

  public static URL getParent(URL url) {
    try {
      return url.toURI().getPath().endsWith("/") ? url.toURI().resolve("..").toURL()
          : url.toURI().resolve(".").toURL();
    } catch (Exception e) {
      return null;
    }
  }

  public static boolean canRead(URL url) {
    try {
      url.openStream().close();
      return true;
    } catch (IOException io) {
      return false;
    }
  }

  public static boolean canRead(String url) {
    try {
      return canRead(new URL(url));
    } catch (MalformedURLException e) {
      return false;
    }
  }

  public static String removeLastSlash(String url) {
    if (url.endsWith("/")) {
      return url.substring(0, url.lastIndexOf("/"));
    }
    return url;
  }

  /**
   * Convenience method for disabling xinclude support throughout the core library.
   * 
   * @return
   */
  public static boolean supportXincludes() {
    return false;
  }

  /**
   * Replace backslashes with forward slashes. (URLs always use forward slashes.)
   *
   * @param sysid The input system identifier.
   * @return The same system identifier with backslashes turned into forward slashes.
   */
  public static String fixSlashes(String sysid) {
    return sysid.replace('\\', '/');
  }

  /**
   * Construct an absolute URI from a relative one, using the current base URI.
   *
   * @param sysid The (possibly relative) system identifier
   * @return The system identifier made absolute with respect to the current {@link #base}.
   * @throws MalformedURLException
   */
  public static String makeAbsolute(String base, String sysid) throws MalformedURLException {
    URL local = null;

    sysid = fixSlashes(sysid);

    try {
      local = new URL(new URL(base), sysid);
      return local.toString();
    } catch (MalformedURLException e) {
      throw new MalformedURLException("Malformed URL on system identifier: " + sysid);
    }
  }

  public static TargetType getTargetType(URL url) {
    if (isDir(url)) {
      return TargetType.DIRECTORY;
    }
    if (TargetExaminer.isTargetBundleType (url, true)) {
      return TargetType.BUNDLE;
    }
    if (TargetExaminer.isTargetCollectionType (url, true)) {
      return TargetType.COLLECTION;
    }
    return TargetType.FILE;
  }
  public static TargetType getTargetType(URL source, URL label) {
    int extIndex = source.getPath().lastIndexOf(".");
    if (isDir(source)) {
      return TargetType.DIRECTORY;
    }
    if (label != null 
        && -1 < extIndex
        && FileUtils.toFile(label).getPath().toLowerCase().endsWith(FileUtils.toFile(source).getPath().substring(extIndex).toLowerCase())) {
      if (TargetExaminer.isTargetBundleType (source, true)) {
        return TargetType.BUNDLE;
      }
      if (TargetExaminer.isTargetCollectionType (source, true)) {
        return TargetType.COLLECTION;
      }
    }
    return TargetType.FILE;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy