RelativePath.java revision 3392:04fcbc7234a4
119573Sjoerg/*
219573Sjoerg * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
319573Sjoerg * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
419573Sjoerg *
519573Sjoerg * This code is free software; you can redistribute it and/or modify it
619573Sjoerg * under the terms of the GNU General Public License version 2 only, as
719573Sjoerg * published by the Free Software Foundation.  Oracle designates this
819573Sjoerg * particular file as subject to the "Classpath" exception as provided
919573Sjoerg * by Oracle in the LICENSE file that accompanied this code.
1019573Sjoerg *
1119573Sjoerg * This code is distributed in the hope that it will be useful, but WITHOUT
1219573Sjoerg * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1319573Sjoerg * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1419573Sjoerg * version 2 for more details (a copy is included in the LICENSE file that
1519573Sjoerg * accompanied this code).
1619573Sjoerg *
1719573Sjoerg * You should have received a copy of the GNU General Public License version
1819573Sjoerg * 2 along with this work; if not, write to the Free Software Foundation,
1919573Sjoerg * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2019573Sjoerg *
2119573Sjoerg * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2219573Sjoerg * or visit www.oracle.com if you need additional information or have any
2319573Sjoerg * questions.
2450479Speter */
2519573Sjoerg
2619573Sjoergpackage com.sun.tools.javac.file;
2719573Sjoerg
2821243Sjkhimport java.nio.file.FileSystem;
2919573Sjoergimport java.nio.file.InvalidPathException;
3019573Sjoergimport java.nio.file.Path;
3119573Sjoergimport java.util.zip.ZipEntry;
3219573Sjoergimport java.util.zip.ZipFile;
3366834Sphk
3419573Sjoergimport javax.tools.JavaFileObject;
3519573Sjoerg
3619573Sjoerg/**
3719573Sjoerg * Used to represent a platform-neutral path within a platform-specific
3819573Sjoerg * container, such as a directory or zip file.
3919573Sjoerg * Internally, the file separator is always '/'.
4019573Sjoerg *
4119573Sjoerg * <p><b>This is NOT part of any supported API.
4219573Sjoerg * If you write code that depends on this, you do so at your own risk.
4319573Sjoerg * This code and its internal interfaces are subject to change or
4419573Sjoerg * deletion without notice.</b>
4519573Sjoerg */
4619573Sjoergpublic abstract class RelativePath implements Comparable<RelativePath> {
4719573Sjoerg    /**
4819573Sjoerg     * @param p must use '/' as an internal separator
4919573Sjoerg     */
5019573Sjoerg    protected RelativePath(String p) {
5119573Sjoerg        path = p;
5219573Sjoerg    }
53156160Sjhb
54156118Sjhb    public abstract RelativeDirectory dirname();
55156118Sjhb
56156118Sjhb    public abstract String basename();
57156118Sjhb
58156118Sjhb    public Path resolveAgainst(Path directory) throws /*unchecked*/ InvalidPathException {
59156118Sjhb        String sep = directory.getFileSystem().getSeparator();
60156118Sjhb        return directory.resolve(path.replace("/", sep));
61156118Sjhb    }
62156118Sjhb
63156118Sjhb    public Path resolveAgainst(FileSystem fs) throws /*unchecked*/ InvalidPathException {
64156118Sjhb        String sep = fs.getSeparator();
65156118Sjhb        Path root = fs.getRootDirectories().iterator().next();
66156118Sjhb        return root.resolve(path.replace("/", sep));
67156118Sjhb    }
68156118Sjhb
69156118Sjhb    @Override
70156118Sjhb    public int compareTo(RelativePath other) {
71156118Sjhb        return path.compareTo(other.path);
72156118Sjhb    }
73156118Sjhb
74156118Sjhb    @Override
75156118Sjhb    public boolean equals(Object other) {
76156118Sjhb        if (!(other instanceof RelativePath))
77156118Sjhb            return false;
78156118Sjhb         return path.equals(((RelativePath) other).path);
79156118Sjhb    }
80156118Sjhb
81156118Sjhb    @Override
82156118Sjhb    public int hashCode() {
83156118Sjhb        return path.hashCode();
84156118Sjhb    }
85156118Sjhb
86156118Sjhb    @Override
87156118Sjhb    public String toString() {
88156118Sjhb        return "RelPath[" + path + "]";
89156118Sjhb    }
90156118Sjhb
91156118Sjhb    public String getPath() {
92156118Sjhb        return path;
93156118Sjhb    }
94156118Sjhb
95156118Sjhb    protected final String path;
96156118Sjhb
97156118Sjhb    /**
98156118Sjhb     * Used to represent a platform-neutral subdirectory within a platform-specific
99156118Sjhb     * container, such as a directory or zip file.
100156118Sjhb     * Internally, the file separator is always '/', and if the path is not empty,
101156118Sjhb     * it always ends in a '/' as well.
102156118Sjhb     */
103156118Sjhb    public static class RelativeDirectory extends RelativePath {
104156118Sjhb
105156118Sjhb        static RelativeDirectory forPackage(CharSequence packageName) {
106156757Sthompsa            return new RelativeDirectory(packageName.toString().replace('.', '/'));
107156757Sthompsa        }
108156757Sthompsa
109156757Sthompsa        /**
110156757Sthompsa         * @param p must use '/' as an internal separator
111156118Sjhb         */
112156118Sjhb        public RelativeDirectory(String p) {
113156118Sjhb            super(p.length() == 0 || p.endsWith("/") ? p : p + "/");
114156118Sjhb        }
115156118Sjhb
116156118Sjhb        /**
117156118Sjhb         * @param p must use '/' as an internal separator
118156118Sjhb         */
119156118Sjhb        public RelativeDirectory(RelativeDirectory d, String p) {
120156160Sjhb            this(d.path + p);
121156118Sjhb        }
12219573Sjoerg
12319573Sjoerg        @Override
12419573Sjoerg        public RelativeDirectory dirname() {
12519573Sjoerg            int l = path.length();
12619573Sjoerg            if (l == 0)
12719573Sjoerg                return this;
12819573Sjoerg            int sep = path.lastIndexOf('/', l - 2);
12919573Sjoerg            return new RelativeDirectory(path.substring(0, sep + 1));
13019573Sjoerg        }
13119573Sjoerg
13219573Sjoerg        @Override
13319573Sjoerg        public String basename() {
13419573Sjoerg            int l = path.length();
13519573Sjoerg            if (l == 0)
13619573Sjoerg                return path;
13719573Sjoerg            int sep = path.lastIndexOf('/', l - 2);
13819573Sjoerg            return path.substring(sep + 1, l - 1);
13919573Sjoerg        }
14019573Sjoerg
14119573Sjoerg        /**
14219573Sjoerg         * Return true if this subdirectory "contains" the other path.
14319573Sjoerg         * A subdirectory path does not contain itself.
14419573Sjoerg         **/
14519573Sjoerg        boolean contains(RelativePath other) {
14619573Sjoerg            return other.path.length() > path.length() && other.path.startsWith(path);
14719573Sjoerg        }
14819573Sjoerg
14919573Sjoerg        @Override
15019573Sjoerg        public String toString() {
15119573Sjoerg            return "RelativeDirectory[" + path + "]";
15219573Sjoerg        }
15319573Sjoerg    }
15419573Sjoerg
15519573Sjoerg    /**
15619573Sjoerg     * Used to represent a platform-neutral file within a platform-specific
15719573Sjoerg     * container, such as a directory or zip file.
15819573Sjoerg     * Internally, the file separator is always '/'. It never ends in '/'.
15919573Sjoerg     */
16019573Sjoerg    public static class RelativeFile extends RelativePath {
16119573Sjoerg        static RelativeFile forClass(CharSequence className, JavaFileObject.Kind kind) {
16219573Sjoerg            return new RelativeFile(className.toString().replace('.', '/') + kind.extension);
16319573Sjoerg        }
16419573Sjoerg
165        public RelativeFile(String p) {
166            super(p);
167            if (p.endsWith("/"))
168                throw new IllegalArgumentException(p);
169        }
170
171        /**
172         * @param p must use '/' as an internal separator
173         */
174        public RelativeFile(RelativeDirectory d, String p) {
175            this(d.path + p);
176        }
177
178        RelativeFile(RelativeDirectory d, RelativePath p) {
179            this(d, p.path);
180        }
181
182        @Override
183        public RelativeDirectory dirname() {
184            int sep = path.lastIndexOf('/');
185            return new RelativeDirectory(path.substring(0, sep + 1));
186        }
187
188        @Override
189        public String basename() {
190            int sep = path.lastIndexOf('/');
191            return path.substring(sep + 1);
192        }
193
194        ZipEntry getZipEntry(ZipFile zip) {
195            return zip.getEntry(path);
196        }
197
198        @Override
199        public String toString() {
200            return "RelativeFile[" + path + "]";
201        }
202
203    }
204
205}
206