001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019:
020: package org.apache.axis2.deployment;
021:
022: import org.apache.axiom.attachments.utils.IOUtils;
023:
024: import java.io.ByteArrayInputStream;
025: import java.io.IOException;
026: import java.io.InputStream;
027: import java.net.URL;
028: import java.net.URLClassLoader;
029: import java.net.URLStreamHandler;
030: import java.net.URLConnection;
031: import java.util.ArrayList;
032: import java.util.Collections;
033: import java.util.Enumeration;
034: import java.util.List;
035: import java.util.HashMap;
036:
037: import java.util.zip.ZipEntry;
038: import java.util.zip.ZipInputStream;
039:
040: public class DeploymentClassLoader extends URLClassLoader {
041: // List of URL's
042: private URL[] urls = null;
043:
044: // List of jar files inside the jars in the original url
045: private List embedded_jars;
046:
047: private HashMap loadedClass = new HashMap();
048:
049: /**
050: * DeploymentClassLoader is extended from URLClassLoader. The constructor
051: * does not override the super constructor, but takes in an addition list of
052: * jar files inside /lib directory.
053: *
054: * @param urls <code>URL</code>s
055: * @param parent parent classloader <code>ClassLoader</code>
056: */
057: public DeploymentClassLoader(URL[] urls, List embedded_jars,
058: ClassLoader parent) {
059: super (urls, parent);
060: this .urls = urls;
061: this .embedded_jars = embedded_jars;
062: }
063:
064: /**
065: * Finds and loads the class with the specified name from the URL search
066: * path. Any URLs referring to JAR files are loaded and opened as needed
067: * until the class is found.
068: *
069: * @param name the name of the class
070: * @return the resulting class
071: * @exception ClassNotFoundException if the class could not be found
072: */
073: protected Class findClass(String name)
074: throws ClassNotFoundException {
075: Class clazz;
076: try {
077: clazz = super .findClass(name);
078: } catch (ClassNotFoundException e) {
079: byte raw[] = null;
080: try {
081: String completeFileName = name;
082: /**
083: * Replacing org.apache. -> org/apache/...
084: */
085: completeFileName = completeFileName.replace('.', '/')
086: .concat(".class");
087: raw = getBytes(completeFileName);
088: } catch (Exception ex) {
089: // Fall through
090: }
091: if (raw == null) {
092: throw new ClassNotFoundException("Class Not found : "
093: + name);
094: }
095: clazz = defineClass(name, raw, 0, raw.length);
096: }
097: return clazz;
098: }
099:
100: /**
101: * Finds the resource with the specified name on the URL search path.
102: *
103: * @param resource the name of the resource
104: * @return a <code>URL</code> for the resource, or <code>null</code>
105: * if the resource could not be found.
106: */
107: public URL findResource(String resource) {
108: URL url = super .findResource(resource);
109: if (url == null) {
110: for (int i = 0; embedded_jars != null
111: && i < embedded_jars.size(); i++) {
112: String libjar_name = (String) embedded_jars.get(i);
113: try {
114: InputStream in = getJarAsStream(libjar_name);
115: ZipInputStream zin = new ZipInputStream(in);
116: ZipEntry entry;
117: String entryName;
118: while ((entry = zin.getNextEntry()) != null) {
119: entryName = entry.getName();
120: if (entryName != null
121: && entryName.endsWith(resource)) {
122: byte[] raw = IOUtils
123: .getStreamAsByteArray(zin);
124: return new URL("jar", "", -1, urls[0]
125: + "!/" + libjar_name + "!/"
126: + entryName,
127: new ByteUrlStreamHandler(raw));
128: }
129: }
130: } catch (Exception e) {
131: throw new RuntimeException(e);
132: }
133: }
134: }
135: return url;
136: }
137:
138: /**
139: * Returns an Enumeration of URLs representing all of the resources
140: * on the URL search path having the specified name.
141: *
142: * @param resource the resource name
143: * @exception IOException if an I/O exception occurs
144: * @return an <code>Enumeration</code> of <code>URL</code>s
145: */
146: public Enumeration findResources(String resource)
147: throws IOException {
148: ArrayList resources = new ArrayList();
149: Enumeration e = super .findResources(resource);
150: while (e.hasMoreElements()) {
151: resources.add(e.nextElement());
152: }
153: for (int i = 0; embedded_jars != null
154: && i < embedded_jars.size(); i++) {
155: String libjar_name = (String) embedded_jars.get(i);
156: try {
157: InputStream in = getJarAsStream(libjar_name);
158: ZipInputStream zin = new ZipInputStream(in);
159: ZipEntry entry;
160: String entryName;
161: while ((entry = zin.getNextEntry()) != null) {
162: entryName = entry.getName();
163: if (entryName != null
164: && entryName.endsWith(resource)) {
165: byte[] raw = IOUtils.getStreamAsByteArray(zin);
166: resources.add(new URL("jar", "", -1,
167: urls[0] + "!/" + libjar_name + "!/"
168: + entryName,
169: new ByteUrlStreamHandler(raw)));
170: }
171: }
172: } catch (Exception ex) {
173: throw new RuntimeException(ex);
174: }
175: }
176: return Collections.enumeration(resources);
177: }
178:
179: /**
180: * Access the jars file (/lib) one by one , then for each one create a <code>ZipInputStream</code>
181: * and check to see whether there is any entry eith given name. if it is found then
182: * return the byte array for that
183: *
184: * @param resource <code>String</code> Name of the file to be found
185: * @return byte[]
186: * @throws java.io.IOException <code>Exception</code>
187: */
188: private byte[] getBytes(String resource) throws Exception {
189: for (int i = 0; embedded_jars != null
190: && i < embedded_jars.size(); i++) {
191: String libjar_name = (String) embedded_jars.get(i);
192: InputStream in = getJarAsStream(libjar_name);
193: byte[] bytes = getBytes(in, resource);
194: if (bytes != null) {
195: return bytes;
196: }
197: }
198: return null;
199: }
200:
201: /**
202: * Get a specific entry's content as a byte array
203: *
204: * @param in
205: * @param resource
206: * @return
207: * @throws Exception
208: */
209: private byte[] getBytes(InputStream in, String resource)
210: throws Exception {
211: ZipInputStream zin = new ZipInputStream(in);
212: ZipEntry entry;
213: String entryName;
214: while ((entry = zin.getNextEntry()) != null) {
215: entryName = entry.getName();
216: if (entryName != null && entryName.endsWith(resource)) {
217: byte[] raw = IOUtils.getStreamAsByteArray(zin);
218: zin.close();
219: return raw;
220: }
221: }
222: return null;
223: }
224:
225: /**
226: * Get the specified embedded jar from the main jar
227: *
228: * @param libjar_name
229: * @return
230: * @throws Exception
231: */
232: private InputStream getJarAsStream(String libjar_name)
233: throws Exception {
234: return new ByteArrayInputStream(getBytes(urls[0].openStream(),
235: libjar_name));
236: }
237:
238: public static class ByteUrlStreamHandler extends URLStreamHandler {
239: private byte[] bytes;
240:
241: public ByteUrlStreamHandler(byte[] bytes) {
242: this .bytes = bytes;
243: }
244:
245: protected URLConnection openConnection(URL u)
246: throws IOException {
247: return new ByteURLConnection(u, bytes);
248: }
249: }
250:
251: public static class ByteURLConnection extends URLConnection {
252: protected byte[] bytes;
253:
254: public ByteURLConnection(URL url, byte[] bytes) {
255: super (url);
256: this .bytes = bytes;
257: }
258:
259: public void connect() {
260: }
261:
262: public InputStream getInputStream() {
263: return new ByteArrayInputStream(bytes);
264: }
265: }
266:
267: public InputStream getResourceAsStream(String name) {
268: URL url = findResource(name);
269: if (url == null) {
270: url = getResource(name);
271: }
272: if (url != null) {
273: try {
274: return url.openStream();
275: } catch (IOException e) {
276: throw new RuntimeException(e);
277: }
278: }
279: return null;
280: }
281: }
|