001    /*--------------------------------------------------------------------------+
002    $Id: CanonicalFile.java 26268 2010-02-18 10:44:30Z juergens $
003    |                                                                          |
004    | Copyright 2005-2010 Technische Universitaet Muenchen                     |
005    |                                                                          |
006    | Licensed under the Apache License, Version 2.0 (the "License");          |
007    | you may not use this file except in compliance with the License.         |
008    | You may obtain a copy of the License at                                  |
009    |                                                                          |
010    |    http://www.apache.org/licenses/LICENSE-2.0                            |
011    |                                                                          |
012    | Unless required by applicable law or agreed to in writing, software      |
013    | distributed under the License is distributed on an "AS IS" BASIS,        |
014    | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
015    | See the License for the specific language governing permissions and      |
016    | limitations under the License.                                           |
017    +--------------------------------------------------------------------------*/
018    package edu.tum.cs.commons.filesystem;
019    
020    import java.io.File;
021    import java.io.FileFilter;
022    import java.io.FilenameFilter;
023    import java.io.IOException;
024    import java.net.URI;
025    
026    /**
027     * This class represents files that are guaranteed to be canonical. For this
028     * class methods <code>getPath()</code>, <code>getAbsolutePath()</code> and
029     * <code>getCanonicalPath()</code> all return the same (canonical) path.
030     * 
031     * @author deissenb
032     * @author $Author: juergens $
033     * @version $Rev: 26268 $
034     * @levd.rating GREEN Hash: F36AFC8726FA8659B2B0CA3F4501A4E3
035     */
036    public class CanonicalFile extends File {
037    
038            /**
039             * Create new canonical file from existing file.
040             */
041            public CanonicalFile(File file) throws IOException {
042                    super(file.getCanonicalPath());
043            }
044    
045            /**
046             * Create new canonical file.
047             * 
048             * @see File#File(String)
049             */
050            public CanonicalFile(String pathname) throws IOException {
051                    super(new File(pathname).getCanonicalPath());
052            }
053    
054            /**
055             * Create new canonical file.
056             * 
057             * @see File#File(File, String)
058             */
059            public CanonicalFile(File parent, String child) throws IOException {
060                    this(new File(parent, child));
061            }
062    
063            /**
064             * Create new canonical file.
065             * 
066             * @see File#File(String, String)
067             */
068            public CanonicalFile(String parent, String child) throws IOException {
069                    this(new File(parent, child));
070            }
071    
072            /**
073             * Create new canonical file.
074             * 
075             * @see File#File(URI)
076             */
077            public CanonicalFile(URI uri) throws IOException {
078                    super(new File(uri).getCanonicalPath());
079            }
080    
081            /**
082             * Returns the canonical file itself. Use {@link #getCanonicalFile()} for
083             * consistency reasons.
084             */
085            @Deprecated
086            @Override
087            public CanonicalFile getAbsoluteFile() {
088                    return this;
089            }
090    
091            /** Returns the canonical file itself. */
092            @Override
093            public CanonicalFile getCanonicalFile() {
094                    return this;
095            }
096    
097            /**
098             * Same as {@link File#listFiles()} but returns canonical files. If for some
099             * strange reason the files below a canonical file cannot be canonized, this
100             * may throw an {@link AssertionError}.
101             */
102            @Override
103            public CanonicalFile[] listFiles() {
104                    return canonize(super.listFiles());
105            }
106    
107            /**
108             * Same as {@link File#listFiles(FileFilter)} but returns canonical files.
109             * If for some strange reason the files below a canonical file cannot be
110             * canonized, this may throw an {@link AssertionError}.
111             */
112            @Override
113            public CanonicalFile[] listFiles(FileFilter filter) {
114                    File[] files = super.listFiles(filter);
115                    CanonicalFile[] result = new CanonicalFile[files.length];
116                    for (int i = 0; i < result.length; i++) {
117                            result[i] = canonize(files[i].getAbsoluteFile());
118                    }
119                    return result;
120            }
121    
122            /**
123             * Same as {@link File#listFiles(FilenameFilter)} but returns canonical
124             * files. If for some strange reason the files below a canonical file cannot
125             * be canonized, this may throw an {@link AssertionError}.
126             */
127            @Override
128            public CanonicalFile[] listFiles(FilenameFilter filter) {
129                    return canonize(super.listFiles(filter));
130            }
131    
132            /**
133             * Same as {@link File#getParentFile()} but returns a canonical file. If for
134             * some strange reason the parent file of a canonical file cannot be
135             * canonized, this may throw an {@link AssertionError}.
136             */
137            @Override
138            public CanonicalFile getParentFile() {
139                    File parent = super.getParentFile();
140                    if (parent == null) {
141                            return null;
142                    }
143                    return canonize(parent);
144            }
145    
146            /** Checks if this <em>file</em> is a file an can be read. */
147            public boolean isReadableFile() {
148                    return isFile() && canRead();
149            }
150    
151            /**
152             * This method is overridden to save effort for call to
153             * {@link File#getCanonicalPath()}.
154             */
155            @Override
156            public String getCanonicalPath() {
157                    return super.getPath();
158            }
159    
160            /**
161             * This method is overridden to save effort for call to
162             * {@link File#getAbsolutePath()}. Use {@link #getCanonicalPath()} for
163             * consistency reasons.
164             */
165            @Deprecated
166            @Override
167            public String getAbsolutePath() {
168                    return super.getPath();
169            }
170    
171            /**
172             * Use {@link #getCanonicalPath()} for consistency reasons.
173             */
174            @Deprecated
175            @Override
176            public String getPath() {
177                    return super.getPath();
178            }
179    
180            /**
181             * Returns the extension of the file.
182             * 
183             * @return File extension, i.e. "java" for "FileSystemUtils.java", or
184             *         <code>null</code>, if the file has no extension (i.e. if a
185             *         filename contains no '.'), returns the empty string if the '.' is
186             *         the filename's last character.
187             */
188            public String getExtension() {
189                    return FileSystemUtils.getFileExtension(this);
190            }
191    
192            /**
193             * Canonizes list of filenames. If a file could not be canonized, this
194             * throws an {@link AssertionError}.
195             */
196            private CanonicalFile[] canonize(File[] files) {
197                    CanonicalFile[] result = new CanonicalFile[files.length];
198                    for (int i = 0; i < result.length; i++) {
199                            result[i] = canonize(files[i]);
200                    }
201                    return result;
202    
203            }
204    
205            /**
206             * Canonizes filename. If a file could not be canonized, this throws an
207             * {@link AssertionError}.
208             */
209            private CanonicalFile canonize(File file) {
210                    try {
211                            return new CanonicalFile(file);
212                    } catch (IOException e) {
213                            throw new AssertionError("Problems creating canonical path for "
214                                            + file + ": " + e.getMessage());
215                    }
216            }
217    
218    }