| /* |
| * 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<String> mPackages = new HashSet<String>(); |
| |
| private static ClassLoader mCurrentClassLoader; |
| private static HashSet<String> mLibraries; |
| private static Object mClassLoaderGuard; |
| |
| static { |
| mCurrentClassLoader = Thread.currentThread().getContextClassLoader(); |
| mLibraries = new HashSet<String>(); |
| 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 <init>(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; |
| } |
| } |