6657026: Numerous static security flaws in Swing (findbugs)
authormalenkov
Thu, 03 Sep 2009 19:42:27 +0400
changeset 4199 151e13fd2df1
parent 4198 b7add99efe8e
child 4200 7761313b9b16
6657026: Numerous static security flaws in Swing (findbugs) Reviewed-by: hawtin, peterz
jdk/src/share/classes/javax/swing/ToolTipManager.java
jdk/src/share/classes/javax/swing/UIManager.java
jdk/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java
jdk/src/share/classes/javax/swing/plaf/metal/MetalBumps.java
jdk/src/share/classes/javax/swing/plaf/metal/MetalInternalFrameUI.java
jdk/src/share/classes/javax/swing/plaf/metal/MetalSliderUI.java
jdk/test/javax/swing/ToolTipManager/Test6657026.java
jdk/test/javax/swing/UIManager/Test6657026.java
jdk/test/javax/swing/plaf/basic/BasicSplitPaneUI/Test6657026.java
jdk/test/javax/swing/plaf/metal/MetalBorders/Test6657026.java
jdk/test/javax/swing/plaf/metal/MetalBumps/Test6657026.java
jdk/test/javax/swing/plaf/metal/MetalInternalFrameUI/Test6657026.java
jdk/test/javax/swing/plaf/metal/MetalSliderUI/Test6657026.java
--- a/jdk/src/share/classes/javax/swing/ToolTipManager.java	Tue Sep 01 08:15:00 2009 -0700
+++ b/jdk/src/share/classes/javax/swing/ToolTipManager.java	Thu Sep 03 19:42:27 2009 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,10 +27,7 @@
 package javax.swing;
 
 import java.awt.event.*;
-import java.applet.*;
 import java.awt.*;
-import java.io.Serializable;
-import sun.swing.UIAction;
 
 /**
  * Manages all the <code>ToolTips</code> in the system.
@@ -60,7 +57,7 @@
     JComponent insideComponent;
     MouseEvent mouseEvent;
     boolean showImmediately;
-    final static ToolTipManager sharedInstance = new ToolTipManager();
+    private static final Object TOOL_TIP_MANAGER_KEY = new Object();
     transient Popup tipWindow;
     /** The Window tip is being displayed in. This will be non-null if
      * the Window tip is in differs from that of insideComponent's Window.
@@ -345,7 +342,13 @@
      * @return a shared <code>ToolTipManager</code> object
      */
     public static ToolTipManager sharedInstance() {
-        return sharedInstance;
+        Object value = SwingUtilities.appContextGet(TOOL_TIP_MANAGER_KEY);
+        if (value instanceof ToolTipManager) {
+            return (ToolTipManager) value;
+        }
+        ToolTipManager manager = new ToolTipManager();
+        SwingUtilities.appContextPut(TOOL_TIP_MANAGER_KEY, manager);
+        return manager;
     }
 
     // add keylistener here to trigger tip for access
--- a/jdk/src/share/classes/javax/swing/UIManager.java	Tue Sep 01 08:15:00 2009 -0700
+++ b/jdk/src/share/classes/javax/swing/UIManager.java	Thu Sep 03 19:42:27 2009 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -197,6 +197,8 @@
         Vector<LookAndFeel> auxLookAndFeels = null;
         SwingPropertyChangeSupport changeSupport;
 
+        LookAndFeelInfo[] installedLAFs;
+
         UIDefaults getLookAndFeelDefaults() { return tables[0]; }
         void setLookAndFeelDefaults(UIDefaults x) { tables[0] = x; }
 
@@ -227,18 +229,6 @@
      */
     private static final Object classLock = new Object();
 
-
-    /* Cache the last referenced LAFState to improve performance
-     * when accessing it.  The cache is based on last thread rather
-     * than last AppContext because of the cost of looking up the
-     * AppContext each time.  Since most Swing UI work is on the
-     * EventDispatchThread, this hits often enough to justify the
-     * overhead.  (4193032)
-     */
-    private static Thread currentLAFStateThread = null;
-    private static LAFState currentLAFState = null;
-
-
     /**
      * Return the <code>LAFState</code> object, lazily create one if necessary.
      * All access to the <code>LAFState</code> fields is done via this method,
@@ -248,13 +238,6 @@
      * </pre>
      */
     private static LAFState getLAFState() {
-        // First check whether we're running on the same thread as
-        // the last request.
-        Thread thisThread = Thread.currentThread();
-        if (thisThread == currentLAFStateThread) {
-            return currentLAFState;
-        }
-
         LAFState rv = (LAFState)SwingUtilities.appContextGet(
                 SwingUtilities2.LAF_STATE_KEY);
         if (rv == null) {
@@ -268,10 +251,6 @@
                 }
             }
         }
