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