提交 5e89ded1 编写于 作者: J jjg

8001664: refactor javadoc to use abstraction to handle files

Reviewed-by: darcy
上级 f4fd0524
......@@ -25,7 +25,6 @@
package com.sun.tools.doclets.formats.html;
import java.io.*;
import java.net.*;
import java.util.*;
......@@ -46,6 +45,11 @@ import com.sun.tools.doclets.internal.toolkit.util.*;
* use "-helpfile" option when already "-nohelp" option is used.
* </p>
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*
* @author Robert Field.
* @author Atul Dambalkar.
* @author Jamie Ho
......@@ -362,7 +366,7 @@ public class ConfigurationImpl extends Configuration {
"-helpfile"));
return false;
}
File help = new File(os[1]);
DocFile help = DocFile.createFileForInput(this, os[1]);
if (!help.exists()) {
reporter.printError(getText("doclet.File_not_found", os[1]));
return false;
......
......@@ -104,15 +104,12 @@ public class HtmlDoclet extends AbstractDoclet {
return;
}
boolean nodeprecated = configuration.nodeprecated;
String configdestdir = configuration.destDirName;
String confighelpfile = configuration.helpfile;
String configstylefile = configuration.stylesheetfile;
performCopy(configdestdir, confighelpfile);
performCopy(configdestdir, configstylefile);
Util.copyResourceFile(configuration, "background.gif", false);
Util.copyResourceFile(configuration, "tab.gif", false);
Util.copyResourceFile(configuration, "titlebar.gif", false);
Util.copyResourceFile(configuration, "titlebar_end.gif", false);
performCopy(configuration.helpfile);
performCopy(configuration.stylesheetfile);
copyResourceFile("background.gif");
copyResourceFile("tab.gif");
copyResourceFile("titlebar.gif");
copyResourceFile("titlebar_end.gif");
// do early to reduce memory footprint
if (configuration.classuse) {
ClassUseWriter.generate(configuration, classtree);
......@@ -149,8 +146,8 @@ public class HtmlDoclet extends AbstractDoclet {
// If a stylesheet file is not specified, copy the default stylesheet
// and replace newline with platform-specific newline.
if (configuration.stylesheetfile.length() == 0) {
Util.copyFile(configuration, "stylesheet.css", DocPaths.RESOURCES,
DocPath.empty, false, true);
DocFile f = DocFile.createFileForOutput(configuration, DocPaths.STYLESHEET);
f.copyResource(DocPaths.RESOURCES.resolve(DocPaths.STYLESHEET), false, true);
}
}
......@@ -251,29 +248,33 @@ public class HtmlDoclet extends AbstractDoclet {
return (ConfigurationImpl.getInstance()).validOptions(options, reporter);
}
private void performCopy(String configdestdir, String filename) {
/**
* Copy a file in the resources directory to the destination directory.
* @param resource The name of the resource file to copy
*/
private void copyResourceFile(String resource) {
DocPath p = DocPaths.RESOURCES.resolve(resource);
DocFile f = DocFile.createFileForOutput(configuration, p);
f.copyResource(p, false, false);
}
private void performCopy(String filename) {
if (filename.isEmpty())
return;
try {
String destdir = (configdestdir.length() > 0) ?
configdestdir + File.separatorChar: "";
if (filename.length() > 0) {
File helpstylefile = new File(filename);
String parent = helpstylefile.getParent();
String helpstylefilename = (parent == null)?
filename:
filename.substring(parent.length() + 1);
File desthelpfile = new File(destdir + helpstylefilename);
if (!desthelpfile.getCanonicalPath().equals(
helpstylefile.getCanonicalPath())) {
configuration.message.
notice((SourcePosition) null,
"doclet.Copying_File_0_To_File_1",
helpstylefile.toString(), desthelpfile.toString());
Util.copyFile(desthelpfile, helpstylefile);
}
}
DocFile fromfile = DocFile.createFileForInput(configuration, filename);
DocPath path = DocPath.create(fromfile.getName());
DocFile toFile = DocFile.createFileForOutput(configuration, path);
if (toFile.isSameFile(fromfile))
return;
configuration.message.notice((SourcePosition) null,
"doclet.Copying_File_0_To_File_1",
fromfile.toString(), path.getPath());
toFile.copyFile(fromfile);
} catch (IOException exc) {
configuration.message.
error((SourcePosition) null,
configuration.message.error((SourcePosition) null,
"doclet.perform_copy_exception_encountered",
exc.toString());
throw new DocletAbortException();
......
......@@ -723,7 +723,8 @@ public class HtmlDocletWriter extends HtmlDocWriter {
if (helpfile.isEmpty()) {
helpfilenm = DocPaths.HELP_DOC;
} else {
helpfilenm = DocPath.create(new File(helpfile).getName());
DocFile file = DocFile.createFileForInput(configuration, helpfile);
helpfilenm = DocPath.create(file.getName());
}
Content linkContent = getHyperLink(pathToRoot.resolve(helpfilenm),
helpLabel, "", "");
......@@ -1671,12 +1672,13 @@ public class HtmlDocletWriter extends HtmlDocWriter {
* @return an HtmlTree for the lINK tag which provides the stylesheet location
*/
public HtmlTree getStyleSheetProperties() {
String filename = configuration.stylesheetfile;
String stylesheetfile = configuration.stylesheetfile;
DocPath stylesheet;
if (filename.length() > 0) {
stylesheet = DocPath.create(new File(filename).getName());
} else {
if (stylesheetfile.isEmpty()) {
stylesheet = DocPaths.STYLESHEET;
} else {
DocFile file = DocFile.createFileForInput(configuration, stylesheetfile);
stylesheet = DocPath.create(file.getName());
}
HtmlTree link = HtmlTree.LINK("stylesheet", "text/css",
pathToRoot.resolve(stylesheet).getPath(),
......
......@@ -26,11 +26,13 @@
package com.sun.tools.doclets.formats.html;
import java.io.*;
import javax.tools.FileObject;
import com.sun.javadoc.*;
import com.sun.tools.doclets.formats.html.markup.*;
import com.sun.tools.doclets.internal.toolkit.*;
import com.sun.tools.doclets.internal.toolkit.util.*;
import com.sun.tools.doclets.formats.html.markup.*;
/**
* Converts Java Source Code to HTML.
......@@ -95,8 +97,7 @@ public class SourceToHTMLConverter {
// package files to HTML.
if (!(configuration.nodeprecated &&
(Util.isDeprecated(cds[i]) || Util.isDeprecated(cds[i].containingPackage()))))
convertClass(configuration, cds[i],
getPackageOutputDir(outputdir, cds[i].containingPackage()));
convertClass(configuration, cds[i], outputdir);
}
}
......@@ -109,10 +110,9 @@ public class SourceToHTMLConverter {
*/
public static void convertPackage(ConfigurationImpl configuration, PackageDoc pd,
DocPath outputdir) {
if (pd == null || outputdir == null) {
if (pd == null) {
return;
}
DocPath classOutputdir = getPackageOutputDir(outputdir, pd);
ClassDoc[] cds = pd.allClasses();
for (int i = 0; i < cds.length; i++) {
// If -nodeprecated option is set and the class is marked as deprecated,
......@@ -120,21 +120,10 @@ public class SourceToHTMLConverter {
// containing package deprecation since it is already check in
// the calling method above.
if (!(configuration.nodeprecated && Util.isDeprecated(cds[i])))
convertClass(configuration, cds[i], classOutputdir);
convertClass(configuration, cds[i], outputdir);
}
}
/**
* Return the directory write output to for the given package.
*
* @param outputDir the directory to output to.
* @param pd the Package to generate output for.
* @return the package output directory as a String.
*/
private static DocPath getPackageOutputDir(DocPath outputDir, PackageDoc pd) {
return outputDir.resolve(DocPath.forPackage(pd));
}
/**
* Convert the given Class to an HTML.
*
......@@ -144,7 +133,7 @@ public class SourceToHTMLConverter {
*/
public static void convertClass(ConfigurationImpl configuration, ClassDoc cd,
DocPath outputdir) {
if (cd == null || outputdir == null) {
if (cd == null) {
return;
}
try {
......@@ -184,8 +173,8 @@ public class SourceToHTMLConverter {
addBlankLines(pre);
Content div = HtmlTree.DIV(HtmlStyle.sourceContainer, pre);
body.addContent(div);
writeToFile(body, outputdir, cd.name(), configuration);
} catch (Exception e){
writeToFile(body, outputdir.resolve(DocPath.forClass(cd)), configuration);
} catch (IOException e) {
e.printStackTrace();
}
}
......@@ -194,12 +183,11 @@ public class SourceToHTMLConverter {
* Write the output to the file.
*
* @param body the documentation content to be written to the file.
* @param outputDir the directory to output to.
* @param className the name of the class that I am converting to HTML.
* @param path the path for the file.
* @param configuration the Doclet configuration to pass notices to.
*/
private static void writeToFile(Content body, DocPath outputDir,
String className, ConfigurationImpl configuration) throws IOException {
private static void writeToFile(Content body, DocPath path,
ConfigurationImpl configuration) throws IOException {
Content htmlDocType = DocType.Transitional();
Content head = new HtmlTree(HtmlTag.HEAD);
head.addContent(HtmlTree.TITLE(new StringContent(
......@@ -208,15 +196,15 @@ public class SourceToHTMLConverter {
Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
head, body);
Content htmlDocument = new HtmlDocument(htmlDocType, htmlTree);
File dir = outputDir.resolveAgainst(configuration.destDirName);
dir.mkdirs();
File newFile = new File(dir, className + ".html");
configuration.message.notice("doclet.Generating_0", newFile.getPath());
FileOutputStream fout = new FileOutputStream(newFile);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fout));
bw.write(htmlDocument.toString());
bw.close();
fout.close();
configuration.message.notice("doclet.Generating_0", path.getPath());
DocFile df = DocFile.createFileForOutput(configuration, path);
Writer w = df.openWriter();
try {
htmlDocument.write(w, true);
} finally {
w.close();
}
}
/**
......@@ -229,7 +217,8 @@ public class SourceToHTMLConverter {
String filename = configuration.stylesheetfile;
DocPath stylesheet;
if (filename.length() > 0) {
stylesheet = DocPath.create(new File(filename).getName());
DocFile file = DocFile.createFileForInput(configuration, filename);
stylesheet = DocPath.create(file.getName());
} else {
stylesheet = DocPaths.STYLESHEET;
}
......
......@@ -156,7 +156,7 @@ public class HtmlWriter {
*/
public HtmlWriter(Configuration configuration, DocPath path)
throws IOException, UnsupportedEncodingException {
writer = Util.genWriter(configuration, path);
writer = DocFile.createFileForOutput(configuration, path).openWriter();
this.configuration = configuration;
this.memberDetailsListPrinted = false;
packageTableHeader = new String[] {
......
......@@ -106,7 +106,7 @@ public abstract class AbstractDoclet {
/**
* Start the generation of files. Call generate methods in the individual
* writers, which will in turn genrate the documentation files. Call the
* writers, which will in turn generate the documentation files. Call the
* TreeWriter generation first to ensure the Class Hierarchy is built
* first and then can be used in the later generation.
*
......@@ -124,17 +124,7 @@ public abstract class AbstractDoclet {
ClassTree classtree = new ClassTree(configuration, configuration.nodeprecated);
generateClassFiles(root, classtree);
if (configuration.sourcepath != null && configuration.sourcepath.length() > 0) {
StringTokenizer pathTokens = new StringTokenizer(configuration.sourcepath,
String.valueOf(File.pathSeparatorChar));
boolean first = true;
while(pathTokens.hasMoreTokens()){
Util.copyDocFiles(configuration,
new File(pathTokens.nextToken()),
DocPaths.DOC_FILES, first);
first = false;
}
}
Util.copyDocFiles(configuration, DocPaths.DOC_FILES);
PackageListWriter.generate(configuration);
generatePackageFiles(classtree);
......
......@@ -456,7 +456,7 @@ public abstract class Configuration {
tagletManager.addCustomTag(args[1], tagletpath);
continue;
}
String[] tokens = Util.tokenize(args[1],
String[] tokens = tokenize(args[1],
TagletManager.SIMPLE_TAGLET_OPT_SEPERATOR, 3);
if (tokens.length == 1) {
String tagName = args[1];
......@@ -480,6 +480,47 @@ public abstract class Configuration {
}
}
/**
* Given a string, return an array of tokens. The separator can be escaped
* with the '\' character. The '\' character may also be escaped by the
* '\' character.
*
* @param s the string to tokenize.
* @param separator the separator char.
* @param maxTokens the maximum number of tokens returned. If the
* max is reached, the remaining part of s is appended
* to the end of the last token.
*
* @return an array of tokens.
*/
private String[] tokenize(String s, char separator, int maxTokens) {
List<String> tokens = new ArrayList<String>();
StringBuilder token = new StringBuilder ();
boolean prevIsEscapeChar = false;
for (int i = 0; i < s.length(); i += Character.charCount(i)) {
int currentChar = s.codePointAt(i);
if (prevIsEscapeChar) {
// Case 1: escaped character
token.appendCodePoint(currentChar);
prevIsEscapeChar = false;
} else if (currentChar == separator && tokens.size() < maxTokens-1) {
// Case 2: separator
tokens.add(token.toString());
token = new StringBuilder();
} else if (currentChar == '\\') {
// Case 3: escape character
prevIsEscapeChar = true;
} else {
// Case 4: regular character
token.appendCodePoint(currentChar);
}
}
if (token.length() > 0) {
tokens.add(token.toString());
}
return tokens.toArray(new String[] {});
}
private void addToSet(Set<String> s, String str){
StringTokenizer st = new StringTokenizer(str, ":");
String current;
......@@ -532,12 +573,12 @@ public abstract class Configuration {
String opt = os[0].toLowerCase();
if (opt.equals("-d")) {
String destdirname = addTrailingFileSep(os[1]);
File destDir = new File(destdirname);
DocFile destDir = DocFile.createFileForDirectory(this, destdirname);
if (!destDir.exists()) {
//Create the output directory (in case it doesn't exist yet)
reporter.printNotice(getText("doclet.dest_dir_create",
destdirname));
(new File(destdirname)).mkdirs();
destDir.mkdirs();
} else if (!destDir.isDirectory()) {
reporter.printError(getText(
"doclet.destination_directory_not_directory_0",
......@@ -711,7 +752,7 @@ public abstract class Configuration {
public InputStream getBuilderXML() throws FileNotFoundException {
return builderXMLPath == null ?
Configuration.class.getResourceAsStream(DEFAULT_BUILDER_XML) :
new FileInputStream(new File(builderXMLPath));
DocFile.createFileForInput(this, builderXMLPath).openInputStream();
}
/**
......
......@@ -140,10 +140,7 @@ public class AnnotationTypeBuilder extends AbstractBuilder {
//Only copy doc files dir if the containing package is not
//documented AND if we have not documented a class from the same
//package already. Otherwise, we are making duplicate copies.
Util.copyDocFiles(configuration,
new File(Util.getPackageSourcePath(configuration, containingPackage),
DocPath.forPackage(annotationTypeDoc).getPath()),
DocPaths.DOC_FILES, true);
Util.copyDocFiles(configuration, containingPackage);
containingPackagesSeen.add(containingPackage.name());
}
}
......
......@@ -266,10 +266,7 @@ public class ClassBuilder extends AbstractBuilder {
//Only copy doc files dir if the containing package is not
//documented AND if we have not documented a class from the same
//package already. Otherwise, we are making duplicate copies.
Util.copyDocFiles(configuration,
new File(Util.getPackageSourcePath(configuration, containingPackage),
DocPath.forPackage(classDoc).getPath()),
DocPaths.DOC_FILES, true);
Util.copyDocFiles(configuration, containingPackage);
containingPackagesSeen.add(containingPackage.name());
}
}
......
......@@ -119,11 +119,7 @@ public class PackageSummaryBuilder extends AbstractBuilder {
packageWriter.addPackageFooter(contentTree);
packageWriter.printDocument(contentTree);
packageWriter.close();
Util.copyDocFiles(
configuration,
Util.getPackageSourcePath(configuration, packageDoc),
DocPath.forPackage(packageDoc).resolve(DocPaths.DOC_FILES),
true);
Util.copyDocFiles(configuration, packageDoc);
}
/**
......
......@@ -161,7 +161,7 @@ public class TagletManager {
* @param message the message retriever to print warnings.
*/
public TagletManager(boolean nosince, boolean showversion,
boolean showauthor, MessageRetriever message){
boolean showauthor, MessageRetriever message) {
overridenStandardTags = new HashSet<String>();
potentiallyConflictingTags = new HashSet<String>();
standardTags = new HashSet<String>();
......@@ -253,47 +253,17 @@ public class TagletManager {
* @param path the search path string
* @return the resulting array of directory and JAR file URLs
*/
private static URL[] pathToURLs(String path) {
StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
URL[] urls = new URL[st.countTokens()];
int count = 0;
while (st.hasMoreTokens()) {
URL url = fileToURL(new File(st.nextToken()));
if (url != null) {
urls[count++] = url;
private URL[] pathToURLs(String path) {
Set<URL> urls = new LinkedHashSet<URL>();
for (String s: path.split(File.pathSeparator)) {
if (s.isEmpty()) continue;
try {
urls.add(new File(s).getAbsoluteFile().toURI().toURL());
} catch (MalformedURLException e) {
message.error("doclet.MalformedURL", s);
}
}
urls = Arrays.copyOf(urls, count);
return urls;
}
/**
* Returns the directory or JAR file URL corresponding to the specified
* local file name.
*
* @param file the File object
* @return the resulting directory or JAR file URL, or null if unknown
*/
private static URL fileToURL(File file) {
String name;
try {
name = file.getCanonicalPath();
} catch (IOException e) {
name = file.getAbsolutePath();
}
name = name.replace(File.separatorChar, '/');
if (!name.startsWith("/")) {
name = "/" + name;
}
// If the file does not exist, then assume that it's a directory
if (!file.isFile()) {
name = name + "/";
}
try {
return new URL("file", "", name);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("file");
}
return urls.toArray(new URL[urls.size()]);
}
......
/*
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.doclets.internal.toolkit.util;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.tools.JavaFileManager.Location;
import javax.tools.StandardLocation;
import com.sun.tools.doclets.internal.toolkit.Configuration;
/**
* Abstraction for handling files, which may be specified directly
* (e.g. via a path on the command line) or relative to a Location.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*
* @since 8
*/
public class DocFile {
/**
* The doclet configuration.
* Provides access to options such as docencoding, output directory, etc.
*/
private final Configuration configuration;
/**
* The location for this file. Maybe null if the file was created without
* a location or path.
*/
private final Location location;
/**
* The path relative to the (output) location. Maybe null if the file was
* created without a location or path.
*/
private final DocPath path;
/**
* The file object itself.
* This is temporary, until we create different subtypes of DocFile.
*/
private final File file;
/** Create a DocFile for a directory. */
public static DocFile createFileForDirectory(Configuration configuration, String file) {
return new DocFile(configuration, new File(file));
}
/** Create a DocFile for a file that will be opened for reading. */
public static DocFile createFileForInput(Configuration configuration, String file) {
return new DocFile(configuration, new File(file));
}
/** Create a DocFile for a file that will be opened for writing. */
public static DocFile createFileForOutput(Configuration configuration, DocPath path) {
return new DocFile(configuration, StandardLocation.CLASS_OUTPUT, path);
}
/**
* List the directories and files found in subdirectories along the
* elements of the given location.
* @param configuration the doclet configuration
* @param location currently, only {@link StandardLocation#SOURCE_PATH} is supported.
* @param path the subdirectory of the directories of the location for which to
* list files
*/
public static Iterable<DocFile> list(Configuration configuration, Location location, DocPath path) {
if (location != StandardLocation.SOURCE_PATH)
throw new IllegalArgumentException();
Set<DocFile> files = new LinkedHashSet<DocFile>();
for (String s : configuration.sourcepath.split(File.pathSeparator)) {
if (s.isEmpty())
continue;
File f = new File(s);
if (f.isDirectory()) {
f = new File(f, path.getPath());
if (f.exists())
files.add(new DocFile(configuration, f));
}
}
return files;
}
/** Create a DocFile for a given file. */
private DocFile(Configuration configuration, File file) {
this.configuration = configuration;
this.location = null;
this.path = null;
this.file = file;
}
/** Create a DocFile for a given location and relative path. */
private DocFile(Configuration configuration, Location location, DocPath path) {
this.configuration = configuration;
this.location = location;
this.path = path;
this.file = path.resolveAgainst(configuration.destDirName);
}
/** Open an input stream for the file. */
public InputStream openInputStream() throws FileNotFoundException {
return new BufferedInputStream(new FileInputStream(file));
}
/**
* Open an output stream for the file.
* The file must have been created with a location of
* {@link StandardLocation#CLASS_OUTPUT} and a corresponding relative path.
*/
public OutputStream openOutputStream() throws IOException, UnsupportedEncodingException {
if (location != StandardLocation.CLASS_OUTPUT)
throw new IllegalStateException();
createDirectoryForFile(file);
return new BufferedOutputStream(new FileOutputStream(file));
}
/**
* Open an writer for the file, using the encoding (if any) given in the
* doclet configuration.
* The file must have been created with a location of
* {@link StandardLocation#CLASS_OUTPUT} and a corresponding relative path.
*/
public Writer openWriter() throws IOException, UnsupportedEncodingException {
if (location != StandardLocation.CLASS_OUTPUT)
throw new IllegalStateException();
createDirectoryForFile(file);
FileOutputStream fos = new FileOutputStream(file);
if (configuration.docencoding == null) {
return new BufferedWriter(new OutputStreamWriter(fos));
} else {
return new BufferedWriter(new OutputStreamWriter(fos, configuration.docencoding));
}
}
/**
* Copy the contents of another file directly to this file.
*/
public void copyFile(DocFile fromFile) throws IOException {
if (location != StandardLocation.CLASS_OUTPUT)
throw new IllegalStateException();
createDirectoryForFile(file);
InputStream input = fromFile.openInputStream();
OutputStream output = openOutputStream();
try {
byte[] bytearr = new byte[1024];
int len;
while ((len = input.read(bytearr)) != -1) {
output.write(bytearr, 0, len);
}
} catch (FileNotFoundException exc) {
} catch (SecurityException exc) {
} finally {
input.close();
output.close();
}
}
/**
* Copy the contents of a resource file to this file.
* @param resource the path of the resource, relative to the package of this class
* @param overwrite whether or not to overwrite the file if it already exists
* @param replaceNewLine if false, the file is copied as a binary file;
* if true, the file is written line by line, using the platform line
* separator
*/
public void copyResource(DocPath resource, boolean overwrite, boolean replaceNewLine) {
if (location != StandardLocation.CLASS_OUTPUT)
throw new IllegalStateException();
if (file.exists() && !overwrite)
return;
createDirectoryForFile(file);
try {
InputStream in = Configuration.class.getResourceAsStream(resource.getPath());
if (in == null)
return;
OutputStream out = new FileOutputStream(file);
try {
if (!replaceNewLine) {
byte[] buf = new byte[2048];
int n;
while((n = in.read(buf))>0) out.write(buf,0,n);
} else {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
BufferedWriter writer;
if (configuration.docencoding == null) {
writer = new BufferedWriter(new OutputStreamWriter(out));
} else {
writer = new BufferedWriter(new OutputStreamWriter(out,
configuration.docencoding));
}
try {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.write(DocletConstants.NL);
}
} finally {
reader.close();
writer.close();
}
}
} finally {
in.close();
out.close();
}
} catch (IOException e) {
e.printStackTrace(System.err);
throw new DocletAbortException();
}
}
/** Return true if the file can be read. */
public boolean canRead() {
return file.canRead();
}
/** Return true if the file can be written. */
public boolean canWrite() {
return file.canRead();
}
/** Return true if the file exists. */
public boolean exists() {
return file.exists();
}
/** Return the base name (last component) of the file name. */
public String getName() {
return file.getName();
}
/** Return the file system path for this file. */
public String getPath() {
return file.getPath();
}
/** Return true is file has an absolute path name. */
boolean isAbsolute() {
return file.isAbsolute();
}
/** Return true is file identifies a directory. */
public boolean isDirectory() {
return file.isDirectory();
}
/** Return true is file identifies a file. */
public boolean isFile() {
return file.isFile();
}
/** Return true if this file is the same as another. */
public boolean isSameFile(DocFile other) {
try {
return file.exists()
&& file.getCanonicalFile().equals(other.file.getCanonicalFile());
} catch (IOException e) {
return false;
}
}
/** If the file is a directory, list its contents. */
public Iterable<DocFile> list() {
List<DocFile> files = new ArrayList<DocFile>();
for (File f: file.listFiles()) {
files.add(new DocFile(configuration, f));
}
return files;
}
/** Create the file as a directory, including any parent directories. */
public boolean mkdirs() {
return file.mkdirs();
}
/**
* Derive a new file by resolving a relative path against this file.
* The new file will inherit the configuration and location of this file
* If this file has a path set, the new file will have a corresponding
* new path.
*/
public DocFile resolve(DocPath p) {
return resolve(p.getPath());
}
/**
* Derive a new file by resolving a relative path against this file.
* The new file will inherit the configuration and location of this file
* If this file has a path set, the new file will have a corresponding
* new path.
*/
public DocFile resolve(String p) {
if (location == null && path == null) {
return new DocFile(configuration, new File(file, p));
} else {
return new DocFile(configuration, location, path.resolve(p));
}
}
/**
* Resolve a relative file against the given output location.
* @param locn Currently, only SOURCE_OUTPUT is supported.
*/
public DocFile resolveAgainst(StandardLocation locn) {
if (locn != StandardLocation.CLASS_OUTPUT)
throw new IllegalArgumentException();
return new DocFile(configuration,
new File(configuration.destDirName, file.getPath()));
}
/**
* Given a path string create all the directories in the path. For example,
* if the path string is "java/applet", the method will create directory
* "java" and then "java/applet" if they don't exist. The file separator
* string "/" is platform dependent system property.
*
* @param path Directory path string.
*/
private void createDirectoryForFile(File file) {
File dir = file.getParentFile();
if (dir == null || dir.exists() || dir.mkdirs())
return;
configuration.message.error(
"doclet.Unable_to_create_directory_0", dir.getPath());
throw new DocletAbortException();
}
/** Return a string to identify the contents of this object,
* for debugging purposes.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("DocFile[");
if (location != null)
sb.append("locn:").append(location).append(",");
if (path != null)
sb.append("path:").append(path.getPath()).append(",");
sb.append("file:").append(file);
sb.append("]");
return sb.toString();
}
}
......@@ -28,6 +28,11 @@ package com.sun.tools.doclets.internal.toolkit.util;
/**
* Standard DocPath objects.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*
* @since 8
*/
public class DocPaths {
......
......@@ -30,6 +30,8 @@ import java.net.*;
import java.util.HashMap;
import java.util.Map;
import javax.tools.StandardLocation;
import com.sun.javadoc.*;
import com.sun.tools.doclets.internal.toolkit.*;
......@@ -177,7 +179,7 @@ public class Extern {
if (isUrl(pkglisturl)) {
readPackageListFromURL(url, toURL(pkglisturl));
} else {
readPackageListFromFile(url, new File(pkglisturl));
readPackageListFromFile(url, DocFile.createFileForInput(configuration, pkglisturl));
}
return true;
} catch (Fault f) {
......@@ -247,16 +249,18 @@ public class Extern {
* @param path URL or directory path to the packages.
* @param pkgListPath Path to the local "package-list" file.
*/
private void readPackageListFromFile(String path, File pkgListPath)
private void readPackageListFromFile(String path, DocFile pkgListPath)
throws Fault {
File file = new File(pkgListPath, "package-list");
DocFile file = pkgListPath.resolve(DocPaths.PACKAGE_LIST);
if (! (file.isAbsolute() || linkoffline)){
file = new File(configuration.destDirName, file.getPath());
file = file.resolveAgainst(StandardLocation.CLASS_OUTPUT);
}
try {
if (file.exists() && file.canRead()) {
readPackageList(new FileInputStream(file), path,
! ((new File(path)).isAbsolute() || isUrl(path)));
boolean pathIsRelative =
!DocFile.createFileForInput(configuration, path).isAbsolute()
&& !isUrl(path);
readPackageList(file.openInputStream(), path, pathIsRelative);
} else {
throw new Fault(configuration.getText("doclet.File_error", file.getPath()), null);
}
......
......@@ -52,7 +52,7 @@ public class PackageListWriter extends PrintWriter {
* @param configuration the current configuration of the doclet.
*/
public PackageListWriter(Configuration configuration) throws IOException {
super(Util.genWriter(configuration, DocPaths.PACKAGE_LIST));
super(DocFile.createFileForOutput(configuration, DocPaths.PACKAGE_LIST).openWriter());
this.configuration = configuration;
}
......
/*
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.doclets.internal.toolkit.util;
import java.io.File;
/**
* This class is used to represent a source path which can contain only
* directories no zip files. If a zip file is specified in the command line it
* will not get reflected in the SourcePath.
*
* This code is not part of an API.
* It is implementation that is subject to change.
* Do not use it as an API
*
* @author Atul M Dambalkar
*/
public class SourcePath {
private final char dirSeparator = File.pathSeparatorChar;
/**
* The original class path string
*/
private String pathstr;
/**
* List of source path entries. Each entry is a directory.
*/
private File[] sourcePath;
/**
* Build a source path from the specified path string on the command line.
*/
public SourcePath(String pathstr) {
init(pathstr);
}
/**
* Build a default source path from the path strings specified by
* the properties env.class.path.
*/
public SourcePath() {
init(System.getProperty("env.class.path"));
}
/**
* Initialize the SourcePath File array, which will contain only the
* directory names from the given path string.
*
* @param pathstr Path String.
*/
private void init(String pathstr) {
if (pathstr == null || pathstr.length() == 0) {
pathstr = ".";
}
int noOfFileSep = 0;
int index = 0;
this.pathstr = pathstr; // Save original class path string
// Count the number of path separators
while ((index = pathstr.indexOf(dirSeparator, index)) != -1) {
noOfFileSep++;
index++;
}
// Build the source path
File[] tempPath = new File[noOfFileSep + 1];
int tempPathIndex = 0;
int len = pathstr.length();
int sepPos = 0;
for (index = 0; index < len; index = sepPos + 1) {
sepPos = pathstr.indexOf(dirSeparator, index);
if (sepPos < 0) {
sepPos = len;
}
File file = new File(pathstr.substring(index, sepPos));
if (file.isDirectory()) {
tempPath[tempPathIndex++] = file;
} // if it is really a file, ignore it.
}
sourcePath = new File[tempPathIndex];
System.arraycopy((Object)tempPath, 0, (Object)sourcePath,
0, tempPathIndex);
}
/**
* Find the specified directory in the source path.
*
* @param p Name of the directory to be searched for in the source path.
* @return File Return the directory if found else return null.
*/
public File getDirectory(DocPath p) {
for (int i = 0; i < sourcePath.length; i++) {
File directoryNeeded = new File(sourcePath[i], p.getPath());
if (directoryNeeded.isDirectory()) {
return directoryNeeded;
}
}
return null;
}
/**
* Return original source path string.
*/
public String toString() {
return pathstr;
}
}
......@@ -30,6 +30,7 @@ import java.util.*;
import com.sun.javadoc.*;
import com.sun.tools.doclets.internal.toolkit.*;
import javax.tools.StandardLocation;
/**
* Utilities Class for Doclets.
......@@ -191,32 +192,6 @@ public class Util {
}
}
/**
* Copy source file to destination file.
*
* @throws SecurityException
* @throws IOException
*/
public static void copyFile(File destfile, File srcfile)
throws IOException {
byte[] bytearr = new byte[512];
int len = 0;
FileInputStream input = new FileInputStream(srcfile);
File destDir = destfile.getParentFile();
destDir.mkdirs();
FileOutputStream output = new FileOutputStream(destfile);
try {
while ((len = input.read(bytearr)) != -1) {
output.write(bytearr, 0, len);
}
} catch (FileNotFoundException exc) {
} catch (SecurityException exc) {
} finally {
input.close();
output.close();
}
}
/**
* Copy the given directory contents from the source package directory
* to the generated documentation directory. For example for a package
......@@ -230,210 +205,53 @@ public class Util {
* @param dir The original directory name to copy from.
* @param overwrite Overwrite files if true.
*/
public static void copyDocFiles(Configuration configuration,
File path, DocPath dir, boolean overwrite) {
if (checkCopyDocFilesErrors(configuration, path, dir)) {
return;
}
File srcdir = new File(path, dir.getPath());
File destdir = new File(configuration.docFileDestDirName, dir.getPath());
try {
createDirectory(configuration, destdir);
String[] files = srcdir.list();
for (int i = 0; i < files.length; i++) {
File srcfile = new File(srcdir, files[i]);
File destfile = new File(destdir, files[i]);
if (srcfile.isFile()) {
if (destfile.exists() && ! overwrite) {
configuration.message.warning((SourcePosition) null,
"doclet.Copy_Overwrite_warning",
srcfile.toString(), destdir.toString());
} else {
configuration.message.notice(
"doclet.Copying_File_0_To_Dir_1",
srcfile.toString(), destdir.toString());
Util.copyFile(destfile, srcfile);
}
} else if (srcfile.isDirectory()) {
if (configuration.copydocfilesubdirs
&& ! configuration.shouldExcludeDocFileDir(
srcfile.getName())){
copyDocFiles(configuration, path, dir.resolve(files[i]),
overwrite);
}
}
}
} catch (SecurityException exc) {
throw new DocletAbortException();
} catch (IOException exc) {
throw new DocletAbortException();
}
}
/**
* Given the parameters for copying doc-files, check for errors.
*
* @param configuration The configuration of the current doclet.
* @param path The relative path to the directory to be copied.
* @param dirName The original directory name to copy from.
*/
private static boolean checkCopyDocFilesErrors (Configuration configuration,
File path, DocPath dirName) {
if ((configuration.sourcepath == null || configuration.sourcepath.length() == 0) &&
(configuration.destDirName == null || configuration.destDirName.length() == 0)) {
//The destination path and source path are definitely equal.
return true;
}
File sourcePath, destPath = new File(configuration.destDirName);
StringTokenizer pathTokens = new StringTokenizer(
configuration.sourcepath == null ? "" : configuration.sourcepath,
File.pathSeparator);
//Check if the destination path is equal to the source path. If yes,
//do not copy doc-file directories.
while(pathTokens.hasMoreTokens()){
sourcePath = new File(pathTokens.nextToken());
if(destPath.equals(sourcePath)){
return true;
}
}
//Make sure the doc-file being copied exists.
File srcdir = new File(path, dirName.getPath());
if (! srcdir.exists()) {
return true;
}
return false;
}
/**
* Copy a file in the resources directory to the destination
* directory (if it is not there already). If
* <code>overwrite</code> is true and the destination file
* already exists, overwrite it.
*
* @param configuration Holds the destination directory and error message
* @param resourcefile The name of the resource file to copy
* @param overwrite A flag to indicate whether the file in the
* destination directory will be overwritten if
* it already exists.
*/
public static void copyResourceFile(Configuration configuration,
String resourcefile, boolean overwrite) {
copyFile(configuration, resourcefile, DocPaths.RESOURCES, DocPaths.RESOURCES,
overwrite, false);
public static void copyDocFiles(Configuration configuration, PackageDoc pd) {
copyDocFiles(configuration, DocPath.forPackage(pd).resolve(DocPaths.DOC_FILES));
}
/**
* Copy a file from a source directory to a destination directory
* (if it is not there already). If <code>overwrite</code> is true and
* the destination file already exists, overwrite it.
*
* @param configuration Holds the error message
* @param file The name of the file to copy
* @param source The source directory
* @param destination The destination directory where the file needs to be copied
* @param overwrite A flag to indicate whether the file in the
* destination directory will be overwritten if
* it already exists.
* @param replaceNewLine true if the newline needs to be replaced with platform-
* specific newline.
*/
public static void copyFile(Configuration configuration, String file, DocPath source,
DocPath destination, boolean overwrite, boolean replaceNewLine) {
copyFile(configuration, file, source.getPath(), destination.getPath(),
overwrite, replaceNewLine);
}
public static void copyFile(Configuration configuration, String file, String source,
String destination, boolean overwrite, boolean replaceNewLine) {
File destdir = configuration.destDirName.isEmpty() ?
(destination.isEmpty() ? null : new File(destination)) :
new File(configuration.destDirName, destination);
File destfile = (destdir == null) ? new File(file) : new File(destdir, file);
createDirectory(configuration, destfile.getParentFile());
if (destfile.exists() && (! overwrite)) return;
public static void copyDocFiles(Configuration configuration, DocPath dir) {
try {
InputStream in = Configuration.class.getResourceAsStream(
source + '/' + file);
if (in == null) return;
OutputStream out = new FileOutputStream(destfile);
try {
if (!replaceNewLine) {
byte[] buf = new byte[2048];
int n;
while((n = in.read(buf))>0) out.write(buf,0,n);
} else {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
BufferedWriter writer;
if (configuration.docencoding == null) {
writer = new BufferedWriter(new OutputStreamWriter(out));
} else {
writer = new BufferedWriter(new OutputStreamWriter(out,
configuration.docencoding));
}
try {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.write(DocletConstants.NL);
boolean first = true;
for (DocFile f : DocFile.list(configuration, StandardLocation.SOURCE_PATH, dir)) {
if (!f.isDirectory()) {
continue;
}
DocFile srcdir = f;
DocFile destdir = DocFile.createFileForOutput(configuration, dir);
if (srcdir.isSameFile(destdir)) {
continue;
}
for (DocFile srcfile: srcdir.list()) {
DocFile destfile = destdir.resolve(srcfile.getName());
if (srcfile.isFile()) {
if (destfile.exists() && !first) {
configuration.message.warning((SourcePosition) null,
"doclet.Copy_Overwrite_warning",
srcfile.getPath(), destdir.getPath());
} else {
configuration.message.notice(
"doclet.Copying_File_0_To_Dir_1",
srcfile.getPath(), destdir.getPath());
destfile.copyFile(srcfile);
}
} else if (srcfile.isDirectory()) {
if (configuration.copydocfilesubdirs
&& !configuration.shouldExcludeDocFileDir(srcfile.getName())) {
copyDocFiles(configuration, dir.resolve(srcfile.getName()));
}
} finally {
reader.close();
writer.close();
}
}
} finally {
in.close();
out.close();
}
} catch (IOException ie) {
ie.printStackTrace(System.err);
throw new DocletAbortException();
}
}
/**
* Given a path string create all the directories in the path. For example,
* if the path string is "java/applet", the method will create directory
* "java" and then "java/applet" if they don't exist. The file separator
* string "/" is platform dependent system property.
*
* @param dir Directory path string.
*/
public static void createDirectory(Configuration configuration, File dir) {
if (dir == null) {
return;
}
if (dir.exists()) {
return;
} else {
if (dir.mkdirs()) {
return;
} else {
configuration.message.error(
"doclet.Unable_to_create_directory_0", dir.getPath());
throw new DocletAbortException();
first = false;
}
} catch (SecurityException exc) {
throw new DocletAbortException();
} catch (IOException exc) {
throw new DocletAbortException();
}
}
/**
* Given a PackageDoc, return the source path for that package.
* @param configuration The Configuration for the current Doclet.
* @param pkgDoc The package to search the path for.
* @return A string representing the path to the given package.
*/
public static File getPackageSourcePath(Configuration configuration,
PackageDoc pkgDoc) {
DocPath pkgPath = DocPath.forPackage(pkgDoc);
File pkgDir = new SourcePath(configuration.sourcepath).getDirectory(pkgPath);
if (pkgDir == null)
return null;
//Make sure that both paths are using the same separators.
String completePath = Util.replaceText(pkgDir.getPath(), File.separator, "/");
String pathForPkg = completePath.substring(0, completePath.lastIndexOf(pkgPath.getPath()));
return new File(pathForPkg);
}
/**
* We want the list of types in alphabetical order. However, types are not
* comparable. We need a comparator for now.
......@@ -638,31 +456,6 @@ public class Util {
return rawString.trim();
}
/**
* Create the directory path for the file to be generated, construct
* FileOutputStream and OutputStreamWriter depending upon docencoding.
*
* @param path The directory path to be created for this file.
* @exception IOException Exception raised by the FileWriter is passed on
* to next level.
* @exception UnsupportedEncodingException Exception raised by the
* OutputStreamWriter is passed on to next level.
* @return Writer Writer for the file getting generated.
* @see java.io.FileOutputStream
* @see java.io.OutputStreamWriter
*/
public static Writer genWriter(Configuration configuration, DocPath path)
throws IOException, UnsupportedEncodingException {
File file = path.resolveAgainst(configuration.destDirName);
createDirectory(configuration, file.getParentFile());
FileOutputStream fos = new FileOutputStream(file);
if (configuration.docencoding == null) {
return new BufferedWriter(new OutputStreamWriter(fos));
} else {
return new BufferedWriter(new OutputStreamWriter(fos, configuration.docencoding));
}
}
/**
* Given an annotation, return true if it should be documented and false
* otherwise.
......@@ -682,47 +475,6 @@ public class Util {
return false;
}
/**
* Given a string, return an array of tokens. The separator can be escaped
* with the '\' character. The '\' character may also be escaped by the
* '\' character.
*
* @param s the string to tokenize.
* @param separator the separator char.
* @param maxTokens the maxmimum number of tokens returned. If the
* max is reached, the remaining part of s is appended
* to the end of the last token.
*
* @return an array of tokens.
*/
public static String[] tokenize(String s, char separator, int maxTokens) {
List<String> tokens = new ArrayList<String>();
StringBuilder token = new StringBuilder ();
boolean prevIsEscapeChar = false;
for (int i = 0; i < s.length(); i += Character.charCount(i)) {
int currentChar = s.codePointAt(i);
if (prevIsEscapeChar) {
// Case 1: escaped character
token.appendCodePoint(currentChar);
prevIsEscapeChar = false;
} else if (currentChar == separator && tokens.size() < maxTokens-1) {
// Case 2: separator
tokens.add(token.toString());
token = new StringBuilder();
} else if (currentChar == '\\') {
// Case 3: escape character
prevIsEscapeChar = true;
} else {
// Case 4: regular character
token.appendCodePoint(currentChar);
}
}
if (token.length() > 0) {
tokens.add(token.toString());
}
return tokens.toArray(new String[] {});
}
/**
* Return true if this class is linkable and false if we can't link to the
* desired class.
......
/*
* Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -77,17 +77,19 @@ public class TestDocFileDir extends JavadocTester {
//Output dir = Input Dir
private static final String[] ARGS1 =
new String[] {
"-d", BUG_ID + "-1", "-sourcepath",
"blah" + String.valueOf(File.pathSeparatorChar) +
BUG_ID + "-1" + String.valueOf(File.pathSeparatorChar) +
"blah", "pkg"};
"-d", BUG_ID + "-1",
"-sourcepath",
"blah" + File.pathSeparator + BUG_ID + "-1" + File.pathSeparator + "blah",
"pkg"};
//Exercising -docfilessubdirs and -excludedocfilessubdir
private static final String[] ARGS2 =
new String[] {
"-d", BUG_ID + "-2", "-sourcepath", SRC_DIR,
"-docfilessubdirs", "-excludedocfilessubdir",
"subdir-excluded1:subdir-excluded2", "pkg"};
"-d", BUG_ID + "-2",
"-sourcepath", SRC_DIR,
"-docfilessubdirs",
"-excludedocfilessubdir", "subdir-excluded1:subdir-excluded2",
"pkg"};
//Output dir = "", Input dir = ""
private static final String[] ARGS0 =
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册