1/* 2 * Copyright (c) 1997, 2015, 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.IOException; 29import java.io.InputStream; 30 31import javax.tools.FileObject; 32 33import com.sun.javadoc.*; 34import com.sun.source.util.TreePath; 35import com.sun.tools.javac.code.Attribute; 36import com.sun.tools.javac.code.Symbol; 37import com.sun.tools.javac.code.Symbol.ClassSymbol; 38import com.sun.tools.javac.code.Symbol.PackageSymbol; 39import com.sun.tools.javac.tree.JCTree; 40import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 41import com.sun.tools.javac.util.List; 42import com.sun.tools.javac.util.ListBuffer; 43import com.sun.tools.javac.util.Name; 44import com.sun.tools.javac.util.Position; 45 46import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; 47 48/** 49 * Represents a java package. Provides access to information 50 * about the package, the package's comment and tags, and the 51 * classes in the package. 52 * 53 * <p><b>This is NOT part of any supported API. 54 * If you write code that depends on this, you do so at your own risk. 55 * This code and its internal interfaces are subject to change or 56 * deletion without notice.</b> 57 * 58 * @since 1.2 59 * @author Kaiyang Liu (original) 60 * @author Robert Field (rewrite) 61 * @author Neal Gafter (rewrite) 62 * @author Scott Seligman (package-info.java) 63 */ 64 65@Deprecated 66public class PackageDocImpl extends DocImpl implements PackageDoc { 67 68 public final PackageSymbol sym; 69 private JCCompilationUnit tree = null; // for source position 70 71 public FileObject docPath = null; 72 private boolean foundDoc; // found a doc comment in either 73 // package.html or package-info.java 74 75 boolean isIncluded = false; // Set in RootDocImpl. 76 public boolean setDocPath = false; //Flag to avoid setting doc path multiple times. 77 78 /** 79 * Constructor 80 */ 81 public PackageDocImpl(DocEnv env, PackageSymbol sym) { 82 this(env, sym, null); 83 } 84 85 /** 86 * Constructor 87 */ 88 public PackageDocImpl(DocEnv env, PackageSymbol sym, TreePath treePath) { 89 super(env, treePath); 90 this.sym = sym; 91 this.tree = (treePath == null) ? null : (JCCompilationUnit) treePath.getCompilationUnit(); 92 foundDoc = (documentation != null); 93 } 94 95 void setTree(JCTree tree) { 96 this.tree = (JCCompilationUnit) tree; 97 } 98 99 public void setTreePath(TreePath treePath) { 100 super.setTreePath(treePath); 101 checkDoc(); 102 } 103 104 /** 105 * Do lazy initialization of "documentation" string. 106 */ 107 protected String documentation() { 108 if (documentation != null) 109 return documentation; 110 if (docPath != null) { 111 // read from file 112 try { 113 InputStream s = docPath.openInputStream(); 114 documentation = readHTMLDocumentation(s, docPath); 115 } catch (IOException exc) { 116 documentation = ""; 117 env.error(null, "javadoc.File_Read_Error", docPath.getName()); 118 } 119 } else { 120 // no doc file to be had 121 documentation = ""; 122 } 123 return documentation; 124 } 125 126 /** 127 * Cache of all classes contained in this package, including 128 * member classes of those classes, and their member classes, etc. 129 * Includes only those classes at the specified protection level 130 * and weaker. 131 */ 132 private List<ClassDocImpl> allClassesFiltered = null; 133 134 /** 135 * Cache of all classes contained in this package, including 136 * member classes of those classes, and their member classes, etc. 137 */ 138 private List<ClassDocImpl> allClasses = null; 139 140 /** 141 * Return a list of all classes contained in this package, including 142 * member classes of those classes, and their member classes, etc. 143 */ 144 private List<ClassDocImpl> getClasses(boolean filtered) { 145 if (allClasses != null && !filtered) { 146 return allClasses; 147 } 148 if (allClassesFiltered != null && filtered) { 149 return allClassesFiltered; 150 } 151 ListBuffer<ClassDocImpl> classes = new ListBuffer<>(); 152 for (Symbol enumerated : sym.members().getSymbols(NON_RECURSIVE)) { 153 if (enumerated != null) { 154 ClassSymbol s = (ClassSymbol)enumerated; 155 ClassDocImpl c = env.getClassDoc(s); 156 if (c != null && !c.isSynthetic()) 157 c.addAllClasses(classes, filtered); 158 } 159 } 160 if (filtered) 161 return allClassesFiltered = classes.toList(); 162 else 163 return allClasses = classes.toList(); 164 } 165 166 /** 167 * Add all included classes (including Exceptions and Errors) 168 * and interfaces. 169 */ 170 public void addAllClassesTo(ListBuffer<ClassDocImpl> list) { 171 list.appendList(getClasses(true)); 172 } 173 174 /** 175 * Get all classes (including Exceptions and Errors) 176 * and interfaces. 177 * @since J2SE1.4. 178 * 179 * @return all classes and interfaces in this package, filtered to include 180 * only the included classes if filter==true. 181 */ 182 public ClassDoc[] allClasses(boolean filter) { 183 List<ClassDocImpl> classes = getClasses(filter); 184 return classes.toArray(new ClassDocImpl[classes.length()]); 185 } 186 187 /** 188 * Get all included classes (including Exceptions and Errors) 189 * and interfaces. Same as allClasses(true). 190 * 191 * @return all included classes and interfaces in this package. 192 */ 193 public ClassDoc[] allClasses() { 194 return allClasses(true); 195 } 196 197 /** 198 * Get ordinary classes (that is, exclude exceptions, errors, 199 * enums, interfaces, and annotation types) in this package. 200 * 201 * @return included ordinary classes in this package. 202 */ 203 public ClassDoc[] ordinaryClasses() { 204 ListBuffer<ClassDocImpl> ret = new ListBuffer<>(); 205 for (ClassDocImpl c : getClasses(true)) { 206 if (c.isOrdinaryClass()) { 207 ret.append(c); 208 } 209 } 210 return ret.toArray(new ClassDocImpl[ret.length()]); 211 } 212 213 /** 214 * Get Exception classes in this package. 215 * 216 * @return included Exceptions in this package. 217 */ 218 public ClassDoc[] exceptions() { 219 ListBuffer<ClassDocImpl> ret = new ListBuffer<>(); 220 for (ClassDocImpl c : getClasses(true)) { 221 if (c.isException()) { 222 ret.append(c); 223 } 224 } 225 return ret.toArray(new ClassDocImpl[ret.length()]); 226 } 227 228 /** 229 * Get Error classes in this package. 230 * 231 * @return included Errors in this package. 232 */ 233 public ClassDoc[] errors() { 234 ListBuffer<ClassDocImpl> ret = new ListBuffer<>(); 235 for (ClassDocImpl c : getClasses(true)) { 236 if (c.isError()) { 237 ret.append(c); 238 } 239 } 240 return ret.toArray(new ClassDocImpl[ret.length()]); 241 } 242 243 /** 244 * Get included enum types in this package. 245 * 246 * @return included enum types in this package. 247 */ 248 public ClassDoc[] enums() { 249 ListBuffer<ClassDocImpl> ret = new ListBuffer<>(); 250 for (ClassDocImpl c : getClasses(true)) { 251 if (c.isEnum()) { 252 ret.append(c); 253 } 254 } 255 return ret.toArray(new ClassDocImpl[ret.length()]); 256 } 257 258 /** 259 * Get included interfaces in this package, omitting annotation types. 260 * 261 * @return included interfaces in this package. 262 */ 263 public ClassDoc[] interfaces() { 264 ListBuffer<ClassDocImpl> ret = new ListBuffer<>(); 265 for (ClassDocImpl c : getClasses(true)) { 266 if (c.isInterface()) { 267 ret.append(c); 268 } 269 } 270 return ret.toArray(new ClassDocImpl[ret.length()]); 271 } 272 273 /** 274 * Get included annotation types in this package. 275 * 276 * @return included annotation types in this package. 277 */ 278 public AnnotationTypeDoc[] annotationTypes() { 279 ListBuffer<AnnotationTypeDocImpl> ret = new ListBuffer<>(); 280 for (ClassDocImpl c : getClasses(true)) { 281 if (c.isAnnotationType()) { 282 ret.append((AnnotationTypeDocImpl)c); 283 } 284 } 285 return ret.toArray(new AnnotationTypeDocImpl[ret.length()]); 286 } 287 288 /** 289 * Get the annotations of this package. 290 * Return an empty array if there are none. 291 */ 292 public AnnotationDesc[] annotations() { 293 AnnotationDesc res[] = new AnnotationDesc[sym.getRawAttributes().length()]; 294 int i = 0; 295 for (Attribute.Compound a : sym.getRawAttributes()) { 296 res[i++] = new AnnotationDescImpl(env, a); 297 } 298 return res; 299 } 300 301 302 /** 303 * Lookup for a class within this package. 304 * 305 * @return ClassDocImpl of found class, or null if not found. 306 */ 307 public ClassDoc findClass(String className) { 308 final boolean filtered = true; 309 for (ClassDocImpl c : getClasses(filtered)) { 310 if (c.name().equals(className)) { 311 return c; 312 } 313 } 314 return null; 315 } 316 317 /** 318 * Return true if this package is included in the active set. 319 */ 320 public boolean isIncluded() { 321 return isIncluded; 322 } 323 324 /** 325 * Get package name. 326 * 327 * Note that we do not provide a means of obtaining the simple 328 * name of a package -- package names are always returned in their 329 * uniquely qualified form. 330 */ 331 public String name() { 332 return qualifiedName(); 333 } 334 335 /** 336 * Get package name. 337 */ 338 public String qualifiedName() { 339 if (qualifiedName == null) { 340 Name fullname = sym.getQualifiedName(); 341 // Some bogus tests depend on the interned "" being returned. 342 // See 6457276. 343 qualifiedName = fullname.isEmpty() ? "" : fullname.toString(); 344 } 345 return qualifiedName; 346 } 347 348 private String qualifiedName; 349 350 /** 351 * set doc path for an unzipped directory 352 */ 353 public void setDocPath(FileObject path) { 354 setDocPath = true; 355 if (path == null) 356 return; 357 if (!path.equals(docPath)) { 358 docPath = path; 359 checkDoc(); 360 } 361 } 362 363 // Has checkDoc() sounded off yet? 364 private boolean checkDocWarningEmitted = false; 365 366 /** 367 * Invoked when a source of package doc comments is located. 368 * Emits a diagnostic if this is the second one. 369 */ 370 private void checkDoc() { 371 if (foundDoc) { 372 if (!checkDocWarningEmitted) { 373 env.warning(null, "javadoc.Multiple_package_comments", name()); 374 checkDocWarningEmitted = true; 375 } 376 } else { 377 foundDoc = true; 378 } 379 } 380 381 /** 382 * Return the source position of the entity, or null if 383 * no position is available. 384 */ 385 public SourcePosition position() { 386 return (tree != null) 387 ? SourcePositionImpl.make(tree.sourcefile, tree.pos, tree.lineMap) 388 : SourcePositionImpl.make(docPath, Position.NOPOS, null); 389 } 390} 391