This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 239310
Collapse All | Expand All

(-)a/openide.filesystems/src/org/openide/filesystems/FileUtil.java (-80 / +149 lines)
Lines 111-117 Link Here
111
    private static byte[] ZIP_HEADER_1 = {0x50, 0x4b, 0x03, 0x04};
111
    private static byte[] ZIP_HEADER_1 = {0x50, 0x4b, 0x03, 0x04};
112
    /** 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 */
112
    /** 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 */
113
    private static byte[] ZIP_HEADER_2 = {0x50, 0x4b, 0x05, 0x06};
113
    private static byte[] ZIP_HEADER_2 = {0x50, 0x4b, 0x05, 0x06};
114
    
114
115
    /** transient attributes which should not be copied
115
    /** transient attributes which should not be copied
116
    * of type Set<String>
116
    * of type Set<String>
117
    */
117
    */
Lines 144-155 Link Here
144
            return file.getPath() + "(" + file.getClass() + ")"; // NOI18N
144
            return file.getPath() + "(" + file.getClass() + ")"; // NOI18N
145
        }
145
        }
146
    }
146
    }
147
    
147
148
    static boolean assertNormalized(File path) {
148
    static boolean assertNormalized(File path) {
149
        if (path != null) {
149
        if (path != null) {
150
            File np;
150
            File np;
151
            assert path.getClass().getName().startsWith("sun.awt.shell") ||
151
            assert path.getClass().getName().startsWith("sun.awt.shell") ||
152
                path.equals(np = FileUtil.normalizeFileCached(path)) : 
152
                path.equals(np = FileUtil.normalizeFileCached(path)) :
153
                "Need to normalize " + toDebugString(path) + " was " + toDebugString(np);  //NOI18N
153
                "Need to normalize " + toDebugString(path) + " was " + toDebugString(np);  //NOI18N
154
        }
154
        }
155
        return true;
155
        return true;
Lines 171-177 Link Here
171
171
172
    private FileUtil() {
172
    private FileUtil() {
173
    }
173
    }
174
    
174
175
    /**
175
    /**
176
     * Refreshes all necessary filesystems. Not all instances of <code>FileObject</code> are refreshed
176
     * Refreshes all necessary filesystems. Not all instances of <code>FileObject</code> are refreshed
177
     * but just those that represent passed <code>files</code> and their children recursively.
177
     * but just those that represent passed <code>files</code> and their children recursively.
Lines 186-196 Link Here
186
            } catch (IOException ex) {
186
            } catch (IOException ex) {
187
                Exceptions.printStackTrace(ex);
187
                Exceptions.printStackTrace(ex);
188
            }
188
            }
189
        } 
189
        }
190
    }         
190
    }
191
191
192
    /**
192
    /**
193
     * Refreshes all <code>FileObject</code> that represent files <code>File.listRoots()</code> 
193
     * Refreshes all <code>FileObject</code> that represent files <code>File.listRoots()</code>
194
     * and their children recursively.
194
     * and their children recursively.
195
     * @since 7.7
195
     * @since 7.7
196
     */
196
     */
Lines 230-236 Link Here
230
    /**
230
    /**
231
     * Registers <code>listener</code> so that it will receive
231
     * Registers <code>listener</code> so that it will receive
232
     * <code>FileEvent</code>s from <code>FileSystem</code>s providing instances
232
     * <code>FileEvent</code>s from <code>FileSystem</code>s providing instances
233
     * of <code>FileObject</code> convertible to <code>java.io.File</code>. 
233
     * of <code>FileObject</code> convertible to <code>java.io.File</code>.
234
     * @param fcl
234
     * @param fcl
235
     * @see #toFileObject
235
     * @see #toFileObject
236
     * @since 7.7
236
     * @since 7.7
Lines 242-252 Link Here
242
            fs.addFileChangeListener(fcl);
242
            fs.addFileChangeListener(fcl);
243
        }
243
        }
244
    }
244
    }
245
    
245
246
    /**
246
    /**
247
     * Unregisters <code>listener</code> so that it will no longer receive
247
     * Unregisters <code>listener</code> so that it will no longer receive
248
     * <code>FileEvent</code>s from <code>FileSystem</code>s providing instances
248
     * <code>FileEvent</code>s from <code>FileSystem</code>s providing instances
249
     * of <code>FileObject</code> convertible to <code>java.io.File</code>      
249
     * of <code>FileObject</code> convertible to <code>java.io.File</code>
250
     * @param fcl
250
     * @param fcl
251
     * @see #toFileObject
251
     * @see #toFileObject
252
     * @since 7.7
252
     * @since 7.7
Lines 280-286 Link Here
280
     * <li>fileRenamed event is fired when the folder is renamed or a child file/folder is renamed</li>
280
     * <li>fileRenamed event is fired when the folder is renamed or a child file/folder is renamed</li>
281
     * <li>fileAttributeChanged is fired when FileObject's attribute is changed</li>
281
     * <li>fileAttributeChanged is fired when FileObject's attribute is changed</li>
282
     *</ul>
282
     *</ul>
283
     * Can only add a given [listener, path] pair once. However a listener can 
283
     * Can only add a given [listener, path] pair once. However a listener can
284
     * listen to any number of paths. Note that listeners are always held weakly
284
     * listen to any number of paths. Note that listeners are always held weakly
285
     * - if the listener is collected, it is quietly removed.
285
     * - if the listener is collected, it is quietly removed.
286
     *
286
     *
Lines 307-313 Link Here
307
        FileChangeImpl.removeFileChangeListenerImpl(LOG, listener, path);
307
        FileChangeImpl.removeFileChangeListenerImpl(LOG, listener, path);
308
    }
308
    }
309
    /**
309
    /**
310
     * Works like {@link #addRecursiveListener(org.openide.filesystems.FileChangeListener, java.io.File, java.io.FileFilter, java.util.concurrent.Callable) 
310
     * Works like {@link #addRecursiveListener(org.openide.filesystems.FileChangeListener, java.io.File, java.io.FileFilter, java.util.concurrent.Callable)
311
     * addRecursiveListener(listener, path, null, null)}.
311
     * addRecursiveListener(listener, path, null, null)}.
312
     *
312
     *
313
     * @param listener FileChangeListener to listen to changes in path
313
     * @param listener FileChangeListener to listen to changes in path
Lines 319-325 Link Here
319
        addRecursiveListener(listener, path, null, null);
319
        addRecursiveListener(listener, path, null, null);
320
    }
320
    }
321
321
322
    /** Works like {@link #addRecursiveListener(org.openide.filesystems.FileChangeListener, java.io.File, java.io.FileFilter, java.util.concurrent.Callable) 
322
    /** Works like {@link #addRecursiveListener(org.openide.filesystems.FileChangeListener, java.io.File, java.io.FileFilter, java.util.concurrent.Callable)
323
     * addRecursiveListener(listener, path, null, stop)}.
323
     * addRecursiveListener(listener, path, null, stop)}.
324
     *
324
     *
325
     * @param listener FileChangeListener to listen to changes in path
325
     * @param listener FileChangeListener to listen to changes in path
Lines 335-341 Link Here
335
        addRecursiveListener(listener, path, null, stop);
335
        addRecursiveListener(listener, path, null, stop);
336
    }
336
    }
337
337
338
    /** 
338
    /**
339
     * Adds a listener to changes under given path. It permits you to listen to a file
339
     * Adds a listener to changes under given path. It permits you to listen to a file
340
     * which does not yet exist, or continue listening to it after it is deleted and recreated, etc.
340
     * which does not yet exist, or continue listening to it after it is deleted and recreated, etc.
341
     * <br/>
341
     * <br/>
Lines 368-380 Link Here
368
     * next recursive items is interrupted. The listener may or may not get
368
     * next recursive items is interrupted. The listener may or may not get
369
     * some events from already registered folders.
369
     * some events from already registered folders.
370
     * </div>
370
     * </div>
371
     * 
371
     *
372
     * Those who provide {@link FileFilter recurseInto} callback can prevent
372
     * Those who provide {@link FileFilter recurseInto} callback can prevent
373
     * the system to enter, and register operating system level listeners 
373
     * the system to enter, and register operating system level listeners
374
     * to certain subtrees under the provided <code>path</code>. This does
374
     * to certain subtrees under the provided <code>path</code>. This does
375
     * not prevent delivery of changes, if they are made via the filesystem API.
375
     * not prevent delivery of changes, if they are made via the filesystem API.
376
     * External changes however will not be detected.
376
     * External changes however will not be detected.
377
     * 
377
     *
378
     * @param listener FileChangeListener to listen to changes in path
378
     * @param listener FileChangeListener to listen to changes in path
379
     * @param path File path to listen to (even not existing)
379
     * @param path File path to listen to (even not existing)
380
     * @param stop an interface to interrupt the process of registering
380
     * @param stop an interface to interrupt the process of registering
Lines 404-413 Link Here
404
    }
404
    }
405
405
406
    /**
406
    /**
407
     * Executes atomic action. For more info see {@link FileSystem#runAtomicAction}. 
407
     * Executes atomic action. For more info see {@link FileSystem#runAtomicAction}.
408
     * <p>
408
     * <p>
409
     * All events about filesystem changes (related to events on all affected instances of <code>FileSystem</code>)
409
     * All events about filesystem changes (related to events on all affected instances of <code>FileSystem</code>)
410
     * are postponed after the whole <code>atomicCode</code> 
410
     * are postponed after the whole <code>atomicCode</code>
411
     * is executed.
411
     * is executed.
412
     * </p>
412
     * </p>
413
     * @param atomicCode code that is supposed to be run as atomic action. See {@link FileSystem#runAtomicAction}
413
     * @param atomicCode code that is supposed to be run as atomic action. See {@link FileSystem#runAtomicAction}
Lines 420-429 Link Here
420
    }
420
    }
421
421
422
    /**
422
    /**
423
     * Executes atomic action. For more info see {@link FileSystem#runAtomicAction}. 
423
     * Executes atomic action. For more info see {@link FileSystem#runAtomicAction}.
424
     * <p>
424
     * <p>
425
     * All events about filesystem changes (related to events on all affected instances of <code>FileSystem</code>)
425
     * All events about filesystem changes (related to events on all affected instances of <code>FileSystem</code>)
426
     * are postponed after the whole <code>atomicCode</code> 
426
     * are postponed after the whole <code>atomicCode</code>
427
     * is executed.
427
     * is executed.
428
     * </p>
428
     * </p>
429
     * @param atomicCode code that is supposed to be run as atomic action. See {@link FileSystem#runAtomicAction}
429
     * @param atomicCode code that is supposed to be run as atomic action. See {@link FileSystem#runAtomicAction}
Lines 440-449 Link Here
440
        } catch (IOException ex) {
440
        } catch (IOException ex) {
441
            Exceptions.printStackTrace(ex);
441
            Exceptions.printStackTrace(ex);
442
        }
442
        }
443
    }        
443
    }
444
    /**
444
    /**
445
     * Returns FileObject for a folder.
445
     * Returns FileObject for a folder.
446
     * If such a folder does not exist then it is created, including any necessary but nonexistent parent 
446
     * If such a folder does not exist then it is created, including any necessary but nonexistent parent
447
     * folders. Note that if this operation fails it may have succeeded in creating some of the necessary
447
     * folders. Note that if this operation fails it may have succeeded in creating some of the necessary
448
     * parent folders.
448
     * parent folders.
449
     * @param folder folder to be created
449
     * @param folder folder to be created
Lines 458-483 Link Here
458
        }
458
        }
459
        if (existingFolder == null) {
459
        if (existingFolder == null) {
460
            throw new IOException(folder.getAbsolutePath());
460
            throw new IOException(folder.getAbsolutePath());
461
        }        
461
        }
462
                      
462
463
        FileObject retval = null;
463
        FileObject retval = null;
464
        FileObject folderFo = FileUtil.toFileObject(existingFolder);        
464
        FileObject folderFo = FileUtil.toFileObject(existingFolder);
465
        assert folderFo != null : existingFolder.getAbsolutePath();
465
        assert folderFo != null : existingFolder.getAbsolutePath();
466
        final String relativePath = getRelativePath(existingFolder, folder);
466
        final String relativePath = getRelativePath(existingFolder, folder);
467
        try {
467
        try {
468
            retval = FileUtil.createFolder(folderFo,relativePath);        
468
            retval = FileUtil.createFolder(folderFo,relativePath);
469
        } catch (IOException ex) {
469
        } catch (IOException ex) {
470
            //thus retval = null;
470
            //thus retval = null;
471
        }
471
        }
472
        //if refresh needed because of external changes        
472
        //if refresh needed because of external changes
473
        if (retval == null || !retval.isValid()) {
473
        if (retval == null || !retval.isValid()) {
474
            folderFo.getFileSystem().refresh(false);
474
            folderFo.getFileSystem().refresh(false);
475
            retval = FileUtil.createFolder(folderFo,relativePath);
475
            retval = FileUtil.createFolder(folderFo,relativePath);
476
        }        
476
        }
477
        assert retval != null;        
477
        assert retval != null;
478
        return retval;        
478
        return retval;
479
    } 
479
    }
480
    
480
481
    /**Returns FileObject for a data file.
481
    /**Returns FileObject for a data file.
482
     * If such a data file does not exist then it is created, including any necessary but nonexistent parent
482
     * If such a data file does not exist then it is created, including any necessary but nonexistent parent
483
     * folders. Note that if this operation fails it may have succeeded in creating some of the necessary
483
     * folders. Note that if this operation fails it may have succeeded in creating some of the necessary
Lines 487-519 Link Here
487
     * @throws java.io.IOException if the creation fails
487
     * @throws java.io.IOException if the creation fails
488
     * @since 7.0
488
     * @since 7.0
489
     */
489
     */
490
    public static FileObject createData (final File data) throws IOException {        
490
    public static FileObject createData (final File data) throws IOException {
491
        File folder = data;
491
        File folder = data;
492
        while(folder != null && !folder.isDirectory()) {
492
        while(folder != null && !folder.isDirectory()) {
493
            folder = folder.getParentFile();
493
            folder = folder.getParentFile();
494
        }
494
        }
495
        if (folder == null) {
495
        if (folder == null) {
496
            throw new IOException(data.getAbsolutePath());
496
            throw new IOException(data.getAbsolutePath());
497
        }        
497
        }
498
                      
498
499
        FileObject retval = null;
499
        FileObject retval = null;
500
        FileObject folderFo = FileUtil.toFileObject(folder);
500
        FileObject folderFo = FileUtil.toFileObject(folder);
501
        assert folderFo != null : folder.getAbsolutePath();
501
        assert folderFo != null : folder.getAbsolutePath();
502
        final String relativePath = getRelativePath(folder, data);
502
        final String relativePath = getRelativePath(folder, data);
503
        try {
503
        try {
504
            retval = FileUtil.createData(folderFo,relativePath);        
504
            retval = FileUtil.createData(folderFo,relativePath);
505
        } catch (IOException ex) {
505
        } catch (IOException ex) {
506
            //thus retval = null;
506
            //thus retval = null;
507
        }
507
        }
508
        //if refresh needed because of external changes        
508
        //if refresh needed because of external changes
509
        if (retval == null || !retval.isValid()) {
509
        if (retval == null || !retval.isValid()) {
510
            folderFo.getFileSystem().refresh(false);
510
            folderFo.getFileSystem().refresh(false);
511
            retval = FileUtil.createData(folderFo,relativePath);
511
            retval = FileUtil.createData(folderFo,relativePath);
512
        }        
512
        }
513
        assert retval != null;        
513
        assert retval != null;
514
        return retval;
514
        return retval;
515
    } 
515
    }
516
        
516
517
    private static String getRelativePath(final File dir, final File file) {
517
    private static String getRelativePath(final File dir, final File file) {
518
        Stack<String> stack = new Stack<String>();
518
        Stack<String> stack = new Stack<String>();
519
        File tempFile = file;
519
        File tempFile = file;
Lines 528-537 Link Here
528
            if (!stack.isEmpty()) {
528
            if (!stack.isEmpty()) {
529
                retval.append('/');//NOI18N
529
                retval.append('/');//NOI18N
530
            }
530
            }
531
        }                        
531
        }
532
        return retval.toString();
532
        return retval.toString();
533
    }
533
    }
