1/* 2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.javadoc.main; 27 28import java.io.DataInputStream; 29import java.io.IOException; 30import java.io.InputStream; 31import java.text.CollationKey; 32import java.util.regex.Matcher; 33import java.util.regex.Pattern; 34 35import javax.tools.FileObject; 36 37import com.sun.javadoc.*; 38import com.sun.source.util.TreePath; 39import com.sun.tools.doclets.internal.toolkit.util.DocletAbortException; 40import com.sun.tools.doclets.internal.toolkit.util.FatalError; 41import com.sun.tools.javac.tree.JCTree; 42import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 43import com.sun.tools.javac.util.Position; 44 45/** 46 * abstract base class of all Doc classes. Doc item's are representations 47 * of java language constructs (class, package, method,...) which have 48 * comments and have been processed by this run of javadoc. All Doc items 49 * are unique, that is, they are == comparable. 50 * 51 * <p><b>This is NOT part of any supported API. 52 * If you write code that depends on this, you do so at your own risk. 53 * This code and its internal interfaces are subject to change or 54 * deletion without notice.</b> 55 * 56 * @since 1.2 57 * @author Robert Field 58 * @author Atul M Dambalkar 59 * @author Neal Gafter (rewrite) 60 */ 61@Deprecated 62public abstract class DocImpl implements Doc, Comparable<Object> { 63 64 /** 65 * Doc environment 66 */ 67 protected final DocEnv env; //### Rename this everywhere to 'docenv' ? 68 69 /** 70 * Back pointer to the tree node for this doc item. 71 * May be null if there is no associated tree. 72 */ 73 protected TreePath treePath; 74 75 /** 76 * The complex comment object, lazily initialized. 77 */ 78 private Comment comment; 79 80 /** 81 * The cached sort key, to take care of Natural Language Text sorting. 82 */ 83 private CollationKey collationkey = null; 84 85 /** 86 * Raw documentation string. 87 */ 88 protected String documentation; // Accessed in PackageDocImpl, RootDocImpl 89 90 /** 91 * Cached first sentence. 92 */ 93 private Tag[] firstSentence; 94 95 /** 96 * Cached inline tags. 97 */ 98 private Tag[] inlineTags; 99 100 /** 101 * Constructor. 102 */ 103 DocImpl(DocEnv env, TreePath treePath) { 104 this.treePath = treePath; 105 this.documentation = getCommentText(treePath); 106 this.env = env; 107 } 108 109 private static String getCommentText(TreePath p) { 110 if (p == null) 111 return null; 112 113 JCCompilationUnit topLevel = (JCCompilationUnit) p.getCompilationUnit(); 114 JCTree tree = (JCTree) p.getLeaf(); 115 return topLevel.docComments.getCommentText(tree); 116 } 117 118 /** 119 * So subclasses have the option to do lazy initialization of 120 * "documentation" string. 121 */ 122 protected String documentation() { 123 if (documentation == null) documentation = ""; 124 return documentation; 125 } 126 127 /** 128 * For lazy initialization of comment. 129 */ 130 Comment comment() { 131 if (comment == null) { 132 String d = documentation(); 133 if (env.javaScriptScanner != null) { 134 env.javaScriptScanner.parse(d, new JavaScriptScanner.Reporter() { 135 @Override 136 public void report() { 137 env.error(DocImpl.this, "javadoc.JavaScript_in_comment"); 138 throw new FatalError(); 139 } 140 }); 141 } 142 if (env.doclint != null 143 && treePath != null 144 && env.shouldCheck(treePath.getCompilationUnit()) 145 && d.equals(getCommentText(treePath))) { 146 env.doclint.scan(treePath); 147 } 148 comment = new Comment(this, d); 149 } 150 return comment; 151 } 152 153 /** 154 * Return the text of the comment for this doc item. 155 * TagImpls have been removed. 156 */ 157 public String commentText() { 158 return comment().commentText(); 159 } 160 161 /** 162 * Return all tags in this Doc item. 163 * 164 * @return an array of TagImpl containing all tags on this Doc item. 165 */ 166 public Tag[] tags() { 167 return comment().tags(); 168 } 169 170 /** 171 * Return tags of the specified kind in this Doc item. 172 * 173 * @param tagname name of the tag kind to search for. 174 * @return an array of TagImpl containing all tags whose 'kind()' 175 * matches 'tagname'. 176 */ 177 public Tag[] tags(String tagname) { 178 return comment().tags(tagname); 179 } 180 181 /** 182 * Return the see also tags in this Doc item. 183 * 184 * @return an array of SeeTag containing all @see tags. 185 */ 186 public SeeTag[] seeTags() { 187 return comment().seeTags(); 188 } 189 190 public Tag[] inlineTags() { 191 if (inlineTags == null) { 192 inlineTags = Comment.getInlineTags(this, commentText()); 193 } 194 return inlineTags; 195 } 196 197 public Tag[] firstSentenceTags() { 198 if (firstSentence == null) { 199 //Parse all sentences first to avoid duplicate warnings. 200 inlineTags(); 201 try { 202 env.setSilent(true); 203 firstSentence = Comment.firstSentenceTags(this, commentText()); 204 } finally { 205 env.setSilent(false); 206 } 207 } 208 return firstSentence; 209 } 210 211 /** 212 * Utility for subclasses which read HTML documentation files. 213 */ 214 String readHTMLDocumentation(InputStream input, FileObject filename) throws IOException { 215 byte[] filecontents = new byte[input.available()]; 216 try { 217 DataInputStream dataIn = new DataInputStream(input); 218 dataIn.readFully(filecontents); 219 } finally { 220 input.close(); 221 } 222 String encoding = env.getEncoding(); 223 String rawDoc = (encoding!=null) 224 ? new String(filecontents, encoding) 225 : new String(filecontents); 226 Pattern bodyPat = Pattern.compile("(?is).*<body\\b[^>]*>(.*)</body\\b.*"); 227 Matcher m = bodyPat.matcher(rawDoc); 228 if (m.matches()) { 229 return m.group(1); 230 } else { 231 String key = rawDoc.matches("(?is).*<body\\b.*") 232 ? "javadoc.End_body_missing_from_html_file" 233 : "javadoc.Body_missing_from_html_file"; 234 env.error(SourcePositionImpl.make(filename, Position.NOPOS, null), key); 235 return ""; 236 } 237 } 238 239 /** 240 * Return the full unprocessed text of the comment. Tags 241 * are included as text. Used mainly for store and retrieve 242 * operations like internalization. 243 */ 244 public String getRawCommentText() { 245 return documentation(); 246 } 247 248 /** 249 * Set the full unprocessed text of the comment. Tags 250 * are included as text. Used mainly for store and retrieve 251 * operations like internalization. 252 */ 253 public void setRawCommentText(String rawDocumentation) { 254 treePath = null; 255 documentation = rawDocumentation; 256 comment = null; 257 } 258 259 /** 260 * Set the full unprocessed text of the comment and tree path. 261 */ 262 void setTreePath(TreePath treePath) { 263 this.treePath = treePath; 264 documentation = getCommentText(treePath); 265 comment = null; 266 } 267 268 /** 269 * return a key for sorting. 270 */ 271 CollationKey key() { 272 if (collationkey == null) { 273 collationkey = generateKey(); 274 } 275 return collationkey; 276 } 277 278 /** 279 * Generate a key for sorting. 280 * <p> 281 * Default is name(). 282 */ 283 CollationKey generateKey() { 284 String k = name(); 285 // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\""); 286 return env.doclocale.collator.getCollationKey(k); 287 } 288 289 /** 290 * Returns a string representation of this Doc item. 291 */ 292 @Override 293 public String toString() { 294 return qualifiedName(); 295 } 296 297 /** 298 * Returns the name of this Doc item. 299 * 300 * @return the name 301 */ 302 public abstract String name(); 303 304 /** 305 * Returns the qualified name of this Doc item. 306 * 307 * @return the name 308 */ 309 public abstract String qualifiedName(); 310 311 /** 312 * Compares this Object with the specified Object for order. Returns a 313 * negative integer, zero, or a positive integer as this Object is less 314 * than, equal to, or greater than the given Object. 315 * <p> 316 * Included so that Doc item are java.lang.Comparable. 317 * 318 * @param obj the {@code Object} to be compared. 319 * @return a negative integer, zero, or a positive integer as this Object 320 * is less than, equal to, or greater than the given Object. 321 * @exception ClassCastException the specified Object's type prevents it 322 * from being compared to this Object. 323 */ 324 public int compareTo(Object obj) { 325 // System.out.println("COMPARE \"" + this + "\" to \"" + obj + "\" = " + key().compareTo(((DocImpl)obj).key())); 326 return key().compareTo(((DocImpl)obj).key()); 327 } 328 329 /** 330 * Is this Doc item a field? False until overridden. 331 * 332 * @return true if it represents a field 333 */ 334 public boolean isField() { 335 return false; 336 } 337 338 /** 339 * Is this Doc item an enum constant? False until overridden. 340 * 341 * @return true if it represents an enum constant 342 */ 343 public boolean isEnumConstant() { 344 return false; 345 } 346 347 /** 348 * Is this Doc item a constructor? False until overridden. 349 * 350 * @return true if it represents a constructor 351 */ 352 public boolean isConstructor() { 353 return false; 354 } 355 356 /** 357 * Is this Doc item a method (but not a constructor or annotation 358 * type element)? 359 * False until overridden. 360 * 361 * @return true if it represents a method 362 */ 363 public boolean isMethod() { 364 return false; 365 } 366 367 /** 368 * Is this Doc item an annotation type element? 369 * False until overridden. 370 * 371 * @return true if it represents an annotation type element 372 */ 373 public boolean isAnnotationTypeElement() { 374 return false; 375 } 376 377 /** 378 * Is this Doc item a interface (but not an annotation type)? 379 * False until overridden. 380 * 381 * @return true if it represents a interface 382 */ 383 public boolean isInterface() { 384 return false; 385 } 386 387 /** 388 * Is this Doc item a exception class? False until overridden. 389 * 390 * @return true if it represents a exception 391 */ 392 public boolean isException() { 393 return false; 394 } 395 396 /** 397 * Is this Doc item a error class? False until overridden. 398 * 399 * @return true if it represents a error 400 */ 401 public boolean isError() { 402 return false; 403 } 404 405 /** 406 * Is this Doc item an enum type? False until overridden. 407 * 408 * @return true if it represents an enum type 409 */ 410 public boolean isEnum() { 411 return false; 412 } 413 414 /** 415 * Is this Doc item an annotation type? False until overridden. 416 * 417 * @return true if it represents an annotation type 418 */ 419 public boolean isAnnotationType() { 420 return false; 421 } 422 423 /** 424 * Is this Doc item an ordinary class (i.e. not an interface, 425 * annotation type, enumeration, exception, or error)? 426 * False until overridden. 427 * 428 * @return true if it represents an ordinary class 429 */ 430 public boolean isOrdinaryClass() { 431 return false; 432 } 433 434 /** 435 * Is this Doc item a class 436 * (and not an interface or annotation type)? 437 * This includes ordinary classes, enums, errors and exceptions. 438 * False until overridden. 439 * 440 * @return true if it represents a class 441 */ 442 public boolean isClass() { 443 return false; 444 } 445 446 /** 447 * return true if this Doc is include in the active set. 448 */ 449 public abstract boolean isIncluded(); 450 451 /** 452 * Return the source position of the entity, or null if 453 * no position is available. 454 */ 455 public SourcePosition position() { return null; } 456} 457