diff options
Diffstat (limited to 'media/mca/filterfw/java/android/filterfw/core/FilterFactory.java')
-rw-r--r-- | media/mca/filterfw/java/android/filterfw/core/FilterFactory.java | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/media/mca/filterfw/java/android/filterfw/core/FilterFactory.java b/media/mca/filterfw/java/android/filterfw/core/FilterFactory.java new file mode 100644 index 0000000..779df99 --- /dev/null +++ b/media/mca/filterfw/java/android/filterfw/core/FilterFactory.java @@ -0,0 +1,145 @@ +/* + * 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; + } +} |