001: package net.sourceforge.squirrel_sql.fw.util;
002:
003: /*
004: * Copyright (C) 2001-2003 Colin Bell
005: * colbell@users.sourceforge.net
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
022: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
023:
024: import java.io.*;
025: import java.text.NumberFormat;
026: import java.util.regex.Matcher;
027: import java.util.regex.Pattern;
028:
029: /**
030: * General purpose utilities functions.
031: *
032: * @author <A HREF="mailto:colbell@users.sourceforge.net">Colin Bell</A>
033: */
034: public class Utilities {
035: /** Logger for this class. */
036: private static ILogger s_log = LoggerController
037: .createLogger(Utilities.class);
038:
039: private static Pattern spanStartPattern = Pattern
040: .compile(".*\\<span\\>.*");
041: private static Pattern spanStartSplitPattern = Pattern
042: .compile("\\<span\\>");
043: private static Pattern spanEndPattern = Pattern
044: .compile(".*<\\/span\\>.*");
045: private static Pattern spanEndSplitPattern = Pattern
046: .compile("<\\/span\\>");
047:
048: /**
049: * Ctor. <TT>private</TT> as all methods are static.
050: */
051: private Utilities() {
052: super ();
053: }
054:
055: /**
056: * Print the current stack trace to <TT>ps</TT>.
057: *
058: * @param ps The <TT>PrintStream</TT> to print stack trace to.
059: *
060: * @throws IllegalArgumentException If a null <TT>ps</TT> passed.
061: */
062: public static void printStackTrace(PrintStream ps) {
063: if (ps == null) {
064: throw new IllegalArgumentException("PrintStream == null");
065: }
066:
067: try {
068: throw new Exception();
069: } catch (Exception ex) {
070: ps.println(getStackTrace(ex));
071: }
072: }
073:
074: /**
075: * Return the stack trace from the passed exception as a string
076: *
077: * @param th The exception to retrieve stack trace for.
078: */
079: public static String getStackTrace(Throwable th) {
080: if (th == null) {
081: throw new IllegalArgumentException("Throwable == null");
082: }
083:
084: StringWriter sw = new StringWriter();
085: try {
086: PrintWriter pw = new PrintWriter(sw);
087: try {
088: th.printStackTrace(pw);
089: return sw.toString();
090: } finally {
091: pw.close();
092: }
093: } finally {
094: try {
095: sw.close();
096: } catch (IOException ex) {
097: s_log
098: .error("Unexpected error closing StringWriter",
099: ex);
100: }
101: }
102: }
103:
104: public static Throwable getDeepestThrowable(Throwable t) {
105: Throwable parent = t;
106: Throwable child = t.getCause();
107: while (null != child) {
108: parent = child;
109: child = parent.getCause();
110: }
111:
112: return parent;
113:
114: }
115:
116: /**
117: * Change the passed class name to its corresponding file name. E.G.
118: * change "Utilities" to "Utilities.class".
119: *
120: * @param name Class name to be changed.
121: *
122: * @throws IllegalArgumentException If a null <TT>name</TT> passed.
123: */
124: public static String changeClassNameToFileName(String name) {
125: if (name == null) {
126: throw new IllegalArgumentException("Class Name == null");
127: }
128: return name.replace('.', '/').concat(".class");
129: }
130:
131: /**
132: * Change the passed file name to its corresponding class name. E.G.
133: * change "Utilities.class" to "Utilities".
134: *
135: * @param name Class name to be changed. If this does not represent
136: * a Java class then <TT>null</TT> is returned.
137: *
138: * @throws IllegalArgumentException If a null <TT>name</TT> passed.
139: */
140: public static String changeFileNameToClassName(String name) {
141: if (name == null) {
142: throw new IllegalArgumentException("File Name == null");
143: }
144: String className = null;
145: if (name.toLowerCase().endsWith(".class")) {
146: className = name.replace('/', '.');
147: className = className.replace('\\', '.');
148: className = className.substring(0, className.length() - 6);
149: }
150: return className;
151: }
152:
153: /**
154: * Clean the passed string. Replace whitespace characters with a single
155: * space. If a <TT>null</TT> string passed return an empty string. E.G.
156: * replace
157: *
158: * [pre]
159: * \t\tselect\t* from\t\ttab01
160: * [/pre]
161: *
162: * with
163: *
164: * [pre]
165: * select * from tab01
166: * [/pre]
167: *
168: * @deprecated Use <tt>StringUtilities.cleanString(String)</tt> instead.
169: *
170: * @param str String to be cleaned.
171: *
172: * @return Cleaned string.
173: */
174: public static String cleanString(String str) {
175: return StringUtilities.cleanString(str);
176: }
177:
178: /**
179: * Return whether the 2 passed strings are equal. This function
180: * allows for <TT>null</TT> strings. If <TT>s1</TT> and <TT>s1</TT> are
181: * both <TT>null</TT> they are considered equal.
182: *
183: * @deprecated Use <tt>StringUtilities.areStringsEqual(String, String)</tt>
184: * instead.
185: */
186: public static boolean areStringsEqual(String s1, String s2) {
187: return StringUtilities.areStringsEqual(s1, s2);
188: }
189:
190: /**
191: * Return the suffix of the passed file name.
192: *
193: * @param fileName File name to retrieve suffix for.
194: *
195: * @return Suffix for <TT>fileName</TT> or an empty string
196: * if unable to get the suffix.
197: *
198: * @throws IllegalArgumentException if <TT>null</TT> file name passed.
199: */
200: public static String getFileNameSuffix(String fileName) {
201: if (fileName == null) {
202: throw new IllegalArgumentException("file name == null");
203: }
204: int pos = fileName.lastIndexOf('.');
205: if (pos > 0 && pos < fileName.length() - 1) {
206: return fileName.substring(pos + 1);
207: }
208: return "";
209: }
210:
211: /**
212: * Remove the suffix from the passed file name.
213: *
214: * @param fileName File name to remove suffix from.
215: *
216: * @return <TT>fileName</TT> without a suffix.
217: *
218: * @throws IllegalArgumentException if <TT>null</TT> file name passed.
219: */
220: public static String removeFileNameSuffix(String fileName) {
221: if (fileName == null) {
222: throw new IllegalArgumentException("file name == null");
223: }
224: int pos = fileName.lastIndexOf('.');
225: if (pos > 0 && pos < fileName.length() - 1) {
226: return fileName.substring(0, pos);
227: }
228: return fileName;
229: }
230:
231: /**
232: * Return <tt>true</tt> if the passed string is <tt>null</tt> or empty.
233: *
234: * @deprecated Use <tt>StringUtilities.isEmpty(String)</tt> instead.
235: *
236: * @param str String to be tested.
237: *
238: * @return <tt>true</tt> if the passed string is <tt>null</tt> or empty.
239: */
240: public static boolean isStringEmpty(String str) {
241: return StringUtilities.isEmpty(str);
242: }
243:
244: public static String formatSize(long longSize) {
245: return formatSize(longSize, -1);
246: }
247:
248: // TODO: i18n
249: public static String formatSize(long longSize, int decimalPos) {
250: NumberFormat fmt = NumberFormat.getNumberInstance();
251: if (decimalPos >= 0) {
252: fmt.setMaximumFractionDigits(decimalPos);
253: }
254: final double size = longSize;
255: double val = size / (1024 * 1024);
256: if (val > 1) {
257: return fmt.format(val).concat(" MB");
258: }
259: val = size / 1024;
260: if (val > 10) {
261: return fmt.format(val).concat(" KB");
262: }
263: return fmt.format(val).concat(" bytes");
264: }
265:
266: /**
267: * Split a string based on the given delimiter, but don't remove
268: * empty elements.
269: *
270: * @deprecated Use <tt>StringUtilities.split(String, char)</tt>
271: * instead.
272: *
273: * @param str The string to be split.
274: * @param delimiter Split string based on this delimiter.
275: *
276: * @return Array of split strings. Guaranteeded to be not null.
277: */
278: public static String[] splitString(String str, char delimiter) {
279: return StringUtilities.split(str, delimiter);
280: }
281:
282: /**
283: * Split a string based on the given delimiter, optionally removing
284: * empty elements.
285: *
286: * @deprecated Use <tt>StringUtilities.split(String, char, boolean)</tt>
287: * instead.
288: *
289: * @param str The string to be split.
290: * @param delimiter Split string based on this delimiter.
291: * @param removeEmpty If <tt>true</tt> then remove empty elements.
292: *
293: * @return Array of split strings. Guaranteeded to be not null.
294: */
295: public static String[] splitString(String str, char delimiter,
296: boolean removeEmpty) {
297: return StringUtilities.split(str, delimiter, removeEmpty);
298: }
299:
300: /**
301: * Creates a clone of any serializable object. Collections and arrays
302: * may be cloned if the entries are serializable.
303: *
304: * Caution super class members are not cloned if a super class is not serializable.
305: */
306: public static Object cloneObject(Object toClone,
307: final ClassLoader classLoader) {
308: if (null == toClone) {
309: return null;
310: } else {
311: try {
312: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
313: ObjectOutputStream oOut = new ObjectOutputStream(bOut);
314: oOut.writeObject(toClone);
315: oOut.close();
316: ByteArrayInputStream bIn = new ByteArrayInputStream(
317: bOut.toByteArray());
318: bOut.close();
319: ObjectInputStream oIn = new ObjectInputStream(bIn) {
320: protected Class<?> resolveClass(
321: ObjectStreamClass desc) throws IOException,
322: ClassNotFoundException {
323: return Class.forName(desc.getName(), false,
324: classLoader);
325: }
326: };
327: bIn.close();
328: Object copy = oIn.readObject();
329: oIn.close();
330:
331: return copy;
332: } catch (Exception e) {
333: throw new RuntimeException(e);
334: }
335:
336: }
337: }
338:
339: /**
340: * Internationalizes a line with an embedded I18n key in it. Suppose that
341: * the line looks like:
342: *
343: * This is a line with a <span>embeddedKey</span> in it.
344: *
345: * Further suppose the our I18NStrings.properties has the line:
346: *
347: * embeddedKey=(string that all would like to read)
348: *
349: * This method will return the value:
350: *
351: * This is a line with a (string that all would like to read) in it.
352: *
353: * Note: This method cannot currently handle more than one embedded I18n
354: * string in the specified line at this time. Please put multiple
355: * keys on separate lines. Otherwise, truncation of the specified
356: * line could result!
357: *
358: * @param line the line to internationalize
359: * @param s_stringMgr the StringManager to use to lookup I18N keys.
360: *
361: * @return an internationalized replacement for this line
362: */
363: public static String replaceI18NSpanLine(String line,
364: StringManager s_stringMgr) {
365: String result = line;
366: Matcher start = spanStartPattern.matcher(line);
367: Matcher end = spanEndPattern.matcher(line);
368: if (start.matches() && end.matches()) {
369: // line should look like :
370: //
371: // This is a line with an <span>embedded key</span> in it.
372: //
373: StringBuffer tmp = new StringBuffer();
374: String[] startparts = spanStartSplitPattern.split(line);
375:
376: tmp.append(startparts[0]);
377:
378: // startparts[1] contains our I18n string key followed by </span>
379: String[] endparts = spanEndSplitPattern
380: .split(startparts[1]);
381:
382: String key = endparts[0];
383:
384: String value = s_stringMgr.getString(key);
385: tmp.append(value);
386: tmp.append(endparts[1]);
387:
388: result = tmp.toString();
389: }
390: return result;
391: }
392:
393: /**
394: * Closes the specified Reader which can be null. Logs an error if
395: * an exception occurs while closing.
396: *
397: * @param reader the Reader to close.
398: */
399: public static void closeReader(Reader reader) {
400: if (reader == null) {
401: return;
402: }
403: try {
404: reader.close();
405: } catch (IOException e) {
406: s_log.error("Unable to close Reader: " + e.getMessage(), e);
407: }
408: }
409: }
|