/** * Copyright (c) 2003, Spellcast development team * http://spellcast.dev.java.net/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * [1] Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * [2] Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * [3] Neither the name "Spellcast development team" nor the names of * its contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package net.java.dev.spellcast.utilities; import java.awt.Color; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Arrays; /** * Formed after the same idea as <code>SwingUtilities</code>, this contains * common functions needed by many of the data-related classes. Any methods * which are used by multiple instances of a JComponent and have a * non-class-specific purpose should be placed into this class in order to * simplify the overall design of the system and to facilitate documentation. */ public final class DataUtilities { private static final String[] EMPTY_STRING_ARRAY = new String[0]; private static final File[] EMPTY_FILE_ARRAY = new File[0]; private static final FilenameFilter BACKUP_FILTER = new FilenameFilter() { @Override public boolean accept(final File dir, final String name) { return !name.startsWith(".") && !name.endsWith("~") && !name.endsWith(".bak") && !name.endsWith(".map") && (name.indexOf("datamaps") == -1) && (dir.getPath().indexOf("datamaps") == -1); } }; public static String[] list(final File directory) { if (!directory.exists() || !directory.isDirectory()) { return DataUtilities.EMPTY_STRING_ARRAY; } final String[] result = directory.list(DataUtilities.BACKUP_FILTER); Arrays.sort(result); return result; } public static File[] listFiles(final File directory) { if (!directory.exists() || !directory.isDirectory()) { return DataUtilities.EMPTY_FILE_ARRAY; } final File[] result = directory.listFiles(DataUtilities.BACKUP_FILTER); Arrays.sort(result); return result; } /** * A public function used to retrieve the reader for a file. Allows the * referencing of files contained within a JAR, inside of a class tree, and * from the local directory from which the Java command line is called. The * priority is as listed, in reverse order. Note that rather than throwing * an exception should the file not be successfully found, this function * will instead print out an error message and simply return null. * * @param file * the file to be retrieved */ public static BufferedReader getReader(final File file) { return DataUtilities.getReader(DataUtilities.getInputStream(file)); } /** * A public function used to retrieve the reader for a file. Allows the * referencing of files contained within a JAR, inside of a class tree, and * from the local directory from which the Java command line is called. The * priority is as listed, in reverse order. Note that rather than throwing * an exception should the file not be successfully found, this function * will instead print out an error message and simply return null. * * @param directory * the subdirectory of the file * @param filename * the name of the file to be retrieved */ public static BufferedReader getReader(final String directory, final String filename) { return DataUtilities.getReader(directory, filename, true); } @SuppressWarnings("resource") public static BufferedReader getReader(final String directory, final String filename, final boolean allowOverride) { try { if (filename.startsWith("http://")) { final HttpURLConnection connection = (HttpURLConnection) new URL( null, filename).openConnection(); final InputStream istream = connection.getInputStream(); if (connection.getResponseCode() != 200) { return DataUtilities.getReader(DataUtilities.EMPTY_STREAM); } return DataUtilities.getReader(istream, connection.getContentEncoding()); } } catch (final IOException e) { return DataUtilities.getReader(DataUtilities.EMPTY_STREAM); } return DataUtilities.getReader(DataUtilities.getInputStream(directory, filename, allowOverride)); } public static BufferedReader getReader(final InputStream istream) { return DataUtilities.getReader(istream, "ISO-8859-1"); } public static BufferedReader getReader(final InputStream istream, final String encoding) { if (istream == null) { return DataUtilities.getReader(DataUtilities.EMPTY_STREAM); } InputStreamReader reader = null; try { if (encoding != null) { reader = new InputStreamReader(istream, encoding); } else { reader = new InputStreamReader(istream, "ISO-8859-1"); } } catch (final Exception e) { reader = new InputStreamReader(istream); } return new BufferedReader(reader); } public static InputStream getInputStream(final File file) { final File parent = file.getParentFile(); if ((parent != null) && !parent.exists()) { parent.mkdirs(); } try { if (!file.exists()) { file.createNewFile(); } return new FileInputStream(file); } catch (final Exception e) { e.printStackTrace(); return DataUtilities.EMPTY_STREAM; } } /** * A public function used to retrieve the input stream, given a filename. * Allows referencing images within a JAR, inside of a class tree, and from * the local directory from which the Java command line is called. The * priority is as listed, in reverse order. * * @param directory * the subtree in which the file can be found * @param filename * the name of the file to be retrieved */ public static InputStream getInputStream(final String directory, final String filename) { return DataUtilities.getInputStream(directory, filename, true); } public static InputStream getInputStream(String directory, String filename, final boolean allowOverride) { // Reformat the name of the directory and the // filename to use strictly forward slashes. directory = directory.replaceAll( File.separator.replaceAll("\\\\", "\\\\\\\\"), "/"); filename = filename.replaceAll( File.separator.replaceAll("\\\\", "\\\\\\\\"), "/"); if ((directory.length() > 0) && !directory.endsWith("/")) { directory += "/"; } InputStream locationAsInputStream; final String fullname = directory + filename; if (allowOverride) { final File override = new File(UtilityConstants.ROOT_LOCATION, fullname); if (override.exists()) { try { return new FileInputStream(override); } catch (final Exception e) { e.printStackTrace(); } } } locationAsInputStream = DataUtilities.getInputStream( UtilityConstants.SYSTEM_CLASSLOADER, fullname); if (locationAsInputStream != null) { return locationAsInputStream; } locationAsInputStream = DataUtilities.getInputStream( UtilityConstants.MAINCLASS_CLASSLOADER, fullname); if (locationAsInputStream != null) { return locationAsInputStream; } // if it's gotten this far, the file does not exist return DataUtilities.EMPTY_STREAM; } private static InputStream getInputStream(final ClassLoader loader, final String filename) { return loader.getResourceAsStream(filename); } public static OutputStream getOutputStream(final String filename) { return DataUtilities.getOutputStream(new File(filename)); } public static OutputStream getOutputStream(final File file) { return DataUtilities.getOutputStream(file, false); } public static OutputStream getOutputStream(final File file, final boolean shouldAppend) { final File directory = file.getParentFile(); if ((directory != null) && !directory.exists()) { directory.mkdirs(); } if (!shouldAppend && file.exists()) { file.delete(); } try { if (!file.exists()) { file.createNewFile(); } return new FileOutputStream(file, shouldAppend); } catch (final Exception e) { e.printStackTrace(); return DataUtilities.MEMORY_OUTPUT_STREAM; } } /** * In a lot of HTML documents and still others, colors are represented using * the RGB values, concatenated as hexadecimal strings. This function is * used to create that hexadecimal string from a color object. Note that the * traditional pound symbol will also be part of the string. * * @param c * The color to be translated to a hexadecimal string. * @return The hexadecimal string representation of the color */ public static String toHexString(final Color c) { if (c == null) { return "#000000"; } final StringBuffer hexString = new StringBuffer(7); hexString.append('#'); final int bitmask = (1 << 24) - 1; hexString.append(DataUtilities.toHexString(c.getRGB() & bitmask, 6)); return hexString.toString(); } /** * In a lot of HTML documents and still others, colors are represented using * the RGB values, concatenated as hexadecimal strings. This function is * used to create a color object from such a hexadecimal string. * * @param hexString * The hexadecimal string (with # prefix) to be translated to a * color * @return The color represented by this hexadecimal string */ public static Color toColor(final String hexString) { return new Color((Character.digit(hexString.charAt(1), 16) * 16) + Character.digit(hexString.charAt(2), 16), (Character.digit( hexString.charAt(3), 16) * 16) + Character.digit(hexString.charAt(4), 16), (Character.digit( hexString.charAt(5), 16) * 16) + Character.digit(hexString.charAt(6), 16)); } /** * The static <code>getHexString()</code> method found in the * <code>Long</code> class has the advantage of converting a value to a * hexadecimal string. However, it does not fix this hexadecimal string to * any length. Thus, the purpose of this function is to convert a given long * to a zero-filled hexadecimal string of given length. Note, however, that * negative values and values which cannot be represented with the given * number of hexadecimal digits will cause an exception to be thrown. * * @param value * The value to convert to hexadecimal * @param digitCount * The number of digits to use * @return The hexadecimal string representation of the given value, set to * the given length */ public static String toHexString(final long value, final int digitCount) { if (value < 0) { throw new IllegalArgumentException( "This function cannot convert negative values"); } final String hexString = Long.toHexString(value); if (hexString.length() > digitCount) { throw new IllegalArgumentException(value + " cannot be represented in " + digitCount + " hexadecimal digits"); } final StringBuffer hexBuffer = new StringBuffer(digitCount); final int zeroesToAdd = digitCount - hexString.length(); for (int i = 0; i < zeroesToAdd; ++i) { hexBuffer.append(0); } hexBuffer.append(hexString); return hexBuffer.toString(); } /** * A method to convert a given text string to its HTML equivalent. This * method is used primarily by the <code>ChatBuffer</code> component to * translate the plain text values returned by the * <code>getChatDisplayForm()</code> to values that can be displayed in a * <code>JEditorPane</code> set to display HTML. * * @param plainText * The plain text to be converted to HTML * @return The HTML representation of the plain text. */ public static String convertToHTML(final String plainText) { if ((plainText == null) || (plainText.length() == 0)) { return ""; } String html = plainText; html = html.replaceAll("&", "&"); // first replace all ampersands html = html.replaceAll("<", "<"); // then replace all < symbols // finally, replace all the new lines with the <br> tag html = html.replaceAll(System.getProperty("line.separator"), "<br>" + System.getProperty("line.separator")); // the conversion to HTML is complete return html; } private static final ByteArrayInputStream EMPTY_STREAM = new ByteArrayInputStream( new byte[0]); private static final ByteArrayOutputStream MEMORY_OUTPUT_STREAM = new ByteArrayOutputStream(); // This class is not to be instanced. private DataUtilities() { } }