com.google.gwt.util.tools.Utility.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.util.tools.Utility.java

Source

/*
 * Copyright 2006 Google Inc.
 *
 * 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.
 */
package com.google.gwt.util.tools;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.net.Socket;
import java.net.URI;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

/**
 * A smattering of useful functions.
 */
public final class Utility {

    /**
     * Per thread MD5 instance.
     */
    private static final ThreadLocal<MessageDigest> perThreadMd5 = new ThreadLocal<MessageDigest>() {
        @Override
        protected MessageDigest initialValue() {
            try {
                return MessageDigest.getInstance("MD5");
            } catch (NoSuchAlgorithmException e) {
                return null;
            }
        };
    };

    public static char[] HEX_CHARS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
            'D', 'E', 'F' };

    private static String sInstallPath = null;

    /**
     * Helper that ignores exceptions during close, because what are you going to
     * do?
     */
    public static void close(InputStream is) {
        try {
            if (is != null) {
                is.close();
            }
        } catch (IOException e) {
        }
    }

    /**
     * Helper that ignores exceptions during close, because what are you going to
     * do?
     */
    public static void close(OutputStream os) {
        try {
            if (os != null) {
                os.close();
            }
        } catch (IOException e) {
        }
    }

    /**
     * Helper that ignores exceptions during close, because what are you going to
     * do?
     */
    public static void close(RandomAccessFile f) {
        if (f != null) {
            try {
                f.close();
            } catch (IOException e) {
            }
        }
    }

    /**
     * Helper that ignores exceptions during close, because what are you going to
     * do?
     */
    public static void close(Reader reader) {
        try {
            if (reader != null) {
                reader.close();
            }
        } catch (IOException e) {
        }
    }

    /**
     * Helper that ignores exceptions during close, because what are you going to
     * do?
     */
    public static void close(Socket socket) {
        try {
            if (socket != null) {
                socket.close();
            }
        } catch (IOException e) {
        }
    }

    /**
     * Helper that ignores exceptions during close, because what are you going to
     * do?
     */
    public static void close(Writer writer) {
        try {
            if (writer != null) {
                writer.close();
            }
        } catch (IOException e) {
        }
    }

    /**
     * @param parent Parent directory
     * @param fileName New file name
     * @param overwrite Is overwriting an existing file allowed?
     * @return Handle to the file
     * @throws IOException If the file cannot be created, or if the file already
     *           existed and overwrite was false.
     */
    public static File createNormalFile(File parent, String fileName, boolean overwrite, boolean ignore)
            throws IOException {
        File file = new File(parent, fileName);
        if (file.createNewFile()) {
            System.out.println("Created file " + file);
            return file;
        }

        if (!file.exists() || file.isDirectory()) {
            throw new IOException(file.getPath() + " : could not create normal file.");
        }

        if (ignore) {
            System.out.println(file + " already exists; skipping");
            return null;
        }

        if (!overwrite) {
            throw new IOException(file.getPath()
                    + " : already exists; please remove it or use the -overwrite or -ignore option.");
        }

        System.out.println("Overwriting existing file " + file);
        return file;
    }

    /**
     * @param parent Parent directory of the requested directory.
     * @param dirName Requested name for the directory.
     * @param create Create the directory if it does not already exist?
     * @return A {@link File} representing a directory that now exists.
     * @throws IOException If the directory is not found and/or cannot be created.
     */
    public static File getDirectory(File parent, String dirName, boolean create) throws IOException {
        File dir = new File(parent, dirName);
        boolean alreadyExisted = dir.exists();

        if (create) {
            // No need to check mkdirs result because we check for dir.exists()
            dir.mkdirs();
        }

        if (!dir.exists() || !dir.isDirectory()) {
            if (create) {
                throw new IOException(dir.getPath() + " : could not create directory.");
            } else {
                throw new IOException(dir.getPath() + " : could not find directory.");
            }
        }

        if (create && !alreadyExisted) {
            System.out.println("Created directory " + dir);
        }

        return dir;
    }

    /**
     * @param dirPath Requested path for the directory.
     * @param create Create the directory if it does not already exist?
     * @return A {@link File} representing a directory that now exists.
     * @throws IOException If the directory is not found and/or cannot be created.
     */
    public static File getDirectory(String dirPath, boolean create) throws IOException {
        return getDirectory(null, dirPath, create);
    }

    /**
     * Gets the contents of a file from the class path as a String. Note: this
     * method is only guaranteed to work for resources in the same class loader
     * that contains this {@link Utility} class.
     *
     * @param partialPath the partial path to the resource on the class path
     * @return the contents of the file
     * @throws IOException if the file could not be found or an error occurred
     *           while reading it
     */
    public static String getFileFromClassPath(String partialPath) throws IOException {
        InputStream in = Utility.class.getClassLoader().getResourceAsStream(partialPath);
        try {
            if (in == null) {
                throw new FileNotFoundException(partialPath);
            }
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            streamOut(in, os, 1024);
            return new String(os.toByteArray(), "UTF-8");
        } finally {
            close(in);
        }
    }

    public static String getInstallPath() {
        if (sInstallPath == null) {
            computeInstallationPath();
        }
        return sInstallPath;
    }

    /**
     * Generate MD5 digest.
     *
     * @param input input data to be hashed.
     * @return MD5 digest.
     */
    public static byte[] getMd5Digest(byte[] input) {
        MessageDigest md5 = perThreadMd5.get();
        md5.reset();
        md5.update(input);
        return md5.digest();
    }

    /**
     * A 4-digit hex result.
     */
    public static void hex4(char c, StringBuffer sb) {
        sb.append(HEX_CHARS[(c & 0xF000) >> 12]);
        sb.append(HEX_CHARS[(c & 0x0F00) >> 8]);
        sb.append(HEX_CHARS[(c & 0x00F0) >> 4]);
        sb.append(HEX_CHARS[c & 0x000F]);
    }

    /**
     * Creates a randomly-named temporary directory.
     *
     * @param baseDir base directory to contain the new directory. May be
     *          {@code null}, in which case the directory given by the
     *          {@code java.io.tmpdir} system property will be used.
     * @param prefix the initial characters of the new directory name
     * @return a newly-created temporary directory; the caller must delete this
     *          directory (either when done or on VM exit)
     */
    public static File makeTemporaryDirectory(File baseDir, String prefix) throws IOException {
        if (baseDir == null) {
            baseDir = new File(System.getProperty("java.io.tmpdir"));
        }
        // No need to check the result of this mkdirs call because
        // we will detect the subsequent failure
        baseDir.mkdirs();

        // Try this a few times due to non-atomic delete+mkdir operations.
        for (int tries = 0; tries < 3; ++tries) {
            File result = File.createTempFile(prefix, null, baseDir);
            if (!result.delete()) {
                throw new IOException("Couldn't delete temporary file " + result.getAbsolutePath()
                        + " to replace with a directory.");
            }
            if (result.mkdirs()) {
                // Success.
                return result;
            }
        }
        throw new IOException("Couldn't create temporary directory after 3 tries in " + baseDir.getAbsolutePath());
    }

    public static void streamOut(File file, OutputStream out, int bufferSize) throws IOException {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            streamOut(fis, out, bufferSize);
        } finally {
            com.google.gwt.util.tools.Utility.close(fis);
        }
    }

    public static void streamOut(InputStream in, OutputStream out, int bufferSize) throws IOException {
        assert (bufferSize >= 0);

        byte[] buffer = new byte[bufferSize];
        int bytesRead = 0;
        while (true) {
            bytesRead = in.read(buffer);
            if (bytesRead >= 0) {
                // Copy the bytes out.
                out.write(buffer, 0, bytesRead);
            } else {
                // End of input stream.
                return;
            }
        }
    }

    /**
     * Returns a string representation of the byte array as a series of
     * hexadecimal characters.
     *
     * @param bytes byte array to convert
     * @return a string representation of the byte array as a series of
     *         hexadecimal characters
     */
    public static String toHexString(byte[] bytes) {
        char[] hexString = new char[2 * bytes.length];
        int j = 0;
        for (int i = 0; i < bytes.length; i++) {
            hexString[j++] = HEX_CHARS[(bytes[i] & 0xF0) >> 4];
            hexString[j++] = HEX_CHARS[bytes[i] & 0x0F];
        }

        return new String(hexString);
    }

    public static void writeTemplateBinaryFile(File file, byte[] contents) throws IOException {

        FileOutputStream o = new FileOutputStream(file);
        o.write(contents);
        close(o);
    }

    public static void writeTemplateFile(File file, String contents, Map<String, String> replacements)
            throws IOException {

        String replacedContents = contents;
        Set<Entry<String, String>> entries = replacements.entrySet();
        for (Iterator<Entry<String, String>> iter = entries.iterator(); iter.hasNext();) {
            Entry<String, String> entry = iter.next();
            String replaceThis = entry.getKey();
            String withThis = entry.getValue();
            withThis = withThis.replaceAll("\\\\", "\\\\\\\\");
            withThis = withThis.replaceAll("\\$", "\\\\\\$");
            replacedContents = replacedContents.replaceAll(replaceThis, withThis);
        }

        PrintWriter pw = new PrintWriter(file);
        LineNumberReader lnr = new LineNumberReader(new StringReader(replacedContents));
        for (String line = lnr.readLine(); line != null; line = lnr.readLine()) {
            pw.println(line);
        }
        close(pw);
    }

    private static void computeInstallationPath() {
        try {
            String override = System.getProperty("gwt.devjar");
            if (override == null) {
                String partialPath = Utility.class.getName().replace('.', '/').concat(".class");
                URL url = Utility.class.getClassLoader().getResource(partialPath);
                if (url != null && "jar".equals(url.getProtocol())) {
                    String path = url.toString();
                    String jarPath = path.substring(path.indexOf("file:"), path.lastIndexOf('!'));
                    File devJarFile = new File(URI.create(jarPath));
                    if (!devJarFile.isFile()) {
                        throw new IOException("Could not find jar file; " + devJarFile.getCanonicalPath()
                                + " does not appear to be a valid file");
                    }

                    String dirPath = jarPath.substring(0, jarPath.lastIndexOf('/') + 1);
                    File installDirFile = new File(URI.create(dirPath));
                    if (!installDirFile.isDirectory()) {
                        throw new IOException("Could not find installation directory; "
                                + installDirFile.getCanonicalPath() + " does not appear to be a valid directory");
                    }

                    sInstallPath = installDirFile.getCanonicalPath().replace(File.separatorChar, '/');
                } else {
                    throw new IOException(
                            "Cannot determine installation directory; apparently not running from a jar");
                }
            } else {
                override = override.replace('\\', '/');
                int pos = override.lastIndexOf('/');
                if (pos < 0) {
                    sInstallPath = "";
                } else {
                    sInstallPath = override.substring(0, pos);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException("Installation problem detected, please reinstall GWT", e);
        }
    }

}