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