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            this(p, null);
052        }
053    
054        /**
055         * Create an extended Package instance for the specified package.
056         * @param p package
057         * @param c class loader
058         */
059        public PackageEx(Package p, ClassLoader c) {
060            super(c);
061            java = p;
062            ClassFileTools.ClassLocation cl = ClassFileTools.findClassFile(java.getName()+".package-info", _classPath);
063            if (cl==null) { _ai = null; return; }
064            _ai = new RuntimeVisibleAnnotationsAttributeInfo[1];
065            _ai[0] = (RuntimeVisibleAnnotationsAttributeInfo)
066                cl.getClassFile().getAttribute(RuntimeVisibleAnnotationsAttributeInfo.getAttributeName());
067            try {
068                cl.close();
069            }
070            catch(IOException e) { /* ignore */ }
071        }
072    
073        /**
074         * Return the annotated element.
075         *
076         * @return annotated element
077         */
078        protected AnnotatedElement getAnnotatedElement() {
079            return java;
080        }
081    
082        /**
083         * Return the name of this package.
084         *
085         * @return The name of this package using the Java language dot notation for the package. i.e  java.lang
086         */
087        public String getName() {
088            return java.getName();
089        }
090    
091        /**
092         * Return the title of the specification that this package implements.
093         *
094         * @return the specification title, null is returned if it is not known.
095         */
096        public String getSpecificationTitle() {
097            return java.getSpecificationTitle();
098        }
099    
100        /**
101         * Returns the version number of the specification that this package implements. This version string must be a
102         * sequence of positive decimal integers separated by "."'s and may have leading zeros. When version strings are
103         * compared the most significant numbers are compared.
104         *
105         * @return the specification version, null is returned if it is not known.
106         */
107        public String getSpecificationVersion() {
108            return java.getSpecificationVersion();
109        }
110    
111        /**
112         * Return the name of the organization, vendor, or company that owns and maintains the specification of the classes
113         * that implement this package.
114         *
115         * @return the specification vendor, null is returned if it is not known.
116         */
117        public String getSpecificationVendor() {
118            return java.getSpecificationVendor();
119        }
120    
121        /**
122         * Return the title of this package.
123         *
124         * @return the title of the implementation, null is returned if it is not known.
125         */
126        public String getImplementationTitle() {
127            return java.getImplementationTitle();
128        }
129    
130        /**
131         * Return the version of this implementation. It consists of any string assigned by the vendor of this
132         * implementation and does not have any particular syntax specified or expected by the Java runtime. It may be
133         * compared for equality with other package version strings used for this implementation by this vendor for this
134         * package.
135         *
136         * @return the version of the implementation, null is returned if it is not known.
137         */
138        public String getImplementationVersion() {
139            return java.getImplementationVersion();
140        }
141    
142        /**
143         * Returns the name of the organization, vendor or company that provided this implementation.
144         *
145         * @return the vendor that implemented this package..
146         */
147        public String getImplementationVendor() {
148            return java.getImplementationVendor();
149        }
150    
151        /**
152         * Returns true if this package is sealed.
153         *
154         * @return true if the package is sealed, false otherwise
155         */
156        public boolean isSealed() {
157            return java.isSealed();
158        }
159    
160        /**
161         * Returns true if this package is sealed with respect to the specified code source url.
162         *
163         * @param url the code source url
164         *
165         * @return true if this package is sealed with respect to url
166         */
167        public boolean isSealed(URL url) {
168            return java.isSealed(url);
169        }
170    
171        /**
172         * Compare this package's specification version with a desired version. It returns true if this packages
173         * specification version number is greater than or equal to the desired version number. <p>
174         * <p/>
175         * Version numbers are compared by sequentially comparing corresponding components of the desired and specification
176         * strings. Each component is converted as a decimal integer and the values compared. If the specification value is
177         * greater than the desired value true is returned. If the value is less false is returned. If the values are equal
178         * the period is skipped and the next pair of components is compared.
179         *
180         * @param desired the version string of the desired version.
181         *
182         * @return true if this package's version number is greater than or equal to the desired version number
183         *
184         * @throws NumberFormatException if the desired or current version is not of the correct dotted form.
185         */
186        public boolean isCompatibleWith(String desired) throws NumberFormatException {
187            return java.isCompatibleWith(desired);
188        }
189    
190        /**
191         * Return the hash code computed from the package name.
192         *
193         * @return the hash code computed from the package name.
194         */
195        public int hashCode() {
196            return java.hashCode();
197        }
198    
199        /**
200         * Returns the string representation of this Package. Its value is the string "package " and the package name. If
201         * the package title is defined it is appended. If the package version is defined it is appended.
202         *
203         * @return the string representation of the package.
204         */
205        public String toString() {
206            return java.toString();
207        }
208    
209        /**
210         * Compares this <code>Constructor</code> against the specified object. Returns true if the objects are the same.  Two
211         * <code>Constructor</code> objects are the same if they were declared by the same class and have the same formal
212         * parameter types.
213         */
214        public boolean equals(Object obj) {
215            return (obj!=null)&&(obj.getClass().equals(this.getClass()) && (java.equals(obj)));
216        }
217    }