Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.axis2.deployment; import org.apache.axis2.classloader.BeanInfoCache; import org.apache.axis2.classloader.BeanInfoCachingClassLoader; import org.apache.commons.io.IOUtils; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import java.net.URLConnection; import java.net.URLStreamHandler; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class DeploymentClassLoader extends URLClassLoader implements BeanInfoCachingClassLoader { // List of URL's private URL[] urls = null; // List of jar files inside the jars in the original url private List embedded_jars; private boolean isChildFirstClassLoading; private final BeanInfoCache beanInfoCache = new BeanInfoCache(); /** * DeploymentClassLoader is extended from URLClassLoader. The constructor * does not override the super constructor, but takes in an addition list of * jar files inside /lib directory. * * @param urls <code>URL</code>s * @param parent parent classloader <code>ClassLoader</code> */ public DeploymentClassLoader(URL[] urls, List embedded_jars, ClassLoader parent, boolean isChildFirstClassLoading) { super(urls, parent); this.urls = urls; this.embedded_jars = embedded_jars; this.isChildFirstClassLoading = isChildFirstClassLoading; } /** * Finds and loads the class with the specified name from the URL search * path. Any URLs referring to JAR files are loaded and opened as needed * until the class is found. * * @param name the name of the class * @return the resulting class * @exception ClassNotFoundException if the class could not be found */ protected Class findClass(String name) throws ClassNotFoundException { Class clazz; try { clazz = super.findClass(name); } catch (ClassNotFoundException e) { byte raw[] = null; try { String completeFileName = name; /** * Replacing org.apache. -> org/apache/... */ completeFileName = completeFileName.replace('.', '/').concat(".class"); raw = getBytes(completeFileName); } catch (Exception ex) { // Fall through } if (raw == null) { throw new ClassNotFoundException("Class Not found : " + name); } clazz = defineClass(name, raw, 0, raw.length); } return clazz; } /** * Finds the resource with the specified name on the URL search path. * * @param resource the name of the resource * @return a <code>URL</code> for the resource, or <code>null</code> * if the resource could not be found. */ public URL findResource(String resource) { URL url = super.findResource(resource); if (url == null) { for (int i = 0; embedded_jars != null && i < embedded_jars.size(); i++) { String libjar_name = (String) embedded_jars.get(i); try { InputStream in = getJarAsStream(libjar_name); ZipInputStream zin = new ZipInputStream(in); ZipEntry entry; String entryName; while ((entry = zin.getNextEntry()) != null) { entryName = entry.getName(); if (entryName != null && entryName.endsWith(resource)) { byte[] raw = IOUtils.toByteArray(zin); return new URL("jar", "", -1, urls[0] + "!/" + libjar_name + "!/" + entryName, new ByteUrlStreamHandler(raw)); } } } catch (Exception e) { throw new RuntimeException(e); } } } return url; } /** * Returns an Enumeration of URLs representing all of the resources * on the URL search path having the specified name. * * @param resource the resource name * @exception IOException if an I/O exception occurs * @return an <code>Enumeration</code> of <code>URL</code>s */ public Enumeration findResources(String resource) throws IOException { ArrayList resources = new ArrayList(); Enumeration e = super.findResources(resource); while (e.hasMoreElements()) { resources.add(e.nextElement()); } for (int i = 0; embedded_jars != null && i < embedded_jars.size(); i++) { String libjar_name = (String) embedded_jars.get(i); try { InputStream in = getJarAsStream(libjar_name); ZipInputStream zin = new ZipInputStream(in); ZipEntry entry; String entryName; while ((entry = zin.getNextEntry()) != null) { entryName = entry.getName(); if (entryName != null && entryName.endsWith(resource)) { byte[] raw = IOUtils.toByteArray(zin); resources.add(new URL("jar", "", -1, urls[0] + "!/" + libjar_name + "!/" + entryName, new ByteUrlStreamHandler(raw))); } } } catch (Exception ex) { throw new RuntimeException(ex); } } return Collections.enumeration(resources); } /** * Access the jars file (/lib) one by one , then for each one create a <code>ZipInputStream</code> * and check to see whether there is any entry eith given name. if it is found then * return the byte array for that * * @param resource <code>String</code> Name of the file to be found * @return byte[] * @throws java.io.IOException <code>Exception</code> */ private byte[] getBytes(String resource) throws Exception { for (int i = 0; embedded_jars != null && i < embedded_jars.size(); i++) { String libjar_name = (String) embedded_jars.get(i); InputStream in = getJarAsStream(libjar_name); byte[] bytes = getBytes(in, resource); if (bytes != null) { return bytes; } } return null; } /** * Get a specific entry's content as a byte array * * @param in * @param resource * @return * @throws Exception */ private byte[] getBytes(InputStream in, String resource) throws Exception { ZipInputStream zin = new ZipInputStream(in); ZipEntry entry; String entryName; while ((entry = zin.getNextEntry()) != null) { entryName = entry.getName(); if (entryName != null && entryName.endsWith(resource)) { byte[] raw = IOUtils.toByteArray(zin); zin.close(); return raw; } } return null; } /** * Get the specified embedded jar from the main jar * * @param libjar_name * @return * @throws Exception */ private InputStream getJarAsStream(String libjar_name) throws Exception { return new ByteArrayInputStream(getBytes(urls[0].openStream(), libjar_name)); } public static class ByteUrlStreamHandler extends URLStreamHandler { private byte[] bytes; public ByteUrlStreamHandler(byte[] bytes) { this.bytes = bytes; } protected URLConnection openConnection(URL u) throws IOException { return new ByteURLConnection(u, bytes); } } public static class ByteURLConnection extends URLConnection { protected byte[] bytes; public ByteURLConnection(URL url, byte[] bytes) { super(url); this.bytes = bytes; } public void connect() { } public InputStream getInputStream() { return new ByteArrayInputStream(bytes); } } public InputStream getResourceAsStream(String name) { URL url = findResource(name); if (url == null) { url = getResource(name); } if (url != null) { try { return url.openStream(); } catch (IOException e) { throw new RuntimeException(e); } } return null; } protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { Class c = null; if (!isChildFirstClassLoading) { c = super.loadClass(name, resolve); } else { c = findLoadedClass(name); if (c == null) { try { c = findClass(name); } catch (Exception e) { c = super.loadClass(name, resolve); } } } return c; } public boolean isChildFirstClassLoading() { return isChildFirstClassLoading; } public void setChildFirstClassLoading(boolean childFirstClassLoading) { isChildFirstClassLoading = childFirstClassLoading; } public final BeanInfoCache getBeanInfoCache() { return beanInfoCache; } }