You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by nd...@apache.org on 2007/04/11 18:58:21 UTC

svn commit: r527579 - in /harmony/enhanced/classlib/trunk/modules/swing: make/exclude.common src/main/java/common/javax/swing/JEditorPane.java src/test/api/java/common/javax/swing/JEditorPaneTest.java

Author: ndbeyer
Date: Wed Apr 11 09:58:19 2007
New Revision: 527579

URL: http://svn.apache.org/viewvc?view=rev&rev=527579
Log:
Apply patches for HARMONY-3454: [classlib][swing] JEditorPane.createEditorKitForContentType() uses wrong classloader

Modified:
    harmony/enhanced/classlib/trunk/modules/swing/make/exclude.common
    harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/JEditorPane.java
    harmony/enhanced/classlib/trunk/modules/swing/src/test/api/java/common/javax/swing/JEditorPaneTest.java

Modified: harmony/enhanced/classlib/trunk/modules/swing/make/exclude.common
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/swing/make/exclude.common?view=diff&rev=527579&r1=527578&r2=527579
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/swing/make/exclude.common (original)
+++ harmony/enhanced/classlib/trunk/modules/swing/make/exclude.common Wed Apr 11 09:58:19 2007
@@ -9,10 +9,7 @@
 # should be checked once again: does it still hang?
 javax/swing/JComponent_MultithreadedTest.java
 javax/swing/JDialogTest.java
-javax/swing/JEditorPaneTest.java
 javax/swing/JEditorPane_AccessibleJEditorPaneHTMLTest.java
-javax/swing/JEditorPane_AccessibleJEditorPaneTest.java
-javax/swing/JEditorPane_MultithreadedTest.java
 javax/swing/JFormattedTextFieldTest.java
 javax/swing/JFormattedTextField_CommitActionRTest.java
 javax/swing/JFrameRTest.java

Modified: harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/JEditorPane.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/JEditorPane.java?view=diff&rev=527579&r1=527578&r2=527579
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/JEditorPane.java (original)
+++ harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/JEditorPane.java Wed Apr 11 09:58:19 2007
@@ -26,8 +26,8 @@
 import java.io.StringWriter;
 import java.net.URL;
 import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Map;
+import java.util.Hashtable;
 
 import javax.accessibility.AccessibleContext;
 import javax.accessibility.AccessibleHyperlink;
@@ -203,19 +203,15 @@
 
     private static final String REFERENCE_TAIL_PATTERN = "#.*";
 
-    private static List<String> contentTypes = new ArrayList<String>();
-
-    private static List<String> editorKitNames = new ArrayList<String>();
-
-    private static List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
-
     private static final String RTF_HEADER = "{\\rtf";
 
     private static final String HTML_HEADER = "<html";
 
-    private List<String> localContentTypes = new ArrayList<String>();
+    private static Map<String, ContentTypeRegistration> contentTypes =
+            new Hashtable<String, ContentTypeRegistration>();
 
-    private List<EditorKit> localEditorKits = new ArrayList<EditorKit>();
+    private static Map<String, EditorKit> localContentTypes =
+            new Hashtable<String, EditorKit>();
 
     private String contentType = PLAIN_CONTENT_TYPE;
 
@@ -226,43 +222,49 @@
     private AccessibleContext accessible;
 
     private AccessibleContext accessibleHTML;
