/* * 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 com.sun.jini.start; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.activation.ActivationException; import java.rmi.activation.ActivationID; import java.security.SecureClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.logging.Level; import java.util.logging.Logger; import java.util.StringTokenizer; import net.jini.loader.ClassAnnotation; /** * This class provides useful utilities for creating and * manipulating class loaders. * * @author Sun Microsystems, Inc. * */ public class ClassLoaderUtil { /** Configure logger */ static final Logger logger = Logger.getLogger("com.sun.jini.start.ClassLoaderUtil"); // Private constructor to prevent instantiation private ClassLoaderUtil() { } /** * Utility method that converts the components of a <code>String</code> * representing a classpath into file <code>URL</code>(s). * * @param classpath <code>String</code> containing components separated * by path separators that represent the components * making up a classpath * * @return a <code>URL[]</code> where * each element of the array corresponds to one of the components * in the <code>classpath</code> parameter. The path components * are (potentially) expanded via * <code>File.getCanonicalFile()</code> before converting to a * <code>URL</code> format. * * @throws java.net.MalformedURLException * If the path cannot be parsed as a URL * @throws java.net.IOException * If an I/O error occurs, * which is possible because the construction of * the canonical pathname may require filesystem queries */ public static URL[] getClasspathURLs(String classpath) throws IOException, MalformedURLException { StringTokenizer st = new StringTokenizer(classpath,File.pathSeparator); URL[] urls = new URL[st.countTokens()]; for (int i=0; st.hasMoreTokens(); i++) { urls[i] = new File(st.nextToken()).getCanonicalFile().toURI().toURL(); } return urls; }//end getClasspathURLs /** * Utility method that converts the components of a <code>String</code> * representing a codebase into standard <code>URL</code>(s). * * @param codebase <code>String</code> containing components separated * by spaces in which each component is in * <code>URL</code> format. * * @return a <code>URL[]</code> where * each element of the array corresponds to one of the components * in the <code>codebase</code> parameter * * @throws java.net.MalformedURLException */ public static URL[] getCodebaseURLs(String codebase) throws MalformedURLException { StringTokenizer st = new StringTokenizer(codebase); URL[] urls = new URL[st.countTokens()]; for (int i=0; st.hasMoreTokens(); i++) { urls[i] = new URL(st.nextToken()); } return urls; }//end getCodebaseURLs /** * Utility method that converts the components of a <code>String</code> * representing a codebase or classpath into <code>URL</code>(s). * * @param importCodebase <code>String</code> assumed (in order) to be either * 1) a space delimited set of <code>URL</code>(s) * representing a codebase or * 2) a <code>File.pathSeparator</code> delimited set * of class paths. * * @return a <code>URL[]</code> where * each element of the array corresponds to one of the components * in the <code>importCodebase</code> parameter * * @throws java.net.MalformedURLException * If the path cannot be parsed as a URL * @throws java.net.IOException * If an I/O error occurs, * which is possible because the construction of * the canonical pathname may require filesystem queries */ public static URL[] getImportCodebaseURLs(String importCodebase) throws IOException, MalformedURLException { try { return getCodebaseURLs(importCodebase); } catch (MalformedURLException me) { return getClasspathURLs(importCodebase); } }//end getImportCodebaseURLs /** * Utility method that retrieves the components making up the class loader * delegation tree for the current context class loader and returns each * in an <code>ArrayList</code>. * * @return an <code>ArrayList</code> instance in which each element of the * list is one of the components making up the current delegation * tree. */ private static ArrayList getContextClassLoaderTree() { Thread curThread = Thread.currentThread(); ClassLoader curClassLoader = curThread.getContextClassLoader(); return getClassLoaderTree(curClassLoader); }//end getCurClassLoaderTree /** * Utility method that retrieves the components making up the class loader * delegation tree for the given <code>classloader</code> parameter and * returns them via an <code>ArrayList</code>. * * @param classloader <code>ClassLoader</code> instance whose delegation * tree is to be retrieved and returned * * @return an <code>ArrayList</code> instance in which each element of the * list is one of the components making up the delegation tree * of the given class loader. */ private static ArrayList getClassLoaderTree(ClassLoader classloader) { ArrayList loaderList = new ArrayList(); while(classloader != null) { loaderList.add(classloader); classloader = classloader.getParent(); }//end loop loaderList.add(null); //Append boot classloader Collections.reverse(loaderList); return loaderList; }//end getClassLoaderTree /** * Utility method that displays the class loader delegation tree for * the current context class loader. For each class loader in the tree, * this method displays the locations from which that class loader * will retrieve and load requested classes. * <p> * This method can be useful when debugging problems related to the * receipt of exceptions such as <code>ClassNotFoundException</code>. */ public static void displayContextClassLoaderTree() { Thread curThread = Thread.currentThread(); ClassLoader curClassLoader = curThread.getContextClassLoader(); displayClassLoaderTree(curClassLoader); }//end displayCurClassLoaderTree /** * Utility method that displays the class loader delegation tree for * the given class loader. For each class loader in the tree, this * method displays the locations from which that class loader will * retrieve and load requested classes. * <p> * This method can be useful when debugging problems related to the * receipt of exceptions such as <code>ClassNotFoundException</code>. * * @param classloader <code>ClassLoader</code> instance whose delegation * tree is to be displayed */ public static void displayClassLoaderTree(ClassLoader classloader) { ArrayList loaderList = getClassLoaderTree(classloader); System.out.println(""); System.out.println("ClassLoader Tree has " + loaderList.size() + " levels"); System.out.println(" cl0 -- Boot ClassLoader "); ClassLoader curClassLoader = null; for(int i=1; i < loaderList.size(); i++) { System.out.println(" |"); curClassLoader = (ClassLoader)loaderList.get(i); System.out.print(" cl"+i+" -- ClassLoader " +curClassLoader+": "); if(curClassLoader instanceof URLClassLoader) { URL[] urls = ((URLClassLoader)(curClassLoader)).getURLs(); if(urls != null) { System.out.print(urls[0]); for(int j=1;j<urls.length;j++){ System.out.print(", "+urls[j]); } } else {//urls == null System.out.print("null search path"); }//endif } else { if(curClassLoader instanceof SecureClassLoader) { System.out.print("is instance of SecureClassLoader"); } else { System.out.print("is unknown ClassLoader type"); } }//endif System.out.println(""); }//end loop System.out.println(""); }//end displayClassLoaderTree }//end class ClassLoaderUtil