com.openhtmltopdf.util.GeneralUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openhtmltopdf-core Show documentation
Show all versions of openhtmltopdf-core Show documentation
Open HTML to PDF is a CSS 2.1 renderer written in Java. This artifact contains the core rendering and layout code.
/*
* {{{ header & license
* GeneralUtil.java
* Copyright (c) 2004, 2005 Patrick Wright
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser 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.
* }}}
*/
package com.openhtmltopdf.util;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Description of the Class
*
* @author Patrick Wright
*/
public class GeneralUtil {
/**
* Used to format an Object's hashcode into a 0-padded 10 char String, e.g.
* for 24993066 returns "0024993066"
*/
public final static java.text.DecimalFormat PADDED_HASH_FORMAT = new java.text.DecimalFormat("0000000000");
/**
* Description of the Method
*
* @param obj PARAM
* @param resource PARAM
* @return Returns
*/
public static InputStream openStreamFromClasspath(Object obj, String resource) {
InputStream readStream = null;
try {
ClassLoader loader = obj.getClass().getClassLoader();
if (loader == null) {
readStream = ClassLoader.getSystemResourceAsStream(resource);
} else {
readStream = loader.getResourceAsStream(resource);
}
if (readStream == null) {
URL stream = resource.getClass().getResource(resource);
if (stream != null) readStream = stream.openStream();
}
} catch (Exception ex) {
XRLog.exception("Could not open stream from CLASSPATH: " + resource, ex);
}
return readStream;
}
public static URL getURLFromClasspath(Object obj, String resource) {
URL url = null;
try {
ClassLoader loader = obj.getClass().getClassLoader();
if (loader == null) {
url = ClassLoader.getSystemResource(resource);
} else {
url = loader.getResource(resource);
}
if (url == null) {
url = resource.getClass().getResource(resource);
}
} catch (Exception ex) {
XRLog.exception("Could not get URL from CLASSPATH: " + resource, ex);
}
return url;
}
/**
* Dumps an exception to the console, only the last 5 lines of the stack
* trace.
*
* @param ex PARAM
*/
public static void dumpShortException(Exception ex) {
String s = ex.getMessage();
if (s == null || s.trim().equals("null")) {
s = "{no ex. message}";
}
System.out.println(s + ", " + ex.getClass());
StackTraceElement[] stes = ex.getStackTrace();
for (int i = 0; i < stes.length && i < 5; i++) {
StackTraceElement ste = stes[i];
System.out.println(" " + ste.getClassName() + "." + ste.getMethodName() + "(ln " + ste.getLineNumber() + ")");
}
}
/**
* Returns a String tracking the last n method calls, from oldest to most
* recent. You can use this as a simple tracing mechanism to find out the
* calls that got to where you execute the trackBack()
call
* from. Example:
*
* // called from Box.calcBorders(), line 639
* String tback = GeneralUtil.trackBack(6);
* System.out.println(tback);
*
produces
*
* Boxing.layoutChildren(ln 204)
* BlockBoxing.layoutContent(ln 81)
* Boxing.layout(ln 72)
* Boxing.layout(ln 133)
* Box.totalLeftPadding(ln 306)
* Box.calcBorders(ln 639)
*
* The trackBack()
method itself is always excluded from the dump.
* Note the output may not be useful if HotSpot has been optimizing the
* code.
*
* @param cnt How far back in the call tree to go; if call tree is smaller, will
* be limited to call tree.
* @return see desc
*/
public static String trackBack(int cnt) {
Exception ex = new Exception();
StringBuffer sb = new StringBuffer();
List list = new ArrayList(cnt);
StackTraceElement[] stes = ex.getStackTrace();
if (cnt >= stes.length) {
cnt = stes.length - 1;
}
// >= 1 to not include this method
for (int i = cnt; i >= 1; i--) {
StackTraceElement ste = stes[i];
sb.append(GeneralUtil.classNameOnly(ste.getClassName()));
sb.append(".");
sb.append(ste.getMethodName());
sb.append("(ln ").append(ste.getLineNumber()).append(")");
list.add(sb.toString());
sb = new StringBuffer();
}
Iterator iter = list.iterator();
StringBuffer padding = new StringBuffer("");
StringBuffer trackback = new StringBuffer();
while (iter.hasNext()) {
String s = (String) iter.next();
trackback.append(padding).append(s).append("\n");
padding.append(" ");
}
return trackback.toString();
}
/**
* Given an Object instance, returns just the classname with no package
*
* @param o PARAM
* @return Returns
*/
public static String classNameOnly(Object o) {
String s = "[null object ref]";
if (o != null) {
s = classNameOnly(o.getClass().getName());
}
return s;
}
/**
* Given a String classname, returns just the classname with no package
*
* @param cname PARAM
* @return Returns
*/
public static String classNameOnly(String cname) {
String s = "[null object ref]";
if (cname != null) {
s = cname.substring(cname.lastIndexOf('.') + 1);
}
return s;
}
/**
* Description of the Method
*
* @param o PARAM
* @return Returns
*/
public static String paddedHashCode(Object o) {
String s = "0000000000";
if (o != null) {
s = PADDED_HASH_FORMAT.format(o.hashCode());
}
return s;
}
public static boolean isMacOSX() {
try {
if (System.getProperty("os.name").toLowerCase().startsWith("mac os x")) {
return true;
}
} catch (SecurityException e) {
System.err.println(e.getLocalizedMessage());
}
return false;
}
public static StringBuffer htmlEscapeSpace(String uri) {
StringBuffer sbURI = new StringBuffer((int) (uri.length() * 1.5));
char ch;
for (int i = 0; i < uri.length(); ++i) {
ch = uri.charAt(i);
if (ch == ' ') {
sbURI.append("%20");
} else if (ch == '\\') {
sbURI.append('/');
} else {
sbURI.append(ch);
}
}
return sbURI;
}
/**
* Reads all content from a given InputStream into a String using the default platform encoding.
*
* @param is the InputStream to read from. Must already be open, and will NOT be closed by this function. Failing to
* close this stream after the call will result in a resource leak.
*
* @return String containing contents read from the stream
* @throws IOException if the stream could not be read
*/
public static String inputStreamToString(InputStream is) throws IOException {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
StringWriter sw = new StringWriter();
char c[] = new char[1024];
while (true) {
int n = br.read(c, 0, c.length);
if (n < 0) break;
sw.write(c, 0, n);
}
isr.close();
return sw.toString();
}
public static void writeStringToFile(String content, String encoding, String fileName)
throws IOException {
File f = new File(fileName);
FileOutputStream fos = new FileOutputStream(f);
try {
OutputStreamWriter osw = new OutputStreamWriter(fos, encoding);
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw);
try {
pw.print(content);
pw.flush();
bw.flush();
} finally {
try {
pw.close();
} catch (Exception e) {
// ignore
}
}
} catch (IOException e) {
throw e;
} finally {
try {
fos.close();
} catch (Exception e) {
// ignore
}
}
System.out.println("Wrote file: " + f.getAbsolutePath());
}
/**
* Parses an integer from a string using less restrictive rules about which
* characters we won't accept. This scavenges the supplied string for any
* numeric character, while dropping all others.
*
* @param s The string to parse
* @return The number represented by the passed string, or 0 if the string
* is null, empty, white-space only, contains only non-numeric
* characters, or simply evaluates to 0 after parsing (e.g. "0")
*/
public static int parseIntRelaxed(String s) {
// An edge-case short circuit...
if (s == null || s.length() == 0 || s.trim().length() == 0) {
return 0;
}
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isDigit(c)) {
buffer.append(c);
} else {
// If we hit a non-numeric with numbers already in the
// buffer, we're done.
if (buffer.length() > 0) {
break;
}
}
}
if (buffer.length() == 0) {
return 0;
}
try {
return Integer.parseInt(buffer.toString());
} catch (NumberFormatException exception) {
// The only way we get here now is if s > Integer.MAX_VALUE
return Integer.MAX_VALUE;
}
}
/**
* Converts any special characters into their corresponding HTML entities , for example < to <. This is done using a character
* by character test, so you may consider other approaches for large documents. Make sure you declare the
* entities that might appear in this replacement, e.g. the latin-1 entities
* This method was taken from a code-samples website, written and hosted by Real Gagnon, at
* http://www.rgagnon.com/javadetails/java-0306.html.
*
* @param s The String which may contain characters to escape.
* @return The string with the characters as HTML entities.
*/
public static String escapeHTML(String s){
if (s == null) {
return "";
}
StringBuffer sb = new StringBuffer();
int n = s.length();
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
switch (c) {
case '<':
sb.append("<");
break;
case '>':
sb.append(">");
break;
case '&':
sb.append("&");
break;
case '"':
sb.append(""");
break;
/*
case 'ÔøΩ': sb.append("à");break;
case 'ÔøΩ': sb.append("À");break;
case 'ÔøΩ': sb.append("â");break;
case 'ÔøΩ': sb.append("Â");break;
case 'ÔøΩ': sb.append("ä");break;
case 'ÔøΩ': sb.append("Ä");break;
case 'ÔøΩ': sb.append("å");break;
case 'ÔøΩ': sb.append("Å");break;
case 'ÔøΩ': sb.append("æ");break;
case 'ÔøΩ': sb.append("Æ");break;
case 'ÔøΩ': sb.append("ç");break;
case 'ÔøΩ': sb.append("Ç");break;
case 'ÔøΩ': sb.append("é");break;
case 'ÔøΩ': sb.append("É");break;
case 'ÔøΩ': sb.append("è");break;
case 'ÔøΩ': sb.append("È");break;
case 'ÔøΩ': sb.append("ê");break;
case 'ÔøΩ': sb.append("Ê");break;
case 'ÔøΩ': sb.append("ë");break;
case 'ÔøΩ': sb.append("Ë");break;
case 'ÔøΩ': sb.append("ï");break;
case 'ÔøΩ': sb.append("Ï");break;
case 'ÔøΩ': sb.append("ô");break;
case 'ÔøΩ': sb.append("Ô");break;
case 'ÔøΩ': sb.append("ö");break;
case 'ÔøΩ': sb.append("Ö");break;
case 'ÔøΩ': sb.append("ø");break;
case 'ÔøΩ': sb.append("Ø");break;
case 'ÔøΩ': sb.append("ß");break;
case 'ÔøΩ': sb.append("ù");break;
case 'ÔøΩ': sb.append("Ù");break;
case 'ÔøΩ': sb.append("û");break;
case 'ÔøΩ': sb.append("Û");break;
case 'ÔøΩ': sb.append("ü");break;
case 'ÔøΩ': sb.append("Ü");break;
case 'ÔøΩ': sb.append("®");break;
case 'ÔøΩ': sb.append("©");break;
case 'ÔøΩ': sb.append("€"); break;
*/
// be carefull with this one (non-breaking whitee space)
case ' ':
sb.append(" ");
break;
default:
sb.append(c);
break;
}
}
return sb.toString();
}
}
/*
* $Id$
*
* $Log$
* Revision 1.19 2009/05/09 15:16:43 pdoubleya
* FindBugs: proper disposal of IO resources
*
* Revision 1.18 2009/04/25 11:03:27 pdoubleya
* Fix some potential IO resource leaks, patches from Peter Fassev in issue #263. Clarifying docs on inputStreamToString() (we don't close the stream, the caller does), and a couple of other minor edits.
*
* Revision 1.17 2008/03/13 16:46:47 peterbrant
* Comment out non-ASCII characters in escapeHTML() for now. Will only work if the compiler assumes the source file encoding is ISO-8859-1 (or maybe Cp1252). Does not work on Linux (with a default encoding of UTF-8). Should be replaced with equivalent Unicode escapes.
*
* Revision 1.16 2008/03/01 19:27:28 pdoubleya
* Utility method to convert certain character to HTML entity equivalents.
*
* Revision 1.15 2007/05/11 22:51:35 peterbrant
* Patch from Sean Bright
*
* Revision 1.14 2007/04/10 20:46:38 pdoubleya
* Fix, was not checking if resource was actually available before opening it
*
* Revision 1.13 2006/07/26 18:17:09 pdoubleya
* Added convenience method, write string to file.
*
* Revision 1.12 2006/07/17 22:16:31 pdoubleya
* Added utility methods, InputStream to String, and simple HTML escaping.
*
* Revision 1.11 2005/06/26 01:02:22 tobega
* Now checking for SecurityException on System.getProperty
*
* Revision 1.10 2005/06/13 06:50:17 tobega
* Fixed a bug in table content resolution.
* Various "tweaks" in other stuff.
*
* Revision 1.9 2005/04/03 21:51:31 joshy
* fixed code that gets the XMLReader on the mac
* added isMacOSX() to GeneralUtil
* added app name and single menu bar to browser
*
* Issue number:
* Obtained from:
* Submitted by:
* Reviewed by:
*
* Revision 1.8 2005/02/02 11:17:18 pdoubleya
* Added trackBack() method.
*
* Revision 1.7 2005/01/29 20:21:08 pdoubleya
* Clean/reformat code. Removed commented blocks, checked copyright.
*
* Revision 1.6 2005/01/24 14:33:47 pdoubleya
* Added exception dump.
*
* Revision 1.5 2004/10/23 14:06:56 pdoubleya
* Re-formatted using JavaStyle tool.
* Cleaned imports to resolve wildcards except for common packages (java.io, java.util, etc).
* Added CVS log comments at bottom.
*
* Revision 1.4 2004/10/19 15:00:53 joshy
* updated the build file
* removed some extraneous files
* update the home page to point to the new jnlp files
* updated the resource loader to use the marker class
* updated the text of the about box
*
* Issue number:
* Obtained from:
* Submitted by:
* Reviewed by:
*
* Revision 1.3 2004/10/18 23:43:02 joshy
* final updates today
*
* Issue number:
* Obtained from:
* Submitted by:
* Reviewed by:
*
* Revision 1.2 2004/10/18 17:10:13 pdoubleya
* Added additional condition, and error check.
*
* Revision 1.1 2004/10/13 23:00:32 pdoubleya
* Added to CVS.
*
*/