org.oscarehr.util.MiscUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.oscarehr.util.MiscUtils.java

Source

/**
 *
 * Copyright (c) 2005-2012. Centre for Research on Inner City Health, St. Michael's Hospital, Toronto. All Rights Reserved.
 * This software is published under the GPL GNU General Public License.
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * This software was written for
 * Centre for Research on Inner City Health, St. Michael's Hospital,
 * Toronto, Ontario, Canada
 */
package org.oscarehr.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;

/**
 * When using the shutdown hook...
 * <br /><br />
 * In the context of a normal JVM, you only need to use
 * the register and deregister methods where ever appropriate.
 * In your code you can periodically checkShutdownSignaled on long
 * running threads.
 * <br /><br />
 * In the conext of a application context such as a servlet
 * container. You should register and deregister in the context
 * startup/shutdown methods. In addition you should manually flag
 * set shutdownSignaled=true upon context shutdown as the jvm
 * itself may not be shutting down and no shutdown hook signal
 * maybe sent. Similarly you should set the shutdownSignaled=false
 * upon startup as it may have been set true by a previous context stop
 * even though the jvm itself has not restarted.
 */
public final class MiscUtils {

    public static final String ENCODING = "UTF-8";
    private static final Base64 base64 = new Base64(0);
    private static boolean shutdownSignaled = false;
    private static Thread shutdownHookThread = null;

    private static class ShutdownHookThread extends Thread {
        // can't have override until everyone uses jdk1.6
        // @Override
        public void run() {
            shutdownSignaled = true;
        }
    }

    public static void checkShutdownSignaled() throws ShutdownException {
        if (shutdownSignaled)
            throw (new ShutdownException());
    }

    /**
     * This method should in most cases only be called by the context startup listener.
     */
    public static synchronized void registerShutdownHook() {
        if (shutdownHookThread == null) {
            shutdownHookThread = new ShutdownHookThread();
            Runtime.getRuntime().addShutdownHook(shutdownHookThread);
        }
    }

    public static synchronized void deregisterShutdownHook() {
        if (shutdownHookThread != null) {
            Runtime.getRuntime().removeShutdownHook(shutdownHookThread);
            shutdownHookThread = null;
        }
    }

    /**
     * This menthod should only ever be called by a context startup listener. Other than that, the shutdown signal should be set by the shutdown hook.
     */
    protected static void setShutdownSignaled(boolean shutdownSignaled) {
        MiscUtils.shutdownSignaled = shutdownSignaled;
    }

    public static byte[] propertiesToXmlByteArray(Properties p) throws IOException {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        p.storeToXML(os, null);
        return (os.toByteArray());
    }

    public static Properties xmlByteArrayToProperties(byte[] b) throws IOException {
        Properties p = new Properties();

        ByteArrayInputStream is = new ByteArrayInputStream(b);
        p.loadFromXML(is);

        return (p);
    }

    /**
     * This method will set the calendar to the beginning of the month, i.e. day=1, hour=0, minute=0, sec=0, ms=0. It will return the same instance passed in (not a clone of it).
     */
    public static Calendar setToBeginningOfMonth(Calendar cal) {
        cal.set(Calendar.DAY_OF_MONTH, 1);
        return (setToBeginningOfDay(cal));
    }

    /**
     * This method will set the calenders hour/min/sec//milliseconds all to 0.
     */
    public static Calendar setToBeginningOfDay(Calendar cal) {
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        // force calculation / materialisation of actual time.
        cal.getTimeInMillis();

        return (cal);
    }

    public static GregorianCalendar toCalendar(Date date) {
        if (date == null)
            return (null);

        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(date);
        return (cal);
    }

    /**
     * Null safe toDate
     */
    public static Date toDate(Calendar cal) {
        if (cal == null)
            return (null);

        return (cal.getTime());
    }

