Saturday, December 17, 2005

Ghostscript and Java

I recently experienced problem printing from my java app using ghostscript. The error message is here:
 D [17/Dec/2005:14:25:48 +0700] [Job 54] Error: /configurationerror in --setpagedevice-- D [17/Dec/2005:14:25:48 +0700] [Job 54] Additional information: [/ManualFeed false]  
After hours searching, I finally found the solution.
It is in /usr/share/ghostscript/8.15/lib/gs_setpd.ps
Here is the diff
 --- gs_setpd.ps.bak     2005-12-17 14:30:23.000000000 +0700 +++ gs_setpd.ps 2005-12-17 14:31:49.000000000 +0700 @@ -171,10 +171,10 @@    % the default policy to "7" (impose) to avoid numerous problems with    % printing within CUPS...    % -  % /PolicyNotFound 1 -  % /PageSize 0 -  /PolicyNotFound 7 -  /PageSize 7 +  /PolicyNotFound 1 +  /PageSize 0 +  % /PolicyNotFound 7 +  % /PageSize 7    /PolicyReport {      dup /.LockSafetyParams known {         % Only possible error is invalidaccess  

Monday, November 7, 2005

Mandriva 2006

I upgraded my and my clients PCs to Mandriva 2006 PowerPack. It is
fantastic. Shorter boot time, look and feel, and the list grows. I
copied the CDs' contents to my harddisk then invoked urpmi.addmedia
--distrib, and then urpmi --auto-select. It worked like charm.

But...

There is one disappointment. There is no postgresql-server package. I
was forced to download it manually.

Friday, November 4, 2005

FasterFox Break

Recently I discovered that FasterFox extension located in mozilla break
WebWork's token mechanism.
It appears that FasterFox caused the lines

public static String setToken(String tokenName, HttpServletRequest
request) {
HttpSession session = request.getSession(true);
String token = GUID.generateGUID();
session.setAttribute(tokenName, token);

return token;
}

in TokenHelper to be executed twice. This make the token saved in the
session differs to those rendered in the page. As a result,
invalid.token is always returned thus disabling user from using forms.

Thursday, November 3, 2005

Found Resin Xml Bug Revisited

After I wrote my blog titled Found Resin Xml Bug (http://tew.blogspot.com/2005/09/found-resin-xml-bug.html), I discovered that it only applies to JDK 1.4. Things are different in 1.5.
Here it is:
 	<system-property javax.xml.parsers.DocumentBuilderFactory= 				 "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl"/> 	<system-property javax.xml.parsers.SAXParserFactory= 				 "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"/> 

Solitaire is Deadlock-Prone

Solitaire is one of my favorite games. Recently, I discovered that it is
deadlock-prone. Why? I think you who have ever played it have noticed
it. Sometimes I cannot make any progress and is forced to give up the
game session because one or more important cards are buried.

I think this is interesting because people tend to use Philosopher to
explain deadlock.

PS: I use PySol in Linux for playing. PySol contains several games. The
game I play is Klondike.

Wednesday, September 21, 2005

Samsung CD Writer and K3B

I experienced weird things when writing CD using K3B. The verification
always fails when I use cdrecord in DAO mode. I tried RAW mode and
suprprisingly it succeeded.

Tuesday, September 6, 2005

Found Resin Xml Bug

I've finally fixed bug which plagued my project for some time. The bug causes FileSystemPreferences to throw warning messages like this:
Couldn't flush user prefs: java.util.prefs.BackingStoreException: java.lang.NullPointerException
every 30 seconds.
This is happened on Resin 3.0.13. I fixed this by adding the following lines into my resin-web.xml.
<system-property
javax.xml.parsers.DocumentBuilderFactory=
"org.apache.crimson.jaxp.DocumentBuilderFactoryImpl"/>
<system-property
javax.xml.parsers.SAXParserFactory=
"org.apache.crimson.jaxp.SAXParserFactoryImpl"/>

The NPE is thrown on the line 321 of java.util.prefs.XmlSupport

319 | Element xmlMap = (Element) doc.getChildNodes().item(1);
returns null ^^^
320 | // check version
321 | String mapVersion = xmlMap.getAttribute("MAP_XML_VERSION");

Resin xml implementation would behave correctly if item(1) was modified to item(0). After several considerations I decide to stop using resin xml implementation in favor of default JDK 1.4 xml instead of creating my own implementation of Preferences.

Thursday, August 25, 2005

Hard Time Working with Webwork's altSyntax

Actually I have hard time working with Webwork's altSyntax. It is %{} that caused me headache. I have to check whether the getValueClassType() return String or not. To me it's inconsistent. I'm more willing to put %{} every where when I need OGNL than checking individual tag;s value class type.

Tuesday, July 26, 2005

Migration to WebWork altSyntax

Today I've just migrated my WebWork application to altSyntax. My IDEA made this job painless. I just replaced with regular expression "'|'" to  ". Then I enclosed some parameter values with %{...}. I just realized that hidden, textfield, label, and textarea tags need their value parameter enclosed with %{...} opposed to those of checkbox, checkbox list, radio, and select tags which do not so.
Also, param tags still need the "''" if you want to pass String values.

Saturday, July 16, 2005

Indonesian IzPack

Today I created an Indonesian translation of IzPack. IzPack is a free installer. I am now submitting this translation to the IzPack team.

Thursday, July 14, 2005

Thinking Of Bug

I was thinking the issues of my JavaBeanAdapter. I think one of the issues is that the inner bean is always regenerated each time the getter was called.

Tuesday, July 12, 2005

Dropping JavaBeanAdapter

I experienced too many issues with JavaBeanAdapter. So, I decided to drop it from my project because I have not enough time to fix it.

Monday, July 11, 2005

POJO Binding

I managed to make JGoodies Binding works with simple POJO. I create JavaBeanAdapter class to do that. Suppose that you have this POJO:
<code>
public class Pojo {
private String name;
public void setName(String name) { this.name = name; }
public String getName() { return name; }
}
</code>
Then, wrap the POJO:
<code>
Pojo javaBean = JavaBeanAdapter.wrap(new Pojo());
</code>
That's all. I usually do this in my projects that use JGoodies Binding.
<code>
PresentationModel model = new PresentationModel(JavaBeanAdapter.wrap(new Pojo());
</code>
Here is the complete source code for JavaBeanAdapter.
<code>
package com.katalis.commons.util;

import net.sf.cglib.core.DefaultNamingPolicy;
import net.sf.cglib.core.NamingPolicy;
import net.sf.cglib.core.Predicate;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.apache.commons.beanutils.PropertyUtils;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Java Bean adapter using CGLIB. Adapted from <a href="http://cglib.sourceforge.net/xref/samples/Beans.html">http://cglib.sourceforge.net/xref/samples/Beans.html</a>.
* Adapt POJO to meet JavaBean specification. All generated objects will implement {@link Observable}.
* <p/>
* Expected use of this adapter is as follow:<pre>
*      Foo javaBean = JavaBeanAdapter.wrap(new Foo());
* </pre>
* <p/>
* All object graph of the pojo will be wrapped. Exceptions are those of standard java packages.
* <p/>
* Note: Great care must be excercised if you modify the pojo after wrapping. The most obvious is that
* the symetric contract of {@link Object#equals(Object)} will be violated. Example:<pre>
*      javaBean.setFoo("foo");
*      pojo.setFoo("another");
*      javaBean.equals(pojo) //true
*      pojo.equals(javaBean) // false
* </pre>
* The safest approach is to use the generated java bean instead.
*
* @author Thomas Edwin Santosa
*/
public class JavaBeanAdapter {
// ------------------------------ FIELDS ------------------------------

private static final Logger log = Logger.getLogger(JavaBeanAdapter.class.getPackage().getName());
private static final Map cache = Collections.synchronizedMap(new WeakHashMap());
private static final InternalCallbackFilter INTERNAL_CALLBACK_FILTER = new InternalCallbackFilter();
private static final NamingPolicy namingPolicy = new JBNamingPolicy();
private static final Class[] INTERFACES = new Class[]{Observable.class};
private Object pojo;
private final PropertyChangeSupport propertySupport;
private final GetterInterceptor getterInterceptor = new GetterInterceptor();
private final SetterInterceptor setterInterceptor = new SetterInterceptor();
private final AddListenerInterceptor addListenerInterceptor = new AddListenerInterceptor();
private final RemoveListenerInterceptor removeListenerInterceptor = new RemoveListenerInterceptor();
private final DelegateInterceptor delegateInterceptor = new DelegateInterceptor();
private final boolean multicast;

// -------------------------- STATIC METHODS --------------------------

/**
* Wrap the pojo using with no multicast .
*
* @param pojo plain old java object
* @return java bean
* @see #wrap(Object, boolean)
*/
public static Object wrap(Object pojo) {
return wrap(pojo, false);
}

/**
* Wrap the pojo. The pojo will be enhanced so that all setters will fire property change support. This method will try
* its best to synchronize the generated java bean's contents with those of the pojo. If that fails, it will log a
* warning.
*
* @param pojo      plain old java object
* @param multicast whether the property change event will be multicast or not
* @return JavaBean
* @throws IllegalArgumentException if the pojo have been wrapped already
*/
public static Object wrap(Object pojo, boolean multicast) {
if (Enhancer.isEnhanced(pojo.getClass()) && pojo.getClass().getName().endsWith("JavaBeanAdapter")) {
throw new IllegalArgumentException("The pojo is already wrapped.");
}

Object bean;

IdentitySupport key = new IdentitySupport(pojo);
bean = cache.get(key);
if (bean == null) {
JavaBeanAdapter adapter = new JavaBeanAdapter(pojo, multicast);
Enhancer e = new Enhancer();
e.setSuperclass(pojo.getClass());
e.setNamingPolicy(namingPolicy);
e.setInterfaces(INTERFACES);
e.setCallbacks(
        new Callback[]{
        adapter.addListenerInterceptor,
        adapter.removeListenerInterceptor,
        adapter.getterInterceptor,
        adapter.setterInterceptor,
        adapter.delegateInterceptor
        });
e.setCallbackFilter(INTERNAL_CALLBACK_FILTER);
bean = e.create();
try {
PropertyUtils.copyProperties(bean, pojo);
} catch (IllegalAccessException e1) {
log.log(Level.WARNING, "The caller does not have access to the property accessor method.", e1);
} catch (InvocationTargetException e1) {
log.log(Level.WARNING, "The property accessor method throws an exception.", e1);
} catch (NoSuchMethodException e1) {
log.log(Level.WARNING, "an accessor method for this propety cannot be found.", e1);
}
cache.put(key, bean);
}
return bean;
}

private static boolean isSetter(Method method) {
String name = method.getName();
return name.startsWith("set") &&
        isVoidAndSingleArgument(method);
}

private static boolean isVoidAndSingleArgument(Method method) {
return method.getParameterTypes().length == 1 && method.getReturnType() == Void.TYPE;
}

private static boolean isNonJavaGetter(Method method) {
String name = method.getName();
boolean possibleGetter = name.startsWith("get") && method.getParameterTypes().length == 0;
if (possibleGetter) {
Class returnType = method.getReturnType();
return !(returnType.isPrimitive() || returnType.isArray() || returnType.getName().startsWith("java"));
}
return false;
}

private static String extractPropertyName(String name) {
char[] propName = name.substring(3).toCharArray();
propName[0] = Character.toLowerCase(propName[0]);
String propNameStr = String.valueOf(propName);
return propNameStr;
}

// --------------------------- CONSTRUCTORS ---------------------------

private JavaBeanAdapter(Object delegate, boolean multicast) {
assert delegate != null : "Delegate must be not null";
pojo = delegate;
propertySupport = new PropertyChangeSupport(delegate);
this.multicast = multicast;
}

// -------------------------- INNER CLASSES --------------------------

private static class IdentitySupport {
private Object object;

IdentitySupport(Object object) {
this.object = object;
}

public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof IdentitySupport)) return false;

final IdentitySupport identitySupport = (IdentitySupport) o;

return object == identitySupport.object;
}

public int hashCode() {
return System.identityHashCode(object);
}
}

private class GetterInterceptor
        implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
        throws Throwable {
Object retValFromSuper;
Object getterResult = methodProxy.invoke(pojo, objects);
if (getterResult != null && !Enhancer.isEnhanced(getterResult.getClass())) {
retValFromSuper = wrap(getterResult, false);
} else {
retValFromSuper = getterResult;
}
return retValFromSuper;
}
}

private class SetterInterceptor
        implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
        throws Throwable {
String name = method.getName();
String propNameStr = null;
Object oldValue = null;
Object newValue = null;
if (!multicast) {
propNameStr = extractPropertyName(name);
if (PropertyUtils.isReadable(pojo, propNameStr)) {
oldValue = PropertyUtils.getProperty(pojo, propNameStr);
}
newValue = objects[0];
}
methodProxy.invoke(pojo, objects);
// we try to minimize the symetric issue
methodProxy.invokeSuper(o, objects);

propertySupport.firePropertyChange(propNameStr, oldValue, newValue);
if (log.isLoggable(Level.FINE)) {
log.fine(name + " called");
}
return null;
}
}

private class AddListenerInterceptor
        implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
        throws Throwable {
propertySupport.addPropertyChangeListener((PropertyChangeListener) objects[0]);
return null;
}
}

