--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.iapi.tools.i18n.LocalizedResource\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+package org.apache.derby.iapi.tools.i18n;\r
+\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+import java.io.UnsupportedEncodingException;\r
+import java.lang.reflect.Method;\r
+\r
+import java.util.ResourceBundle;\r
+import java.util.Date;\r
+import java.util.Locale;\r
+import java.util.StringTokenizer;\r
+\r
+import java.text.MessageFormat;\r
+import java.text.NumberFormat;\r
+import java.text.DecimalFormat;\r
+import java.text.DateFormat;\r
+import java.text.ParseException;\r
+import java.text.FieldPosition;\r
+\r
+import java.sql.Timestamp;\r
+import java.sql.ResultSet;\r
+import java.sql.ResultSetMetaData;\r
+import java.sql.SQLException;\r
+import java.sql.Types;\r
+\r
+\r
+public final class LocalizedResource implements java.security.PrivilegedAction {\r
+\r
+ private static final boolean SUPPORTS_BIG_DECIMAL_CALLS;\r
+ \r
+ static {\r
+ boolean supportsBigDecimalCalls;\r
+ try {\r
+ // This class attempts to make a call to a \r
+ // ResultSet.getBigDecimal method, which may not be available.\r
+ // For instance, java.math.BigDecimal is not available with\r
+ // J2ME/CDC/Foundation 1.0 profile.\r
+ Class.forName("java.math.BigDecimal");\r
+ //Added by Jeff Huang\r
+ //TODO: FIXIT\r
+ supportsBigDecimalCalls = true;\r
+ // And no methods using BigDecimal are available with JSR169 spec.\r
+ Method getbd = ResultSet.class.getMethod("getBigDecimal", new Class[] {int.class});\r
+ supportsBigDecimalCalls = true;\r
+ } catch (Throwable t) {\r
+ supportsBigDecimalCalls = false;\r
+ }\r
+ SUPPORTS_BIG_DECIMAL_CALLS = supportsBigDecimalCalls;\r
+ }\r
+ \r
+ private ResourceBundle res;\r
+ private Locale locale;\r
+ private String encode;\r
+ private final static String MESSAGE_FILE = "org.apache.derby.loc.toolsmessages";\r
+ private final static String ENV_CODESET = "derby.ui.codeset";\r
+ private final static String ENV_LOCALE = "derby.ui.locale";\r
+ private String messageFileName;\r
+ private String resourceKey;\r
+ private LocalizedOutput out;\r
+ private LocalizedInput in;\r
+ private boolean enableLocalized;\r
+ private boolean unicodeEscape;\r
+ private static LocalizedResource local;\r
+ private int dateSize;\r
+ private int timeSize;\r
+ private int timestampSize;\r
+ private DateFormat formatDate;\r
+ private DateFormat formatTime;\r
+ private DateFormat formatTimestamp;\r
+ private NumberFormat formatNumber;\r
+ private DecimalFormat formatDecimal;\r
+ public LocalizedResource(){\r
+ init();\r
+ }\r
+ public LocalizedResource(String encStr, String locStr, String msgF){\r
+ init(encStr,locStr,msgF);\r
+ }\r
+ public static LocalizedResource getInstance(){\r
+ if (local == null){\r
+ local = new LocalizedResource();\r
+ }\r
+ return local;\r
+ }\r
+ public void init(){\r
+ init(null,null,null);\r
+ }\r
+ public void init (String encStr, String locStr, String msgF){\r
+ if (encStr != null){\r
+ encode = encStr;\r
+ }\r
+ //then get encoding string from environment\r
+ if (encode == null) {\r
+ String eEncode = getEnvProperty(ENV_CODESET);\r
+ if ( eEncode != null ){\r
+ encode = eEncode;\r
+ }\r
+ }\r
+ \r
+ // If null at this point then the default encoding\r
+ // will be always used.\r
+\r
+ //get locale string from the caller first\r
+ locale = getNewLocale(locStr);\r
+\r
+ //if null, get locale again from the environment variable\r
+ if (locale==null) {\r
+ String s = getEnvProperty(ENV_LOCALE);\r
+ locale = getNewLocale(s);\r
+ }\r
+ //get the default locale if forced\r
+ if (locale==null){\r
+ locale = Locale.getDefault();\r
+ }\r
+ if (msgF != null) {\r
+ messageFileName = msgF;\r
+ }\r
+ else {\r
+ messageFileName = MESSAGE_FILE;\r
+ }\r
+ //create default in/out\r
+ out = getNewOutput(System.out);\r
+ in = getNewInput(System.in);\r
+\r
+ //for faster code: get the format objs\r
+ if (enableLocalized && locale != null){\r
+ formatDecimal = (DecimalFormat)DecimalFormat.getInstance(locale);\r
+ formatNumber = NumberFormat.getInstance(locale);\r
+ formatDate = DateFormat.getDateInstance(DateFormat.LONG,locale);\r
+ formatTime = DateFormat.getTimeInstance(DateFormat.LONG,locale);\r
+ formatTimestamp = DateFormat.getDateTimeInstance(DateFormat.LONG,\r
+ DateFormat.LONG, locale);\r
+ }\r
+ else {\r
+ formatDecimal = (DecimalFormat)DecimalFormat.getInstance();\r
+ formatNumber = NumberFormat.getInstance();\r
+ formatDate = DateFormat.getDateInstance(DateFormat.LONG);\r
+ formatTime = DateFormat.getTimeInstance(DateFormat.LONG);\r
+ formatTimestamp = DateFormat.getDateTimeInstance(DateFormat.LONG,\r
+ DateFormat.LONG);\r
+ }\r
+ //initialize display sizes for columns\r
+ initMaxSizes2();\r
+ }\r
+ //get the message file resource according to the locale\r
+ //fall back to English message file if locale message file is not found\r
+ private void setResource(){\r
+ if (res != null){\r
+ return;\r
+ }\r
+ if ( locale == null || locale.toString().equals("none") ){\r
+ res = ResourceBundle.getBundle(messageFileName);\r
+ }\r
+ else\r
+ try {\r
+ res = ResourceBundle.getBundle(messageFileName,locale);\r
+ }\r
+ catch(java.util.MissingResourceException e){\r
+ res = ResourceBundle.getBundle(messageFileName,Locale.ENGLISH);\r
+ }\r
+ }\r
+ private void initMaxSizes2(){\r
+ dateSize = 0;\r
+ timeSize = 0;\r
+ timestampSize = 0;\r
+\r
+ int len;\r
+\r
+ // check the date & timestamp max length\r
+ // 3900/01/28 !! original devloper thought they were getting 2000/01/28\r
+ Date d = new Date(60907276800000L);\r
+ Timestamp t = new Timestamp(d.getTime());\r
+ for(int month = 0 ; month <=11 ; month++, d.setTime(d.getTime() + (30L * 24L * 60L * 60L * 1000L))) {\r
+ len=getDateAsString(d).length();\r
+\r
+ if(len > dateSize ) {\r
+ dateSize=len;\r
+ }\r
+\r
+ t.setTime(d.getTime() + ((((21L * 60L) + 59L) * 60L) + 59L));\r
+ len=getTimestampAsString(t).length();\r
+\r
+ if(len > timestampSize) {\r
+ timestampSize=len;\r
+ }\r
+ }\r
+\r
+ // set the time max length\r
+ // minimum of 18 because the old buggy code always used 18\r
+ len = 18;\r
+ for (int hour = 0 ; hour < 24; hour++) {\r
+\r
+ long secs = (hour * 3600L) + (59 * 60L) + 59L;\r
+\r
+ long ms = secs * 1000L;\r
+\r
+ Date td = new Date(ms);\r
+\r
+ String fd = formatTime.format(td);\r
+\r
+ if (fd.length() > len)\r
+ len = fd.length();\r
+ }\r
+ timeSize=len;\r
+\r
+ }\r
+\r
+ public LocalizedInput getNewInput(InputStream i) {\r
+ try {\r
+ if (encode != null)\r
+ return new LocalizedInput(i,encode);\r
+ }\r
+ catch (UnsupportedEncodingException e){\r
+ \r
+ }\r
+ return new LocalizedInput(i);\r
+ }\r
+\r
+ public LocalizedInput getNewEncodedInput(InputStream i, String encoding) {\r
+ try {\r
+ return new LocalizedInput(i,encoding);\r
+ }\r
+ catch (UnsupportedEncodingException e){\r
+ \r
+ }\r
+ return new LocalizedInput(i);\r
+ }\r
+\r
+ public LocalizedOutput getNewOutput(OutputStream o){\r
+ try {\r
+ if (encode != null)\r
+ return new LocalizedOutput(o,encode);\r
+ }\r
+ catch(UnsupportedEncodingException e){\r
+ }\r
+ return new LocalizedOutput(o);\r
+ }\r
+ /**\r
+ * Get a new LocalizedOutput with the given encoding.\r
+ * @throws UnsupportedEncodingException\r
+ */\r
+ public LocalizedOutput getNewEncodedOutput(OutputStream o,\r
+ String encoding) throws UnsupportedEncodingException{\r
+ return new LocalizedOutput(o, encoding);\r
+ }\r
+ public String getTextMessage(String key ) {\r
+ if ( res == null){\r
+ setResource();\r
+ }\r
+ String s = key;\r
+ try{\r
+ s = res.getString(key);\r
+ } catch (Exception e) {\r
+ s = key;\r
+ }\r
+ //System.out.println(local.toString());\r
+ //System.out.println("GetKey:"+key+"="+s);\r
+ return s;\r
+ }\r
+ public String getTextMessage(String key, Object o){\r
+ Object [] att=new Object[] {o};\r
+ return getTextMessage(key,att);\r
+ }\r
+ public String getTextMessage(String key, Object o1, Object o2){\r
+ Object [] att=new Object[] {o1,o2};\r
+ return getTextMessage(key,att);\r
+ }\r
+ public String getTextMessage(String key, Object o1, Object o2, Object o3){\r
+ Object [] att=new Object[] {o1,o2,o3};\r
+ return getTextMessage(key,att);\r
+ }\r
+ public String getTextMessage(String key, Object o1, Object o2, Object o3, Object o4){\r
+ Object [] att=new Object[] {o1,o2,o3,o4};\r
+ return getTextMessage(key,att);\r
+ }\r
+ private Locale getNewLocale(String locStr){\r
+ String l="", r="", v="";\r
+ StringTokenizer st;\r
+ if (locStr==null) {\r
+ return null;\r
+ }\r
+ st=new StringTokenizer(locStr, "_");\r
+ try {\r
+ l=st.nextToken();\r
+ if(st.hasMoreTokens()==true)\r
+ r=st.nextToken();\r
+ if(st.hasMoreTokens()==true)\r
+ v=st.nextToken();\r
+ return new Locale(l,r,v);\r
+ } catch (Exception e) {\r
+ return null;\r
+ }\r
+ }\r
+ public String getTextMessage(String key, Object [] objectArr) {\r
+ if (res == null){\r
+ setResource();\r
+ }\r
+ try{\r
+ return MessageFormat.format(res.getString(key), objectArr);\r
+ } catch (Exception e) {\r
+ String tmpFormat = key;\r
+ for (int i=0; i<objectArr.length; i++)\r
+ tmpFormat = tmpFormat + ", <{" + (i) + "}>";\r
+ return MessageFormat.format(tmpFormat, objectArr);\r
+ }\r
+ }\r
+ public String getLocalizedString(ResultSet rs,\r
+ ResultSetMetaData rsm,\r
+ int columnNumber) throws SQLException{\r
+ if (!enableLocalized){\r
+ return rs.getString(columnNumber);\r
+ }\r
+ int type = rsm.getColumnType(columnNumber);\r
+ if ( type == Types.DATE ) {\r
+ return getDateAsString(rs.getDate(columnNumber));\r
+ }\r
+ else if ( type == Types.INTEGER || type == Types.SMALLINT ||\r
+ type == Types.BIGINT || type == Types.TINYINT ) {\r
+ return getNumberAsString(rs.getLong(columnNumber));\r
+ }\r
+ else if (type == Types.REAL || type == Types.FLOAT ||\r
+ type == Types.DOUBLE ) {\r
+ return getNumberAsString(rs.getDouble(columnNumber));\r
+ }\r
+ else if (SUPPORTS_BIG_DECIMAL_CALLS && (type == Types.NUMERIC || type == Types.DECIMAL)) {\r
+ return getNumberAsString(rs.getBigDecimal(columnNumber,\r
+ rsm.getScale(columnNumber)));\r
+ }\r
+ else if (type == Types.TIME ) {\r
+ return getTimeAsString(rs.getTime(columnNumber));\r
+ }\r
+ else if (type == Types.TIMESTAMP ) {\r
+ return getTimestampAsString(rs.getTimestamp(columnNumber));\r
+ }\r
+ return rs.getString(columnNumber);\r
+ }\r
+\r
+ public String getDateAsString(Date d){\r
+ if (!enableLocalized){\r
+ return d.toString();\r
+ }\r
+ return formatDate.format(d);\r
+ }\r
+ public String getTimeAsString(Date t){\r
+ if (!enableLocalized){\r
+ return t.toString();\r
+ }\r
+ return formatTime.format(t, new StringBuffer(),\r
+ new java.text.FieldPosition(0)).toString();\r
+ }\r
+ public String getNumberAsString(int o){\r
+ if (enableLocalized){\r
+ return formatNumber.format(o);\r
+ }\r
+ else {\r
+ return String.valueOf(o);\r
+ }\r
+ }\r
+ public String getNumberAsString(long o){\r
+ if (enableLocalized){\r
+ return formatNumber.format(o);\r
+ }\r
+ else{\r
+ return String.valueOf(o);\r
+ }\r
+ }\r
+ public String getNumberAsString(Object o){\r
+ if (enableLocalized){\r
+ return formatNumber.format(o, new StringBuffer(),\r
+ new FieldPosition(0)).toString();\r
+ }\r
+ else {\r
+ return o.toString();\r
+ }\r
+ }\r
+ public String getNumberAsString(double o){\r
+ if (!enableLocalized) {\r
+ return String.valueOf(o);\r
+ }\r
+ return formatDecimal.format(o);\r
+ }\r
+ public String getTimestampAsString(Timestamp t){\r
+ if (!enableLocalized){\r
+ return t.toString();\r
+ }\r
+ return formatTime.format(t, new StringBuffer(),\r
+ new java.text.FieldPosition(0)).toString();\r
+ }\r
+ public int getColumnDisplaySize(ResultSetMetaData rsm,\r
+ int columnNumber) throws SQLException{\r
+ if (!enableLocalized){\r
+ return rsm.getColumnDisplaySize(columnNumber);\r
+ }\r
+ int type = rsm.getColumnType(columnNumber);\r
+ if (type == Types.DATE)\r
+ return dateSize;\r
+ if (type == Types.TIME)\r
+ return timeSize;\r
+ if (type == Types.TIMESTAMP)\r
+ return timestampSize;\r
+ return rsm.getColumnDisplaySize(columnNumber);\r
+ }\r
+ public String getStringFromDate(String dateStr)\r
+ throws ParseException{\r
+ if (!enableLocalized){\r
+ return dateStr;\r
+ }\r
+ Date d = formatDate.parse(dateStr);\r
+ return new java.sql.Date(d.getTime()).toString();\r
+ }\r
+ public String getStringFromTime(String timeStr)\r
+ throws ParseException{\r
+ if (!enableLocalized){\r
+ return timeStr;\r
+ }\r
+ Date t = formatTime.parse(timeStr);\r
+ return new java.sql.Time(t.getTime()).toString();\r
+ }\r
+ public String getStringFromValue(String val)\r
+ throws ParseException{\r
+ if (!enableLocalized){\r
+ return val;\r
+ }\r
+ return formatNumber.parse(val).toString();\r
+ }\r
+ public String getStringFromTimestamp(String timestampStr)\r
+ throws ParseException{\r
+ if (!enableLocalized){\r
+ return timestampStr;\r
+ }\r
+ Date ts = formatTimestamp.parse(timestampStr);\r
+ return new java.sql.Timestamp(ts.getTime()).toString();\r
+ }\r
+ public Locale getLocale(){\r
+ return locale;\r
+ }\r
+\r
+ private final synchronized String getEnvProperty(String key) {\r
+ String s;\r
+ try\r
+ {\r
+ resourceKey = key;\r
+ s = (String) java.security.AccessController.doPrivileged(this);\r
+ }\r
+ catch (SecurityException se) {\r
+ s = null;\r
+ }\r
+ //System.out.println("{"+resourceKey+"="+s+"}");\r
+ return s;\r
+ }\r
+ public final Object run() {\r
+ String s = System.getProperty(resourceKey);\r
+ return s;\r
+ }\r
+ public static boolean enableLocalization(boolean mode) {\r
+ getInstance().enableLocalized = mode;\r
+ //re-initialized locale\r
+ getInstance().init();\r
+ return mode;\r
+ }\r
+ public boolean isLocalized(){\r
+ return getInstance().enableLocalized;\r
+ }\r
+ public static String getMessage(String key){\r
+ return getInstance().getTextMessage(key);\r
+ }\r
+ public static String getMessage(String key, Object o1){\r
+ return getInstance().getTextMessage(key,o1);\r
+ }\r
+ public static String getMessage(String key, Object o1, Object o2){\r
+ return getInstance().getTextMessage(key,o1,o2);\r
+ }\r
+ public static String getMessage(String key, Object o1, Object o2, Object o3){\r
+ return getInstance().getTextMessage(key,o1,o2,o3);\r
+ }\r
+ public static String getMessage(String key, Object o1, Object o2, Object o3, Object o4){\r
+ return getInstance().getTextMessage(key,o1,o2,o3,o4);\r
+ }\r
+ public static LocalizedOutput OutputWriter(){\r
+ return getInstance().out;\r
+ }\r
+ public static LocalizedInput InputReader(){\r
+ return getInstance().in;\r
+ }\r
+ public static String getNumber(long o){\r
+ return getInstance().getNumberAsString(o);\r
+ }\r
+ public static String getNumber(int o){\r
+ return getInstance().getNumberAsString(o);\r
+ }\r
+ public static void setUnicodeEscape(boolean u){\r
+ getInstance().unicodeEscape = u;\r
+ }\r
+ public static boolean getUnicodeEscape(){\r
+ return getInstance().unicodeEscape;\r
+ }\r
+ public String toString(){\r
+ String s = "toString(){\n" +\r
+ "locale=" + (locale==null?"null":locale.toString()) + "\n" +\r
+ "encode=" + encode + "\n" +\r
+ "messageFile=" + messageFileName + "\n" +\r
+ "resourceKey=" + resourceKey + "\n" +\r
+ "enableLocalized=" + enableLocalized + " \n" +\r
+ "unicodeEscape=" + unicodeEscape + "\n" +\r
+ "dateSize=" + dateSize + "\n" +\r
+ "timeSize=" + timeSize + "\n" +\r
+ "timestampSize="+timestampSize+ "\n}";\r
+ return s;\r
+ }\r
+}\r