8017487: filechooser in Windows-Libraries folder: columns are mixed up
Reviewed-by: serb, ant
--- a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java Mon Jun 08 11:31:09 2015 -0700
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java Tue Jun 09 14:11:11 2015 +0300
@@ -29,6 +29,7 @@
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.*;
@@ -233,6 +234,7 @@
private Image smallIcon = null;
private Image largeIcon = null;
private Boolean isDir = null;
+ private final boolean isLib;
/*
* The following is to identify the My Documents folder as being special
@@ -254,6 +256,7 @@
// Desktop is parent of DRIVES and NETWORK, not necessarily
// other special shell folders.
super(null, composePathForCsidl(csidl));
+ isLib = false;
invoke(new Callable<Void>() {
public Void call() throws InterruptedException {
@@ -279,7 +282,7 @@
// Now we know that parent isn't immediate to 'this' because it
// has a continued ID list. Create a shell folder for this child
// pidl and make it the new 'parent'.
- parent = new Win32ShellFolder2((Win32ShellFolder2) parent, childPIDL);
+ parent = createShellFolder((Win32ShellFolder2) parent, childPIDL);
} else {
// No grandchildren means we have arrived at the parent of 'this',
// and childPIDL is directly relative to parent.
@@ -301,8 +304,9 @@
/**
* Create a system shell folder
*/
- Win32ShellFolder2(Win32ShellFolder2 parent, long pIShellFolder, long relativePIDL, String path) {
+ Win32ShellFolder2(Win32ShellFolder2 parent, long pIShellFolder, long relativePIDL, String path, boolean isLib) {
super(parent, (path != null) ? path : "ShellFolder: ");
+ this.isLib = isLib;
this.disposer.pIShellFolder = pIShellFolder;
this.disposer.relativePIDL = relativePIDL;
sun.java2d.Disposer.addRecord(this, disposer);
@@ -312,16 +316,19 @@
/**
* Creates a shell folder with a parent and relative PIDL
*/
- Win32ShellFolder2(final Win32ShellFolder2 parent, final long relativePIDL) throws InterruptedException {
- super(parent,
- invoke(new Callable<String>() {
- public String call() {
- return getFileSystemPath(parent.getIShellFolder(), relativePIDL);
- }
- }, RuntimeException.class)
- );
- this.disposer.relativePIDL = relativePIDL;
- sun.java2d.Disposer.addRecord(this, disposer);
+ static Win32ShellFolder2 createShellFolder(Win32ShellFolder2 parent, long pIDL)
+ throws InterruptedException {
+ String path = invoke(new Callable<String>() {
+ public String call() {
+ return getFileSystemPath(parent.getIShellFolder(), pIDL);
+ }
+ }, RuntimeException.class);
+ String libPath = resolveLibrary(path);
+ if (libPath == null) {
+ return new Win32ShellFolder2(parent, 0, pIDL, path, false);
+ } else {
+ return new Win32ShellFolder2(parent, 0, pIDL, libPath, true);
+ }
}
// Initializes the desktop shell folder
@@ -601,20 +608,24 @@
}
String path = getDisplayNameOf(parentIShellFolder, relativePIDL,
SHGDN_FORPARSING);
+ return path;
+ }
+
+ private static String resolveLibrary(String path) {
// if this is a library its default save location is taken as a path
// this is a temp fix until java.io starts support Libraries
if( path != null && path.startsWith("::{") &&
path.toLowerCase().endsWith(".library-ms")) {
for (KnownFolderDefinition kf : KnownFolderDefinition.libraries) {
- if( path.toLowerCase().endsWith(
- kf.relativePath.toLowerCase()) &&
- path.toUpperCase().startsWith(
- kf.parsingName.substring(0, 40).toUpperCase()) ) {
+ if (path.toLowerCase().endsWith(
+ "\\" + kf.relativePath.toLowerCase()) &&
+ path.toUpperCase().startsWith(
+ kf.parsingName.substring(0, 40).toUpperCase())) {
return kf.saveLocation;
}
}
}
- return path;
+ return null;
}
// Needs to be accessible to Win32ShellFolderManager2
@@ -750,7 +761,7 @@
&& pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL)) {
childFolder = personal;
} else {
- childFolder = new Win32ShellFolder2(Win32ShellFolder2.this, childPIDL);
+ childFolder = createShellFolder(Win32ShellFolder2.this, childPIDL);
releasePIDL = false;
}
list.add(childFolder);
@@ -790,10 +801,11 @@
while ((childPIDL = getNextChild(pEnumObjects)) != 0) {
if (getAttributes0(pIShellFolder, childPIDL, ATTRIB_FILESYSTEM) != 0) {
String path = getFileSystemPath(pIShellFolder, childPIDL);
+ if(isLib) path = resolveLibrary( path );
if (path != null && path.equalsIgnoreCase(filePath)) {
long childIShellFolder = bindToObject(pIShellFolder, childPIDL);
child = new Win32ShellFolder2(Win32ShellFolder2.this,
- childIShellFolder, childPIDL, path);
+ childIShellFolder, childPIDL, path, isLib);
break;
}
}
@@ -1129,6 +1141,8 @@
private static final int LVCFMT_CENTER = 2;
public ShellFolderColumnInfo[] getFolderColumns() {
+ ShellFolder library = resolveLibrary();
+ if (library != null) return library.getFolderColumns();
return invoke(new Callable<ShellFolderColumnInfo[]>() {
public ShellFolderColumnInfo[] call() {
ShellFolderColumnInfo[] columns = doGetColumnInfo(getIShellFolder());
@@ -1159,6 +1173,10 @@
}
public Object getFolderColumnValue(final int column) {
+ if(!isLibrary()) {
+ ShellFolder library = resolveLibrary();
+ if (library != null) return library.getFolderColumnValue(column);
+ }
return invoke(new Callable<Object>() {
public Object call() {
return doGetColumnValue(getParentIShellFolder(), getRelativePIDL(), column);
@@ -1166,6 +1184,26 @@
});
}
+ boolean isLibrary() {
+ return isLib;
+ }
+
+ private ShellFolder resolveLibrary() {
+ for (ShellFolder f = this; f != null; f = f.parent) {
+ if (!f.isFileSystem()) {
+ if (f instanceof Win32ShellFolder2 &&
+ ((Win32ShellFolder2)f).isLibrary()) {
+ try {
+ return getShellFolder(new File(getPath()));
+ } catch (FileNotFoundException e) {
+ }
+ }
+ break;
+ }
+ }
+ return null;
+ }
+
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
private native ShellFolderColumnInfo[] doGetColumnInfo(long iShellFolder2);
--- a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Mon Jun 08 11:31:09 2015 -0700
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Tue Jun 09 14:11:11 2015 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. 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
@@ -94,7 +94,7 @@
while (pIDL != 0) {
long curPIDL = Win32ShellFolder2.copyFirstPIDLEntry(pIDL);
if (curPIDL != 0) {
- parent = new Win32ShellFolder2(parent, curPIDL);
+ parent = Win32ShellFolder2.createShellFolder(parent, curPIDL);
pIDL = Win32ShellFolder2.getNextPIDLEntry(pIDL);
} else {
// The list is empty if the parent is Desktop and pIDL is a shortcut to Desktop
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FileDialog/8017487/bug8017487.java Tue Jun 09 14:11:11 2015 +0300
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ @bug 8017487
+ @summary filechooser in Windows-Libraries folder: columns are mixed up
+ @author Semyon Sadetsky
+ @library /lib/testlibrary
+ @build jdk.testlibrary.OSInfo
+ @run main bug8017487
+ */
+
+
+import jdk.testlibrary.OSInfo;
+
+import sun.awt.shell.ShellFolder;
+import sun.awt.shell.ShellFolderColumnInfo;
+import javax.swing.filechooser.FileSystemView;
+import java.io.File;
+
+public class bug8017487
+{
+ public static void main(String[] p_args) throws Exception {
+ if (OSInfo.getOSType() == OSInfo.OSType.WINDOWS &&
+ OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_VISTA) > 0 ) {
+ test();
+ System.out.println("ok");
+ }
+ }
+
+ private static void test() throws Exception {
+ FileSystemView fsv = FileSystemView.getFileSystemView();
+ File def = new File(fsv.getDefaultDirectory().getAbsolutePath());
+ ShellFolderColumnInfo[] defColumns =
+ ShellFolder.getShellFolder(def).getFolderColumns();
+
+ File[] files = fsv.getHomeDirectory().listFiles();
+ for (File file : files) {
+ if( "Libraries".equals(ShellFolder.getShellFolder( file ).getDisplayName())) {
+ File[] libs = file.listFiles();
+ for (File lib : libs) {
+ ShellFolder libFolder =
+ ShellFolder.getShellFolder(lib);
+ if( "Library".equals(libFolder.getFolderType() ) ) {
+ ShellFolderColumnInfo[] folderColumns =
+ libFolder.getFolderColumns();
+
+ for (int i = 0; i < defColumns.length; i++) {
+ if (!defColumns[i].getTitle()
+ .equals(folderColumns[i].getTitle()))
+ throw new RuntimeException("Columnn " +
+ folderColumns[i].getTitle() +
+ " doesn't match " +
+ defColumns[i].getTitle());
+ }
+ }
+ }
+ }
+ }
+ }
+
+}