    /**
     * This method should only really be called once per context in the context startup listener.
     * 
     * The purpose of this is to allow customisations to the logging on a per-deployment basis with out
     * needing to commit the configuration to cvs while at the same time allowing you to keep your
     * configuration through multiple deployments. As an example, if you modified the WEB-INF/classes/log4j.xml
     * either you have to commit that and everyone gets your configuration, or you don't commit it,
     * every new deploy will over write changes you made locally to your log4j.xml. This helper method alleviates this problem.
     * 
     * The functionality of this is as follows :
     * 
     * The system configuration parameter "log4j.override.configuration" specifies the file to use
     * to override overlay on top of the default log4j.xml file. This can be a relative or absolute path.
     * An example maybe "/home/foo/my_override_log4j.xml"
     * 
     * The filename specified is allowed to have a special placeholder ${contextName}, this allows the
     * system variable to be used when multiple oscar contexts exist. As an example it maybe
     * "/home/foo/${contextName}_log4.xml". During runtime, when each context startup calls this method
     * the ${contextName} is replaced with the contextPath. So as an example of you had 2 contexts called
     * "asdf" and "zxcv" respectively, it will look for /home/foo/asdf_log4j.xml and /home/foo/zxcv_log4j.xml.
     */
    protected static void addLoggingOverrideConfiguration(String contextPath) {
        String configLocation = System.getProperty("log4j.override.configuration");
        if (configLocation != null) {
            if (configLocation.contains("${contextName}")) {
                if (contextPath != null) {
                    if (contextPath.length() > 0 && contextPath.charAt(0) == '/')
                        contextPath = contextPath.substring(1);
                    if (contextPath.length() > 0 && contextPath.charAt(contextPath.length() - 1) == '/')
                        contextPath = contextPath.substring(0, contextPath.length() - 2);
                }

                configLocation = configLocation.replace("${contextName}", contextPath);
            }

            getLogger().info("loading additional override logging configuration from : " + configLocation);
            DOMConfigurator.configureAndWatch(configLocation);
        }
    }

    /**
     * This method will return a logger instance which has the name based on the class that's calling this method.
     */
    public static Logger getLogger() {
        StackTraceElement[] ste = Thread.currentThread().getStackTrace();
        String caller = ste[2].getClassName();
        return (Logger.getLogger(caller));
    }

    /*
     * Null safe getSize()
     */
    public static Integer getSize(List list) {
        if (list == null)
            return null;
        return list.size();
    }

    //return a vector which contains distinctive string elements
    public static Vector findUniqueElementVector(Vector v) {
        Vector retVec = new Vector();
        for (int i = 0; i < v.size(); i++) {
            if (!retVec.contains(v.get(i)))
                retVec.add(v.get(i));
        }
        return retVec;
    }

    /**
     * You better have a good reason for using this. This ain't something you normally do.
     */
    public static final byte[] serialiseToByteArray(Serializable s) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(s);

        return (baos.toByteArray());
    }

    /**
     * You better have a good reason for using this. This ain't something you normally do.
     */
    public static final Serializable deserialiseFromByteArray(byte b[]) throws IOException, ClassNotFoundException {
        return ((Serializable) (new ObjectInputStream(new ByteArrayInputStream(b))).readObject());
    }

    public static String encodeToBase64String(String s) throws UnsupportedEncodingException {
        return (new String(base64.encode(s.getBytes(ENCODING)), ENCODING));
    }

    public static String decodeBase64StoString(String s) throws UnsupportedEncodingException {
        return (new String(base64.decode(s.getBytes(ENCODING)), ENCODING));
    }

    public static String encodeToBase64String(byte[] b) throws UnsupportedEncodingException {
        return (new String(base64.encode(b), ENCODING));
    }

    public static byte[] decodeBase64(String s) throws UnsupportedEncodingException {
        return (base64.decode(s.getBytes(ENCODING)));
    }

    public static String getUserNameNoDomain(String s) {
        if (s == null)
            return (null);

        int indexOfAt = s.indexOf('@');
        if (indexOfAt != -1)
            s = s.substring(0, indexOfAt);
        return (s);
    }
}