blob: 10e08f95ccb1b642181c0a26114fc4bd5f083862 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Jens Lukowski/Innoopract - initial renaming/restructuring
*
*******************************************************************************/
package org.eclipse.wst.sse.core.internal.encoding;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Properties;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.wst.sse.core.internal.encoding.util.Logger;
import org.osgi.framework.Bundle;
/**
* CommonCharsets is a utility class to provide a central place to map some
* IANA charset name to a Java charset name. In 1.4 JRE's this mostly is a
* thin wrapper of existing Charset functionality. It does, however, allow
* some "overriding" of the built in JRE mappings in the event they are
* necessary. See CodedIO.checkMappingOverrides.
* <p>
* This class also provides some convenient human readable description for the
* charset names which can be used in user interfaces. The description is NL
* aware based on locale. The data is populated via the charset.properties
* file only once, based on static initialization of the hashtables.
* <p>
* The IANA tags are based on reference information found at the
* http://www.iana.org site. Specifically see
* http://www.iana.org/assignments/character-sets
*/
public final class CommonCharsetNames {
private static Properties defaultIANAmappings = null;
private static ArrayList encodings = null;
private static Hashtable supportedEncodingDisplayNames = null;
/**
* Returns list of commonly available encoding names. Suitable for
* populating a UI dialog or drop down. This list would be a subset of all
* possible charsets the VM supports (which can get into the hundreds).
* For the VM supported charsets, use
* <code>Charset.availableCharsets()</code>
*
* @return String[]
*/
public static String[] getCommonCharsetNames() {
String[] enc = new String[getEncodings().size()];
getEncodings().toArray(enc);
return enc;
}
/**
* @return Returns the defaultIANAmappings.
*/
private static Properties getDefaultIANAMappings() {
if (defaultIANAmappings == null) {
defaultIANAmappings = new Properties();
Bundle keyBundle = Platform.getBundle(ICodedResourcePlugin.ID);
IPath keyPath = new Path("config/defaultIANA.properties"); //$NON-NLS-1$
URL location = Platform.find(keyBundle, keyPath);
InputStream propertiesInputStream = null;
try {
propertiesInputStream = location.openStream();
defaultIANAmappings.load(propertiesInputStream);
}
catch (IOException e) {
// if can't read, just assume there's no
// default IANA mappings
// and repeated attempts will not occur,
// since they
// will be represented by an empty
// Properties object
}
}
return defaultIANAmappings;
}
/**
* Returns display (translated) string for encoding name. If there is no
* "custom" translated version available, it defers to ther VM's Charset
* support. It will return null if no display name is available.
*
* @param String
* charset name
* @return Human friendly display name
*/
public static String getDisplayString(String charsetName) {
if (charsetName == null)
return null;
String result = (String) getSupportedEncodingDisplayNames().get(charsetName);
if (result == null) {
// if we don't have a special one, just return
// what's provided by Charset
try {
Charset charset = Charset.forName(charsetName);
result = charset.displayName();
}
catch (UnsupportedCharsetException e) {
// if not supported, the display name is
// the least of clients concerns :)
}
}
return result;
}
/**
* @return Returns the javaEncodings.
*/
private static ArrayList getEncodings() {
if (encodings == null) {
initHashTables();
}
return encodings;
}
public static String getIanaPreferredCharsetName(String charsetName) {
String preferredName = charsetName;
try {
Charset charset = Charset.forName(charsetName);
if (charset.name() != null) {
preferredName = charset.name();
}
}
catch (IllegalCharsetNameException e) {
// just return input if illegal
}
catch (UnsupportedCharsetException e) {
// just return input if illegal
}
return preferredName;
}
/**
* Returns a default IANA name that is listed in CommonCharsetNames. Here
* is how it checks: 1. check to see if charsetName is in the
* CommonCharsetNames list and if so, just return it. 2. check to see if
* charsetName is listed in defaultIANAmappings which contains a mapping
* of more common encodings and the default IANA name they should map to.
* 3. return defaultIanaName if all else fails
*/
public static String getPreferredDefaultIanaName(String charsetName, String defaultIanaName) {
String preferredName = defaultIanaName;
String guessedName = charsetName;
try {
guessedName = CodedIO.getAppropriateJavaCharset(charsetName);
}
catch (IllegalCharsetNameException e) {
// just ignore if illegal
}
catch (UnsupportedCharsetException e) {
// just ignore if illegal
}
if (getEncodings().contains(guessedName))
preferredName = guessedName;
else {
preferredName = getDefaultIANAMappings().getProperty(guessedName, preferredName);
}
return preferredName;
}
/**
* @return
*/
private static Hashtable getSupportedEncodingDisplayNames() {
if (supportedEncodingDisplayNames == null) {
initHashTables();
}
return supportedEncodingDisplayNames;
}
private static void initHashTables() {
if (supportedEncodingDisplayNames == null) {
// Initialize hash table for encoding table
supportedEncodingDisplayNames = new Hashtable();
encodings = new ArrayList();
ResourceBundle bundle = null;
InputStream bundleStream = null;
try {
URL bundleURL = Platform.find(Platform.getBundle(ICodedResourcePlugin.ID), Path.fromOSString("$nl$/config/charset.properties")); //$NON-NLS-1$
if (bundleURL != null) {
bundleStream = bundleURL.openStream();
bundle = new PropertyResourceBundle(bundleStream);
}
String totalNumString = bundle.getString("totalnumber");//$NON-NLS-1$
int totalNum = 0;
if (totalNumString.length() != 0) {
try {
totalNum = Integer.valueOf(totalNumString).intValue();
}
catch (NumberFormatException e) {
totalNum = 0;
}
}
for (int i = 0; i < totalNum; i++) {
String iana = bundle.getString("codeset." + i + ".iana");//$NON-NLS-2$//$NON-NLS-1$
String displayName = bundle.getString("codeset." + i + ".label");//$NON-NLS-2$//$NON-NLS-1$
encodings.add(iana);
supportedEncodingDisplayNames.put(iana, displayName);
}
}
catch (IOException e) {
Logger.logException("invalid install or configuration", e); //$NON-NLS-1$
}
finally {
try {
if (bundleStream != null)
bundleStream.close();
}
catch (IOException x) {
}
}
}
}
public static void main(String[] args) {
// unit test only
String test = "Cp1252"; //$NON-NLS-1$
String result = CommonCharsetNames.getIanaPreferredCharsetName(test);
System.out.println(test + " --> " + result); //$NON-NLS-1$
test = "MS932"; //$NON-NLS-1$
result = CommonCharsetNames.getIanaPreferredCharsetName(test);
System.out.println(test + " --> " + result); //$NON-NLS-1$
}
public CommonCharsetNames() {
super();
initHashTables();
}
}