com.google.gwt.util.tools.Utility Maven / Gradle / Ivy
The newest version!
/*
* 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.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.StringReader;
import java.net.URI;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A smattering of useful functions.
*/
public final class Utility {
private static String sInstallPath = null;
/**
* A pattern that expresses version strings. It has two groups the prefix (a dotted integer
* sequence) and a suffix (a regular string)
*
* Examples: 1.6.7, 1.2_b10
*
*/
private static Pattern versionPattern =
Pattern.compile("([0-9]+(?:\\.[0-9]+)*)((?:_[a-zA-Z0-9]+)?)");
/**
* Helper that ignores exceptions during close, because what are you going to
* do?
*/
public static void close(AutoCloseable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (Exception 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;
}
/**
* 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(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;
}
}
}
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 replacements) throws IOException {
String replacedContents = contents;
Set> entries = replacements.entrySet();
for (Iterator> iter = entries.iterator(); iter.hasNext();) {
Entry 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);
}
}
/**
* Handles comparison between version numbers (the right way(TM)).
*
* Examples of version strings: 1.6.7, 1.2_b10
*
* @param v1 the first version to compare.
* @param v2 the second version to compare.
* @return a negative integer, zero, or a positive integer as the first argument is less than,
* equal to, or greater than the second.
* @throws IllegalArgumentException if the version number are not proper (i.e. the do not comply
* with the following regular expression
* [0-9]+(.[0-9]+)*(_[a-zA-Z0-9]+)?
*/
public static int versionCompare(String v1, String v2) {
Matcher v1Matcher = versionPattern.matcher(v1);
Matcher v2Matcher = versionPattern.matcher(v2);
if (!v1Matcher.matches() || !v2Matcher.matches()) {
throw new IllegalArgumentException(v1Matcher.matches() ? v2 : v1 + " is not a proper version"
+ " string");
}
String[] v1Prefix = v1Matcher.group(1).split("\\.");
String[] v2Prefix = v2Matcher.group(1).split("\\.");
for (int i = 0; i < v1Prefix.length; i++) {
if (v2Prefix.length <= i) {
return 1; // v1 > v2
}
int compare = Integer.parseInt(v1Prefix[i]) - Integer.parseInt(v2Prefix[i]);
if (compare != 0) {
return compare;
}
}
// So far they are equal (or v2 is longer than v1)
if (v2Prefix.length == v1Prefix.length) {
// then it is up to the suffixes
return v1Matcher.group(2).compareTo(v2Matcher.group(2));
}
// v2 is greater than v1,
return -1;
}
}