private class RemoveListenerInterceptor
        implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
        throws Throwable {
propertySupport.removePropertyChangeListener((PropertyChangeListener) objects[0]);
return null;
}
}

private class DelegateInterceptor
        implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
        throws Throwable {
return methodProxy.invoke(pojo, objects);
}
}

private static class InternalCallbackFilter
        implements CallbackFilter {
public int accept(Method method) {
int result;
String name = method.getName();

if ("addPropertyChangeListener".equals(name) && isVoidAndSingleArgument(method)) {
result = 0;
} else if ("removePropertyChangeListener".equals(name) && isVoidAndSingleArgument(method)) {
result = 1;
} else if (isNonJavaGetter(method)) {
result = 2;
} else if (isSetter(method)) {
result = 3;
} else {
result = 4;
}
if (log.isLoggable(Level.FINE)) {
log.fine(method + ":" + result);
}
return result;
}
}

private static class JBNamingPolicy
        extends DefaultNamingPolicy {
public String getClassName(String prefix, String source, Object key, Predicate predicate) {
return super.getClassName(prefix, source, key, predicate) + "JavaBeanAdapter";
}
}
}
</code>
Here is the code for Observable:
<code>
package com.katalis.commons.util;

import java.beans.PropertyChangeListener;

/**
* Describes objects that provide bound properties as specified in the
* <a href="http://java.sun.com/products/javabeans/docs/spec.html">Java
* Bean Secification</a>.
*
* @author  Karsten Lentzsch
*
* @see     java.beans.PropertyChangeListener
* @see     java.beans.PropertyChangeEvent
* @see     java.beans.PropertyChangeSupport
*/

