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 208779
Collapse All | Expand All

(-)a/openide.loaders/src/org/openide/loaders/DataShadow.java (+41 lines)
Lines 393-401 Link Here
393
    /**
393
    /**
394
     * Tries to load the original file from a shadow.
394
     * Tries to load the original file from a shadow.
395
     * Looks for file contents as well as the originalFile/originalFileSystem attributes.
395
     * Looks for file contents as well as the originalFile/originalFileSystem attributes.
396
     * Attempts to discover locations for migrated files in configuration.
397
     * 
396
     * @param fileObject a data shadow
398
     * @param fileObject a data shadow
397
     * @return the original <code>DataObject</code> referenced by the shadow
399
     * @return the original <code>DataObject</code> referenced by the shadow
398
     * @throws IOException error during load or broken link
400
     * @throws IOException error during load or broken link
401
     * 
402
     * @see Utilities#translate
399
     */
403
     */
400
    protected static DataObject deserialize(FileObject fileObject) throws IOException {
404
    protected static DataObject deserialize(FileObject fileObject) throws IOException {
401
        String[] fileAndFileSystem = readOriginalFileAndFileSystem(fileObject);
405
        String[] fileAndFileSystem = readOriginalFileAndFileSystem(fileObject);
Lines 411-428 Link Here
411
        String fsname = fileAndFileSystem[1];
415
        String fsname = fileAndFileSystem[1];
412
        if (u != null && u.isAbsolute()) {
416
        if (u != null && u.isAbsolute()) {
413
            target = URLMapper.findFileObject(u.toURL());
417
            target = URLMapper.findFileObject(u.toURL());
418
            if (target == null) {
419
                FileObject cfgRoot = FileUtil.getConfigRoot();
420
                URI cfgURI = cfgRoot.toURI();
421
                String prefix = cfgURI.toString();
422
                String urlText = u.toString();
423
                // try to recover a broken shadow by translation, but only for 
424
                // configuration
425
                if (urlText.startsWith(prefix)) {
426
                    String rootPathFragment = cfgURI.getRawPath();
427
                    // get the file part with all the URL escaping, escapes e.g. # and = characters.
428
                    String cfgPart = u.getRawPath().substring(rootPathFragment.length());
429
                    String translated = Utilities.translate(cfgPart);
430
                    if (!translated.equals(cfgPart)) {
431
                        try {
432
                            // assume translated value can be added to the prefix, no bad characters allowed
433
                            URI temp = new URI(prefix + translated);
434
                            target = URLMapper.findFileObject(temp.toURL());
435
                        } catch (URISyntaxException ex) {
436
                            LOG.log(Level.WARNING, "Could not form URI from {0}: {1}", new Object[] { translated, ex });
437
                        }
438
                    }
439
                }
440
            }
414
        } else {
441
        } else {
415
            FileSystem fs;
442
            FileSystem fs;
443
            boolean sfs;
416
            if (SFS_NAME.equals(fsname)) {
444
            if (SFS_NAME.equals(fsname)) {
417
                fs = FileUtil.getConfigRoot().getFileSystem();
445
                fs = FileUtil.getConfigRoot().getFileSystem();
446
                sfs = true;
418
            } else {
447
            } else {
419
                // Even if it is specified, we no longer have mounts, so we can no longer find it.
448
                // Even if it is specified, we no longer have mounts, so we can no longer find it.
420
                fs = fileObject.getFileSystem();
449
                fs = fileObject.getFileSystem();
450
                sfs = false;
421
            }
451
            }
422
            target = fs.findResource(path);
452
            target = fs.findResource(path);
423
            if (target == null && fsname == null) {
453
            if (target == null && fsname == null) {
454
                sfs = true;
424
                target = FileUtil.getConfigFile(path);
455
                target = FileUtil.getConfigFile(path);
425
            }
456
            }
457
            
458
            // defect #208779 - if target is not found on SFS, try to translate the path:
459
            if (sfs && target == null) {
460
                // encode the path:
461
                String translated = Utilities.translate(path);
462
                if (!path.equals(translated)) {
463
                    // decode translated path back:
464
                    target = FileUtil.getConfigFile(translated);
465
                }
466
            }
426
        }
467
        }
427
        if (target != null) {
468
        if (target != null) {
428
            return DataObject.find(target);
469
            return DataObject.find(target);
(-)a/openide.loaders/test/unit/src/META-INF/netbeans/translate.names (+2 lines)
Line 0 Link Here
1
origFolder/regularFileName.txt.old=origFolder/regularFileName.txt
2
dead-file-location.old=origFolder3/moved-here.txt
(-)a/openide.loaders/test/unit/src/org/netbeans/modules/openide/loaders/DataShadowTranslateTest.java (+203 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.openide.loaders;
43
44
import java.io.*;
45
import java.net.URI;
46
import java.net.URL;
47
import java.net.URLClassLoader;
48
import org.netbeans.junit.NbTestCase;
49
import org.openide.filesystems.FileObject;
50
import org.openide.filesystems.FileSystem.AtomicAction;
51
import org.openide.filesystems.FileUtil;
52
import org.openide.loaders.DataObject;
53
import org.openide.loaders.DataShadow;
54
import org.openide.util.Lookup;
55
import org.openide.util.test.MockLookup;
56
import org.openide.util.test.TestFileUtils;
57
58
/**
59
 * See defect #208779 - DataShadows should update themselves iff they could not find 
60
 * the target.
61
 * 
62
 * @author sdedic
63
 */
64
public class DataShadowTranslateTest extends NbTestCase {
65
66
    public DataShadowTranslateTest(String name) {
67
        super(name);
68
    }
69
    
70
    /**
71
     * Checks that file with just regular characters in name is translated OK
72
     * @throws Exception 
73
     */
74
    public void testRegularURI() throws Exception {
75
        
76
        FileObject fo = FileUtil.getConfigRoot();
77
        
78
        FileObject origDir = fo.createFolder("origFolder");
79
        FileObject newFile = origDir.createData("regularFileName.txt");
80
        
81
        final FileObject d = fo.createFolder("subfolder");
82
        OutputStream ostm = d.createAndOpen("regularShadowURI.shadow");
83
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(ostm));
84
        
85
        URI uri = newFile.toURI();
86
        String urlString = newFile.toURI().toString();
87
        bw.write(urlString + ".old");
88
        bw.newLine();
89
        bw.newLine();
90
        bw.close();
91
        
92
        FileObject fob = d.getFileObject("regularShadowURI.shadow");
93
        DataObject dd = DataObject.find(fob);
94
        
95
        assertTrue("Shadow must be translated, not broken", dd instanceof DataShadow);
96
        
97
        DataShadow ds = (DataShadow)dd;
98
        assertEquals("Shadow's original must be on the translated location", newFile, ds.getOriginal().getPrimaryFile());
99
    }
100
    
101
102
    /**
103
     * Checks translation on Shadows, which use FS name + path, not URI
104
     * @throws Exception 
105
     */
106
    public void testFSNameAndPath() throws Exception {
107
        FileObject fo = FileUtil.getConfigRoot();
108
        
109
        FileObject origDir = fo.createFolder("origFolder3");
110
        
111
        // create empty real file with special and non-ASCII chars
112
        FileObject newFile = origDir.createData("moved-here.txt");
113
        
114
        // createa a fake file, just to get its URI right:
115
        FileObject fake = fo.createData("dead-file-location.old");
116
        
117
        final FileObject d = fo.createFolder("subfolder3");
118
        OutputStream ostm = d.createAndOpen("regularShadowURI.shadow");
119
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(ostm));
120
        
121
        bw.write(fake.getPath());
122
        bw.newLine();
123
        bw.write(fake.getFileSystem().getSystemName());
124
        bw.newLine();
125
        
126
        fake.delete();
127
        
128
        bw.close();
129
        
130
        FileObject fob = d.getFileObject("regularShadowURI.shadow");
131
        DataObject dd = DataObject.find(fob);
132
        
133
        assertTrue("Shadow must be translated, not broken", dd instanceof DataShadow);
134
        
135
        DataShadow ds = (DataShadow)dd;
136
        assertEquals("Shadow's original must be on the translated location", newFile, ds.getOriginal().getPrimaryFile());
137
    }
138
    
139
    /**
140
     * Checks that DataShadows to regular (non-SFS) files are not translated
141
     * even if a translation is defined for their path
142
     * 
143
     * @throws Exception 
144
     */
145
    public void testNonSFSUriNotAffected() throws Exception {
146
        File wd = getWorkDir();
147
        
148
        clearWorkDir();
149
        
150
        FileObject origDir = FileUtil.toFileObject(wd);
151
        
152
        FileObject dirWithSpace = origDir.createFolder("Space Dir");
153
        FileObject newFile = dirWithSpace.createData("testFile.txt");
154
        
155
156
        File subDir = new File(wd, "translate");
157
        
158
        subDir.mkdirs();
159
        
160
        File metaTranslate = new File(subDir, "META-INF/netbeans");
161
        metaTranslate.mkdirs();
162
        
163
        String workPath = newFile.toURI().getRawPath();
164
        FileWriter wr = new FileWriter(new File(metaTranslate, "translate.names"));
165
        BufferedWriter bw = new BufferedWriter(wr);
166
        
167
        bw.write(workPath.substring(1) + "/testFile.txt=" + workPath.substring(1) + "/moved/testFile.txt");
168
        bw.close();
169
        
170
        
171
        FileObject fo = FileUtil.toFileObject(wd);
172
        
173
        ClassLoader orig = Lookup.getDefault().lookup(ClassLoader.class);
174
        
175
        ClassLoader my = new URLClassLoader(new URL[] {
176
            subDir.toURL()
177
        }, orig);
178
        
179
        MockLookup.setInstances(my);
180
        
181
        
182
        FileObject cfgRoot = FileUtil.getConfigRoot();
183
        
184
        
185
        OutputStream ostm = cfgRoot.createAndOpen("nonSFSFile.shadow");
186
        
187
        bw = new BufferedWriter(new OutputStreamWriter(ostm));
188
        
189
        bw.write(newFile.toURI().toString());
190
        bw.newLine();
191
        bw.newLine();
192
        
193
        newFile.delete();
194
        
195
        bw.close();
196
        
197
        FileObject fob = cfgRoot.getFileObject("nonSFSFile.shadow");
198
        DataObject dd = DataObject.find(fob);
199
        
200
        assertFalse("Shadow must be still broken", dd instanceof DataShadow);
201
    }
202
}
203
(-)a/openide.util/src/org/openide/util/Utilities.java (-2 / +16 lines)
Lines 2468-2474 Link Here
2468
    }
2468
    }
2469
2469
2470
    /** Provides support for parts of the system that deal with classnames
2470
    /** Provides support for parts of the system that deal with classnames
2471
     * (use <code>Class.forName</code>, <code>NbObjectInputStream</code>, etc.).
2471
     * (use <code>Class.forName</code>, <code>NbObjectInputStream</code>, etc.) or filenames
2472
     * in layers.
2472
     * <P>
2473
     * <P>
2473
     * Often class names (especially package names) changes during lifecycle
2474
     * Often class names (especially package names) changes during lifecycle
2474
     * of a module. When some piece of the system stores the name of a class
2475
     * of a module. When some piece of the system stores the name of a class
Lines 2513-2520 Link Here
2513
     * className is not listed as one that is to be renamed, the returned
2514
     * className is not listed as one that is to be renamed, the returned
2514
     * string == className, if the className is registered to be renamed
2515
     * string == className, if the className is registered to be renamed
2515
     * than the className != returned value, even in a case when className.equals (retValue)
2516
     * than the className != returned value, even in a case when className.equals (retValue)
2517
     * <p/>
2518
     * Similar behaviour applies to <b>filenames</b> provided by layers (system filesystem). Filenames
2519
     * can be also translated to adapt to location changes e.g. in action registrations. Note that 
2520
     * <b>no spaces or special characters</b> are allowed in both translated filenames or translation 
2521
     * results. Filenames must conform to regexp {@code ^[/a-zA-Z0-9$_.+-]+$}. Keys and values are treated
2522
     * as paths from fs root.
2523
     * 
2524
     * <p/>
2525
     * Example of file path translation (action registration file has moved):
2526
     * <pre>
2527
     * # registration ID has changed
2528
     * Actions/Refactoring/RefactoringWhereUsed.instance=Actions/Refactoring/org-netbeans-modules-refactoring-api-ui-WhereUsedAction.instance
2529
     * </pre>
2516
     *
2530
     *
2517
     * @param className fully qualified name of a class to translate
2531
     * @param className fully qualified name of a class, or file path to translate
2518
     * @return new name of the class according to renaming rules.
2532
     * @return new name of the class according to renaming rules.
2519
     */
2533
     */
2520
    public static String translate(final String className) {
2534
    public static String translate(final String className) {

Return to bug 208779