# HG changeset patch # User ssadetsky # Date 1433848271 -10800 # Node ID 66b012d00bd3c9a54ebd0b8455803cb7ed734cee # Parent f3e2593f91ccafd26aa86d2fb0260012f6c787ea 8017487: filechooser in Windows-Libraries folder: columns are mixed up Reviewed-by: serb, ant diff -r f3e2593f91cc -r 66b012d00bd3 jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java --- 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() { 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() { - 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() { + 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() { 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() { 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); diff -r f3e2593f91cc -r 66b012d00bd3 jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java --- 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 diff -r f3e2593f91cc -r 66b012d00bd3 jdk/test/java/awt/FileDialog/8017487/bug8017487.java --- /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()); + } + } + } + } + } + } + +}