package tools.util; | |
//import com.crossgain.util.AssertError; | |
import java.io.*; | |
import java.net.ServerSocket; | |
import java.net.Socket; | |
import java.net.URL; | |
import java.net.URLConnection; | |
import java.net.JarURLConnection; | |
import java.security.MessageDigest; | |
import java.sql.ResultSet; | |
import java.sql.SQLException; | |
import java.sql.Statement; | |
import java.sql.DriverManager; | |
import java.sql.Connection; | |
import java.util.Enumeration; | |
import java.util.HashMap; | |
import java.util.Map.Entry; | |
import java.util.Vector; | |
import java.util.Iterator; | |
import java.util.regex.Pattern; | |
import java.util.regex.Matcher; | |
import java.util.zip.ZipFile; | |
import java.util.zip.ZipEntry; | |
/* | |
import javax.servlet.ServletRequest; | |
import javax.servlet.http.HttpServletRequest; | |
import org.w3c.dom.*; | |
*/ | |
/** | |
* Utilities to copy files, directories, etc. | |
* | |
* @author charles.scharr@bea.com | |
* @author kevin.krouse@bea.com | |
* @author raju.subramanian@bea.com | |
*/ | |
public class Util | |
{ | |
private static byte[] _byteBuffer = new byte[32768]; | |
private static char[] _charBuffer = new char[32768]; | |
private static boolean filteredStackTrace = true; | |
/** | |
* Read the contents of the given file into a String. | |
*/ | |
public static String read(File file) | |
throws IOException | |
{ | |
FileInputStream fis = new FileInputStream(file); | |
return read(new InputStreamReader(fis, "UTF8")); | |
} | |
/** | |
* Read the contents of the given input stream into a String. This will | |
* also close the stream. | |
*/ | |
public static String read(InputStream in) | |
throws IOException | |
{ | |
return read(new InputStreamReader(in, "UTF8")); | |
} | |
/** | |
* Read the contents in the given <code>Reader</code> into a String. This | |
* will also close the reader. | |
*/ | |
public static String read(Reader in) | |
throws IOException | |
{ | |
try | |
{ | |
StringBuffer sb = new StringBuffer(_charBuffer.length); | |
int amount = 0; | |
while (true) | |
{ | |
synchronized (_charBuffer) | |
{ | |
amount = in.read(_charBuffer); | |
if (amount != -1) | |
sb.append(_charBuffer, 0, amount); | |
else | |
break; | |
} | |
} | |
return sb.toString(); | |
} | |
finally | |
{ | |
close(in); | |
} | |
} | |
public static String read(Reader in, int length) | |
throws IOException | |
{ | |
BufferedReader bin = null; | |
try | |
{ | |
bin = new BufferedReader(in, length); | |
char[] s = new char[length]; | |
bin.read(s, 0, length); | |
return new String(s); | |
} | |
finally | |
{ | |
close(bin); | |
} | |
} | |
/** | |
* Read the contents of the given file line by line into a String array | |
* | |
* If the second argument is true, then all whitespace lines at the end will | |
* be removed from the array | |
*/ | |
public static String[] readIntoArray(File file, boolean trimLines) | |
throws IOException | |
{ | |
BufferedReader reader = new BufferedReader(new FileReader(file)); | |
Vector v = new Vector(); | |
while (true) | |
{ | |
String s = reader.readLine(); | |
if (s == null) break; | |
v.addElement(s); | |
} | |
reader.close(); | |
// Discard all trailing lines that are only whitespaces.. | |
if (trimLines) | |
{ | |
int i = v.size(); | |
while (--i >= 0) | |
if (isWhiteSpace((String) v.get(i))) | |
v.removeElementAt(i); | |
} | |
String[] strArray = new String[v.size()]; | |
v.copyInto(strArray); | |
return strArray; | |
} | |
public static void copy(InputStream in, OutputStream out) | |
throws IOException | |
{ | |
try | |
{ | |
int amount = 0; | |
while (true) | |
{ | |
synchronized (_byteBuffer) | |
{ | |
amount = in.read(_byteBuffer); | |
if (amount == -1) | |
break; | |
out.write(_byteBuffer, 0, amount); | |
} | |
} | |
} | |
finally | |
{ | |
close(in); | |
close(out); | |
} | |
} | |
/** | |
* Copy a stream to a file. | |
*/ | |
public static void copyToFile(InputStream in, File toFile, | |
boolean overwrite) | |
throws IOException | |
{ | |
if (toFile.exists() && !overwrite) | |
return; | |
// create any parent directories | |
File parent = toFile.getParentFile(); | |
if (parent != null) | |
parent.mkdirs(); | |
// creates a new file only if it doesn't exist | |
toFile.createNewFile(); | |
copy(in, new FileOutputStream(toFile)); | |
} | |
/** | |
* Copy URL to file. | |
*/ | |
public static void copyToFile(URL url, File toFile, | |
boolean replaceNewer) | |
throws IOException | |
{ | |
Log.debug("copyToFile(url=" + url + ",\n toFile=" + toFile + ")"); | |
URLConnection conn = url.openConnection(); | |
if (toFile.exists() && | |
toFile.lastModified() > conn.getLastModified() && | |
!replaceNewer) | |
return; | |
copyToFile(conn.getInputStream(), toFile, true); | |
} | |
/** | |
* Copy file to file. | |
*/ | |
public static void copyToFile(File fromFile, File toFile, | |
boolean replaceNewer) | |
throws IOException | |
{ | |
Log.debug("copyToFile(fromFile=" + fromFile + ",\n toFile=" + toFile + | |
")"); | |
// don't replace newer files unless flag is set | |
if (toFile.exists() && | |
toFile.lastModified() > fromFile.lastModified() && | |
!replaceNewer) | |
return; | |
copyToFile(new FileInputStream(fromFile), | |
toFile, true); | |
} | |
/** | |
* Copy file to a dir. | |
*/ | |
public static void copyToDir(File fromFile, File toDir, | |
boolean replaceNewer) | |
throws IOException | |
{ | |
//System.out.println("copyToDir(fromFile=" + fromFile + | |
//",\n toDir=" + toDir + ")"); | |
toDir.mkdirs(); | |
copyToFile(fromFile, new File(toDir, fromFile.getName()), | |
replaceNewer); | |
} | |
/** | |
* Copy URL to a dir. | |
*/ | |
public static void copyToDir(URL url, File toDir, | |
boolean replaceNewer) | |
throws IOException | |
{ | |
//System.out.println("copyToDir(url=" + url + | |
//",\n toDir=" + toDir + ")"); | |
toDir.mkdirs(); | |
copyToFile(url, new File(toDir, url.getFile()), | |
replaceNewer); | |
} | |
/** | |
* Recursively copy a dir to a new dir. Creates target tree if needed. | |
*/ | |
public static void copyDirToDir(File fromDir, File toDir, | |
boolean replaceNewer, final String[] exclude) | |
throws IOException | |
{ | |
//System.out.println("copyDirToDir(fromDir=" + fromDir + | |
//",\n toDir=" + toDir + ")"); | |
File[] fs = fromDir.listFiles(); | |
COPY_FILE_LOOP: | |
for (int i = 0; i < fs.length; i++) | |
{ | |
// exclude based only on last part of file name | |
String name = fs[i].getName(); | |
if (exclude != null) | |
{ | |
for (int j = 0; j < exclude.length; ++j) | |
{ | |
if (name.equals(exclude[j])) | |
continue COPY_FILE_LOOP; | |
} | |
} | |
if (fs[i].isFile()) | |
{ | |
copyToDir(fs[i], toDir, replaceNewer); | |
} else | |
{ | |
copyDirToDir(fs[i], new File(toDir, fs[i].getName()), | |
replaceNewer, exclude); | |
} | |
} | |
} | |
/** | |
* Recursively copy a jar dir entry to a new dir. This is expensive since | |
* we have to iterate over all the entries in the .zip/.jar file. | |
* The <code>fromDir</code> parameter must end in '/'. | |
*/ | |
public static void copyDirToDir(ZipFile zip, String fromDir, | |
File toDir, boolean replaceNewer, final String[] exclude) | |
throws IOException | |
{ | |
//System.out.println("copyDirToDir(zip=" + zip + | |
//", fromDir=" + fromDir + | |
//", toDir=" + toDir + ")"); | |
if (!fromDir.endsWith("/")) | |
return; | |
Enumeration _enum = zip.entries(); | |
COPY_JAR_LOOP: | |
while (_enum.hasMoreElements()) | |
{ | |
ZipEntry entry = (ZipEntry) _enum.nextElement(); | |
//System.out.println(" entry = " + entry.getName()); | |
// skip directories | |
if (entry.isDirectory()) | |
continue; | |
if (!entry.getName().startsWith(fromDir)) | |
continue; | |
String entryFile = entry.getName().substring(fromDir.length()); | |
// FIXME: exclude files matching any pattern in exclude array | |
// use this class' loader to obtain the resource | |
URL url = Util.class.getResource("/" + entry.getName()); | |
if (url == null) | |
{ | |
throw new java.io.IOException("Resource not found: " + | |
entry.toString()); | |
} | |
copyToFile(url, new File(toDir, entryFile), replaceNewer); | |
} | |
} | |
/** | |
* Copy a dir url to a new dir. | |
*/ | |
public static void copyDirToDir(URL url, File toDir, | |
boolean replaceNewer, String[] exclude) | |
throws IOException | |
{ | |
Log.debug("copyDirToDir(url=" + url + ", toDir=" + toDir + ")"); | |
// url must end in '/' | |
if (!url.getFile().endsWith("/")) | |
return; | |
if ("file".equals(url.getProtocol())) | |
{ | |
copyDirToDir(new File(url.getPath()), toDir, | |
replaceNewer, exclude); | |
} else if ("jar".equals(url.getProtocol())) | |
{ | |
JarURLConnection conn = (JarURLConnection) url.openConnection(); | |
copyDirToDir(conn.getJarFile(), conn.getEntryName(), | |
toDir, replaceNewer, exclude); | |
} else if ("zip".equals(url.getProtocol())) | |
{ | |
URL newUrl = new URL("jar:file:" + url.getPath()); | |
Log.debug("changed zip url to = " + newUrl); | |
copyDirToDir(newUrl, toDir, replaceNewer, exclude); | |
} else | |
{ | |
throw new IOException("Protocol not supported yet: " + | |
url.getProtocol()); | |
} | |
} | |
/** | |
* Copy a dir to a new dir. | |
*/ | |
public static void copyDirToDir(File fromDir, File toDir, | |
boolean replaceNewer) | |
throws IOException | |
{ | |
copyDirToDir(fromDir, toDir, replaceNewer, null); | |
} | |
/** | |
* Recursively remove a directory and it's contents. | |
*/ | |
public static void remove(String file) | |
{ | |
remove(new File(file)); | |
} | |
/** | |
* Recursively remove a directory and it's contents. | |
*/ | |
public static void remove(File file) | |
{ | |
if (file == null || !file.exists()) | |
return; | |
if (file.isFile()) | |
removeFile(file); | |
else if (file.isDirectory()) | |
removeDir(file); | |
} | |
/** | |
* Remove a directory's contents. | |
*/ | |
private static void removeDir(File dir) | |
{ | |
File[] entries = dir.listFiles(); | |
if (entries == null) | |
{ | |
Log.fatal("IO Error or dir doesn't exist: " + dir); | |
return; | |
} | |
for (int i = 0; i < entries.length; ++i) | |
remove(entries[i]); | |
Log.debug("removing dir: " + dir.toString()); | |
dir.delete(); | |
} | |
/** | |
* Remote a file. | |
*/ | |
private static void removeFile(File file) | |
{ | |
Log.debug("removing file: " + file.toString()); | |
file.delete(); | |
} | |
/** | |
* Checks if the two files are identical | |
* If the 'trim' is true then any blank lines at the end of the files are ignored | |
* | |
* Return: A String containing the Differences between the two files | |
* null if the files are identical | |
*/ | |
public static String compareFiles(String fileA, | |
String fileB, | |
boolean trim) | |
throws IOException | |
{ | |
return new Diff(true).compareFiles(fileA, fileB); | |
} | |
/** | |
* @deprecated This is really overkill. | |
* | |
* Parses command-line arguments into a Hashtable. | |
* <pre> | |
* command-line : ( arg-assignment )* the-rest | |
* arg-assignment : option-name option-value? | |
* option-name : "any string with a leading '-' " | |
* option-value : "any string without a leading '-' " | |
* the-rest : "any args after options ended" | |
* | |
* The following rules are used: | |
* - If an option appears multiple times, then its value is OVERWRITTEN! | |
* - If no value is given for an option, then the Hashtable entry contains a Boolean object TRUE | |
* - the rest of the arguments are stored as an array under the special key @REST | |
* - @REST value is always filled, at least with an EMPTY ARRAY (and not a null!!!) | |
* - An option of "-" ends option parsing. Use this when a value-less option is followed by the-rest | |
* | |
* Examples: (1) "-foo bar -goo zabba -boo -hoo" is parsed as | |
* {foo -> bar, goo -> zabba, -boo -> TRUE, -hoo -> TRUE} | |
* (2) "-foo bar -foo bar2 aaa bbb ccc" is parsed as { foo -> bar2, @REST -> [aaa,bbb,ccc] } | |
* | |
* Rationale: | |
* The above grammar and rules are less powerful than those given by gnu.getopt, but | |
* are easier to use for our purposes | |
* </pre> | |
*/ | |
public static HashMap parseArgs(String args[]) | |
{ | |
HashMap ht = new HashMap(); | |
int k; | |
int n = args.length; | |
for (k = 0; k < n; k++) | |
{ | |
// Stop option processing if not an option or is the single character '-' | |
if (args[k].startsWith("-")) | |
{ | |
// eat the '-' and end option processing if it's just a '-' | |
if (args[k].length() == 1) | |
{ | |
k++; | |
break; | |
} | |
String opt = args[k].substring(1); // skip - | |
String optarg = null; | |
if ((k < n - 1) && !args[k + 1].startsWith("-")) | |
{ | |
// got an option value | |
optarg = args[k + 1]; | |
k++; | |
} | |
ht.put(opt, | |
(null != optarg) ? | |
(Object) optarg : | |
(Object) Boolean.TRUE); | |
} else | |
{ | |
break; | |
} | |
} | |
// either we have run out of options or | |
// we have hit the first non-option argument | |
// | |
int n_rest = n - k; | |
String rest[] = new String[n_rest]; | |
int j; | |
for (j = 0; k < n; j++, k++) | |
{ | |
rest[j] = args[k]; | |
} | |
ht.put("@REST", rest); | |
return ht; | |
} | |
/** | |
* @deprecated This is really overkill. | |
* | |
* This is a subset of the above parser. It assumes only boolean options, but | |
* allows arguments to be interspersed with options. | |
* | |
* Parses command-line arguments into a Hashtable using the following grammar: | |
* command-line : ( option-name | argument )* | |
* option-name : "any string with a leading '-' " | |
* argument : "any string without a leading '-' " | |
* | |
* The following rules are used: | |
* - If an option appears multiple times, then its value is OVERWRITTEN! | |
* - The Hashtable entry for any option contains a Boolean object TRUE | |
* - the rest of the arguments are stored as an array under the special key @REST | |
* - @REST value is always filled, at least with an EMPTY ARRAY (and not a null!!!) | |
* - An option of "-" ends option parsing. Use this before an argument that must begin with a '-' | |
* | |
* Examples: (1) "-foo bar -goo zabba -boo -hoo" is parsed as | |
* {foo -> TRUE, goo -> TRUE, -boo -> TRUE, -hoo -> TRUE, @REST -> [bar,zabba]} | |
* (2) "-foo bar -foo bar2 aaa - -bbb -ccc" | |
* is parsed as { foo -> TRUE, @REST -> [bar,bar2,aaa,-bbb,-ccc] } | |
* | |
* Rationale: | |
* parseArgs does not have a way of specifying a trailing boolean option followed by an | |
* argument except through the '-' hack. It is unable to implement, for example, the argument scanning of | |
* SystemSchemaBooter without forcing a change in the command-line syntax | |
*/ | |
public static HashMap parseOptions(String args[]) | |
{ | |
HashMap ht = new HashMap(); | |
int k; | |
int n = args.length; | |
int nOptions = 0; | |
for (k = 0; k < n; k++) | |
{ | |
// Stop option processing if not an option or is the single character '-' | |
if (args[k].startsWith("-")) | |
{ | |
nOptions++; | |
// eat the '-' and end option processing if it's just a '-' | |
if (args[k].length() == 1) | |
{ | |
k++; | |
break; | |
} | |
String opt = args[k].substring(1); // skip - | |
ht.put(opt, (Object) Boolean.TRUE); | |
} | |
} | |
// either we have run out of options or | |
// we have hit a single '-' | |
// | |
int n_rest = n - nOptions; | |
String rest[] = new String[n_rest]; | |
boolean bIgnoreOptions = false; | |
int j = 0; | |
// Rescan the args and put non-options in the rest array | |
for (k = 0; k < n; k++) | |
{ | |
if (bIgnoreOptions || !args[k].startsWith("-")) | |
{ | |
rest[j++] = args[k]; | |
} else if (args[k].length() == 1) | |
{ | |
bIgnoreOptions = true; | |
} | |
} | |
ht.put("@REST", rest); | |
return ht; | |
} | |
/** | |
* Close a possibly null output stream. Ignore any exceptions. | |
*/ | |
static public void close(OutputStream stream) | |
{ | |
if (stream == null) | |
return; | |
try | |
{ | |
stream.close(); | |
} | |
catch (Exception ignore) | |
{ | |
} | |
} | |
/** | |
* Close a possibly null input stream. Ignore any exceptions. | |
*/ | |
static public void close(InputStream stream) | |
{ | |
if (stream == null) | |
return; | |
try | |
{ | |
stream.close(); | |
} | |
catch (Exception ignore) | |
{ | |
} | |
} | |
/** | |
* Close a possibly null reader. Ignore any exceptions. | |
*/ | |
static public void close(Reader reader) | |
{ | |
if (reader == null) | |
return; | |
try | |
{ | |
reader.close(); | |
} | |
catch (Exception ignore) | |
{ | |
} | |
} | |
/** | |
* Close a possibly null writer. Ignore any exceptions. | |
*/ | |
static public void close(Writer writer) | |
{ | |
if (writer == null) | |
return; | |
try | |
{ | |
writer.close(); | |
} | |
catch (Exception ignore) | |
{ | |
} | |
} | |
/** | |
* Close a possibly null server socket. Ignore any exceptions. | |
*/ | |
static public void close(ServerSocket socket) | |
{ | |
if (socket == null) | |
return; | |
try | |
{ | |
socket.close(); | |
} | |
catch (Exception ignore) | |
{ | |
} | |
} | |
/** | |
* Close a possibly null socket. Ignore any exceptions. | |
*/ | |
static public void close(Socket socket) | |
{ | |
if (socket == null) | |
return; | |
try | |
{ | |
socket.close(); | |
} | |
catch (Exception ignore) | |
{ | |
} | |
} | |
/** | |
* Copy from an output stream to an input stream. | |
*/ | |
static public int | |
copyStream(InputStream in, OutputStream out, byte[] buffer) | |
throws IOException | |
{ | |
int c; | |
int length = 0; | |
if (buffer == null) | |
buffer = new byte[4096]; | |
while ((c = in.read(buffer)) > 0) | |
{ | |
length += c; | |
out.write(buffer, 0, c); | |
} | |
return length; | |
} | |
public static String | |
hexStringFromBytes(byte[] bytes) | |
{ | |
String hex = "0123456789abcdef"; | |
StringBuffer buf = new StringBuffer(2 * bytes.length); | |
for (int i = 0; i < bytes.length; i++) | |
{ | |
int b = bytes[i]; | |
buf.append(hex.charAt((b >> 4) & 0xf)); | |
buf.append(hex.charAt(b & 0xf)); | |
} | |
return buf.toString(); | |
} | |
/** | |
* Convert a nibble to a hex character | |
* | |
* @param nibble the nibble to convert. | |
*/ | |
public static char toHex(int nibble) | |
{ | |
return hexDigit[(nibble & 0xF)]; | |
} | |
/** | |
* A table of hex digits | |
*/ | |
private static final char[] hexDigit = { | |
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' | |
}; | |
public static String gobbleUpReader(Reader in) | |
throws Exception | |
{ | |
StringBuffer buf = new StringBuffer(); | |
int c; | |
while (-1 != (c = in.read())) | |
{ | |
buf.append(c); | |
} | |
return buf.toString(); | |
} | |
public static String createHashedPassword(String user, String password) | |
{ | |
MessageDigest md = null; | |
try | |
{ | |
md = MessageDigest.getInstance("SHA1", "SUN"); | |
} | |
catch (Exception e) | |
{ | |
throw new RuntimeException(e.getMessage()); | |
} | |
md.update(user.getBytes()); | |
md.update(password.getBytes()); | |
return hexStringFromBytes(md.digest()); | |
} | |
static public String makeHtmlStringNoNewLine(String sIn) | |
{ | |
if (null == sIn) | |
return null; | |
int lenIn = sIn.length(); | |
int iIn; | |
StringBuffer outBuf = new StringBuffer(lenIn + lenIn / 4); // Plenty of room for extra characters | |
char c; | |
for (iIn = 0; iIn < lenIn; ++iIn) | |
{ | |
c = sIn.charAt(iIn); | |
switch (c) | |
{ | |
case '&': | |
outBuf.append("&"); | |
break; | |
case '"': | |
outBuf.append("""); | |
break; | |
case '<': | |
outBuf.append("<"); | |
break; | |
case '>': | |
outBuf.append(">"); | |
break; | |
default: | |
outBuf.append(c); | |
break; | |
} | |
} | |
return outBuf.toString(); | |
} | |
/** | |
* Helper function to split a String into an array of Strings somewhat | |
* like the JDK 1.4.1 {@link java.lang.String#split(String)} method does. | |
*/ | |
public static java.util.List splitList(String s, String match) | |
{ | |
java.util.List strings = new java.util.ArrayList(); | |
s.trim(); | |
while (!s.equals("")) | |
{ | |
if (s.indexOf(match) != -1) | |
{ | |
strings.add(s.substring(0, s.indexOf(match))); | |
s = s.substring(s.indexOf(match) + 1, s.length()); | |
} else | |
{ | |
strings.add(s); | |
s = ""; | |
} | |
s.trim(); | |
} | |
return strings; | |
} | |
/** | |
* Helper function to split a String into an array of Strings somewhat | |
* like the JDK 1.4.1 {@link java.lang.String#split(String)} method does. | |
*/ | |
public static String[] split(String s, String match) | |
{ | |
java.util.List strings = splitList(s, match); | |
return (String[]) strings.toArray((Object[]) (new String[0])); | |
} | |
/** | |
* Programtically turn on/off the stack trace filter. | |
*/ | |
public static void setFilteredStackTrace(boolean filter) | |
{ | |
Util.filteredStackTrace = filter; | |
} | |
/** | |
* State of the stack trace filter. | |
*/ | |
public static boolean isFilteredStackTrace() | |
{ | |
return Util.filteredStackTrace; | |
} | |
/** | |
* Helper to get the stack trace of an Exception as a String. | |
* | |
* @param t Use the stack trace of this exception. | |
* @return The stack trace as a String. | |
*/ | |
public static String getStackTrace(Throwable t) | |
{ | |
if (t == null) | |
return null; | |
StringWriter sw = new StringWriter(); | |
t.printStackTrace(new PrintWriter(sw)); | |
return sw.toString(); | |
} | |
/** | |
* Filter a stack trace by removing any lines matching the set. A default | |
* set will always be applied, but a custom set can also be provided. | |
* | |
* @param t Use the stack trace of this exception. | |
* @return The filtered stack trace as a String. | |
*/ | |
public static String getFilteredStackTrace(Throwable t) | |
{ | |
return getFilteredStackTrace(t, null); | |
} | |
/** | |
* Filter a stack trace by removing any lines matching the set. A default | |
* set will always be applied, but a custom set can also be provided. | |
* | |
* @param t Use the stack trace of this exception. | |
* @param filters Set of custom filters where each filter is | |
* the beginning of a class name. | |
* @return The filtered stack trace as a String. | |
*/ | |
public static String getFilteredStackTrace(Throwable t, String[] filters) | |
{ | |
return filterStack(getStackTrace(t), filters); | |
} | |
/** | |
* Helper for the {@link #getFilteredStackTrace(java.lang.Throwable)} | |
* method. | |
* | |
* @param stack A stack trace as a String. | |
* @param filters Set of custom filters where each filter is | |
* the beginning of a class name. | |
* @return The filtered stack trace as a String. | |
*/ | |
public static String filterStack(String stack, String[] filters) | |
{ | |
if (!isFilteredStackTrace()) | |
return stack; | |
StringWriter sw = new StringWriter(); | |
PrintWriter pw = new PrintWriter(sw); | |
BufferedReader br = new BufferedReader(new StringReader(stack)); | |
String line; | |
try | |
{ | |
while ((line = br.readLine()) != null) | |
{ | |
if (!isFiltered(line, filters)) | |
{ | |
pw.println(line); | |
} | |
} | |
} | |
catch (Exception e) | |
{ | |
return stack; | |
} | |
return sw.toString(); | |
} | |
/** | |
* Helper for the {@link #getFilteredStackTrace(java.lang.Throwable)} | |
* method. | |
* | |
* @param line A single line from the stack trace. | |
* @param filters Set of custom filters where each filter is | |
* the beginning of a class name. | |
* @return true if the line should be filtered; false otherwise. | |
*/ | |
static boolean isFiltered(String line, String[] filters) | |
{ | |
final String[] defaultFilters = new String[]{ | |
"org.apache.xmlbeansbeans.test.tools.moosehead", | |
"org.apache.xmlbeansbeans.test.tools.harness.Main", | |
"junit.framework.TestCase", | |
"junit.framework.TestResult", | |
"junit.framework.TestSuite", | |
"junit.framework.Assert.", // don't filter AssertException | |
"java.lang.reflect.Method.invoke(", | |
"org.apache.tools.ant" | |
}; | |
for (int i = 0; i < defaultFilters.length; ++i) | |
{ | |
if (line.indexOf(defaultFilters[i]) > 0) | |
{ | |
return true; | |
} | |
} | |
if (filters != null) | |
for (int i = 0; i < filters.length; ++i) | |
{ | |
if (line.indexOf(filters[i]) > 0) | |
return true; | |
} | |
return false; | |
} | |
/** | |
* @deprecated | |
*/ | |
public static URL getURL(String name) | |
{ | |
return ResourceUtil.getURL(name); | |
} | |
/** | |
* @deprecated | |
*/ | |
public static InputStream getStream(String name) | |
{ | |
return ResourceUtil.getStream(name); | |
} | |
/** | |
* @deprecated | |
*/ | |
public static File getFile(String name) | |
{ | |
return ResourceUtil.getFile(name); | |
} | |
/** | |
* /** | |
* Expand key/value pairs in a String. | |
* Replaces patterns in the string of the form ${key} where | |
* the keys and values are taken from the hash map. I'm sure someone | |
* could write this more efficiently if they wanted to. Replacement is | |
* recursive. Eg, if the map contains the key "foo" with value "bar", the | |
* string "My dog has ${foo}." will become "My dog has bar." | |
* | |
* @param str String to be expanded. | |
* @param map Map of key value pairs. | |
* @return The string after replacement. | |
* | |
* @deprecated See <code>expand()</code>. | |
*/ | |
public static String _expand(String str, HashMap map) | |
{ | |
if (str == null) | |
return null; | |
if (map == null) | |
return str; | |
StringBuffer result = new StringBuffer(); | |
int pos = 0; | |
int open = -1; | |
//System.out.println("expand("+str+")"); | |
while (-1 != (open = str.indexOf("${", pos))) | |
{ | |
//System.out.println("open: " + open + " = " + str.charAt(open)); | |
//System.out.println("appending: " + str.substring(pos, open) + "<"); | |
// replace everything we've passed so far. | |
result.append(str.substring(pos, open)); | |
pos = open + 1; | |
int close = str.indexOf("}", open); | |
if (close == -1) | |
continue; | |
//System.out.println("close: " + close + " = " + str.charAt(close)); | |
//System.out.println("whole region: " + str.substring(open, close+1)); | |
//System.out.println("match region: " + str.substring(open+2, close)); | |
String key = str.substring(open + 2, close); | |
if (map.containsKey(key)) | |
{ | |
String value = expand((String) map.get(key), map); | |
result.append(value); | |
// non-recursive implementation below: | |
//result.append(map.get(key)); | |
pos = close + 1; | |
continue; | |
} | |
// we've passed the start character (pos = open+1) and didn't find | |
// a match, so copy the '$' to the result string | |
result.append('$'); | |
} | |
result.append(str.substring(pos)); | |
//System.out.println("## expanded: " + result.toString()); | |
return result.toString(); | |
} | |
/** | |
* Expand key/value pairs in a String. | |
* Replaces patterns in the string of the form ${key} where | |
* the keys and values are taken from the hash map. I'm sure someone | |
* could write this more efficiently if they wanted to. Replacement is | |
* recursive. Eg, if the map contains the key "foo" with value "bar", the | |
* string "My dog has ${foo}." will become "My dog has bar." This version | |
* uses the JDK 1.4 regex classes. | |
* | |
* @param str String to be expanded. | |
* @param map Map of key value pairs. | |
* @return The string after replacement. | |
*/ | |
public static String expand(String str, HashMap map) | |
{ | |
final Pattern p = Pattern.compile("\\$\\{.+?\\}"); | |
if (str == null) | |
return null; | |
if (map == null) | |
return str; | |
int last = 0; | |
StringBuffer buf = new StringBuffer(); | |
Matcher m = p.matcher(str); | |
while (m.find()) | |
{ | |
// guarenteed to return ${key} where key is at least one character | |
// in length. match will never be null. | |
String match = m.group(); | |
int start = m.start(); | |
int end = m.end(); | |
// remove the ${ and } from the match | |
String key = match.substring("${".length(), | |
match.length() - "}".length()); | |
if (map.containsKey(key)) | |
{ | |
String value = expand((String) map.get(key), map); | |
buf.append(str.substring(last, start)); | |
buf.append(value); | |
last = end; | |
} | |
} | |
buf.append(str.substring(last, str.length())); | |
return buf.toString(); | |
} | |
/** | |
* Escape a string for writing to a property file. | |
* This is a simplistic version of the Properties.store() escaping. | |
*/ | |
public static String escapeProperty(String s) | |
{ | |
int len = s.length(); | |
StringBuffer buf = new StringBuffer(len * 2); | |
for (int i = 0; i < len; ++i) | |
{ | |
char c = s.charAt(i); | |
switch (c) | |
{ | |
case '\t': | |
buf.append('\\').append('t'); | |
break; | |
case '\n': | |
buf.append('\\').append('n'); | |
break; | |
case '\r': | |
buf.append('\\').append('r'); | |
break; | |
case '\f': | |
buf.append('\\').append('f'); | |
break; | |
case '\\': | |
case ' ': | |
case '=': | |
case ':': | |
case '#': | |
case '!': | |
buf.append('\\').append(c); | |
break; | |
default: | |
if ((c < 0x0020) || (c > 0x007e)) | |
{ | |
buf.append('\\'); | |
buf.append('u'); | |
buf.append(toHex((c >> 12) & 0xF)); | |
buf.append(toHex((c >> 8) & 0xF)); | |
buf.append(toHex((c >> 4) & 0xF)); | |
buf.append(toHex(c & 0xF)); | |
} else | |
{ | |
buf.append(c); | |
} | |
} | |
} | |
return buf.toString(); | |
} | |
/** | |
* Checks if a string is entirely whitespace | |
*/ | |
public static boolean isWhiteSpace(String s) | |
{ | |
for (int i = 0; i < s.length(); i++) | |
if (!Character.isWhitespace(s.charAt(i))) | |
return false; | |
return true; | |
} | |
} | |