esg.common.Utils.java Source code

Java tutorial

Introduction

Here is the source code for esg.common.Utils.java

Source

/***************************************************************************
*                                                                          *
*  Organization: Lawrence Livermore National Lab (LLNL)                    *
*   Directorate: Computation                                               *
*    Department: Computing Applications and Research                       *
*      Division: S&T Global Security                                       *
*        Matrix: Atmospheric, Earth and Energy Division                    *
*       Program: PCMDI                                                     *
*       Project: Earth Systems Grid (ESG) Data Node Software Stack         *
*  First Author: Gavin M. Bell (gavin@llnl.gov)                            *
*                                                                          *
****************************************************************************
*                                                                          *
*   Copyright (c) 2009, Lawrence Livermore National Security, LLC.         *
*   Produced at the Lawrence Livermore National Laboratory                 *
*   Written by: Gavin M. Bell (gavin@llnl.gov)                             *
*   LLNL-CODE-420962                                                       *
*                                                                          *
*   All rights reserved. This file is part of the:                         *
*   Earth System Grid Federation (ESGF) Data Node Software Stack           *
*                                                                          *
*   For details, see http://esgf.org/esg-node/                             *
*   Please also read this link                                             *
*    http://esgf.org/LICENSE                                               *
*                                                                          *
*   * Redistribution and use in source and binary forms, with or           *
*   without modification, are permitted provided that the following        *
*   conditions are met:                                                    *
*                                                                          *
*   * Redistributions of source code must retain the above copyright       *
*   notice, this list of conditions and the disclaimer below.              *
*                                                                          *
*   * Redistributions in binary form must reproduce the above copyright    *
*   notice, this list of conditions and the disclaimer (as noted below)    *
*   in the documentation and/or other materials provided with the          *
*   distribution.                                                          *
*                                                                          *
*   Neither the name of the LLNS/LLNL nor the names of its contributors    *
*   may be used to endorse or promote products derived from this           *
*   software without specific prior written permission.                    *
*                                                                          *
*   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS    *
*   "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 LAWRENCE    *
*   LIVERMORE NATIONAL SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR     *
*   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,           *
*   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT       *
*   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF       *
*   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND    *
*   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,     *
*   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT     *
*   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF     *
*   SUCH DAMAGE.                                                           *
*                                                                          *
***************************************************************************/

/**
   Description:
    
**/
package esg.common;

import java.util.regex.Pattern;
import java.util.regex.Matcher;

import java.net.Socket;
import java.net.InetSocketAddress;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.impl.*;

import java.util.concurrent.atomic.AtomicLong;

public class Utils {

    private static final Log log = LogFactory.getLog(Utils.class);

    private static AtomicLong msgCounter = new AtomicLong(0);
    private static String myHostname = null;
    private static String myServiceUrl = null;
    private static final String httpSchemeRegex = "(http)(://.*)";
    private static final Pattern httpSchemePattern = Pattern.compile(httpSchemeRegex, Pattern.CASE_INSENSITIVE);
    private static final String httpsSchemeRegex = "(https)(://.*)";
    private static final Pattern httpsSchemePattern = Pattern.compile(httpsSchemeRegex, Pattern.CASE_INSENSITIVE);
    private static final String urlRegex = "http[s]?://([^:/]*)(:(?:[0-9]*))?/(.*/)*(.*$)";
    private static final Pattern urlPattern = Pattern.compile(urlRegex, Pattern.CASE_INSENSITIVE);
    private static final String serviceUrlRegex = "http[s]?://([^:/]*)(:(?:[0-9]*))?/esgf-node-manager/node";
    private static final Pattern serviceUrlPattern = Pattern.compile(serviceUrlRegex, Pattern.CASE_INSENSITIVE);
    private static QuickHash quickHash = null;

    //For version compare methods...
    private static final Pattern versionPattern = Pattern.compile("[v.-]([0-9]*)");

    public static long nextSeq() {
        return msgCounter.getAndIncrement();
    }

    public static String getNodeID() {
        String nodeID = null;
        if (null != nodeID) {
            return nodeID;
        }
        try {
            nodeID = java.net.InetAddress.getLocalHost().getHostAddress();
        } catch (java.net.UnknownHostException ex) {
            log.error(ex);
        }
        //NOTE: Doing the call to "toString" on purpose to force a null
        //pointer exception the return value should NEVER be null!
        return nodeID.toString();
    }

    public static boolean poke(String host, int port) {
        return poke(host, port, 200);
    }

    public static boolean poke(String host, int port, int timeout) {
        boolean ret = false;
        Socket socket = null;
        try {
            (socket = new Socket()).connect(new InetSocketAddress(java.net.InetAddress.getByName(host), port),
                    timeout);
            socket.close();
            ret = true;
        } catch (Throwable t) {
            log.error(t.getMessage());
        } finally {
            try {
                socket.close();
            } catch (Throwable t) {
            }
        }
        return ret;
    }

    public static String hashSum(String plaintext) {
        try {
            if (quickHash == null)
                quickHash = new QuickHash();
            return quickHash.sum(plaintext);
        } catch (Throwable t) {
            System.out.println(t.getMessage());
            return null;
        }
    }