-
-        currentLAFStateThread = thisThread;
-        currentLAFState = rv;
-
         return rv;
     }
 
@@ -431,7 +410,10 @@
      */
     public static LookAndFeelInfo[] getInstalledLookAndFeels() {
         maybeInitialize();
-        LookAndFeelInfo[] ilafs = installedLAFs;
+        LookAndFeelInfo[] ilafs = getLAFState().installedLAFs;
+        if (ilafs == null) {
+            ilafs = installedLAFs;
+        }
         LookAndFeelInfo[] rv = new LookAndFeelInfo[ilafs.length];
         System.arraycopy(ilafs, 0, rv, 0, ilafs.length);
         return rv;
@@ -453,9 +435,10 @@
     public static void setInstalledLookAndFeels(LookAndFeelInfo[] infos)
         throws SecurityException
     {
+        maybeInitialize();
         LookAndFeelInfo[] newInfos = new LookAndFeelInfo[infos.length];
         System.arraycopy(infos, 0, newInfos, 0, infos.length);
-        installedLAFs = newInfos;
+        getLAFState().installedLAFs = newInfos;
     }
 
 
@@ -1307,10 +1290,11 @@
             }
         }
 
-        installedLAFs = new LookAndFeelInfo[ilafs.size()];
+        LookAndFeelInfo[] installedLAFs = new LookAndFeelInfo[ilafs.size()];
         for(int i = 0; i < ilafs.size(); i++) {
             installedLAFs[i] = ilafs.elementAt(i);
         }
+        getLAFState().installedLAFs = installedLAFs;
     }
 
 
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java	Tue Sep 01 08:15:00 2009 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java	Thu Sep 03 19:42:27 2009 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,14 +31,12 @@
 import sun.swing.UIAction;
 import javax.swing.*;
 import javax.swing.border.Border;
-import javax.swing.event.*;
 import java.awt.*;
 import java.awt.event.*;
 import java.awt.peer.ComponentPeer;
 import java.awt.peer.LightweightPeer;
 import java.beans.*;
 import java.util.*;
-import javax.swing.plaf.ActionMapUIResource;
 import javax.swing.plaf.SplitPaneUI;
 import javax.swing.plaf.ComponentUI;
 import javax.swing.plaf.UIResource;
@@ -106,13 +104,13 @@
      * Keys to use for forward focus traversal when the JComponent is
      * managing focus.
      */
-    private static Set<KeyStroke> managingFocusForwardTraversalKeys;
+    private Set<KeyStroke> managingFocusForwardTraversalKeys;
 
     /**
      * Keys to use for backward focus traversal when the JComponent is
      * managing focus.
      */
