Source Code Cross Referenced for FileUtil.java in  » IDE-Netbeans » openide » org » openide » filesystems » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » openide » org.openide.filesystems 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.openide.filesystems;
0043:
0044:        import java.io.File;
0045:        import java.io.FileFilter;
0046:        import java.io.FilenameFilter;
0047:        import java.io.IOException;
0048:        import java.io.InputStream;
0049:        import java.io.OutputStream;
0050:        import java.io.SyncFailedException;
0051:        import java.net.MalformedURLException;
0052:        import java.net.URI;
0053:        import java.net.URL;
0054:        import java.net.URLStreamHandler;
0055:        import java.util.Arrays;
0056:        import java.util.Collection;
0057:        import java.util.Dictionary;
0058:        import java.util.Enumeration;
0059:        import java.util.HashMap;
0060:        import java.util.HashSet;
0061:        import java.util.Hashtable;
0062:        import java.util.Iterator;
0063:        import java.util.List;
0064:        import java.util.Map;
0065:        import java.util.Set;
0066:        import java.util.Stack;
0067:        import java.util.StringTokenizer;
0068:        import java.util.WeakHashMap;
0069:        import java.util.jar.JarEntry;
0070:        import java.util.jar.JarInputStream;
0071:        import java.util.logging.Level;
0072:        import java.util.logging.Logger;
0073:        import javax.swing.Icon;
0074:        import javax.swing.JFileChooser;
0075:        import javax.swing.SwingUtilities;
0076:        import javax.swing.filechooser.FileSystemView;
0077:        import org.openide.filesystems.FileSystem.AtomicAction;
0078:        import org.openide.util.Exceptions;
0079:        import org.openide.util.Lookup;
0080:        import org.openide.util.NbBundle;
0081:        import org.openide.util.Utilities;
0082:        import org.openide.util.WeakListeners;
0083:
0084:        /** Common utilities for handling files.
0085:         * This is a dummy class; all methods are static.
0086:         */
0087:        public final class FileUtil extends Object {
0088:
0089:            /** Normal header for ZIP files. */
0090:            private static byte[] ZIP_HEADER_1 = { 0x50, 0x4b, 0x03, 0x04 };
0091:            /** Also seems to be used at least in apisupport/project/test/unit/data/example-external-projects/suite3/nbplatform/random/modules/ext/stuff.jar; not known why */
0092:            private static byte[] ZIP_HEADER_2 = { 0x50, 0x4b, 0x05, 0x06 };
0093:
0094:            /** transient attributes which should not be copied
0095:             * of type Set<String>
0096:             */
0097:            static final Set<String> transientAttributes = new HashSet<String>();
0098:
0099:            static {
0100:                transientAttributes.add("templateWizardURL"); // NOI18N
0101:                transientAttributes.add("templateWizardIterator"); // NOI18N
0102:                transientAttributes.add("templateWizardDescResource"); // NOI18N
0103:                transientAttributes.add("templateCategory"); // NOI18N
0104:                transientAttributes.add("instantiatingIterator"); // NOI18N
0105:                transientAttributes.add("instantiatingWizardURL"); // NOI18N
0106:                transientAttributes.add("SystemFileSystem.localizingBundle"); // NOI18N
0107:                transientAttributes.add("SystemFileSystem.icon"); // NOI18N
0108:                transientAttributes.add("SystemFileSystem.icon32"); // NOI18N
0109:                transientAttributes.add("position"); // NOI18N
0110:            }
0111:
0112:            /* mapping of file extensions to content-types */
0113:            private static Dictionary<String, String> map = new Hashtable<String, String>();
0114:
0115:            static {
0116:                // Set up at least this one statically, because it is so basic;
0117:                // we do not want to rely on Lookup, MIMEResolver, declarative resolvers,
0118:                // XML layers, etc. just to find this.
0119:                setMIMEType("xml", "text/xml"); // NOI18N
0120:            }
0121:
0122:            /** Cache for {@link #isArchiveFile(FileObject)}. */
0123:            private static final Map<FileObject, Boolean> archiveFileCache = new WeakHashMap<FileObject, Boolean>();
0124:            private static FileSystem diskFileSystem;
0125:
0126:            private static FileSystem getDiskFileSystemFor(File... files) {
0127:                FileSystem fs = getDiskFileSystem();
0128:                if (fs == null) {
0129:                    for (File file : files) {
0130:                        FileObject fo = toFileObject(file);
0131:                        fs = getDiskFileSystem();
0132:                        if (fs != null) {
0133:                            break;
0134:                        }
0135:                    }
0136:                }
0137:                return fs;
0138:            }
0139:
0140:            private FileUtil() {
0141:            }
0142:
0143:            /**
0144:             * Refreshes all necessary filesystems. Not all instances of <code>FileObject</code> are refreshed
0145:             * but just those that represent passed <code>files</code> and their children recursively.
0146:             * @param files
0147:             * @since 7.6
0148:             */
0149:            public static void refreshFor(File... files) {
0150:                FileSystem fs = getDiskFileSystemFor(files);
0151:                if (fs != null) {
0152:                    try {
0153:                        fs
0154:                                .getRoot()
0155:                                .setAttribute(
0156:                                        "request_for_refreshing_files_be_aware_this_is_not_public_api",
0157:                                        files);
0158:                    } catch (IOException ex) {
0159:                        Exceptions.printStackTrace(ex);
0160:                    }
0161:                }
0162:            }
0163:
0164:            /**
0165:             * Refreshes all <code>FileObject</code> that represent files <code>File.listRoots()</code> 
0166:             * and their children recursively.
0167:             * @since 7.7
0168:             */
0169:            public static void refreshAll() {
0170:                refreshFor(File.listRoots());
0171:            }
0172:
0173:            /**
0174:             * Registers <code>listener</code> so that it will receive
0175:             * <code>FileEvent</code>s from <code>FileSystem</code>s providing instances
0176:             * of <code>FileObject</code> convertible to <code>java.io.File</code>. 
0177:             * @param fcl
0178:             * @see #toFileObject
0179:             * @since 7.7
0180:             */
0181:            public static void addFileChangeListener(FileChangeListener fcl) {
0182:                FileSystem fs = getDiskFileSystem();
0183:                if (fs == null) {
0184:                    fs = getDiskFileSystemFor(File.listRoots());
0185:                }
0186:                if (fs != null) {
0187:                    fs.addFileChangeListener(fcl);
0188:                }
0189:            }
0190:
0191:            /**
0192:             * Unregisters <code>listener</code> so that it will no longer receive
0193:             * <code>FileEvent</code>s from <code>FileSystem</code>s providing instances
0194:             * of <code>FileObject</code> convertible to <code>java.io.File</code>      
0195:             * @param fcl
0196:             * @see #toFileObject
0197:             * @since 7.7
0198:             */
0199:            public static void removeFileChangeListener(FileChangeListener fcl) {
0200:                FileSystem fs = getDiskFileSystem();
0201:                if (fs == null) {
0202:                    fs = getDiskFileSystemFor(File.listRoots());
0203:                }
0204:                if (fs != null) {
0205:                    fs.addFileChangeListener(fcl);
0206:                }
0207:            }
0208:
0209:            /**
0210:             * Executes atomic action. For more info see {@link FileSystem#runAtomicAction}. 
0211:             * <p>
0212:             * All events about filesystem changes (related to events on all affected instances of <code>FileSystem</code>)
0213:             * are postponed after the whole <code>atomicCode</code> 
0214:             * is executed.
0215:             * </p>
0216:             * @param atomicCode code that is supposed to be run as atomic action. See {@link FileSystem#runAtomicAction}
0217:             * @throws java.io.IOException
0218:             * @since 7.5
0219:             */
0220:            public static final void runAtomicAction(
0221:                    final AtomicAction atomicCode) throws IOException {
0222:                Repository.getDefault().getDefaultFileSystem().runAtomicAction(
0223:                        atomicCode);
0224:            }
0225:
0226:            /**
0227:             * Executes atomic action. For more info see {@link FileSystem#runAtomicAction}. 
0228:             * <p>
0229:             * All events about filesystem changes (related to events on all affected instances of <code>FileSystem</code>)
0230:             * are postponed after the whole <code>atomicCode</code> 
0231:             * is executed.
0232:             * </p>
0233:             * @param atomicCode code that is supposed to be run as atomic action. See {@link FileSystem#runAtomicAction}
0234:             * @since 7.5
0235:             */
0236:            public static final void runAtomicAction(final Runnable atomicCode) {
0237:                final AtomicAction action = new FileSystem.AtomicAction() {
0238:                    public void run() throws IOException {
0239:                        atomicCode.run();
0240:                    }
0241:                };
0242:                try {
0243:                    FileUtil.runAtomicAction(action);
0244:                } catch (IOException ex) {
0245:                    Exceptions.printStackTrace(ex);
0246:                }
0247:            }
0248:
0249:            /**
0250:             * Returns FileObject for a folder.
0251:             * If such a folder does not exist then it is created, including any necessary but nonexistent parent 
0252:             * folders. Note that if this operation fails it may have succeeded in creating some of the necessary
0253:             * parent folders.
0254:             * @param folder folder to be created
0255:             * @return FileObject for a folder
0256:             * @throws java.io.IOException if the creation fails
0257:             * @since 7.0
0258:             */
0259:            public static FileObject createFolder(final File folder)
0260:                    throws IOException {
0261:                File existingFolder = folder;
0262:                while (existingFolder != null && !existingFolder.isDirectory()) {
0263:                    existingFolder = existingFolder.getParentFile();
0264:                }
0265:                if (existingFolder == null) {
0266:                    throw new IOException(folder.getAbsolutePath());
0267:                }
0268:
0269:                FileObject retval = null;
0270:                FileObject folderFo = FileUtil.toFileObject(existingFolder);
0271:                assert folderFo != null : existingFolder.getAbsolutePath();
0272:                final String relativePath = getRelativePath(existingFolder,
0273:                        folder);
0274:                try {
0275:                    retval = FileUtil.createFolder(folderFo, relativePath);
0276:                } catch (IOException ex) {
0277:                    //thus retval = null;
0278:                }
0279:                //if refresh needed because of external changes        
0280:                if (retval == null || !retval.isValid()) {
0281:                    folderFo.getFileSystem().refresh(false);
0282:                    retval = FileUtil.createFolder(folderFo, relativePath);
0283:                }
0284:                assert retval != null;
0285:                return retval;
0286:            }
0287:
0288:            /**Returns FileObject for a data file.
0289:             * If such a data file does not exist then it is created, including any necessary but nonexistent parent
0290:             * folders. Note that if this operation fails it may have succeeded in creating some of the necessary
0291:             * parent folders.
0292:             * @param data data file to be created
0293:             * @return FileObject for a data file
0294:             * @throws java.io.IOException if the creation fails
0295:             * @since 7.0
0296:             */
0297:            public static FileObject createData(final File data)
0298:                    throws IOException {
0299:                File folder = data;
0300:                while (folder != null && !folder.isDirectory()) {
0301:                    folder = folder.getParentFile();
0302:                }
0303:                if (folder == null) {
0304:                    throw new IOException(data.getAbsolutePath());
0305:                }
0306:
0307:                FileObject retval = null;
0308:                FileObject folderFo = FileUtil.toFileObject(folder);
0309:                assert folderFo != null : folder.getAbsolutePath();
0310:                final String relativePath = getRelativePath(folder, data);
0311:                try {
0312:                    retval = FileUtil.createData(folderFo, relativePath);
0313:                } catch (IOException ex) {
0314:                    //thus retval = null;
0315:                }
0316:                //if refresh needed because of external changes        
0317:                if (retval == null || !retval.isValid()) {
0318:                    folderFo.getFileSystem().refresh(false);
0319:                    retval = FileUtil.createData(folderFo, relativePath);
0320:                }
0321:                assert retval != null;
0322:                return retval;
0323:            }
0324:
0325:            private static File getRoot(final File dir) {
0326:                File retval = dir;
0327:                for (; retval.getParentFile() != null; retval = retval
0328:                        .getParentFile())
0329:                    ;
0330:                assert retval != null;
0331:                return retval;
0332:            }
0333:
0334:            private static String getRelativePath(final File dir,
0335:                    final File file) {
0336:                Stack<String> stack = new Stack<String>();
0337:                File tempFile = file;
0338:                while (tempFile != null && !tempFile.equals(dir)) {
0339:                    stack.push(tempFile.getName());
0340:                    tempFile = tempFile.getParentFile();
0341:                }
0342:                assert tempFile != null : file.getAbsolutePath()
0343:                        + "not found in " + dir.getAbsolutePath();//NOI18N
0344:                StringBuilder retval = new StringBuilder();
0345:                while (!stack.isEmpty()) {
0346:                    retval.append(stack.pop());
0347:                    if (!stack.isEmpty()) {
0348:                        retval.append('/');//NOI18N
0349:                    }
0350:                }
0351:                return retval.toString();
0352:            }
0353:
0354:            /** Copies stream of files.
0355:             * <P>
0356:             * Please be aware, that this method doesn't close any of passed streams.
0357:             * @param is input stream
0358:             * @param os output stream
0359:             */
0360:            public static void copy(InputStream is, OutputStream os)
0361:                    throws IOException {
0362:                final byte[] BUFFER = new byte[4096];
0363:                int len;
0364:
0365:                for (;;) {
0366:                    len = is.read(BUFFER);
0367:
0368:                    if (len == -1) {
0369:                        return;
0370:                    }
0371:
0372:                    os.write(BUFFER, 0, len);
0373:                }
0374:            }
0375:
0376:            /** Copies file to the selected folder.
0377:             * This implementation simply copies the file by stream content.
0378:             * @param source source file object
0379:             * @param destFolder destination folder
0380:             * @param newName file name (without extension) of destination file
0381:             * @param newExt extension of destination file
0382:             * @return the created file object in the destination folder
0383:             * @exception IOException if <code>destFolder</code> is not a folder or does not exist; the destination file already exists; or
0384:             *      another critical error occurs during copying
0385:             */
0386:            static FileObject copyFileImpl(FileObject source,
0387:                    FileObject destFolder, String newName, String newExt)
0388:                    throws IOException {
0389:                FileObject dest = destFolder.createData(newName, newExt);
0390:
0391:                FileLock lock = null;
0392:                InputStream bufIn = null;
0393:                OutputStream bufOut = null;
0394:
0395:                try {
0396:                    lock = dest.lock();
0397:                    bufIn = source.getInputStream();
0398:
0399:                    if (dest instanceof  AbstractFileObject) {
0400:                        /** prevents from firing fileChange*/
0401:                        bufOut = ((AbstractFileObject) dest).getOutputStream(
0402:                                lock, false);
0403:                    } else {
0404:                        bufOut = dest.getOutputStream(lock);
0405:                    }
0406:
0407:                    copy(bufIn, bufOut);
0408:                    copyAttributes(source, dest);
0409:                } finally {
0410:                    if (bufIn != null) {
0411:                        bufIn.close();
0412:                    }
0413:
0414:                    if (bufOut != null) {
0415:                        bufOut.close();
0416:                    }
0417:
0418:                    if (lock != null) {
0419:                        lock.releaseLock();
0420:                    }
0421:                }
0422:
0423:                return dest;
0424:            }
0425:
0426:            //
0427:            // public methods
0428:            //
0429:
0430:            /** Factory method that creates an empty implementation of a filesystem that
0431:             * completely resides in a memory.
0432:             * @return a blank writable filesystem
0433:             * @since 4.43
0434:             */
0435:            public static FileSystem createMemoryFileSystem() {
0436:                return new MemoryFileSystem();
0437:            }
0438:
0439:            /** Copies file to the selected folder.
0440:             * This implementation simply copies the file by stream content.
0441:             * @param source source file object
0442:             * @param destFolder destination folder
0443:             * @param newName file name (without extension) of destination file
0444:             * @param newExt extension of destination file
0445:             * @return the created file object in the destination folder
0446:             * @exception IOException if <code>destFolder</code> is not a folder or does not exist; the destination file already exists; or
0447:             *      another critical error occurs during copying
0448:             */
0449:            public static FileObject copyFile(FileObject source,
0450:                    FileObject destFolder, String newName, String newExt)
0451:                    throws IOException {
0452:                return source.copy(destFolder, newName, newExt);
0453:            }
0454:
0455:            /** Copies file to the selected folder.
0456:             * This implementation simply copies the file by stream content.
0457:             * Uses the extension of the source file.
0458:             * @param source source file object
0459:             * @param destFolder destination folder
0460:             * @param newName file name (without extension) of destination file
0461:             * @return the created file object in the destination folder
0462:             * @exception IOException if <code>destFolder</code> is not a folder or does not exist; the destination file already exists; or
0463:             *      another critical error occurs during copying
0464:             */
0465:            public static FileObject copyFile(FileObject source,
0466:                    FileObject destFolder, String newName) throws IOException {
0467:                return copyFile(source, destFolder, newName, source.getExt());
0468:            }
0469:
0470:            /** Moves file to the selected folder.
0471:             * This implementation uses a copy-and-delete mechanism, and automatically uses the necessary lock.
0472:             * @param source source file object
0473:             * @param destFolder destination folder
0474:             * @param newName file name (without extension) of destination file
0475:             * @return new file object
0476:             * @exception IOException if either the {@link #copyFile copy} or {@link FileObject#delete delete} failed
0477:             */
0478:            public static FileObject moveFile(FileObject source,
0479:                    FileObject destFolder, String newName) throws IOException {
0480:                FileLock lock = null;
0481:
0482:                try {
0483:                    lock = source.lock();
0484:
0485:                    return source.move(lock, destFolder, newName, source
0486:                            .getExt());
0487:                } finally {
0488:                    if (lock != null) {
0489:                        lock.releaseLock();
0490:                    }
0491:                }
0492:            }
0493:
0494:            /** Returns a folder on given filesystem if such a folder exists. 
0495:             * If not then a folder is created, including any necessary but nonexistent parent 
0496:             * folders. Note that if this operation fails it may have succeeded in creating some of the necessary
0497:             * parent folders. 
0498:             * The name of the new folder can be
0499:             * specified as a multi-component pathname whose components are separated
0500:             * by File.separatorChar or &quot;/&quot; (forward slash).
0501:             *
0502:             * @param folder where the new folder will be placed in
0503:             * @param name name of the new folder
0504:             * @return the new folder
0505:             * @exception IOException if the creation fails
0506:             */
0507:            public static FileObject createFolder(FileObject folder, String name)
0508:                    throws IOException {
0509:                String separators;
0510:
0511:                if (File.separatorChar != '/') {
0512:                    separators = "/" + File.separatorChar; // NOI18N
0513:                } else {
0514:                    separators = "/"; // NOI18N
0515:                }
0516:
0517:                StringTokenizer st = new StringTokenizer(name, separators);
0518:
0519:                while (st.hasMoreElements()) {
0520:                    name = st.nextToken();
0521:
0522:                    if (name.length() > 0) {
0523:                        FileObject f = folder.getFileObject(name);
0524:
0525:                        if (f == null) {
0526:                            try {
0527:                                f = folder.createFolder(name);
0528:                            } catch (SyncFailedException ex) {
0529:                                // there might be unconsistency between the cache
0530:                                // and the disk, that is why
0531:                                folder.refresh();
0532:
0533:                                // and try again
0534:                                f = folder.getFileObject(name);
0535:
0536:                                if (f == null) {
0537:                                    // if still not found than we have to report the
0538:                                    // exception
0539:                                    throw ex;
0540:                                }
0541:                            }
0542:                        }
0543:
0544:                        folder = f;
0545:                    }
0546:                }
0547:
0548:                return folder;
0549:            }
0550:
0551:            /** Returns a data file on given filesystem if such a data file exists. 
0552:             * If not then a data file is created, including any necessary but nonexistent parent 
0553:             * folders. Note that if this operation fails it may have succeeded in creating some of the necessary
0554:             * parent folders. The name of
0555:             * data file can be composed as resource name (e. g. org/netbeans/myfolder/mydata ).
0556:             *
0557:             * @param folder to begin with creation at
0558:             * @param name name of data file as a resource
0559:             * @return the data file for given name
0560:             * @exception IOException if the creation fails
0561:             */
0562:            public static FileObject createData(FileObject folder, String name)
0563:                    throws IOException {
0564:                if (folder == null) {
0565:                    throw new IllegalArgumentException("Null folder"); // NOI18N
0566:                }
0567:
0568:                if (name == null) {
0569:                    throw new IllegalArgumentException("Null name"); // NOI18N
0570:                }
0571:
0572:                String foldername;
0573:                String dataname;
0574:                String fname;
0575:                String ext;
0576:                int index = name.lastIndexOf('/');
0577:                FileObject data;
0578:
0579:                // names with '/' on the end are not valid
0580:                if (index >= name.length()) {
0581:                    throw new IOException("Wrong file name."); // NOI18N
0582:                }
0583:
0584:                // if name contains '/', create necessary folder first
0585:                if (index != -1) {
0586:                    foldername = name.substring(0, index);
0587:                    dataname = name.substring(index + 1);
0588:                    folder = createFolder(folder, foldername);
0589:                    assert folder != null;
0590:                } else {
0591:                    dataname = name;
0592:                }
0593:
0594:                // create data
0595:                index = dataname.lastIndexOf('.');
0596:
0597:                if (index != -1) {
0598:                    fname = dataname.substring(0, index);
0599:                    ext = dataname.substring(index + 1);
0600:                } else {
0601:                    fname = dataname;
0602:                    ext = ""; // NOI18N
0603:                }
0604:
0605:                data = folder.getFileObject(fname, ext);
0606:
0607:                if (data == null) {
0608:                    try {
0609:                        data = folder.createData(fname, ext);
0610:                        assert data != null : "FileObject.createData cannot return null; called on "
0611:                                + folder + " + " + fname + " + " + ext; // #50802
0612:                    } catch (SyncFailedException ex) {
0613:                        // there might be unconsistency between the cache
0614:                        // and the disk, that is why
0615:                        folder.refresh();
0616:
0617:                        // and try again
0618:                        data = folder.getFileObject(fname, ext);
0619:
0620:                        if (data == null) {
0621:                            // if still not found than we have to report the
0622:                            // exception
0623:                            throw ex;
0624:                        }
0625:                    }
0626:                }
0627:
0628:                return data;
0629:            }
0630:
0631:            /** Finds appropriate java.io.File to FileObject if possible.
0632:             * If not possible then null is returned.
0633:             * This is the inverse operation of {@link #toFileObject}.
0634:             * @param fo FileObject whose corresponding File will be looked for
0635:             * @return java.io.File or null if no corresponding File exists.
0636:             * @since 1.29
0637:             */
0638:            public static File toFile(FileObject fo) {
0639:                File retVal = (File) fo.getAttribute("java.io.File"); // NOI18N;        
0640:
0641:                if (retVal == null) {
0642:                    URL fileURL = null;
0643:                    int[] types = new int[] { URLMapper.INTERNAL,
0644:                            URLMapper.EXTERNAL };
0645:
0646:                    for (int i = 0; ((fileURL == null) || "file".equals(fileURL
0647:                            .getProtocol()))
0648:                            && (i < types.length); i++) { // NOI18N
0649:                        fileURL = URLMapper.findURL(fo, types[i]);
0650:                    }
0651:
0652:                    if ((fileURL != null)
0653:                            && "file".equals(fileURL.getProtocol())) {
0654:                        retVal = new File(URI.create(fileURL.toExternalForm()));
0655:                    }
0656:                }
0657:
0658:                return (retVal != null) ? normalizeFile(retVal) : null;
0659:            }
0660:
0661:            /**
0662:             * Converts a disk file to a matching file object.
0663:             * This is the inverse operation of {@link #toFile}.
0664:             * <p class="nonnormative">
0665:             * If you are running with the MasterFS module enabled, that will guarantee
0666:             * that this method never returns null for a file which exists on disk.
0667:             * </p>
0668:             * @param file a disk file (may or may not exist). This file
0669:             * must be {@link #normalizeFile normalized}.
0670:             * @return a corresponding file object, or null if the file does not exist
0671:             *         or there is no {@link URLMapper} available to convert it
0672:             * @since 4.29
0673:             */
0674:            public static FileObject toFileObject(File file) {
0675:                boolean asserts = false;
0676:                assert asserts = true;
0677:                if (asserts) {
0678:                    File normFile = normalizeFile(file);
0679:                    if (!file.equals(normFile)) {
0680:                        Logger.getLogger(FileUtil.class.getName()).log(
0681:                                Level.WARNING,
0682:                                null,
0683:                                new IllegalArgumentException(
0684:                                        "Parameter file was not "
0685:                                                + // NOI18N   
0686:                                                "normalized. Was " + file
0687:                                                + " instead of " + normFile));
0688:                    }
0689:                    file = normFile;
0690:                }
0691:
0692:                FileObject retVal = null;
0693:
0694:                try {
0695:                    URL url = fileToURL(file);
0696:
0697:                    if ((url.getAuthority() != null)
0698:                            && (Utilities.isWindows() || (Utilities
0699:                                    .getOperatingSystem() == Utilities.OS_OS2))) {
0700:                        return null;
0701:                    }
0702:
0703:                    retVal = URLMapper.findFileObject(url);
0704:
0705:                    /*probably temporary piece of code to catch the cause of #46630*/
0706:                } catch (MalformedURLException e) {
0707:                    retVal = null;
0708:                }
0709:
0710:                if (retVal != null) {
0711:                    if (getDiskFileSystem() == null) {
0712:                        try {
0713:                            FileSystem fs = retVal.getFileSystem();
0714:                            setDiskFileSystem(fs);
0715:                        } catch (FileStateInvalidException ex) {
0716:                            Exceptions.printStackTrace(ex);
0717:                        }
0718:                    }
0719:                }
0720:                return retVal;
0721:            }
0722:
0723:            static URL fileToURL(File file) throws MalformedURLException {
0724:                URL retVal = null;
0725:
0726:                if (!Utilities.isWindows() || canBeCanonicalizedOnWindows(file)) {
0727:                    retVal = file.toURI().toURL();
0728:                } else {
0729:                    if (Utilities.isWindows() && file.getParentFile() == null) {
0730:                        retVal = new URL("file:/"
0731:                                + file.getAbsolutePath().toUpperCase()); //NOI18N
0732:                    } else {
0733:                        retVal = new URL("file:/" + file.getAbsolutePath()); //NOI18N
0734:                    }
0735:                }
0736:
0737:                return retVal;
0738:            }
0739:
0740:            /** Finds appropriate FileObjects to java.io.File if possible.
0741:             * If not possible then empty array is returned. More FileObjects may
0742:             * correspond to one java.io.File that`s why array is returned.
0743:             * @param file File whose corresponding FileObjects will be looked for.
0744:             * The file has to be "normalized" otherwise IllegalArgumentException is thrown.
0745:             * See {@link #normalizeFile} for how to do that.
0746:             * @return corresponding FileObjects or empty array  if no
0747:             * corresponding FileObject exists.
0748:             * @since 1.29
0749:             * @deprecated Use {@link #toFileObject} instead.
0750:             */
0751:            @Deprecated
0752:            public static FileObject[] fromFile(File file) {
0753:                FileObject[] retVal;
0754:
0755:                if (!file.equals(normalizeFile(file))) {
0756:                    throw new IllegalArgumentException(
0757:                            "Parameter file was not "
0758:                                    + // NOI18N
0759:                                    "normalized. Was " + file + " instead of "
0760:                                    + normalizeFile(file)); // NOI18N
0761:                }
0762:
0763:                try {
0764:                    URL url = (file.toURI().toURL());
0765:
0766:                    if ((url.getAuthority() != null)
0767:                            && (Utilities.isWindows() || (Utilities
0768:                                    .getOperatingSystem() == Utilities.OS_OS2))) {
0769:                        return null;
0770:                    }
0771:
0772:                    retVal = URLMapper.findFileObjects(url);
0773:                } catch (MalformedURLException e) {
0774:                    retVal = null;
0775:                }
0776:
0777:                return retVal;
0778:            }
0779:
0780:            /** Copies attributes from one file to another.
0781:             * Note: several special attributes will not be copied, as they should
0782:             * semantically be transient. These include attributes used by the
0783:             * template wizard (but not the template attribute itself).
0784:             * @param source source file object
0785:             * @param dest destination file object
0786:             * @exception IOException if the copying failed
0787:             */
0788:            public static void copyAttributes(FileObject source, FileObject dest)
0789:                    throws IOException {
0790:                Enumeration<String> attrKeys = source.getAttributes();
0791:
0792:                while (attrKeys.hasMoreElements()) {
0793:                    String key = attrKeys.nextElement();
0794:
0795:                    if (transientAttributes.contains(key)) {
0796:                        continue;
0797:                    }
0798:
0799:                    if (isTransient(source, key)) {
0800:                        continue;
0801:                    }
0802:
0803:                    Object value = source.getAttribute(key);
0804:
0805:                    if (value != null) {
0806:                        dest.setAttribute(key, value);
0807:                    }
0808:                }
0809:            }
0810:
0811:            static boolean isTransient(FileObject fo, String attrName) {
0812:                return XMLMapAttr.ModifiedAttribute.isTransient(fo, attrName);
0813:            }
0814:
0815:            /** Extract jar file into folder represented by file object. If the JAR contains
0816:             * files with name filesystem.attributes, it is assumed that these files
0817:             * has been created by DefaultAttributes implementation and the content
0818:             * of these files is treated as attributes and added to extracted files.
0819:             * <p><code>META-INF/</code> directories are skipped over.
0820:             *
0821:             * @param fo file object of destination folder
0822:             * @param is input stream of jar file
0823:             * @exception IOException if the extraction fails
0824:             * @deprecated Use of XML filesystem layers generally obsoletes this method.
0825:             */
0826:            @Deprecated
0827:            public static void extractJar(final FileObject fo,
0828:                    final InputStream is) throws IOException {
0829:                FileSystem fs = fo.getFileSystem();
0830:
0831:                fs.runAtomicAction(new FileSystem.AtomicAction() {
0832:                    public void run() throws IOException {
0833:                        extractJarImpl(fo, is);
0834:                    }
0835:                });
0836:            }
0837:
0838:            /** Does the actual extraction of the Jar file.
0839:             */
0840:            private static void extractJarImpl(FileObject fo, InputStream is)
0841:                    throws IOException {
0842:                JarInputStream jis;
0843:                JarEntry je;
0844:
0845:                // files with extended attributes (name, DefaultAttributes.Table)
0846:                HashMap<String, DefaultAttributes.Table> attributes = new HashMap<String, DefaultAttributes.Table>(
0847:                        7);
0848:
0849:                jis = new JarInputStream(is);
0850:
0851:                while ((je = jis.getNextJarEntry()) != null) {
0852:                    String name = je.getName();
0853:
0854:                    if (name.toLowerCase().startsWith("meta-inf/")) {
0855:                        continue; // NOI18N
0856:                    }
0857:
0858:                    if (je.isDirectory()) {
0859:                        createFolder(fo, name);
0860:
0861:                        continue;
0862:                    }
0863:
0864:                    if (DefaultAttributes.acceptName(name)) {
0865:                        // file with extended attributes
0866:                        DefaultAttributes.Table table = DefaultAttributes
0867:                                .loadTable(jis, name);
0868:                        attributes.put(name, table);
0869:                    } else {
0870:                        // copy the file
0871:                        FileObject fd = createData(fo, name);
0872:                        FileLock lock = fd.lock();
0873:
0874:                        try {
0875:                            OutputStream os = fd.getOutputStream(lock);
0876:
0877:                            try {
0878:                                copy(jis, os);
0879:                            } finally {
0880:                                os.close();
0881:                            }
0882:                        } finally {
0883:                            lock.releaseLock();
0884:                        }
0885:                    }
0886:                }
0887:
0888:                //
0889:                // apply all extended attributes
0890:                //
0891:                Iterator it = attributes.entrySet().iterator();
0892:
0893:                while (it.hasNext()) {
0894:                    Map.Entry entry = (Map.Entry) it.next();
0895:
0896:                    String fileName = (String) entry.getKey();
0897:                    int last = fileName.lastIndexOf('/');
0898:                    String dirName;
0899:
0900:                    if (last != -1) {
0901:                        dirName = fileName.substring(0, last + 1);
0902:                    } else {
0903:                        dirName = ""; // NOI18N
0904:                    }
0905:
0906:                    String prefix = fo.isRoot() ? dirName
0907:                            : (fo.getPath() + '/' + dirName);
0908:
0909:                    DefaultAttributes.Table t = (DefaultAttributes.Table) entry
0910:                            .getValue();
0911:                    Iterator files = t.keySet().iterator();
0912:
0913:                    while (files.hasNext()) {
0914:                        String orig = (String) files.next();
0915:                        String fn = prefix + orig;
0916:                        FileObject obj = fo.getFileSystem().findResource(fn);
0917:
0918:                        if (obj == null) {
0919:                            continue;
0920:                        }
0921:
0922:                        Enumeration<String> attrEnum = t.attrs(orig);
0923:
0924:                        while (attrEnum.hasMoreElements()) {
0925:                            // iterate thru all arguments
0926:                            String attrName = attrEnum.nextElement();
0927:
0928:                            // Note: even transient attributes set here!
0929:                            Object value = t.getAttr(orig, attrName);
0930:
0931:                            if (value != null) {
0932:                                obj.setAttribute(attrName, value);
0933:                            }
0934:                        }
0935:                    }
0936:                }
0937:            }
0938:
0939:            // extractJar
0940:
0941:            /** Gets the extension of a specified file name. The extension is
0942:             * everything after the last dot.
0943:             *
0944:             * @param fileName name of the file
0945:             * @return extension of the file (or <code>""</code> if it had none)
0946:             */
0947:            public static String getExtension(String fileName) {
0948:                int index = fileName.lastIndexOf("."); // NOI18N
0949:
0950:                if (index == -1) {
0951:                    return ""; // NOI18N
0952:                } else {
0953:                    return fileName.substring(index + 1);
0954:                }
0955:            }
0956:
0957:            /** Finds an unused file name similar to that requested in the same folder.
0958:             * The specified file name is used if that does not yet exist or is
0959:             * {@link FileObject#isVirtual isVirtual}.
0960:             * Otherwise, the first available name of the form <code>basename_nnn.ext</code> (counting from one) is used.
0961:             *
0962:             * <p><em>Caution:</em> this method does not lock the parent folder
0963:             * to prevent race conditions: i.e. it is possible (though unlikely)
0964:             * that the resulting name will have been created by another thread
0965:             * just as you were about to create the file yourself (if you are,
0966:             * in fact, intending to create it just after this call). Since you
0967:             * cannot currently lock a folder against child creation actions,
0968:             * the safe approach is to use a loop in which a free name is
0969:             * retrieved; an attempt is made to {@link FileObject#createData create}
0970:             * that file; and upon an <code>IOException</code> during
0971:             * creation, retry the loop up to a few times before giving up.
0972:             *
0973:             * @param folder parent folder
0974:             * @param name preferred base name of file
0975:             * @param ext extension to use
0976:             * @return a free file name <strong>(without the extension)</strong>
0977:             */
0978:            public static String findFreeFileName(FileObject folder,
0979:                    String name, String ext) {
0980:                if (checkFreeName(folder, name, ext)) {
0981:                    return name;
0982:                }
0983:
0984:                for (int i = 1;; i++) {
0985:                    String destName = name + "_" + i; // NOI18N
0986:
0987:                    if (checkFreeName(folder, destName, ext)) {
0988:                        return destName;
0989:                    }
0990:                }
0991:            }
0992:
0993:            /** Finds an unused folder name similar to that requested in the same parent folder.
0994:             * <p>See caveat for <code>findFreeFileName</code>.
0995:             * @see #findFreeFileName findFreeFileName
0996:             * @param folder parent folder
0997:             * @param name preferred folder name
0998:             * @return a free folder name
0999:             */
1000:            public static String findFreeFolderName(FileObject folder,
1001:                    String name) {
1002:                if (checkFreeName(folder, name, null)) {
1003:                    return name;
1004:                }
1005:
1006:                for (int i = 1;; i++) {
1007:                    String destName = name + "_" + i; // NOI18N
1008:
1009:                    if (checkFreeName(folder, destName, null)) {
1010:                        return destName;
1011:                    }
1012:                }
1013:            }
1014:
1015:            /**
1016:             * Gets a relative resource path between folder and fo.
1017:             * @param folder root of filesystem or any other folder in folders hierarchy
1018:             * @param fo arbitrary FileObject in folder's tree (including folder itself)
1019:             * @return relative path between folder and fo. The returned path never
1020:             * starts with a '/'. It never ends with a '/'. Specifically, if
1021:             * folder==fo, returns "". Returns <code>null</code> if fo is not in
1022:             * folder's tree.
1023:             * @see #isParentOf
1024:             * @since 4.16
1025:             */
1026:            public static String getRelativePath(FileObject folder,
1027:                    FileObject fo) {
1028:                if (!isParentOf(folder, fo) && (folder != fo)) {
1029:                    return null;
1030:                }
1031:
1032:                String result = fo.getPath().substring(
1033:                        folder.getPath().length());
1034:
1035:                if (result.startsWith("/")) {
1036:                    result = result.substring(1);
1037:                }
1038:
1039:                return result;
1040:            }
1041:
1042:            /** Test if given name is free in given folder.
1043:             * @param fo folder to check in
1044:             * @param name name of the file or folder to check
1045:             * @param ext extension of the file (null for folders)
1046:             * @return true, if such name does not exists
1047:             */
1048:            private static boolean checkFreeName(FileObject fo, String name,
1049:                    String ext) {
1050:                if ((Utilities.isWindows() || (Utilities.getOperatingSystem() == Utilities.OS_OS2))
1051:                        || Utilities.isMac()) {
1052:                    // case-insensitive, do some special check
1053:                    Enumeration<? extends FileObject> en = fo
1054:                            .getChildren(false);
1055:
1056:                    while (en.hasMoreElements()) {
1057:                        fo = en.nextElement();
1058:
1059:                        String n = fo.getName();
1060:                        String e = fo.getExt();
1061:
1062:                        // different names => check others
1063:                        if (!n.equalsIgnoreCase(name)) {
1064:                            continue;
1065:                        }
1066:
1067:                        // same name + without extension => no
1068:                        if (((ext == null) || (ext.trim().length() == 0))
1069:                                && ((e == null) || (e.trim().length() == 0))) {
1070:                            return fo.isVirtual();
1071:                        }
1072:
1073:                        // one of there is witout extension => check next
1074:                        if ((ext == null) || (e == null)) {
1075:                            continue;
1076:                        }
1077:
1078:                        if (ext.equalsIgnoreCase(e)) {
1079:                            // same name + same extension => no
1080:                            return fo.isVirtual();
1081:                        }
1082:                    }
1083:
1084:                    // no of the files has similar name and extension
1085:                    return true;
1086:                } else {
1087:                    if (ext == null) {
1088:                        fo = fo.getFileObject(name);
1089:
1090:                        if (fo == null) {
1091:                            return true;
1092:                        }
1093:
1094:                        return fo.isVirtual();
1095:                    } else {
1096:                        fo = fo.getFileObject(name, ext);
1097:
1098:                        if (fo == null) {
1099:                            return true;
1100:                        }
1101:
1102:                        return fo.isVirtual();
1103:                    }
1104:                }
1105:            }
1106:
1107:            // note: "sister" is preferred in English, please don't ask me why --jglick // NOI18N
1108:
1109:            /** Finds brother file with same base name but different extension.
1110:             * @param fo the file to find the brother for or <CODE>null</CODE>
1111:             * @param ext extension for the brother file
1112:             * @return a brother file (with the requested extension and the same parent folder as the original) or
1113:             *   <CODE>null</CODE> if the brother file does not exist or the original file was <CODE>null</CODE>
1114:             */
1115:            public static FileObject findBrother(FileObject fo, String ext) {
1116:                if (fo == null) {
1117:                    return null;
1118:                }
1119:
1120:                FileObject parent = fo.getParent();
1121:
1122:                if (parent == null) {
1123:                    return null;
1124:                }
1125:
1126:                return parent.getFileObject(fo.getName(), ext);
1127:            }
1128:
1129:            /** Obtain MIME type for a well-known extension.
1130:             * If there is a case-sensitive match, that is used, else will fall back
1131:             * to a case-insensitive match.
1132:             * @param ext the extension: <code>"jar"</code>, <code>"zip"</code>, etc.
1133:             * @return the MIME type for the extension, or <code>null</code> if the extension is unrecognized
1134:             * @deprecated use {@link #getMIMEType(FileObject) getMIMEType(FileObject)} as MIME cannot
1135:             * be generally detected by file object extension.
1136:             */
1137:            @Deprecated
1138:            public static String getMIMEType(String ext) {
1139:                String s = map.get(ext);
1140:
1141:                if (s != null) {
1142:                    return s;
1143:                } else {
1144:                    return map.get(ext.toLowerCase());
1145:                }
1146:            }
1147:
1148:            /** Resolves MIME type. Registered resolvers are invoked and used to achieve this goal.
1149:             * Resolvers must subclass MIMEResolver. If resolvers don`t recognize MIME type then
1150:             * MIME type is obtained  for a well-known extension.
1151:             * @param fo whose MIME type should be recognized
1152:             * @return the MIME type for the FileObject, or <code>null</code> if the FileObject is unrecognized
1153:             */
1154:            public static String getMIMEType(FileObject fo) {
1155:                String retVal = MIMESupport.findMIMEType(fo, null);
1156:
1157:                if (retVal == null) {
1158:                    retVal = getMIMEType(fo.getExt());
1159:                }
1160:
1161:                return retVal;
1162:            }
1163:
1164:            /** Finds mime type by calling getMIMEType, but
1165:             * instead of returning null it fallbacks to default type
1166:             * either text/plain or content/unknown (even for folders)
1167:             */
1168:            static String getMIMETypeOrDefault(FileObject fo) {
1169:                String def = getMIMEType(fo.getExt());
1170:                String t = MIMESupport.findMIMEType(fo, def);
1171:
1172:                if (t == null) {
1173:                    // #42965: never allowed
1174:                    t = "content/unknown"; // NOI18N
1175:                }
1176:
1177:                return t;
1178:            }
1179:
1180:            /**
1181:             * Register MIME type for a new extension.
1182:             * Note that you may register a case-sensitive extension if that is
1183:             * relevant (for example <samp>*.C</samp> for C++) but if you register
1184:             * a lowercase extension it will by default apply to uppercase extensions
1185:             * too (for use on Windows or generally for situations where filenames
1186:             * become accidentally uppercase).
1187:             * @param ext the file extension (should be lowercase unless you specifically care about case)
1188:             * @param mimeType the new MIME type
1189:             * @throws IllegalArgumentException if this extension was already registered with a <em>different</em> MIME type
1190:             * @see #getMIMEType
1191:             * @deprecated You should instead use the more general {@link MIMEResolver} system.
1192:             */
1193:            @Deprecated
1194:            public static void setMIMEType(String ext, String mimeType) {
1195:                synchronized (map) {
1196:                    String old = map.get(ext);
1197:
1198:                    if (old == null) {
1199:                        map.put(ext, mimeType);
1200:                    } else {
1201:                        if (!old.equals(mimeType)) {
1202:                            throw new IllegalArgumentException(
1203:                                    "Cannot overwrite existing MIME type mapping for extension `"
1204:                                            + // NOI18N
1205:                                            ext + "' with " + mimeType
1206:                                            + " (was " + old + ")"); // NOI18N
1207:                        }
1208:
1209:                        // else do nothing
1210:                    }
1211:                }
1212:            }
1213:
1214:            /**
1215:             * Construct a stream handler that handles the <code>nbfs</code> URL protocol
1216:             * used for accessing file objects directly.
1217:             * This method is not intended for module use; only the core
1218:             * should need to call it.
1219:             * Modules probably need only use {@link URLMapper} to create and decode such
1220:             * URLs.
1221:             * @since 3.17
1222:             */
1223:            public static URLStreamHandler nbfsURLStreamHandler() {
1224:                return FileURL.HANDLER;
1225:            }
1226:
1227:            /** Recursively checks whether the file is underneath the folder. It checks whether
1228:             * the file and folder are located on the same filesystem, in such case it checks the
1229:             * parent <code>FileObject</code> of the file recursively until the folder is found
1230:             * or the root of the filesystem is reached.
1231:             * <p><strong>Warning:</strong> this method will return false in the case that
1232:             * <code>folder == fo</code>.
1233:             * @param folder the root of folders hierarchy to search in
1234:             * @param fo the file to search for
1235:             * @return <code>true</code>, if <code>fo</code> lies somewhere underneath the <code>folder</code>,
1236:             * <code>false</code> otherwise
1237:             * @since 3.16
1238:             */
1239:            public static boolean isParentOf(FileObject folder, FileObject fo) {
1240:                if (folder == null) {
1241:                    throw new IllegalArgumentException(
1242:                            "Tried to pass null folder arg"); // NOI18N
1243:                }
1244:
1245:                if (fo == null) {
1246:                    throw new IllegalArgumentException(
1247:                            "Tried to pass null fo arg"); // NOI18N
1248:                }
1249:
1250:                if (folder.isData()) {
1251:                    return false;
1252:                }
1253:
1254:                try {
1255:                    if (folder.getFileSystem() != fo.getFileSystem()) {
1256:                        return false;
1257:                    }
1258:                } catch (FileStateInvalidException e) {
1259:                    return false;
1260:                }
1261:
1262:                FileObject parent = fo.getParent();
1263:
1264:                while (parent != null) {
1265:                    if (parent == folder) {
1266:                        return true;
1267:                    }
1268:
1269:                    parent = parent.getParent();
1270:                }
1271:
1272:                return false;
1273:            }
1274:
1275:            /** Creates a weak implementation of FileChangeListener.
1276:             *
1277:             * @param l the listener to delegate to
1278:             * @param source the source that the listener should detach from when
1279:             *     listener <CODE>l</CODE> is freed, can be <CODE>null</CODE>
1280:             * @return a FileChangeListener delegating to <CODE>l</CODE>.
1281:             * @since 4.10
1282:             */
1283:            public static FileChangeListener weakFileChangeListener(
1284:                    FileChangeListener l, Object source) {
1285:                return WeakListeners
1286:                        .create(FileChangeListener.class, l, source);
1287:            }
1288:
1289:            /** Creates a weak implementation of FileStatusListener.
1290:             *
1291:             * @param l the listener to delegate to
1292:             * @param source the source that the listener should detach from when
1293:             *     listener <CODE>l</CODE> is freed, can be <CODE>null</CODE>
1294:             * @return a FileChangeListener delegating to <CODE>l</CODE>.
1295:             * @since 4.10
1296:             */
1297:            public static FileStatusListener weakFileStatusListener(
1298:                    FileStatusListener l, Object source) {
1299:                return WeakListeners
1300:                        .create(FileStatusListener.class, l, source);
1301:            }
1302:
1303:            /**
1304:             * Get an appropriate display name for a file object.
1305:             * If the file corresponds to a path on disk, this will be the disk path.
1306:             * Otherwise the name will mention the filesystem name or archive name in case
1307:             * the file comes from archive and relative path. Relative path will be mentioned
1308:             * just in case that passed <code>FileObject</code> isn't root {@link FileObject#isRoot}.
1309:             *
1310:             * @param fo a file object
1311:             * @return a display name indicating where the file is
1312:             * @since 4.39
1313:             */
1314:            public static String getFileDisplayName(FileObject fo) {
1315:                String displayName = null;
1316:                File f = FileUtil.toFile(fo);
1317:
1318:                if (f != null) {
1319:                    displayName = f.getAbsolutePath();
1320:                } else {
1321:                    FileObject archiveFile = FileUtil.getArchiveFile(fo);
1322:
1323:                    if (archiveFile != null) {
1324:                        displayName = getArchiveDisplayName(fo, archiveFile);
1325:                    }
1326:                }
1327:
1328:                if (displayName == null) {
1329:                    try {
1330:                        if (fo.isRoot()) {
1331:                            displayName = fo.getFileSystem().getDisplayName();
1332:                        } else {
1333:                            displayName = NbBundle.getMessage(FileUtil.class,
1334:                                    "LBL_file_in_filesystem", fo.getPath(), fo
1335:                                            .getFileSystem().getDisplayName());
1336:                        }
1337:                    } catch (FileStateInvalidException e) {
1338:                        // Not relevant now, just use the simple path.
1339:                        displayName = fo.getPath();
1340:                    }
1341:                }
1342:
1343:                return displayName;
1344:            }
1345:
1346:            private static String getArchiveDisplayName(FileObject fo,
1347:                    FileObject archiveFile) {
1348:                String displayName = null;
1349:
1350:                File f = FileUtil.toFile(archiveFile);
1351:
1352:                if (f != null) {
1353:                    String archivDisplayName = f.getAbsolutePath();
1354:
1355:                    if (fo.isRoot()) {
1356:                        displayName = archivDisplayName;
1357:                    } else {
1358:                        String entryPath = fo.getPath();
1359:                        displayName = NbBundle.getMessage(FileUtil.class,
1360:                                "LBL_file_in_filesystem", entryPath,
1361:                                archivDisplayName);
1362:                    }
1363:                }
1364:
1365:                return displayName;
1366:            }
1367:
1368:            /**
1369:             * Normalize a file path to a clean form.
1370:             * This method may for example make sure that the returned file uses
1371:             * the natural case on Windows; that old Windows 8.3 filenames are changed to the long form;
1372:             * that relative paths are changed to be
1373:             * absolute; that <code>.</code> and <code>..</code> sequences are removed; etc.
1374:             * Unlike {@link File#getCanonicalFile} this method will not traverse symbolic links on Unix.
1375:             * <p>This method involves some overhead and should not be called frivolously.
1376:             * Generally it should be called on <em>incoming</em> pathnames that are gotten from user input
1377:             * (including filechoosers), configuration files, Ant properties, etc. <em>Internal</em>
1378:             * calculations should not need to renormalize paths since {@link File#listFiles},
1379:             * {@link File#getParentFile}, etc. will not produce abnormal variants.
1380:             * @param file file to normalize
1381:             * @return normalized file
1382:             * @since 4.48
1383:             */
1384:            public static File normalizeFile(final File file) {
1385:                File retFile;
1386:
1387:                if ((Utilities.isWindows() || (Utilities.getOperatingSystem() == Utilities.OS_OS2))) {
1388:                    retFile = normalizeFileOnWindows(file);
1389:                } else if (Utilities.isMac()) {
1390:                    retFile = normalizeFileOnMac(file);
1391:                } else {
1392:                    retFile = normalizeFileOnUnixAlike(file);
1393:                }
1394:
1395:                return (file.getPath().equals(retFile.getPath())) ? file
1396:                        : retFile;
1397:            }
1398:
1399:            private static File normalizeFileOnUnixAlike(File file) {
1400:                // On Unix, do not want to traverse symlinks.
1401:                if (file.getAbsolutePath().equals("/..")) { // NOI18N
1402:
1403:                    // Special treatment.
1404:                    file = new File("/"); // NOI18N
1405:                } else {
1406:                    // URI.normalize removes ../ and ./ sequences nicely.
1407:                    file = new File(file.toURI().normalize()).getAbsoluteFile();
1408:                }
1409:
1410:                return file;
1411:            }
1412:
1413:            private static File normalizeFileOnMac(final File file) {
1414:                File retVal = file;
1415:
1416:                try {
1417:                    // URI.normalize removes ../ and ./ sequences nicely.            
1418:                    File absoluteFile = new File(file.toURI().normalize());
1419:                    File canonicalFile = file.getCanonicalFile();
1420:                    boolean isSymLink = !canonicalFile.getAbsolutePath()
1421:                            .equalsIgnoreCase(absoluteFile.getAbsolutePath());
1422:
1423:                    if (isSymLink) {
1424:                        retVal = normalizeSymLinkOnMac(absoluteFile);
1425:                    } else {
1426:                        retVal = canonicalFile;
1427:                    }
1428:                } catch (IOException ioe) {
1429:                    Logger.getAnonymousLogger()
1430:                            .severe(
1431:                                    "Normalization failed on file " + file
1432:                                            + ": " + ioe);
1433:
1434:                    // OK, so at least try to absolutize the path
1435:                    retVal = file.getAbsoluteFile();
1436:                }
1437:
1438:                return retVal;
1439:            }
1440:
1441:            /**
1442:             * @param file is expected to be already absolute with removed ../ and ./
1443:             */
1444:            private static File normalizeSymLinkOnMac(final File file)
1445:                    throws IOException {
1446:                File retVal = File.listRoots()[0];
1447:                File pureCanonicalFile = retVal;
1448:
1449:                final String pattern = File.separator + ".." + File.separator; //NOI18N                
1450:                final String fileName;
1451:
1452:                { // strips insufficient non-<tt>".."</tt> segments preceding them
1453:
1454:                    String tmpFileName = file.getAbsolutePath();
1455:                    int index = tmpFileName.lastIndexOf(pattern);
1456:
1457:                    if (index > -1) {
1458:                        tmpFileName = tmpFileName.substring(index
1459:                                + pattern.length()); //Remove starting {/../}*
1460:                    }
1461:
1462:                    fileName = tmpFileName;
1463:                }
1464:
1465:                /*normalized step after step*/
1466:                StringTokenizer fileSegments = new StringTokenizer(fileName,
1467:                        File.separator);
1468:
1469:                while (fileSegments.hasMoreTokens()) {
1470:                    File absolutelyEndingFile = new File(pureCanonicalFile,
1471:                            fileSegments.nextToken());
1472:                    pureCanonicalFile = absolutelyEndingFile.getCanonicalFile();
1473:
1474:                    boolean isSymLink = !pureCanonicalFile.getAbsolutePath()
1475:                            .equalsIgnoreCase(
1476:                                    absolutelyEndingFile.getAbsolutePath());
1477:
1478:                    if (isSymLink) {
1479:                        retVal = new File(retVal, absolutelyEndingFile
1480:                                .getName());
1481:                    } else {
1482:                        retVal = new File(retVal, pureCanonicalFile.getName());
1483:                    }
1484:                }
1485:
1486:                return retVal;
1487:            }
1488:
1489:            private static File normalizeFileOnWindows(final File file) {
1490:                File retVal = null;
1491:
1492:                if (canBeCanonicalizedOnWindows(file)) {
1493:                    try {
1494:                        retVal = file.getCanonicalFile();
1495:                    } catch (IOException e) {
1496:                        Logger.getAnonymousLogger().severe(
1497:                                "getCanonicalFile() on file " + file
1498:                                        + " failed. " + e.toString()); // NOI18N
1499:                    }
1500:                }
1501:
1502:                return (retVal != null) ? retVal : file.getAbsoluteFile();
1503:            }
1504:
1505:            private static FileSystemView fileSystemView;
1506:            private static float javaSpecVersion;
1507:
1508:            private static boolean canBeCanonicalizedOnWindows(final File file) {
1509:                /*#4089199, #95031 - Flopy and empty CD-drives can't be canonicalized*/
1510:                boolean canBeCanonizalized = true;
1511:                if (file.getParent() == null && Utilities.isWindows()) {//NOI18N
1512:                    FileSystemView fsv = getFileSystemView();
1513:                    canBeCanonizalized = (fsv != null) ? !fsv
1514:                            .isFloppyDrive(file)
1515:                            && file.exists() : false;
1516:                }
1517:
1518:                return canBeCanonizalized;
1519:            }
1520:
1521:            private static boolean is4089199() {
1522:                return /*98388*/Utilities.isWindows()
1523:                        && getJavaSpecVersion() < 1.6;
1524:            }
1525:
1526:            private static float getJavaSpecVersion() {
1527:                synchronized (FileUtil.class) {
1528:                    if (javaSpecVersion == 0) {
1529:                        javaSpecVersion = Float.valueOf(System
1530:                                .getProperty("java.specification.version"));//NOI18N
1531:                    }
1532:                }
1533:                return javaSpecVersion;
1534:            }
1535:
1536:            private static FileSystemView getFileSystemView() {
1537:                boolean init = false;
1538:                final FileSystemView[] fsv = { fileSystemView };
1539:
1540:                synchronized (FileUtil.class) {
1541:                    init = is4089199() && fsv[0] == null;
1542:                }
1543:
1544:                if (init) {
1545:                    if (SwingUtilities.isEventDispatchThread()) {
1546:                        fsv[0] = javax.swing.filechooser.FileSystemView
1547:                                .getFileSystemView();
1548:                        synchronized (FileUtil.class) {
1549:                            fileSystemView = fsv[0];
1550:                        }
1551:                    } else {
1552:                        SwingUtilities.invokeLater(new java.lang.Runnable() {
1553:                            public void run() {
1554:                                fsv[0] = javax.swing.filechooser.FileSystemView
1555:                                        .getFileSystemView();
1556:                                synchronized (FileUtil.class) {
1557:                                    fileSystemView = fsv[0];
1558:                                }
1559:                            }
1560:                        });
1561:                    }
1562:                }
1563:                return fileSystemView;
1564:            }
1565:
1566:            /**
1567:             * Returns a FileObject representing the root folder of an archive.
1568:             * Clients may need to first call {@link #isArchiveFile(FileObject)} to determine
1569:             * if the file object refers to an archive file.
1570:             * @param fo a ZIP- (or JAR-) format archive file
1571:             * @return a virtual archive root folder, or null if the file is not actually an archive
1572:             * @since 4.48
1573:             */
1574:            public static FileObject getArchiveRoot(FileObject fo) {
1575:                URL archiveURL = URLMapper.findURL(fo, URLMapper.EXTERNAL);
1576:
1577:                if (archiveURL == null) {
1578:                    return null;
1579:                }
1580:
1581:                return URLMapper.findFileObject(getArchiveRoot(archiveURL));
1582:            }
1583:
1584:            /**
1585:             * Returns a URL representing the root of an archive.
1586:             * Clients may need to first call {@link #isArchiveFile(URL)} to determine if the URL
1587:             * refers to an archive file.
1588:             * @param url of a ZIP- (or JAR-) format archive file
1589:             * @return the <code>jar</code>-protocol URL of the root of the archive
1590:             * @since 4.48
1591:             */
1592:            public static URL getArchiveRoot(URL url) {
1593:                try {
1594:                    // XXX TBD whether the url should ever be escaped...
1595:                    return new URL("jar:" + url + "!/"); // NOI18N
1596:                } catch (MalformedURLException e) {
1597:                    throw new AssertionError(e);
1598:                }
1599:            }
1600:
1601:            /**
1602:             * Returns a FileObject representing an archive file containing the
1603:             * FileObject given by the parameter.
1604:             * <strong>Remember</strong> that any path within the archive is discarded
1605:             * so you may need to check for non-root entries.
1606:             * @param fo a file in a JAR filesystem
1607:             * @return the file corresponding to the archive itself,
1608:             *         or null if <code>fo</code> is not an archive entry
1609:             * @since 4.48
1610:             */
1611:            public static FileObject getArchiveFile(FileObject fo) {
1612:                try {
1613:                    FileSystem fs = fo.getFileSystem();
1614:
1615:                    if (fs instanceof  JarFileSystem) {
1616:                        File jarFile = ((JarFileSystem) fs).getJarFile();
1617:
1618:                        return toFileObject(jarFile);
1619:                    }
1620:                } catch (FileStateInvalidException e) {
1621:                    Exceptions.printStackTrace(e);
1622:                }
1623:
1624:                return null;
1625:            }
1626:
1627:            /**
1628:             * Returns the URL of the archive file containing the file
1629:             * referred to by a <code>jar</code>-protocol URL.
1630:             * <strong>Remember</strong> that any path within the archive is discarded
1631:             * so you may need to check for non-root entries.
1632:             * @param url a URL
1633:             * @return the embedded archive URL, or null if the URL is not a
1634:             *         <code>jar</code>-protocol URL containing <code>!/</code>
1635:             * @since 4.48
1636:             */
1637:            public static URL getArchiveFile(URL url) {
1638:                String protocol = url.getProtocol();
1639:
1640:                if ("jar".equals(protocol)) { //NOI18N
1641:
1642:                    String path = url.getPath();
1643:                    int index = path.indexOf("!/"); //NOI18N
1644:
1645:                    if (index >= 0) {
1646:                        try {
1647:                            return new URL(path.substring(0, index));
1648:                        } catch (MalformedURLException mue) {
1649:                            Exceptions.printStackTrace(mue);
1650:                        }
1651:                    }
1652:                }
1653:
1654:                return null;
1655:            }
1656:
1657:            /**
1658:             * Tests if a file represents a JAR or ZIP archive.
1659:             * @param fo the file to be tested
1660:             * @return true if the file looks like a ZIP-format archive
1661:             * @since 4.48
1662:             */
1663:            public static boolean isArchiveFile(FileObject fo) {
1664:                if (fo == null) {
1665:                    throw new IllegalArgumentException(
1666:                            "Cannot pass null to FileUtil.isArchiveFile"); // NOI18N
1667:                }
1668:
1669:                if (!fo.isValid()) {
1670:                    return false;
1671:                }
1672:                // XXX Special handling of virtual file objects: try to determine it using its name, but don't cache the
1673:                // result; when the file is checked out the more correct method can be used
1674:                if (fo.isVirtual()) {
1675:                    String path = fo.getPath();
1676:                    int index = path.lastIndexOf('.');
1677:
1678:                    return (index != -1) && (index > path.lastIndexOf('/') + 1);
1679:                }
1680:
1681:                if (fo.isFolder()) {
1682:                    return false;
1683:                }
1684:
1685:                // First check the cache.
1686:                Boolean b = archiveFileCache.get(fo);
1687:
1688:                if (b == null) {
1689:                    // Need to check it.
1690:                    try {
1691:                        InputStream in = fo.getInputStream();
1692:
1693:                        try {
1694:                            byte[] buffer = new byte[4];
1695:                            int len = in.read(buffer, 0, 4);
1696:
1697:                            if (len == 4) {
1698:                                // Got a header, see if it is a ZIP file.
1699:                                b = Boolean.valueOf(Arrays.equals(ZIP_HEADER_1,
1700:                                        buffer)
1701:                                        || Arrays.equals(ZIP_HEADER_2, buffer));
1702:                            } else {
1703:                                //If the length is less than 4, it can be either
1704:                                //broken (empty) archive file or other empty file.
1705:                                //Return false and don't cache it, when the archive
1706:                                //file will be written and closed its length will change
1707:                                return false;
1708:                            }
1709:                        } finally {
1710:                            in.close();
1711:                        }
1712:                    } catch (IOException ioe) {
1713:                        Logger.getLogger(FileUtil.class.getName()).log(
1714:                                Level.INFO, null, ioe);
1715:                    }
1716:
1717:                    if (b == null) {
1718:                        String path = fo.getPath();
1719:                        int index = path.lastIndexOf('.');
1720:                        b = ((index != -1) && (index > path.lastIndexOf('/') + 1)) ? Boolean.TRUE
1721:                                : Boolean.FALSE;
1722:                    }
1723:
1724:                    archiveFileCache.put(fo, b);
1725:                }
1726:
1727:                return b.booleanValue();
1728:            }
1729:
1730:            /**
1731:             * Tests if a URL represents a JAR or ZIP archive.
1732:             * If there is no such file object, the test is done by heuristic: any URL with an extension is
1733:             * treated as an archive.
1734:             * @param url a URL to a file
1735:             * @return true if the URL seems to represent a ZIP-format archive
1736:             * @since 4.48
1737:             */
1738:            public static boolean isArchiveFile(URL url) {
1739:                if (url == null) {
1740:                    throw new NullPointerException(
1741:                            "Cannot pass null URL to FileUtil.isArchiveFile"); // NOI18N
1742:                }
1743:
1744:                if ("jar".equals(url.getProtocol())) { //NOI18N
1745:
1746:                    //Already inside archive, return false
1747:                    return false;
1748:                }
1749:
1750:                FileObject fo = URLMapper.findFileObject(url);
1751:
1752:                if ((fo != null) && !fo.isVirtual()) {
1753:                    return isArchiveFile(fo);
1754:                } else {
1755:                    String urlPath = url.getPath();
1756:                    int index = urlPath.lastIndexOf('.');
1757:
1758:                    return (index != -1)
1759:                            && (index > urlPath.lastIndexOf('/') + 1);
1760:                }
1761:            }
1762:
1763:            /**
1764:             * Make sure that a JFileChooser does not traverse symlinks on Unix.
1765:             * @param chooser a file chooser
1766:             * @param currentDirectory if not null, a file to set as the current directory
1767:             *                         using {@link JFileChooser#setCurrentDirectory} without canonicalizing
1768:             * @see <a href="http://www.netbeans.org/issues/show_bug.cgi?id=46459">Issue #46459</a>
1769:             * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4906607">JRE bug #4906607</a>
1770:             * @since org.openide/1 4.42
1771:             */
1772:            public static void preventFileChooserSymlinkTraversal(
1773:                    JFileChooser chooser, File currentDirectory) {
1774:                if (!(Utilities.isWindows() || (Utilities.getOperatingSystem() == Utilities.OS_OS2))
1775:                        && System.getProperty("java.specification.version")
1776:                                .startsWith("1.5")) { // NOI18N
1777:                    chooser
1778:                            .setCurrentDirectory(wrapFileNoCanonicalize(currentDirectory));
1779:                    chooser
1780:                            .setFileSystemView(new NonCanonicalizingFileSystemView());
1781:                } else {
1782:                    chooser.setCurrentDirectory(currentDirectory);
1783:                }
1784:            }
1785:
1786:            /**
1787:             * Sorts some sibling file objects.
1788:             * <p>Normally this is done by looking for numeric file attributes named <code>position</code>
1789:             * on the children; children with a lower position number are placed first.
1790:             * Now-deprecated relative ordering attributes of the form <code>earlier/later</code> may
1791:             * also be used; if the above attribute has a boolean value of <code>true</code>,
1792:             * then the file named <code>earlier</code> will be sorted somewhere (not necessarily directly)
1793:             * before the file named <code>later</code>. Numeric and relative attributes may also be mixed.</p>
1794:             * <p>The sort is <em>stable</em> at least to the extent that if there is no ordering information
1795:             * whatsoever, the returned list will be in the same order as the incoming collection.</p>
1796:             * @param children zero or more files (or folders); must all have the same {@link FileObject#getParent}
1797:             * @param logWarnings true to log warnings about relative ordering attributes or other semantic problems, false to keep quiet
1798:             * @return a sorted list of the same children
1799:             * @throws IllegalArgumentException in case there are duplicates, or nulls, or the files do not have a common parent
1800:             * @since org.openide.filesystems 7.2
1801:             * @see #setOrder
1802:             * @see <a href="http://wiki.netbeans.org/wiki/view/FolderOrdering103187">Specification</a>
1803:             */
1804:            public static List<FileObject> getOrder(
1805:                    Collection<FileObject> children, boolean logWarnings)
1806:                    throws IllegalArgumentException {
1807:                return Ordering.getOrder(children, logWarnings);
1808:            }
1809:
1810:            /**
1811:             * Imposes an order on some sibling file objects.
1812:             * After this call, if no other changes have intervened,
1813:             * {@link #getOrder} on these files should return a list in the same order.
1814:             * Beyond the fact that this call may manipulate the <code>position</code> attributes
1815:             * of files in the folder, and may delete deprecated relative ordering attributes on the folder,
1816:             * the exact means of setting the order is unspecified.
1817:             * @param children a list of zero or more files (or folders); must all have the same {@link FileObject#getParent}
1818:             * @throws IllegalArgumentException in case there are duplicates, or nulls, or the files do not have a common parent
1819:             * @throws IOException if new file attributes to order the children cannot be written out
1820:             * @since org.openide.filesystems 7.2
1821:             */
1822:            public static void setOrder(List<FileObject> children)
1823:                    throws IllegalArgumentException, IOException {
1824:                Ordering.setOrder(children);
1825:            }
1826:
1827:            /**
1828:             * Checks whether a change in a given file attribute would affect the result of {@link #getOrder}.
1829:             * @param event an attribute change event
1830:             * @return true if the attribute in question might affect the order of some folder
1831:             * @since org.openide.filesystems 7.2
1832:             */
1833:            public static boolean affectsOrder(FileAttributeEvent event) {
1834:                return Ordering.affectsOrder(event);
1835:            }
1836:
1837:            static boolean assertDeprecatedMethod() {
1838:                Thread.dumpStack();
1839:
1840:                return true;
1841:            }
1842:
1843:            private static File wrapFileNoCanonicalize(File f) {
1844:                if (f instanceof  NonCanonicalizingFile) {
1845:                    return f;
1846:                } else if (f != null) {
1847:                    return new NonCanonicalizingFile(f);
1848:                } else {
1849:                    return null;
1850:                }
1851:            }
1852:
1853:            private static File[] wrapFilesNoCanonicalize(File[] fs) {
1854:                if (fs != null) {
1855:                    for (int i = 0; i < fs.length; i++) {
1856:                        fs[i] = wrapFileNoCanonicalize(fs[i]);
1857:                    }
1858:                }
1859:
1860:                return fs;
1861:            }
1862:
1863:            private static final class NonCanonicalizingFile extends File {
1864:                public NonCanonicalizingFile(File orig) {
1865:                    this (orig.getPath());
1866:                }
1867:
1868:                private NonCanonicalizingFile(String path) {
1869:                    super (path);
1870:                }
1871:
1872:                private NonCanonicalizingFile(URI uri) {
1873:                    super (uri);
1874:                }
1875:
1876:                public File getCanonicalFile() throws IOException {
1877:                    return wrapFileNoCanonicalize(normalizeFile(super 
1878:                            .getAbsoluteFile()));
1879:                }
1880:
1881:                public String getCanonicalPath() throws IOException {
1882:                    return normalizeFile(super .getAbsoluteFile())
1883:                            .getAbsolutePath();
1884:                }
1885:
1886:                public File getParentFile() {
1887:                    return wrapFileNoCanonicalize(super .getParentFile());
1888:                }
1889:
1890:                public File getAbsoluteFile() {
1891:                    return wrapFileNoCanonicalize(super .getAbsoluteFile());
1892:                }
1893:
1894:                public File[] listFiles() {
1895:                    return wrapFilesNoCanonicalize(super .listFiles());
1896:                }
1897:
1898:                public File[] listFiles(FileFilter filter) {
1899:                    return wrapFilesNoCanonicalize(super .listFiles(filter));
1900:                }
1901:
1902:                public File[] listFiles(FilenameFilter filter) {
1903:                    return wrapFilesNoCanonicalize(super .listFiles(filter));
1904:                }
1905:            }
1906:
1907:            private static final class NonCanonicalizingFileSystemView extends
1908:                    FileSystemView {
1909:                private final FileSystemView delegate = FileSystemView
1910:                        .getFileSystemView();
1911:
1912:                public NonCanonicalizingFileSystemView() {
1913:                }
1914:
1915:                public boolean isFloppyDrive(File dir) {
1916:                    return delegate.isFloppyDrive(dir);
1917:                }
1918:
1919:                public boolean isComputerNode(File dir) {
1920:                    return delegate.isComputerNode(dir);
1921:                }
1922:
1923:                public File createNewFolder(File containingDir)
1924:                        throws IOException {
1925:                    return wrapFileNoCanonicalize(delegate
1926:                            .createNewFolder(containingDir));
1927:                }
1928:
1929:                public boolean isDrive(File dir) {
1930:                    return delegate.isDrive(dir);
1931:                }
1932:
1933:                public boolean isFileSystemRoot(File dir) {
1934:                    return delegate.isFileSystemRoot(dir);
1935:                }
1936:
1937:                public File getHomeDirectory() {
1938:                    return wrapFileNoCanonicalize(delegate.getHomeDirectory());
1939:                }
1940:
1941:                public File createFileObject(File dir, String filename) {
1942:                    return wrapFileNoCanonicalize(delegate.createFileObject(
1943:                            dir, filename));
1944:                }
1945:
1946:                public Boolean isTraversable(File f) {
1947:                    return delegate.isTraversable(f);
1948:                }
1949:
1950:                public boolean isFileSystem(File f) {
1951:                    return delegate.isFileSystem(f);
1952:                }
1953:
1954:                /*
1955:                protected File createFileSystemRoot(File f) {
1956:                    return translate(delegate.createFileSystemRoot(f));
1957:                }
1958:                 */
1959:                public File getChild(File parent, String fileName) {
1960:                    return wrapFileNoCanonicalize(delegate.getChild(parent,
1961:                            fileName));
1962:                }
1963:
1964:                public File getParentDirectory(File dir) {
1965:                    return wrapFileNoCanonicalize(delegate
1966:                            .getParentDirectory(dir));
1967:                }
1968:
1969:                public Icon getSystemIcon(File f) {
1970:                    return delegate.getSystemIcon(f);
1971:                }
1972:
1973:                public boolean isParent(File folder, File file) {
1974:                    return delegate.isParent(folder, file);
1975:                }
1976:
1977:                public String getSystemTypeDescription(File f) {
1978:                    return delegate.getSystemTypeDescription(f);
1979:                }
1980:
1981:                public File getDefaultDirectory() {
1982:                    return wrapFileNoCanonicalize(delegate
1983:                            .getDefaultDirectory());
1984:                }
1985:
1986:                public String getSystemDisplayName(File f) {
1987:                    return delegate.getSystemDisplayName(f);
1988:                }
1989:
1990:                public File[] getRoots() {
1991:                    return wrapFilesNoCanonicalize(delegate.getRoots());
1992:                }
1993:
1994:                public boolean isHiddenFile(File f) {
1995:                    return delegate.isHiddenFile(f);
1996:                }
1997:
1998:                public File[] getFiles(File dir, boolean useFileHiding) {
1999:                    return wrapFilesNoCanonicalize(delegate.getFiles(dir,
2000:                            useFileHiding));
2001:                }
2002:
2003:                public boolean isRoot(File f) {
2004:                    return delegate.isRoot(f);
2005:                }
2006:
2007:                public File createFileObject(String path) {
2008:                    return wrapFileNoCanonicalize(delegate
2009:                            .createFileObject(path));
2010:                }
2011:            }
2012:
2013:            private static FileSystem getDiskFileSystem() {
2014:                synchronized (FileUtil.class) {
2015:                    return diskFileSystem;
2016:                }
2017:            }
2018:
2019:            private static void setDiskFileSystem(FileSystem fs) {
2020:                Object o = fs.getRoot().getAttribute(
2021:                        "SupportsRefreshForNoPublicAPI");
2022:                if (o instanceof  Boolean && ((Boolean) o).booleanValue()) {
2023:                    synchronized (FileUtil.class) {
2024:                        diskFileSystem = fs;
2025:                    }
2026:                }
2027:            }
2028:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.