View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.log4j.chainsaw.plugins;
18  
19  import java.io.File;
20  import java.io.FilenameFilter;
21  import java.net.URL;
22  import java.net.URLClassLoader;
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import org.apache.log4j.chainsaw.prefs.SettingsManager;
27  
28  /**
29   * A factory class to create a Classloader that can refenerence jars/classes/resources
30   * within a users plugin directory.
31   * 
32   * Currently a work in progress to see if this allows external jars required by
33   * some 3rd party vendors for things like the JMSReceiver.
34   *  
35   * @author psmith
36   *
37   * 
38   */
39  public class PluginClassLoaderFactory {
40  	private final ClassLoader pluginClassLoader;
41  
42      private static final PluginClassLoaderFactory instance = new PluginClassLoaderFactory();
43      
44  	private PluginClassLoaderFactory() {
45          this.pluginClassLoader= PluginClassLoaderFactory.create(new File(SettingsManager.getInstance().getSettingsDirectory() + File.separator + "plugins"));
46  
47  	}
48      
49      public static PluginClassLoaderFactory getInstance() {
50       return instance;   
51      }
52      
53      public ClassLoader getClassLoader() {
54       return this.pluginClassLoader;   
55      }
56      
57      /**
58       * Creates a Classloader that will be able to access any of the classes found
59       * in any .JAR file contained within the specified directory path, PLUS
60       * the actual Plugin directory itself, so it acts like the WEB-INF/classes directory,
61       * any class file in the directory will be accessible
62       * 
63       * @param pluginDirectory
64       * @throws IllegalArgumentException if the pluginDirectory is null, does not exist, or cannot be read
65       * @throws RuntimeException if turning a File into a URL failed, which would be very unexpected
66       * @return
67       */
68      private static final ClassLoader create(File pluginDirectory) {
69          if(pluginDirectory == null || !pluginDirectory.exists() || !pluginDirectory.canRead()) {
70           return PluginClassLoaderFactory.class.getClassLoader();
71          }
72          
73          String[] strings = pluginDirectory.list(new FilenameFilter() {
74  
75  			public boolean accept(File dir, String name) {
76                  return name.toUpperCase().endsWith(".JAR");
77  			}});
78          
79        
80          List list = new ArrayList();
81          // add the plugin directory as a resource loading path
82          try {
83  			list.add(pluginDirectory.toURI().toURL());
84  		} catch (Exception e) {
85  			throw new RuntimeException(e.getMessage());
86  		}
87          if (strings !=null) {
88  			for (int i = 0; i < strings.length; i++) {
89  				String name = strings[i];
90  				File file = new File(pluginDirectory, name);
91  				try {
92  					list.add(file.toURI().toURL());
93  					System.out.println("Added " + file.getAbsolutePath()
94  							+ " to Plugin class loader list");
95  				} catch (Exception e) {
96  					System.err.println("Failed to retrieve the URL for file: "
97  							+ file.getAbsolutePath());
98  					throw new RuntimeException(e.getMessage());
99  				}
100 			}
101 		}
102         ClassLoader parent = PluginClassLoaderFactory.class.getClassLoader();
103         URL[] urls = (URL[]) list.toArray(new URL[list.size()]);
104         return new URLClassLoader(urls, parent);
105     }
106 
107 }