Source Code Cross Referenced for EmbeddedPluginClassLoader.java in  » ERP-CRM-Financial » Kuali-Financial-System » edu » iu » uis » eden » plugin » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » ERP CRM Financial » Kuali Financial System » edu.iu.uis.eden.plugin 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2005-2006 The Kuali Foundation.
003:         * 
004:         * 
005:         * Licensed under the Educational Community License, Version 1.0 (the "License");
006:         * you may not use this file except in compliance with the License.
007:         * You may obtain a copy of the License at
008:         * 
009:         * http://www.opensource.org/licenses/ecl1.php
010:         * 
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package edu.iu.uis.eden.plugin;
018:
019:        import java.io.BufferedInputStream;
020:        import java.io.BufferedOutputStream;
021:        import java.io.ByteArrayInputStream;
022:        import java.io.ByteArrayOutputStream;
023:        import java.io.File;
024:        import java.io.IOException;
025:        import java.io.InputStream;
026:        import java.net.MalformedURLException;
027:        import java.net.URI;
028:        import java.net.URISyntaxException;
029:        import java.net.URL;
030:        import java.net.URLConnection;
031:        import java.net.URLStreamHandler;
032:        import java.util.ArrayList;
033:        import java.util.Enumeration;
034:        import java.util.HashMap;
035:        import java.util.Iterator;
036:        import java.util.List;
037:        import java.util.Map;
038:        import java.util.jar.JarEntry;
039:        import java.util.jar.JarFile;
040:        import java.util.zip.ZipEntry;
041:        import java.util.zip.ZipInputStream;
042:
043:        import edu.iu.uis.eden.exception.WorkflowRuntimeException;
044:        import edu.iu.uis.eden.util.SimpleEnumeration;
045:
046:        /**
047:         * A ClassLoader implementation which loads a KEW plugin from the classpath.  The plugin could 
048:         * be embedded within a directory location in the parent classloader's classpath or within a jar
049:         * on the parent classloader's classpath.
050:         * 
051:         * <p>Because of the method by which the embedded jars are stored (an archive within an archive) this
052:         * implementation must decompress all of the jars in the embedded plugin "lib" directory and then 
053:         * read all of the classes and resources from those jars into memory.  This means that using this
054:         * class will result in a decent amount of memory use (depending on the number of jars in the embedded
055:         * plugin) in order to allow for the performance of access to those resources to be acceptiable.
056:         * 
057:         * @author ewestfal
058:         */
059:        public class EmbeddedPluginClassLoader extends PluginClassLoader {
060:
061:            private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
062:                    .getLogger(EmbeddedPluginClassLoader.class);
063:
064:            private static final int BUFFER_SIZE = 2048;
065:
066:            /**
067:             * A cache of all the bytes from all of the embedded jars.
068:             */
069:            private Map<URL, Map<String, byte[]>> byteCache = new HashMap<URL, Map<String, byte[]>>();
070:
071:            /**
072:             * List of urls to embedded jars to include in the classpath of this classloader.
073:             */
074:            private List<URL> embeddedJarUrls = new ArrayList<URL>();
075:
076:            /**
077:             * Constucts the classloader to read the embedded plugin from the given path on the classpath. 
078:             */
079:            public EmbeddedPluginClassLoader(String pathToEmbeddedPlugin) {
080:                initialize(pathToEmbeddedPlugin);
081:            }
082:
083:            /**
084:             * Constucts the classloader to read the embedded plugin from the given path on the classpath.
085:             * The specified classloader will be the parent of this classloader.
086:             */
087:            public EmbeddedPluginClassLoader(ClassLoader parent,
088:                    String pathToEmbeddedPlugin) {
089:                super (parent);
090:                initialize(pathToEmbeddedPlugin);
091:            }
092:
093:            /**
094:             * Initializes the classloader from the gven embedded plugin path.  This process includes searching the
095:             * classpath for any .jar files inside of the embedded plugin.  Also, in order for this classloader to
096:             * be responsive enough for real world use, all of the classes in resources in those jars are loaded into
097:             * memory and cached for future access.
098:             */
099:            protected void initialize(String pathToEmbeddedPlugin) {
100:                try {
101:                    establishEmbeddedUrls(pathToEmbeddedPlugin);
102:                    cacheBytes();
103:                } catch (IOException e) {
104:                    throw new WorkflowRuntimeException(e);
105:                } catch (URISyntaxException e) {
106:                    throw new WorkflowRuntimeException(e);
107:                }
108:            }
109:
110:            /**
111:             * Establishes the set of URLs to resources in this classloader's classpath.  The classpath of this classloader is
112:             * composed of the classes directory and all of the jars within the lib directory.  The classes directory is
113:             * added as a standard URL to the parent classloader.
114:             * <p>
115:             * The jars have to be handled differently because they may be embedded within the classpath inside of a jar as 
116:             * opposed to the standard jar loading model where they are located on the filesystem. 
117:             */
118:            protected void establishEmbeddedUrls(String pathToEmbeddedPlugin)
119:                    throws IOException, URISyntaxException {
120:                URL embeddedUrl = getParent().getResource(pathToEmbeddedPlugin);
121:                if (embeddedUrl == null) {
122:                    throw new WorkflowRuntimeException(
123:                            "Could not locate embedded plugin on the classpath at: "
124:                                    + pathToEmbeddedPlugin);
125:                }
126:                URL embeddedClasses = getParent().getResource(
127:                        pathToEmbeddedPlugin + "/" + CLASSES_DIR + "/");
128:                if (embeddedClasses != null) {
129:                    addURL(embeddedClasses);
130:                }
131:                URL libUrl = getParent().getResource(
132:                        pathToEmbeddedPlugin + "/" + LIB_DIR);
133:                // 1) if the lib directory is located inside of a jar, we need to search the jar to locate all embedded jars
134:                // 2) if the lib directory is on the filesystem, we can load the jars using default URL classloading behavior
135:                if (libUrl.getProtocol().equals("jar")) {
136:                    String jarPath = getJarPath(libUrl);
137:                    JarFile jarFile = new JarFile(new File(new URI(jarPath)));
138:                    Enumeration enumeration = jarFile.entries();
139:                    String libPath = pathToEmbeddedPlugin + "/" + LIB_DIR + "/";
140:                    while (enumeration.hasMoreElements()) {
141:                        JarEntry entry = (JarEntry) enumeration.nextElement();
142:                        String name = entry.getName();
143:                        if (name.startsWith(libPath)) {
144:                            String fileName = name.substring(libPath.length());
145:                            if (!fileName.contains("/")
146:                                    && fileName.endsWith(".jar")) {
147:                                addEmbeddedJarURL(getParent().getResource(
148:                                        pathToEmbeddedPlugin + "/" + LIB_DIR
149:                                                + "/" + fileName));
150:                            }
151:                        }
152:                    }
153:                } else if (libUrl.getProtocol().equals("file")) {
154:                    File libDirectory = new File(libUrl.toURI());
155:                    addLibDirectory(libDirectory);
156:                }
157:            }
158:
159:            /**
160:             * Reads all the data from the embedded jars into memory and caches the bytes of all their resources.
161:             */
162:            protected void cacheBytes() {
163:                byte[] data = new byte[BUFFER_SIZE];
164:                for (Iterator iterator = embeddedJarUrls.iterator(); iterator
165:                        .hasNext();) {
166:                    URL jarUrl = (URL) iterator.next();
167:                    ZipInputStream inputStream = openStreamToEmbeddedJar(jarUrl);
168:                    Map<String, byte[]> byteMap = byteCache.get(jarUrl);
169:                    if (byteMap == null) {
170:                        byteMap = new HashMap<String, byte[]>();
171:                        byteCache.put(jarUrl, byteMap);
172:                    }
173:                    try {
174:                        ZipEntry entry;
175:                        while ((entry = inputStream.getNextEntry()) != null) {
176:                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
177:                            BufferedOutputStream os = new BufferedOutputStream(
178:                                    baos, BUFFER_SIZE);
179:                            try {
180:                                int count;
181:                                while ((count = inputStream.read(data, 0,
182:                                        BUFFER_SIZE)) != -1) {
183:                                    os.write(data, 0, count);
184:                                }
185:                                os.flush();
186:                                byteMap
187:                                        .put(entry.getName(), baos
188:                                                .toByteArray());
189:                            } finally {
190:                                os.close();
191:                            }
192:                        }
193:                    } catch (IOException e) {
194:                        throw new WorkflowRuntimeException(e);
195:                    } finally {
196:                        try {
197:                            inputStream.close();
198:                        } catch (IOException e) {
199:                            throw new WorkflowRuntimeException(e);
200:                        }
201:                    }
202:                }
203:            }
204:
205:            /**
206:             * Add a URL to an embedded JAR on the classpath.  This URL should be of a  form
207:             * similar to the following:
208:             * <pre>jar:file:/path/to/mainjar/mainjar.jar!/pathToEmbeddedPlugin/lib/myEmbeddedJar.jar</pre>
209:             */
210:            protected void addEmbeddedJarURL(URL embeddedJarURL)
211:                    throws MalformedURLException {
212:                embeddedJarUrls.add(embeddedJarURL);
213:            }
214:
215:            /**
216:             * Attempts to locate the class with the given name.  It accomplishes this by first looking in the list of
217:             * standard URLs for the given class (this will search the plugin's "classes" directory).  If the class
218:             * cannot be located there it will then search in the embedded jars (this wil search the plugin's 
219:             * "lib" directory).
220:             */
221:            protected Class<?> findClass(String name)
222:                    throws ClassNotFoundException {
223:                Class foundClass = null;
224:                try {
225:                    foundClass = super .findClass(name);
226:                } catch (ClassNotFoundException e) {
227:                    // now look in the embedded jars
228:                    foundClass = findClassInEmbeddedJars(name);
229:                }
230:                if (foundClass != null) {
231:                    return foundClass;
232:                }
233:                throw new ClassNotFoundException(name);
234:            }
235:
236:            /**
237:             * Searches all of the embedded JARs for the Class with the given name.
238:             */
239:            protected Class findClassInEmbeddedJars(String className) {
240:                String classNamePath = classNameToPath(className);
241:                byte[] classBytes = null;
242:                for (URL jarURLKey : byteCache.keySet()) {
243:                    Map<String, byte[]> byteMap = byteCache.get(jarURLKey);
244:                    byte[] bytes = byteMap.get(classNamePath);
245:                    if (bytes != null) {
246:                        classBytes = bytes;
247:                    }
248:                }
249:                if (classBytes != null) {
250:                    return defineClass(className, classBytes, 0,
251:                            classBytes.length);
252:                }
253:                return null;
254:            }
255:
256:            /**
257:             * Return the cached bytes for the given jar and resource.
258:             */
259:            protected byte[] getCachedBytes(String jarPath, String resourceName) {
260:                try {
261:                    Map<String, byte[]> byteMap = byteCache
262:                            .get(new URL(jarPath));
263:                    if (byteMap != null) {
264:                        return byteMap.get(resourceName);
265:                    }
266:                } catch (MalformedURLException e) {
267:                    throw new WorkflowRuntimeException(e);
268:                }
269:                return null;
270:            }
271:
272:            /**
273:             * Opens a ZipInputStream to the embedded jar represented by the given URL.
274:             */
275:            protected ZipInputStream openStreamToEmbeddedJar(URL jarUrl) {
276:                int sepIndex = jarUrl.getPath().indexOf("!");
277:                if (sepIndex == -1) {
278:                    throw new WorkflowRuntimeException(
279:                            "Invalid embedded jar url found: "
280:                                    + jarUrl.toString());
281:                }
282:                // extract the path to the embedded jar within the classpath, given above example, this will be /pathToEmbeddedPlugin/lib/axis.jar
283:                String jarPath = jarUrl.getPath().substring(sepIndex + 2);
284:                return new ZipInputStream(new BufferedInputStream(getParent()
285:                        .getResourceAsStream(jarPath), BUFFER_SIZE));
286:            }
287:
288:            /**
289:             * Finds the resource with the given resourceName by first searching the embedded plugin's "classes" directory and
290:             * then the embedded JARs in the "lib" directory.  It accomplishes the location of embedded jar resources by
291:             * querying the internal resource cache to fetch the resource's bytes.
292:             */
293:            public URL findResource(String resourceName) {
294:                resourceName = normalizeResourceName(resourceName);
295:                URL resource = super .findResource(resourceName);
296:                if (resource == null) {
297:                    try {
298:                        for (URL jarUrl : byteCache.keySet()) {
299:                            Map<String, byte[]> byteMap = byteCache.get(jarUrl);
300:                            if (byteMap.get(resourceName) != null) {
301:                                resource = new URL(null, jarUrl.toString()
302:                                        + "!/" + resourceName,
303:                                        new ByteURLStreamHandler(this ));
304:                                break;
305:                            }
306:                        }
307:                    } catch (MalformedURLException e) {
308:                        throw new WorkflowRuntimeException(e);
309:                    }
310:                }
311:                return resource;
312:            }
313:
314:            /**
315:             * Finds resources by first looking in the superclass, and then looking at
316:             */
317:            public Enumeration<URL> findResources(String name)
318:                    throws IOException {
319:                // TODO should this implementation somehow search for duplicates resources on the classpath?
320:                return new SimpleEnumeration<URL>(findResource(name));
321:            }
322:
323:            /**
324:             * A toString implementation which prints a list of all standard and embedded URLs in the classpath of this
325:             * classloader.
326:             */
327:            public String toString() {
328:                StringBuffer sb = new StringBuffer(
329:                        "[EmbeddedPluginClassLoader: urls=");
330:                URL[] urls = getURLs();
331:                if (urls == null) {
332:                    sb.append("null");
333:                } else {
334:                    for (int i = 0; i < urls.length; i++) {
335:                        sb.append(urls[i]);
336:                        sb.append(",");
337:                    }
338:                    for (Iterator iterator = embeddedJarUrls.iterator(); iterator
339:                            .hasNext();) {
340:                        URL jarUrl = (URL) iterator.next();
341:                        sb.append(jarUrl);
342:                        sb.append(",");
343:                    }
344:                    // remove trailing comma
345:                    if (urls.length > 1) {
346:                        sb.setLength(sb.length() - 1);
347:                    }
348:                }
349:                sb.append("]");
350:                return sb.toString();
351:            }
352:
353:            /**
354:             * Extract the path to the classpath resources within the parent classloader where the
355:             * embedded jar represented by the given URL is located.
356:             * 
357:             * @param url The URL to the embedded jar
358:             * @return the path to embedded jar resources, should be of the form /pathToEmbeddedPlugin/lib/myEmbeddedJar.jar
359:             */
360:            private String getJarPath(URL url) {
361:                String path = url.getPath();
362:                return path.substring(0, path.indexOf("!"));
363:            }
364:
365:            /**
366:             * Converts the given classname to a resource path.  This is accomplished by replacing all periods (.) with
367:             * forward slashes (/).
368:             */
369:            private String classNameToPath(String className) {
370:                className = className.replace('.', '/');
371:                return normalizeResourceName(className) + ".class";
372:            }
373:
374:            /**
375:             * Normalizes the given resource name by removing any leading forward slashes (/).
376:             */
377:            private String normalizeResourceName(String resourceName) {
378:                while (resourceName.startsWith("/")) {
379:                    resourceName = resourceName.substring(1);
380:                }
381:                return resourceName;
382:            }
383:
384:            /**
385:             * A simple URLStreamHandler implementation which is backed by a connection to an array of bytes.
386:             * 
387:             * @author Eric Westfall
388:             */
389:            private static class ByteURLStreamHandler extends URLStreamHandler {
390:
391:                private EmbeddedPluginClassLoader classLoader;
392:
393:                public ByteURLStreamHandler(
394:                        EmbeddedPluginClassLoader classLoader) {
395:                    this .classLoader = classLoader;
396:                }
397:
398:                protected URLConnection openConnection(URL url)
399:                        throws IOException {
400:                    return new ByteURLConnection(url, classLoader);
401:                }
402:
403:            }
404:
405:            /**
406:             * A simple URLConnection implementation which represents a connection to an array of bytes
407:             * via a URL to a resource within an embedded jar
408:             * 
409:             * @author Eric Westfall
410:             */
411:            private static class ByteURLConnection extends URLConnection {
412:
413:                private String jarPath;
414:                private String resourceName;
415:                private EmbeddedPluginClassLoader classLoader;
416:                private byte[] bytes;
417:
418:                public ByteURLConnection(URL url,
419:                        EmbeddedPluginClassLoader classLoader) {
420:                    super (url);
421:                    this .classLoader = classLoader;
422:                    String urlString = url.toString();
423:                    jarPath = urlString
424:                            .substring(0, urlString.lastIndexOf("!"));
425:                    resourceName = urlString.substring(urlString
426:                            .lastIndexOf("!") + 2);
427:                }
428:
429:                public void connect() throws IOException {
430:                    bytes = classLoader.getCachedBytes(jarPath, resourceName);
431:                    if (bytes == null) {
432:                        throw new IOException(
433:                                "Could not access byte data for the given URL: "
434:                                        + url.toString());
435:                    }
436:                }
437:
438:                public InputStream getInputStream() throws IOException {
439:                    if (bytes == null) {
440:                        connect();
441:                    }
442:                    return new BufferedInputStream(new ByteArrayInputStream(
443:                            bytes), BUFFER_SIZE);
444:                }
445:
446:                public int getContentLength() {
447:                    return bytes.length;
448:                }
449:
450:            }
451:
452:            public void stop() {
453:                LOG
454:                        .info("Stopping the EmbeddedPluginClassLoader, clearing byte cache.");
455:                byteCache.clear();
456:                embeddedJarUrls.clear();
457:                super.stop();
458:            }
459:
460:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.