    public static String getFQDN() {
        try {
            if (myHostname == null) {
                myHostname = java.net.InetAddress.getLocalHost().getCanonicalHostName();
            }
        } catch (java.net.UnknownHostException ex) {
            log.error(ex);
        }
        return myHostname;
    }

    public static String getMyServiceUrl() {
        if (myServiceUrl == null)
            myServiceUrl = asServiceUrl(getFQDN());
        return myServiceUrl;
    }

    public static String asServiceUrl(String hostname, boolean secured) {
        return "http" + (secured ? "s" : "") + "://" + hostname + "/esgf-node-manager/node";
    }

    public static String asServiceUrl(String hostname) {
        return asServiceUrl(hostname, false);
    }

    public static String asSSLUrl(String url) {
        if (url.startsWith("https"))
            return url;
        Matcher m = httpSchemePattern.matcher(url);
        if (m.find())
            url = "https" + m.group(2);
        return url;
    }

    //Note: Uses Regex to check for https scheme instead of String's startsWith()...
    public static String asSSLUrlx(String url) {
        if ((httpsSchemePattern.matcher(url)).find())
            return url;
        Matcher m = httpSchemePattern.matcher(url);
        if (m.find())
            url = "https" + m.group(2);
        return url;
    }

    //NOTE: If there is a point where we want to support running the
    //node manager on another port that 80 Then we may want to always
    //consider the port part of the hostname.  In which case we need
    //to change the regex above for the urlPattern to include the port
    //in the hostname.  That should do it. Then foohost:80 would be
    //diff than foohost:8080 (at the moment we only return foohost
    //regardless of port)
    //Affected code would include callers of the ESGConnector...
    public static String asHostname(String serviceUrl) {
        Matcher m = urlPattern.matcher(serviceUrl);
        if (m.find())
            return m.group(1);
        return null;
    }

    public static boolean isLegalUrl(String urlCandidate) {
        return (urlPattern.matcher(urlCandidate)).find();
    }

    public static boolean isLegalServiceUrl(String urlCandidate) {
        return (serviceUrlPattern.matcher(urlCandidate)).find();
    }

    //------------------------------------------------------------------------------------
    //Util version string comparison functions...
    //------------------------------------------------------------------------------------

    /**
       Compares two version strings and returns comparator compatible
       return values indicating relationship between the versions.
       This uses the Util.versionPattern regex to parse pattern values
       expected in the form v#.#.# (hyphens are also allowed as
       delimiters).
        
       @param candidate the first version value to compare
       @param reference the second version value to compare
       @throws InvalideVersionStringException runtime exception thrown when a value cannot be numerically parsed.
       @return 1 if candidate > reference; -1 if candidate < reference; 0 if candidate = refernece;
     */
    public static int versionCompare(String candidate, String reference)
            throws esg.common.InvalidVersionStringException {
        if (candidate.equals(reference))
            return 0;
        return versionCompare(candidate, versionPattern.matcher(candidate), reference,
                versionPattern.matcher(reference));
    }

    /**
       In an attempt to be a bit more efficient.  If there is a lot of
       comparing that needs to be done it is better to pass in
       matchers, rather than have the matchers be instantiated by the
       Pattern every time a comparison is done.  Matchers are not
       thread safe therefore this method is NOT thread safe.  So be
       aware.  If in doubt call the other version of this method.
        
       @param candidate the first version value to compare
       @param c_matcher a Matcher object from a Pattern that knows how to tokenize the version values
       @param reference the second version value to compare
       @param r_matcher a Matcher object from a Pattern that knows how to tokenize the version values
       @throws InvalideVersionStringException runtime exception thrown when a value cannot be numerically parsed.
       @return 1 if candidate > reference; -1 if candidate < reference; 0 if candidate = refernece;
     */
    public static int versionCompare(String candidate, Matcher c_matcher, String reference, Matcher r_matcher)
            throws esg.common.InvalidVersionStringException {
        c_matcher.reset(candidate);
        r_matcher.reset(reference);

        int c, r = 0;
        try {
            while (c_matcher.find() && r_matcher.find()) {
                c = Integer.parseInt(c_matcher.group(1));
                r = Integer.parseInt(r_matcher.group(1));

                //log.trace("Comparing "+c+" and "+r);
                if (c > r)
                    return 1;
                else if (c < r)
                    return -1;
            }

            //When version positions don't line up...
            int c_len = candidate.length();
            int r_len = reference.length();
            //log.trace("candidate length = "+c_len);
            //log.trace("reference length = "+r_len);
            if (c_len > r_len) {
                c_matcher.reset(candidate.substring(r_len));
                while (c_matcher.find()) {
                    if (Integer.parseInt(c_matcher.group(1)) > 0) {
                        return 1;
                    }
                }
            }
            if (c_len < r_len) {
                r_matcher.reset(reference.substring(c_len));
                while (r_matcher.find()) {
                    if (Integer.parseInt(r_matcher.group(1)) > 0) {
                        return -1;
                    }
                }
            }
            return 0;
        } catch (NumberFormatException e) {
            log.error("Improper version string! " + e.getMessage());
            throw new InvalidVersionStringException(e);
        } catch (Exception e) {
            log.error("Improper version string! " + e.getMessage());
            throw new InvalidVersionStringException(e);
        }
    }

}