All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.enhydra.xml.io.Encodings Maven / Gradle / Ivy

The newest version!
/*
 * Enhydra Java Application Server Project
 * 
 * The contents of this file are subject to the Enhydra Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License on
 * the Enhydra web site ( http://www.enhydra.org/ ).
 * 
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 
 * the License for the specific terms governing rights and limitations
 * under the License.
 * 
 * The Initial Developer of the Enhydra Application Server is Lutris
 * Technologies, Inc. The Enhydra Application Server and portions created
 * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s):
 * 
 * $Id: Encodings.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
 */
package org.enhydra.xml.io;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Iterator;
import java.util.StringTokenizer;

// FIXME: The information here is limited, need to find a canonical
// source of names and encoding sizes, etc.  Create an XML file describing
// it.

/**
 * Class that manages information about encodings.
 */
public final class Encodings {
    /**
     * Some standard character set constants. Using the standard names.
     */
    public static final String ISO_8859_1 = "ISO_8859-1";
    public static final String US_ASCII = "US-ASCII";
    public static final String SHIFT_JIS = "Shift_JIS";

    /**
     * Resource name of file containing character set information.
     */
    private final String CHAR_SET_TABLE
        = "org/enhydra/xml/io/character-sets.tbl";

    /**
     * String use for null encoding in file.
     */
    private final String NULL_STR = "null";

    /**
     * Singleton instance.
     */
    private static Encodings fSingleton;

    /**
     * Singleton empty list of aliases.
     */
    private static final String[] fEmptyAliases = new String[0];

    /**
     * Table of character sets.  The table is keyed by upper-cased encoding
     * names and aliases, containing references to CharacterSet objects.
     */
    private final HashMap fCharSets = new HashMap();
    
    private static final Class CHARSET_CONSTRUCTOR_TYPES[] = {
        String.class, Integer.TYPE, String.class, String[].class
    };

    /**
     * Generate an error about parsing an entry
     */
    private void parseError(String msg,
                            String line) {
        throw new XMLIOError(msg + "; parsing line in " + CHAR_SET_TABLE
                             + "\"" + line + "\"");
    }

    /**
     * Parse the next entry from the file
     */
    private CharacterSet parseCharSetEntry(String line) {
        StringTokenizer tokens = new StringTokenizer(line);
        int numTokens = tokens.countTokens();
        if (numTokens < 4) {
            parseError("must have at least 4 entries", line);
        }

        String className = tokens.nextToken();
        String name = tokens.nextToken();
        Integer charSetSize = null;
        try {
            charSetSize = new Integer(tokens.nextToken());
        } catch (NumberFormatException nfe) {
            parseError("invalid character set size", line);
        }
        String mimePreferred = tokens.nextToken();;
        if (mimePreferred.equals(NULL_STR)) {
            mimePreferred = null;
        }
        String[] aliases = fEmptyAliases;

        if (numTokens > 4) {
            aliases = new String[numTokens - 4];
            int idx = 0;
            while (tokens.hasMoreTokens()) {
                aliases[idx++] = tokens.nextToken();
            }
        }
        
        // Instantiate the appropriate charset class.
        try {
            Class clazz = Class.forName(className);
            Constructor ctr = clazz.getConstructor(CHARSET_CONSTRUCTOR_TYPES);
            Object params[] = { name, charSetSize, mimePreferred, aliases };
            return (CharacterSet)ctr.newInstance(params);
        } catch (Exception e) {
            parseError("Exception loading character set class '" + className + "': " +
            e.toString(), line);
        }
        // Should never be reached, but must be here to make the compiler happy
        throw new IllegalStateException("Ooops. This should never happen. Please debug");        
    }

    /**
     * Add an entry to the mapping table.
     */
    private void addEntry(CharacterSet charSet) {
        fCharSets.put(charSet.getName().toUpperCase().intern(), charSet);
        
        String[] aliases = charSet.getAliases();
        int len = (aliases == null) ? 0 : aliases.length;
        for (int idx = 0; idx < len; idx++) {
            fCharSets.put(aliases[idx].toUpperCase().intern(), charSet);
        }
    }

