/* * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * 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. * * Contributors: * bstefanescu */ package org.nuxeo.ecm.webengine.jaxrs; import java.lang.reflect.Array; import java.util.ArrayList; import org.osgi.framework.Bundle; /** * Some helper methods for parsing configuration and loading contributed servlets or filters. * * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> */ public class Utils { /** * Load classes from a list of class references given as a comma separated string list. * * @param classRefs the string containing the list of class references * @return an array of the loaded classes * @throws ClassNotFoundException * @throws BundleNotFoundException */ public static Class<?>[] loadClasses(String classRefs) throws ClassNotFoundException, BundleNotFoundException { return loadClasses(classRefs, ','); } /** * Load classes from a list of class references given as a 'sep' separated string list. * * @param classRefs the string containing the list of class references * @param sep the separator character used to separate class references in the string. * @return an array of the loaded classes * @throws ClassNotFoundException * @throws BundleNotFoundException */ public static Class<?>[] loadClasses(String classRefs, char sep) throws ClassNotFoundException, BundleNotFoundException { StringBuilder buf = null; ArrayList<Class<?>> classes = new ArrayList<Class<?>>(); char[] chars = classRefs.toCharArray(); for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (c <= ' ') { continue; } else if (c == sep) { if (buf != null) { classes.add(loadClass(buf.toString())); buf = null; } } else { if (buf == null) { buf = new StringBuilder(); } buf.append(c); } } if (buf != null) { classes.add(loadClass(buf.toString())); } return classes.toArray(new Class<?>[classes.size()]); } /** * Get class instances for the given class references string * * @param <T> * @param componentType the type of the expected array component * @param classRefs * @return * @see {@link #loadClasses(String)} */ public static <T> T[] newInstances(Class<T> componentType, String classRefs) throws ReflectiveOperationException, BundleNotFoundException { return newInstances(componentType, classRefs, ','); } /** * Get class instances for the given class references string * * @param <T> * @param componentType * @param classRefs * @param sep * @return * @see {@link #loadClasses(String, char)} */ @SuppressWarnings("unchecked") public static <T> T[] newInstances(Class<T> componentType, String classRefs, char sep) throws ReflectiveOperationException, BundleNotFoundException { Class<?>[] classes = loadClasses(classRefs, sep); T[] ar = (T[]) Array.newInstance(componentType, classes.length); for (int i = 0; i < classes.length; i++) { ar[i] = (T) classes[i].newInstance(); } return ar; } /** * Load a class from a class reference string. The class reference string is in the format: * <code>bundleSymbolicName:className</code> or <code>className</code>. If no bundle symbolic name is given the * class will be loaded using the class loader of the {@link Utils} class. * <p> * The bundle will be resolved to the last version of the bundle (in case when different bundle versions are found) * * @param classRef * @return */ public static Class<?> loadClass(String classRef) throws ClassNotFoundException, BundleNotFoundException { int i = classRef.indexOf(':'); if (i == -1) { // use the current bundle class loader return Activator.getInstance().getContext().getBundle().loadClass(classRef.trim()); } else { return loadClass(classRef.substring(0, i).trim(), classRef.substring(i + 1).trim()); } } /** * Get a class proxy reference for the given class reference * * @param classRef * @return */ public static ClassRef getClassRef(String classRef) throws ClassNotFoundException, BundleNotFoundException { return getClassRef(classRef, null); } public static ClassRef getClassRef(String classRef, Bundle bundle) throws ClassNotFoundException, BundleNotFoundException { int i = classRef.indexOf(':'); if (i == -1) { // use the current bundle class loader if (bundle == null) { bundle = Activator.getInstance().getContext().getBundle(); } return new ClassRef(bundle, bundle.loadClass(classRef.trim())); } else { String bundleId = classRef.substring(0, i).trim(); String className = classRef.substring(i + 1).trim(); Bundle[] bundles = Activator.getInstance().getPackageAdmin().getBundles(bundleId, null); if (bundles != null) { return new ClassRef(bundles[0], bundles[0].loadClass(className)); } else { throw new BundleNotFoundException(bundleId); } } } /** * Load a class given the owner bundle and the class name. * <p> * The bundle will be resolved to the last version of the bundle (in case when different bundle versions are found) * * @param bundleId * @param className * @return * @throws ClassNotFoundException * @throws BundleNotFoundException */ public static Class<?> loadClass(String bundleId, String className) throws ClassNotFoundException, BundleNotFoundException { Bundle[] bundles = Activator.getInstance().getPackageAdmin().getBundles(bundleId, null); if (bundles != null) { return bundles[0].loadClass(className); } else { throw new BundleNotFoundException(bundleId); } } /** * Create a new object of the given class in the given bundle. The class should provide a no-args empty constructor. * <p> * The bundle will be resolved to the last version of the bundle (in case when different bundle versions are found) * * @param bundleId * @param className * @return * @see {@link #loadClass(String, String)} */ public static Object newInstance(String bundleId, String className) throws ReflectiveOperationException, BundleNotFoundException { return loadClass(bundleId, className).newInstance(); } /** * Create a new object of the given a class reference. * <p> * The bundle will be resolved to the last version of the bundle (in case when different bundle versions are found) * * @param classRef * @return * @see {@link #loadClass(String, String)} */ public static Object newInstance(String classRef) throws ReflectiveOperationException, BundleNotFoundException { return loadClass(classRef).newInstance(); } public static class ClassRef { protected Bundle bundle; protected Class<?> clazz; public ClassRef(Bundle bundle, Class<?> clazz) { this.bundle = bundle; this.clazz = clazz; } public Class<?> get() { return clazz; } public Bundle bundle() { return bundle; } public Object newInstance() throws ReflectiveOperationException { return clazz.newInstance(); } @Override public String toString() { if (bundle != null) { return bundle.getSymbolicName() + ":" + clazz.getName(); } return clazz.getName(); } } }