1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFile.java Wed Oct 31 13:48:15 2012 -0700 1.3 @@ -0,0 +1,399 @@ 1.4 +/* 1.5 + * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.doclets.internal.toolkit.util; 1.30 + 1.31 +import java.io.BufferedInputStream; 1.32 +import java.io.BufferedOutputStream; 1.33 +import java.io.BufferedReader; 1.34 +import java.io.BufferedWriter; 1.35 +import java.io.File; 1.36 +import java.io.FileInputStream; 1.37 +import java.io.FileNotFoundException; 1.38 +import java.io.FileOutputStream; 1.39 +import java.io.IOException; 1.40 +import java.io.InputStream; 1.41 +import java.io.InputStreamReader; 1.42 +import java.io.OutputStream; 1.43 +import java.io.OutputStreamWriter; 1.44 +import java.io.UnsupportedEncodingException; 1.45 +import java.io.Writer; 1.46 +import java.util.ArrayList; 1.47 +import java.util.LinkedHashSet; 1.48 +import java.util.List; 1.49 +import java.util.Set; 1.50 + 1.51 +import javax.tools.JavaFileManager.Location; 1.52 +import javax.tools.StandardLocation; 1.53 + 1.54 +import com.sun.tools.doclets.internal.toolkit.Configuration; 1.55 + 1.56 +/** 1.57 + * Abstraction for handling files, which may be specified directly 1.58 + * (e.g. via a path on the command line) or relative to a Location. 1.59 + * 1.60 + * <p><b>This is NOT part of any supported API. 1.61 + * If you write code that depends on this, you do so at your own risk. 1.62 + * This code and its internal interfaces are subject to change or 1.63 + * deletion without notice.</b> 1.64 + * 1.65 + * @since 8 1.66 + */ 1.67 +public class DocFile { 1.68 + 1.69 + /** 1.70 + * The doclet configuration. 1.71 + * Provides access to options such as docencoding, output directory, etc. 1.72 + */ 1.73 + private final Configuration configuration; 1.74 + 1.75 + /** 1.76 + * The location for this file. Maybe null if the file was created without 1.77 + * a location or path. 1.78 + */ 1.79 + private final Location location; 1.80 + 1.81 + /** 1.82 + * The path relative to the (output) location. Maybe null if the file was 1.83 + * created without a location or path. 1.84 + */ 1.85 + private final DocPath path; 1.86 + 1.87 + /** 1.88 + * The file object itself. 1.89 + * This is temporary, until we create different subtypes of DocFile. 1.90 + */ 1.91 + private final File file; 1.92 + 1.93 + /** Create a DocFile for a directory. */ 1.94 + public static DocFile createFileForDirectory(Configuration configuration, String file) { 1.95 + return new DocFile(configuration, new File(file)); 1.96 + } 1.97 + 1.98 + /** Create a DocFile for a file that will be opened for reading. */ 1.99 + public static DocFile createFileForInput(Configuration configuration, String file) { 1.100 + return new DocFile(configuration, new File(file)); 1.101 + } 1.102 + 1.103 + /** Create a DocFile for a file that will be opened for writing. */ 1.104 + public static DocFile createFileForOutput(Configuration configuration, DocPath path) { 1.105 + return new DocFile(configuration, StandardLocation.CLASS_OUTPUT, path); 1.106 + } 1.107 + 1.108 + /** 1.109 + * List the directories and files found in subdirectories along the 1.110 + * elements of the given location. 1.111 + * @param configuration the doclet configuration 1.112 + * @param location currently, only {@link StandardLocation#SOURCE_PATH} is supported. 1.113 + * @param path the subdirectory of the directories of the location for which to 1.114 + * list files 1.115 + */ 1.116 + public static Iterable<DocFile> list(Configuration configuration, Location location, DocPath path) { 1.117 + if (location != StandardLocation.SOURCE_PATH) 1.118 + throw new IllegalArgumentException(); 1.119 + 1.120 + Set<DocFile> files = new LinkedHashSet<DocFile>(); 1.121 + for (String s : configuration.sourcepath.split(File.pathSeparator)) { 1.122 + if (s.isEmpty()) 1.123 + continue; 1.124 + File f = new File(s); 1.125 + if (f.isDirectory()) { 1.126 + f = new File(f, path.getPath()); 1.127 + if (f.exists()) 1.128 + files.add(new DocFile(configuration, f)); 1.129 + } 1.130 + } 1.131 + return files; 1.132 + } 1.133 + 1.134 + /** Create a DocFile for a given file. */ 1.135 + private DocFile(Configuration configuration, File file) { 1.136 + this.configuration = configuration; 1.137 + this.location = null; 1.138 + this.path = null; 1.139 + this.file = file; 1.140 + } 1.141 + 1.142 + /** Create a DocFile for a given location and relative path. */ 1.143 + private DocFile(Configuration configuration, Location location, DocPath path) { 1.144 + this.configuration = configuration; 1.145 + this.location = location; 1.146 + this.path = path; 1.147 + this.file = path.resolveAgainst(configuration.destDirName); 1.148 + } 1.149 + 1.150 + /** Open an input stream for the file. */ 1.151 + public InputStream openInputStream() throws FileNotFoundException { 1.152 + return new BufferedInputStream(new FileInputStream(file)); 1.153 + } 1.154 + 1.155 + /** 1.156 + * Open an output stream for the file. 1.157 + * The file must have been created with a location of 1.158 + * {@link StandardLocation#CLASS_OUTPUT} and a corresponding relative path. 1.159 + */ 1.160 + public OutputStream openOutputStream() throws IOException, UnsupportedEncodingException { 1.161 + if (location != StandardLocation.CLASS_OUTPUT) 1.162 + throw new IllegalStateException(); 1.163 + 1.164 + createDirectoryForFile(file); 1.165 + return new BufferedOutputStream(new FileOutputStream(file)); 1.166 + } 1.167 + 1.168 + /** 1.169 + * Open an writer for the file, using the encoding (if any) given in the 1.170 + * doclet configuration. 1.171 + * The file must have been created with a location of 1.172 + * {@link StandardLocation#CLASS_OUTPUT} and a corresponding relative path. 1.173 + */ 1.174 + public Writer openWriter() throws IOException, UnsupportedEncodingException { 1.175 + if (location != StandardLocation.CLASS_OUTPUT) 1.176 + throw new IllegalStateException(); 1.177 + 1.178 + createDirectoryForFile(file); 1.179 + FileOutputStream fos = new FileOutputStream(file); 1.180 + if (configuration.docencoding == null) { 1.181 + return new BufferedWriter(new OutputStreamWriter(fos)); 1.182 + } else { 1.183 + return new BufferedWriter(new OutputStreamWriter(fos, configuration.docencoding)); 1.184 + } 1.185 + } 1.186 + 1.187 + /** 1.188 + * Copy the contents of another file directly to this file. 1.189 + */ 1.190 + public void copyFile(DocFile fromFile) throws IOException { 1.191 + if (location != StandardLocation.CLASS_OUTPUT) 1.192 + throw new IllegalStateException(); 1.193 + 1.194 + createDirectoryForFile(file); 1.195 + 1.196 + InputStream input = fromFile.openInputStream(); 1.197 + OutputStream output = openOutputStream(); 1.198 + try { 1.199 + byte[] bytearr = new byte[1024]; 1.200 + int len; 1.201 + while ((len = input.read(bytearr)) != -1) { 1.202 + output.write(bytearr, 0, len); 1.203 + } 1.204 + } catch (FileNotFoundException exc) { 1.205 + } catch (SecurityException exc) { 1.206 + } finally { 1.207 + input.close(); 1.208 + output.close(); 1.209 + } 1.210 + } 1.211 + 1.212 + /** 1.213 + * Copy the contents of a resource file to this file. 1.214 + * @param resource the path of the resource, relative to the package of this class 1.215 + * @param overwrite whether or not to overwrite the file if it already exists 1.216 + * @param replaceNewLine if false, the file is copied as a binary file; 1.217 + * if true, the file is written line by line, using the platform line 1.218 + * separator 1.219 + */ 1.220 + public void copyResource(DocPath resource, boolean overwrite, boolean replaceNewLine) { 1.221 + if (location != StandardLocation.CLASS_OUTPUT) 1.222 + throw new IllegalStateException(); 1.223 + 1.224 + if (file.exists() && !overwrite) 1.225 + return; 1.226 + 1.227 + createDirectoryForFile(file); 1.228 + 1.229 + try { 1.230 + InputStream in = Configuration.class.getResourceAsStream(resource.getPath()); 1.231 + if (in == null) 1.232 + return; 1.233 + 1.234 + OutputStream out = new FileOutputStream(file); 1.235 + try { 1.236 + if (!replaceNewLine) { 1.237 + byte[] buf = new byte[2048]; 1.238 + int n; 1.239 + while((n = in.read(buf))>0) out.write(buf,0,n); 1.240 + } else { 1.241 + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 1.242 + BufferedWriter writer; 1.243 + if (configuration.docencoding == null) { 1.244 + writer = new BufferedWriter(new OutputStreamWriter(out)); 1.245 + } else { 1.246 + writer = new BufferedWriter(new OutputStreamWriter(out, 1.247 + configuration.docencoding)); 1.248 + } 1.249 + try { 1.250 + String line; 1.251 + while ((line = reader.readLine()) != null) { 1.252 + writer.write(line); 1.253 + writer.write(DocletConstants.NL); 1.254 + } 1.255 + } finally { 1.256 + reader.close(); 1.257 + writer.close(); 1.258 + } 1.259 + } 1.260 + } finally { 1.261 + in.close(); 1.262 + out.close(); 1.263 + } 1.264 + } catch (IOException e) { 1.265 + e.printStackTrace(System.err); 1.266 + throw new DocletAbortException(); 1.267 + } 1.268 + } 1.269 + 1.270 + /** Return true if the file can be read. */ 1.271 + public boolean canRead() { 1.272 + return file.canRead(); 1.273 + } 1.274 + 1.275 + /** Return true if the file can be written. */ 1.276 + public boolean canWrite() { 1.277 + return file.canRead(); 1.278 + } 1.279 + 1.280 + /** Return true if the file exists. */ 1.281 + public boolean exists() { 1.282 + return file.exists(); 1.283 + } 1.284 + 1.285 + /** Return the base name (last component) of the file name. */ 1.286 + public String getName() { 1.287 + return file.getName(); 1.288 + } 1.289 + 1.290 + /** Return the file system path for this file. */ 1.291 + public String getPath() { 1.292 + return file.getPath(); 1.293 + } 1.294 + 1.295 + /** Return true is file has an absolute path name. */ 1.296 + boolean isAbsolute() { 1.297 + return file.isAbsolute(); 1.298 + } 1.299 + 1.300 + /** Return true is file identifies a directory. */ 1.301 + public boolean isDirectory() { 1.302 + return file.isDirectory(); 1.303 + } 1.304 + 1.305 + /** Return true is file identifies a file. */ 1.306 + public boolean isFile() { 1.307 + return file.isFile(); 1.308 + } 1.309 + 1.310 + /** Return true if this file is the same as another. */ 1.311 + public boolean isSameFile(DocFile other) { 1.312 + try { 1.313 + return file.exists() 1.314 + && file.getCanonicalFile().equals(other.file.getCanonicalFile()); 1.315 + } catch (IOException e) { 1.316 + return false; 1.317 + } 1.318 + } 1.319 + 1.320 + /** If the file is a directory, list its contents. */ 1.321 + public Iterable<DocFile> list() { 1.322 + List<DocFile> files = new ArrayList<DocFile>(); 1.323 + for (File f: file.listFiles()) { 1.324 + files.add(new DocFile(configuration, f)); 1.325 + } 1.326 + return files; 1.327 + } 1.328 + 1.329 + /** Create the file as a directory, including any parent directories. */ 1.330 + public boolean mkdirs() { 1.331 + return file.mkdirs(); 1.332 + } 1.333 + 1.334 + /** 1.335 + * Derive a new file by resolving a relative path against this file. 1.336 + * The new file will inherit the configuration and location of this file 1.337 + * If this file has a path set, the new file will have a corresponding 1.338 + * new path. 1.339 + */ 1.340 + public DocFile resolve(DocPath p) { 1.341 + return resolve(p.getPath()); 1.342 + } 1.343 + 1.344 + /** 1.345 + * Derive a new file by resolving a relative path against this file. 1.346 + * The new file will inherit the configuration and location of this file 1.347 + * If this file has a path set, the new file will have a corresponding 1.348 + * new path. 1.349 + */ 1.350 + public DocFile resolve(String p) { 1.351 + if (location == null && path == null) { 1.352 + return new DocFile(configuration, new File(file, p)); 1.353 + } else { 1.354 + return new DocFile(configuration, location, path.resolve(p)); 1.355 + } 1.356 + } 1.357 + 1.358 + /** 1.359 + * Resolve a relative file against the given output location. 1.360 + * @param locn Currently, only SOURCE_OUTPUT is supported. 1.361 + */ 1.362 + public DocFile resolveAgainst(StandardLocation locn) { 1.363 + if (locn != StandardLocation.CLASS_OUTPUT) 1.364 + throw new IllegalArgumentException(); 1.365 + return new DocFile(configuration, 1.366 + new File(configuration.destDirName, file.getPath())); 1.367 + } 1.368 + 1.369 + /** 1.370 + * Given a path string create all the directories in the path. For example, 1.371 + * if the path string is "java/applet", the method will create directory 1.372 + * "java" and then "java/applet" if they don't exist. The file separator 1.373 + * string "/" is platform dependent system property. 1.374 + * 1.375 + * @param path Directory path string. 1.376 + */ 1.377 + private void createDirectoryForFile(File file) { 1.378 + File dir = file.getParentFile(); 1.379 + if (dir == null || dir.exists() || dir.mkdirs()) 1.380 + return; 1.381 + 1.382 + configuration.message.error( 1.383 + "doclet.Unable_to_create_directory_0", dir.getPath()); 1.384 + throw new DocletAbortException(); 1.385 + } 1.386 + 1.387 + /** Return a string to identify the contents of this object, 1.388 + * for debugging purposes. 1.389 + */ 1.390 + @Override 1.391 + public String toString() { 1.392 + StringBuilder sb = new StringBuilder(); 1.393 + sb.append("DocFile["); 1.394 + if (location != null) 1.395 + sb.append("locn:").append(location).append(","); 1.396 + if (path != null) 1.397 + sb.append("path:").append(path.getPath()).append(","); 1.398 + sb.append("file:").append(file); 1.399 + sb.append("]"); 1.400 + return sb.toString(); 1.401 + } 1.402 +}