/* * Copyright (C) 2011 The Android Open Source Project * * Licensed 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 android.filterfw.core; import android.filterfw.core.Filter; import android.util.Log; import dalvik.system.PathClassLoader; import java.lang.reflect.Constructor; import java.lang.ClassLoader; import java.lang.Thread; import java.util.HashSet; /** * @hide */ public class FilterFactory { private static FilterFactory mSharedFactory; private HashSet mPackages = new HashSet(); private static ClassLoader mCurrentClassLoader; private static HashSet mLibraries; private static Object mClassLoaderGuard; static { mCurrentClassLoader = Thread.currentThread().getContextClassLoader(); mLibraries = new HashSet(); mClassLoaderGuard = new Object(); } private static final String TAG = "FilterFactory"; private static boolean mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE); public static FilterFactory sharedFactory() { if (mSharedFactory == null) { mSharedFactory = new FilterFactory(); } return mSharedFactory; } /** * Adds a new Java library to the list to be scanned for filters. * libraryPath must be an absolute path of the jar file. This needs to be * static because only one classloader per process can open a shared native * library, which a filter may well have. */ public static void addFilterLibrary(String libraryPath) { if (mLogVerbose) Log.v(TAG, "Adding filter library " + libraryPath); synchronized(mClassLoaderGuard) { if (mLibraries.contains(libraryPath)) { if (mLogVerbose) Log.v(TAG, "Library already added"); return; } mLibraries.add(libraryPath); // Chain another path loader to the current chain mCurrentClassLoader = new PathClassLoader(libraryPath, mCurrentClassLoader); } } public void addPackage(String packageName) { if (mLogVerbose) Log.v(TAG, "Adding package " + packageName); /* TODO: This should use a getPackage call in the caller's context, but no such method exists. Package pkg = Package.getPackage(packageName); if (pkg == null) { throw new IllegalArgumentException("Unknown filter package '" + packageName + "'!"); } */ mPackages.add(packageName); } public Filter createFilterByClassName(String className, String filterName) { if (mLogVerbose) Log.v(TAG, "Looking up class " + className); Class filterClass = null; // Look for the class in the imported packages for (String packageName : mPackages) { try { if (mLogVerbose) Log.v(TAG, "Trying "+packageName + "." + className); synchronized(mClassLoaderGuard) { filterClass = mCurrentClassLoader.loadClass(packageName + "." + className); } } catch (ClassNotFoundException e) { continue; } // Exit loop if class was found. if (filterClass != null) { break; } } if (filterClass == null) { throw new IllegalArgumentException("Unknown filter class '" + className + "'!"); } return createFilterByClass(filterClass, filterName); } public Filter createFilterByClass(Class filterClass, String filterName) { // Make sure this is a Filter subclass try { filterClass.asSubclass(Filter.class); } catch (ClassCastException e) { throw new IllegalArgumentException("Attempting to allocate class '" + filterClass + "' which is not a subclass of Filter!"); } // Look for the correct constructor Constructor filterConstructor = null; try { filterConstructor = filterClass.getConstructor(String.class); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("The filter class '" + filterClass + "' does not have a constructor of the form (String name)!"); } // Construct the filter Filter filter = null; try { filter = (Filter)filterConstructor.newInstance(filterName); } catch (Throwable t) { // Condition checked below } if (filter == null) { throw new IllegalArgumentException("Could not construct the filter '" + filterName + "'!"); } return filter; } }