View Javadoc
1   /*
2    * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package com.sun.tools.doclets.internal.toolkit.util;
27  
28  import java.io.BufferedReader;
29  import java.io.BufferedWriter;
30  import java.io.FileNotFoundException;
31  import java.io.IOException;
32  import java.io.InputStream;
33  import java.io.InputStreamReader;
34  import java.io.OutputStream;
35  import java.io.OutputStreamWriter;
36  import java.io.UnsupportedEncodingException;
37  import java.io.Writer;
38  
39  import javax.tools.JavaFileManager.Location;
40  import javax.tools.StandardLocation;
41  
42  import com.sun.tools.doclets.internal.toolkit.Configuration;
43  
44  /**
45   * Abstraction for handling files, which may be specified directly
46   * (e.g. via a path on the command line) or relative to a Location.
47   *
48   *  <p><b>This is NOT part of any supported API.
49   *  If you write code that depends on this, you do so at your own risk.
50   *  This code and its internal interfaces are subject to change or
51   *  deletion without notice.</b>
52   *
53   * @since 8
54   */
55  public abstract class DocFile {
56  
57      /** Create a DocFile for a directory. */
58      public static DocFile createFileForDirectory(Configuration configuration, String file) {
59          return DocFileFactory.getFactory(configuration).createFileForDirectory(file);
60      }
61  
62      /** Create a DocFile for a file that will be opened for reading. */
63      public static DocFile createFileForInput(Configuration configuration, String file) {
64          return DocFileFactory.getFactory(configuration).createFileForInput(file);
65      }
66  
67      /** Create a DocFile for a file that will be opened for writing. */
68      public static DocFile createFileForOutput(Configuration configuration, DocPath path) {
69          return DocFileFactory.getFactory(configuration).createFileForOutput(path);
70      }
71  
72      private final Configuration configuration;
73  
74      /**
75       * The location for this file. Maybe null if the file was created without
76       * a location or path.
77       */
78      protected final Location location;
79  
80      /**
81       * The path relative to the (output) location. Maybe null if the file was
82       * created without a location or path.
83       */
84      protected final DocPath path;
85  
86      /**
87       * List the directories and files found in subdirectories along the
88       * elements of the given location.
89       * @param configuration the doclet configuration
90       * @param location currently, only {@link StandardLocation#SOURCE_PATH} is supported.
91       * @param path the subdirectory of the directories of the location for which to
92       *  list files
93       */
94      public static Iterable<DocFile> list(Configuration configuration, Location location, DocPath path) {
95          return DocFileFactory.getFactory(configuration).list(location, path);
96      }
97  
98      /** Create a DocFile without a location or path */
99      protected DocFile(Configuration configuration) {
100         this.configuration = configuration;
101         this.location = null;
102         this.path = null;
103     }
104 
105     /** Create a DocFile for a given location and relative path. */
106     protected DocFile(Configuration configuration, Location location, DocPath path) {
107         this.configuration = configuration;
108         this.location = location;
109         this.path = path;
110     }
111 
112     /** Open an input stream for the file. */
113     public abstract InputStream openInputStream() throws IOException;
114 
115     /**
116      * Open an output stream for the file.
117      * The file must have been created with a location of
118      * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT}
119      * and a corresponding relative path.
120      */
121     public abstract OutputStream openOutputStream() throws IOException, UnsupportedEncodingException;
122 
123     /**
124      * Open an writer for the file, using the encoding (if any) given in the
125      * doclet configuration.
126      * The file must have been created with a location of
127      * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path.
128      */
129     public abstract Writer openWriter() throws IOException, UnsupportedEncodingException;
130 
131     /**
132      * Copy the contents of another file directly to this file.
133      */
134     public void copyFile(DocFile fromFile) throws IOException {
135         InputStream input = fromFile.openInputStream();
136         OutputStream output = openOutputStream();
137         try {
138             byte[] bytearr = new byte[1024];
139             int len;
140             while ((len = input.read(bytearr)) != -1) {
141                 output.write(bytearr, 0, len);
142             }
143         } catch (FileNotFoundException exc) {
144         } catch (SecurityException exc) {
145         } finally {
146             input.close();
147             output.close();
148         }
149     }
150 
151     /**
152      * Copy the contents of a resource file to this file.
153      * @param resource the path of the resource, relative to the package of this class
154      * @param overwrite whether or not to overwrite the file if it already exists
155      * @param replaceNewLine if false, the file is copied as a binary file;
156      *     if true, the file is written line by line, using the platform line
157      *     separator
158      */
159     public void copyResource(DocPath resource, boolean overwrite, boolean replaceNewLine) {
160         if (exists() && !overwrite)
161             return;
162 
163         try {
164             InputStream in = Configuration.class.getResourceAsStream(resource.getPath());
165             if (in == null)
166                 return;
167 
168             OutputStream out = openOutputStream();
169             try {
170                 if (!replaceNewLine) {
171                     byte[] buf = new byte[2048];
172                     int n;
173                     while((n = in.read(buf))>0) out.write(buf,0,n);
174                 } else {
175                     BufferedReader reader = new BufferedReader(new InputStreamReader(in));
176                     BufferedWriter writer;
177                     if (configuration.docencoding == null) {
178                         writer = new BufferedWriter(new OutputStreamWriter(out));
179                     } else {
180                         writer = new BufferedWriter(new OutputStreamWriter(out,
181                                 configuration.docencoding));
182                     }
183                     try {
184                         String line;
185                         while ((line = reader.readLine()) != null) {
186                             writer.write(line);
187                             writer.write(DocletConstants.NL);
188                         }
189                     } finally {
190                         reader.close();
191                         writer.close();
192                     }
193                 }
194             } finally {
195                 in.close();
196                 out.close();
197             }
198         } catch (IOException e) {
199             e.printStackTrace(System.err);
200             throw new DocletAbortException(e);
201         }
202     }
203 
204     /** Return true if the file can be read. */
205     public abstract boolean canRead();
206 
207     /** Return true if the file can be written. */
208     public abstract boolean canWrite();
209 
210     /** Return true if the file exists. */
211     public abstract boolean exists();
212 
213     /** Return the base name (last component) of the file name. */
214     public abstract String getName();
215 
216     /** Return the file system path for this file. */
217     public abstract String getPath();
218 
219     /** Return true if file has an absolute path name. */
220     public abstract boolean isAbsolute();
221 
222     /** Return true if file identifies a directory. */
223     public abstract boolean isDirectory();
224 
225     /** Return true if file identifies a file. */
226     public abstract boolean isFile();
227 
228     /** Return true if this file is the same as another. */
229     public abstract boolean isSameFile(DocFile other);
230 
231     /** If the file is a directory, list its contents. */
232     public abstract Iterable<DocFile> list() throws IOException;
233 
234     /** Create the file as a directory, including any parent directories. */
235     public abstract boolean mkdirs();
236 
237     /**
238      * Derive a new file by resolving a relative path against this file.
239      * The new file will inherit the configuration and location of this file
240      * If this file has a path set, the new file will have a corresponding
241      * new path.
242      */
243     public abstract DocFile resolve(DocPath p);
244 
245     /**
246      * Derive a new file by resolving a relative path against this file.
247      * The new file will inherit the configuration and location of this file
248      * If this file has a path set, the new file will have a corresponding
249      * new path.
250      */
251     public abstract DocFile resolve(String p);
252 
253     /**
254      * Resolve a relative file against the given output location.
255      * @param locn Currently, only
256      * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} is supported.
257      */
258     public abstract DocFile resolveAgainst(Location locn);
259 }