    /**
     * Parse the character set file.
     */
    private void parseCharacterSetTable(BufferedReader in) throws IOException {
        String line;
        while ((line = in.readLine()) != null) {
            addEntry(parseCharSetEntry(line));
        }
    }

    /**
     * Parse the character set file.
     */
    private void parseCharacterSetTable() {
        ClassLoader loader = Encodings.class.getClassLoader();
        if (loader == null) {
            // Works around a JDeveloper JVM bug.
            loader = ClassLoader.getSystemClassLoader();
        }
        InputStream inStream = loader.getResourceAsStream(CHAR_SET_TABLE);
        if (inStream == null) {
            throw new XMLIOError("can't find \"" + CHAR_SET_TABLE + "\" on class path");
        }
        try {
            try {
                BufferedReader in = new BufferedReader(new InputStreamReader(inStream));
                parseCharacterSetTable(in);
            } finally {
                inStream.close();
            }
        } catch (IOException except) {
            throw new XMLIOError("error reading " + CHAR_SET_TABLE);
        }
    }

    /**
     * Disallow external instantiation.
     */
    private Encodings() {
        parseCharacterSetTable();
    }

    /**
     * Get the entry for an encoding name or null.
     */
    public CharacterSet getCharacterSet(String encoding) {
        return (CharacterSet)fCharSets.get(encoding.toUpperCase());
    }

    /**
     * Determine if an encoding is a valid encoding.
     */
    public boolean isValid(String encoding) {
        return getCharacterSet(encoding) != null;
    }
    
    /**
     * Get the encoding name, given any encoding or alias, or null
     * if unknown encoding.
     */
    public String getName(String encoding) {
        CharacterSet charSet = getCharacterSet(encoding);
        if (charSet == null) {
            return null;
        } else {
            return charSet.getName();
        }
    }

    /**
     * Get the preferred MIME encoding, or null if unknown encoding.
     */
    public String getMIMEPreferred(String encoding) {
        CharacterSet charSet = getCharacterSet(encoding);
        if (charSet == null) {
            return null;
        } else {
            return charSet.getMIMEPreferred();
        }
    }

    /**
     * Get the encoding aliases, given any encoding or alias,
     * or null if unknown encoding.
     */
    public String[] getAliases(String encoding) {
        CharacterSet charSet = getCharacterSet(encoding);
        if (charSet == null) {
            return null;
        } else {
            return charSet.getAliases();
        }
    }

    /**
     * Get the maximum value of an unicode character in an encoding.
     * This checks for 7 and 8 bit encodings; everything else is considered
     * to require 16 bits.
     */
    public int getMaxCharacterValue(String encoding) {
        CharacterSet charSet = getCharacterSet(encoding);
        if (charSet == null) {
            return 0xFFFF;  // assume the best
        } else {
            return charSet.getMaxCharValue();
        }
    }

    /**
     * Determine if two encoding names represent the same encoding.
     * Handles nulls, with two nulls being considered the same encoding.
     */
    public boolean sameEncodings(String encoding1,
                                 String encoding2) {
        if ((encoding1 == null) && (encoding2 == null)) {
            return true;
        } else if ((encoding1 == null) || (encoding2 == null)) {
            return false;
        } else {
            return (getCharacterSet(encoding1) == getCharacterSet(encoding2));
        }
    }

    /**
     * Return string representation for debugging.
     */
    public String toString() {
        StringBuffer buf = new StringBuffer(4096); // larger than default
        Iterator values = fCharSets.values().iterator();
        while (values.hasNext()) {
            buf.append(values.next().toString());
            buf.append('\n');
        }
        return buf.toString();
    }

    /**
     * Get the singleton instance of this class.
     */
    public static Encodings getEncodings() {
        if (fSingleton == null) {
            fSingleton = new Encodings();
        }
        return fSingleton;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy