feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,123 @@
/*
* Copyright (c) 2000, 2002, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.awt.shell;
import java.io.File;
import java.security.AccessController;
import javax.swing.Icon;
import sun.security.action.GetPropertyAction;
/**
* @author Michael Martak
* @since 1.4
*/
class DefaultShellFolder extends ShellFolder {
/**
* Create a file system shell folder from a file
*/
DefaultShellFolder(ShellFolder parent, File f) {
super(parent, f.getAbsolutePath());
}
/**
* This method is implemented to make sure that no instances
* of <code>ShellFolder</code> are ever serialized. An instance of
* this default implementation can always be represented with a
* <code>java.io.File</code> object instead.
*
* @returns a <code>java.io.File</code> replacement object.
*/
protected Object writeReplace() throws java.io.ObjectStreamException {
return new File(getPath());
}
/**
* @return An array of shell folders that are children of this shell folder
* object, null if this shell folder is empty.
*/
public File[] listFiles() {
File[] files = super.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
files[i] = new DefaultShellFolder(this, files[i]);
}
}
return files;
}
/**
* @return Whether this shell folder is a link
*/
public boolean isLink() {
return false; // Not supported by default
}
/**
* @return Whether this shell folder is marked as hidden
*/
public boolean isHidden() {
String fileName = getName();
if (fileName.length() > 0) {
return (fileName.charAt(0) == '.');
}
return false;
}
/**
* @return The shell folder linked to by this shell folder, or null
* if this shell folder is not a link
*/
public ShellFolder getLinkLocation() {
return null; // Not supported by default
}
/**
* @return The name used to display this shell folder
*/
public String getDisplayName() {
return getName();
}
/**
* @return The type of shell folder as a string
*/
public String getFolderType() {
if (isDirectory()) {
return "File Folder"; // TODO : LOCALIZE THIS STRING!!!
} else {
return "File"; // TODO : LOCALIZE THIS STRING!!!
}
}
/**
* @return The executable type as a string
*/
public String getExecutableType() {
return null; // Not supported by default
}
}

View File