public interface Observable {
   

    /**
     * Adds a <code>PropertyChangeListener</code> to the listener list.
     * The listener is registered for all bound properties of this class.
     *
     * @param listener the PropertyChangeListener to be added
     *
     * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
     */
    void addPropertyChangeListener(PropertyChangeListener listener);


    /**
     * Removes a <code>PropertyChangeListener</code> from the listener list.
     * This method should be used to remove PropertyChangeListeners that were
     * registered for all bound properties of this class.
     *
     * @param listener the PropertyChangeListener to be removed
     *
     * @see #addPropertyChangeListener(PropertyChangeListener)
     */
    void removePropertyChangeListener(PropertyChangeListener listener);


}
</code>
You will need Commons-Beanutils from Apache Jakarta on the, I forgot the site. You can google them. I think you will need commons-logging as well. Don't forget to add CGLIB!

Thursday, July 7, 2005

Binding

Today I'm evaluating JGoodies Binding. I'm impressed on how easy it is. In several hours I get my first hello world come out.
The only problem I face is that the firePropertyChange must be after the change.
This one below won't work in JComboBox

public void setFoo(String foo) {
    propertyChangeSupport.firePropertyChange(PROPERTYNAME_FOO, this.foo, foo);
    this.foo=foo;
}

But this one works.