534
    
534
535
    /** Copies stream of files.
535
    /** Copies stream of files.
536
    * <P>
536
    * <P>
537
    * Please be aware, that this method doesn't close any of passed streams.
537
    * Please be aware, that this method doesn't close any of passed streams.
Lines 674-683 Link Here
674
        }
674
        }
675
    }
675
    }
676
676
677
    /** Returns a folder on given filesystem if such a folder exists. 
677
    /** Returns a folder on given filesystem if such a folder exists.
678
     * If not then a folder is created, including any necessary but nonexistent parent 
678
     * If not then a folder is created, including any necessary but nonexistent parent
679
     * folders. Note that if this operation fails it may have succeeded in creating some of the necessary
679
     * folders. Note that if this operation fails it may have succeeded in creating some of the necessary
680
     * parent folders. 
680
     * parent folders.
681
     * The name of the new folder can be
681
     * The name of the new folder can be
682
     * specified as a multi-component pathname whose components are separated
682
     * specified as a multi-component pathname whose components are separated
683
     * by File.separatorChar or &quot;/&quot; (forward slash).
683
     * by File.separatorChar or &quot;/&quot; (forward slash).
Lines 732-739 Link Here
732
        return folder;
732
        return folder;
733
    }
733
    }
734
734
735
    /** Returns a data file on given filesystem if such a data file exists. 
735
    /** Returns a data file on given filesystem if such a data file exists.
736
    * If not then a data file is created, including any necessary but nonexistent parent 
736
    * If not then a data file is created, including any necessary but nonexistent parent
737
    * folders. Note that if this operation fails it may have succeeded in creating some of the necessary
737
    * folders. Note that if this operation fails it may have succeeded in creating some of the necessary
738
    * parent folders. The name of
738
    * parent folders. The name of
739
    * data file can be composed as resource name (e. g. org/netbeans/myfolder/mydata ).
739
    * data file can be composed as resource name (e. g. org/netbeans/myfolder/mydata ).
Lines 814-820 Link Here
814
     * @since 1.29
814
     * @since 1.29
815
     */
