1 package ch.elca.el4j.services.persistence.hibernate.entityfinder;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.net.JarURLConnection;
6 import java.net.URL;
7 import java.util.ArrayList;
8 import java.util.Enumeration;
9 import java.util.List;
10 import java.util.jar.JarEntry;
11 import java.util.jar.JarFile;
12
13 import org.springframework.util.Assert;
14
15
16
17
18
19
20 public class ClassLocator {
21
22
23
24 protected final String[] packageNames;
25
26
27
28
29 protected final ClassLoader classLoader;
30
31
32
33
34
35
36
37
38
39 public ClassLocator(String... packageNames) throws ClassNotFoundException {
40 this(Thread.currentThread().getContextClassLoader(), packageNames);
41 }
42
43
44
45
46
47
48
49
50
51 public ClassLocator(ClassLoader classLoader, String... packageNames) {
52 Assert.notNull(classLoader);
53 Assert.notNull(packageNames);
54 this.classLoader = classLoader;
55 this.packageNames = packageNames;
56 }
57
58
59
60
61
62
63
64
65
66 public List<ClassLocation> getAllClassLocations() throws ClassNotFoundException, IOException {
67 List<ClassLocation> classLocations = new ArrayList<ClassLocation>();
68
69 for (String packageName : packageNames) {
70 String path = packageName.replace('.', '/');
71 Enumeration<URL> resources = classLoader.getResources(path);
72 if (null == resources || !resources.hasMoreElements()) {
73 throw new ClassNotFoundException("No resource for " + path);
74 }
75
76 while (resources.hasMoreElements()) {
77 URL resource = resources.nextElement();
78 if (resource.getProtocol().equalsIgnoreCase("FILE")) {
79 loadDirectory(packageName, resource, classLocations);
80 } else if (resource.getProtocol().equalsIgnoreCase("JAR")) {
81 loadJar(packageName, resource, classLocations);
82 } else if (resource.getProtocol().equalsIgnoreCase("ZIP")) {
83
84 resource = new URL("jar:file://" + resource.getFile().replaceAll("\\\\", "/"));
85 loadJar(packageName, resource, classLocations);
86 } else {
87 throw new ClassNotFoundException("Unknown protocol on class resource: "
88 + resource.toExternalForm());
89 }
90 }
91 }
92 return classLocations;
93 }
94
95
96
97
98
99
100
101
102
103
104 private void loadJar(String packageName, URL resource, List<ClassLocation> classLocations)
105 throws IOException {
106 JarURLConnection conn = (JarURLConnection) resource.openConnection();
107 JarFile jarFile = conn.getJarFile();
108 Enumeration<JarEntry> entries = jarFile.entries();
109 String packagePath = packageName.replace('.', '/');
110
111 while (entries.hasMoreElements()) {
112 JarEntry entry = entries.nextElement();
113 if ((entry.getName().startsWith(packagePath) || entry.getName().startsWith(
114 "WEB-INF/classes/" + packagePath))
115 && entry.getName().endsWith(".class")) {
116 URL url = new URL("jar:"
117 + new URL("file", null, jarFile.getName())
118 .toExternalForm() + "!/" + entry.getName());
119
120 String className = entry.getName();
121 if (className.startsWith("/")) {
122 className = className.substring(1);
123 }
124 className = className.replace('/', '.');
125
126 className = className.substring(0, className.length() - ".class".length());
127
128 ClassLocation classLocation = new ClassLocation(classLoader, className, url);
129 addClassLocation(classLocation, classLocations);
130 }
131 }
132
133 }
134
135
136
137
138
139
140
141 private void loadDirectory(String packageName, URL resource,
142 List<ClassLocation> classLocations) throws IOException {
143 loadDirectory(packageName, resource.getFile(), classLocations);
144
145 }
146
147
148
149
150
151
152
153 private void loadDirectory(String packageName, String fullPath,
154 List<ClassLocation> classLocations) throws IOException {
155 File directory = new File(fullPath);
156 if (!directory.isDirectory()) {
157 throw new IOException("Invalid directory " + directory.getAbsolutePath());
158 }
159
160 File[] files = directory.listFiles();
161 for (File file : files) {
162 if (file.isDirectory()) {
163 loadDirectory(packageName + '.' + file.getName(), file.getAbsolutePath(),
164 classLocations);
165 } else if (file.getName().endsWith(".class")) {
166 String simpleName = file.getName();
167 simpleName = simpleName.substring(0, simpleName.length() - ".class".length());
168 String className = String.format("%s.%s", packageName, simpleName);
169 ClassLocation location = new ClassLocation(classLoader, className, new URL("file",
170 null, file.getAbsolutePath()));
171 addClassLocation(location, classLocations);
172 }
173 }
174 }
175
176
177
178
179
180
181
182
183
184 private void addClassLocation(ClassLocation classLocation, List<ClassLocation> classLocations)
185 throws IOException {
186 if (classLocations.contains(classLocation)) {
187 throw new IOException("Duplicate location found for: " + classLocation.getClassName());
188 }
189 classLocations.add(classLocation);
190 }
191 }