diff -r 4a6cfcd35eb7 masterfs/src/org/netbeans/modules/masterfs/filebasedfs/FileBasedFileSystem.java --- a/masterfs/src/org/netbeans/modules/masterfs/filebasedfs/FileBasedFileSystem.java Tue Jan 18 17:13:43 2011 +0100 +++ b/masterfs/src/org/netbeans/modules/masterfs/filebasedfs/FileBasedFileSystem.java Thu Jan 20 20:33:52 2011 +0100 @@ -54,6 +54,8 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; import org.netbeans.modules.masterfs.ProvidedExtensionsProxy; import org.netbeans.modules.masterfs.filebasedfs.fileobjects.BaseFileObj; import org.netbeans.modules.masterfs.filebasedfs.fileobjects.FileObjectFactory; @@ -72,6 +74,7 @@ * @author Radek Matous */ public final class FileBasedFileSystem extends FileSystem { + private static final Logger LOG = Logger.getLogger(FileBasedFileSystem.class.getName()); private static FileBasedFileSystem INSTANCE = new FileBasedFileSystem(); transient private RootObj root; transient private final StatusImpl status = new StatusImpl(); @@ -200,13 +203,16 @@ } } else { name = (name.startsWith("/")) ? name : ("/"+name); - } + } + File f = new File(name); if (name.contains("..")) { - if (("/" + name + "/").contains("/../")) { - return null; + try { + f = f.getCanonicalFile(); + } catch (IOException ex) { + LOG.log(Level.WARNING, "Cannot canonicalize " + f, ex); } } - return getFileObject(new File(name)); + return getFileObject(f); } @Override diff -r 4a6cfcd35eb7 masterfs/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/FolderObj.java --- a/masterfs/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/FolderObj.java Tue Jan 18 17:13:43 2011 +0100 +++ b/masterfs/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/FolderObj.java Thu Jan 20 20:33:52 2011 +0100 @@ -106,15 +106,18 @@ // #47885 - relative path must not contain back slashes return null; } - if (relativePath.contains("..")) { - if (("/" + relativePath + "/").contains("/../")) { - return null; - } - } if (relativePath.startsWith("/")) { relativePath = relativePath.substring(1); } File file = new File(getFileName().getFile(), relativePath); + if (relativePath.contains("..")) { + try { + file = file.getCanonicalFile(); + } catch (IOException ex) { + LOG.log(Level.WARNING, "Cannot canonicalize " + file, ex); + } + } + FileObjectFactory factory = getFactory(); return factory.getValidFileObject(file, FileObjectFactory.Caller.GetFileObject); } diff -r 4a6cfcd35eb7 masterfs/test/unit/src/org/netbeans/modules/masterfs/filebasedfs/utils/FileUtilParentTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/masterfs/test/unit/src/org/netbeans/modules/masterfs/filebasedfs/utils/FileUtilParentTest.java Thu Jan 20 20:33:52 2011 +0100 @@ -0,0 +1,88 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.masterfs.filebasedfs.utils; + +import java.io.File; +import org.netbeans.junit.NbTestCase; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; + +public class FileUtilParentTest extends NbTestCase { + + public FileUtilParentTest(String testName) { + super(testName); + } + + public void testNorm() throws Exception { + File root = getWorkDir(); + // create dir1 + File dir1 = new File(root, "d1"); + dir1.mkdirs(); + FileObject dirFO1 = FileUtil.toFileObject(dir1); + assertNotNull(dirFO1); + // create dir2 + File dir2 = new File(root, "d2"); + dir2.mkdirs(); + FileObject dirFO2 = FileUtil.toFileObject(dir2); + assertNotNull(dirFO2); + + // create child in dir2 + File file = new File(dir2, "child"); + file.createNewFile(); + FileObject fo = FileUtil.toFileObject(file); + + // find dir2 by its relative path "../dir2" + FileObject foundDirFO2 = dirFO1.getFileObject("../" + dirFO2.getNameExt()); + assertNotNull(foundDirFO2); + + assertParent(dirFO2, fo); + assertParent(foundDirFO2, fo); + } + + private void assertParent(FileObject parent, FileObject fo) { + System.err.printf("isParentOf %s %s ? %b\n", parent.getPath(), + fo.getPath(), FileUtil.isParentOf(parent, fo)); + assertTrue("FileObject " + parent + " should be parent of " + fo, + FileUtil.isParentOf(parent, fo)); + } +} diff -r 4a6cfcd35eb7 openide.filesystems/apichanges.xml --- a/openide.filesystems/apichanges.xml Tue Jan 18 17:13:43 2011 +0100 +++ b/openide.filesystems/apichanges.xml Thu Jan 20 20:33:52 2011 +0100 @@ -49,6 +49,24 @@ Filesystems API + + + FileObject.getFileObject accepts ".." + + + + + +

