1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jadira.scanner.classpath;
17
18 import java.io.File;
19 import java.io.FileNotFoundException;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.net.URL;
23 import java.util.List;
24
25 import javassist.bytecode.ClassFile;
26
27 import org.apache.commons.lang3.builder.ToStringBuilder;
28 import org.apache.commons.lang3.builder.ToStringStyle;
29 import org.jadira.scanner.classfile.ClassFileResolver;
30 import org.jadira.scanner.classpath.types.JClass;
31 import org.jadira.scanner.classpath.types.JElement;
32 import org.jadira.scanner.classpath.types.JInterface;
33 import org.jadira.scanner.classpath.types.JPackage;
34 import org.jadira.scanner.core.api.Allocator;
35 import org.jadira.scanner.core.exception.ClasspathAccessException;
36 import org.jadira.scanner.core.exception.FileAccessException;
37 import org.jadira.scanner.core.helper.FileInputStreamOperation;
38 import org.jadira.scanner.core.helper.FileUtils;
39 import org.jadira.scanner.core.helper.JavassistClassFileHelper;
40 import org.jadira.scanner.core.helper.filenamefilter.ClassFilenameFilter;
41 import org.jadira.scanner.core.spi.AbstractFileResolver;
42 import org.jadira.scanner.core.utils.reflection.ClassLoaderUtils;
43 import org.jadira.scanner.file.locator.JdkBaseClasspathUrlLocator;
44
45 import de.schlichtherle.io.FileInputStream;
46
47 public class ClasspathResolver extends AbstractFileResolver<JElement> {
48
49 private static final List<URL> JDK_BASE_CLASSPATH_JARS = new JdkBaseClasspathUrlLocator().locate();
50
51 private static final ClassFilenameFilter CLASSFILE_FILTER = new ClassFilenameFilter();
52
53 private final ClasspathAssigner assigner = new ClasspathAssigner();
54
55 private final ClassFileResolver classFileResolver;
56
57 private final ClassLoader[] classLoaders;
58
59 public ClasspathResolver() {
60 super(JDK_BASE_CLASSPATH_JARS);
61 this.classLoaders = ClassLoaderUtils.getClassLoaders();
62 classFileResolver = new ClassFileResolver(classLoaders);
63 }
64
65 public ClasspathResolver(List<URL> classpaths) {
66 super();
67 this.classLoaders = ClassLoaderUtils.getClassLoaders();
68 classFileResolver = new ClassFileResolver(classpaths, this.classLoaders);
69 getDriverData().addAll(classpaths);
70 }
71
72 public ClasspathResolver(ClassLoader... classLoaders) {
73 super(JDK_BASE_CLASSPATH_JARS);
74 this.classLoaders = ClassLoaderUtils.getClassLoaders(classLoaders);
75 classFileResolver = new ClassFileResolver(this.classLoaders);
76 }
77
78 public ClasspathResolver(List<URL> classpaths, List<ClassLoader> classLoaders) {
79 super();
80 this.classLoaders = ClassLoaderUtils.getClassLoaders((ClassLoader[])classLoaders.toArray());
81 classFileResolver = new ClassFileResolver(classpaths, this.classLoaders);
82 getDriverData().addAll(classpaths);
83 }
84
85 public ClasspathResolver(List<URL> classpaths, ClassLoader... classLoaders) {
86 super();
87 this.classLoaders = ClassLoaderUtils.getClassLoaders(classLoaders);
88 classFileResolver = new ClassFileResolver(classpaths, this.classLoaders);
89 getDriverData().addAll(classpaths);
90 }
91
92 @Override
93 public String toString() {
94
95 ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
96 builder.append(getDriverData().toArray());
97
98 return builder.toString();
99 }
100
101 @Override
102 protected Allocator<JElement, File> getAssigner() {
103 return assigner;
104 }
105
106 private final class ClasspathAssigner implements Allocator<JElement, File> {
107
108 @Override
109 public JElement allocate(File e) {
110
111 JElement element;
112 if (e.isDirectory()) {
113
114 element = assignPackage(e);
115 } else {
116 try {
117 ClassFile f = JavassistClassFileHelper.constructClassFileForPath(e.getPath(), new FileInputStream(e));
118 if (f.isInterface()) {
119 return JInterface.getJInterface(f, ClasspathResolver.this);
120 } else {
121 return JClass.getJClass(f, ClasspathResolver.this);
122 }
123 } catch (FileNotFoundException e1) {
124 throw new ClasspathAccessException("Couldnt find file", e1);
125 } catch (IOException e1) {
126 throw new ClasspathAccessException("Couldnt access file", e1);
127 }
128 }
129 return element;
130 }
131
132 private JPackage assignPackage(File e) {
133
134 JPackage retVal;
135
136 final File[] classes = e.listFiles(CLASSFILE_FILTER);
137 for (int i = 0; i < classes.length; i++) {
138
139 ClassFile classFile = FileUtils.doWithFile(classes[i], new FileInputStreamOperation<ClassFile>() {
140
141 @Override
142 public ClassFile execute(String path, InputStream fileInputStream) {
143
144 try {
145 return JavassistClassFileHelper.constructClassFile(path, fileInputStream);
146 } catch (IOException e) {
147 throw new FileAccessException("Cannot access class file: " + e.getMessage(), e);
148 }
149 }
150 });
151
152 Package pkg = loadClass(classFile.getName()).getPackage();
153 retVal = JPackage.getJPackage(pkg, ClasspathResolver.this);
154
155 if (retVal != null) {
156 return retVal;
157 }
158 }
159 return null;
160 }
161 }
162
163 public ClassFileResolver getClassFileResolver() {
164 return classFileResolver;
165 }
166
167 public Class<?> loadClass(String className) {
168
169 if ("java.lang.Class".equals(className)) {
170 return java.lang.Class.class;
171 }
172
173 for (int i = 0; i < classLoaders.length; i++) {
174 try {
175 return Class.forName(className, true, classLoaders[i]);
176 } catch (ClassNotFoundException e) {
177
178 }
179 }
180 throw new ClasspathAccessException("Could not find class: " + className);
181 }
182 }