提交 f6d3feef 编写于 作者: R rupashka

6460525: javax/swing/JFileChooser/6396844/TwentyThousandTest.java times out

Reviewed-by: malenkov, peterz
上级 4c55daa3
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -739,6 +739,11 @@ public class JFileChooser extends JComponent implements Accessible { ...@@ -739,6 +739,11 @@ public class JFileChooser extends JComponent implements Accessible {
dialog.show(); dialog.show();
firePropertyChange("JFileChooserDialogIsClosingProperty", dialog, null); 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.dispose();
dialog = null; dialog = null;
return returnValue; return returnValue;
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -232,6 +232,10 @@ public class BasicDirectoryModel extends AbstractListModel implements PropertyCh ...@@ -232,6 +232,10 @@ public class BasicDirectoryModel extends AbstractListModel implements PropertyCh
public void run0() { public void run0() {
FileSystemView fileSystem = filechooser.getFileSystemView(); FileSystemView fileSystem = filechooser.getFileSystemView();
if (isInterrupted()) {
return;
}
File[] list = fileSystem.getFiles(currentDirectory, filechooser.isFileHidingEnabled()); File[] list = fileSystem.getFiles(currentDirectory, filechooser.isFileHidingEnabled());
if (isInterrupted()) { if (isInterrupted()) {
...@@ -268,8 +272,8 @@ public class BasicDirectoryModel extends AbstractListModel implements PropertyCh ...@@ -268,8 +272,8 @@ public class BasicDirectoryModel extends AbstractListModel implements PropertyCh
// To avoid loads of synchronizations with Invoker and improve performance we // To avoid loads of synchronizations with Invoker and improve performance we
// execute the whole block on the COM thread // execute the whole block on the COM thread
DoChangeContents doChangeContents = ShellFolder.getInvoker().invoke(new Callable<DoChangeContents>() { DoChangeContents doChangeContents = ShellFolder.invoke(new Callable<DoChangeContents>() {
public DoChangeContents call() throws Exception { public DoChangeContents call() {
int newSize = newFileCache.size(); int newSize = newFileCache.size();
int oldSize = fileCache.size(); int oldSize = fileCache.size();
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -289,8 +289,8 @@ public abstract class ShellFolder extends File { ...@@ -289,8 +289,8 @@ public abstract class ShellFolder extends File {
// To avoid loads of synchronizations with Invoker and improve performance we // To avoid loads of synchronizations with Invoker and improve performance we
// synchronize the whole code of the sort method once // synchronize the whole code of the sort method once
getInvoker().invoke(new Callable<Void>() { invoke(new Callable<Void>() {
public Void call() throws Exception { public Void call() {
// Check that we can use the ShellFolder.sortChildren() method: // Check that we can use the ShellFolder.sortChildren() method:
// 1. All files have the same non-null parent // 1. All files have the same non-null parent
// 2. All files is ShellFolders // 2. All files is ShellFolders
...@@ -330,8 +330,8 @@ public abstract class ShellFolder extends File { ...@@ -330,8 +330,8 @@ public abstract class ShellFolder extends File {
public void sortChildren(final List<? extends File> files) { public void sortChildren(final List<? extends File> files) {
// To avoid loads of synchronizations with Invoker and improve performance we // To avoid loads of synchronizations with Invoker and improve performance we
// synchronize the whole code of the sort method once // synchronize the whole code of the sort method once
getInvoker().invoke(new Callable<Void>() { invoke(new Callable<Void>() {
public Void call() throws Exception { public Void call() {
Collections.sort(files, FILE_COMPARATOR); Collections.sort(files, FILE_COMPARATOR);
return null; return null;
...@@ -501,18 +501,62 @@ public abstract class ShellFolder extends File { ...@@ -501,18 +501,62 @@ public abstract class ShellFolder extends File {
return invoker; 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> T invoke(Callable<T> 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, E extends Throwable> T invoke(Callable<T> task, Class<E> 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. * Interface allowing to invoke tasks in different environments on different platforms.
*/ */
public static interface Invoker { public static interface Invoker {
/** /**
* Invokes a callable task. If the {@code task} throws a checked exception, * Invokes a callable task.
* it will be wrapped into a {@link RuntimeException}
* *
* @param task a task to invoke * @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 * @return the result of {@code task}'s invokation
*/ */
<T> T invoke(Callable<T> task); <T> T invoke(Callable<T> task) throws Exception;
} }
/** /**
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -108,12 +108,8 @@ class ShellFolderManager { ...@@ -108,12 +108,8 @@ class ShellFolderManager {
} }
private static class DirectInvoker implements ShellFolder.Invoker { private static class DirectInvoker implements ShellFolder.Invoker {
public <T> T invoke(Callable<T> task) { public <T> T invoke(Callable<T> task) throws Exception {
try { return task.call();
return task.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
} }
} }
} }
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -905,8 +904,8 @@ public class FilePane extends JPanel implements PropertyChangeListener { ...@@ -905,8 +904,8 @@ public class FilePane extends JPanel implements PropertyChangeListener {
@Override @Override
public void sort() { public void sort() {
ShellFolder.getInvoker().invoke(new Callable<Void>() { ShellFolder.invoke(new Callable<Void>() {
public Void call() throws Exception { public Void call() {
DetailsTableRowSorter.super.sort(); DetailsTableRowSorter.super.sort();
return null; return null;
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -29,7 +29,6 @@ import java.awt.Image; ...@@ -29,7 +29,6 @@ import java.awt.Image;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
...@@ -185,8 +184,8 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -185,8 +184,8 @@ final class Win32ShellFolder2 extends ShellFolder {
boolean disposed; boolean disposed;
public void dispose() { public void dispose() {
if (disposed) return; if (disposed) return;
ShellFolder.getInvoker().invoke(new Callable<Void>() { invoke(new Callable<Void>() {
public Void call() throws Exception { public Void call() {
if (relativePIDL != 0) { if (relativePIDL != 0) {
releasePIDL(relativePIDL); releasePIDL(relativePIDL);
} }
...@@ -224,7 +223,7 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -224,7 +223,7 @@ final class Win32ShellFolder2 extends ShellFolder {
*/ */
private boolean isPersonal; private boolean isPersonal;
private static String composePathForCsidl(int csidl) throws IOException { private static String composePathForCsidl(int csidl) throws IOException, InterruptedException {
String path = getFileSystemPath(csidl); String path = getFileSystemPath(csidl);
return path == null return path == null
? ("ShellFolder: 0x" + Integer.toHexString(csidl)) ? ("ShellFolder: 0x" + Integer.toHexString(csidl))
...@@ -235,12 +234,13 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -235,12 +234,13 @@ final class Win32ShellFolder2 extends ShellFolder {
* Create a system special shell folder, such as the * Create a system special shell folder, such as the
* desktop or Network Neighborhood. * 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 // Desktop is parent of DRIVES and NETWORK, not necessarily
// other special shell folders. // other special shell folders.
super(null, composePathForCsidl(csidl)); super(null, composePathForCsidl(csidl));
ShellFolder.getInvoker().invoke(new Callable<Void>() {
public Void call() throws Exception { invoke(new Callable<Void>() {
public Void call() throws InterruptedException {
if (csidl == DESKTOP) { if (csidl == DESKTOP) {
initDesktop(); initDesktop();
} else { } else {
...@@ -276,7 +276,7 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -276,7 +276,7 @@ final class Win32ShellFolder2 extends ShellFolder {
} }
return null; return null;
} }
}); }, InterruptedException.class);
sun.java2d.Disposer.addRecord(this, disposer); sun.java2d.Disposer.addRecord(this, disposer);
} }
...@@ -296,13 +296,13 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -296,13 +296,13 @@ final class Win32ShellFolder2 extends ShellFolder {
/** /**
* Creates a shell folder with a parent and relative PIDL * 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, super(parent,
ShellFolder.getInvoker().invoke(new Callable<String>() { invoke(new Callable<String>() {
public String call() throws Exception { public String call() {
return getFileSystemPath(parent.getIShellFolder(), relativePIDL); return getFileSystemPath(parent.getIShellFolder(), relativePIDL);
} }
}) }, RuntimeException.class)
); );
this.disposer.relativePIDL = relativePIDL; this.disposer.relativePIDL = relativePIDL;
getAbsolutePath(); getAbsolutePath();
...@@ -335,8 +335,8 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -335,8 +335,8 @@ final class Win32ShellFolder2 extends ShellFolder {
* drive (normally "C:\"). * drive (normally "C:\").
*/ */
protected Object writeReplace() throws java.io.ObjectStreamException { protected Object writeReplace() throws java.io.ObjectStreamException {
return ShellFolder.getInvoker().invoke(new Callable<File>() { return invoke(new Callable<File>() {
public File call() throws Exception { public File call() {
if (isFileSystem()) { if (isFileSystem()) {
return new File(getPath()); return new File(getPath());
} else { } else {
...@@ -398,11 +398,11 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -398,11 +398,11 @@ final class Win32ShellFolder2 extends ShellFolder {
/** /**
* Accessor for IShellFolder * Accessor for IShellFolder
*/ */
public long getIShellFolder() { private long getIShellFolder() {
if (disposer.pIShellFolder == 0) { if (disposer.pIShellFolder == 0) {
disposer.pIShellFolder = try {
ShellFolder.getInvoker().invoke(new Callable<Long>() { disposer.pIShellFolder = invoke(new Callable<Long>() {
public Long call() throws Exception { public Long call() {
assert(isDirectory()); assert(isDirectory());
assert(parent != null); assert(parent != null);
long parentIShellFolder = getParentIShellFolder(); long parentIShellFolder = getParentIShellFolder();
...@@ -421,7 +421,10 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -421,7 +421,10 @@ final class Win32ShellFolder2 extends ShellFolder {
} }
return pIShellFolder; return pIShellFolder;
} }
}); }, RuntimeException.class);
} catch (InterruptedException e) {
// Ignore error
}
} }
return disposer.pIShellFolder; return disposer.pIShellFolder;
} }
...@@ -505,18 +508,23 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -505,18 +508,23 @@ final class Win32ShellFolder2 extends ShellFolder {
} }
if (parent == rhs.parent || parent.equals(rhs.parent)) { 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; return false;
} }
private static boolean pidlsEqual(final long pIShellFolder, final long pidl1, final long pidl2) { private static boolean pidlsEqual(final long pIShellFolder, final long pidl1, final long pidl2)
return ShellFolder.getInvoker().invoke(new Callable<Boolean>() { throws InterruptedException {
public Boolean call() throws Exception { return invoke(new Callable<Boolean>() {
return (compareIDs(pIShellFolder, pidl1, pidl2) == 0); 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 // 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 { ...@@ -539,14 +547,16 @@ final class Win32ShellFolder2 extends ShellFolder {
* Return whether the given attribute flag is set for this object * Return whether the given attribute flag is set for this object
*/ */
public boolean hasAttribute(final int attribute) { public boolean hasAttribute(final int attribute) {
return ShellFolder.getInvoker().invoke(new Callable<Boolean>() { Boolean result = invoke(new Callable<Boolean>() {
public Boolean call() throws Exception { public Boolean call() {
// Caching at this point doesn't seem to be cost efficient // Caching at this point doesn't seem to be cost efficient
return (getAttributes0(getParentIShellFolder(), return (getAttributes0(getParentIShellFolder(),
getRelativePIDL(), attribute) getRelativePIDL(), attribute)
& attribute) != 0; & attribute) != 0;
} }
}); });
return result != null && result;
} }
/** /**
...@@ -561,32 +571,29 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -561,32 +571,29 @@ final class Win32ShellFolder2 extends ShellFolder {
private static native int getAttributes0(long pParentIShellFolder, long pIDL, int attrsMask); private static native int getAttributes0(long pParentIShellFolder, long pIDL, int attrsMask);
// Return the path to the underlying file system object // 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) { private static String getFileSystemPath(final long parentIShellFolder, final long relativePIDL) {
return ShellFolder.getInvoker().invoke(new Callable<String>() { int linkedFolder = ATTRIB_LINK | ATTRIB_FOLDER;
public String call() throws Exception { if (parentIShellFolder == Win32ShellFolderManager2.getNetwork().getIShellFolder() &&
int linkedFolder = ATTRIB_LINK | ATTRIB_FOLDER; getAttributes0(parentIShellFolder, relativePIDL, linkedFolder) == linkedFolder) {
if (parentIShellFolder == Win32ShellFolderManager2.getNetwork().getIShellFolder() &&
getAttributes0(parentIShellFolder, relativePIDL, linkedFolder) == linkedFolder) { String s =
getFileSystemPath(Win32ShellFolderManager2.getDesktop().getIShellFolder(),
String s = getLinkLocation(parentIShellFolder, relativePIDL, false));
getFileSystemPath(Win32ShellFolderManager2.getDesktop().getIShellFolder(), if (s != null && s.startsWith("\\\\")) {
getLinkLocation(parentIShellFolder, relativePIDL, false)); return s;
if (s != null && s.startsWith("\\\\")) {
return s;
}
}
return getDisplayNameOf(parentIShellFolder, relativePIDL, SHGDN_FORPARSING);
} }
}); }
return getDisplayNameOf(parentIShellFolder, relativePIDL, SHGDN_FORPARSING);
} }
// Needs to be accessible to Win32ShellFolderManager2 // Needs to be accessible to Win32ShellFolderManager2
static String getFileSystemPath(final int csidl) throws IOException { static String getFileSystemPath(final int csidl) throws IOException, InterruptedException {
return ShellFolder.getInvoker().invoke(new Callable<String>() { return invoke(new Callable<String>() {
public String call() throws Exception { public String call() throws IOException {
return getFileSystemPath0(csidl); return getFileSystemPath0(csidl);
} }
}); }, IOException.class);
} }
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details // 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 { ...@@ -630,13 +637,14 @@ final class Win32ShellFolder2 extends ShellFolder {
*/ */
// Returns an IEnumIDList interface for an IShellFolder. The value // Returns an IEnumIDList interface for an IShellFolder. The value
// returned must be released using releaseEnumObjects(). // returned must be released using releaseEnumObjects().
private long getEnumObjects(long pIShellFolder, final boolean includeHiddenFiles) { private long getEnumObjects(final boolean includeHiddenFiles) throws InterruptedException {
final boolean isDesktop = (disposer.pIShellFolder == getDesktopIShellFolder()); return invoke(new Callable<Long>() {
return ShellFolder.getInvoker().invoke(new Callable<Long>() { public Long call() {
public Long call() throws Exception { boolean isDesktop = disposer.pIShellFolder == getDesktopIShellFolder();
return getEnumObjects(disposer.pIShellFolder, isDesktop, includeHiddenFiles); return getEnumObjects(disposer.pIShellFolder, isDesktop, includeHiddenFiles);
} }
}); }, RuntimeException.class);
} }
// Returns an IEnumIDList interface for an IShellFolder. The value // Returns an IEnumIDList interface for an IShellFolder. The value
...@@ -670,58 +678,62 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -670,58 +678,62 @@ final class Win32ShellFolder2 extends ShellFolder {
security.checkRead(getPath()); security.checkRead(getPath());
} }
return ShellFolder.getInvoker().invoke(new Callable<File[]>() { try {
public File[] call() throws Exception { return invoke(new Callable<File[]>() {
if (!isDirectory()) { public File[] call() throws InterruptedException {
return null; 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) // Links to directories are not directories and cannot be parents.
// because they are both links and real directories! // This does not apply to folders in My Network Places (NetHood)
if (isLink() && !hasAttribute(ATTRIB_FOLDER)) { // because they are both links and real directories!
return new File[0]; if (isLink() && !hasAttribute(ATTRIB_FOLDER)) {
} return new File[0];
}
Win32ShellFolder2 desktop = Win32ShellFolderManager2.getDesktop();
Win32ShellFolder2 personal = Win32ShellFolderManager2.getPersonal();
// If we are a directory, we have a parent and (at least) a Win32ShellFolder2 desktop = Win32ShellFolderManager2.getDesktop();
// relative PIDL. We must first ensure we are bound to the Win32ShellFolder2 personal = Win32ShellFolderManager2.getPersonal();
// parent so we have an IShellFolder to query.
long pIShellFolder = getIShellFolder(); // If we are a directory, we have a parent and (at least) a
// Now we can enumerate the objects in this folder. // relative PIDL. We must first ensure we are bound to the
ArrayList<Win32ShellFolder2> list = new ArrayList<Win32ShellFolder2>(); // parent so we have an IShellFolder to query.
long pEnumObjects = getEnumObjects(pIShellFolder, includeHiddenFiles); long pIShellFolder = getIShellFolder();
if (pEnumObjects != 0) { // Now we can enumerate the objects in this folder.
long childPIDL; ArrayList<Win32ShellFolder2> list = new ArrayList<Win32ShellFolder2>();
int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR; long pEnumObjects = getEnumObjects(includeHiddenFiles);
do { if (pEnumObjects != 0) {
childPIDL = getNextChild(pEnumObjects); long childPIDL;
boolean releasePIDL = true; int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR;
if (childPIDL != 0 && do {
(getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) { childPIDL = getNextChild(pEnumObjects);
Win32ShellFolder2 childFolder; boolean releasePIDL = true;
if (Win32ShellFolder2.this.equals(desktop) if (childPIDL != 0 &&
&& personal != null (getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) {
&& pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL)) { Win32ShellFolder2 childFolder;
childFolder = personal; if (Win32ShellFolder2.this.equals(desktop)
} else { && personal != null
childFolder = new Win32ShellFolder2(Win32ShellFolder2.this, childPIDL); && pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL)) {
releasePIDL = false; childFolder = personal;
} else {
childFolder = new Win32ShellFolder2(Win32ShellFolder2.this, childPIDL);
releasePIDL = false;
}
list.add(childFolder);
} }
list.add(childFolder); if (releasePIDL) {
} releasePIDL(childPIDL);
if (releasePIDL) { }
releasePIDL(childPIDL); } while (childPIDL != 0 && !Thread.currentThread().isInterrupted());
} releaseEnumObjects(pEnumObjects);
} 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() }, InterruptedException.class);
? new File[0] } catch (InterruptedException e) {
: list.toArray(new ShellFolder[list.size()]); return new File[0];
} }
});
} }
...@@ -730,13 +742,13 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -730,13 +742,13 @@ final class Win32ShellFolder2 extends ShellFolder {
* *
* @return The child shellfolder, or null if not found. * @return The child shellfolder, or null if not found.
*/ */
Win32ShellFolder2 getChildByPath(final String filePath) { Win32ShellFolder2 getChildByPath(final String filePath) throws InterruptedException {
return ShellFolder.getInvoker().invoke(new Callable<Win32ShellFolder2>() { return invoke(new Callable<Win32ShellFolder2>() {
public Win32ShellFolder2 call() throws Exception { public Win32ShellFolder2 call() throws InterruptedException {
long pIShellFolder = getIShellFolder(); long pIShellFolder = getIShellFolder();
long pEnumObjects = getEnumObjects(pIShellFolder, true); long pEnumObjects = getEnumObjects(true);
Win32ShellFolder2 child = null; Win32ShellFolder2 child = null;
long childPIDL = 0; long childPIDL;
while ((childPIDL = getNextChild(pEnumObjects)) != 0) { while ((childPIDL = getNextChild(pEnumObjects)) != 0) {
if (getAttributes0(pIShellFolder, childPIDL, ATTRIB_FILESYSTEM) != 0) { if (getAttributes0(pIShellFolder, childPIDL, ATTRIB_FILESYSTEM) != 0) {
...@@ -753,7 +765,7 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -753,7 +765,7 @@ final class Win32ShellFolder2 extends ShellFolder {
releaseEnumObjects(pEnumObjects); releaseEnumObjects(pEnumObjects);
return child; return child;
} }
}); }, InterruptedException.class);
} }
private Boolean cachedIsLink; private Boolean cachedIsLink;
...@@ -791,8 +803,8 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -791,8 +803,8 @@ final class Win32ShellFolder2 extends ShellFolder {
} }
private ShellFolder getLinkLocation(final boolean resolve) { private ShellFolder getLinkLocation(final boolean resolve) {
return ShellFolder.getInvoker().invoke(new Callable<ShellFolder>() { return invoke(new Callable<ShellFolder>() {
public ShellFolder call() throws Exception { public ShellFolder call() {
if (!isLink()) { if (!isLink()) {
return null; return null;
} }
...@@ -805,6 +817,8 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -805,6 +817,8 @@ final class Win32ShellFolder2 extends ShellFolder {
location = location =
Win32ShellFolderManager2.createShellFolderFromRelativePIDL(getDesktop(), Win32ShellFolderManager2.createShellFolderFromRelativePIDL(getDesktop(),
linkLocationPIDL); linkLocationPIDL);
} catch (InterruptedException e) {
// Return null
} catch (InternalError e) { } catch (InternalError e) {
// Could be a link to a non-bindable object, such as a network connection // Could be a link to a non-bindable object, such as a network connection
// TODO: getIShellFolder() should throw FileNotFoundException instead // TODO: getIShellFolder() should throw FileNotFoundException instead
...@@ -816,19 +830,12 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -816,19 +830,12 @@ final class Win32ShellFolder2 extends ShellFolder {
} }
// Parse a display name into a PIDL relative to the current IShellFolder. // Parse a display name into a PIDL relative to the current IShellFolder.
long parseDisplayName(final String name) throws FileNotFoundException { long parseDisplayName(final String name) throws IOException, InterruptedException {
try { return invoke(new Callable<Long>() {
return ShellFolder.getInvoker().invoke(new Callable<Long>() { public Long call() throws IOException {
public Long call() throws Exception { return parseDisplayName0(getIShellFolder(), name);
return parseDisplayName0(getIShellFolder(), name);
}
});
} catch (RuntimeException e) {
if (e.getCause() instanceof IOException) {
throw new FileNotFoundException("Could not find file " + name);
} }
throw e; }, IOException.class);
}
} }
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details // 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 { ...@@ -846,8 +853,8 @@ final class Win32ShellFolder2 extends ShellFolder {
public String getDisplayName() { public String getDisplayName() {
if (displayName == null) { if (displayName == null) {
displayName = displayName =
ShellFolder.getInvoker().invoke(new Callable<String>() { invoke(new Callable<String>() {
public String call() throws Exception { public String call() {
return getDisplayNameOf(getParentIShellFolder(), return getDisplayNameOf(getParentIShellFolder(),
getRelativePIDL(), SHGDN_NORMAL); getRelativePIDL(), SHGDN_NORMAL);
} }
...@@ -867,8 +874,8 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -867,8 +874,8 @@ final class Win32ShellFolder2 extends ShellFolder {
if (folderType == null) { if (folderType == null) {
final long absolutePIDL = getAbsolutePIDL(); final long absolutePIDL = getAbsolutePIDL();
folderType = folderType =
ShellFolder.getInvoker().invoke(new Callable<String>() { invoke(new Callable<String>() {
public String call() throws Exception { public String call() {
return getFolderType(absolutePIDL); return getFolderType(absolutePIDL);
} }
}); });
...@@ -926,15 +933,12 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -926,15 +933,12 @@ final class Win32ShellFolder2 extends ShellFolder {
public static native int[] getFileChooserBitmapBits(); public static native int[] getFileChooserBitmapBits();
// Should be called from the COM thread
private long getIShellIcon() { private long getIShellIcon() {
if (pIShellIcon == -1L) { if (pIShellIcon == -1L) {
pIShellIcon = pIShellIcon = getIShellIcon(getIShellFolder());
ShellFolder.getInvoker().invoke(new Callable<Long>() {
public Long call() throws Exception {
return getIShellIcon(getIShellFolder());
}
});
} }
return pIShellIcon; return pIShellIcon;
} }
...@@ -988,8 +992,8 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -988,8 +992,8 @@ final class Win32ShellFolder2 extends ShellFolder {
Image icon = getLargeIcon ? largeIcon : smallIcon; Image icon = getLargeIcon ? largeIcon : smallIcon;
if (icon == null) { if (icon == null) {
icon = icon =
ShellFolder.getInvoker().invoke(new Callable<Image>() { invoke(new Callable<Image>() {
public Image call() throws Exception { public Image call() {
Image newIcon = null; Image newIcon = null;
if (isFileSystem()) { if (isFileSystem()) {
long parentIShellIcon = (parent != null) long parentIShellIcon = (parent != null)
...@@ -1113,8 +1117,8 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -1113,8 +1117,8 @@ final class Win32ShellFolder2 extends ShellFolder {
private static final int LVCFMT_CENTER = 2; private static final int LVCFMT_CENTER = 2;
public ShellFolderColumnInfo[] getFolderColumns() { public ShellFolderColumnInfo[] getFolderColumns() {
return ShellFolder.getInvoker().invoke(new Callable<ShellFolderColumnInfo[]>() { return invoke(new Callable<ShellFolderColumnInfo[]>() {
public ShellFolderColumnInfo[] call() throws Exception { public ShellFolderColumnInfo[] call() {
ShellFolderColumnInfo[] columns = doGetColumnInfo(getIShellFolder()); ShellFolderColumnInfo[] columns = doGetColumnInfo(getIShellFolder());
if (columns != null) { if (columns != null) {
...@@ -1143,8 +1147,8 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -1143,8 +1147,8 @@ final class Win32ShellFolder2 extends ShellFolder {
} }
public Object getFolderColumnValue(final int column) { public Object getFolderColumnValue(final int column) {
return ShellFolder.getInvoker().invoke(new Callable<Object>() { return invoke(new Callable<Object>() {
public Object call() throws Exception { public Object call() {
return doGetColumnValue(getParentIShellFolder(), getRelativePIDL(), column); return doGetColumnValue(getParentIShellFolder(), getRelativePIDL(), column);
} }
}); });
...@@ -1163,8 +1167,8 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -1163,8 +1167,8 @@ final class Win32ShellFolder2 extends ShellFolder {
public void sortChildren(final List<? extends File> files) { public void sortChildren(final List<? extends File> files) {
// To avoid loads of synchronizations with Invoker and improve performance we // To avoid loads of synchronizations with Invoker and improve performance we
// synchronize the whole code of the sort method once // synchronize the whole code of the sort method once
getInvoker().invoke(new Callable<Void>() { invoke(new Callable<Void>() {
public Void call() throws Exception { public Void call() {
Collections.sort(files, new ColumnComparator(getIShellFolder(), 0)); Collections.sort(files, new ColumnComparator(getIShellFolder(), 0));
return null; return null;
...@@ -1184,19 +1188,21 @@ final class Win32ShellFolder2 extends ShellFolder { ...@@ -1184,19 +1188,21 @@ final class Win32ShellFolder2 extends ShellFolder {
// compares 2 objects within this folder by the specified column // compares 2 objects within this folder by the specified column
public int compare(final File o, final File o1) { public int compare(final File o, final File o1) {
return ShellFolder.getInvoker().invoke(new Callable<Integer>() { Integer result = invoke(new Callable<Integer>() {
public Integer call() throws Exception { public Integer call() {
if (o instanceof Win32ShellFolder2 if (o instanceof Win32ShellFolder2
&& o1 instanceof Win32ShellFolder2) { && o1 instanceof Win32ShellFolder2) {
// delegates comparison to native method // delegates comparison to native method
return compareIDsByColumn(parentIShellFolder, return compareIDsByColumn(parentIShellFolder,
((Win32ShellFolder2) o).getRelativePIDL(), ((Win32ShellFolder2) o).getRelativePIDL(),
((Win32ShellFolder2) o1).getRelativePIDL(), ((Win32ShellFolder2) o1).getRelativePIDL(),
columnIdx); columnIdx);
} }
return 0; return 0;
} }
}); });
return result == null ? 0 : result;
} }
} }
} }
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -58,10 +58,15 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { ...@@ -58,10 +58,15 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
} }
public ShellFolder createShellFolder(File file) throws FileNotFoundException { 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; long pIDL;
try { try {
pIDL = parent.parseDisplayName(file.getCanonicalPath()); pIDL = parent.parseDisplayName(file.getCanonicalPath());
...@@ -77,7 +82,8 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { ...@@ -77,7 +82,8 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
return folder; 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 // Walk down this relative pIDL, creating new nodes for each of the entries
while (pIDL != 0) { while (pIDL != 0) {
long curPIDL = Win32ShellFolder2.copyFirstPIDLEntry(pIDL); long curPIDL = Win32ShellFolder2.copyFirstPIDLEntry(pIDL);
...@@ -108,7 +114,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { ...@@ -108,7 +114,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
try { try {
desktop = new Win32ShellFolder2(DESKTOP); desktop = new Win32ShellFolder2(DESKTOP);
} catch (IOException e) { } catch (IOException e) {
desktop = null; // Ignore error
} catch (InterruptedException e) {
// Ignore error
} }
} }
return desktop; return desktop;
...@@ -119,7 +127,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { ...@@ -119,7 +127,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
try { try {
drives = new Win32ShellFolder2(DRIVES); drives = new Win32ShellFolder2(DRIVES);
} catch (IOException e) { } catch (IOException e) {
drives = null; // Ignore error
} catch (InterruptedException e) {
// Ignore error
} }
} }
return drives; return drives;
...@@ -132,8 +142,10 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { ...@@ -132,8 +142,10 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
if (path != null) { if (path != null) {
recent = createShellFolder(getDesktop(), new File(path)); recent = createShellFolder(getDesktop(), new File(path));
} }
} catch (InterruptedException e) {
// Ignore error
} catch (IOException e) { } catch (IOException e) {
recent = null; // Ignore error
} }
} }
return recent; return recent;
...@@ -144,7 +156,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { ...@@ -144,7 +156,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
try { try {
network = new Win32ShellFolder2(NETWORK); network = new Win32ShellFolder2(NETWORK);
} catch (IOException e) { } catch (IOException e) {
network = null; // Ignore error
} catch (InterruptedException e) {
// Ignore error
} }
} }
return network; return network;
...@@ -164,8 +178,10 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { ...@@ -164,8 +178,10 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
personal.setIsPersonal(); personal.setIsPersonal();
} }
} }
} catch (InterruptedException e) {
// Ignore error
} catch (IOException e) { } catch (IOException e) {
personal = null; // Ignore error
} }
} }
return personal; return personal;
...@@ -267,6 +283,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { ...@@ -267,6 +283,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
} }
} catch (IOException e) { } catch (IOException e) {
// Skip this value // Skip this value
} catch (InterruptedException e) {
// Return empty result
return new File[0];
} }
} while (value != null); } while (value != null);
...@@ -476,33 +495,39 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { ...@@ -476,33 +495,39 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
return comThread; return comThread;
} }
public <T> T invoke(Callable<T> task) { public <T> T invoke(Callable<T> task) throws Exception {
try { if (Thread.currentThread() == comThread) {
if (Thread.currentThread() == comThread) { // if it's already called from the COM
// if it's already called from the COM // thread, we don't need to delegate the task
// thread, we don't need to delegate the task return task.call();
return task.call(); } else {
} else { Future<T> future;
while (true) {
Future<T> future = submit(task); try {
future = submit(task);
try { } catch (RejectedExecutionException e) {
return future.get(); throw new InterruptedException(e.getMessage());
} 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;
} }
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);
} }
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册