From f6d3feef93e29356efb407414f49e2c957e39a1d Mon Sep 17 00:00:00 2001 From: rupashka Date: Thu, 23 Jul 2009 17:56:53 +0400 Subject: [PATCH] 6460525: javax/swing/JFileChooser/6396844/TwentyThousandTest.java times out Reviewed-by: malenkov, peterz --- .../classes/javax/swing/JFileChooser.java | 7 +- .../swing/plaf/basic/BasicDirectoryModel.java | 10 +- .../classes/sun/awt/shell/ShellFolder.java | 60 +++- .../sun/awt/shell/ShellFolderManager.java | 10 +- src/share/classes/sun/swing/FilePane.java | 7 +- .../sun/awt/shell/Win32ShellFolder2.java | 296 +++++++++--------- .../awt/shell/Win32ShellFolderManager2.java | 93 ++++-- 7 files changed, 281 insertions(+), 202 deletions(-) diff --git a/src/share/classes/javax/swing/JFileChooser.java b/src/share/classes/javax/swing/JFileChooser.java index 82c85fe9f..8ba9c7c42 100644 --- a/src/share/classes/javax/swing/JFileChooser.java +++ b/src/share/classes/javax/swing/JFileChooser.java @@ -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 @@ -739,6 +739,11 @@ public class JFileChooser extends JComponent implements Accessible { dialog.show(); firePropertyChange("JFileChooserDialogIsClosingProperty", dialog, null); + + // Remove all components from dialog. The MetalFileChooserUI.installUI() method (and other LAFs) + // registers AWT listener for dialogs and produces memory leaks. It happens when + // installUI invoked after the showDialog method. + dialog.getContentPane().removeAll(); dialog.dispose(); dialog = null; return returnValue; diff --git a/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java b/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java index 74f24b6eb..1e5d80f8e 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java @@ -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 @@ -232,6 +232,10 @@ public class BasicDirectoryModel extends AbstractListModel implements PropertyCh public void run0() { FileSystemView fileSystem = filechooser.getFileSystemView(); + if (isInterrupted()) { + return; + } + File[] list = fileSystem.getFiles(currentDirectory, filechooser.isFileHidingEnabled()); if (isInterrupted()) { @@ -268,8 +272,8 @@ public class BasicDirectoryModel extends AbstractListModel implements PropertyCh // To avoid loads of synchronizations with Invoker and improve performance we // execute the whole block on the COM thread - DoChangeContents doChangeContents = ShellFolder.getInvoker().invoke(new Callable() { - public DoChangeContents call() throws Exception { + DoChangeContents doChangeContents = ShellFolder.invoke(new Callable() { + public DoChangeContents call() { int newSize = newFileCache.size(); int oldSize = fileCache.size(); diff --git a/src/share/classes/sun/awt/shell/ShellFolder.java b/src/share/classes/sun/awt/shell/ShellFolder.java index d38fd98e0..cf3c78933 100644 --- a/src/share/classes/sun/awt/shell/ShellFolder.java +++ b/src/share/classes/sun/awt/shell/ShellFolder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-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 @@ -289,8 +289,8 @@ public abstract class ShellFolder extends File { // To avoid loads of synchronizations with Invoker and improve performance we // synchronize the whole code of the sort method once - getInvoker().invoke(new Callable() { - public Void call() throws Exception { + invoke(new Callable() { + public Void call() { // Check that we can use the ShellFolder.sortChildren() method: // 1. All files have the same non-null parent // 2. All files is ShellFolders @@ -330,8 +330,8 @@ public abstract class ShellFolder extends File { public void sortChildren(final List files) { // To avoid loads of synchronizations with Invoker and improve performance we // synchronize the whole code of the sort method once - getInvoker().invoke(new Callable() { - public Void call() throws Exception { + invoke(new Callable() { + public Void call() { Collections.sort(files, FILE_COMPARATOR); return null; @@ -501,18 +501,62 @@ public abstract class ShellFolder extends File { return invoker; } + /** + * Invokes the {@code task} which doesn't throw checked exceptions + * from its {@code call} method. If invokation is interrupted then Thread.currentThread().isInterrupted() will + * be set and result will be {@code null} + */ + public static T invoke(Callable task) { + try { + return invoke(task, RuntimeException.class); + } catch (InterruptedException e) { + return null; + } + } + + /** + * Invokes the {@code task} which throws checked exceptions from its {@code call} method. + * If invokation is interrupted then Thread.currentThread().isInterrupted() will + * be set and InterruptedException will be thrown as well. + */ + public static T invoke(Callable task, Class exceptionClass) + throws InterruptedException, E { + try { + return getInvoker().invoke(task); + } catch (Exception e) { + if (e instanceof RuntimeException) { + // Rethrow unchecked exceptions + throw (RuntimeException) e; + } + + if (e instanceof InterruptedException) { + // Set isInterrupted flag for current thread + Thread.currentThread().interrupt(); + + // Rethrow InterruptedException + throw (InterruptedException) e; + } + + if (exceptionClass.isInstance(e)) { + throw exceptionClass.cast(e); + } + + throw new RuntimeException("Unexpected error", e); + } + } + /** * Interface allowing to invoke tasks in different environments on different platforms. */ public static interface Invoker { /** - * Invokes a callable task. If the {@code task} throws a checked exception, - * it will be wrapped into a {@link RuntimeException} + * Invokes a callable task. * * @param task a task to invoke + * @throws Exception {@code InterruptedException} or an exception that was thrown from the {@code task} * @return the result of {@code task}'s invokation */ - T invoke(Callable task); + T invoke(Callable task) throws Exception; } /** diff --git a/src/share/classes/sun/awt/shell/ShellFolderManager.java b/src/share/classes/sun/awt/shell/ShellFolderManager.java index dc8901f7b..fe00063ff 100644 --- a/src/share/classes/sun/awt/shell/ShellFolderManager.java +++ b/src/share/classes/sun/awt/shell/ShellFolderManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-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 @@ -108,12 +108,8 @@ class ShellFolderManager { } private static class DirectInvoker implements ShellFolder.Invoker { - public T invoke(Callable task) { - try { - return task.call(); - } catch (Exception e) { - throw new RuntimeException(e); - } + public T invoke(Callable task) throws Exception { + return task.call(); } } } diff --git a/src/share/classes/sun/swing/FilePane.java b/src/share/classes/sun/swing/FilePane.java index eae3d5a0d..4aa805222 100644 --- a/src/share/classes/sun/swing/FilePane.java +++ b/src/share/classes/sun/swing/FilePane.java @@ -1,6 +1,5 @@ - /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-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 @@ -905,8 +904,8 @@ public class FilePane extends JPanel implements PropertyChangeListener { @Override public void sort() { - ShellFolder.getInvoker().invoke(new Callable() { - public Void call() throws Exception { + ShellFolder.invoke(new Callable() { + public Void call() { DetailsTableRowSorter.super.sort(); return null; } diff --git a/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java b/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java index 716b56238..1b81007fe 100644 --- a/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-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 @@ -29,7 +29,6 @@ import java.awt.Image; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.util.*; import java.util.concurrent.*; @@ -185,8 +184,8 @@ final class Win32ShellFolder2 extends ShellFolder { boolean disposed; public void dispose() { if (disposed) return; - ShellFolder.getInvoker().invoke(new Callable() { - public Void call() throws Exception { + invoke(new Callable() { + public Void call() { if (relativePIDL != 0) { releasePIDL(relativePIDL); } @@ -224,7 +223,7 @@ final class Win32ShellFolder2 extends ShellFolder { */ private boolean isPersonal; - private static String composePathForCsidl(int csidl) throws IOException { + private static String composePathForCsidl(int csidl) throws IOException, InterruptedException { String path = getFileSystemPath(csidl); return path == null ? ("ShellFolder: 0x" + Integer.toHexString(csidl)) @@ -235,12 +234,13 @@ final class Win32ShellFolder2 extends ShellFolder { * Create a system special shell folder, such as the * desktop or Network Neighborhood. */ - Win32ShellFolder2(final int csidl) throws IOException { + Win32ShellFolder2(final int csidl) throws IOException, InterruptedException { // Desktop is parent of DRIVES and NETWORK, not necessarily // other special shell folders. super(null, composePathForCsidl(csidl)); - ShellFolder.getInvoker().invoke(new Callable() { - public Void call() throws Exception { + + invoke(new Callable() { + public Void call() throws InterruptedException { if (csidl == DESKTOP) { initDesktop(); } else { @@ -276,7 +276,7 @@ final class Win32ShellFolder2 extends ShellFolder { } return null; } - }); + }, InterruptedException.class); sun.java2d.Disposer.addRecord(this, disposer); } @@ -296,13 +296,13 @@ final class Win32ShellFolder2 extends ShellFolder { /** * Creates a shell folder with a parent and relative PIDL */ - Win32ShellFolder2(final Win32ShellFolder2 parent, final long relativePIDL) { + Win32ShellFolder2(final Win32ShellFolder2 parent, final long relativePIDL) throws InterruptedException { super(parent, - ShellFolder.getInvoker().invoke(new Callable() { - public String call() throws Exception { + invoke(new Callable() { + public String call() { return getFileSystemPath(parent.getIShellFolder(), relativePIDL); } - }) + }, RuntimeException.class) ); this.disposer.relativePIDL = relativePIDL; getAbsolutePath(); @@ -335,8 +335,8 @@ final class Win32ShellFolder2 extends ShellFolder { * drive (normally "C:\"). */ protected Object writeReplace() throws java.io.ObjectStreamException { - return ShellFolder.getInvoker().invoke(new Callable() { - public File call() throws Exception { + return invoke(new Callable() { + public File call() { if (isFileSystem()) { return new File(getPath()); } else { @@ -398,11 +398,11 @@ final class Win32ShellFolder2 extends ShellFolder { /** * Accessor for IShellFolder */ - public long getIShellFolder() { + private long getIShellFolder() { if (disposer.pIShellFolder == 0) { - disposer.pIShellFolder = - ShellFolder.getInvoker().invoke(new Callable() { - public Long call() throws Exception { + try { + disposer.pIShellFolder = invoke(new Callable() { + public Long call() { assert(isDirectory()); assert(parent != null); long parentIShellFolder = getParentIShellFolder(); @@ -421,7 +421,10 @@ final class Win32ShellFolder2 extends ShellFolder { } return pIShellFolder; } - }); + }, RuntimeException.class); + } catch (InterruptedException e) { + // Ignore error + } } return disposer.pIShellFolder; } @@ -505,18 +508,23 @@ final class Win32ShellFolder2 extends ShellFolder { } if (parent == rhs.parent || parent.equals(rhs.parent)) { - return pidlsEqual(getParentIShellFolder(), disposer.relativePIDL, rhs.disposer.relativePIDL); + try { + return pidlsEqual(getParentIShellFolder(), disposer.relativePIDL, rhs.disposer.relativePIDL); + } catch (InterruptedException e) { + return false; + } } return false; } - private static boolean pidlsEqual(final long pIShellFolder, final long pidl1, final long pidl2) { - return ShellFolder.getInvoker().invoke(new Callable() { - public Boolean call() throws Exception { - return (compareIDs(pIShellFolder, pidl1, pidl2) == 0); + private static boolean pidlsEqual(final long pIShellFolder, final long pidl1, final long pidl2) + throws InterruptedException { + return invoke(new Callable() { + public Boolean call() { + return compareIDs(pIShellFolder, pidl1, pidl2) == 0; } - }); + }, RuntimeException.class); } // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details @@ -539,14 +547,16 @@ final class Win32ShellFolder2 extends ShellFolder { * Return whether the given attribute flag is set for this object */ public boolean hasAttribute(final int attribute) { - return ShellFolder.getInvoker().invoke(new Callable() { - public Boolean call() throws Exception { + Boolean result = invoke(new Callable() { + public Boolean call() { // Caching at this point doesn't seem to be cost efficient return (getAttributes0(getParentIShellFolder(), getRelativePIDL(), attribute) & attribute) != 0; } }); + + return result != null && result; } /** @@ -561,32 +571,29 @@ final class Win32ShellFolder2 extends ShellFolder { private static native int getAttributes0(long pParentIShellFolder, long pIDL, int attrsMask); // Return the path to the underlying file system object + // Should be called from the COM thread private static String getFileSystemPath(final long parentIShellFolder, final long relativePIDL) { - return ShellFolder.getInvoker().invoke(new Callable() { - public String call() throws Exception { - int linkedFolder = ATTRIB_LINK | ATTRIB_FOLDER; - if (parentIShellFolder == Win32ShellFolderManager2.getNetwork().getIShellFolder() && - getAttributes0(parentIShellFolder, relativePIDL, linkedFolder) == linkedFolder) { - - String s = - getFileSystemPath(Win32ShellFolderManager2.getDesktop().getIShellFolder(), - getLinkLocation(parentIShellFolder, relativePIDL, false)); - if (s != null && s.startsWith("\\\\")) { - return s; - } - } - return getDisplayNameOf(parentIShellFolder, relativePIDL, SHGDN_FORPARSING); + int linkedFolder = ATTRIB_LINK | ATTRIB_FOLDER; + if (parentIShellFolder == Win32ShellFolderManager2.getNetwork().getIShellFolder() && + getAttributes0(parentIShellFolder, relativePIDL, linkedFolder) == linkedFolder) { + + String s = + getFileSystemPath(Win32ShellFolderManager2.getDesktop().getIShellFolder(), + getLinkLocation(parentIShellFolder, relativePIDL, false)); + if (s != null && s.startsWith("\\\\")) { + return s; } - }); + } + return getDisplayNameOf(parentIShellFolder, relativePIDL, SHGDN_FORPARSING); } // Needs to be accessible to Win32ShellFolderManager2 - static String getFileSystemPath(final int csidl) throws IOException { - return ShellFolder.getInvoker().invoke(new Callable() { - public String call() throws Exception { + static String getFileSystemPath(final int csidl) throws IOException, InterruptedException { + return invoke(new Callable() { + public String call() throws IOException { return getFileSystemPath0(csidl); } - }); + }, IOException.class); } // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details @@ -630,13 +637,14 @@ final class Win32ShellFolder2 extends ShellFolder { */ // Returns an IEnumIDList interface for an IShellFolder. The value // returned must be released using releaseEnumObjects(). - private long getEnumObjects(long pIShellFolder, final boolean includeHiddenFiles) { - final boolean isDesktop = (disposer.pIShellFolder == getDesktopIShellFolder()); - return ShellFolder.getInvoker().invoke(new Callable() { - public Long call() throws Exception { + private long getEnumObjects(final boolean includeHiddenFiles) throws InterruptedException { + return invoke(new Callable() { + public Long call() { + boolean isDesktop = disposer.pIShellFolder == getDesktopIShellFolder(); + return getEnumObjects(disposer.pIShellFolder, isDesktop, includeHiddenFiles); } - }); + }, RuntimeException.class); } // Returns an IEnumIDList interface for an IShellFolder. The value @@ -670,58 +678,62 @@ final class Win32ShellFolder2 extends ShellFolder { security.checkRead(getPath()); } - return ShellFolder.getInvoker().invoke(new Callable() { - public File[] call() throws Exception { - if (!isDirectory()) { - return null; - } - // Links to directories are not directories and cannot be parents. - // This does not apply to folders in My Network Places (NetHood) - // because they are both links and real directories! - if (isLink() && !hasAttribute(ATTRIB_FOLDER)) { - return new File[0]; - } - - Win32ShellFolder2 desktop = Win32ShellFolderManager2.getDesktop(); - Win32ShellFolder2 personal = Win32ShellFolderManager2.getPersonal(); + try { + return invoke(new Callable() { + public File[] call() throws InterruptedException { + if (!isDirectory()) { + return null; + } + // Links to directories are not directories and cannot be parents. + // This does not apply to folders in My Network Places (NetHood) + // because they are both links and real directories! + if (isLink() && !hasAttribute(ATTRIB_FOLDER)) { + return new File[0]; + } - // If we are a directory, we have a parent and (at least) a - // relative PIDL. We must first ensure we are bound to the - // parent so we have an IShellFolder to query. - long pIShellFolder = getIShellFolder(); - // Now we can enumerate the objects in this folder. - ArrayList list = new ArrayList(); - long pEnumObjects = getEnumObjects(pIShellFolder, includeHiddenFiles); - if (pEnumObjects != 0) { - long childPIDL; - int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR; - do { - childPIDL = getNextChild(pEnumObjects); - boolean releasePIDL = true; - if (childPIDL != 0 && - (getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) { - Win32ShellFolder2 childFolder; - if (Win32ShellFolder2.this.equals(desktop) - && personal != null - && pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL)) { - childFolder = personal; - } else { - childFolder = new Win32ShellFolder2(Win32ShellFolder2.this, childPIDL); - releasePIDL = false; + Win32ShellFolder2 desktop = Win32ShellFolderManager2.getDesktop(); + Win32ShellFolder2 personal = Win32ShellFolderManager2.getPersonal(); + + // If we are a directory, we have a parent and (at least) a + // relative PIDL. We must first ensure we are bound to the + // parent so we have an IShellFolder to query. + long pIShellFolder = getIShellFolder(); + // Now we can enumerate the objects in this folder. + ArrayList list = new ArrayList(); + long pEnumObjects = getEnumObjects(includeHiddenFiles); + if (pEnumObjects != 0) { + long childPIDL; + int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR; + do { + childPIDL = getNextChild(pEnumObjects); + boolean releasePIDL = true; + if (childPIDL != 0 && + (getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) { + Win32ShellFolder2 childFolder; + if (Win32ShellFolder2.this.equals(desktop) + && personal != null + && pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL)) { + childFolder = personal; + } else { + childFolder = new Win32ShellFolder2(Win32ShellFolder2.this, childPIDL); + releasePIDL = false; + } + list.add(childFolder); } - list.add(childFolder); - } - if (releasePIDL) { - releasePIDL(childPIDL); - } - } while (childPIDL != 0 && !Thread.currentThread().isInterrupted()); - releaseEnumObjects(pEnumObjects); + if (releasePIDL) { + releasePIDL(childPIDL); + } + } while (childPIDL != 0 && !Thread.currentThread().isInterrupted()); + releaseEnumObjects(pEnumObjects); + } + return Thread.currentThread().isInterrupted() + ? new File[0] + : list.toArray(new ShellFolder[list.size()]); } - return Thread.currentThread().isInterrupted() - ? new File[0] - : list.toArray(new ShellFolder[list.size()]); - } - }); + }, InterruptedException.class); + } catch (InterruptedException e) { + return new File[0]; + } } @@ -730,13 +742,13 @@ final class Win32ShellFolder2 extends ShellFolder { * * @return The child shellfolder, or null if not found. */ - Win32ShellFolder2 getChildByPath(final String filePath) { - return ShellFolder.getInvoker().invoke(new Callable() { - public Win32ShellFolder2 call() throws Exception { + Win32ShellFolder2 getChildByPath(final String filePath) throws InterruptedException { + return invoke(new Callable() { + public Win32ShellFolder2 call() throws InterruptedException { long pIShellFolder = getIShellFolder(); - long pEnumObjects = getEnumObjects(pIShellFolder, true); + long pEnumObjects = getEnumObjects(true); Win32ShellFolder2 child = null; - long childPIDL = 0; + long childPIDL; while ((childPIDL = getNextChild(pEnumObjects)) != 0) { if (getAttributes0(pIShellFolder, childPIDL, ATTRIB_FILESYSTEM) != 0) { @@ -753,7 +765,7 @@ final class Win32ShellFolder2 extends ShellFolder { releaseEnumObjects(pEnumObjects); return child; } - }); + }, InterruptedException.class); } private Boolean cachedIsLink; @@ -791,8 +803,8 @@ final class Win32ShellFolder2 extends ShellFolder { } private ShellFolder getLinkLocation(final boolean resolve) { - return ShellFolder.getInvoker().invoke(new Callable() { - public ShellFolder call() throws Exception { + return invoke(new Callable() { + public ShellFolder call() { if (!isLink()) { return null; } @@ -805,6 +817,8 @@ final class Win32ShellFolder2 extends ShellFolder { location = Win32ShellFolderManager2.createShellFolderFromRelativePIDL(getDesktop(), linkLocationPIDL); + } catch (InterruptedException e) { + // Return null } catch (InternalError e) { // Could be a link to a non-bindable object, such as a network connection // TODO: getIShellFolder() should throw FileNotFoundException instead @@ -816,19 +830,12 @@ final class Win32ShellFolder2 extends ShellFolder { } // Parse a display name into a PIDL relative to the current IShellFolder. - long parseDisplayName(final String name) throws FileNotFoundException { - try { - return ShellFolder.getInvoker().invoke(new Callable() { - public Long call() throws Exception { - return parseDisplayName0(getIShellFolder(), name); - } - }); - } catch (RuntimeException e) { - if (e.getCause() instanceof IOException) { - throw new FileNotFoundException("Could not find file " + name); + long parseDisplayName(final String name) throws IOException, InterruptedException { + return invoke(new Callable() { + public Long call() throws IOException { + return parseDisplayName0(getIShellFolder(), name); } - throw e; - } + }, IOException.class); } // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details @@ -846,8 +853,8 @@ final class Win32ShellFolder2 extends ShellFolder { public String getDisplayName() { if (displayName == null) { displayName = - ShellFolder.getInvoker().invoke(new Callable() { - public String call() throws Exception { + invoke(new Callable() { + public String call() { return getDisplayNameOf(getParentIShellFolder(), getRelativePIDL(), SHGDN_NORMAL); } @@ -867,8 +874,8 @@ final class Win32ShellFolder2 extends ShellFolder { if (folderType == null) { final long absolutePIDL = getAbsolutePIDL(); folderType = - ShellFolder.getInvoker().invoke(new Callable() { - public String call() throws Exception { + invoke(new Callable() { + public String call() { return getFolderType(absolutePIDL); } }); @@ -926,15 +933,12 @@ final class Win32ShellFolder2 extends ShellFolder { public static native int[] getFileChooserBitmapBits(); + // Should be called from the COM thread private long getIShellIcon() { if (pIShellIcon == -1L) { - pIShellIcon = - ShellFolder.getInvoker().invoke(new Callable() { - public Long call() throws Exception { - return getIShellIcon(getIShellFolder()); - } - }); + pIShellIcon = getIShellIcon(getIShellFolder()); } + return pIShellIcon; } @@ -988,8 +992,8 @@ final class Win32ShellFolder2 extends ShellFolder { Image icon = getLargeIcon ? largeIcon : smallIcon; if (icon == null) { icon = - ShellFolder.getInvoker().invoke(new Callable() { - public Image call() throws Exception { + invoke(new Callable() { + public Image call() { Image newIcon = null; if (isFileSystem()) { long parentIShellIcon = (parent != null) @@ -1113,8 +1117,8 @@ final class Win32ShellFolder2 extends ShellFolder { private static final int LVCFMT_CENTER = 2; public ShellFolderColumnInfo[] getFolderColumns() { - return ShellFolder.getInvoker().invoke(new Callable() { - public ShellFolderColumnInfo[] call() throws Exception { + return invoke(new Callable() { + public ShellFolderColumnInfo[] call() { ShellFolderColumnInfo[] columns = doGetColumnInfo(getIShellFolder()); if (columns != null) { @@ -1143,8 +1147,8 @@ final class Win32ShellFolder2 extends ShellFolder { } public Object getFolderColumnValue(final int column) { - return ShellFolder.getInvoker().invoke(new Callable() { - public Object call() throws Exception { + return invoke(new Callable() { + public Object call() { return doGetColumnValue(getParentIShellFolder(), getRelativePIDL(), column); } }); @@ -1163,8 +1167,8 @@ final class Win32ShellFolder2 extends ShellFolder { public void sortChildren(final List files) { // To avoid loads of synchronizations with Invoker and improve performance we // synchronize the whole code of the sort method once - getInvoker().invoke(new Callable() { - public Void call() throws Exception { + invoke(new Callable() { + public Void call() { Collections.sort(files, new ColumnComparator(getIShellFolder(), 0)); return null; @@ -1184,19 +1188,21 @@ final class Win32ShellFolder2 extends ShellFolder { // compares 2 objects within this folder by the specified column public int compare(final File o, final File o1) { - return ShellFolder.getInvoker().invoke(new Callable() { - public Integer call() throws Exception { + Integer result = invoke(new Callable() { + public Integer call() { if (o instanceof Win32ShellFolder2 - && o1 instanceof Win32ShellFolder2) { + && o1 instanceof Win32ShellFolder2) { // delegates comparison to native method return compareIDsByColumn(parentIShellFolder, - ((Win32ShellFolder2) o).getRelativePIDL(), - ((Win32ShellFolder2) o1).getRelativePIDL(), - columnIdx); + ((Win32ShellFolder2) o).getRelativePIDL(), + ((Win32ShellFolder2) o1).getRelativePIDL(), + columnIdx); } return 0; } }); + + return result == null ? 0 : result; } } } diff --git a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java index 158684635..4471a3ec0 100644 --- a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-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 @@ -58,10 +58,15 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { } public ShellFolder createShellFolder(File file) throws FileNotFoundException { - return createShellFolder(getDesktop(), file); + try { + return createShellFolder(getDesktop(), file); + } catch (InterruptedException e) { + throw new FileNotFoundException("Execution was interrupted"); + } } - static Win32ShellFolder2 createShellFolder(Win32ShellFolder2 parent, File file) throws FileNotFoundException { + static Win32ShellFolder2 createShellFolder(Win32ShellFolder2 parent, File file) + throws FileNotFoundException, InterruptedException { long pIDL; try { pIDL = parent.parseDisplayName(file.getCanonicalPath()); @@ -77,7 +82,8 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { return folder; } - static Win32ShellFolder2 createShellFolderFromRelativePIDL(Win32ShellFolder2 parent, long pIDL) { + static Win32ShellFolder2 createShellFolderFromRelativePIDL(Win32ShellFolder2 parent, long pIDL) + throws InterruptedException { // Walk down this relative pIDL, creating new nodes for each of the entries while (pIDL != 0) { long curPIDL = Win32ShellFolder2.copyFirstPIDLEntry(pIDL); @@ -108,7 +114,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { try { desktop = new Win32ShellFolder2(DESKTOP); } catch (IOException e) { - desktop = null; + // Ignore error + } catch (InterruptedException e) { + // Ignore error } } return desktop; @@ -119,7 +127,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { try { drives = new Win32ShellFolder2(DRIVES); } catch (IOException e) { - drives = null; + // Ignore error + } catch (InterruptedException e) { + // Ignore error } } return drives; @@ -132,8 +142,10 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { if (path != null) { recent = createShellFolder(getDesktop(), new File(path)); } + } catch (InterruptedException e) { + // Ignore error } catch (IOException e) { - recent = null; + // Ignore error } } return recent; @@ -144,7 +156,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { try { network = new Win32ShellFolder2(NETWORK); } catch (IOException e) { - network = null; + // Ignore error + } catch (InterruptedException e) { + // Ignore error } } return network; @@ -164,8 +178,10 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { personal.setIsPersonal(); } } + } catch (InterruptedException e) { + // Ignore error } catch (IOException e) { - personal = null; + // Ignore error } } return personal; @@ -267,6 +283,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { } } catch (IOException e) { // Skip this value + } catch (InterruptedException e) { + // Return empty result + return new File[0]; } } while (value != null); @@ -476,33 +495,39 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { return comThread; } - public T invoke(Callable task) { - try { - if (Thread.currentThread() == comThread) { - // if it's already called from the COM - // thread, we don't need to delegate the task - return task.call(); - } else { - while (true) { - Future future = submit(task); - - try { - return future.get(); - } catch (InterruptedException e) { - // Repeat the attempt - future.cancel(true); - } - } - } - } catch (Exception e) { - Throwable cause = (e instanceof ExecutionException) ? e.getCause() : e; - if (cause instanceof RuntimeException) { - throw (RuntimeException) cause; + public T invoke(Callable task) throws Exception { + if (Thread.currentThread() == comThread) { + // if it's already called from the COM + // thread, we don't need to delegate the task + return task.call(); + } else { + Future future; + + try { + future = submit(task); + } catch (RejectedExecutionException e) { + throw new InterruptedException(e.getMessage()); } - if (cause instanceof Error) { - throw (Error) cause; + + try { + return future.get(); + } catch (InterruptedException e) { + future.cancel(true); + + throw e; + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + + if (cause instanceof Exception) { + throw (Exception) cause; + } + + if (cause instanceof Error) { + throw (Error) cause; + } + + throw new RuntimeException("Unexpected error", cause); } - throw new RuntimeException(cause); } } } -- GitLab