+ Semantic of + + getFileObject + method has been clarified to accept "..". +

+
+ + +
setAttribute("methodvalue:attrname", method) and "newvalue:" diff -r 4a6cfcd35eb7 openide.filesystems/manifest.mf --- a/openide.filesystems/manifest.mf Tue Jan 18 17:13:43 2011 +0100 +++ b/openide.filesystems/manifest.mf Thu Jan 20 20:33:52 2011 +0100 @@ -2,5 +2,5 @@ OpenIDE-Module: org.openide.filesystems OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties OpenIDE-Module-Layer: org/openide/filesystems/resources/layer.xml -OpenIDE-Module-Specification-Version: 7.44 +OpenIDE-Module-Specification-Version: 7.45 diff -r 4a6cfcd35eb7 openide.filesystems/src/org/openide/filesystems/AbstractFolder.java --- a/openide.filesystems/src/org/openide/filesystems/AbstractFolder.java Tue Jan 18 17:13:43 2011 +0100 +++ b/openide.filesystems/src/org/openide/filesystems/AbstractFolder.java Thu Jan 20 20:33:52 2011 +0100 @@ -280,8 +280,12 @@ // than in getChild, than it is not called // so often. fo.check(); - - fo = fo.getChild(en.nextElement()); + final String next = en.nextElement(); + if ("..".equals(next)) { + fo = (AbstractFolder)fo.getParent(); + } else { + fo = fo.getChild(next); + } } } diff -r 4a6cfcd35eb7 openide.filesystems/src/org/openide/filesystems/FileObject.java --- a/openide.filesystems/src/org/openide/filesystems/FileObject.java Tue Jan 18 17:13:43 2011 +0100 +++ b/openide.filesystems/src/org/openide/filesystems/FileObject.java Thu Jan 20 20:33:52 2011 +0100 @@ -836,6 +836,9 @@ /** Retrieve file or folder relative to a current folder, with a given relative path. * Note that neither file nor folder is created on disk. This method isn't final since revision 1.93. + * Since 7.45 common implementations of this method + * accept also ".." which is interpreted as a reference to parent. + * * @param relativePath is just basename of the file or (since 4.16) the relative path delimited by '/' * @return the object representing this file or null if the file * or folder does not exist @@ -855,7 +858,11 @@ } while ((myObj != null) && st.hasMoreTokens()) { String nameExt = st.nextToken(); - myObj = myObj.getFileObject(nameExt, null); + if (nameExt.equals("..")) { // NOI18N + myObj = myObj.getParent(); + } else { + myObj = myObj.getFileObject(nameExt, null); + } } return myObj; diff -r 4a6cfcd35eb7 openide.filesystems/test/unit/src/org/openide/filesystems/FileObjectTestHid.java --- a/openide.filesystems/test/unit/src/org/openide/filesystems/FileObjectTestHid.java Tue Jan 18 17:13:43 2011 +0100 +++ b/openide.filesystems/test/unit/src/org/openide/filesystems/FileObjectTestHid.java Thu Jan 20 20:33:52 2011 +0100 @@ -720,7 +720,7 @@ FileObject fold2 = getTestFolder1(fold1); assertEquals("Is parent", fold1, fold2.getParent()); - assertEquals("No .. can be used", null, fold2.getFileObject("..")); + assertEquals(".. goes to parent", fold1, fold2.getFileObject("..")); } public void testFindResourceWithDots() throws Exception { @@ -733,8 +733,8 @@ for (String s : arr) { sb.append(s).append("/../").append(s).append('/'); } - assertNull( - "No .. in findResource allowed", + assertEquals( + "Properly found", fold2, fold2.getFileSystem().findResource(sb.toString()) ); } @@ -821,8 +821,8 @@ FileObject r2 = fo1.getParent().getFileObject("../x/y.java"); FileObject r3 = fo1.getFileObject("../../x/y.java"); assertEquals("y.java found without ..", fo2, r1); - assertNull("y.java not found with ..", r2); - assertNull("y.java not found with ../..", r3); + assertEquals("y.java found with ..", fo2, r2); + assertEquals("y.java found with ../..", fo2, r3); } public void testGetPath5() throws IOException{