0N/A/*
1194N/A * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
553N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
553N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
553N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
553N/A * or visit www.oracle.com if you need additional information or have any
553N/A * questions.
0N/A */
0N/A
0N/Apackage com.sun.tools.doclets.internal.toolkit.util;
0N/A
196N/Aimport java.io.*;
196N/Aimport java.util.*;
196N/A
0N/Aimport com.sun.javadoc.*;
0N/Aimport com.sun.tools.doclets.internal.toolkit.*;
0N/A
0N/A/**
0N/A * Utilities Class for Doclets.
0N/A *
0N/A * This code is not part of an API.
0N/A * It is implementation that is subject to change.
0N/A * Do not use it as an API
0N/A *
0N/A * @author Atul M Dambalkar
0N/A * @author Jamie Ho
0N/A */
0N/Apublic class Util {
0N/A
0N/A /**
0N/A * A mapping between characters and their
0N/A * corresponding HTML escape character.
0N/A */
0N/A public static final String[][] HTML_ESCAPE_CHARS =
0N/A {{"&", "&amp;"}, {"<", "&lt;"}, {">", "&gt;"}};
0N/A
0N/A /**
765N/A * Name of the resource directory.
765N/A */
765N/A public static final String RESOURCESDIR = "resources";
765N/A
765N/A /**
1194N/A * Resource bundle corresponding to the doclets.properties file.
1194N/A */
1194N/A public static final ResourceBundle RESOURCE_BUNDLE =
1194N/A ResourceBundle.getBundle(Configuration.DOCLETS_RESOURCE);
1194N/A
1194N/A /**
0N/A * Return array of class members whose documentation is to be generated.
0N/A * If the member is deprecated do not include such a member in the
0N/A * returned array.
0N/A *
0N/A * @param members Array of members to choose from.
0N/A * @return ProgramElementDoc[] Array of eligible members for whom
0N/A * documentation is getting generated.
0N/A */
0N/A public static ProgramElementDoc[] excludeDeprecatedMembers(
0N/A ProgramElementDoc[] members) {
0N/A return
0N/A toProgramElementDocArray(excludeDeprecatedMembersAsList(members));
0N/A }
0N/A
0N/A /**
0N/A * Return array of class members whose documentation is to be generated.
0N/A * If the member is deprecated do not include such a member in the
0N/A * returned array.
0N/A *
0N/A * @param members Array of members to choose from.
0N/A * @return List List of eligible members for whom
0N/A * documentation is getting generated.
0N/A */
73N/A public static List<ProgramElementDoc> excludeDeprecatedMembersAsList(
0N/A ProgramElementDoc[] members) {
73N/A List<ProgramElementDoc> list = new ArrayList<ProgramElementDoc>();
0N/A for (int i = 0; i < members.length; i++) {
0N/A if (members[i].tags("deprecated").length == 0) {
0N/A list.add(members[i]);
0N/A }
0N/A }
0N/A Collections.sort(list);
0N/A return list;
0N/A }
0N/A
0N/A /**
0N/A * Return the list of ProgramElementDoc objects as Array.
0N/A */
183N/A public static ProgramElementDoc[] toProgramElementDocArray(List<ProgramElementDoc> list) {
0N/A ProgramElementDoc[] pgmarr = new ProgramElementDoc[list.size()];
0N/A for (int i = 0; i < list.size(); i++) {
183N/A pgmarr[i] = list.get(i);
0N/A }
0N/A return pgmarr;
0N/A }
0N/A
0N/A /**
0N/A * Return true if a non-public member found in the given array.
0N/A *
0N/A * @param members Array of members to look into.
0N/A * @return boolean True if non-public member found, false otherwise.
0N/A */
0N/A public static boolean nonPublicMemberFound(ProgramElementDoc[] members) {
0N/A for (int i = 0; i < members.length; i++) {
0N/A if (!members[i].isPublic()) {
0N/A return true;
0N/A }
0N/A }
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * Search for the given method in the given class.
0N/A *
0N/A * @param cd Class to search into.
0N/A * @param method Method to be searched.
0N/A * @return MethodDoc Method found, null otherwise.
0N/A */
0N/A public static MethodDoc findMethod(ClassDoc cd, MethodDoc method) {
0N/A MethodDoc[] methods = cd.methods();
0N/A for (int i = 0; i < methods.length; i++) {
0N/A if (executableMembersEqual(method, methods[i])) {
0N/A return methods[i];
0N/A
0N/A }
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A /**
0N/A * @param member1 the first method to compare.
0N/A * @param member2 the second method to compare.
0N/A * @return true if member1 overrides/hides or is overriden/hidden by member2.
0N/A */
0N/A public static boolean executableMembersEqual(ExecutableMemberDoc member1,
0N/A ExecutableMemberDoc member2) {
0N/A if (! (member1 instanceof MethodDoc && member2 instanceof MethodDoc))
0N/A return false;
0N/A
0N/A MethodDoc method1 = (MethodDoc) member1;
0N/A MethodDoc method2 = (MethodDoc) member2;
0N/A if (method1.isStatic() && method2.isStatic()) {
0N/A Parameter[] targetParams = method1.parameters();
0N/A Parameter[] currentParams;
0N/A if (method1.name().equals(method2.name()) &&
0N/A (currentParams = method2.parameters()).length ==
0N/A targetParams.length) {
0N/A int j;
0N/A for (j = 0; j < targetParams.length; j++) {
0N/A if (! (targetParams[j].typeName().equals(
0N/A currentParams[j].typeName()) ||
0N/A currentParams[j].type() instanceof TypeVariable ||
0N/A targetParams[j].type() instanceof TypeVariable)) {
0N/A break;
0N/A }
0N/A }
0N/A if (j == targetParams.length) {
0N/A return true;
0N/A }
0N/A }
0N/A return false;
0N/A } else {
0N/A return method1.overrides(method2) ||
0N/A method2.overrides(method1) ||
0N/A member1 == member2;
0N/A }
0N/A }
0N/A
0N/A /**
971N/A * According to
971N/A * <cite>The Java&trade; Language Specification</cite>,
971N/A * all the outer classes and static inner classes are core classes.
0N/A */
0N/A public static boolean isCoreClass(ClassDoc cd) {
0N/A return cd.containingClass() == null || cd.isStatic();
0N/A }
0N/A
0N/A public static boolean matches(ProgramElementDoc doc1,
0N/A ProgramElementDoc doc2) {
0N/A if (doc1 instanceof ExecutableMemberDoc &&
0N/A doc2 instanceof ExecutableMemberDoc) {
0N/A ExecutableMemberDoc ed1 = (ExecutableMemberDoc)doc1;
0N/A ExecutableMemberDoc ed2 = (ExecutableMemberDoc)doc2;
0N/A return executableMembersEqual(ed1, ed2);
0N/A } else {
0N/A return doc1.name().equals(doc2.name());
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Copy source file to destination file.
0N/A *
0N/A * @throws SecurityException
0N/A * @throws IOException
0N/A */
0N/A public static void copyFile(File destfile, File srcfile)
0N/A throws IOException {
0N/A byte[] bytearr = new byte[512];
0N/A int len = 0;
0N/A FileInputStream input = new FileInputStream(srcfile);
0N/A File destDir = destfile.getParentFile();
0N/A destDir.mkdirs();
0N/A FileOutputStream output = new FileOutputStream(destfile);
0N/A try {
0N/A while ((len = input.read(bytearr)) != -1) {
0N/A output.write(bytearr, 0, len);
792N/A }
0N/A } catch (FileNotFoundException exc) {
0N/A } catch (SecurityException exc) {
792N/A } finally {
0N/A input.close();
0N/A output.close();
792N/A }
0N/A }
0N/A
0N/A /**
0N/A * Copy the given directory contents from the source package directory
0N/A * to the generated documentation directory. For example for a package
0N/A * java.lang this method find out the source location of the package using
0N/A * {@link SourcePath} and if given directory is found in the source
0N/A * directory structure, copy the entire directory, to the generated
0N/A * documentation hierarchy.
0N/A *
0N/A * @param configuration The configuration of the current doclet.
0N/A * @param path The relative path to the directory to be copied.
0N/A * @param dir The original directory name to copy from.
0N/A * @param overwrite Overwrite files if true.
0N/A */
0N/A public static void copyDocFiles(Configuration configuration,
0N/A String path, String dir, boolean overwrite) {
0N/A if (checkCopyDocFilesErrors(configuration, path, dir)) {
0N/A return;
0N/A }
0N/A String destname = configuration.docFileDestDirName;
0N/A File srcdir = new File(path + dir);
0N/A if (destname.length() > 0 && !destname.endsWith(
765N/A DirectoryManager.URL_FILE_SEPARATOR)) {
765N/A destname += DirectoryManager.URL_FILE_SEPARATOR;
0N/A }
0N/A String dest = destname + dir;
0N/A try {
0N/A File destdir = new File(dest);
0N/A DirectoryManager.createDirectory(configuration, dest);
0N/A String[] files = srcdir.list();
0N/A for (int i = 0; i < files.length; i++) {
0N/A File srcfile = new File(srcdir, files[i]);
0N/A File destfile = new File(destdir, files[i]);
0N/A if (srcfile.isFile()) {
0N/A if(destfile.exists() && ! overwrite) {
0N/A configuration.message.warning((SourcePosition) null,
0N/A "doclet.Copy_Overwrite_warning",
0N/A srcfile.toString(), destdir.toString());
0N/A } else {
0N/A configuration.message.notice(
0N/A "doclet.Copying_File_0_To_Dir_1",
0N/A srcfile.toString(), destdir.toString());
0N/A Util.copyFile(destfile, srcfile);
0N/A }
0N/A } else if(srcfile.isDirectory()) {
0N/A if(configuration.copydocfilesubdirs
0N/A && ! configuration.shouldExcludeDocFileDir(
0N/A srcfile.getName())){
0N/A copyDocFiles(configuration, path, dir +
765N/A DirectoryManager.URL_FILE_SEPARATOR + srcfile.getName(),
0N/A overwrite);
0N/A }
0N/A }
0N/A }
0N/A } catch (SecurityException exc) {
0N/A throw new DocletAbortException();
0N/A } catch (IOException exc) {
0N/A throw new DocletAbortException();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Given the parameters for copying doc-files, check for errors.
0N/A *
0N/A * @param configuration The configuration of the current doclet.
0N/A * @param path The relative path to the directory to be copied.
0N/A * @param dirName The original directory name to copy from.
0N/A */
0N/A private static boolean checkCopyDocFilesErrors (Configuration configuration,
0N/A String path, String dirName) {
0N/A if ((configuration.sourcepath == null || configuration.sourcepath.length() == 0) &&
0N/A (configuration.destDirName == null || configuration.destDirName.length() == 0)) {
0N/A //The destination path and source path are definitely equal.
0N/A return true;
0N/A }
0N/A File sourcePath, destPath = new File(configuration.destDirName);
0N/A StringTokenizer pathTokens = new StringTokenizer(
0N/A configuration.sourcepath == null ? "" : configuration.sourcepath,
0N/A File.pathSeparator);
0N/A //Check if the destination path is equal to the source path. If yes,
0N/A //do not copy doc-file directories.
0N/A while(pathTokens.hasMoreTokens()){
0N/A sourcePath = new File(pathTokens.nextToken());
0N/A if(destPath.equals(sourcePath)){
0N/A return true;
0N/A }
0N/A }
0N/A //Make sure the doc-file being copied exists.
0N/A File srcdir = new File(path + dirName);
0N/A if (! srcdir.exists()) {
0N/A return true;
0N/A }
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * Copy a file in the resources directory to the destination
0N/A * directory (if it is not there already). If
0N/A * <code>overwrite</code> is true and the destination file
0N/A * already exists, overwrite it.
0N/A *
0N/A * @param configuration Holds the destination directory and error message
0N/A * @param resourcefile The name of the resource file to copy
0N/A * @param overwrite A flag to indicate whether the file in the
0N/A * destination directory will be overwritten if
0N/A * it already exists.
0N/A */
0N/A public static void copyResourceFile(Configuration configuration,
765N/A String resourcefile, boolean overwrite) {
765N/A String destresourcesdir = configuration.destDirName + RESOURCESDIR;
765N/A copyFile(configuration, resourcefile, RESOURCESDIR, destresourcesdir,
792N/A overwrite, false);
765N/A }
765N/A
765N/A /**
765N/A * Copy a file from a source directory to a destination directory
765N/A * (if it is not there already). If <code>overwrite</code> is true and
765N/A * the destination file already exists, overwrite it.
765N/A *
765N/A * @param configuration Holds the error message
765N/A * @param file The name of the file to copy
765N/A * @param source The source directory
765N/A * @param destination The destination directory where the file needs to be copied
765N/A * @param overwrite A flag to indicate whether the file in the
765N/A * destination directory will be overwritten if
765N/A * it already exists.
792N/A * @param replaceNewLine true if the newline needs to be replaced with platform-
792N/A * specific newline.
765N/A */
765N/A public static void copyFile(Configuration configuration, String file, String source,
792N/A String destination, boolean overwrite, boolean replaceNewLine) {
765N/A DirectoryManager.createDirectory(configuration, destination);
765N/A File destfile = new File(destination, file);
0N/A if(destfile.exists() && (! overwrite)) return;
0N/A try {
0N/A InputStream in = Configuration.class.getResourceAsStream(
792N/A source + DirectoryManager.URL_FILE_SEPARATOR + file);
0N/A if(in==null) return;
0N/A OutputStream out = new FileOutputStream(destfile);
792N/A try {
792N/A if (!replaceNewLine) {
792N/A byte[] buf = new byte[2048];
792N/A int n;
792N/A while((n = in.read(buf))>0) out.write(buf,0,n);
792N/A } else {
792N/A BufferedReader reader = new BufferedReader(new InputStreamReader(in));
1299N/A BufferedWriter writer;
1299N/A if (configuration.docencoding == null) {
1299N/A writer = new BufferedWriter(new OutputStreamWriter(out));
1299N/A } else {
1299N/A writer = new BufferedWriter(new OutputStreamWriter(out,
1299N/A configuration.docencoding));
1299N/A }
792N/A try {
792N/A String line;
792N/A while ((line = reader.readLine()) != null) {
792N/A writer.write(line);
792N/A writer.write(DocletConstants.NL);
792N/A }
792N/A } finally {
792N/A reader.close();
792N/A writer.close();
792N/A }
792N/A }
792N/A } finally {
792N/A in.close();
792N/A out.close();
792N/A }
792N/A } catch (IOException ie) {
909N/A ie.printStackTrace(System.err);
792N/A throw new DocletAbortException();
792N/A }
0N/A }
0N/A
0N/A /**
0N/A * Given a PackageDoc, return the source path for that package.
0N/A * @param configuration The Configuration for the current Doclet.
0N/A * @param pkgDoc The package to seach the path for.
0N/A * @return A string representing the path to the given package.
0N/A */
0N/A public static String getPackageSourcePath(Configuration configuration,
0N/A PackageDoc pkgDoc){
0N/A try{
0N/A String pkgPath = DirectoryManager.getDirectoryPath(pkgDoc);
0N/A String completePath = new SourcePath(configuration.sourcepath).
765N/A getDirectory(pkgPath) + DirectoryManager.URL_FILE_SEPARATOR;
909N/A //Make sure that both paths are using the same separators.
0N/A completePath = Util.replaceText(completePath, File.separator,
765N/A DirectoryManager.URL_FILE_SEPARATOR);
0N/A pkgPath = Util.replaceText(pkgPath, File.separator,
765N/A DirectoryManager.URL_FILE_SEPARATOR);
909N/A return completePath.substring(0, completePath.lastIndexOf(pkgPath));
0N/A } catch (Exception e){
0N/A return "";
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * We want the list of types in alphabetical order. However, types are not
0N/A * comparable. We need a comparator for now.
0N/A */
73N/A private static class TypeComparator implements Comparator<Type> {
73N/A public int compare(Type type1, Type type2) {
73N/A return type1.qualifiedTypeName().toLowerCase().compareTo(
73N/A type2.qualifiedTypeName().toLowerCase());
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * For the class return all implemented interfaces including the
0N/A * superinterfaces of the implementing interfaces, also iterate over for
0N/A * all the superclasses. For interface return all the extended interfaces
0N/A * as well as superinterfaces for those extended interfaces.
0N/A *
0N/A * @param type type whose implemented or
0N/A * super interfaces are sought.
0N/A * @param configuration the current configuration of the doclet.
0N/A * @param sort if true, return list of interfaces sorted alphabetically.
0N/A * @return List of all the required interfaces.
0N/A */
73N/A public static List<Type> getAllInterfaces(Type type,
0N/A Configuration configuration, boolean sort) {
73N/A Map<ClassDoc,Type> results = sort ? new TreeMap<ClassDoc,Type>() : new LinkedHashMap<ClassDoc,Type>();
0N/A Type[] interfaceTypes = null;
0N/A Type superType = null;
0N/A if (type instanceof ParameterizedType) {
0N/A interfaceTypes = ((ParameterizedType) type).interfaceTypes();
0N/A superType = ((ParameterizedType) type).superclassType();
0N/A } else if (type instanceof ClassDoc) {
0N/A interfaceTypes = ((ClassDoc) type).interfaceTypes();
0N/A superType = ((ClassDoc) type).superclassType();
0N/A } else {
0N/A interfaceTypes = type.asClassDoc().interfaceTypes();
0N/A superType = type.asClassDoc().superclassType();
0N/A }
0N/A
0N/A for (int i = 0; i < interfaceTypes.length; i++) {
0N/A Type interfaceType = interfaceTypes[i];
0N/A ClassDoc interfaceClassDoc = interfaceType.asClassDoc();
0N/A if (! (interfaceClassDoc.isPublic() ||
0N/A (configuration == null ||
0N/A isLinkable(interfaceClassDoc, configuration)))) {
0N/A continue;
0N/A }
0N/A results.put(interfaceClassDoc, interfaceType);
183N/A List<Type> superInterfaces = getAllInterfaces(interfaceType, configuration, sort);
183N/A for (Iterator<Type> iter = superInterfaces.iterator(); iter.hasNext(); ) {
183N/A Type t = iter.next();
0N/A results.put(t.asClassDoc(), t);
0N/A }
0N/A }
0N/A if (superType == null)
73N/A return new ArrayList<Type>(results.values());
0N/A //Try walking the tree.
0N/A addAllInterfaceTypes(results,
0N/A superType,
0N/A superType instanceof ClassDoc ?
0N/A ((ClassDoc) superType).interfaceTypes() :
0N/A ((ParameterizedType) superType).interfaceTypes(),
0N/A false, configuration);
73N/A List<Type> resultsList = new ArrayList<Type>(results.values());
0N/A if (sort) {
0N/A Collections.sort(resultsList, new TypeComparator());
0N/A }
0N/A return resultsList;
0N/A }
0N/A
183N/A public static List<Type> getAllInterfaces(Type type, Configuration configuration) {
0N/A return getAllInterfaces(type, configuration, true);
0N/A }
0N/A
73N/A private static void findAllInterfaceTypes(Map<ClassDoc,Type> results, ClassDoc c, boolean raw,
0N/A Configuration configuration) {
0N/A Type superType = c.superclassType();
0N/A if (superType == null)
0N/A return;
0N/A addAllInterfaceTypes(results, superType,
0N/A superType instanceof ClassDoc ?
0N/A ((ClassDoc) superType).interfaceTypes() :
0N/A ((ParameterizedType) superType).interfaceTypes(),
0N/A raw, configuration);
0N/A }
0N/A
73N/A private static void findAllInterfaceTypes(Map<ClassDoc,Type> results, ParameterizedType p,
0N/A Configuration configuration) {
0N/A Type superType = p.superclassType();
0N/A if (superType == null)
0N/A return;
0N/A addAllInterfaceTypes(results, superType,
0N/A superType instanceof ClassDoc ?
0N/A ((ClassDoc) superType).interfaceTypes() :
0N/A ((ParameterizedType) superType).interfaceTypes(),
0N/A false, configuration);
0N/A }
0N/A
73N/A private static void addAllInterfaceTypes(Map<ClassDoc,Type> results, Type type,
0N/A Type[] interfaceTypes, boolean raw,
0N/A Configuration configuration) {
0N/A for (int i = 0; i < interfaceTypes.length; i++) {
0N/A Type interfaceType = interfaceTypes[i];
0N/A ClassDoc interfaceClassDoc = interfaceType.asClassDoc();
0N/A if (! (interfaceClassDoc.isPublic() ||
0N/A (configuration != null &&
0N/A isLinkable(interfaceClassDoc, configuration)))) {
0N/A continue;
0N/A }
0N/A if (raw)
0N/A interfaceType = interfaceType.asClassDoc();
0N/A results.put(interfaceClassDoc, interfaceType);
183N/A List<Type> superInterfaces = getAllInterfaces(interfaceType, configuration);
183N/A for (Iterator<Type> iter = superInterfaces.iterator(); iter.hasNext(); ) {
183N/A Type superInterface = iter.next();
0N/A results.put(superInterface.asClassDoc(), superInterface);
0N/A }
0N/A }
0N/A if (type instanceof ParameterizedType)
0N/A findAllInterfaceTypes(results, (ParameterizedType) type, configuration);
0N/A else if (((ClassDoc) type).typeParameters().length == 0)
0N/A findAllInterfaceTypes(results, (ClassDoc) type, raw, configuration);
0N/A else
0N/A findAllInterfaceTypes(results, (ClassDoc) type, true, configuration);
0N/A }
0N/A
0N/A /**
0N/A * Enclose in quotes, used for paths and filenames that contains spaces
0N/A */
0N/A public static String quote(String filepath) {
0N/A return ("\"" + filepath + "\"");
0N/A }
0N/A
0N/A /**
0N/A * Given a package, return it's name.
0N/A * @param packageDoc the package to check.
0N/A * @return the name of the given package.
0N/A */
0N/A public static String getPackageName(PackageDoc packageDoc) {
0N/A return packageDoc == null || packageDoc.name().length() == 0 ?
0N/A DocletConstants.DEFAULT_PACKAGE_NAME : packageDoc.name();
0N/A }
0N/A
0N/A /**
0N/A * Given a package, return it's file name without the extension.
0N/A * @param packageDoc the package to check.
0N/A * @return the file name of the given package.
0N/A */
0N/A public static String getPackageFileHeadName(PackageDoc packageDoc) {
0N/A return packageDoc == null || packageDoc.name().length() == 0 ?
0N/A DocletConstants.DEFAULT_PACKAGE_FILE_NAME : packageDoc.name();
0N/A }
0N/A
0N/A /**
0N/A * Given a string, replace all occurraces of 'newStr' with 'oldStr'.
0N/A * @param originalStr the string to modify.
0N/A * @param oldStr the string to replace.
0N/A * @param newStr the string to insert in place of the old string.
0N/A */
0N/A public static String replaceText(String originalStr, String oldStr,
0N/A String newStr) {
0N/A if (oldStr == null || newStr == null || oldStr.equals(newStr)) {
0N/A return originalStr;
0N/A }
909N/A return originalStr.replace(oldStr, newStr);
0N/A }
0N/A
0N/A /**
0N/A * Given a string, escape all special html characters and
0N/A * return the result.
0N/A *
0N/A * @param s The string to check.
0N/A * @return the original string with all of the HTML characters
0N/A * escaped.
0N/A *
0N/A * @see #HTML_ESCAPE_CHARS
0N/A */
0N/A public static String escapeHtmlChars(String s) {
0N/A String result = s;
0N/A for (int i = 0; i < HTML_ESCAPE_CHARS.length; i++) {
0N/A result = Util.replaceText(result,
0N/A HTML_ESCAPE_CHARS[i][0], HTML_ESCAPE_CHARS[i][1]);
0N/A }
0N/A return result;
0N/A }
0N/A
0N/A /**
765N/A * Given a string, strips all html characters and
765N/A * return the result.
765N/A *
765N/A * @param rawString The string to check.
765N/A * @return the original string with all of the HTML characters
765N/A * stripped.
765N/A *
765N/A */
765N/A public static String stripHtml(String rawString) {
765N/A // remove HTML tags
765N/A rawString = rawString.replaceAll("\\<.*?>", " ");
765N/A // consolidate multiple spaces between a word to a single space
765N/A rawString = rawString.replaceAll("\\b\\s{2,}\\b", " ");
765N/A // remove extra whitespaces
765N/A return rawString.trim();
765N/A }
765N/A
765N/A /**
0N/A * Create the directory path for the file to be generated, construct
0N/A * FileOutputStream and OutputStreamWriter depending upon docencoding.
0N/A *
0N/A * @param path The directory path to be created for this file.
0N/A * @param filename File Name to which the PrintWriter will do the Output.
0N/A * @param docencoding Encoding to be used for this file.
0N/A * @exception IOException Exception raised by the FileWriter is passed on
0N/A * to next level.
196N/A * @exception UnsupportedEncodingException Exception raised by the
0N/A * OutputStreamWriter is passed on to next level.
0N/A * @return Writer Writer for the file getting generated.
0N/A * @see java.io.FileOutputStream
0N/A * @see java.io.OutputStreamWriter
0N/A */
0N/A public static Writer genWriter(Configuration configuration,
0N/A String path, String filename,
0N/A String docencoding)
0N/A throws IOException, UnsupportedEncodingException {
0N/A FileOutputStream fos;
0N/A if (path != null) {
0N/A DirectoryManager.createDirectory(configuration, path);
0N/A fos = new FileOutputStream(((path.length() > 0)?
0N/A path + File.separator: "") + filename);
0N/A } else {
0N/A fos = new FileOutputStream(filename);
0N/A }
0N/A if (docencoding == null) {
196N/A return new OutputStreamWriter(fos);
0N/A } else {
0N/A return new OutputStreamWriter(fos, docencoding);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Given an annotation, return true if it should be documented and false
0N/A * otherwise.
0N/A *
0N/A * @param annotationDoc the annotation to check.
0N/A *
0N/A * @return true return true if it should be documented and false otherwise.
0N/A */
0N/A public static boolean isDocumentedAnnotation(AnnotationTypeDoc annotationDoc) {
0N/A AnnotationDesc[] annotationDescList = annotationDoc.annotations();
0N/A for (int i = 0; i < annotationDescList.length; i++) {
0N/A if (annotationDescList[i].annotationType().qualifiedName().equals(
0N/A java.lang.annotation.Documented.class.getName())){
0N/A return true;
0N/A }
0N/A }
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * Given a string, return an array of tokens. The separator can be escaped
0N/A * with the '\' character. The '\' character may also be escaped by the
0N/A * '\' character.
0N/A *
0N/A * @param s the string to tokenize.
0N/A * @param separator the separator char.
0N/A * @param maxTokens the maxmimum number of tokens returned. If the
0N/A * max is reached, the remaining part of s is appended
0N/A * to the end of the last token.
0N/A *
0N/A * @return an array of tokens.
0N/A */
0N/A public static String[] tokenize(String s, char separator, int maxTokens) {
73N/A List<String> tokens = new ArrayList<String>();
0N/A StringBuilder token = new StringBuilder ();
0N/A boolean prevIsEscapeChar = false;
0N/A for (int i = 0; i < s.length(); i += Character.charCount(i)) {
0N/A int currentChar = s.codePointAt(i);
0N/A if (prevIsEscapeChar) {
0N/A // Case 1: escaped character
0N/A token.appendCodePoint(currentChar);
0N/A prevIsEscapeChar = false;
0N/A } else if (currentChar == separator && tokens.size() < maxTokens-1) {
0N/A // Case 2: separator
0N/A tokens.add(token.toString());
0N/A token = new StringBuilder();
0N/A } else if (currentChar == '\\') {
0N/A // Case 3: escape character
0N/A prevIsEscapeChar = true;
0N/A } else {
0N/A // Case 4: regular character
0N/A token.appendCodePoint(currentChar);
0N/A }
0N/A }
0N/A if (token.length() > 0) {
0N/A tokens.add(token.toString());
0N/A }
73N/A return tokens.toArray(new String[] {});
0N/A }
0N/A
0N/A /**
0N/A * Return true if this class is linkable and false if we can't link to the
0N/A * desired class.
0N/A * <br>
0N/A * <b>NOTE:</b> You can only link to external classes if they are public or
0N/A * protected.
0N/A *
0N/A * @param classDoc the class to check.
0N/A * @param configuration the current configuration of the doclet.
0N/A *
0N/A * @return true if this class is linkable and false if we can't link to the
0N/A * desired class.
0N/A */
0N/A public static boolean isLinkable(ClassDoc classDoc,
0N/A Configuration configuration) {
0N/A return
0N/A ((classDoc.isIncluded() && configuration.isGeneratedDoc(classDoc))) ||
0N/A (configuration.extern.isExternal(classDoc) &&
0N/A (classDoc.isPublic() || classDoc.isProtected()));
0N/A }
0N/A
0N/A /**
0N/A * Given a class, return the closest visible super class.
0N/A *
0N/A * @param classDoc the class we are searching the parent for.
0N/A * @param configuration the current configuration of the doclet.
0N/A * @return the closest visible super class. Return null if it cannot
0N/A * be found (i.e. classDoc is java.lang.Object).
0N/A */
0N/A public static Type getFirstVisibleSuperClass(ClassDoc classDoc,
0N/A Configuration configuration) {
0N/A if (classDoc == null) {
0N/A return null;
0N/A }
0N/A Type sup = classDoc.superclassType();
0N/A ClassDoc supClassDoc = classDoc.superclass();
0N/A while (sup != null &&
0N/A (! (supClassDoc.isPublic() ||
0N/A isLinkable(supClassDoc, configuration))) ) {
0N/A if (supClassDoc.superclass().qualifiedName().equals(supClassDoc.qualifiedName()))
0N/A break;
0N/A sup = supClassDoc.superclassType();
0N/A supClassDoc = supClassDoc.superclass();
0N/A }
0N/A if (classDoc.equals(supClassDoc)) {
0N/A return null;
0N/A }
0N/A return sup;
0N/A }
0N/A
0N/A /**
0N/A * Given a class, return the closest visible super class.
0N/A *
0N/A * @param classDoc the class we are searching the parent for.
0N/A * @param configuration the current configuration of the doclet.
0N/A * @return the closest visible super class. Return null if it cannot
0N/A * be found (i.e. classDoc is java.lang.Object).
0N/A */
0N/A public static ClassDoc getFirstVisibleSuperClassCD(ClassDoc classDoc,
0N/A Configuration configuration) {
0N/A if (classDoc == null) {
0N/A return null;
0N/A }
0N/A ClassDoc supClassDoc = classDoc.superclass();
0N/A while (supClassDoc != null &&
0N/A (! (supClassDoc.isPublic() ||
0N/A isLinkable(supClassDoc, configuration))) ) {
0N/A supClassDoc = supClassDoc.superclass();
0N/A }
0N/A if (classDoc.equals(supClassDoc)) {
0N/A return null;
0N/A }
0N/A return supClassDoc;
0N/A }
0N/A
0N/A /**
0N/A * Given a ClassDoc, return the name of its type (Class, Interface, etc.).
0N/A *
0N/A * @param cd the ClassDoc to check.
0N/A * @param lowerCaseOnly true if you want the name returned in lower case.
0N/A * If false, the first letter of the name is capatilized.
0N/A * @return
0N/A */
0N/A public static String getTypeName(Configuration config,
0N/A ClassDoc cd, boolean lowerCaseOnly) {
0N/A String typeName = "";
0N/A if (cd.isOrdinaryClass()) {
0N/A typeName = "doclet.Class";
0N/A } else if (cd.isInterface()) {
0N/A typeName = "doclet.Interface";
0N/A } else if (cd.isException()) {
0N/A typeName = "doclet.Exception";
0N/A } else if (cd.isError()) {
0N/A typeName = "doclet.Error";
0N/A } else if (cd.isAnnotationType()) {
0N/A typeName = "doclet.AnnotationType";
0N/A } else if (cd.isEnum()) {
0N/A typeName = "doclet.Enum";
0N/A }
0N/A return config.getText(
0N/A lowerCaseOnly ? typeName.toLowerCase() : typeName);
0N/A }
0N/A
0N/A /**
0N/A * Given a string, replace all tabs with the appropriate
0N/A * number of spaces.
0N/A * @param tabLength the length of each tab.
0N/A * @param s the String to scan.
0N/A */
909N/A public static void replaceTabs(int tabLength, StringBuilder s) {
909N/A if (whitespace == null || whitespace.length() < tabLength)
909N/A whitespace = String.format("%" + tabLength + "s", " ");
909N/A int index = 0;
909N/A while ((index = s.indexOf("\t", index)) != -1) {
909N/A int spaceCount = tabLength - index % tabLength;
909N/A s.replace(index, index+1, whitespace.substring(0, spaceCount));
909N/A index += spaceCount;
0N/A }
0N/A }
909N/A private static String whitespace;
0N/A
0N/A /**
0N/A * The documentation for values() and valueOf() in Enums are set by the
0N/A * doclet.
0N/A */
0N/A public static void setEnumDocumentation(Configuration configuration,
0N/A ClassDoc classDoc) {
0N/A MethodDoc[] methods = classDoc.methods();
0N/A for (int j = 0; j < methods.length; j++) {
0N/A MethodDoc currentMethod = methods[j];
0N/A if (currentMethod.name().equals("values") &&
0N/A currentMethod.parameters().length == 0) {
0N/A currentMethod.setRawCommentText(
0N/A configuration.getText("doclet.enum_values_doc", classDoc.name()));
0N/A } else if (currentMethod.name().equals("valueOf") &&
0N/A currentMethod.parameters().length == 1) {
0N/A Type paramType = currentMethod.parameters()[0].type();
0N/A if (paramType != null &&
0N/A paramType.qualifiedTypeName().equals(String.class.getName())) {
0N/A currentMethod.setRawCommentText(
0N/A configuration.getText("doclet.enum_valueof_doc"));
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Return true if the given Doc is deprecated.
0N/A *
0N/A * @param doc the Doc to check.
0N/A * @return true if the given Doc is deprecated.
0N/A */
994N/A public static boolean isDeprecated(Doc doc) {
0N/A if (doc.tags("deprecated").length > 0) {
0N/A return true;
0N/A }
994N/A AnnotationDesc[] annotationDescList;
994N/A if (doc instanceof PackageDoc)
994N/A annotationDescList = ((PackageDoc)doc).annotations();
994N/A else
994N/A annotationDescList = ((ProgramElementDoc)doc).annotations();
0N/A for (int i = 0; i < annotationDescList.length; i++) {
0N/A if (annotationDescList[i].annotationType().qualifiedName().equals(
0N/A java.lang.Deprecated.class.getName())){
0N/A return true;
0N/A }
0N/A }
0N/A return false;
0N/A }
1194N/A
1194N/A /**
1194N/A * A convenience method to get property name from the name of the
1194N/A * getter or setter method.
1194N/A * @param name name of the getter or setter method.
1194N/A * @return the name of the property of the given setter of getter.
1194N/A */
1194N/A public static String propertyNameFromMethodName(String name) {
1194N/A String propertyName = null;
1194N/A if (name.startsWith("get") || name.startsWith("set")) {
1194N/A propertyName = name.substring(3);
1194N/A } else if (name.startsWith("is")) {
1194N/A propertyName = name.substring(2);
1194N/A }
1194N/A if ((propertyName == null) || propertyName.isEmpty()){
1194N/A return "";
1194N/A }
1194N/A return propertyName.substring(0, 1).toLowerCase()
1194N/A + propertyName.substring(1);
1194N/A }
0N/A}