Package.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /* Package.java -- information about a package
  2. Copyright (C) 2000, 2001, 2002, 2003, 2005, 2006
  3. Free Software Foundation, Inc.
  4. This file is part of GNU Classpath.
  5. GNU Classpath is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. GNU Classpath is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GNU Classpath; see the file COPYING. If not, write to the
  15. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. 02110-1301 USA.
  17. Linking this library statically or dynamically with other modules is
  18. making a combined work based on this library. Thus, the terms and
  19. conditions of the GNU General Public License cover the whole
  20. combination.
  21. As a special exception, the copyright holders of this library give you
  22. permission to link this library with independent modules to produce an
  23. executable, regardless of the license terms of these independent
  24. modules, and to copy and distribute the resulting executable under
  25. terms of your choice, provided that you also meet, for each linked
  26. independent module, the terms and conditions of the license of that
  27. module. An independent module is a module which is not derived from
  28. or based on this library. If you modify this library, you may extend
  29. this exception to your version of the library, but you are not
  30. obligated to do so. If you do not wish to do so, delete this
  31. exception statement from your version. */
  32. package java.lang;
  33. import gnu.classpath.VMStackWalker;
  34. import java.lang.annotation.Annotation;
  35. import java.lang.reflect.AnnotatedElement;
  36. import java.net.URL;
  37. import java.util.NoSuchElementException;
  38. import java.util.StringTokenizer;
  39. /**
  40. * Everything you ever wanted to know about a package. This class makes it
  41. * possible to attach specification and implementation information to a
  42. * package as explained in the
  43. * <a href="http://java.sun.com/products/jdk/1.3/docs/guide/versioning/spec/VersioningSpecification.html#PackageVersionSpecification">Package Versioning Specification</a>
  44. * section of the
  45. * <a href="http://java.sun.com/products/jdk/1.3/docs/guide/versioning/spec/VersioningSpecification.html">Product Versioning Specification</a>.
  46. * It also allows packages to be sealed with respect to the originating URL.
  47. *
  48. * <p>The most useful method is the <code>isCompatibleWith()</code> method that
  49. * compares a desired version of a specification with the version of the
  50. * specification as implemented by a package. A package is considered
  51. * compatible with another version if the version of the specification is
  52. * equal or higher then the requested version. Version numbers are represented
  53. * as strings of positive numbers separated by dots (e.g. "1.2.0").
  54. * The first number is called the major number, the second the minor,
  55. * the third the micro, etc. A version is considered higher then another
  56. * version if it has a bigger major number then the another version or when
  57. * the major numbers of the versions are equal if it has a bigger minor number
  58. * then the other version, etc. (If a version has no minor, micro, etc numbers
  59. * then they are considered the be 0.)
  60. *
  61. * @author Mark Wielaard (mark@klomp.org)
  62. * @see ClassLoader#definePackage(String, String, String, String, String,
  63. * String, String, URL)
  64. * @since 1.2
  65. * @status updated to 1.5
  66. */
  67. public class Package
  68. implements AnnotatedElement
  69. {
  70. /** The name of the Package */
  71. private final String name;
  72. /** The name if the implementation */
  73. private final String implTitle;
  74. /** The vendor that wrote this implementation */
  75. private final String implVendor;
  76. /** The version of this implementation */
  77. private final String implVersion;
  78. /** The name of the specification */
  79. private final String specTitle;
  80. /** The name of the specification designer */
  81. private final String specVendor;
  82. /** The version of this specification */
  83. private final String specVersion;
  84. /** If sealed the origin of the package classes, otherwise null */
  85. private final URL sealed;
  86. /** The class loader that defined this package */
  87. private ClassLoader loader;
  88. /** @deprecated Please use the other constructor that takes the class loader
  89. * that defines the Package.
  90. */
  91. Package(String name,
  92. String specTitle, String specVendor, String specVersion,
  93. String implTitle, String implVendor, String implVersion, URL sealed)
  94. {
  95. this(name, specTitle, specVendor, specVersion, implTitle, implVendor,
  96. implVersion, sealed, null);
  97. }
  98. /**
  99. * A package local constructor for the Package class. All parameters except
  100. * the <code>name</code> of the package may be <code>null</code>.
  101. * There are no public constructors defined for Package; this is a package
  102. * local constructor that is used by java.lang.Classloader.definePackage().
  103. *
  104. * @param name The name of the Package
  105. * @param specTitle The name of the specification
  106. * @param specVendor The name of the specification designer
  107. * @param specVersion The version of this specification
  108. * @param implTitle The name of the implementation
  109. * @param implVendor The vendor that wrote this implementation
  110. * @param implVersion The version of this implementation
  111. * @param sealed If sealed the origin of the package classes
  112. */
  113. Package(String name,
  114. String specTitle, String specVendor, String specVersion,
  115. String implTitle, String implVendor, String implVersion, URL sealed,
  116. ClassLoader loader)
  117. {
  118. if (name == null)
  119. throw new IllegalArgumentException("null Package name");
  120. this.name = name;
  121. this.implTitle = implTitle;
  122. this.implVendor = implVendor;
  123. this.implVersion = implVersion;
  124. this.specTitle = specTitle;
  125. this.specVendor = specVendor;
  126. this.specVersion = specVersion;
  127. this.sealed = sealed;
  128. this.loader = loader;
  129. }
  130. /**
  131. * Returns the Package name in dot-notation.
  132. *
  133. * @return the non-null package name
  134. */
  135. public String getName()
  136. {
  137. return name;
  138. }
  139. /**
  140. * Returns the name of the specification, or null if unknown.
  141. *
  142. * @return the specification title
  143. */
  144. public String getSpecificationTitle()
  145. {
  146. return specTitle;
  147. }
  148. /**
  149. * Returns the version of the specification, or null if unknown.
  150. *
  151. * @return the specification version
  152. */
  153. public String getSpecificationVersion()
  154. {
  155. return specVersion;
  156. }
  157. /**
  158. * Returns the name of the specification designer, or null if unknown.
  159. *
  160. * @return the specification vendor
  161. */
  162. public String getSpecificationVendor()
  163. {
  164. return specVendor;
  165. }
  166. /**
  167. * Returns the name of the implementation, or null if unknown.
  168. *
  169. * @return the implementation title
  170. */
  171. public String getImplementationTitle()
  172. {
  173. return implTitle;
  174. }
  175. /**
  176. * Returns the version of this implementation, or null if unknown.
  177. *
  178. * @return the implementation version
  179. */
  180. public String getImplementationVersion()
  181. {
  182. return implVersion;
  183. }
  184. /**
  185. * Returns the vendor that wrote this implementation, or null if unknown.
  186. *
  187. * @return the implementation vendor
  188. */
  189. public String getImplementationVendor()
  190. {
  191. return implVendor;
  192. }
  193. /**
  194. * Returns true if this Package is sealed.
  195. *
  196. * @return true if the package is sealed
  197. */
  198. public boolean isSealed()
  199. {
  200. return sealed != null;
  201. }
  202. /**
  203. * Returns true if this Package is sealed and the origin of the classes is
  204. * the given URL.
  205. *
  206. * @param url the URL to test
  207. * @return true if the package is sealed by this URL
  208. * @throws NullPointerException if url is null
  209. */
  210. public boolean isSealed(URL url)
  211. {
  212. return url.equals(sealed);
  213. }
  214. /**
  215. * Checks if the version of the specification is higher or at least as high
  216. * as the desired version. Comparison is done by sequentially comparing
  217. * dotted decimal numbers from the parameter and from
  218. * <code>getSpecificationVersion</code>.
  219. *
  220. * @param version the (minimal) desired version of the specification
  221. *
  222. * @return true if the version is compatible, false otherwise
  223. *
  224. * @throws NumberFormatException if either version string is invalid
  225. * @throws NullPointerException if either version string is null
  226. */
  227. public boolean isCompatibleWith(String version)
  228. {
  229. StringTokenizer versionTokens = new StringTokenizer(version, ".");
  230. StringTokenizer specTokens = new StringTokenizer(specVersion, ".");
  231. try
  232. {
  233. while (versionTokens.hasMoreElements())
  234. {
  235. int vers = Integer.parseInt(versionTokens.nextToken());
  236. int spec = Integer.parseInt(specTokens.nextToken());
  237. if (spec < vers)
  238. return false;
  239. else if (spec > vers)
  240. return true;
  241. // They must be equal, next Token please!
  242. }
  243. }
  244. catch (NoSuchElementException e)
  245. {
  246. // This must have been thrown by spec.nextToken() so return false.
  247. return false;
  248. }
  249. // They must have been exactly the same version.
  250. // Or the specVersion has more subversions. That is also good.
  251. return true;
  252. }
  253. /**
  254. * Returns the named package if it is known by the callers class loader.
  255. * It may return null if the package is unknown, when there is no
  256. * information on that particular package available or when the callers
  257. * classloader is null.
  258. *
  259. * @param name the name of the desired package
  260. * @return the package by that name in the current ClassLoader
  261. */
  262. public static Package getPackage(String name)
  263. {
  264. // Get the caller's classloader
  265. ClassLoader cl = VMStackWalker.getCallingClassLoader();
  266. return cl != null ? cl.getPackage(name) : VMClassLoader.getPackage(name);
  267. }
  268. /**
  269. * Returns all the packages that are known to the callers class loader.
  270. * It may return an empty array if the classloader of the caller is null.
  271. *
  272. * @return an array of all known packages
  273. */
  274. public static Package[] getPackages()
  275. {
  276. // Get the caller's classloader
  277. ClassLoader cl = VMStackWalker.getCallingClassLoader();
  278. return cl != null ? cl.getPackages() : VMClassLoader.getPackages();
  279. }
  280. /**
  281. * Returns the hashCode of the name of this package.
  282. *
  283. * @return the hash code
  284. */
  285. public int hashCode()
  286. {
  287. return name.hashCode();
  288. }
  289. /**
  290. * Returns a string representation of this package. It is specified to
  291. * be <code>"package " + getName() + (getSpecificationTitle() == null
  292. * ? "" : ", " + getSpecificationTitle()) + (getSpecificationVersion()
  293. * == null ? "" : ", version " + getSpecificationVersion())</code>.
  294. *
  295. * @return the string representation of the package
  296. */
  297. public String toString()
  298. {
  299. return ("package " + name + (specTitle == null ? "" : ", " + specTitle)
  300. + (specVersion == null ? "" : ", version " + specVersion));
  301. }
  302. /**
  303. * Returns this package's annotation for the specified annotation type,
  304. * or <code>null</code> if no such annotation exists.
  305. *
  306. * @param annotationClass the type of annotation to look for.
  307. * @return this package's annotation for the specified type, or
  308. * <code>null</code> if no such annotation exists.
  309. * @since 1.5
  310. */
  311. public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
  312. {
  313. A foundAnnotation = null;
  314. Annotation[] annotations = getAnnotations();
  315. for (Annotation annotation : annotations)
  316. if (annotation.annotationType() == annotationClass)
  317. foundAnnotation = (A) annotation;
  318. return foundAnnotation;
  319. }
  320. /**
  321. * Returns all annotations associated with this package. If there are
  322. * no annotations associated with this package, then a zero-length array
  323. * will be returned. The returned array may be modified by the client
  324. * code, but this will have no effect on the annotation content of this
  325. * package, and hence no effect on the return value of this method for
  326. * future callers.
  327. *
  328. * @return this package' annotations.
  329. * @since 1.5
  330. */
  331. public Annotation[] getAnnotations()
  332. {
  333. /** All a package's annotations are declared within it. */
  334. return getDeclaredAnnotations();
  335. }
  336. /**
  337. * Returns all annotations directly defined by this package. If there are
  338. * no annotations associated with this package, then a zero-length array
  339. * will be returned. The returned array may be modified by the client
  340. * code, but this will have no effect on the annotation content of this
  341. * package, and hence no effect on the return value of this method for
  342. * future callers.
  343. *
  344. * @return the annotations directly defined by this package.
  345. * @since 1.5
  346. */
  347. public Annotation[] getDeclaredAnnotations()
  348. {
  349. try
  350. {
  351. Class pkgInfo = Class.forName(name + ".package-info", false, loader);
  352. return pkgInfo.getDeclaredAnnotations();
  353. }
  354. catch (ClassNotFoundException _)
  355. {
  356. return new Annotation[0];
  357. }
  358. }
  359. /**
  360. * Returns true if an annotation for the specified type is associated
  361. * with this package. This is primarily a short-hand for using marker
  362. * annotations.
  363. *
  364. * @param annotationClass the type of annotation to look for.
  365. * @return true if an annotation exists for the specified type.
  366. * @since 1.5
  367. */
  368. public boolean isAnnotationPresent(Class<? extends Annotation>
  369. annotationClass)
  370. {
  371. return getAnnotation(annotationClass) != null;
  372. }
  373. } // class Package