001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 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 org.apache.xbean.classpath; 018 019 import java.io.File; 020 import java.lang.reflect.Method; 021 import java.net.URL; 022 import java.net.URLClassLoader; 023 import java.security.AccessController; 024 import java.security.PrivilegedAction; 025 026 public class TomcatClassPath extends SunURLClassPath { 027 028 /** 029 * The Tomcat Common ClassLoader 030 */ 031 private final ClassLoader classLoader; 032 033 /** 034 * The addRepository(String jar) method of the Tomcat Common ClassLoader 035 */ 036 private Method addRepositoryMethod; 037 private Method addURLMethod; 038 039 040 public TomcatClassPath() { 041 this(getCommonLoader(getContextClassLoader()).getParent()); 042 } 043 044 public TomcatClassPath(ClassLoader classLoader){ 045 this.classLoader = classLoader; 046 try { 047 addRepositoryMethod = getAddRepositoryMethod(); 048 } catch (Exception tomcat4Exception) { 049 // Must be tomcat 5 050 try { 051 addURLMethod = getAddURLMethod(); 052 } catch (Exception tomcat5Exception) { 053 throw new RuntimeException("Failed accessing classloader for Tomcat 4 or 5", tomcat5Exception); 054 } 055 } 056 } 057 058 private static ClassLoader getCommonLoader(ClassLoader loader) { 059 if (loader.getClass().getName().equals("org.apache.catalina.loader.StandardClassLoader")) { 060 return loader; 061 } else { 062 return getCommonLoader(loader.getParent()); 063 } 064 } 065 066 public ClassLoader getClassLoader() { 067 return classLoader; 068 } 069 070 public void addJarsToPath(File dir) throws Exception { 071 String[] jarNames = dir.list(new java.io.FilenameFilter() { 072 public boolean accept(File dir, String name) { 073 return (name.endsWith(".jar") || name.endsWith(".zip")); 074 } 075 }); 076 077 if (jarNames == null) { 078 return; 079 } 080 081 for (int j = 0; j < jarNames.length; j++) { 082 this.addJarToPath(new File(dir, jarNames[j]).toURL()); 083 } 084 rebuild(); 085 } 086 087 public void addJarToPath(URL jar) throws Exception { 088 this._addJarToPath(jar); 089 rebuild(); 090 } 091 092 public void _addJarToPath(URL jar) throws Exception { 093 String path = jar.toExternalForm(); 094 this.addRepository(path); 095 } 096 097 public void addRepository(String path) throws Exception { 098 if (addRepositoryMethod != null){ 099 addRepositoryMethod.invoke(getClassLoader(), new Object[]{path}); 100 } else { 101 addURLMethod.invoke(getClassLoader(), new Object[]{new File(path).toURL()}); 102 } 103 } 104 105 protected void rebuild() { 106 try { 107 sun.misc.URLClassPath cp = getURLClassPath((URLClassLoader) getClassLoader()); 108 URL[] urls = cp.getURLs(); 109 //for (int i=0; i < urls.length; i++){ 110 // System.out.println(urls[i].toExternalForm()); 111 //} 112 if (urls.length < 1) 113 return; 114 115 StringBuffer path = new StringBuffer(urls.length * 32); 116 117 File s = new File(urls[0].getFile()); 118 path.append(s.getPath()); 119 //System.out.println(s.getPath()); 120 121 for (int i = 1; i < urls.length; i++) { 122 path.append(File.pathSeparator); 123 124 s = new File(urls[i].getFile()); 125 //System.out.println(s.getPath()); 126 path.append(s.getPath()); 127 } 128 System.setProperty("java.class.path", path.toString()); 129 } catch (Exception e) { 130 } 131 132 } 133 134 /** 135 * This method gets the Tomcat StandardClassLoader.addRepository method 136 * via reflection. This allows us to call the addRepository method for 137 * Tomcat integration, but doesn't require us to include or ship any 138 * Tomcat libraries. 139 * 140 * @return URLClassLoader.addURL method instance 141 */ 142 private Method getAddURLMethod() throws Exception { 143 return (Method) AccessController.doPrivileged(new PrivilegedAction() { 144 public Object run() { 145 Method method = null; 146 try { 147 Class clazz = URLClassLoader.class; 148 method = clazz.getDeclaredMethod("addURL", new Class[]{URL.class}); 149 method.setAccessible(true); 150 return method; 151 } catch (Exception e2) { 152 e2.printStackTrace(); 153 } 154 return method; 155 } 156 }); 157 } 158 159 private Method getAddRepositoryMethod() throws Exception { 160 return (Method) AccessController.doPrivileged(new PrivilegedAction() { 161 public Object run() { 162 Method method = null; 163 try { 164 Class clazz = getClassLoader().getClass(); 165 method = clazz.getDeclaredMethod("addRepository", new Class[]{String.class}); 166 method.setAccessible(true); 167 return method; 168 } catch (Exception e2) { 169 throw (IllegalStateException) new IllegalStateException("Unable to find or access the addRepository method in StandardClassLoader").initCause(e2); 170 } 171 } 172 }); 173 } 174 175 }