Source for java.lang.Package

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