+
     static {
-        contentTypes.add(PLAIN_CONTENT_TYPE);
-        contentTypes.add(HTML_CONTENT_TYPE);
-        contentTypes.add(RTF_CONTENT_TYPE);
-        editorKitNames.add("javax.swing.JEditorPane$PlainEditorKit");
-        editorKitNames.add("javax.swing.text.html.HTMLEditorKit");
-        editorKitNames.add("javax.swing.text.rtf.RTFEditorKit");
-        classLoaders.add(null);
-        classLoaders.add(null);
-        classLoaders.add(null);
+        contentTypes.put(PLAIN_CONTENT_TYPE,
+                new ContentTypeRegistration("javax.swing.JEditorPane$PlainEditorKit", null));
+        contentTypes.put(HTML_CONTENT_TYPE,
+                new ContentTypeRegistration("javax.swing.text.html.HTMLEditorKit", null));
+        contentTypes.put(RTF_CONTENT_TYPE,
+                new ContentTypeRegistration("javax.swing.text.rtf.RTFEditorKit", null));
     }
 
     public static EditorKit createEditorKitForContentType(final String contentType) {
-        int index = contentTypes.indexOf(contentType);
-        if (index < 0) {
-            return null;
-        }
-        String kitName = editorKitNames.get(index);
-        Object loader = classLoaders.get(index);
-        EditorKit editorKit = null;
-        try {
-            editorKit = (EditorKit) ((loader != null) ? ((ClassLoader) loader).loadClass(
-                    kitName).newInstance() : Class.forName(kitName).newInstance());
-        } catch (IllegalAccessException e) {
-        } catch (ClassNotFoundException e) {
-        } catch (InstantiationException e) {
+        ContentTypeRegistration registration = contentTypes.get(contentType);
+
+        if (registration != null) {
+            try {
+                if (registration.editorKit == null) {
+                    registration.editorKit = (EditorKit)
+                            Class.forName(registration.className, true,
+                                    registration.classLoader).newInstance();
+                }
+                return (EditorKit) registration.editorKit.clone();
+            } catch (Throwable e) {
+                // Ignore.
+
+                /*
+                 * This is rather dangerous, but is being done so for
+                 * compatibility with RI that seems to do the same.
+                 * See HARMONY-3454 for details.
+                 * This could be tweaked in the future and changed to
+                 * only catch Exception and LinkageError, for example.
+                 */
+            }
         }
-        return editorKit;
+        return null;
     }
 
     public static String getEditorKitClassNameForContentType(final String type) {
         if (type == null) {
-            throw new NullPointerException();
+            throw new NullPointerException(Messages.getString("swing.03","Content type")); //$NON-NLS-1$ //$NON-NLS-2$
         }
+        ContentTypeRegistration registration = contentTypes.get(type);
 
-        int index = contentTypes.indexOf(type);
-        return (index >= 0) ? editorKitNames.get(index) : null;
+        return ((registration != null) ? registration.className : null);
     }
 
     public static void registerEditorKitForContentType(final String type,
@@ -272,20 +274,16 @@
 
     public static void registerEditorKitForContentType(final String type,
             final String editorKitName, final ClassLoader loader) {
-
-        if (type == null || editorKitName == null) {
-            throw new NullPointerException();
+        if (type == null) {
+            throw new NullPointerException(Messages.getString("swing.03","Content type")); //$NON-NLS-1$ //$NON-NLS-2$
         }
 
-        int index = contentTypes.indexOf(type);
-        if (index >= 0) {
-            contentTypes.remove(index);
-            editorKitNames.remove(index);
-            classLoaders.remove(index);
-        }
-        contentTypes.add(type);
-        editorKitNames.add(editorKitName);
-        classLoaders.add(loader);
+        if (editorKitName == null) {
+            throw new NullPointerException(Messages.getString("swing.03","Class name")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        contentTypes.put(type, new ContentTypeRegistration(
+                editorKitName, ((loader != null) ? loader
+                        : Thread.currentThread().getContextClassLoader())));
     }
 
     public JEditorPane() {
@@ -299,8 +297,9 @@
 
     public JEditorPane(final String type, final String text) {
         this();
+
         if (type == null) {
-            throw new NullPointerException();
+            throw new NullPointerException(Messages.getString("swing.03","Content type")); //$NON-NLS-1$ //$NON-NLS-2$
         }
         setContentType(type);
         setText(text);
@@ -352,12 +351,16 @@
     }
 
     public EditorKit getEditorKitForContentType(final String type) {
-        int index = localContentTypes.indexOf(type);
-        if (index >= 0) {
-            return localEditorKits.get(index);
+        EditorKit kit = localContentTypes.get(type);
+
+        if (kit == null) {
+            kit = createEditorKitForContentType(type);
+
+            if (kit == null) {
+                kit = createDefaultEditorKit();
+            }
         }
-        EditorKit kit = JEditorPane.createEditorKitForContentType(type);
-        return (kit == null) ? createDefaultEditorKit() : kit;
+        return kit;
     }
 
     public synchronized HyperlinkListener[] getHyperlinkListeners() {
@@ -557,7 +560,7 @@
         scrollRectToVisible(rect);
     }
 
-    private boolean changeEditoKit(final String contentType) {
+    private boolean changeEditorKit(final String contentType) {
         return !(/*(RTF_CONTENT_TYPE.equals(contentType) && editorKit instanceof RTFEditorKit)
                  ||*/ (HTML_CONTENT_TYPE.equals(contentType) && editorKit instanceof HTMLEditorKit)
                  || (PLAIN_CONTENT_TYPE.equals(contentType) && editorKit instanceof PlainEditorKit));
@@ -567,11 +570,9 @@
         if (type == null) {
             throw new NullPointerException(Messages.getString("swing.03","Content type")); //$NON-NLS-1$ //$NON-NLS-2$
         }
+        contentType = (contentTypes.containsKey(type) ? type : PLAIN_CONTENT_TYPE);
 
-        int index = contentTypes.indexOf(type);
-        contentType = (index >= 0) ? (String)contentTypes.get(index)
-                                  : PLAIN_CONTENT_TYPE;
-        if (changeEditoKit(contentType)) {
+        if (changeEditorKit(contentType)) {
             EditorKit kit = getEditorKitForContentType(contentType);
             updateEditorKit((kit != null) ? kit : new PlainEditorKit());
             updateDocument(editorKit);
@@ -582,14 +583,19 @@
         if (kit == null) {
             return PLAIN_CONTENT_TYPE;
         }
-        int index = localEditorKits.indexOf(kit);
-        if (index >= 0) {
-            return localContentTypes.get(index);
-        }
-        index = editorKitNames.indexOf(kit.getClass().getName());
-        if (index >= 0) {
-            return contentTypes.get(index);
+
+        for (Map.Entry<String, EditorKit> entry : localContentTypes.entrySet()) {
+             if (kit.equals(entry.getValue())) {
+                 return entry.getKey();
+             }
+        }
+
+        for (Map.Entry<String, ContentTypeRegistration> entry : contentTypes.entrySet()) {
+             if (kit.getClass().getName().equals(entry.getValue().className)) {
+                 return entry.getKey();
+             }
         }
+
         return PLAIN_CONTENT_TYPE;
     }
 
@@ -619,17 +625,14 @@
     }
 
     public void setEditorKitForContentType(final String type, final EditorKit kit) {
-        if (type == null || kit == null) {
-            throw new NullPointerException();
+        if (type == null) {
+            throw new NullPointerException(Messages.getString("swing.03","Content type")); //$NON-NLS-1$ //$NON-NLS-2$
         }
-  
-        int index = localContentTypes.indexOf(contentType);
-        if (index >= 0) {
-            localContentTypes.remove(index);
-            localEditorKits.remove(index);
+
+        if (kit == null) {
+            throw new NullPointerException(Messages.getString("swing.03","Editor kit")); //$NON-NLS-1$ //$NON-NLS-2$
         }
-        localContentTypes.add(type);
-        localEditorKits.add(kit);
+        localContentTypes.put(type, kit);
     }
 
     public void setPage(final String page) throws IOException {
@@ -655,6 +658,17 @@
             } catch (BadLocationException e1) {
             }
         } catch (BadLocationException e) {
+        }
+    }
+
+    private static class ContentTypeRegistration {
+        String className;
+        ClassLoader classLoader;
+        EditorKit editorKit;
+
+        ContentTypeRegistration(String className, ClassLoader classLoader) {
+            this.className = className;
+            this.classLoader = classLoader;
         }
     }
 

Modified: harmony/enhanced/classlib/trunk/modules/swing/src/test/api/java/common/javax/swing/JEditorPaneTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/swing/src/test/api/java/common/javax/swing/JEditorPaneTest.java?view=diff&rev=527579&r1=527578&r2=527579
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/swing/src/test/api/java/common/javax/swing/JEditorPaneTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/swing/src/test/api/java/common/javax/swing/JEditorPaneTest.java Wed Apr 11 09:58:19 2007
@@ -30,6 +30,8 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
 import javax.accessibility.AccessibleContext;
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.HyperlinkListener;
@@ -857,5 +859,125 @@
     public void testIsFocusCycleRoot() throws Exception {
         // Regression test for HARMONY-2573
         assertTrue(new JEditorPane().isFocusCycleRoot());
+    }
+
+    public void testCreateEditorKitForContentType() throws Exception {
+
+        // Regression test for HARMONY-3453, HARMONY-3454
+        final ClassLoader classLoader1 = new ArrayClassLoader();
+        final ClassLoader classLoader2 = new ArrayClassLoader();
+        final ClassLoader classLoader3 = new ArrayClassLoader();
+
+        class ThreadCheckEditorKit extends Thread {
+            private boolean register;
+            public EditorKit[] result = new EditorKit[9];
+
+            public ThreadCheckEditorKit(boolean register) {
+                this.register = register;
+
+                if (register) {
+                    setContextClassLoader(classLoader1);
+                }
+            }
+
+            public void run() {
+                result[0] = JEditorPane.createEditorKitForContentType("testContentType1");
+                result[1] = JEditorPane.createEditorKitForContentType("testContentType2");
+                result[2] = JEditorPane.createEditorKitForContentType("testContentType3");
+
+                if (register) {
+                    JEditorPane.registerEditorKitForContentType(
+                            "testContentType1", "MyEditorKit");
+                    JEditorPane.registerEditorKitForContentType( // This throws NPE on RI
+                            "testContentType2", "MyEditorKit", null); // see HARMONY-3453.
+                    JEditorPane.registerEditorKitForContentType(
+                            "testContentType3", "MyEditorKit",
+                            (register ? classLoader2 : classLoader3));
+                }
+                result[3] = JEditorPane.createEditorKitForContentType("testContentType1");
+                result[4] = JEditorPane.createEditorKitForContentType("testContentType2");
+                result[5] = JEditorPane.createEditorKitForContentType("testContentType3");
+
+                result[6] = JEditorPane.createEditorKitForContentType("testContentType1");
+                result[7] = JEditorPane.createEditorKitForContentType("testContentType2");
+                result[8] = JEditorPane.createEditorKitForContentType("testContentType3");
+            }
+
+            public void go() {
+                start();
+
+                while (true) {
+                    try {
+                        join();
+                        return;
+                    } catch (InterruptedException e) {
+                        // Ignored.
+                    }
+                }
+            }
+        };
+
+        ThreadCheckEditorKit thread1 = new ThreadCheckEditorKit(true);
+        thread1.go();
+        ThreadCheckEditorKit thread2 = new ThreadCheckEditorKit(false);
+        thread2.go();
+
+        Map<EditorKit, Object> kitMap = new HashMap<EditorKit, Object>();
+        EditorKit result;
+
+        for (int i = 0; i < 9; i++) {
+            result = thread1.result[i];
+
+            if (i < 3) {
+                assertNull(result);
+            } else {
+                assertNotNull(result);
+                kitMap.put(result, null);
+                assertEquals(result.getClass().getClassLoader(),
+                        ((i % 3) == 2) ? classLoader2 : classLoader1);
+            }
+            result = thread2.result[i];
+            assertNotNull(result);
+            kitMap.put(result, null);
+            assertEquals(result.getClass().getClassLoader(),
+                    (((i % 3) == 2) ? classLoader2 : classLoader1));
+        }
+        // Make sure all returned values are unique.
+        assertEquals(kitMap.size(), 15);
+    }
+
+    /**
+     * Special classloader for testCreateEditorKitForContentType().
+     */
+    private static class ArrayClassLoader extends ClassLoader {
+
+        private static byte[] bytesMyEditorKit = new byte[] {
+                /*
+                 * public class MyEditorKit extends DefaultEditorKit {}
+                 */
+                -54, -2, -70, -66, 0, 0, 0, 49, 0, 13, 10, 0, 3, 0, 10, 7, 0,
+                11, 7, 0, 12, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40,
+                41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110,
+                101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0,
+                10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 16,
+                77, 121, 69, 100, 105, 116, 111, 114, 75, 105, 116, 46, 106,
+                97, 118, 97, 12, 0, 4, 0, 5, 1, 0, 11, 77, 121, 69, 100, 105,
+                116, 111, 114, 75, 105, 116, 1, 0, 33, 106, 97, 118, 97, 120,
+                47, 115, 119, 105, 110, 103, 47, 116, 101, 120, 116, 47, 68,
+                101, 102, 97, 117, 108, 116, 69, 100, 105, 116, 111, 114, 75,
+                105, 116, 0, 33, 0, 2, 0, 3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 4, 0,
+                5, 0, 1, 0, 6, 0, 0, 0, 29, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0,
+                1, -79, 0, 0, 0, 1, 0, 7, 0, 0, 0, 6, 0, 1, 0, 0, 0, 5, 0, 1,
+                0, 8, 0, 0, 0, 2, 0, 9
+        };
+
+        protected Class findClass(String name) throws ClassNotFoundException {
+            if ("MyEditorKit".equals(name)) {
+                return defineClass("MyEditorKit", bytesMyEditorKit,
+                        0, bytesMyEditorKit.length);
+            } else {
+                throw new ClassNotFoundException(name);
+            }
+        }
     }
 }