@@ -0,0 +1,619 @@
/*
* Copyright (c) 2000, 2014, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.awt.shell;
import javax.swing.*;
import java.awt.Image;
import java.awt.Toolkit;
import java.io.*;
import java.io.FileNotFoundException;
import java.util.*;
import java.util.concurrent.Callable;
/**
* @author Michael Martak
* @since 1.4
*/
public abstract class ShellFolder extends File {
private static final String COLUMN_NAME = "FileChooser.fileNameHeaderText";
private static final String COLUMN_SIZE = "FileChooser.fileSizeHeaderText";
private static final String COLUMN_DATE = "FileChooser.fileDateHeaderText";
protected ShellFolder parent;
/**
* Create a file system shell folder from a file
*/
ShellFolder(ShellFolder parent, String pathname) {
super((pathname != null) ? pathname : "ShellFolder");
this.parent = parent;
}
/**
* @return Whether this is a file system shell folder
*/
public boolean isFileSystem() {
return (!getPath().startsWith("ShellFolder"));
}
/**
* This method must be implemented to make sure that no instances
* of <code>ShellFolder</code> are ever serialized. If <code>isFileSystem()</code> returns
* <code>true</code>, then the object should be representable with an instance of
* <code>java.io.File</code> instead. If not, then the object is most likely
* depending on some internal (native) state and cannot be serialized.
*
* @returns a <code>java.io.File</code> replacement object, or <code>null</code>
* if no suitable replacement can be found.
*/
protected abstract Object writeReplace() throws java.io.ObjectStreamException;
/**
* Returns the path for this object's parent,
* or <code>null</code> if this object does not name a parent
* folder.
*
* @return the path as a String for this object's parent,
* or <code>null</code> if this object does not name a parent
* folder
*
* @see java.io.File#getParent()
* @since 1.4
*/
public String getParent() {
if (parent == null && isFileSystem()) {
return super.getParent();
}
if (parent != null) {
return (parent.getPath());
} else {
return null;
}
}
/**
* Returns a File object representing this object's parent,
* or <code>null</code> if this object does not name a parent
* folder.
*
* @return a File object representing this object's parent,
* or <code>null</code> if this object does not name a parent
* folder
*
* @see java.io.File#getParentFile()
* @since 1.4
*/
public File getParentFile() {
if (parent != null) {
return parent;
} else if (isFileSystem()) {
return super.getParentFile();
} else {
return null;
}
}
public File[] listFiles() {
return listFiles(true);
}
public File[] listFiles(boolean includeHiddenFiles) {
File[] files = super.listFiles();
if (!includeHiddenFiles) {
Vector v = new Vector();
int nameCount = (files == null) ? 0 : files.length;
for (int i = 0; i < nameCount; i++) {
if (!files[i].isHidden()) {
v.addElement(files[i]);
}
}
files = (File[])v.toArray(new File[v.size()]);
}
return files;
}
/**
* @return Whether this shell folder is a link
*/
public abstract boolean isLink();
/**
* @return The shell folder linked to by this shell folder, or null
* if this shell folder is not a link
*/
public abstract ShellFolder getLinkLocation() throws FileNotFoundException;
/**
* @return The name used to display this shell folder
*/
public abstract String getDisplayName();
/**
* @return The type of shell folder as a string
*/
public abstract String getFolderType();
/**
* @return The executable type as a string
*/
public abstract String getExecutableType();
/**
* Compares this ShellFolder with the specified ShellFolder for order.
*
* @see #compareTo(Object)
*/
public int compareTo(File file2) {
if (file2 == null || !(file2 instanceof ShellFolder)
|| ((file2 instanceof ShellFolder) && ((ShellFolder)file2).isFileSystem())) {
if (isFileSystem()) {
return super.compareTo(file2);
} else {
return -1;
}
} else {
if (isFileSystem()) {
return 1;
} else {
return getName().compareTo(file2.getName());
}
}
}
/**
* @param getLargeIcon whether to return large icon (ignored in base implementation)
* @return The icon used to display this shell folder
*/
public Image getIcon(boolean getLargeIcon) {
return null;
}
// Static
private static final ShellFolderManager shellFolderManager;
private static final Invoker invoker;
static {
String managerClassName = (String)Toolkit.getDefaultToolkit().
getDesktopProperty("Shell.shellFolderManager");
Class managerClass = null;
try {
managerClass = Class.forName(managerClassName, false, null);
if (!ShellFolderManager.class.isAssignableFrom(managerClass)) {
managerClass = null;
}
// swallow the exceptions below and use default shell folder
} catch(ClassNotFoundException e) {
} catch(NullPointerException e) {
} catch(SecurityException e) {
}
if (managerClass == null) {
managerClass = ShellFolderManager.class;
}
try {
shellFolderManager =
(ShellFolderManager)managerClass.newInstance();
} catch (InstantiationException e) {
throw new Error("Could not instantiate Shell Folder Manager: "
+ managerClass.getName());
} catch (IllegalAccessException e) {
throw new Error ("Could not access Shell Folder Manager: "
+ managerClass.getName());
}
invoker = shellFolderManager.createInvoker();
}
/**
* Return a shell folder from a file object
* @exception FileNotFoundException if file does not exist
*/
public static ShellFolder getShellFolder(File file) throws FileNotFoundException {
if (file instanceof ShellFolder) {
return (ShellFolder)file;
}
if (!file.exists()) {
throw new FileNotFoundException();
}
return shellFolderManager.createShellFolder(file);
}
/**
* @param key a <code>String</code>
* @return An Object matching the string <code>key</code>.
* @see ShellFolderManager#get(String)
*/
public static Object get(String key) {
return shellFolderManager.get(key);
}
/**
* Does <code>dir</code> represent a "computer" such as a node on the network, or
* "My Computer" on the desktop.
*/
public static boolean isComputerNode(File dir) {
return shellFolderManager.isComputerNode(dir);
}
/**
* @return Whether this is a file system root directory
*/
public static boolean isFileSystemRoot(File dir) {
return shellFolderManager.isFileSystemRoot(dir);
}
/**
* Canonicalizes files that don't have symbolic links in their path.
* Normalizes files that do, preserving symbolic links from being resolved.
*/
public static File getNormalizedFile(File f) throws IOException {
File canonical = f.getCanonicalFile();
if (f.equals(canonical)) {
// path of f doesn't contain symbolic links
return canonical;
}
// preserve symbolic links from being resolved
return new File(f.toURI().normalize());
}
// Override File methods
public static void sort(final List<? extends File> files) {
if (files == null || files.size() <= 1) {
return;
}
// To avoid loads of synchronizations with Invoker and improve performance we
// synchronize the whole code of the sort method once
invoke(new Callable<Void>() {
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
File commonParent = null;
for (File file : files) {
File parent = file.getParentFile();
if (parent == null || !(file instanceof ShellFolder)) {
commonParent = null;
break;
}
if (commonParent == null) {
commonParent = parent;
} else {
if (commonParent != parent && !commonParent.equals(parent)) {
commonParent = null;
break;
}
}
}
if (commonParent instanceof ShellFolder) {
((ShellFolder) commonParent).sortChildren(files);
} else {
Collections.sort(files, FILE_COMPARATOR);
}
return null;
}
});
}
public void sortChildren(final List<? extends File> files) {
// To avoid loads of synchronizations with Invoker and improve performance we
// synchronize the whole code of the sort method once
invoke(new Callable<Void>() {
public Void call() {
Collections.sort(files, FILE_COMPARATOR);
return null;
}
});
}
public boolean isAbsolute() {
return (!isFileSystem() || super.isAbsolute());
}
public File getAbsoluteFile() {
return (isFileSystem() ? super.getAbsoluteFile() : this);
}
public boolean canRead() {
return (isFileSystem() ? super.canRead() : true); // ((Fix?))
}
/**
* Returns true if folder allows creation of children.
* True for the "Desktop" folder, but false for the "My Computer"
* folder.
*/
public boolean canWrite() {
return (isFileSystem() ? super.canWrite() : false); // ((Fix?))
}
public boolean exists() {
// Assume top-level drives exist, because state is uncertain for
// removable drives.
return (!isFileSystem() || isFileSystemRoot(this) || super.exists()) ;
}
public boolean isDirectory() {
return (isFileSystem() ? super.isDirectory() : true); // ((Fix?))
}
public boolean isFile() {
return (isFileSystem() ? super.isFile() : !isDirectory()); // ((Fix?))
}
public long lastModified() {
return (isFileSystem() ? super.lastModified() : 0L); // ((Fix?))
}
public long length() {
return (isFileSystem() ? super.length() : 0L); // ((Fix?))
}
public boolean createNewFile() throws IOException {
return (isFileSystem() ? super.createNewFile() : false);
}
public boolean delete() {
return (isFileSystem() ? super.delete() : false); // ((Fix?))
}
public void deleteOnExit() {
if (isFileSystem()) {
super.deleteOnExit();
} else {
// Do nothing // ((Fix?))
}
}
public boolean mkdir() {
return (isFileSystem() ? super.mkdir() : false);
}
public boolean mkdirs() {
return (isFileSystem() ? super.mkdirs() : false);
}
public boolean renameTo(File dest) {
return (isFileSystem() ? super.renameTo(dest) : false); // ((Fix?))
}
public boolean setLastModified(long time) {
return (isFileSystem() ? super.setLastModified(time) : false); // ((Fix?))
}
public boolean setReadOnly() {
return (isFileSystem() ? super.setReadOnly() : false); // ((Fix?))
}
public String toString() {
return (isFileSystem() ? super.toString() : getDisplayName());
}
public static ShellFolderColumnInfo[] getFolderColumns(File dir) {
ShellFolderColumnInfo[] columns = null;
if (dir instanceof ShellFolder) {
columns = ((ShellFolder) dir).getFolderColumns();
}
if (columns == null) {
columns = new ShellFolderColumnInfo[]{
new ShellFolderColumnInfo(COLUMN_NAME, 150,
SwingConstants.LEADING, true, null,
FILE_COMPARATOR),
new ShellFolderColumnInfo(COLUMN_SIZE, 75,
SwingConstants.RIGHT, true, null,
DEFAULT_COMPARATOR, true),
new ShellFolderColumnInfo(COLUMN_DATE, 130,
SwingConstants.LEADING, true, null,
DEFAULT_COMPARATOR, true)
};
}
return columns;
}
public ShellFolderColumnInfo[] getFolderColumns() {
return null;
}
public static Object getFolderColumnValue(File file, int column) {
if (file instanceof ShellFolder) {
Object value = ((ShellFolder)file).getFolderColumnValue(column);
if (value != null) {
return value;
}
}
if (file == null || !file.exists()) {
return null;
}
switch (column) {
case 0:
// By default, file name will be rendered using getSystemDisplayName()
return file;
case 1: // size
return file.isDirectory() ? null : Long.valueOf(file.length());
case 2: // date
if (isFileSystemRoot(file)) {
return null;
}
long time = file.lastModified();
return (time == 0L) ? null : new Date(time);
default:
return null;
}
}
public Object getFolderColumnValue(int column) {
return null;
}
/**
* 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 invoker.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.
*
* @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> T invoke(Callable<T> task) throws Exception;
}
/**
* Provides a default comparator for the default column set
*/
private static final Comparator DEFAULT_COMPARATOR = new Comparator() {
public int compare(Object o1, Object o2) {
int gt;
if (o1 == null && o2 == null) {
gt = 0;
} else if (o1 != null && o2 == null) {
gt = 1;
} else if (o1 == null && o2 != null) {
gt = -1;
} else if (o1 instanceof Comparable) {
gt = ((Comparable) o1).compareTo(o2);
} else {
gt = 0;
}
return gt;
}
};
private static final Comparator<File> FILE_COMPARATOR = new Comparator<File>() {
public int compare(File f1, File f2) {
ShellFolder sf1 = null;
ShellFolder sf2 = null;
if (f1 instanceof ShellFolder) {
sf1 = (ShellFolder) f1;
if (sf1.isFileSystem()) {
sf1 = null;
}
}
if (f2 instanceof ShellFolder) {
sf2 = (ShellFolder) f2;
if (sf2.isFileSystem()) {
sf2 = null;
}
}
if (sf1 != null && sf2 != null) {
return sf1.compareTo(sf2);
} else if (sf1 != null) {
// Non-file shellfolders sort before files
return -1;
} else if (sf2 != null) {
return 1;
} else {
String name1 = f1.getName();
String name2 = f2.getName();
// First ignore case when comparing
int diff = name1.compareToIgnoreCase(name2);
if (diff != 0) {
return diff;
} else {
// May differ in case (e.g. "mail" vs. "Mail")
// We need this test for consistent sorting
return name1.compareTo(name2);
}
}
}
};
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright (c) 2005, 2006, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.awt.shell;
import javax.swing.*;
import java.util.Comparator;
public class ShellFolderColumnInfo {
private String title;
private Integer width;
private boolean visible;
/**
* Allowed values are {@link SwingConstants#LEFT}, {@link SwingConstants#RIGHT}, {@link SwingConstants#LEADING},
* {@link SwingConstants#TRAILING}, {@link SwingConstants#CENTER}
*/
private Integer alignment;
private SortOrder sortOrder;
private Comparator comparator;
/**
* <code>false</code> (default) if the {@link comparator} expects folders as arguments,
* and <code>true</code> if folder's column values. The first option is used default for comparison
* on Windows and also for separating files from directories when sorting using
* ShellFolderManager's inner comparator.
*/
private boolean compareByColumn;
public ShellFolderColumnInfo(String title, Integer width,
Integer alignment, boolean visible,
SortOrder sortOrder, Comparator comparator,
boolean compareByColumn) {
this.title = title;
this.width = width;
this.alignment = alignment;
this.visible = visible;
this.sortOrder = sortOrder;
this.comparator = comparator;
this.compareByColumn = compareByColumn;
}
public ShellFolderColumnInfo(String title, Integer width,
Integer alignment, boolean visible,
SortOrder sortOrder, Comparator comparator) {
this(title, width, alignment, visible, sortOrder, comparator, false);
}
/**
* This constructor is used by native code when getting column set for
* a folder under Windows
*/
public ShellFolderColumnInfo(String title, int width, int alignment,
boolean visible) {
this(title, width, alignment, visible, null, null);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
this.width = width;
}
public Integer getAlignment() {
return alignment;
}
public void setAlignment(Integer alignment) {
this.alignment = alignment;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public SortOrder getSortOrder() {
return sortOrder;
}
public void setSortOrder(SortOrder sortOrder) {
this.sortOrder = sortOrder;
}
public Comparator getComparator() {
return comparator;
}
public void setComparator(Comparator comparator) {
this.comparator = comparator;
}
public boolean isCompareByColumn() {
return compareByColumn;
}
public void setCompareByColumn(boolean compareByColumn) {
this.compareByColumn = compareByColumn;
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 2000, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.awt.shell;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.concurrent.Callable;
/**
* @author Michael Martak
* @since 1.4
*/
class ShellFolderManager {
/**
* Create a shell folder from a file.
* Override to return machine-dependent behavior.
*/
public ShellFolder createShellFolder(File file) throws FileNotFoundException {
return new DefaultShellFolder(null, file);
}
/**
* @param key a <code>String</code>
* "fileChooserDefaultFolder":
* Returns a <code>File</code> - the default shellfolder for a new filechooser
* "roots":
* Returns a <code>File[]</code> - containing the root(s) of the displayable hierarchy
* "fileChooserComboBoxFolders":
* Returns a <code>File[]</code> - an array of shellfolders representing the list to
* show by default in the file chooser's combobox
* "fileChooserShortcutPanelFolders":
* Returns a <code>File[]</code> - an array of shellfolders representing well-known
* folders, such as Desktop, Documents, History, Network, Home, etc.
* This is used in the shortcut panel of the filechooser on Windows 2000
* and Windows Me.
* "fileChooserIcon <icon>":
* Returns an <code>Image</code> - icon can be ListView, DetailsView, UpFolder, NewFolder or
* ViewMenu (Windows only).
*
* @return An Object matching the key string.
*/
public Object get(String key) {
if (key.equals("fileChooserDefaultFolder")) {
// Return the default shellfolder for a new filechooser
File homeDir = new File(System.getProperty("user.home"));
try {
return createShellFolder(homeDir);
} catch (FileNotFoundException e) {
return homeDir;
}
} else if (key.equals("roots")) {
// The root(s) of the displayable hierarchy
return File.listRoots();
} else if (key.equals("fileChooserComboBoxFolders")) {
// Return an array of ShellFolders representing the list to
// show by default in the file chooser's combobox
return get("roots");
} else if (key.equals("fileChooserShortcutPanelFolders")) {
// Return an array of ShellFolders representing well-known
// folders, such as Desktop, Documents, History, Network, Home, etc.
// This is used in the shortcut panel of the filechooser on Windows 2000
// and Windows Me
return new File[] { (File)get("fileChooserDefaultFolder") };
}
return null;
}
/**
* Does <code>dir</code> represent a "computer" such as a node on the network, or
* "My Computer" on the desktop.
*/
public boolean isComputerNode(File dir) {
return false;
}
public boolean isFileSystemRoot(File dir) {
if (dir instanceof ShellFolder && !((ShellFolder) dir).isFileSystem()) {
return false;
}
return (dir.getParentFile() == null);
}
protected ShellFolder.Invoker createInvoker() {
return new DirectInvoker();
}
private static class DirectInvoker implements ShellFolder.Invoker {
public <T> T invoke(Callable<T> task) throws Exception {
return task.call();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,652 @@
/*
* Copyright (c) 2003, 2019, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.awt.shell;
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.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import sun.awt.OSInfo;
import sun.misc.ThreadGroupUtils;
import sun.util.logging.PlatformLogger;
import static sun.awt.shell.Win32ShellFolder2.DESKTOP;
import static sun.awt.shell.Win32ShellFolder2.DRIVES;
import static sun.awt.shell.ShellFolder.Invoker;
import static sun.awt.shell.Win32ShellFolder2.NETWORK;
import static sun.awt.shell.Win32ShellFolder2.PERSONAL;
import static sun.awt.shell.Win32ShellFolder2.RECENT;
// NOTE: This class supersedes Win32ShellFolderManager, which was removed
// from distribution after version 1.4.2.
/**
* @author Michael Martak
* @author Leif Samuelsson
* @author Kenneth Russell
* @since 1.4
*/
public class Win32ShellFolderManager2 extends ShellFolderManager {
private static final PlatformLogger
log = PlatformLogger.getLogger("sun.awt.shell.Win32ShellFolderManager2");
static {
// Load library here
sun.awt.windows.WToolkit.loadLibraries();
}
public ShellFolder createShellFolder(File file) throws FileNotFoundException {
try {
return createShellFolder(getDesktop(), file);
} catch (InterruptedException e) {
throw new FileNotFoundException("Execution was interrupted");
}
}
static Win32ShellFolder2 createShellFolder(Win32ShellFolder2 parent, File file)
throws FileNotFoundException, InterruptedException {
long pIDL;
try {
pIDL = parent.parseDisplayName(file.getCanonicalPath());
} catch (IOException ex) {
pIDL = 0;
}
if (pIDL == 0) {
// Shouldn't happen but watch for it anyway
throw new FileNotFoundException("File " + file.getAbsolutePath() + " not found");
}
try {
return createShellFolderFromRelativePIDL(parent, pIDL);
} finally {
Win32ShellFolder2.releasePIDL(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);
if (curPIDL != 0) {
parent = new Win32ShellFolder2(parent, curPIDL);
pIDL = Win32ShellFolder2.getNextPIDLEntry(pIDL);
} else {
// The list is empty if the parent is Desktop and pIDL is a shortcut to Desktop
break;
}
}
return parent;
}
private static final int VIEW_LIST = 2;
private static final int VIEW_DETAILS = 3;
private static final int VIEW_PARENTFOLDER = 8;
private static final int VIEW_NEWFOLDER = 11;
private static final Image[] STANDARD_VIEW_BUTTONS = new Image[12];
private static Image getStandardViewButton(int iconIndex) {
Image result = STANDARD_VIEW_BUTTONS[iconIndex];
if (result != null) {
return result;
}
BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
img.setRGB(0, 0, 16, 16, Win32ShellFolder2.getStandardViewButton0(iconIndex), 0, 16);
STANDARD_VIEW_BUTTONS[iconIndex] = img;
return img;
}
// Special folders
private static Win32ShellFolder2 desktop;
private static Win32ShellFolder2 drives;
private static Win32ShellFolder2 recent;
private static Win32ShellFolder2 network;
private static Win32ShellFolder2 personal;
static Win32ShellFolder2 getDesktop() {
if (desktop == null) {
try {
desktop = new Win32ShellFolder2(DESKTOP);
} catch (final SecurityException ignored) {
// Ignore, the message may have sensitive information, not
// accessible other ways
} catch (IOException | InterruptedException e) {
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
log.warning("Cannot access 'Desktop'", e);
}
}
}
return desktop;
}
static Win32ShellFolder2 getDrives() {
if (drives == null) {
try {
drives = new Win32ShellFolder2(DRIVES);
} catch (final SecurityException ignored) {
// Ignore, the message may have sensitive information, not
// accessible other ways
} catch (IOException | InterruptedException e) {
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
log.warning("Cannot access 'Drives'", e);
}
}
}
return drives;
}
static Win32ShellFolder2 getRecent() {
if (recent == null) {
try {
String path = Win32ShellFolder2.getFileSystemPath(RECENT);
if (path != null) {
recent = createShellFolder(getDesktop(), new File(path));
}
} catch (final SecurityException ignored) {
// Ignore, the message may have sensitive information, not
// accessible other ways
} catch (InterruptedException | IOException e) {
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
log.warning("Cannot access 'Recent'", e);
}
}
}
return recent;
}
static Win32ShellFolder2 getNetwork() {
if (network == null) {
try {
network = new Win32ShellFolder2(NETWORK);
} catch (final SecurityException ignored) {
// Ignore, the message may have sensitive information, not
// accessible other ways
} catch (IOException | InterruptedException e) {
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
log.warning("Cannot access 'Network'", e);
}
}
}
return network;
}
static Win32ShellFolder2 getPersonal() {
if (personal == null) {
try {
String path = Win32ShellFolder2.getFileSystemPath(PERSONAL);
if (path != null) {
Win32ShellFolder2 desktop = getDesktop();
personal = desktop.getChildByPath(path);
if (personal == null) {
personal = createShellFolder(getDesktop(), new File(path));
}
if (personal != null) {
personal.setIsPersonal();
}
}
} catch (final SecurityException ignored) {
// Ignore, the message may have sensitive information, not
// accessible other ways
} catch (InterruptedException | IOException e) {
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
log.warning("Cannot access 'Personal'", e);
}
}
}
return personal;
}
private static File[] roots;
/**
* @param key a <code>String</code>
* "fileChooserDefaultFolder":
* Returns a <code>File</code> - the default shellfolder for a new filechooser
* "roots":
* Returns a <code>File[]</code> - containing the root(s) of the displayable hierarchy
* "fileChooserComboBoxFolders":
* Returns a <code>File[]</code> - an array of shellfolders representing the list to
* show by default in the file chooser's combobox
* "fileChooserShortcutPanelFolders":
* Returns a <code>File[]</code> - an array of shellfolders representing well-known
* folders, such as Desktop, Documents, History, Network, Home, etc.
* This is used in the shortcut panel of the filechooser on Windows 2000
* and Windows Me.
* "fileChooserIcon <icon>":
* Returns an <code>Image</code> - icon can be ListView, DetailsView, UpFolder, NewFolder or
* ViewMenu (Windows only).
* "optionPaneIcon iconName":
* Returns an <code>Image</code> - icon from the system icon list
*
* @return An Object matching the key string.
*/
public Object get(String key) {
if (key.equals("fileChooserDefaultFolder")) {
File file = getPersonal();
if (file == null) {
file = getDesktop();
}
return checkFile(file);
} else if (key.equals("roots")) {
// Should be "History" and "Desktop" ?
if (roots == null) {
File desktop = getDesktop();
if (desktop != null) {
roots = new File[] { desktop };
} else {
roots = (File[])super.get(key);
}
}
return checkFiles(roots);
} else if (key.equals("fileChooserComboBoxFolders")) {
Win32ShellFolder2 desktop = getDesktop();
if (desktop != null && checkFile(desktop) != null) {
ArrayList<File> folders = new ArrayList<File>();
Win32ShellFolder2 drives = getDrives();
Win32ShellFolder2 recentFolder = getRecent();
if (recentFolder != null && OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_2000) >= 0) {
folders.add(recentFolder);
}
folders.add(desktop);
// Add all second level folders
File[] secondLevelFolders = checkFiles(desktop.listFiles());
Arrays.sort(secondLevelFolders);
for (File secondLevelFolder : secondLevelFolders) {
Win32ShellFolder2 folder = (Win32ShellFolder2) secondLevelFolder;
if (!folder.isFileSystem() || (folder.isDirectory() && !folder.isLink())) {
folders.add(folder);
// Add third level for "My Computer"
if (folder.equals(drives)) {
File[] thirdLevelFolders = checkFiles(folder.listFiles());
if (thirdLevelFolders != null && thirdLevelFolders.length > 0) {
List<File> thirdLevelFoldersList = Arrays.asList(thirdLevelFolders);
folder.sortChildren(thirdLevelFoldersList);
folders.addAll(thirdLevelFoldersList);
}
}
}
}
return checkFiles(folders);
} else {
return super.get(key);
}
} else if (key.equals("fileChooserShortcutPanelFolders")) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
ArrayList<File> folders = new ArrayList<File>();
int i = 0;
Object value;
do {
value = toolkit.getDesktopProperty("win.comdlg.placesBarPlace" + i++);
try {
if (value instanceof Integer) {
// A CSIDL
folders.add(new Win32ShellFolder2((Integer)value));
} else if (value instanceof String) {
// A path
folders.add(createShellFolder(new File((String)value)));
}
} catch (IOException e) {
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
log.warning("Cannot read value = " + value, e);
}
// Skip this value
} catch (InterruptedException e) {
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
log.warning("Cannot read value = " + value, e);
}
// Return empty result
return new File[0];
}
} while (value != null);
if (folders.size() == 0) {
// Use default list of places
for (File f : new File[] {
getRecent(), getDesktop(), getPersonal(), getDrives(), getNetwork()
}) {
if (f != null) {
folders.add(f);
}
}
}
return checkFiles(folders);
} else if (key.startsWith("fileChooserIcon ")) {
String name = key.substring(key.indexOf(" ") + 1);
int iconIndex;
if (name.equals("ListView") || name.equals("ViewMenu")) {
iconIndex = VIEW_LIST;
} else if (name.equals("DetailsView")) {
iconIndex = VIEW_DETAILS;
} else if (name.equals("UpFolder")) {
iconIndex = VIEW_PARENTFOLDER;
} else if (name.equals("NewFolder")) {
iconIndex = VIEW_NEWFOLDER;
} else {
return null;
}
return getStandardViewButton(iconIndex);
} else if (key.startsWith("optionPaneIcon ")) {
Win32ShellFolder2.SystemIcon iconType;
if (key == "optionPaneIcon Error") {
iconType = Win32ShellFolder2.SystemIcon.IDI_ERROR;
} else if (key == "optionPaneIcon Information") {
iconType = Win32ShellFolder2.SystemIcon.IDI_INFORMATION;
} else if (key == "optionPaneIcon Question") {
iconType = Win32ShellFolder2.SystemIcon.IDI_QUESTION;
} else if (key == "optionPaneIcon Warning") {
iconType = Win32ShellFolder2.SystemIcon.IDI_EXCLAMATION;
} else {
return null;
}
return Win32ShellFolder2.getSystemIcon(iconType);
} else if (key.startsWith("shell32Icon ") || key.startsWith("shell32LargeIcon ")) {
String name = key.substring(key.indexOf(" ") + 1);
try {
int i = Integer.parseInt(name);
if (i >= 0) {
return Win32ShellFolder2.getShell32Icon(i, key.startsWith("shell32LargeIcon "));
}
} catch (NumberFormatException ex) {
}
}
return null;
}
private static File checkFile(File file) {
SecurityManager sm = System.getSecurityManager();
return (sm == null || file == null) ? file : checkFile(file, sm);
}
private static File checkFile(File file, SecurityManager sm) {
try {
sm.checkRead(file.getPath());
if (file instanceof Win32ShellFolder2) {
Win32ShellFolder2 f = (Win32ShellFolder2)file;
if (f.isLink()) {
Win32ShellFolder2 link = (Win32ShellFolder2)f.getLinkLocation();
if (link != null)
sm.checkRead(link.getPath());
}
}
return file;
} catch (SecurityException se) {
return null;
}
}
static File[] checkFiles(File[] files) {
SecurityManager sm = System.getSecurityManager();
if (sm == null || files == null || files.length == 0) {
return files;
}
return checkFiles(Arrays.stream(files), sm);
}
private static File[] checkFiles(List<File> files) {
SecurityManager sm = System.getSecurityManager();
if (sm == null || files.isEmpty()) {
return files.toArray(new File[files.size()]);
}
return checkFiles(files.stream(), sm);
}
private static File[] checkFiles(Stream<File> filesStream, SecurityManager sm) {
return filesStream.filter((file) -> checkFile(file, sm) != null)
.toArray(File[]::new);
}
/**
* Does <code>dir</code> represent a "computer" such as a node on the network, or
* "My Computer" on the desktop.
*/
public boolean isComputerNode(final File dir) {
if (dir != null && dir == getDrives()) {
return true;
} else {
String path = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return dir.getAbsolutePath();
}
});
return (path.startsWith("\\\\") && path.indexOf("\\", 2) < 0); //Network path
}
}
public boolean isFileSystemRoot(File dir) {
//Note: Removable drives don't "exist" but are listed in "My Computer"
if (dir != null) {
Win32ShellFolder2 drives = getDrives();
if (dir instanceof Win32ShellFolder2) {
Win32ShellFolder2 sf = (Win32ShellFolder2)dir;
if (sf.isFileSystem()) {
if (sf.parent != null) {
return sf.parent.equals(drives);
}
// else fall through ...
} else {
return false;
}
}
String path = dir.getPath();
if (path.length() != 3 || path.charAt(1) != ':') {
return false;
}
File[] files = drives.listFiles();
return files != null && Arrays.asList(files).contains(dir);
}
return false;
}
private static List topFolderList = null;
static int compareShellFolders(Win32ShellFolder2 sf1, Win32ShellFolder2 sf2) {
boolean special1 = sf1.isSpecial();
boolean special2 = sf2.isSpecial();
if (special1 || special2) {
if (topFolderList == null) {
ArrayList tmpTopFolderList = new ArrayList();
tmpTopFolderList.add(Win32ShellFolderManager2.getPersonal());
tmpTopFolderList.add(Win32ShellFolderManager2.getDesktop());
tmpTopFolderList.add(Win32ShellFolderManager2.getDrives());
tmpTopFolderList.add(Win32ShellFolderManager2.getNetwork());
topFolderList = tmpTopFolderList;
}
int i1 = topFolderList.indexOf(sf1);
int i2 = topFolderList.indexOf(sf2);
if (i1 >= 0 && i2 >= 0) {
return (i1 - i2);
} else if (i1 >= 0) {
return -1;
} else if (i2 >= 0) {
return 1;
}
}
// Non-file shellfolders sort before files
if (special1 && !special2) {
return -1;
} else if (special2 && !special1) {
return 1;
}
return compareNames(sf1.getAbsolutePath(), sf2.getAbsolutePath());
}
static int compareNames(String name1, String name2) {
// First ignore case when comparing
int diff = name1.compareToIgnoreCase(name2);
if (diff != 0) {
return diff;
} else {
// May differ in case (e.g. "mail" vs. "Mail")
// We need this test for consistent sorting
return name1.compareTo(name2);
}
}
@Override
protected Invoker createInvoker() {
return new ComInvoker();
}
private static class ComInvoker extends ThreadPoolExecutor implements ThreadFactory, ShellFolder.Invoker {
private static Thread comThread;
private ComInvoker() {
super(1, 1, 0, TimeUnit.DAYS, new LinkedBlockingQueue<Runnable>());
allowCoreThreadTimeOut(false);
setThreadFactory(this);
final Runnable shutdownHook = new Runnable() {
public void run() {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
shutdownNow();
return null;
}
});
}
};
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
Runtime.getRuntime().addShutdownHook(
new Thread(shutdownHook)
);
return null;
}
});
}
public synchronized Thread newThread(final Runnable task) {
final Runnable comRun = new Runnable() {
public void run() {
try {
initializeCom();
task.run();
} finally {
uninitializeCom();
}
}
};
comThread = AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
/* The thread must be a member of a thread group
* which will not get GCed before VM exit.
* Make its parent the top-level thread group.
*/
ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
Thread thread = new Thread(rootTG, comRun, "Swing-Shell");
thread.setDaemon(true);
return thread;
}
);
return comThread;
}
public <T> T invoke(Callable<T> 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 {
final Future<T> future;
try {
future = submit(task);
} catch (RejectedExecutionException e) {
throw new InterruptedException(e.getMessage());
}
try {
return future.get();
} catch (InterruptedException e) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
future.cancel(true);
return null;
}
});
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);
}
}
}
}
static native void initializeCom();
static native void uninitializeCom();
}