src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java

Tue, 28 Dec 2010 15:54:52 -0800

author
ohair
date
Tue, 28 Dec 2010 15:54:52 -0800
changeset 798
4868a36f6fd8
parent 793
ffbf2b2a8611
child 910
ebf7c13df6c0
permissions
-rw-r--r--

6962318: Update copyright year
Reviewed-by: xdono

duke@1 1 /*
ohair@798 2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
duke@1 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1 4 *
duke@1 5 * This code is free software; you can redistribute it and/or modify it
duke@1 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
duke@1 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
duke@1 10 *
duke@1 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@1 15 * accompanied this code).
duke@1 16 *
duke@1 17 * You should have received a copy of the GNU General Public License version
duke@1 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@1 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
duke@1 24 */
duke@1 25
duke@1 26 package com.sun.tools.doclets.internal.toolkit.util;
duke@1 27
jjg@197 28 import java.io.*;
jjg@197 29 import java.util.*;
jjg@197 30
duke@1 31 import com.sun.javadoc.*;
duke@1 32 import com.sun.tools.doclets.internal.toolkit.*;
duke@1 33
duke@1 34 /**
duke@1 35 * Utilities Class for Doclets.
duke@1 36 *
duke@1 37 * This code is not part of an API.
duke@1 38 * It is implementation that is subject to change.
duke@1 39 * Do not use it as an API
duke@1 40 *
duke@1 41 * @author Atul M Dambalkar
duke@1 42 * @author Jamie Ho
duke@1 43 */
duke@1 44 public class Util {
duke@1 45
duke@1 46 /**
duke@1 47 * A mapping between characters and their
duke@1 48 * corresponding HTML escape character.
duke@1 49 */
duke@1 50 public static final String[][] HTML_ESCAPE_CHARS =
duke@1 51 {{"&", "&amp;"}, {"<", "&lt;"}, {">", "&gt;"}};
duke@1 52
duke@1 53 /**
bpatel@766 54 * Name of the resource directory.
bpatel@766 55 */
bpatel@766 56 public static final String RESOURCESDIR = "resources";
bpatel@766 57
bpatel@766 58 /**
duke@1 59 * Return array of class members whose documentation is to be generated.
duke@1 60 * If the member is deprecated do not include such a member in the
duke@1 61 * returned array.
duke@1 62 *
duke@1 63 * @param members Array of members to choose from.
duke@1 64 * @return ProgramElementDoc[] Array of eligible members for whom
duke@1 65 * documentation is getting generated.
duke@1 66 */
duke@1 67 public static ProgramElementDoc[] excludeDeprecatedMembers(
duke@1 68 ProgramElementDoc[] members) {
duke@1 69 return
duke@1 70 toProgramElementDocArray(excludeDeprecatedMembersAsList(members));
duke@1 71 }
duke@1 72
duke@1 73 /**
duke@1 74 * Return array of class members whose documentation is to be generated.
duke@1 75 * If the member is deprecated do not include such a member in the
duke@1 76 * returned array.
duke@1 77 *
duke@1 78 * @param members Array of members to choose from.
duke@1 79 * @return List List of eligible members for whom
duke@1 80 * documentation is getting generated.
duke@1 81 */
jjg@74 82 public static List<ProgramElementDoc> excludeDeprecatedMembersAsList(
duke@1 83 ProgramElementDoc[] members) {
jjg@74 84 List<ProgramElementDoc> list = new ArrayList<ProgramElementDoc>();
duke@1 85 for (int i = 0; i < members.length; i++) {
duke@1 86 if (members[i].tags("deprecated").length == 0) {
duke@1 87 list.add(members[i]);
duke@1 88 }
duke@1 89 }
duke@1 90 Collections.sort(list);
duke@1 91 return list;
duke@1 92 }
duke@1 93
duke@1 94 /**
duke@1 95 * Return the list of ProgramElementDoc objects as Array.
duke@1 96 */
mcimadamore@184 97 public static ProgramElementDoc[] toProgramElementDocArray(List<ProgramElementDoc> list) {
duke@1 98 ProgramElementDoc[] pgmarr = new ProgramElementDoc[list.size()];
duke@1 99 for (int i = 0; i < list.size(); i++) {
mcimadamore@184 100 pgmarr[i] = list.get(i);
duke@1 101 }
duke@1 102 return pgmarr;
duke@1 103 }
duke@1 104
duke@1 105 /**
duke@1 106 * Return true if a non-public member found in the given array.
duke@1 107 *
duke@1 108 * @param members Array of members to look into.
duke@1 109 * @return boolean True if non-public member found, false otherwise.
duke@1 110 */
duke@1 111 public static boolean nonPublicMemberFound(ProgramElementDoc[] members) {
duke@1 112 for (int i = 0; i < members.length; i++) {
duke@1 113 if (!members[i].isPublic()) {
duke@1 114 return true;
duke@1 115 }
duke@1 116 }
duke@1 117 return false;
duke@1 118 }
duke@1 119
duke@1 120 /**
duke@1 121 * Search for the given method in the given class.
duke@1 122 *
duke@1 123 * @param cd Class to search into.
duke@1 124 * @param method Method to be searched.
duke@1 125 * @return MethodDoc Method found, null otherwise.
duke@1 126 */
duke@1 127 public static MethodDoc findMethod(ClassDoc cd, MethodDoc method) {
duke@1 128 MethodDoc[] methods = cd.methods();
duke@1 129 for (int i = 0; i < methods.length; i++) {
duke@1 130 if (executableMembersEqual(method, methods[i])) {
duke@1 131 return methods[i];
duke@1 132
duke@1 133 }
duke@1 134 }
duke@1 135 return null;
duke@1 136 }
duke@1 137
duke@1 138 /**
duke@1 139 * @param member1 the first method to compare.
duke@1 140 * @param member2 the second method to compare.
duke@1 141 * @return true if member1 overrides/hides or is overriden/hidden by member2.
duke@1 142 */
duke@1 143 public static boolean executableMembersEqual(ExecutableMemberDoc member1,
duke@1 144 ExecutableMemberDoc member2) {
duke@1 145 if (! (member1 instanceof MethodDoc && member2 instanceof MethodDoc))
duke@1 146 return false;
duke@1 147
duke@1 148 MethodDoc method1 = (MethodDoc) member1;
duke@1 149 MethodDoc method2 = (MethodDoc) member2;
duke@1 150 if (method1.isStatic() && method2.isStatic()) {
duke@1 151 Parameter[] targetParams = method1.parameters();
duke@1 152 Parameter[] currentParams;
duke@1 153 if (method1.name().equals(method2.name()) &&
duke@1 154 (currentParams = method2.parameters()).length ==
duke@1 155 targetParams.length) {
duke@1 156 int j;
duke@1 157 for (j = 0; j < targetParams.length; j++) {
duke@1 158 if (! (targetParams[j].typeName().equals(
duke@1 159 currentParams[j].typeName()) ||
duke@1 160 currentParams[j].type() instanceof TypeVariable ||
duke@1 161 targetParams[j].type() instanceof TypeVariable)) {
duke@1 162 break;
duke@1 163 }
duke@1 164 }
duke@1 165 if (j == targetParams.length) {
duke@1 166 return true;
duke@1 167 }
duke@1 168 }
duke@1 169 return false;
duke@1 170 } else {
duke@1 171 return method1.overrides(method2) ||
duke@1 172 method2.overrides(method1) ||
duke@1 173 member1 == member2;
duke@1 174 }
duke@1 175 }
duke@1 176
duke@1 177 /**
duke@1 178 * According to the Java Language Specifications, all the outer classes
duke@1 179 * and static inner classes are core classes.
duke@1 180 */
duke@1 181 public static boolean isCoreClass(ClassDoc cd) {
duke@1 182 return cd.containingClass() == null || cd.isStatic();
duke@1 183 }
duke@1 184
duke@1 185 public static boolean matches(ProgramElementDoc doc1,
duke@1 186 ProgramElementDoc doc2) {
duke@1 187 if (doc1 instanceof ExecutableMemberDoc &&
duke@1 188 doc2 instanceof ExecutableMemberDoc) {
duke@1 189 ExecutableMemberDoc ed1 = (ExecutableMemberDoc)doc1;
duke@1 190 ExecutableMemberDoc ed2 = (ExecutableMemberDoc)doc2;
duke@1 191 return executableMembersEqual(ed1, ed2);
duke@1 192 } else {
duke@1 193 return doc1.name().equals(doc2.name());
duke@1 194 }
duke@1 195 }
duke@1 196
duke@1 197 /**
duke@1 198 * Copy source file to destination file.
duke@1 199 *
duke@1 200 * @throws SecurityException
duke@1 201 * @throws IOException
duke@1 202 */
duke@1 203 public static void copyFile(File destfile, File srcfile)
duke@1 204 throws IOException {
duke@1 205 byte[] bytearr = new byte[512];
duke@1 206 int len = 0;
duke@1 207 FileInputStream input = new FileInputStream(srcfile);
duke@1 208 File destDir = destfile.getParentFile();
duke@1 209 destDir.mkdirs();
duke@1 210 FileOutputStream output = new FileOutputStream(destfile);
duke@1 211 try {
duke@1 212 while ((len = input.read(bytearr)) != -1) {
duke@1 213 output.write(bytearr, 0, len);
bpatel@793 214 }
duke@1 215 } catch (FileNotFoundException exc) {
duke@1 216 } catch (SecurityException exc) {
bpatel@793 217 } finally {
duke@1 218 input.close();
duke@1 219 output.close();
bpatel@793 220 }
duke@1 221 }
duke@1 222
duke@1 223 /**
duke@1 224 * Copy the given directory contents from the source package directory
duke@1 225 * to the generated documentation directory. For example for a package
duke@1 226 * java.lang this method find out the source location of the package using
duke@1 227 * {@link SourcePath} and if given directory is found in the source
duke@1 228 * directory structure, copy the entire directory, to the generated
duke@1 229 * documentation hierarchy.
duke@1 230 *
duke@1 231 * @param configuration The configuration of the current doclet.
duke@1 232 * @param path The relative path to the directory to be copied.
duke@1 233 * @param dir The original directory name to copy from.
duke@1 234 * @param overwrite Overwrite files if true.
duke@1 235 */
duke@1 236 public static void copyDocFiles(Configuration configuration,
duke@1 237 String path, String dir, boolean overwrite) {
duke@1 238 if (checkCopyDocFilesErrors(configuration, path, dir)) {
duke@1 239 return;
duke@1 240 }
duke@1 241 String destname = configuration.docFileDestDirName;
duke@1 242 File srcdir = new File(path + dir);
duke@1 243 if (destname.length() > 0 && !destname.endsWith(
bpatel@766 244 DirectoryManager.URL_FILE_SEPARATOR)) {
bpatel@766 245 destname += DirectoryManager.URL_FILE_SEPARATOR;
duke@1 246 }
duke@1 247 String dest = destname + dir;
duke@1 248 try {
duke@1 249 File destdir = new File(dest);
duke@1 250 DirectoryManager.createDirectory(configuration, dest);
duke@1 251 String[] files = srcdir.list();
duke@1 252 for (int i = 0; i < files.length; i++) {
duke@1 253 File srcfile = new File(srcdir, files[i]);
duke@1 254 File destfile = new File(destdir, files[i]);
duke@1 255 if (srcfile.isFile()) {
duke@1 256 if(destfile.exists() && ! overwrite) {
duke@1 257 configuration.message.warning((SourcePosition) null,
duke@1 258 "doclet.Copy_Overwrite_warning",
duke@1 259 srcfile.toString(), destdir.toString());
duke@1 260 } else {
duke@1 261 configuration.message.notice(
duke@1 262 "doclet.Copying_File_0_To_Dir_1",
duke@1 263 srcfile.toString(), destdir.toString());
duke@1 264 Util.copyFile(destfile, srcfile);
duke@1 265 }
duke@1 266 } else if(srcfile.isDirectory()) {
duke@1 267 if(configuration.copydocfilesubdirs
duke@1 268 && ! configuration.shouldExcludeDocFileDir(
duke@1 269 srcfile.getName())){
duke@1 270 copyDocFiles(configuration, path, dir +
bpatel@766 271 DirectoryManager.URL_FILE_SEPARATOR + srcfile.getName(),
duke@1 272 overwrite);
duke@1 273 }
duke@1 274 }
duke@1 275 }
duke@1 276 } catch (SecurityException exc) {
duke@1 277 throw new DocletAbortException();
duke@1 278 } catch (IOException exc) {
duke@1 279 throw new DocletAbortException();
duke@1 280 }
duke@1 281 }
duke@1 282
duke@1 283 /**
duke@1 284 * Given the parameters for copying doc-files, check for errors.
duke@1 285 *
duke@1 286 * @param configuration The configuration of the current doclet.
duke@1 287 * @param path The relative path to the directory to be copied.
duke@1 288 * @param dirName The original directory name to copy from.
duke@1 289 */
duke@1 290 private static boolean checkCopyDocFilesErrors (Configuration configuration,
duke@1 291 String path, String dirName) {
duke@1 292 if ((configuration.sourcepath == null || configuration.sourcepath.length() == 0) &&
duke@1 293 (configuration.destDirName == null || configuration.destDirName.length() == 0)) {
duke@1 294 //The destination path and source path are definitely equal.
duke@1 295 return true;
duke@1 296 }
duke@1 297 File sourcePath, destPath = new File(configuration.destDirName);
duke@1 298 StringTokenizer pathTokens = new StringTokenizer(
duke@1 299 configuration.sourcepath == null ? "" : configuration.sourcepath,
duke@1 300 File.pathSeparator);
duke@1 301 //Check if the destination path is equal to the source path. If yes,
duke@1 302 //do not copy doc-file directories.
duke@1 303 while(pathTokens.hasMoreTokens()){
duke@1 304 sourcePath = new File(pathTokens.nextToken());
duke@1 305 if(destPath.equals(sourcePath)){
duke@1 306 return true;
duke@1 307 }
duke@1 308 }
duke@1 309 //Make sure the doc-file being copied exists.
duke@1 310 File srcdir = new File(path + dirName);
duke@1 311 if (! srcdir.exists()) {
duke@1 312 return true;
duke@1 313 }
duke@1 314 return false;
duke@1 315 }
duke@1 316
duke@1 317 /**
duke@1 318 * Copy a file in the resources directory to the destination
duke@1 319 * directory (if it is not there already). If
duke@1 320 * <code>overwrite</code> is true and the destination file
duke@1 321 * already exists, overwrite it.
duke@1 322 *
duke@1 323 * @param configuration Holds the destination directory and error message
duke@1 324 * @param resourcefile The name of the resource file to copy
duke@1 325 * @param overwrite A flag to indicate whether the file in the
duke@1 326 * destination directory will be overwritten if
duke@1 327 * it already exists.
duke@1 328 */
duke@1 329 public static void copyResourceFile(Configuration configuration,
bpatel@766 330 String resourcefile, boolean overwrite) {
bpatel@766 331 String destresourcesdir = configuration.destDirName + RESOURCESDIR;
bpatel@766 332 copyFile(configuration, resourcefile, RESOURCESDIR, destresourcesdir,
bpatel@793 333 overwrite, false);
bpatel@766 334 }
bpatel@766 335
bpatel@766 336 /**
bpatel@766 337 * Copy a file from a source directory to a destination directory
bpatel@766 338 * (if it is not there already). If <code>overwrite</code> is true and
bpatel@766 339 * the destination file already exists, overwrite it.
bpatel@766 340 *
bpatel@766 341 * @param configuration Holds the error message
bpatel@766 342 * @param file The name of the file to copy
bpatel@766 343 * @param source The source directory
bpatel@766 344 * @param destination The destination directory where the file needs to be copied
bpatel@766 345 * @param overwrite A flag to indicate whether the file in the
bpatel@766 346 * destination directory will be overwritten if
bpatel@766 347 * it already exists.
bpatel@793 348 * @param replaceNewLine true if the newline needs to be replaced with platform-
bpatel@793 349 * specific newline.
bpatel@766 350 */
bpatel@766 351 public static void copyFile(Configuration configuration, String file, String source,
bpatel@793 352 String destination, boolean overwrite, boolean replaceNewLine) {
bpatel@766 353 DirectoryManager.createDirectory(configuration, destination);
bpatel@766 354 File destfile = new File(destination, file);
duke@1 355 if(destfile.exists() && (! overwrite)) return;
duke@1 356 try {
duke@1 357 InputStream in = Configuration.class.getResourceAsStream(
bpatel@793 358 source + DirectoryManager.URL_FILE_SEPARATOR + file);
duke@1 359 if(in==null) return;
duke@1 360 OutputStream out = new FileOutputStream(destfile);
bpatel@793 361 try {
bpatel@793 362 if (!replaceNewLine) {
bpatel@793 363 byte[] buf = new byte[2048];
bpatel@793 364 int n;
bpatel@793 365 while((n = in.read(buf))>0) out.write(buf,0,n);
bpatel@793 366 } else {
bpatel@793 367 BufferedReader reader = new BufferedReader(new InputStreamReader(in));
bpatel@793 368 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
bpatel@793 369 try {
bpatel@793 370 String line;
bpatel@793 371 while ((line = reader.readLine()) != null) {
bpatel@793 372 writer.write(line);
bpatel@793 373 writer.write(DocletConstants.NL);
bpatel@793 374 }
bpatel@793 375 } finally {
bpatel@793 376 reader.close();
bpatel@793 377 writer.close();
bpatel@793 378 }
bpatel@793 379 }
bpatel@793 380 } finally {
bpatel@793 381 in.close();
bpatel@793 382 out.close();
bpatel@793 383 }
bpatel@793 384 } catch (IOException ie) {
bpatel@793 385 ie.printStackTrace();
bpatel@793 386 throw new DocletAbortException();
bpatel@793 387 }
duke@1 388 }
duke@1 389
duke@1 390 /**
duke@1 391 * Given a PackageDoc, return the source path for that package.
duke@1 392 * @param configuration The Configuration for the current Doclet.
duke@1 393 * @param pkgDoc The package to seach the path for.
duke@1 394 * @return A string representing the path to the given package.
duke@1 395 */
duke@1 396 public static String getPackageSourcePath(Configuration configuration,
duke@1 397 PackageDoc pkgDoc){
duke@1 398 try{
duke@1 399 String pkgPath = DirectoryManager.getDirectoryPath(pkgDoc);
duke@1 400 String completePath = new SourcePath(configuration.sourcepath).
bpatel@766 401 getDirectory(pkgPath) + DirectoryManager.URL_FILE_SEPARATOR;
duke@1 402 //Make sure that both paths are using the same seperators.
duke@1 403 completePath = Util.replaceText(completePath, File.separator,
bpatel@766 404 DirectoryManager.URL_FILE_SEPARATOR);
duke@1 405 pkgPath = Util.replaceText(pkgPath, File.separator,
bpatel@766 406 DirectoryManager.URL_FILE_SEPARATOR);
duke@1 407 return completePath.substring(0, completePath.indexOf(pkgPath));
duke@1 408 } catch (Exception e){
duke@1 409 return "";
duke@1 410 }
duke@1 411 }
duke@1 412
duke@1 413 /**
duke@1 414 * We want the list of types in alphabetical order. However, types are not
duke@1 415 * comparable. We need a comparator for now.
duke@1 416 */
jjg@74 417 private static class TypeComparator implements Comparator<Type> {
jjg@74 418 public int compare(Type type1, Type type2) {
jjg@74 419 return type1.qualifiedTypeName().toLowerCase().compareTo(
jjg@74 420 type2.qualifiedTypeName().toLowerCase());
duke@1 421 }
duke@1 422 }
duke@1 423
duke@1 424 /**
duke@1 425 * For the class return all implemented interfaces including the
duke@1 426 * superinterfaces of the implementing interfaces, also iterate over for
duke@1 427 * all the superclasses. For interface return all the extended interfaces
duke@1 428 * as well as superinterfaces for those extended interfaces.
duke@1 429 *
duke@1 430 * @param type type whose implemented or
duke@1 431 * super interfaces are sought.
duke@1 432 * @param configuration the current configuration of the doclet.
duke@1 433 * @param sort if true, return list of interfaces sorted alphabetically.
duke@1 434 * @return List of all the required interfaces.
duke@1 435 */
jjg@74 436 public static List<Type> getAllInterfaces(Type type,
duke@1 437 Configuration configuration, boolean sort) {
jjg@74 438 Map<ClassDoc,Type> results = sort ? new TreeMap<ClassDoc,Type>() : new LinkedHashMap<ClassDoc,Type>();
duke@1 439 Type[] interfaceTypes = null;
duke@1 440 Type superType = null;
duke@1 441 if (type instanceof ParameterizedType) {
duke@1 442 interfaceTypes = ((ParameterizedType) type).interfaceTypes();
duke@1 443 superType = ((ParameterizedType) type).superclassType();
duke@1 444 } else if (type instanceof ClassDoc) {
duke@1 445 interfaceTypes = ((ClassDoc) type).interfaceTypes();
duke@1 446 superType = ((ClassDoc) type).superclassType();
duke@1 447 } else {
duke@1 448 interfaceTypes = type.asClassDoc().interfaceTypes();
duke@1 449 superType = type.asClassDoc().superclassType();
duke@1 450 }
duke@1 451
duke@1 452 for (int i = 0; i < interfaceTypes.length; i++) {
duke@1 453 Type interfaceType = interfaceTypes[i];
duke@1 454 ClassDoc interfaceClassDoc = interfaceType.asClassDoc();
duke@1 455 if (! (interfaceClassDoc.isPublic() ||
duke@1 456 (configuration == null ||
duke@1 457 isLinkable(interfaceClassDoc, configuration)))) {
duke@1 458 continue;
duke@1 459 }
duke@1 460 results.put(interfaceClassDoc, interfaceType);
mcimadamore@184 461 List<Type> superInterfaces = getAllInterfaces(interfaceType, configuration, sort);
mcimadamore@184 462 for (Iterator<Type> iter = superInterfaces.iterator(); iter.hasNext(); ) {
mcimadamore@184 463 Type t = iter.next();
duke@1 464 results.put(t.asClassDoc(), t);
duke@1 465 }
duke@1 466 }
duke@1 467 if (superType == null)
jjg@74 468 return new ArrayList<Type>(results.values());
duke@1 469 //Try walking the tree.
duke@1 470 addAllInterfaceTypes(results,
duke@1 471 superType,
duke@1 472 superType instanceof ClassDoc ?
duke@1 473 ((ClassDoc) superType).interfaceTypes() :
duke@1 474 ((ParameterizedType) superType).interfaceTypes(),
duke@1 475 false, configuration);
jjg@74 476 List<Type> resultsList = new ArrayList<Type>(results.values());
duke@1 477 if (sort) {
duke@1 478 Collections.sort(resultsList, new TypeComparator());
duke@1 479 }
duke@1 480 return resultsList;
duke@1 481 }
duke@1 482
mcimadamore@184 483 public static List<Type> getAllInterfaces(Type type, Configuration configuration) {
duke@1 484 return getAllInterfaces(type, configuration, true);
duke@1 485 }
duke@1 486
jjg@74 487 private static void findAllInterfaceTypes(Map<ClassDoc,Type> results, ClassDoc c, boolean raw,
duke@1 488 Configuration configuration) {
duke@1 489 Type superType = c.superclassType();
duke@1 490 if (superType == null)
duke@1 491 return;
duke@1 492 addAllInterfaceTypes(results, superType,
duke@1 493 superType instanceof ClassDoc ?
duke@1 494 ((ClassDoc) superType).interfaceTypes() :
duke@1 495 ((ParameterizedType) superType).interfaceTypes(),
duke@1 496 raw, configuration);
duke@1 497 }
duke@1 498
jjg@74 499 private static void findAllInterfaceTypes(Map<ClassDoc,Type> results, ParameterizedType p,
duke@1 500 Configuration configuration) {
duke@1 501 Type superType = p.superclassType();
duke@1 502 if (superType == null)
duke@1 503 return;
duke@1 504 addAllInterfaceTypes(results, superType,
duke@1 505 superType instanceof ClassDoc ?
duke@1 506 ((ClassDoc) superType).interfaceTypes() :
duke@1 507 ((ParameterizedType) superType).interfaceTypes(),
duke@1 508 false, configuration);
duke@1 509 }
duke@1 510
jjg@74 511 private static void addAllInterfaceTypes(Map<ClassDoc,Type> results, Type type,
duke@1 512 Type[] interfaceTypes, boolean raw,
duke@1 513 Configuration configuration) {
duke@1 514 for (int i = 0; i < interfaceTypes.length; i++) {
duke@1 515 Type interfaceType = interfaceTypes[i];
duke@1 516 ClassDoc interfaceClassDoc = interfaceType.asClassDoc();
duke@1 517 if (! (interfaceClassDoc.isPublic() ||
duke@1 518 (configuration != null &&
duke@1 519 isLinkable(interfaceClassDoc, configuration)))) {
duke@1 520 continue;
duke@1 521 }
duke@1 522 if (raw)
duke@1 523 interfaceType = interfaceType.asClassDoc();
duke@1 524 results.put(interfaceClassDoc, interfaceType);
mcimadamore@184 525 List<Type> superInterfaces = getAllInterfaces(interfaceType, configuration);
mcimadamore@184 526 for (Iterator<Type> iter = superInterfaces.iterator(); iter.hasNext(); ) {
mcimadamore@184 527 Type superInterface = iter.next();
duke@1 528 results.put(superInterface.asClassDoc(), superInterface);
duke@1 529 }
duke@1 530 }
duke@1 531 if (type instanceof ParameterizedType)
duke@1 532 findAllInterfaceTypes(results, (ParameterizedType) type, configuration);
duke@1 533 else if (((ClassDoc) type).typeParameters().length == 0)
duke@1 534 findAllInterfaceTypes(results, (ClassDoc) type, raw, configuration);
duke@1 535 else
duke@1 536 findAllInterfaceTypes(results, (ClassDoc) type, true, configuration);
duke@1 537 }
duke@1 538
duke@1 539
mcimadamore@184 540 public static <T extends ProgramElementDoc> List<T> asList(T[] members) {
mcimadamore@184 541 List<T> list = new ArrayList<T>();
duke@1 542 for (int i = 0; i < members.length; i++) {
duke@1 543 list.add(members[i]);
duke@1 544 }
duke@1 545 return list;
duke@1 546 }
duke@1 547
duke@1 548 /**
duke@1 549 * Enclose in quotes, used for paths and filenames that contains spaces
duke@1 550 */
duke@1 551 public static String quote(String filepath) {
duke@1 552 return ("\"" + filepath + "\"");
duke@1 553 }
duke@1 554
duke@1 555 /**
duke@1 556 * Given a package, return it's name.
duke@1 557 * @param packageDoc the package to check.
duke@1 558 * @return the name of the given package.
duke@1 559 */
duke@1 560 public static String getPackageName(PackageDoc packageDoc) {
duke@1 561 return packageDoc == null || packageDoc.name().length() == 0 ?
duke@1 562 DocletConstants.DEFAULT_PACKAGE_NAME : packageDoc.name();
duke@1 563 }
duke@1 564
duke@1 565 /**
duke@1 566 * Given a package, return it's file name without the extension.
duke@1 567 * @param packageDoc the package to check.
duke@1 568 * @return the file name of the given package.
duke@1 569 */
duke@1 570 public static String getPackageFileHeadName(PackageDoc packageDoc) {
duke@1 571 return packageDoc == null || packageDoc.name().length() == 0 ?
duke@1 572 DocletConstants.DEFAULT_PACKAGE_FILE_NAME : packageDoc.name();
duke@1 573 }
duke@1 574
duke@1 575 /**
duke@1 576 * Given a string, replace all occurraces of 'newStr' with 'oldStr'.
duke@1 577 * @param originalStr the string to modify.
duke@1 578 * @param oldStr the string to replace.
duke@1 579 * @param newStr the string to insert in place of the old string.
duke@1 580 */
duke@1 581 public static String replaceText(String originalStr, String oldStr,
duke@1 582 String newStr) {
duke@1 583 if (oldStr == null || newStr == null || oldStr.equals(newStr)) {
duke@1 584 return originalStr;
duke@1 585 }
duke@1 586 StringBuffer result = new StringBuffer(originalStr);
duke@1 587 int startIndex = 0;
duke@1 588 while ((startIndex = result.indexOf(oldStr, startIndex)) != -1) {
duke@1 589 result = result.replace(startIndex, startIndex + oldStr.length(),
duke@1 590 newStr);
duke@1 591 startIndex += newStr.length();
duke@1 592 }
duke@1 593 return result.toString();
duke@1 594 }
duke@1 595
duke@1 596 /**
duke@1 597 * Given a string, escape all special html characters and
duke@1 598 * return the result.
duke@1 599 *
duke@1 600 * @param s The string to check.
duke@1 601 * @return the original string with all of the HTML characters
duke@1 602 * escaped.
duke@1 603 *
duke@1 604 * @see #HTML_ESCAPE_CHARS
duke@1 605 */
duke@1 606 public static String escapeHtmlChars(String s) {
duke@1 607 String result = s;
duke@1 608 for (int i = 0; i < HTML_ESCAPE_CHARS.length; i++) {
duke@1 609 result = Util.replaceText(result,
duke@1 610 HTML_ESCAPE_CHARS[i][0], HTML_ESCAPE_CHARS[i][1]);
duke@1 611 }
duke@1 612 return result;
duke@1 613 }
duke@1 614
duke@1 615 /**
bpatel@766 616 * Given a string, strips all html characters and
bpatel@766 617 * return the result.
bpatel@766 618 *
bpatel@766 619 * @param rawString The string to check.
bpatel@766 620 * @return the original string with all of the HTML characters
bpatel@766 621 * stripped.
bpatel@766 622 *
bpatel@766 623 */
bpatel@766 624 public static String stripHtml(String rawString) {
bpatel@766 625 // remove HTML tags
bpatel@766 626 rawString = rawString.replaceAll("\\<.*?>", " ");
bpatel@766 627 // consolidate multiple spaces between a word to a single space
bpatel@766 628 rawString = rawString.replaceAll("\\b\\s{2,}\\b", " ");
bpatel@766 629 // remove extra whitespaces
bpatel@766 630 return rawString.trim();
bpatel@766 631 }
bpatel@766 632
bpatel@766 633 /**
duke@1 634 * Create the directory path for the file to be generated, construct
duke@1 635 * FileOutputStream and OutputStreamWriter depending upon docencoding.
duke@1 636 *
duke@1 637 * @param path The directory path to be created for this file.
duke@1 638 * @param filename File Name to which the PrintWriter will do the Output.
duke@1 639 * @param docencoding Encoding to be used for this file.
duke@1 640 * @exception IOException Exception raised by the FileWriter is passed on
duke@1 641 * to next level.
jjg@197 642 * @exception UnsupportedEncodingException Exception raised by the
duke@1 643 * OutputStreamWriter is passed on to next level.
duke@1 644 * @return Writer Writer for the file getting generated.
duke@1 645 * @see java.io.FileOutputStream
duke@1 646 * @see java.io.OutputStreamWriter
duke@1 647 */
duke@1 648 public static Writer genWriter(Configuration configuration,
duke@1 649 String path, String filename,
duke@1 650 String docencoding)
duke@1 651 throws IOException, UnsupportedEncodingException {
duke@1 652 FileOutputStream fos;
duke@1 653 if (path != null) {
duke@1 654 DirectoryManager.createDirectory(configuration, path);
duke@1 655 fos = new FileOutputStream(((path.length() > 0)?
duke@1 656 path + File.separator: "") + filename);
duke@1 657 } else {
duke@1 658 fos = new FileOutputStream(filename);
duke@1 659 }
duke@1 660 if (docencoding == null) {
jjg@197 661 return new OutputStreamWriter(fos);
duke@1 662 } else {
duke@1 663 return new OutputStreamWriter(fos, docencoding);
duke@1 664 }
duke@1 665 }
duke@1 666
duke@1 667 /**
duke@1 668 * Given an annotation, return true if it should be documented and false
duke@1 669 * otherwise.
duke@1 670 *
duke@1 671 * @param annotationDoc the annotation to check.
duke@1 672 *
duke@1 673 * @return true return true if it should be documented and false otherwise.
duke@1 674 */
duke@1 675 public static boolean isDocumentedAnnotation(AnnotationTypeDoc annotationDoc) {
duke@1 676 AnnotationDesc[] annotationDescList = annotationDoc.annotations();
duke@1 677 for (int i = 0; i < annotationDescList.length; i++) {
duke@1 678 if (annotationDescList[i].annotationType().qualifiedName().equals(
duke@1 679 java.lang.annotation.Documented.class.getName())){
duke@1 680 return true;
duke@1 681 }
duke@1 682 }
duke@1 683 return false;
duke@1 684 }
duke@1 685
duke@1 686 /**
duke@1 687 * Given a string, return an array of tokens. The separator can be escaped
duke@1 688 * with the '\' character. The '\' character may also be escaped by the
duke@1 689 * '\' character.
duke@1 690 *
duke@1 691 * @param s the string to tokenize.
duke@1 692 * @param separator the separator char.
duke@1 693 * @param maxTokens the maxmimum number of tokens returned. If the
duke@1 694 * max is reached, the remaining part of s is appended
duke@1 695 * to the end of the last token.
duke@1 696 *
duke@1 697 * @return an array of tokens.
duke@1 698 */
duke@1 699 public static String[] tokenize(String s, char separator, int maxTokens) {
jjg@74 700 List<String> tokens = new ArrayList<String>();
duke@1 701 StringBuilder token = new StringBuilder ();
duke@1 702 boolean prevIsEscapeChar = false;
duke@1 703 for (int i = 0; i < s.length(); i += Character.charCount(i)) {
duke@1 704 int currentChar = s.codePointAt(i);
duke@1 705 if (prevIsEscapeChar) {
duke@1 706 // Case 1: escaped character
duke@1 707 token.appendCodePoint(currentChar);
duke@1 708 prevIsEscapeChar = false;
duke@1 709 } else if (currentChar == separator && tokens.size() < maxTokens-1) {
duke@1 710 // Case 2: separator
duke@1 711 tokens.add(token.toString());
duke@1 712 token = new StringBuilder();
duke@1 713 } else if (currentChar == '\\') {
duke@1 714 // Case 3: escape character
duke@1 715 prevIsEscapeChar = true;
duke@1 716 } else {
duke@1 717 // Case 4: regular character
duke@1 718 token.appendCodePoint(currentChar);
duke@1 719 }
duke@1 720 }
duke@1 721 if (token.length() > 0) {
duke@1 722 tokens.add(token.toString());
duke@1 723 }
jjg@74 724 return tokens.toArray(new String[] {});
duke@1 725 }
duke@1 726
duke@1 727 /**
duke@1 728 * Return true if this class is linkable and false if we can't link to the
duke@1 729 * desired class.
duke@1 730 * <br>
duke@1 731 * <b>NOTE:</b> You can only link to external classes if they are public or
duke@1 732 * protected.
duke@1 733 *
duke@1 734 * @param classDoc the class to check.
duke@1 735 * @param configuration the current configuration of the doclet.
duke@1 736 *
duke@1 737 * @return true if this class is linkable and false if we can't link to the
duke@1 738 * desired class.
duke@1 739 */
duke@1 740 public static boolean isLinkable(ClassDoc classDoc,
duke@1 741 Configuration configuration) {
duke@1 742 return
duke@1 743 ((classDoc.isIncluded() && configuration.isGeneratedDoc(classDoc))) ||
duke@1 744 (configuration.extern.isExternal(classDoc) &&
duke@1 745 (classDoc.isPublic() || classDoc.isProtected()));
duke@1 746 }
duke@1 747
duke@1 748 /**
duke@1 749 * Given a class, return the closest visible super class.
duke@1 750 *
duke@1 751 * @param classDoc the class we are searching the parent for.
duke@1 752 * @param configuration the current configuration of the doclet.
duke@1 753 * @return the closest visible super class. Return null if it cannot
duke@1 754 * be found (i.e. classDoc is java.lang.Object).
duke@1 755 */
duke@1 756 public static Type getFirstVisibleSuperClass(ClassDoc classDoc,
duke@1 757 Configuration configuration) {
duke@1 758 if (classDoc == null) {
duke@1 759 return null;
duke@1 760 }
duke@1 761 Type sup = classDoc.superclassType();
duke@1 762 ClassDoc supClassDoc = classDoc.superclass();
duke@1 763 while (sup != null &&
duke@1 764 (! (supClassDoc.isPublic() ||
duke@1 765 isLinkable(supClassDoc, configuration))) ) {
duke@1 766 if (supClassDoc.superclass().qualifiedName().equals(supClassDoc.qualifiedName()))
duke@1 767 break;
duke@1 768 sup = supClassDoc.superclassType();
duke@1 769 supClassDoc = supClassDoc.superclass();
duke@1 770 }
duke@1 771 if (classDoc.equals(supClassDoc)) {
duke@1 772 return null;
duke@1 773 }
duke@1 774 return sup;
duke@1 775 }
duke@1 776
duke@1 777 /**
duke@1 778 * Given a class, return the closest visible super class.
duke@1 779 *
duke@1 780 * @param classDoc the class we are searching the parent for.
duke@1 781 * @param configuration the current configuration of the doclet.
duke@1 782 * @return the closest visible super class. Return null if it cannot
duke@1 783 * be found (i.e. classDoc is java.lang.Object).
duke@1 784 */
duke@1 785 public static ClassDoc getFirstVisibleSuperClassCD(ClassDoc classDoc,
duke@1 786 Configuration configuration) {
duke@1 787 if (classDoc == null) {
duke@1 788 return null;
duke@1 789 }
duke@1 790 ClassDoc supClassDoc = classDoc.superclass();
duke@1 791 while (supClassDoc != null &&
duke@1 792 (! (supClassDoc.isPublic() ||
duke@1 793 isLinkable(supClassDoc, configuration))) ) {
duke@1 794 supClassDoc = supClassDoc.superclass();
duke@1 795 }
duke@1 796 if (classDoc.equals(supClassDoc)) {
duke@1 797 return null;
duke@1 798 }
duke@1 799 return supClassDoc;
duke@1 800 }
duke@1 801
duke@1 802 /**
duke@1 803 * Given a ClassDoc, return the name of its type (Class, Interface, etc.).
duke@1 804 *
duke@1 805 * @param cd the ClassDoc to check.
duke@1 806 * @param lowerCaseOnly true if you want the name returned in lower case.
duke@1 807 * If false, the first letter of the name is capatilized.
duke@1 808 * @return
duke@1 809 */
duke@1 810 public static String getTypeName(Configuration config,
duke@1 811 ClassDoc cd, boolean lowerCaseOnly) {
duke@1 812 String typeName = "";
duke@1 813 if (cd.isOrdinaryClass()) {
duke@1 814 typeName = "doclet.Class";
duke@1 815 } else if (cd.isInterface()) {
duke@1 816 typeName = "doclet.Interface";
duke@1 817 } else if (cd.isException()) {
duke@1 818 typeName = "doclet.Exception";
duke@1 819 } else if (cd.isError()) {
duke@1 820 typeName = "doclet.Error";
duke@1 821 } else if (cd.isAnnotationType()) {
duke@1 822 typeName = "doclet.AnnotationType";
duke@1 823 } else if (cd.isEnum()) {
duke@1 824 typeName = "doclet.Enum";
duke@1 825 }
duke@1 826 return config.getText(
duke@1 827 lowerCaseOnly ? typeName.toLowerCase() : typeName);
duke@1 828 }
duke@1 829
duke@1 830 /**
duke@1 831 * Given a string, replace all tabs with the appropriate
duke@1 832 * number of spaces.
duke@1 833 * @param tabLength the length of each tab.
duke@1 834 * @param s the String to scan.
duke@1 835 */
duke@1 836 public static void replaceTabs(int tabLength, StringBuffer s) {
duke@1 837 int index, col;
duke@1 838 StringBuffer whitespace;
duke@1 839 while ((index = s.indexOf("\t")) != -1) {
duke@1 840 whitespace = new StringBuffer();
duke@1 841 col = index;
duke@1 842 do {
duke@1 843 whitespace.append(" ");
duke@1 844 col++;
duke@1 845 } while ((col%tabLength) != 0);
duke@1 846 s.replace(index, index+1, whitespace.toString());
duke@1 847 }
duke@1 848 }
duke@1 849
duke@1 850 /**
duke@1 851 * The documentation for values() and valueOf() in Enums are set by the
duke@1 852 * doclet.
duke@1 853 */
duke@1 854 public static void setEnumDocumentation(Configuration configuration,
duke@1 855 ClassDoc classDoc) {
duke@1 856 MethodDoc[] methods = classDoc.methods();
duke@1 857 for (int j = 0; j < methods.length; j++) {
duke@1 858 MethodDoc currentMethod = methods[j];
duke@1 859 if (currentMethod.name().equals("values") &&
duke@1 860 currentMethod.parameters().length == 0) {
duke@1 861 currentMethod.setRawCommentText(
duke@1 862 configuration.getText("doclet.enum_values_doc", classDoc.name()));
duke@1 863 } else if (currentMethod.name().equals("valueOf") &&
duke@1 864 currentMethod.parameters().length == 1) {
duke@1 865 Type paramType = currentMethod.parameters()[0].type();
duke@1 866 if (paramType != null &&
duke@1 867 paramType.qualifiedTypeName().equals(String.class.getName())) {
duke@1 868 currentMethod.setRawCommentText(
duke@1 869 configuration.getText("doclet.enum_valueof_doc"));
duke@1 870 }
duke@1 871 }
duke@1 872 }
duke@1 873 }
duke@1 874
duke@1 875 /**
duke@1 876 * Return true if the given Doc is deprecated.
duke@1 877 *
duke@1 878 * @param doc the Doc to check.
duke@1 879 * @return true if the given Doc is deprecated.
duke@1 880 */
duke@1 881 public static boolean isDeprecated(ProgramElementDoc doc) {
duke@1 882 if (doc.tags("deprecated").length > 0) {
duke@1 883 return true;
duke@1 884 }
duke@1 885 AnnotationDesc[] annotationDescList = doc.annotations();
duke@1 886 for (int i = 0; i < annotationDescList.length; i++) {
duke@1 887 if (annotationDescList[i].annotationType().qualifiedName().equals(
duke@1 888 java.lang.Deprecated.class.getName())){
duke@1 889 return true;
duke@1 890 }
duke@1 891 }
duke@1 892 return false;
duke@1 893 }
duke@1 894 }

mercurial