public void setFoo(String foo) {
    String oldValue = this.foo;
    this.foo=foo;
    propertyChangeSupport.firePropertyChange(PROPERTYNAME_FOO, oldValue, foo);
}

I don't know why. I suppose Binding does not use the PropertyChangeEvent's new value.
By the way, I use binding 1.0.

Wednesday, July 6, 2005

My Photo


me
Originally uploaded by t_edwin_s.
I just tried to upload my photo.

Indonesian Locale

I create an Indonesian locale patch for Sun Java implementation. You can use it on your class path if you have swing applications. However, this way would not work in applications. You have to add this class to your rt.jar.
Here it is.
<code>


/*
* This file is part of sunsdk-patch.
* Copyright (c) 2004 Katalis Indonesia.
* All rights reserved.
* See LICENSE.txt for more information.
* Created on Oct 15, 2004
*
*/

package sun.text.resources;

import java.util.ListResourceBundle;

/**
*
@author Thomas Edwin Santosa
*
@version $Revision: 1.3 $
*/

public class LocaleElements_in_ID
extends ListResourceBundle {
/**
* Overrides ListResourceBundle
*/

public Object[][] getContents() {
return new Object[][]{
{
"Languages",
// language names
new String[][]{{"ab", "Abkhazian"},
{
"aa", "Afar"},
{
"af", "Afrikaans"},
{
"sq", "Albanian"},
{
"am", "Amharic"},
{
"ar", "Arabic"},
{
"hy", "Armenian"},
{
"as", "Assamese"},
{
"ay", "Aymara"},
{
"az", "Azerbaijani"},
{
"ba", "Bashkir"},
{
"eu", "Basque"},
{
"bn", "Bengali"},
{
"dz", "Bhutani"},
{
"bh", "Bihari"},
{
"bi", "Bislama"},
{
"br", "Breton"},
{
"bg", "Bulgarian"},
{
"my", "Burmese"},
{
"be", "Byelorussian"},
{
"km", "Cambodian"},
{
"ca", "Catalan"},
{
"zh", "Chinese"},
{
"co", "Corsican"},
{
"hr", "Croatian"},
{
"cs", "Czech"},
{
"da", "Danish"},
{
"nl", "Dutch"},
{
"en", "English"},
{
"eo", "Esperanto"},
{
"et", "Estonian"},
{
"fo", "Faroese"},
{
"fj", "Fiji"},
{
"fi", "Finnish"},
{
"fr", "French"},
{
"fy", "Frisian"},
{
"gl", "Galician"},
{
"ka", "Georgian"},
{
"de", "German"},
{
"el", "Greek"},
{
"kl", "Greenlandic"},
{
"gn", "Guarani"},
{
"gu", "Gujarati"},
{
"ha", "Hausa"},
{
"he", "Hebrew"},
{
"iw", "Hebrew"},
{
"hi", "Hindi"},
{
"hu", "Hungarian"},
{
"is", "Icelandic"},
{
"id", "Indonesian"},
{
"in", "Indonesian"},
{
"ia", "Interlingua"},
{
"ie", "Interlingue"},
{
"iu", "Inuktitut"},
{
"ik", "Inupiak"},
{
"ga", "Irish"},
{
"it", "Italian"},
{
"ja", "Japanese"},
{
"jw", "Javanese"},
{
"kn", "Kannada"},
{
"ks", "Kashmiri"},
{
"kk", "Kazakh"},
{
"rw", "Kinyarwanda"},
{
"ky", "Kirghiz"},
{
"rn", "Kirundi"},
{
"ko", "Korean"},
{
"ku", "Kurdish"},
{
"lo", "Laothian"},
{
"la", "Latin"},
{
"lv", "Latvian (Lettish)"},
{
"ln", "Lingala"},
{
"lt", "Lithuanian"},
{
"mk", "Macedonian"},
{
"mg", "Malagasy"},
{
"ms", "Malay"},
{
"ml", "Malayalam"},
{
"mt", "Maltese"},
{
"mi", "Maori"},
{
"mr", "Marathi"},
{
"mo", "Moldavian"},
{
"mn", "Mongolian"},
{
"na", "Nauru"},
{
"ne", "Nepali"},
{
"no", "Norwegian"},
{
"oc", "Occitan"},
{
"or", "Oriya"},
{
"om", "Oromo (Afan)"},
{
"ps", "Pashto (Pushto)"},
{
"fa", "Persian"},
{
"pl", "Polish"},
{
"pt", "Portuguese"},
{
"pa", "Punjabi"},
{
"qu", "Quechua"},
{
"rm", "Rhaeto-Romance"},
{
"ro", "Romanian"},
{
"ru", "Russian"},
{
"sm", "Samoan"},
{
"sg", "Sangho"},
{
"sa", "Sanskrit"},
{
"gd", "Scots Gaelic"},
{
"sr", "Serbian"},
{
"sh", "Serbo-Croatian"},
{
"st", "Sesotho"},
{
"tn", "Setswana"},
{
"sn", "Shona"},
{
"sd", "Sindhi"},
{
"si", "Sinhalese"},
{
"ss", "Siswati"},
{
"sk", "Slovak"},
{
"sl", "Slovenian"},
{
"so", "Somali"},
{
"es", "Spanish"},
{
"su", "Sundanese"},
{
"sw", "Swahili"},
{
"sv", "Swedish"},
{
"tl", "Tagalog"},
{
"tg", "Tajik"},
{
"ta", "Tamil"},
{
"tt", "Tatar"},
{
"te", "Telugu"},
{
"th", "Thai"},
{
"bo", "Tibetan"},
{
"ti", "Tigrinya"},
{
"to", "Tonga"},
{
"ts", "Tsonga"},
{
"tr", "Turkish"},
{
"tk", "Turkmen"},
{
"tw", "Twi"},
{
"ug", "Uighur"},
{
"uk", "Ukrainian"},
{
"ur", "Urdu"},
{
"uz", "Uzbek"},
{
"vi", "Vietnamese"},
{
"vo", "Volapuk"},
{
"cy", "Welsh"},
{
"wo", "Wolof"},
{
"xh", "Xhosa"},
{
"ji", "Yiddish"},
{
"yi", "Yiddish"},
{
"yo", "Yoruba"},
{
"za", "Zhuang"},
{
"zu", "Zulu"}}}, {"Countries",
// country names
new String[][]{{"AF", "Afghanistan"},
{
"AL", "Albania"},
{
"DZ", "Algeria"},
{
"AD", "Andorra"},
{
"AO", "Angola"},
{
"AI", "Anguilla"},
{
"AR", "Argentina"},
{
"AM", "Armenia"},
{
"AW", "Aruba"},
{
"AU", "Australia"},
{
"AT", "Austria"},
{
"AZ", "Azerbaijan"},
{
"BS", "Bahamas"},
{
"BH", "Bahrain"},
{
"BD", "Bangladesh"},
{
"BB", "Barbados"},
{
"BY", "Belarus"},
{
"BE", "Belgium"},
{
"BZ", "Belize"},
{
"BJ", "Benin"},
{
"BM", "Bermuda"},
{
"BT", "Bhutan"},
{
"BO", "Bolivia"},
{
"BA", "Bosnia and Herzegovina"},
{
"BW", "Botswana"},
{
"BR", "Brazil"},
{
"BN", "Brunei"},
{
"BG", "Bulgaria"},
{
"BF", "Burkina Faso"},
{
"BI", "Burundi"},
{
"KH", "Cambodia"},
{
"CM", "Cameroon"},
{
"CA", "Canada"},
{
"CV", "Cape Verde"},
{
"CF", "Central African Republic"},
{
"TD", "Chad"},
{
"CL", "Chile"},
{
"CN", "China"},
{
"CO", "Colombia"},
{
"KM", "Comoros"},
{
"CG", "Congo"},
{
"CR", "Costa Rica"},
// Ivory Coast is older usage; Cd'I is now in common use in English
{
"CI", "C\u00F4te d'Ivoire"},
{
"HR", "Croatia"},
{
"CU", "Cuba"},
{
"CY", "Cyprus"},
{
"CZ", "Czech Republic"},
{
"DK", "Denmark"},
{
"DJ", "Djibouti"},
{
"DM", "Dominica"},
{
"DO", "Dominican Republic"},
{
"TP", "East Timor"},
{
"EC", "Ecuador"},
{
"EG", "Egypt"},
{
"SV", "El Salvador"},
{
"GQ", "Equatorial Guinea"},
{
"ER", "Eritrea"},
{
"EE", "Estonia"},
{
"ET", "Ethiopia"},
{
"FJ", "Fiji"},
{
"FI", "Finland"},
{
"FR", "France"},
{
"GF", "French Guiana"},
{
"PF", "French Polynesia"},
{
"TF", "French Southern Territories"},
{
"GA", "Gabon"},
{
"GM", "Gambia"},
{
"GE", "Georgia"},
{
"DE", "Germany"},
{
"GH", "Ghana"},
{
"GR", "Greece"},
{
"GP", "Guadeloupe"},
{
"GT", "Guatemala"},
{
"GN", "Guinea"},
{
"GW", "Guinea-Bissau"},
{
"GY", "Guyana"},
{
"HT", "Haiti"},
{
"HN", "Honduras"},
{
"HK", "Hong Kong"},
{
"HU", "Hungary"},
{
"IS", "Iceland"},
{
"IN", "India"},
{
"ID", "Indonesia"},
{
"IR", "Iran"},
{
"IQ", "Iraq"},
{
"IE", "Ireland"},
{
"IL", "Israel"},
{
"IT", "Italy"},
{
"JM", "Jamaica"},
{
"JP", "Japan"},
{
"JO", "Jordan"},
{
"KZ", "Kazakhstan"},
{
"KE", "Kenya"},
{
"KI", "Kiribati"},
{
"KP", "North Korea"},
{
"KR", "South Korea"},
{
"KW", "Kuwait"},
{
"KG", "Kyrgyzstan"},
{
"LA", "Laos"},
{
"LV", "Latvia"},
{
"LB", "Lebanon"},
{
"LS", "Lesotho"},
{
"LR", "Liberia"},
{
"LY", "Libya"},
{
"LI", "Liechtenstein"},
{
"LT", "Lithuania"},
{
"LU", "Luxembourg"},
{
"MK", "Macedonia"},
{
"MG", "Madagascar"},
{
"MY", "Malaysia"},
{
"ML", "Mali"},
{
"MT", "Malta"},
{
"MQ", "Martinique"},
{
"MR", "Mauritania"},
{
"MU", "Mauritius"},
{
"YT", "Mayotte"},
{
"MX", "Mexico"},
{
"FM", "Micronesia"},
{
"MD", "Moldova"},
{
"MC", "Monaco"},
{
"MN", "Mongolia"},
{
"MS", "Montserrat"},
{
"MA", "Morocco"},
{
"MZ", "Mozambique"},
{
"MM", "Myanmar"},
{
"NA", "Namibia"},
{
"NP", "Nepal"},
{
"NL", "Netherlands"},
{
"AN", "Netherlands Antilles"},
{
"NC", "New Caledonia"},
{
"NZ", "New Zealand"},
{
"NI", "Nicaragua"},
{
"NE", "Niger"},
{
"NG", "Nigeria"},
{
"NU", "Niue"},
{
"NO", "Norway"},
{
"OM", "Oman"},
{
"PK", "Pakistan"},
{
"PA", "Panama"},
{
"PG", "Papua New Guinea"},
{
"PY", "Paraguay"},
{
"PE", "Peru"},
{
"PH", "Philippines"},
{
"PL", "Poland"},
{
"PT", "Portugal"},
{
"PR", "Puerto Rico"},
{
"QA", "Qatar"},
{
"RO", "Romania"},
{
"RU", "Russia"},
{
"RW", "Rwanda"},
{
"SA", "Saudi Arabia"},
{
"SN", "Senegal"},
{
"SP", "Serbia"},
{
"SC", "Seychelles"},
{
"SL", "Sierra Leone"},
{
"SG", "Singapore"},
{
"SK", "Slovakia"},
{
"SI", "Slovenia"},
{
"SO", "Somalia"},
{
"ZA", "South Africa"},
{
"ES", "Spain"},
{
"LK", "Sri Lanka"},
{
"SD", "Sudan"},
{
"SR", "Suriname"},
{
"SZ", "Swaziland"},
{
"SE", "Sweden"},
{
"CH", "Switzerland"},
{
"SY", "Syria"},
{
"TW", "Taiwan"},
{
"TJ", "Tajikistan"},
{
"TZ", "Tanzania"},
{
"TH", "Thailand"},
{
"TG", "Togo"},
{
"TK", "Tokelau"},
{
"TO", "Tonga"},
{
"TT", "Trinidad and Tobago"},
{
"TN", "Tunisia"},
{
"TR", "Turkey"},
{
"TM", "Turkmenistan"},
{
"UG", "Uganda"},
{
"UA", "Ukraine"},
{
"AE", "United Arab Emirates"},
{
"GB", "United Kingdom"},
{
"US", "United States"},
{
"UY", "Uruguay"},
{
"UZ", "Uzbekistan"},
{
"VU", "Vanuatu"},
{
"VA", "Vatican"},
{
"VE", "Venezuela"},
{
"VN", "Vietnam"},
// One word
{
"VG", "British Virgin Islands"},
{
"VI", "U.S. Virgin Islands"},
{
"EH", "Western Sahara"},
{
"YE", "Yemen"},
{
"YU", "Yugoslavia"},
{
"ZR", "Zaire"},
{
"ZM", "Zambia"},
{
"ZW", "Zimbabwe"}}}, {"%%EURO", "Euro"}, // Euro variant display name
{
"%%B", "Bokm\u00e5l"}, // Norwegian variant display name
{
"%%NY", "Nynorsk"}, // Norwegian variant display name
{
"LocaleNamePatterns", /* Formats for the display name of a locale, for a list of
* items, and for composing two items in a list into one item.
* The list patterns are used in the variant name and in the
* full display name.
*
* This is the language-neutral form of this resource.
*/

new String[]{"{0,choice,0#|1#{1}|2#{1} ({2})}", // Display name
"{0,choice,0#|1#{1}|2#{1},{2}|3#{1},{2},{3}}", // List
"{0},{1}" // List composition
}}, {
"MonthNames", new String[]{"Januari", // january
"Februari", // february
"Maret", // march
"April", // april
"Mei", // may
"Juni", // june
"Juli", // july
"Augustus", // august
"September", // september
"Oktober", // october
"November", // november
"Desember", // december
"" // month 13 if applicable
}}, {
"MonthAbbreviations", new String[]{"Jan", // abb january
"Feb", // abb february
"Mar", // abb march
"Apr", // abb april
"Mei", // abb may
"Jun", // abb june
"Jul", // abb july
"Agu", // abb august
"Sep", // abb september
"Okt", // abb october
"Nov", // abb november
"Des", // abb december
"" // abb month 13 if applicable
}}, {
"DayNames", new String[]{"Minggu", // Sunday
"Senin", // Monday
"Selasa", // Tuesday
"Rabu", // Wednesday
"Kamis", // Thursday
"Jumat", // Friday
"Sabtu" // Saturday
}}, {
"DayAbbreviations", new String[]{"Min", // abb Sunday
"Sen", // abb Monday
"Sel", // abb Tuesday
"Rab", // abb Wednesday
"Kam", // abb Thursday
"Jum", // abb Friday
"Sab" // abb Saturday
}}, {
"AmPmMarkers", new String[]{"AM", // am marker
"PM" // pm marker
}}, {
"Eras", new String[]{// era strings
"SM", "M"}}, {"NumberPatterns", new String[]{"#,##0.###;-#,##0.###", // decimal pattern
"\u00a4 #,##0.00;(\u00a4 #,##0.00)", // currency pattern
"#,##0%" // percent pattern
}}, {
"NumberElements", new String[]{",", // decimal separator
".", // group (thousands) separator
";", // list separator
"%", // percent sign
"0", // native 0 digit
"#", // pattern digit
"-", // minus sign
"E", // exponential
"\u2030", // per mille
"\u221e", // infinity
"\ufffd" // NaN
}}, {
"CurrencySymbols", // localized versions should have entries of the form
// {<ISO 4217 currency code>, <localized currency symbol>}
// e.g., {"USD", "US$"}
// There are no entries for the root locale, so we fall
// back onto the ISO 4217 currency code.
new String[][]{{"IDR", "Rp"}}}, {"DateTimePatterns", new String[]{"H.mm.ss z", // full time pattern
"H.mm.ss z", // long time pattern
"H.mm.ss", // medium time pattern
"H.mm", // short time pattern
"EEEE, d MMMM yyyy", // full date pattern
"d MMMM yyyy", // long date pattern
"d MMM yyyy", // medium date pattern
"d/M/yy", // short date pattern
"{1} {0}" // date-time pattern
}}, {
"DateTimeElements", new String[]{"0", // first day of week
"1" // min days in first week
}}, {
"CollationElements", ""}, };
}

}

</code>