-    private static Set<KeyStroke> managingFocusBackwardTraversalKeys;
+    private Set<KeyStroke> managingFocusBackwardTraversalKeys;
 
 
     /**
@@ -675,7 +673,7 @@
      * @return increment via keyboard methods.
      */
     int getKeyboardMoveIncrement() {
-        return KEYBOARD_DIVIDER_MOVE_OFFSET;
+        return 3;
     }
 
     /**
--- a/jdk/src/share/classes/javax/swing/plaf/metal/MetalBumps.java	Tue Sep 01 08:15:00 2009 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/metal/MetalBumps.java	Thu Sep 03 19:42:27 2009 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,9 @@
 import java.awt.*;
 import java.awt.image.*;
 import javax.swing.*;
-import java.io.*;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import sun.awt.AppContext;
 
 /**
  * Implements the bumps used throughout the Metal Look and Feel.
@@ -49,19 +50,9 @@
     protected Color shadowColor;
     protected Color backColor;
 
-    protected static Vector<BumpBuffer> buffers = new Vector<BumpBuffer>();
+    private static final Object METAL_BUMPS = new Object();
     protected BumpBuffer buffer;
 
-    public MetalBumps( Dimension bumpArea ) {
-        this( bumpArea.width, bumpArea.height );
-    }
-
-    public MetalBumps( int width, int height ) {
-        this(width, height, MetalLookAndFeel.getPrimaryControlHighlight(),
-             MetalLookAndFeel.getPrimaryControlDarkShadow(),
-             MetalLookAndFeel.getPrimaryControlShadow());
-    }
-
     /**
      * Creates MetalBumps of the specified size with the specified colors.
      * If <code>newBackColor</code> is null, the background will be
@@ -73,26 +64,22 @@
         setBumpColors( newTopColor, newShadowColor, newBackColor );
     }
 
-    private BumpBuffer getBuffer(GraphicsConfiguration gc, Color aTopColor,
-                                 Color aShadowColor, Color aBackColor) {
-        if (buffer != null && buffer.hasSameConfiguration(
-                              gc, aTopColor, aShadowColor, aBackColor)) {
-            return buffer;
+    private static BumpBuffer createBuffer(GraphicsConfiguration gc,
+                                           Color topColor, Color shadowColor, Color backColor) {
+        AppContext context = AppContext.getAppContext();
+        List<BumpBuffer> buffers = (List<BumpBuffer>) context.get(METAL_BUMPS);
+        if (buffers == null) {
+            buffers = new ArrayList<BumpBuffer>();
+            context.put(METAL_BUMPS, buffers);
         }
-        BumpBuffer result = null;
-
-        for (BumpBuffer aBuffer : buffers) {
-            if ( aBuffer.hasSameConfiguration(gc, aTopColor, aShadowColor,
-                                              aBackColor)) {
-                result = aBuffer;
-                break;
+        for (BumpBuffer buffer : buffers) {
+            if (buffer.hasSameConfiguration(gc, topColor, shadowColor, backColor)) {
+                return buffer;
             }
         }
-        if (result == null) {
-            result = new BumpBuffer(gc, topColor, shadowColor, backColor);
-            buffers.addElement(result);
-        }
-        return result;
+        BumpBuffer buffer = new BumpBuffer(gc, topColor, shadowColor, backColor);
+        buffers.add(buffer);
+        return buffer;
     }
 
     public void setBumpArea( Dimension bumpArea ) {
@@ -119,10 +106,12 @@
         GraphicsConfiguration gc = (g instanceof Graphics2D) ?
                 ((Graphics2D) g).getDeviceConfiguration() : null;
 
-        buffer = getBuffer(gc, topColor, shadowColor, backColor);
+        if ((buffer == null) || !buffer.hasSameConfiguration(gc, topColor, shadowColor, backColor)) {
+            buffer = createBuffer(gc, topColor, shadowColor, backColor);
+        }
 
-        int bufferWidth = buffer.getImageSize().width;
-        int bufferHeight = buffer.getImageSize().height;
+        int bufferWidth = BumpBuffer.IMAGE_SIZE;
+        int bufferHeight = BumpBuffer.IMAGE_SIZE;
         int iconWidth = getIconWidth();
         int iconHeight = getIconHeight();
         int x2 = x + iconWidth;
@@ -155,7 +144,6 @@
 class BumpBuffer {
 
     static final int IMAGE_SIZE = 64;
-    static Dimension imageSize = new Dimension( IMAGE_SIZE, IMAGE_SIZE );
 
     transient Image image;
     Color topColor;
@@ -197,10 +185,6 @@
         return image;
     }
 
-    public Dimension getImageSize() {
-        return imageSize;
-    }
-
     /**
      * Paints the bumps into the current image.
      */
--- a/jdk/src/share/classes/javax/swing/plaf/metal/MetalInternalFrameUI.java	Tue Sep 01 08:15:00 2009 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/metal/MetalInternalFrameUI.java	Thu Sep 03 19:42:27 2009 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,10 +31,8 @@
 import javax.swing.event.*;
 import javax.swing.border.*;
 import javax.swing.plaf.basic.*;
