View Javadoc
1   /*
2    *  Copyright 2012 Chris Pheby
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  package org.jadira.scanner.classpath.types;
17  
18  import java.io.File;
19  import java.lang.annotation.Annotation;
20  import java.util.HashSet;
21  import java.util.List;
22  import java.util.Set;
23  
24  import javassist.bytecode.ClassFile;
25  
26  import org.apache.commons.lang3.builder.EqualsBuilder;
27  import org.apache.commons.lang3.builder.HashCodeBuilder;
28  import org.apache.commons.lang3.builder.ToStringBuilder;
29  import org.apache.commons.lang3.builder.ToStringStyle;
30  import org.jadira.scanner.classfile.filter.PackageFileFilter;
31  import org.jadira.scanner.classpath.ClasspathResolver;
32  import org.jadira.scanner.classpath.filter.JElementTypeFilter;
33  import org.jadira.scanner.classpath.filter.PackageFilter;
34  import org.jadira.scanner.classpath.filter.PackagePrefixFilter;
35  import org.jadira.scanner.classpath.projector.ClasspathProjector;
36  import org.jadira.scanner.classpath.visitor.IntrospectionVisitor;
37  import org.jadira.scanner.core.api.Projector;
38  import org.jadira.scanner.core.exception.ClasspathAccessException;
39  import org.jadira.scanner.core.helper.JavassistAnnotationsHelper;
40  
41  public class JPackage extends JElement {
42  
43  	private static final Projector<File> CLASSPATH_PROJECTOR = ClasspathProjector.SINGLETON;
44  	
45      private Package wrappedPackage;
46      
47      protected JPackage(String name, ClasspathResolver resolver) throws ClasspathAccessException {
48          super(name, resolver);
49          wrappedPackage = Package.getPackage(name);
50      }
51  
52      protected JPackage(Package wrappedPackage, ClasspathResolver resolver) {
53          super(wrappedPackage.getName(), resolver);
54          this.wrappedPackage = wrappedPackage;
55      }
56  
57      public static JPackage getJPackage(String name, ClasspathResolver resolver) throws ClasspathAccessException {
58          return new JPackage(name, resolver);
59      }
60  
61      public static JPackage getJPackage(Package pkg, ClasspathResolver resolver) throws ClasspathAccessException {
62          return new JPackage(pkg, resolver);
63      }
64  
65      public Set<JClass> getClasses() throws ClasspathAccessException {
66  
67          Set<JClass> retVal = new HashSet<JClass>();
68          List<? extends ClassFile> classes = getResolver().getClassFileResolver().resolveAll(null, CLASSPATH_PROJECTOR, new PackageFileFilter(getName(), false), new PackagePrefixFilter(this), new JElementTypeFilter(JClass.class)); 
69          for (ClassFile classFile : classes) {
70  
71          	if ((classFile.getSuperclass() != null) && 
72          			(!classFile.isInterface() && (!classFile.getSuperclass().equals("java.lang.Enum"))
73  	            		&& (classFile.getInnerAccessFlags() == -1))) {
74          		retVal.add(JClass.getJClass(classFile, getResolver()));
75          	}
76          }
77          return retVal;
78      }
79  
80      public Set<JInterface> getInterfaces() throws ClasspathAccessException {
81  
82          Set<JInterface> retVal = new HashSet<JInterface>();
83          List<? extends ClassFile> classes = getResolver().getClassFileResolver().resolveAll(null, CLASSPATH_PROJECTOR, new PackageFileFilter(getName(), false), new PackageFilter(this), new JElementTypeFilter(JInterface.class));
84          for (ClassFile classFile : classes) {
85              if (classFile.isInterface() && (!classFile.getSuperclass().equals("java.lang.annotation.Annotation"))) {
86                  retVal.add(JInterface.getJInterface(classFile, getResolver()));
87              }
88          }
89          return retVal;
90      }
91  
92      @Override
93      public Set<JAnnotation<?>> getAnnotations() throws ClasspathAccessException {
94  
95          Set<JAnnotation<?>> retVal = new HashSet<JAnnotation<?>>();
96          List<? extends ClassFile> classes = getResolver().getClassFileResolver().resolveAll(null, CLASSPATH_PROJECTOR, new PackageFileFilter(getName(), false), new PackageFilter(this), new JElementTypeFilter(JAnnotation.class));
97          for (ClassFile classFile : classes) {
98              if (classFile.isInterface() && (classFile.getSuperclass().equals("java.lang.annotation.Annotation"))) {
99                  try {
100                     @SuppressWarnings("unchecked")
101                     Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) (getResolver().loadClass(classFile.getName()));
102                     Annotation theAnnotation = annotationClass.newInstance();
103                     retVal.add(JAnnotation.getJAnnotation(theAnnotation, this, getResolver()));
104                 } catch (InstantiationException e) {
105                     throw new ClasspathAccessException("Cannot instantiate annotation: " + e.getMessage(), e);
106                 } catch (IllegalAccessException e) {
107                     throw new ClasspathAccessException("Cannot access annotation: " + e.getMessage(), e);
108                 }
109             }
110         }
111         return retVal;
112     }
113 
114 //    public Set<JPackage> getChildPackages() throws ClasspathAccessException {
115 //
116 //        Set<JPackage> retVal = new HashSet<JPackage>();
117 //        List<ClassFile> classes = getResolver().getClassFileResolver().resolveAll(null, PACKAGE_PROJECTOR);
118 //        for (Package pkg : packages) {
119 //
120 //            retVal.add(getJPackage(pkg, getResolver()));
121 //        }
122 //        return retVal;
123 //    }
124 
125     public Package getActualPackage() {
126         return wrappedPackage;
127     }
128 
129     @Override
130     public <A extends java.lang.annotation.Annotation> JAnnotation<A> getAnnotation(Class<A> annotation)  throws ClasspathAccessException {
131 
132         Set<JAnnotation<?>> inspAnnotations = getAnnotations();
133         for (JAnnotation<?> next : inspAnnotations) {
134             if (next.getName().equals(annotation.getName())
135                     && (next.getActualAnnotation().getClass().equals(annotation.getClass()))) {
136                 @SuppressWarnings("unchecked") JAnnotation<A> retVal = (JAnnotation<A>) next;
137                 return retVal;
138             }
139         }
140         return null;
141     }
142     
143     public JPackage getParentPackage() throws ClasspathAccessException {
144 
145     	String name = getName();
146     	
147         Package retVal = null;
148         while (retVal == null && name.lastIndexOf('.') != -1) {
149             name = name.substring(0, name.lastIndexOf('.'));
150             retVal = Package.getPackage(name);
151         }
152         if (retVal == null) {
153             retVal = Package.getPackage("");
154         }
155         return JPackage.getJPackage(retVal, getResolver());
156     }
157     
158 	public Annotation[] getAnnotationsForPackage() {
159 
160 		ClassFile cf = findClassFile(getName() + ".package-info.class", getResolver());
161 
162 		if (cf == null) {
163 			return new Annotation[] {};
164 		}
165 
166 		return JavassistAnnotationsHelper.getAnnotationsForClass(cf);
167 	}
168     
169     @Override
170     public void acceptVisitor(IntrospectionVisitor visitor) throws ClasspathAccessException {
171         visitor.visit(this);
172 
173         for (JInterface next : getInterfaces()) {
174             next.acceptVisitor(visitor);
175         }
176         for (JClass next : getClasses()) {
177             next.acceptVisitor(visitor);
178         }
179         for (JAnnotation<?> next : getAnnotations()) {
180             next.acceptVisitor(visitor);
181         }
182 //        for (JPackage next : getChildPackages()) {
183 //            next.acceptVisitor(visitor);
184 //        }
185     }
186 
187     @Override
188     public JElement getEnclosingElement() {
189         return null;
190     }
191 
192 //	private static List<Package> findChildPackagesForPackage(String name, ClasspathResolver resolver) throws ClasspathAccessException {
193 //
194 //		List<Package> retVal = new ArrayList<Package>();
195 //
196 //		for (URL url : resolver.getClasspaths()) {
197 //
198 //			File nextFile = FileUtils.getFileForPathName(name, url);
199 //
200 //			if (nextFile != null) {
201 //
202 //				File[] files = nextFile.listFiles();
203 //
204 //				for (int i = 0; i < files.length; i++) {
205 //					if (files[i].isDirectory()) {
206 //						retVal.add(findPackage(name + "." + files[i].getName(), resolver));
207 //					}
208 //				}
209 //			}
210 //		}
211 //		return retVal;
212 //	}
213 
214     @Override
215     public String toString() {
216     	
217     	ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
218     	builder.append("name", this.getName());
219     	
220     	return builder.toString();
221     }
222     
223     @Override
224 	public boolean equals(Object obj) {
225 		if (obj == null) {
226 			return false;
227 		}
228 		if (obj == this) {
229 			return true;
230 		}
231 		if (obj.getClass() != getClass()) {
232 			return false;
233 		}
234 		// JPackage rhs = (JPackage) obj;
235 		return new EqualsBuilder()
236 			 	.appendSuper(super.equals(obj))
237 				.isEquals();
238 	}
239 
240     @Override
241 	public int hashCode() {
242 		return new HashCodeBuilder(11, 47).append(super.hashCode())
243 				.toHashCode();
244 	}    
245 }