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 java.net.URL;
  41: import java.util.NoSuchElementException;
  42: import java.util.StringTokenizer;
  43: 
  44: 
  45: /**
  46:  * Everything you ever wanted to know about a package. This class makes it
  47:  * possible to attach specification and implementation information to a
  48:  * package as explained in the
  49:  * <a href="http://java.sun.com/products/jdk/1.3/docs/guide/versioning/spec/VersioningSpecification.html#PackageVersionSpecification">Package Versioning Specification</a>
  50:  * section of the
  51:  * <a href="http://java.sun.com/products/jdk/1.3/docs/guide/versioning/spec/VersioningSpecification.html">Product Versioning Specification</a>.
  52:  * It also allows packages to be sealed with respect to the originating URL.
  53:  *
  54:  * <p>The most useful method is the <code>isCompatibleWith()</code> method that
  55:  * compares a desired version of a specification with the version of the
  56:  * specification as implemented by a package. A package is considered
  57:  * compatible with another version if the version of the specification is
  58:  * equal or higher then the requested version. Version numbers are represented
  59:  * as strings of positive numbers separated by dots (e.g. "1.2.0").
  60:  * The first number is called the major number, the second the minor,
  61:  * the third the micro, etc. A version is considered higher then another
  62:  * version if it has a bigger major number then the another version or when
  63:  * the major numbers of the versions are equal if it has a bigger minor number
  64:  * then the other version, etc. (If a version has no minor, micro, etc numbers
  65:  * then they are considered the be 0.)
  66:  *
  67:  * @author Mark Wielaard (mark@klomp.org)
  68:  * @see ClassLoader#definePackage(String, String, String, String, String,
  69:  *      String, String, URL)
  70:  * @since 1.2
  71:  * @status updated to 1.4
  72:  */
  73: public class Package
  74: {
  75:   /** The name of the Package */
  76:   private final String name;
  77: 
  78:   /** The name if the implementation */
  79:   private final String implTitle;
  80: 
  81:   /** The vendor that wrote this implementation */
  82:   private final String implVendor;
  83: 
  84:   /** The version of this implementation */
  85:   private final String implVersion;
  86: 
  87:   /** The name of the specification */
  88:   private final String specTitle;
  89: 
  90:   /** The name of the specification designer */
  91:   private final String specVendor;
  92: 
  93:   /** The version of this specification */
  94:   private final String specVersion;
  95: 
  96:   /** If sealed the origin of the package classes, otherwise null */
  97:   private final URL sealed;
  98: 
  99:   /**
 100:    * A package local constructor for the Package class. All parameters except
 101:    * the <code>name</code> of the package may be <code>null</code>.
 102:    * There are no public constructors defined for Package; this is a package
 103:    * local constructor that is used by java.lang.Classloader.definePackage().
 104:    * 
 105:    * @param name The name of the Package
 106:    * @param specTitle The name of the specification
 107:    * @param specVendor The name of the specification designer
 108:    * @param specVersion The version of this specification
 109:    * @param implTitle The name of the implementation
 110:    * @param implVendor The vendor that wrote this implementation
 111:    * @param implVersion The version of this implementation
 112:    * @param sealed If sealed the origin of the package classes
 113:    */
 114:   Package(String name,
 115:       String specTitle, String specVendor, String specVersion,
 116:       String implTitle, String implVendor, String implVersion, URL sealed)
 117:   {
 118:     if (name == null)
 119:       throw new IllegalArgumentException("null Package name");
 120: 
 121:     this.name = name;
 122:     this.implTitle = implTitle;
 123:     this.implVendor = implVendor;
 124:     this.implVersion = implVersion;
 125:     this.specTitle = specTitle;
 126:     this.specVendor = specVendor;
 127:     this.specVersion = specVersion;
 128:     this.sealed = sealed;
 129:   }
 130: 
 131:   /**
 132:    * Returns the Package name in dot-notation.
 133:    *
 134:    * @return the non-null package name
 135:    */
 136:   public String getName()
 137:   {
 138:     return name;
 139:   }
 140: 
 141:   /**
 142:    * Returns the name of the specification, or null if unknown.
 143:    *
 144:    * @return the specification title
 145:    */
 146:   public String getSpecificationTitle()
 147:   {
 148:     return specTitle;
 149:   }
 150: 
 151:   /**
 152:    * Returns the version of the specification, or null if unknown.
 153:    *
 154:    * @return the specification version
 155:    */
 156:   public String getSpecificationVersion()
 157:   {
 158:     return specVersion;
 159:   }
 160: 
 161:   /**
 162:    * Returns the name of the specification designer, or null if unknown.
 163:    *
 164:    * @return the specification vendor
 165:    */
 166:   public String getSpecificationVendor()
 167:   {
 168:     return specVendor;
 169:   }
 170: 
 171:   /**
 172:    * Returns the name of the implementation, or null if unknown.
 173:    *
 174:    * @return the implementation title
 175:    */
 176:   public String getImplementationTitle()
 177:   {
 178:     return implTitle;
 179:   }
 180: 
 181:   /**
 182:    * Returns the version of this implementation, or null if unknown.
 183:    *
 184:    * @return the implementation version
 185:    */
 186:   public String getImplementationVersion()
 187:   {
 188:     return implVersion;
 189:   }
 190: 
 191:   /**
 192:    * Returns the vendor that wrote this implementation, or null if unknown.
 193:    *
 194:    * @return the implementation vendor
 195:    */
 196:   public String getImplementationVendor()
 197:   {
 198:     return implVendor;
 199:   }
 200: 
 201:   /**
 202:    * Returns true if this Package is sealed.
 203:    *
 204:    * @return true if the package is sealed
 205:    */
 206:   public boolean isSealed()
 207:   {
 208:     return sealed != null;
 209:   }
 210: 
 211:   /**
 212:    * Returns true if this Package is sealed and the origin of the classes is
 213:    * the given URL.
 214:    *
 215:    * @param url the URL to test
 216:    * @return true if the package is sealed by this URL
 217:    * @throws NullPointerException if url is null
 218:    */
 219:   public boolean isSealed(URL url)
 220:   {
 221:     return url.equals(sealed);
 222:   }
 223: 
 224:   /**
 225:    * Checks if the version of the specification is higher or at least as high
 226:    * as the desired version. Comparison is done by sequentially comparing
 227:    * dotted decimal numbers from the parameter and from
 228:    * <code>getSpecificationVersion</code>.
 229:    *
 230:    * @param version the (minimal) desired version of the specification
 231:    *
 232:    * @return true if the version is compatible, false otherwise
 233:    *
 234:    * @Throws NumberFormatException if either version string is invalid
 235:    * @throws NullPointerException if either version string is null
 236:    */
 237:   public boolean isCompatibleWith(String version)
 238:   {
 239:     StringTokenizer versionTokens = new StringTokenizer(version, ".");
 240:     StringTokenizer specTokens = new StringTokenizer(specVersion, ".");
 241:     try
 242:       {
 243:         while (versionTokens.hasMoreElements())
 244:           {
 245:             int vers = Integer.parseInt(versionTokens.nextToken());
 246:             int spec = Integer.parseInt(specTokens.nextToken());
 247:             if (spec < vers)
 248:               return false;
 249:             else if (spec > vers)
 250:               return true;
 251:             // They must be equal, next Token please!
 252:           }
 253:       }
 254:     catch (NoSuchElementException e)
 255:       {
 256:         // This must have been thrown by spec.nextToken() so return false.
 257:         return false;
 258:       }
 259:     // They must have been exactly the same version.
 260:     // Or the specVersion has more subversions. That is also good.
 261:     return true;
 262:   }
 263: 
 264:   /**
 265:    * Returns the named package if it is known by the callers class loader.
 266:    * It may return null if the package is unknown, when there is no
 267:    * information on that particular package available or when the callers
 268:    * classloader is null.
 269:    *
 270:    * @param name the name of the desired package
 271:    * @return the package by that name in the current ClassLoader
 272:    */
 273:   public static Package getPackage(String name)
 274:   {
 275:     // Get the caller's classloader
 276:     ClassLoader cl = VMSecurityManager.currentClassLoader(Package.class);
 277:     return cl != null ? cl.getPackage(name) : VMClassLoader.getPackage(name);
 278:   }
 279: 
 280:   /**
 281:    * Returns all the packages that are known to the callers class loader.
 282:    * It may return an empty array if the classloader of the caller is null.
 283:    *
 284:    * @return an array of all known packages
 285:    */
 286:   public static Package[] getPackages()
 287:   {
 288:     // Get the caller's classloader
 289:     Class c = VMSecurityManager.getClassContext(Package.class)[1];
 290:     ClassLoader cl = c.getClassLoader();
 291:     return cl != null ? cl.getPackages() : VMClassLoader.getPackages();
 292:   }
 293: 
 294:   /**
 295:    * Returns the hashCode of the name of this package.
 296:    *
 297:    * @return the hash code
 298:    */
 299:   public int hashCode()
 300:   {
 301:     return name.hashCode();
 302:   }
 303: 
 304:   /**
 305:    * Returns a string representation of this package. It is specified to
 306:    * be <code>"package " + getName() + (getSpecificationTitle() == null
 307:    * ? "" : ", " + getSpecificationTitle()) + (getSpecificationVersion()
 308:    * == null ? "" : ", version " + getSpecificationVersion())</code>.
 309:    *
 310:    * @return the string representation of the package
 311:    */
 312:   public String toString()
 313:   {
 314:     return ("package " + name + (specTitle == null ? "" : ", " + specTitle)
 315:         + (specVersion == null ? "" : ", version " + specVersion));
 316:   }
 317: } // class Package