-import java.util.EventListener;
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeEvent;
-import java.beans.PropertyVetoException;
 import javax.swing.plaf.*;
 
 /**
@@ -51,7 +49,7 @@
   private static final Border handyEmptyBorder = new EmptyBorder(0,0,0,0);
 
   protected static String IS_PALETTE   = "JInternalFrame.isPalette";
-
+  private static String IS_PALETTE_KEY = "JInternalFrame.isPalette";
   private static String FRAME_TYPE     = "JInternalFrame.frameType";
   private static String NORMAL_FRAME   = "normal";
   private static String PALETTE_FRAME  = "palette";
@@ -68,7 +66,7 @@
   public void installUI(JComponent c) {
     super.installUI(c);
 
-    Object paletteProp = c.getClientProperty( IS_PALETTE );
+    Object paletteProp = c.getClientProperty(IS_PALETTE_KEY);
     if ( paletteProp != null ) {
         setPalette( ((Boolean)paletteProp).booleanValue() );
     }
@@ -187,7 +185,7 @@
                   ui.setFrameType( (String) e.getNewValue() );
               }
           }
-          else if ( name.equals( IS_PALETTE ) )
+          else if ( name.equals(IS_PALETTE_KEY) )
           {
               if ( e.getNewValue() != null )
               {
--- a/jdk/src/share/classes/javax/swing/plaf/metal/MetalSliderUI.java	Tue Sep 01 08:15:00 2009 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/metal/MetalSliderUI.java	Thu Sep 03 19:42:27 2009 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,12 +54,13 @@
 
     protected final int TICK_BUFFER = 4;
     protected boolean filledSlider = false;
-    // NOTE: these next three variables are currently unused.
+    // NOTE: these next five variables are currently unused.
     protected static Color thumbColor;
     protected static Color highlightColor;
     protected static Color darkShadowColor;
     protected static int trackWidth;
     protected static int tickLength;
+    private int safeLength;
 
    /**
     * A default horizontal thumb <code>Icon</code>. This field might not be
@@ -107,7 +108,7 @@
 
     public void installUI( JComponent c ) {
         trackWidth = ((Integer)UIManager.get( "Slider.trackWidth" )).intValue();
-        tickLength = ((Integer)UIManager.get( "Slider.majorTickLength" )).intValue();
+        tickLength = safeLength = ((Integer)UIManager.get( "Slider.majorTickLength" )).intValue();
         horizThumbIcon = SAFE_HORIZ_THUMB_ICON =
                 UIManager.getIcon( "Slider.horizontalThumbIcon" );
         vertThumbIcon = SAFE_VERT_THUMB_ICON =
@@ -477,8 +478,8 @@
      * determine the tick area rectangle.
      */
     public int getTickLength() {
-        return slider.getOrientation() == JSlider.HORIZONTAL ? tickLength + TICK_BUFFER + 1 :
-        tickLength + TICK_BUFFER + 3;
+        return slider.getOrientation() == JSlider.HORIZONTAL ? safeLength + TICK_BUFFER + 1 :
+        safeLength + TICK_BUFFER + 3;
     }
 
     /**
@@ -523,22 +524,22 @@
 
     protected void paintMinorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {
         g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
-        g.drawLine( x, TICK_BUFFER, x, TICK_BUFFER + (tickLength / 2) );
+        g.drawLine( x, TICK_BUFFER, x, TICK_BUFFER + (safeLength / 2) );
     }
 
     protected void paintMajorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {
         g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
-        g.drawLine( x, TICK_BUFFER , x, TICK_BUFFER + (tickLength - 1) );
+        g.drawLine( x, TICK_BUFFER , x, TICK_BUFFER + (safeLength - 1) );
     }
 
     protected void paintMinorTickForVertSlider( Graphics g, Rectangle tickBounds, int y ) {
         g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
 
         if (MetalUtils.isLeftToRight(slider)) {
-            g.drawLine( TICK_BUFFER, y, TICK_BUFFER + (tickLength / 2), y );
+            g.drawLine( TICK_BUFFER, y, TICK_BUFFER + (safeLength / 2), y );
         }
         else {
-            g.drawLine( 0, y, tickLength/2, y );
+            g.drawLine( 0, y, safeLength/2, y );
         }
     }
 
@@ -546,10 +547,10 @@
         g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
 
         if (MetalUtils.isLeftToRight(slider)) {
-            g.drawLine( TICK_BUFFER, y, TICK_BUFFER + tickLength, y );
+            g.drawLine( TICK_BUFFER, y, TICK_BUFFER + safeLength, y );
         }
         else {
-            g.drawLine( 0, y, tickLength, y );
+            g.drawLine( 0, y, safeLength, y );
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/ToolTipManager/Test6657026.java	Thu Sep 03 19:42:27 2009 +0400
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests shared ToolTipManager in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+import javax.swing.ToolTipManager;
+
+public class Test6657026 implements Runnable {
+
+    private static final int DISMISS = 4000;
+    private static final int INITIAL = 750;
+    private static final int RESHOW = 500;
+
+    public static void main(String[] args) throws InterruptedException {
+        ToolTipManager manager = ToolTipManager.sharedInstance();
+        if (DISMISS != manager.getDismissDelay()) {
+            throw new Error("unexpected dismiss delay");
+        }
+        if (INITIAL != manager.getInitialDelay()) {
+            throw new Error("unexpected initial delay");
+        }
+        if (RESHOW != manager.getReshowDelay()) {
+            throw new Error("unexpected reshow delay");
+        }
+        manager.setDismissDelay(DISMISS + 1);
+        manager.setInitialDelay(INITIAL + 1);
+        manager.setReshowDelay(RESHOW + 1);
+
+        ThreadGroup group = new ThreadGroup("$$$");
+        Thread thread = new Thread(group, new Test6657026());
+        thread.start();
+        thread.join();
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        ToolTipManager manager = ToolTipManager.sharedInstance();
+        if (DISMISS != manager.getDismissDelay()) {
+            throw new Error("shared dismiss delay");
+        }
+        if (INITIAL != manager.getInitialDelay()) {
+            throw new Error("shared initial delay");
+        }
+        if (RESHOW != manager.getReshowDelay()) {
+            throw new Error("shared reshow delay");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/UIManager/Test6657026.java	Thu Sep 03 19:42:27 2009 +0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests shared UIManager in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+
+import javax.swing.UIManager;
+import javax.swing.UIManager.LookAndFeelInfo;
+
+public class Test6657026 implements Runnable {
+
+    public static void main(String[] args) throws Exception {
+        if (UIManager.getInstalledLookAndFeels().length == 0) {
+            throw new Error("unexpected amount of look&feels");
+        }
+        UIManager.setInstalledLookAndFeels(new LookAndFeelInfo[0]);
+        if (UIManager.getInstalledLookAndFeels().length != 0) {
+            throw new Error("unexpected amount of look&feels");
+        }
+
+        ThreadGroup group = new ThreadGroup("$$$");
+        Thread thread = new Thread(group, new Test6657026());
+        thread.start();
+        thread.join();
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        if (UIManager.getInstalledLookAndFeels().length == 0) {
+            throw new Error("shared look&feels");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/basic/BasicSplitPaneUI/Test6657026.java	Thu Sep 03 19:42:27 2009 +0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests shared BasicSplitPaneUI in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+
+import java.awt.event.ActionEvent;
+import java.util.Set;
+import javax.swing.JSplitPane;
+import javax.swing.plaf.basic.BasicSplitPaneUI;
+
+public class Test6657026 extends BasicSplitPaneUI implements Runnable {
+
+    public static void main(String[] args) throws InterruptedException {
+        if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()){
+            throw new Error("unexpected traversal keys");
+        }
+        new JSplitPane() {
+            public void setFocusTraversalKeys(int id, Set keystrokes) {
+                keystrokes.clear();
+                super.setFocusTraversalKeys(id, keystrokes);
+            }
+        };
+        if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()) {
+            throw new Error("shared traversal keys");
+        }
+        KEYBOARD_DIVIDER_MOVE_OFFSET = -KEYBOARD_DIVIDER_MOVE_OFFSET;
+
+        ThreadGroup group = new ThreadGroup("$$$");
+        Thread thread = new Thread(group, new Test6657026());
+        thread.start();
+        thread.join();
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()) {
+            throw new Error("shared traversal keys");
+        }
+        JSplitPane pane = new JSplitPane();
+        pane.setUI(this);
+
+        createFocusListener().focusGained(null); // allows actions
+        test(pane, "positiveIncrement", 3);
+        test(pane, "negativeIncrement", 0);
+    }
+
+    private static void test(JSplitPane pane, String action, int expected) {
+        ActionEvent event = new ActionEvent(pane, expected, action);
+        pane.getActionMap().get(action).actionPerformed(event);
+        int actual = pane.getDividerLocation();
+        if (actual != expected) {
+            throw new Error(actual + ", but expected " + expected);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/metal/MetalBorders/Test6657026.java	Thu Sep 03 19:42:27 2009 +0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests constancy of borders
+ * @author Sergey Malenkov
+ */
+
+import java.awt.Insets;
+import javax.swing.border.Border;
+import javax.swing.plaf.metal.MetalBorders.ButtonBorder;
+import javax.swing.plaf.metal.MetalBorders.MenuBarBorder;
+import javax.swing.plaf.metal.MetalBorders.MenuItemBorder;
+import javax.swing.plaf.metal.MetalBorders.PopupMenuBorder;
+
+public class Test6657026 {
+
+    private static final Insets NEGATIVE = new Insets(Integer.MIN_VALUE,
+                                                      Integer.MIN_VALUE,
+                                                      Integer.MIN_VALUE,
+                                                      Integer.MIN_VALUE);
+
+    public static void main(String[] args) {
+        new ButtonBorder() {{borderInsets = NEGATIVE;}};
+        new MenuBarBorder() {{borderInsets = NEGATIVE;}};
+        new MenuItemBorder() {{borderInsets = NEGATIVE;}};
+        new PopupMenuBorder() {{borderInsets = NEGATIVE;}};
+
+        test(create("ButtonBorder"));
+        test(create("MenuBarBorder"));
+        test(create("MenuItemBorder"));
+        test(create("PopupMenuBorder"));
+
+        test(create("Flush3DBorder"));
+        test(create("InternalFrameBorder"));
+        // NOT USED: test(create("FrameBorder"));
+        // NOT USED: test(create("DialogBorder"));
+        test(create("PaletteBorder"));
+        test(create("OptionDialogBorder"));
+        test(create("ScrollPaneBorder"));
+    }
+
+    private static Border create(String name) {
+        try {
+            name = "javax.swing.plaf.metal.MetalBorders$" + name;
+            return (Border) Class.forName(name).newInstance();
+        }
+        catch (Exception exception) {
+            throw new Error("unexpected exception", exception);
+        }
+    }
+
+    private static void test(Border border) {
+        Insets actual = border.getBorderInsets(null);
+        if (NEGATIVE.equals(actual)) {
+            throw new Error("unexpected insets in " + border.getClass());
+        }
+        Insets expected = (Insets) actual.clone();
+        // modify
+        actual.top++;
+        actual.left++;
+        actual.right++;
+        actual.bottom++;
+        // validate
+        if (!expected.equals(border.getBorderInsets(null))) {
+            throw new Error("shared insets in " + border.getClass());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/metal/MetalBumps/Test6657026.java	Thu Sep 03 19:42:27 2009 +0400
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests shared MetalBumps in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+import java.text.AttributedCharacterIterator;
+import javax.swing.Icon;
+import javax.swing.plaf.metal.MetalBorders.ToolBarBorder;
+
+public class Test6657026 extends ToolBarBorder implements Runnable {
+
+    public static void main(String[] args) throws Exception {
+        new Test6657026().test();
+
+        ThreadGroup group = new ThreadGroup("$$$");
+        Thread thread = new Thread(group, new Test6657026());
+        thread.start();
+        thread.join();
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        test();
+    }
+
+    private void test() {
+        MyGraphics mg = new MyGraphics();
+        Icon icon = bumps;
+        icon.paintIcon(mg.component, mg, 0, 0);
+        if (mg.image != null) {
+            boolean failed = true;
+            int value = mg.image.getRGB(0, 0);
+            for (int x = 0; x < mg.image.getWidth(); x++) {
+                for (int y = 0; y < mg.image.getHeight(); y++) {
+                    int current = mg.image.getRGB(x, y);
+                    if (current != value) {
+                        mg.image.setRGB(x, y, value);
+                        failed = false;
+                    }
+
+                }
+            }
+            if (failed) {
+                throw new Error("shared metal bumps");
+            }
+        }
+    }
+
+    private static class MyGraphics extends Graphics {
+
+        private final Component component = new Component() {};
+        private BufferedImage image;
+
+        public Graphics create() {
+            return null;  // TODO: check
+        }
+
+        public void translate(int x, int y) {
+            // TODO: check
+        }
+
+        public Color getColor() {
+            return null;  // TODO: check
+        }
+
+        public void setColor(Color color) {
+            // TODO: check
+        }
+
+        public void setPaintMode() {
+            // TODO: check
+        }
+
+        public void setXORMode(Color c1) {
+            // TODO: check
+        }
+
+        public Font getFont() {
+            return null;  // TODO: check
+        }
+
+        public void setFont(Font font) {
+            // TODO: check
+        }
+
+        public FontMetrics getFontMetrics(Font font) {
+            return null;  // TODO: check
+        }
+
+        public Rectangle getClipBounds() {
+            return null;  // TODO: check
+        }
+
+        public void clipRect(int x, int y, int width, int height) {
+            // TODO: check
+        }
+
+        public void setClip(int x, int y, int width, int height) {
+            // TODO: check
+        }
+
+        public Shape getClip() {
+            return null;  // TODO: check
+        }
+
+        public void setClip(Shape clip) {
+            // TODO: check
+        }
+
+        public void copyArea(int x, int y, int width, int height, int dx, int dy) {
+            // TODO: check
+        }
+
+        public void drawLine(int x1, int y1, int x2, int y2) {
+            // TODO: check
+        }
+
+        public void fillRect(int x, int y, int width, int height) {
+            // TODO: check
+        }
+
+        public void clearRect(int x, int y, int width, int height) {
+            // TODO: check
+        }
+
+        public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
+            // TODO: check
+        }
+
+        public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
+            // TODO: check
+        }
+
+        public void drawOval(int x, int y, int width, int height) {
+            // TODO: check
+        }
+
+        public void fillOval(int x, int y, int width, int height) {
+            // TODO: check
+        }
+
+        public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
+            // TODO: check
+        }
+
+        public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
+            // TODO: check
+        }
+
+        public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
+            // TODO: check
+        }
+
+        public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
+            // TODO: check
+        }
+
+        public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
+            // TODO: check
+        }
+
+        public void drawString(String str, int x, int y) {
+            // TODO: check
+        }
+
+        public void drawString(AttributedCharacterIterator iterator, int x, int y) {
+            // TODO: check
+        }
+
+        public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
+            return false;  // TODO: check
+        }
+
+        public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
+            return false;  // TODO: check
+        }
+
+        public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
+            return false;  // TODO: check
+        }
+
+        public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) {
+            return false;  // TODO: check
+        }
+
+        public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
+            if (img instanceof BufferedImage) {
+                this.image = (BufferedImage) img;
+            }
+            return false;  // TODO: check
+        }
+
+        public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) {
+            return false;  // TODO: check
+        }
+
+        public void dispose() {
+            // TODO: check
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/metal/MetalInternalFrameUI/Test6657026.java	Thu Sep 03 19:42:27 2009 +0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests shared MetalInternalFrameUI in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+
+import javax.swing.JInternalFrame;
+import javax.swing.JPanel;
+import javax.swing.UIManager;
+import javax.swing.plaf.metal.MetalInternalFrameUI;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+
+public class Test6657026 extends MetalInternalFrameUI implements Runnable {
+
+    public static void main(String[] args) throws Exception {
+        UIManager.setLookAndFeel(new MetalLookAndFeel());
+
+        ThreadGroup group = new ThreadGroup("$$$");
+        Thread thread = new Thread(group, new Test6657026());
+        thread.start();
+        thread.join();
+
+        new JInternalFrame().setContentPane(new JPanel());
+    }
+
+    public Test6657026() {
+        super(null);
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        IS_PALETTE = JInternalFrame.CONTENT_PANE_PROPERTY;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/metal/MetalSliderUI/Test6657026.java	Thu Sep 03 19:42:27 2009 +0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests shared MetalSliderUI in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+
+import javax.swing.JSlider;
+import javax.swing.UIManager;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+import javax.swing.plaf.metal.MetalSliderUI;
+
+public class Test6657026 extends MetalSliderUI implements Runnable {
+
+    public static void main(String[] args) throws Exception {
+        UIManager.setLookAndFeel(new MetalLookAndFeel());
+        JSlider slider = new JSlider();
+        test(slider);
+
+        ThreadGroup group = new ThreadGroup("$$$");
+        Thread thread = new Thread(group, new Test6657026());
+        thread.start();
+        thread.join();
+
+        test(slider);
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        JSlider slider = new JSlider();
+        test(slider);
+        tickLength = -10000;
+    }
+
+    private static void test(JSlider slider) {
+        MetalSliderUI ui = (MetalSliderUI) slider.getUI();
+        int actual = ui.getTickLength();
+        if (actual != 11) {
+            throw new Error(actual + ", but expected 11");
+        }
+    }
+}