815
     */
816
    public static File toFile(FileObject fo) {
816
    public static File toFile(FileObject fo) {
817
        File retVal = (File) fo.getAttribute("java.io.File"); // NOI18N;        
817
        File retVal = (File) fo.getAttribute("java.io.File"); // NOI18N;
818
818
819
        if (retVal == null) {
819
        if (retVal == null) {
820
            URL fileURL = URLMapper.findURL(fo, URLMapper.INTERNAL);
820
            URL fileURL = URLMapper.findURL(fo, URLMapper.INTERNAL);
Lines 845-851 Link Here
845
     * <pre>
845
     * <pre>
846
     * OpenIDE-Module-Needs: org.openide.filesystems.FileUtil.toFileObject
846
     * OpenIDE-Module-Needs: org.openide.filesystems.FileUtil.toFileObject
847
     * </pre>
847
     * </pre>
848
     * 
848
     *
849
     * @param file a disk file (may or may not exist). This file
849
     * @param file a disk file (may or may not exist). This file
850
     * must be {@linkplain #normalizeFile normalized}.
850
     * must be {@linkplain #normalizeFile normalized}.
851
     * @return a corresponding file object, or null if the file does not exist
851
     * @return a corresponding file object, or null if the file does not exist
Lines 863-869 Link Here
863
        if (asserts) {
863
        if (asserts) {
864
            File normFile = normalizeFile(file);
864
            File normFile = normalizeFile(file);
865
            if (!file.equals(normFile)) {
865
            if (!file.equals(normFile)) {
866
                final String msg = "Parameter file was not " + // NOI18N   
866
                final String msg = "Parameter file was not " + // NOI18N
867
                    "normalized. Was " + toDebugString(file) + " instead of " + toDebugString(normFile); // NOI18N
867
                    "normalized. Was " + toDebugString(file) + " instead of " + toDebugString(normFile); // NOI18N
868
                LOG.log(Level.WARNING, msg);
868
                LOG.log(Level.WARNING, msg);
869
                LOG.log(Level.INFO, msg, new IllegalArgumentException(msg));
869
                LOG.log(Level.INFO, msg, new IllegalArgumentException(msg));
Lines 893-899 Link Here
893
        }
893
        }
894
        return retVal;
894
        return retVal;
895
    }
895
    }
896
        
896
897
    /** Finds appropriate FileObjects to java.io.File if possible.
897
    /** Finds appropriate FileObjects to java.io.File if possible.
898
     * If not possible then empty array is returned. More FileObjects may
898
     * If not possible then empty array is returned. More FileObjects may
899
     * correspond to one java.io.File that`s why array is returned.
899
     * correspond to one java.io.File that`s why array is returned.
Lines 951-958 Link Here
951
            AtomicBoolean isRawValue = new AtomicBoolean();
951
            AtomicBoolean isRawValue = new AtomicBoolean();
952
            Object value = XMLMapAttr.getRawAttribute(source, key, isRawValue);
952
            Object value = XMLMapAttr.getRawAttribute(source, key, isRawValue);
953
953
954
            // #132801 and #16761 - don't set attributes where value is 
954
            // #132801 and #16761 - don't set attributes where value is
955
            // instance of VoidValue because these attributes were previously written 
955
            // instance of VoidValue because these attributes were previously written
956
            // by mistake in code. So it should happen only if you import some
956
            // by mistake in code. So it should happen only if you import some
957
            // settings from old version.
957
            // settings from old version.
958
            if (value != null && !(value instanceof MultiFileObject.VoidValue)) {
958
            if (value != null && !(value instanceof MultiFileObject.VoidValue)) {
Lines 1310-1316 Link Here
1310
     * {@link MIMEResolver#getMIMETypes} contain one or more of the requested
1310
     * {@link MIMEResolver#getMIMETypes} contain one or more of the requested
1311
     * MIME types will be asked if they recognize the file. It is possible for
1311
     * MIME types will be asked if they recognize the file. It is possible for
1312
     * the resulting MIME type to not be a member of this list.
1312
     * the resulting MIME type to not be a member of this list.
1313
     * @return the MIME type for the FileObject, or <code>null</code> if 
1313
     * @return the MIME type for the FileObject, or <code>null</code> if
1314
     * the FileObject is unrecognized. It may return {@code content/unknown} instead of {@code null}.
1314
     * the FileObject is unrecognized. It may return {@code content/unknown} instead of {@code null}.
1315
     * It is possible for the resulting MIME type to not be a member of given list.
1315
     * It is possible for the resulting MIME type to not be a member of given list.
1316
     * @since 7.13
1316
     * @since 7.13
Lines 1319-1325 Link Here
1319
        Parameters.notNull("withinMIMETypes", withinMIMETypes);  //NOI18N
1319
        Parameters.notNull("withinMIMETypes", withinMIMETypes);  //NOI18N
1320
        return MIMESupport.findMIMEType(fo, withinMIMETypes);
1320
        return MIMESupport.findMIMEType(fo, withinMIMETypes);
1321
    }
1321
    }
1322
    
1322
1323
    /** Registers specified extension to be recognized as specified MIME type.
1323
    /** Registers specified extension to be recognized as specified MIME type.
1324
     * If MIME type parameter is null, it cancels previous registration.
1324
     * If MIME type parameter is null, it cancels previous registration.
1325
     * Note that you may register a case-sensitive extension if that is
1325
     * Note that you may register a case-sensitive extension if that is
Lines 1541-1547 Link Here
1541
        }
1541
        }
1542
        return normalized;
1542
        return normalized;
1543
    }
1543
    }
1544
    
1544
1545
    /**
1545
    /**
1546
     * Normalize a file path to a clean form.
1546
     * Normalize a file path to a clean form.
1547
     * This method may for example make sure that the returned file uses
1547
     * This method may for example make sure that the returned file uses
Lines 1563-1576 Link Here
1563
        assert assertNormalized(ret);
1563
        assert assertNormalized(ret);
1564
        return ret;
1564
        return ret;
1565
    }
1565
    }
1566
    
1566
1567
    private static File normalizeFileCached(final File file) {
1567
    private static File normalizeFileCached(final File file) {
1568
        Map<String, String> normalizedPaths = getNormalizedFilesMap();
1568
        Map<String, String> normalizedPaths = getNormalizedFilesMap();
1569
        String unnormalized = file.getPath();
1569
        String unnormalized = file.getPath();
1570
        String normalized = normalizedPaths.get(unnormalized);
1570
        String normalized = normalizedPaths.get(unnormalized);
1571
        if (
1571
        if (
1572
            normalized != null && 
1572
            normalized != null &&
1573
                normalized.equalsIgnoreCase(unnormalized) && 
1573
                normalized.equalsIgnoreCase(unnormalized) &&
1574
                !normalized.equals(unnormalized)
1574
                !normalized.equals(unnormalized)
1575
        ) {
1575
        ) {
1576
            normalized = null;
1576
            normalized = null;
Lines 1628-1634 Link Here
1628
        File retVal = file;
1628
        File retVal = file;
1629
1629
1630
        try {
1630
        try {
1631
            // URI.normalize removes ../ and ./ sequences nicely.            
1631
            // URI.normalize removes ../ and ./ sequences nicely.
1632
            File absoluteFile = Utilities.toFile(Utilities.toURI(file).normalize());
1632
            File absoluteFile = Utilities.toFile(Utilities.toURI(file).normalize());
1633
            File canonicalFile = file.getCanonicalFile();
1633
            File canonicalFile = file.getCanonicalFile();
1634
            String absolutePath = absoluteFile.getAbsolutePath();
1634
            String absolutePath = absoluteFile.getAbsolutePath();
Lines 1661-1667 Link Here
1661
        File retVal = File.listRoots()[0];
1661
        File retVal = File.listRoots()[0];
1662
        File pureCanonicalFile = retVal;
1662
        File pureCanonicalFile = retVal;
1663
1663
1664
        final String pattern = File.separator + ".." + File.separator; //NOI18N                
1664
        final String pattern = File.separator + ".." + File.separator; //NOI18N
1665
        final String fileName;
1665
        final String fileName;
1666
1666
1667
        { // strips insufficient non-<tt>".."</tt> segments preceding them
1667
        { // strips insufficient non-<tt>".."</tt> segments preceding them
Lines 1697-1720 Link Here
1697
        return retVal;
1697
        return retVal;
1698
    }
1698
    }
1699
1699
1700
    private static File normalizeFileOnWindows(final File file) {
1700
    /**
1701
     * Fast normalization of local file paths located on a drive without using IO
1702
     *
1703
     * Notes: Declared public to allow unit testing of this method
1704
     *
1705
     * @param filePath
1706
     * @throws Exception
1707
     * @return String  Normalized file path
1708
     */
1709
    public static String getNormalizedPathOnWindows(String filePath)
1710
    throws Exception {
1711
        /* Check for wildcards - Canonicalization is not globbing */
1712
        if (filePath.contains("?") || filePath.contains("*"))
1713
            throw new Exception();
1714
1715
        String[] pathParts = filePath.split("[\\\\/]");
1716
        ArrayList<String> normalizedPathParts;
1717
        normalizedPathParts = new ArrayList(pathParts.length);
1718
1719
        for (String subPath : pathParts) {
1720
            /* Skip the dot and empty(sequence of slashes) names */
1721
            if (subPath.equals(".") || subPath.length() == 0)
1722
                continue;
1723
1724
            /* Do not remove drive letter and : */
1725
            if (subPath.equals("..")) {
1726
                if (normalizedPathParts.size() > 1)
1727
                    normalizedPathParts.remove(normalizedPathParts.size() - 1);
1728
                continue;
1729
            }
1730
1731
            /* Path chunk should not end with a dot(Except special "." and ".." notations which are specially checked above) */
1732
            if (subPath.endsWith("."))
1733
                throw new Exception();
1734
1735
            normalizedPathParts.add(subPath);
1736
        }
1737
1738
        String fileName = normalizedPathParts.get(normalizedPathParts.size() - 1);
1739
        normalizedPathParts.remove(normalizedPathParts.size() - 1);
1740
1741
        String normalizedPath = "";
1742
        for (String pathPart : normalizedPathParts)
1743
            normalizedPath += pathPart + File.separator;
1744
        normalizedPath += fileName;
1745
        /* Process shorts like "C:" correctly -> Shall return "C:\" */
1746
        if (normalizedPath.length() == 2)
1747
            normalizedPath += File.separator;
1748
1749
        char driveLetter = normalizedPath.charAt(0);
1750
        normalizedPath = normalizedPath.replaceFirst(Character.toString(driveLetter), Character.toString(Character.toUpperCase(driveLetter)));
1751
1752
        return normalizedPath;
1753
    }
1754
1755
	private static File normalizeFileOnWindows(final File file) {
1701
        File retVal = null;
1756
        File retVal = null;
1702
        
1757
1703
        if (file.getClass().getName().startsWith("sun.awt.shell")) { // NOI18N
1758
        if (file.getClass().getName().startsWith("sun.awt.shell")) { // NOI18N
1704
            return file;
1759
            return file;
1705
        }
1760
        }
1706
1761
1707
        try {
1762
        String filePath = file.getAbsolutePath();
1708
            retVal = file.getCanonicalFile();
1763
1709
            if (retVal.getName().equals(".")) { // NOI18Ny
1764
        /* Check if path starts with a standard drive letter */
1710
                // try one more time
1765
        if (filePath.length() > 1 && filePath.charAt(1) == ':') {
1711
                retVal = retVal.getCanonicalFile();
1766
            try {
1767
                String normalizedPath = getNormalizedPathOnWindows(filePath);
1768
                retVal = new File(normalizedPath);
1769
            } catch (Exception e) {
1770
                String path = file.getPath();
1771
                LOG.log(Level.FINE, path, e);
1712
            }
1772
            }
1713
        } catch (IOException e) {
1773
        }
1714
            String path = file.getPath();
1774
        else {
1715
            // report only other than UNC path \\ or \\computerName because these cannot be canonicalized
1775
            try {
1716
            if (!path.equals("\\\\") && !("\\\\".equals(file.getParent()))) {  //NOI18N
1776
                retVal = file.getCanonicalFile();
1717
                LOG.log(Level.FINE, path, e);
1777
                if (retVal.getName().equals(".")) { // NOI18Ny
1778
                    // try one more time
1779
                    retVal = retVal.getCanonicalFile();
1780
                }
1781
            } catch (IOException e) {
1782
                String path = file.getPath();
1783
                // report only other than UNC path \\ or \\computerName because these cannot be canonicalized
1784
                if (!path.equals("\\\\") && !("\\\\".equals(file.getParent()))) {  //NOI18N
1785
                    LOG.log(Level.FINE, path, e);
1786
                }
1718
            }
1787
            }
1719
        }
1788
        }
1720
        // #135547 - on Windows Vista map "Documents and Settings\<username>\My Documents" to "Users\<username>\Documents"
1789
        // #135547 - on Windows Vista map "Documents and Settings\<username>\My Documents" to "Users\<username>\Documents"
Lines 1843-1849 Link Here
1843
                    }
1912
                    }
1844
                    return new URL(jarPath);
1913
                    return new URL(jarPath);
1845
1914
1846
                } catch (MalformedURLException mue) {                    
1915
                } catch (MalformedURLException mue) {
1847
                    LOG.log(
1916
                    LOG.log(
1848
                        Level.WARNING,
1917
                        Level.WARNING,
1849
                        "Invalid URL ({0}): {1}, jarPath: {2}", //NOI18N
1918
                        "Invalid URL ({0}): {1}, jarPath: {2}", //NOI18N
Lines 1963-1969 Link Here
1963
        try {
2032
        try {
1964
            boolean wasDir;
2033
            boolean wasDir;
1965
            boolean isDir;
2034
            boolean isDir;
1966
            URL u;            
2035
            URL u;
1967
            do {
2036
            do {
1968
                wasDir = entry.isDirectory();
2037
                wasDir = entry.isDirectory();
1969
                LOG.finest("urlForArchiveOrDir:toURI:entry");   //NOI18N
2038
                LOG.finest("urlForArchiveOrDir:toURI:entry");   //NOI18N
Lines 2091-2097 Link Here
2091
        Parameters.notNull("path", path);  //NOI18N
2160
        Parameters.notNull("path", path);  //NOI18N
2092
        return Repository.getDefault().getDefaultFileSystem().findResource(path);
2161
        return Repository.getDefault().getDefaultFileSystem().findResource(path);
2093
    }
2162
    }
2094
    
2163
2095
    /** Finds a config object under given path. The path contains the extension
2164
    /** Finds a config object under given path. The path contains the extension
2096
     * of a file e.g.:
2165
     * of a file e.g.:
2097
     * <pre>
2166
     * <pre>
Lines 2101-2107 Link Here
2101
     * @param filePath path to .instance or .settings file
2170
     * @param filePath path to .instance or .settings file
2102
     * @param type the requested type for given object
2171
     * @param type the requested type for given object
2103
     * @return either null or instance of requrested type
2172
     * @return either null or instance of requrested type
2104
     * @since 7.49 
2173
     * @since 7.49
2105
     */
2174
     */
2106
    public static <T> T getConfigObject(String path, Class<T> type) {
2175
    public static <T> T getConfigObject(String path, Class<T> type) {
2107
        FileObject fo = getConfigFile(path);
2176
        FileObject fo = getConfigFile(path);
Lines 2307-2313 Link Here
2307
            return wrapFileNoCanonicalize(delegate.createFileObject(path));
2376
            return wrapFileNoCanonicalize(delegate.createFileObject(path));
2308
        }
2377
        }
2309
    }
2378
    }
2310
    
2379
2311
    private static FileSystem getDiskFileSystem() {
2380
    private static FileSystem getDiskFileSystem() {
2312
        synchronized (FileUtil.class) {
2381
        synchronized (FileUtil.class) {
2313
            return diskFileSystem;
2382
            return diskFileSystem;

Return to bug 239310