langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFile.java
changeset 40587 1c355ea550ed
parent 35426 374342e56a56
child 45417 f7479ee8de69
equal deleted inserted replaced
40519:e17429a7e843 40587:1c355ea550ed
    24  */
    24  */
    25 
    25 
    26 package jdk.javadoc.internal.doclets.toolkit.util;
    26 package jdk.javadoc.internal.doclets.toolkit.util;
    27 
    27 
    28 import java.io.BufferedReader;
    28 import java.io.BufferedReader;
    29 import java.io.BufferedWriter;
       
    30 import java.io.FileNotFoundException;
       
    31 import java.io.IOException;
    29 import java.io.IOException;
    32 import java.io.InputStream;
    30 import java.io.InputStream;
    33 import java.io.InputStreamReader;
    31 import java.io.InputStreamReader;
    34 import java.io.OutputStream;
    32 import java.io.OutputStream;
    35 import java.io.OutputStreamWriter;
       
    36 import java.io.UnsupportedEncodingException;
    33 import java.io.UnsupportedEncodingException;
    37 import java.io.Writer;
    34 import java.io.Writer;
    38 
    35 
    39 import javax.tools.JavaFileManager.Location;
    36 import javax.tools.JavaFileManager.Location;
    40 import javax.tools.StandardLocation;
    37 import javax.tools.StandardLocation;
    65 
    62 
    66     /** Create a DocFile for a file that will be opened for writing. */
    63     /** Create a DocFile for a file that will be opened for writing. */
    67     public static DocFile createFileForOutput(Configuration configuration, DocPath path) {
    64     public static DocFile createFileForOutput(Configuration configuration, DocPath path) {
    68         return DocFileFactory.getFactory(configuration).createFileForOutput(path);
    65         return DocFileFactory.getFactory(configuration).createFileForOutput(path);
    69     }
    66     }
    70 
       
    71     private final Configuration configuration;
       
    72 
    67 
    73     /**
    68     /**
    74      * The location for this file. Maybe null if the file was created without
    69      * The location for this file. Maybe null if the file was created without
    75      * a location or path.
    70      * a location or path.
    76      */
    71      */
    93     public static Iterable<DocFile> list(Configuration configuration, Location location, DocPath path) {
    88     public static Iterable<DocFile> list(Configuration configuration, Location location, DocPath path) {
    94         return DocFileFactory.getFactory(configuration).list(location, path);
    89         return DocFileFactory.getFactory(configuration).list(location, path);
    95     }
    90     }
    96 
    91 
    97     /** Create a DocFile without a location or path */
    92     /** Create a DocFile without a location or path */
    98     protected DocFile(Configuration configuration) {
    93     protected DocFile() {
    99         this.configuration = configuration;
       
   100         this.location = null;
    94         this.location = null;
   101         this.path = null;
    95         this.path = null;
   102     }
    96     }
   103 
    97 
   104     /** Create a DocFile for a given location and relative path. */
    98     /** Create a DocFile for a given location and relative path. */
   105     protected DocFile(Configuration configuration, Location location, DocPath path) {
    99     protected DocFile(Location location, DocPath path) {
   106         this.configuration = configuration;
       
   107         this.location = location;
   100         this.location = location;
   108         this.path = path;
   101         this.path = path;
   109     }
   102     }
   110 
   103 
   111     /** Open an input stream for the file. */
   104     /**
   112     public abstract InputStream openInputStream() throws IOException;
   105      * Open an input stream for the file.
       
   106      *
       
   107      * @return an open input stream for the file
       
   108      * @throws DocFileIOException if there is a problem opening the stream
       
   109      */
       
   110     public abstract InputStream openInputStream() throws DocFileIOException;
   113 
   111 
   114     /**
   112     /**
   115      * Open an output stream for the file.
   113      * Open an output stream for the file.
   116      * The file must have been created with a location of
   114      * The file must have been created with a location of
   117      * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT}
   115      * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT}
   118      * and a corresponding relative path.
   116      * and a corresponding relative path.
   119      */
   117      *
   120     public abstract OutputStream openOutputStream() throws IOException, UnsupportedEncodingException;
   118      * @return an open output stream for the file
       
   119      * @throws DocFileIOException if there is a problem opening the stream
       
   120      * @throws UnsupportedEncodingException if the configured encoding is not supported
       
   121      */
       
   122     public abstract OutputStream openOutputStream() throws DocFileIOException, UnsupportedEncodingException;
   121 
   123 
   122     /**
   124     /**
   123      * Open an writer for the file, using the encoding (if any) given in the
   125      * Open an writer for the file, using the encoding (if any) given in the
   124      * doclet configuration.
   126      * doclet configuration.
   125      * The file must have been created with a location of
   127      * The file must have been created with a location of
   126      * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path.
   128      * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path.
   127      */
   129      *
   128     public abstract Writer openWriter() throws IOException, UnsupportedEncodingException;
   130      * @return an open output stream for the file
       
   131      * @throws DocFileIOException if there is a problem opening the stream
       
   132      * @throws UnsupportedEncodingException if the configured encoding is not supported
       
   133      */
       
   134     public abstract Writer openWriter() throws DocFileIOException, UnsupportedEncodingException;
   129 
   135 
   130     /**
   136     /**
   131      * Copy the contents of another file directly to this file.
   137      * Copy the contents of another file directly to this file.
   132      */
   138      *
   133     public void copyFile(DocFile fromFile) throws IOException {
   139      * @param fromFile the file to be copied
   134         try (OutputStream output = openOutputStream();
   140      * @throws DocFileIOException if there is a problem file copying the file
   135              InputStream input = fromFile.openInputStream()) {
   141      */
   136             byte[] bytearr = new byte[1024];
   142     public void copyFile(DocFile fromFile) throws DocFileIOException {
   137             int len;
   143         try (OutputStream output = openOutputStream()) {
   138             while ((len = input.read(bytearr)) != -1) {
   144             try (InputStream input = fromFile.openInputStream()) {
   139                 output.write(bytearr, 0, len);
   145                 byte[] bytearr = new byte[1024];
       
   146                 int len;
       
   147                 while ((len = read(fromFile, input, bytearr)) != -1) {
       
   148                     write(this, output, bytearr, len);
       
   149                 }
       
   150             } catch (IOException e) {
       
   151                 throw new DocFileIOException(fromFile, DocFileIOException.Mode.READ, e);
   140             }
   152             }
   141         }
   153         } catch (IOException e) {
   142         catch (FileNotFoundException | SecurityException exc) {
   154             throw new DocFileIOException(this, DocFileIOException.Mode.WRITE, e);
   143         }
   155         }
   144     }
   156     }
   145 
   157 
   146     /**
   158     /**
   147      * Copy the contents of a resource file to this file.
   159      * Copy the contents of a resource file to this file.
       
   160      *
   148      * @param resource the path of the resource, relative to the package of this class
   161      * @param resource the path of the resource, relative to the package of this class
   149      * @param overwrite whether or not to overwrite the file if it already exists
   162      * @param overwrite whether or not to overwrite the file if it already exists
   150      * @param replaceNewLine if false, the file is copied as a binary file;
   163      * @param replaceNewLine if false, the file is copied as a binary file;
   151      *     if true, the file is written line by line, using the platform line
   164      *     if true, the file is written line by line, using the platform line
   152      *     separator
   165      *     separator
   153      */
   166      *
   154     public void copyResource(DocPath resource, boolean overwrite, boolean replaceNewLine) {
   167      * @throws DocFileIOException if there is a problem while writing the copy
       
   168      * @throws ResourceIOException if there is a problem while reading the resource
       
   169      */
       
   170     public void copyResource(DocPath resource, boolean overwrite, boolean replaceNewLine)
       
   171                 throws DocFileIOException, ResourceIOException {
   155         if (exists() && !overwrite)
   172         if (exists() && !overwrite)
   156             return;
   173             return;
   157 
   174 
   158         try {
   175         try {
   159             InputStream in = Configuration.class.getResourceAsStream(resource.getPath());
   176             InputStream in = Configuration.class.getResourceAsStream(resource.getPath());
   160             if (in == null)
   177             if (in == null)
   161                 return;
   178                 return;
   162 
   179 
   163             try (OutputStream out = openOutputStream()) {
   180             try {
   164                 if (!replaceNewLine) {
   181                 if (replaceNewLine) {
   165                     byte[] buf = new byte[2048];
   182                     try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
   166                     int n;
   183                         try (Writer writer = openWriter()) {
   167                     while ((n = in.read(buf)) > 0)
   184                             String line;
   168                         out.write(buf, 0, n);
   185                             while ((line = readResourceLine(resource, reader)) != null) {
       
   186                                 write(this, writer, line);
       
   187                                 write(this, writer, DocletConstants.NL);
       
   188                             }
       
   189                         } catch (IOException e) {
       
   190                             throw new DocFileIOException(this, DocFileIOException.Mode.WRITE, e);
       
   191                         }
       
   192                     }
   169                 } else {
   193                 } else {
   170                     try (BufferedReader reader = new BufferedReader(new InputStreamReader(in));
   194                     try (OutputStream out = openOutputStream()) {
   171                          BufferedWriter writer = new BufferedWriter(configuration.docencoding == null
   195                         byte[] buf = new byte[2048];
   172                                                                     ? new OutputStreamWriter(out)
   196                         int n;
   173                                                                     : new OutputStreamWriter(out, configuration.docencoding))) {
   197                         while ((n = readResource(resource, in, buf)) > 0) {
   174                         String line;
   198                             write(this, out, buf, n);
   175                         while ((line = reader.readLine()) != null) {
       
   176                             writer.write(line);
       
   177                             writer.write(DocletConstants.NL);
       
   178                         }
   199                         }
       
   200                     } catch (IOException e) {
       
   201                         throw new DocFileIOException(this, DocFileIOException.Mode.WRITE, e);
   179                     }
   202                     }
   180                 }
   203                 }
   181             } finally {
   204             } finally {
   182                 in.close();
   205                 in.close();
   183             }
   206             }
   184         } catch (IOException e) {
   207         } catch (IOException e) {
   185             e.printStackTrace(System.err);
   208             throw new ResourceIOException(resource, e);
   186             throw new DocletAbortException(e);
       
   187         }
   209         }
   188     }
   210     }
   189 
   211 
   190     /** Return true if the file can be read. */
   212     /** Return true if the file can be read. */
   191     public abstract boolean canRead();
   213     public abstract boolean canRead();
   212     public abstract boolean isFile();
   234     public abstract boolean isFile();
   213 
   235 
   214     /** Return true if this file is the same as another. */
   236     /** Return true if this file is the same as another. */
   215     public abstract boolean isSameFile(DocFile other);
   237     public abstract boolean isSameFile(DocFile other);
   216 
   238 
   217     /** If the file is a directory, list its contents. */
   239     /** If the file is a directory, list its contents.
   218     public abstract Iterable<DocFile> list() throws IOException;
   240      *
       
   241      * @return the contents of the directory
       
   242      * @throws DocFileIOException if there is a problem while listing the directory
       
   243      */
       
   244     public abstract Iterable<DocFile> list() throws DocFileIOException;
   219 
   245 
   220     /** Create the file as a directory, including any parent directories. */
   246     /** Create the file as a directory, including any parent directories. */
   221     public abstract boolean mkdirs();
   247     public abstract boolean mkdirs();
   222 
   248 
   223     /**
   249     /**
   240      * Resolve a relative file against the given output location.
   266      * Resolve a relative file against the given output location.
   241      * @param locn Currently, only
   267      * @param locn Currently, only
   242      * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} is supported.
   268      * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} is supported.
   243      */
   269      */
   244     public abstract DocFile resolveAgainst(Location locn);
   270     public abstract DocFile resolveAgainst(Location locn);
       
   271 
       
   272 
       
   273     /**
       
   274      * Reads from an input stream opened from a given file into a given buffer.
       
   275      * If an IOException occurs, it is wrapped in a DocFileIOException.
       
   276      *
       
   277      * @param inFile the file for the stream
       
   278      * @param input the stream
       
   279      * @param buf the buffer
       
   280      * @return the number of bytes read, or -1 if at end of file
       
   281      * @throws DocFileIOException if an exception occurred while reading the stream
       
   282      */
       
   283     private static int read(DocFile inFile, InputStream input, byte[] buf) throws DocFileIOException {
       
   284         try {
       
   285             return input.read(buf);
       
   286         } catch (IOException e) {
       
   287             throw new DocFileIOException(inFile, DocFileIOException.Mode.READ, e);
       
   288         }
       
   289     }
       
   290 
       
   291     /**
       
   292      * Writes to an output stream for a given file from a given buffer.
       
   293      * If an IOException occurs, it is wrapped in a DocFileIOException.
       
   294      *
       
   295      * @param outFile the file for the stream
       
   296      * @param out the stream
       
   297      * @param buf the buffer
       
   298      * @throws DocFileIOException if an exception occurred while writing the stream
       
   299      */
       
   300     private static void write(DocFile outFile, OutputStream out, byte[] buf, int len) throws DocFileIOException {
       
   301         try {
       
   302             out.write(buf, 0, len);
       
   303         } catch (IOException e) {
       
   304             throw new DocFileIOException(outFile, DocFileIOException.Mode.WRITE, e);
       
   305         }
       
   306     }
       
   307 
       
   308     /**
       
   309      * Writes text to an output stream for a given file from a given buffer.
       
   310      * If an IOException occurs, it is wrapped in a DocFileIOException.
       
   311      *
       
   312      * @param outFile the file for the stream
       
   313      * @param out the stream
       
   314      * @param text the text to be written
       
   315      * @throws DocFileIOException if an exception occurred while writing the stream
       
   316      */
       
   317     private static void write(DocFile outFile, Writer out, String text) throws DocFileIOException {
       
   318         try {
       
   319             out.write(text);
       
   320         } catch (IOException e) {
       
   321             throw new DocFileIOException(outFile, DocFileIOException.Mode.WRITE, e);
       
   322         }
       
   323     }
       
   324 
       
   325     /**
       
   326      * Reads from an input stream opened from a given resource into a given buffer.
       
   327      * If an IOException occurs, it is wrapped in a ResourceIOException.
       
   328      *
       
   329      * @param resource the resource for the stream
       
   330      * @param in the stream
       
   331      * @param buf the buffer
       
   332      * @return the number of bytes read, or -1 if at end of file
       
   333      * @throws ResourceIOException if an exception occurred while reading the stream
       
   334      */
       
   335     private static int readResource(DocPath resource, InputStream in, byte[] buf) throws ResourceIOException {
       
   336         try {
       
   337             return in.read(buf);
       
   338         } catch (IOException e) {
       
   339             throw new ResourceIOException(resource, e);
       
   340         }
       
   341     }
       
   342 
       
   343     /**
       
   344      * Reads a line of characters from an input stream opened from a given resource.
       
   345      * If an IOException occurs, it is wrapped in a ResourceIOException.
       
   346      *
       
   347      * @param resource the resource for the stream
       
   348      * @param in the stream
       
   349      * @return the line of text, or {@code null} if at end of stream
       
   350      * @throws ResourceIOException if an exception occurred while reading the stream
       
   351      */
       
   352     private static String readResourceLine(DocPath docPath, BufferedReader in) throws ResourceIOException {
       
   353         try {
       
   354             return in.readLine();
       
   355         } catch (IOException e) {
       
   356             throw new ResourceIOException(docPath, e);
       
   357         }
       
   358     }
   245 }
   359 }