001    package edu.rice.cs.cunit.subAnnot;
002    
003    import edu.rice.cs.cunit.classFile.ClassFileTools;
004    import edu.rice.cs.cunit.classFile.attributes.RuntimeVisibleAnnotationsAttributeInfo;
005    
006    import java.lang.reflect.AnnotatedElement;
007    import java.util.ArrayList;
008    import java.util.List;
009    import java.net.URL;
010    import java.io.IOException;
011    
012    /**
013     * Extended Package class to support annotations with subclassing.
014     *
015     * @author Mathias Ricken
016     */
017    public class PackageEx extends AAnnotatedElementEx {
018        /**
019         * The java.lang.reflect.Package object that represents the package.
020         */
021        public final Package java;
022    
023        /**
024         * Return an extended Package instance for the class with the specified package name.
025         * @param s package name
026         * @return package
027         */
028        @SuppressWarnings("unchecked")
029        public static PackageEx getPackage(String s) {
030            return new PackageEx(Package.getPackage(s));
031        }
032    
033        /**
034         * Return an array of all extended Package instances known to the caller's ClassLoader instance.
035         * @return array of packages
036         */
037        @SuppressWarnings("unchecked")
038        public static PackageEx[] getPackages() {
039            List<PackageEx> list = new ArrayList<PackageEx>();
040            for(Package p: Package.getPackages()) {
041                list.add(new PackageEx(p));
042            }
043            return list.toArray(new PackageEx[list.size()]);
044        }
045    
046        /**
047         * Create an extended Package instance for the specified package.
048         * @param p package
049         */
050        public PackageEx(Package p) {
051            java = p;
052            ClassFileTools.ClassLocation cl = ClassFileTools.findClassFile(java.getName()+".package-info", _classPath);
053            if (cl==null) { _ai = null; return; }
054            _ai = new RuntimeVisibleAnnotationsAttributeInfo[0];
055     _ai[0] = (RuntimeVisibleAnnotationsAttributeInfo)
056                cl.getClassFile().getAttribute(RuntimeVisibleAnnotationsAttributeInfo.getAttributeName());
057            try {
058                cl.close();
059            }
060            catch(IOException e) { /* ignore */ }
061        }
062    
063        /**
064         * Return the annotated element.
065         *
066         * @return annotated element
067         */
068        protected AnnotatedElement getAnnotatedElement() {
069            return java;
070        }
071    
072        /**
073         * Return the name of this package.
074         *
075         * @return The name of this package using the Java language dot notation for the package. i.e  java.lang
076         */
077        public String getName() {
078            return java.getName();
079        }
080    
081        /**
082         * Return the title of the specification that this package implements.
083         *
084         * @return the specification title, null is returned if it is not known.
085         */
086        public String getSpecificationTitle() {
087            return java.getSpecificationTitle();
088        }
089    
090        /**
091         * Returns the version number of the specification that this package implements. This version string must be a
092         * sequence of positive decimal integers separated by "."'s and may have leading zeros. When version strings are
093         * compared the most significant numbers are compared.
094         *
095         * @return the specification version, null is returned if it is not known.
096         */
097        public String getSpecificationVersion() {
098            return java.getSpecificationVersion();
099        }
100    
101        /**
102         * Return the name of the organization, vendor, or company that owns and maintains the specification of the classes
103         * that implement this package.
104         *
105         * @return the specification vendor, null is returned if it is not known.
106         */
107        public String getSpecificationVendor() {
108            return java.getSpecificationVendor();
109        }
110    
111        /**
112         * Return the title of this package.
113         *
114         * @return the title of the implementation, null is returned if it is not known.
115         */
116        public String getImplementationTitle() {
117            return java.getImplementationTitle();
118        }
119    
120        /**
121         * Return the version of this implementation. It consists of any string assigned by the vendor of this
122         * implementation and does not have any particular syntax specified or expected by the Java runtime. It may be
123         * compared for equality with other package version strings used for this implementation by this vendor for this
124         * package.
125         *
126         * @return the version of the implementation, null is returned if it is not known.
127         */
128        public String getImplementationVersion() {
129            return java.getImplementationVersion();
130        }
131    
132        /**
133         * Returns the name of the organization, vendor or company that provided this implementation.
134         *
135         * @return the vendor that implemented this package..
136         */
137        public String getImplementationVendor() {
138            return java.getImplementationVendor();
139        }
140    
141        /**
142         * Returns true if this package is sealed.
143         *
144         * @return true if the package is sealed, false otherwise
145         */
146        public boolean isSealed() {
147            return java.isSealed();
148        }
149    
150        /**
151         * Returns true if this package is sealed with respect to the specified code source url.
152         *
153         * @param url the code source url
154         *
155         * @return true if this package is sealed with respect to url
156         */
157        public boolean isSealed(URL url) {
158            return java.isSealed(url);
159        }
160    
161        /**
162         * Compare this package's specification version with a desired version. It returns true if this packages
163         * specification version number is greater than or equal to the desired version number. <p>
164         * <p/>
165         * Version numbers are compared by sequentially comparing corresponding components of the desired and specification
166         * strings. Each component is converted as a decimal integer and the values compared. If the specification value is
167         * greater than the desired value true is returned. If the value is less false is returned. If the values are equal
168         * the period is skipped and the next pair of components is compared.
169         *
170         * @param desired the version string of the desired version.
171         *
172         * @return true if this package's version number is greater than or equal to the desired version number
173         *
174         * @throws NumberFormatException if the desired or current version is not of the correct dotted form.
175         */
176        public boolean isCompatibleWith(String desired) throws NumberFormatException {
177            return java.isCompatibleWith(desired);
178        }
179    
180        /**
181         * Return the hash code computed from the package name.
182         *
183         * @return the hash code computed from the package name.
184         */
185        public int hashCode() {
186            return java.hashCode();
187        }
188    
189        /**
190         * Returns the string representation of this Package. Its value is the string "package " and the package name. If
191         * the package title is defined it is appended. If the package version is defined it is appended.
192         *
193         * @return the string representation of the package.
194         */
195        public String toString() {
196            return java.toString();
197        }
198    
199        /**
200         * Compares this <code>Constructor</code> against the specified object. Returns true if the objects are the same.  Two
201         * <code>Constructor</code> objects are the same if they were declared by the same class and have the same formal
202         * parameter types.
203         */
204        public boolean equals(Object obj) {
205            return (obj!=null)&&(obj.getClass().equals(this.getClass()) && (java.equals(obj)));
206        }
207    }