001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * bstefanescu 011 */ 012package org.nuxeo.ecm.webengine.jaxrs; 013 014import java.lang.reflect.Array; 015import java.util.ArrayList; 016 017import org.osgi.framework.Bundle; 018 019/** 020 * Some helper methods for parsing configuration and loading contributed servlets or filters. 021 * 022 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 023 */ 024public class Utils { 025 026 /** 027 * Load classes from a list of class references given as a comma separated string list. 028 * 029 * @param classRefs the string containing the list of class references 030 * @return an array of the loaded classes 031 * @throws ClassNotFoundException 032 * @throws BundleNotFoundException 033 */ 034 public static Class<?>[] loadClasses(String classRefs) throws ClassNotFoundException, BundleNotFoundException { 035 return loadClasses(classRefs, ','); 036 } 037 038 /** 039 * Load classes from a list of class references given as a 'sep' separated string list. 040 * 041 * @param classRefs the string containing the list of class references 042 * @param sep the separator character used to separate class references in the string. 043 * @return an array of the loaded classes 044 * @throws ClassNotFoundException 045 * @throws BundleNotFoundException 046 */ 047 public static Class<?>[] loadClasses(String classRefs, char sep) throws ClassNotFoundException, 048 BundleNotFoundException { 049 StringBuilder buf = null; 050 ArrayList<Class<?>> classes = new ArrayList<Class<?>>(); 051 char[] chars = classRefs.toCharArray(); 052 for (int i = 0; i < chars.length; i++) { 053 char c = chars[i]; 054 if (c <= ' ') { 055 continue; 056 } else if (c == sep) { 057 if (buf != null) { 058 classes.add(loadClass(buf.toString())); 059 buf = null; 060 } 061 } else { 062 if (buf == null) { 063 buf = new StringBuilder(); 064 } 065 buf.append(c); 066 } 067 } 068 069 if (buf != null) { 070 classes.add(loadClass(buf.toString())); 071 } 072 073 return classes.toArray(new Class<?>[classes.size()]); 074 } 075 076 /** 077 * Get class instances for the given class references string 078 * 079 * @param <T> 080 * @param componentType the type of the expected array component 081 * @param classRefs 082 * @return 083 * @see {@link #loadClasses(String)} 084 */ 085 public static <T> T[] newInstances(Class<T> componentType, String classRefs) throws ReflectiveOperationException, 086 BundleNotFoundException { 087 return newInstances(componentType, classRefs, ','); 088 } 089 090 /** 091 * Get class instances for the given class references string 092 * 093 * @param <T> 094 * @param componentType 095 * @param classRefs 096 * @param sep 097 * @return 098 * @see {@link #loadClasses(String, char)} 099 */ 100 @SuppressWarnings("unchecked") 101 public static <T> T[] newInstances(Class<T> componentType, String classRefs, char sep) 102 throws ReflectiveOperationException, BundleNotFoundException { 103 Class<?>[] classes = loadClasses(classRefs, sep); 104 T[] ar = (T[]) Array.newInstance(componentType, classes.length); 105 for (int i = 0; i < classes.length; i++) { 106 ar[i] = (T) classes[i].newInstance(); 107 } 108 return ar; 109 } 110 111 /** 112 * Load a class from a class reference string. The class reference string is in the format: 113 * <code>bundleSymbolicName:className</code> or <code>className</code>. If no bundle symbolic name is given the 114 * class will be loaded using the class loader of the {@link Utils} class. 115 * <p> 116 * The bundle will be resolved to the last version of the bundle (in case when different bundle versions are found) 117 * 118 * @param classRef 119 * @return 120 */ 121 public static Class<?> loadClass(String classRef) throws ClassNotFoundException, BundleNotFoundException { 122 int i = classRef.indexOf(':'); 123 if (i == -1) { 124 // use the current bundle class loader 125 return Activator.getInstance().getContext().getBundle().loadClass(classRef.trim()); 126 } else { 127 return loadClass(classRef.substring(0, i).trim(), classRef.substring(i + 1).trim()); 128 } 129 } 130 131 /** 132 * Get a class proxy reference for the given class reference 133 * 134 * @param classRef 135 * @return 136 */ 137 public static ClassRef getClassRef(String classRef) throws ClassNotFoundException, BundleNotFoundException { 138 return getClassRef(classRef, null); 139 } 140 141 public static ClassRef getClassRef(String classRef, Bundle bundle) throws ClassNotFoundException, 142 BundleNotFoundException { 143 int i = classRef.indexOf(':'); 144 if (i == -1) { 145 // use the current bundle class loader 146 if (bundle == null) { 147 bundle = Activator.getInstance().getContext().getBundle(); 148 } 149 return new ClassRef(bundle, bundle.loadClass(classRef.trim())); 150 } else { 151 String bundleId = classRef.substring(0, i).trim(); 152 String className = classRef.substring(i + 1).trim(); 153 Bundle[] bundles = Activator.getInstance().getPackageAdmin().getBundles(bundleId, null); 154 if (bundles != null) { 155 return new ClassRef(bundles[0], bundles[0].loadClass(className)); 156 } else { 157 throw new BundleNotFoundException(bundleId); 158 } 159 } 160 } 161 162 /** 163 * Load a class given the owner bundle and the class name. 164 * <p> 165 * The bundle will be resolved to the last version of the bundle (in case when different bundle versions are found) 166 * 167 * @param bundleId 168 * @param className 169 * @return 170 * @throws ClassNotFoundException 171 * @throws BundleNotFoundException 172 */ 173 public static Class<?> loadClass(String bundleId, String className) throws ClassNotFoundException, 174 BundleNotFoundException { 175 Bundle[] bundles = Activator.getInstance().getPackageAdmin().getBundles(bundleId, null); 176 if (bundles != null) { 177 return bundles[0].loadClass(className); 178 } else { 179 throw new BundleNotFoundException(bundleId); 180 } 181 } 182 183 /** 184 * Create a new object of the given class in the given bundle. The class should provide a no-args empty constructor. 185 * <p> 186 * The bundle will be resolved to the last version of the bundle (in case when different bundle versions are found) 187 * 188 * @param bundleId 189 * @param className 190 * @return 191 * @see {@link #loadClass(String, String)} 192 */ 193 public static Object newInstance(String bundleId, String className) throws ReflectiveOperationException, 194 BundleNotFoundException { 195 return loadClass(bundleId, className).newInstance(); 196 } 197 198 /** 199 * Create a new object of the given a class reference. 200 * <p> 201 * The bundle will be resolved to the last version of the bundle (in case when different bundle versions are found) 202 * 203 * @param classRef 204 * @return 205 * @see {@link #loadClass(String, String)} 206 */ 207 public static Object newInstance(String classRef) throws ReflectiveOperationException, BundleNotFoundException { 208 return loadClass(classRef).newInstance(); 209 } 210 211 public static class ClassRef { 212 protected Bundle bundle; 213 214 protected Class<?> clazz; 215 216 public ClassRef(Bundle bundle, Class<?> clazz) { 217 this.bundle = bundle; 218 this.clazz = clazz; 219 } 220 221 public Class<?> get() { 222 return clazz; 223 } 224 225 public Bundle bundle() { 226 return bundle; 227 } 228 229 public Object newInstance() throws ReflectiveOperationException { 230 return clazz.newInstance(); 231 } 232 233 @Override 234 public String toString() { 235 if (bundle != null) { 236 return bundle.getSymbolicName() + ":" + clazz.getName(); 237 } 238 return clazz.getName(); 239 } 240 241 } 242 243}