1 5 package com.tc.plugins; 6 7 import org.apache.xmlbeans.XmlException; 8 import org.osgi.framework.Bundle; 9 import org.osgi.framework.BundleException; 10 import org.osgi.framework.Constants; 11 import org.osgi.framework.InvalidSyntaxException; 12 import org.osgi.framework.ServiceReference; 13 14 import com.tc.bundles.EmbeddedOSGiRuntime; 15 import com.tc.config.schema.setup.ConfigurationSetupException; 16 import com.tc.logging.TCLogger; 17 import com.tc.logging.TCLogging; 18 import com.tc.object.config.ConfigLoader; 19 import com.tc.object.config.DSOClientConfigHelper; 20 import com.tc.object.config.ModuleSpec; 21 import com.tc.object.config.StandardDSOClientConfigHelper; 22 import com.tc.object.loaders.ClassProvider; 23 import com.tc.object.loaders.NamedClassLoader; 24 import com.tc.object.loaders.Namespace; 25 import com.terracottatech.config.DsoApplication; 26 import com.terracottatech.config.Module; 27 import com.terracottatech.config.Modules; 28 29 import java.io.IOException ; 30 import java.io.InputStream ; 31 import java.lang.reflect.Method ; 32 import java.net.MalformedURLException ; 33 import java.net.URL ; 34 import java.util.Dictionary ; 35 import java.util.Hashtable ; 36 import java.util.jar.JarEntry ; 37 import java.util.jar.JarInputStream ; 38 39 public class ModulesLoader { 40 41 private static final TCLogger logger = TCLogging.getLogger(ModulesLoader.class); 42 43 private static final Object lock = new Object (); 44 45 private ModulesLoader() { 46 } 48 49 public static void initModules(final DSOClientConfigHelper configHelper, final ClassProvider classProvider, final boolean forBootJar) { 50 EmbeddedOSGiRuntime osgiRuntime = null; 51 synchronized (lock) { 52 final Modules modules = configHelper.getModulesForInitialization(); 53 if (modules != null && modules.sizeOfModuleArray() > 0) { 54 try { 55 osgiRuntime = EmbeddedOSGiRuntime.Factory.createOSGiRuntime(modules); 56 } catch (Exception e) { 57 throw new RuntimeException ("Unable to create runtime for plugins", e); 58 } 59 try { 60 initModules(osgiRuntime, configHelper, classProvider, modules.getModuleArray(), forBootJar); 61 if (!forBootJar) { 62 getModulesCustomApplicatorSpecs(osgiRuntime, configHelper); 63 } 64 } catch (BundleException be1) { 65 try { 66 osgiRuntime.shutdown(); 67 } catch (BundleException be2) { 68 logger.error("Error shutting down plugin runtime", be2); 69 } 70 throw new RuntimeException ("Exception initializing plugins", be1); 71 } catch (InvalidSyntaxException be1) { 72 try { 73 osgiRuntime.shutdown(); 74 } catch (BundleException be2) { 75 logger.error("Error shutting down plugin runtime", be2); 76 } 77 throw new RuntimeException ("Exception initializing plugins", be1); 78 } finally { 79 if (forBootJar) { 80 try { 81 osgiRuntime.shutdown(); 82 } catch (BundleException be2) { 83 logger.error("Error shutting down plugin runtime", be2); 84 } 85 } 86 } 87 } else { 88 osgiRuntime = null; 89 } 90 } 91 } 92 93 private static void initModules(final EmbeddedOSGiRuntime osgiRuntime, final DSOClientConfigHelper configHelper, 94 final ClassProvider classProvider, final Module[] modules, boolean forBootJar) throws BundleException { 95 osgiRuntime.installBundle("modules-common-1.0", "1.0.0"); 97 for (int pos = 0; pos < modules.length; ++pos) { 98 String bundle = modules[pos].getName() + "-" + modules[pos].getVersion(); 99 logger.info("Installing OSGI bundle " + bundle); 100 osgiRuntime.installBundle(modules[pos].getName(), modules[pos].getVersion()); 101 logger.info("Installation of OSGI bundle " + bundle + " successful"); 102 } 103 if (configHelper instanceof StandardDSOClientConfigHelper) { 104 final Dictionary serviceProps = new Hashtable (); 105 serviceProps.put(Constants.SERVICE_VENDOR, "Terracotta, Inc."); 106 serviceProps.put(Constants.SERVICE_DESCRIPTION, "Main point of entry for programmatic access to" 107 + " the Terracotta bytecode instrumentation"); 108 osgiRuntime.registerService(configHelper, serviceProps); 109 } 110 for (int pos = 0; pos < modules.length; ++pos) { 111 String name = modules[pos].getName(); 112 String version = modules[pos].getVersion(); 113 114 osgiRuntime.startBundle(name, version); 115 116 Bundle bundle = osgiRuntime.getBundle(name, version); 117 if (bundle != null) { 118 if (!forBootJar) { 119 registerClassLoader(classProvider, bundle); 120 } 121 loadConfiguration(configHelper, bundle); 122 } 123 } 124 } 125 126 private static void registerClassLoader(final ClassProvider classProvider, final Bundle bundle) throws BundleException { 127 NamedClassLoader ncl = getClassLoader(bundle); 128 129 String loaderName = Namespace.createLoaderName(Namespace.MODULES_NAMESPACE, ncl.toString()); 130 ncl.__tc_setClassLoaderName(loaderName); 131 classProvider.registerNamedLoader(ncl); 132 } 133 134 private static NamedClassLoader getClassLoader(Bundle bundle) throws BundleException { 135 try { 136 Method m = bundle.getClass().getDeclaredMethod("getClassLoader", new Class [0]); 137 m.setAccessible(true); 138 ClassLoader classLoader = (ClassLoader ) m.invoke(bundle, new Object [0]); 139 return (NamedClassLoader) classLoader; 140 } catch (Throwable t) { 141 throw new BundleException("Unable to get classloader for bundle.", t); 142 } 143 } 144 145 private static void getModulesCustomApplicatorSpecs(final EmbeddedOSGiRuntime osgiRuntime, 146 final DSOClientConfigHelper configHelper) 147 throws InvalidSyntaxException { 148 ServiceReference[] serviceReferences = osgiRuntime.getAllServiceReferences(ModuleSpec.class.getName(), null); 149 if (serviceReferences == null) { return; } 150 ModuleSpec[] modulesSpecs = new ModuleSpec[serviceReferences.length]; 151 for (int i = 0; i < serviceReferences.length; i++) { 152 modulesSpecs[i] = (ModuleSpec) osgiRuntime.getService(serviceReferences[i]); 153 osgiRuntime.ungetService(serviceReferences[i]); 154 } 155 configHelper.setModuleSpecs(modulesSpecs); 156 } 157 158 private static void loadConfiguration(final DSOClientConfigHelper configHelper, final Bundle bundle) 159 throws BundleException { 160 String config = (String ) bundle.getHeaders().get("Terracotta-Configuration"); 161 if (config == null) { 162 config = "terracotta.xml"; 163 } 164 165 final InputStream is; 166 try { 167 is = getJarResource(new URL (bundle.getLocation()), config); 168 } catch (MalformedURLException murle) { 169 throw new BundleException("Unable to create URL from: " + bundle.getLocation(), murle); 170 } catch (IOException ioe) { 171 throw new BundleException("Unable to extract " + config + " from URL: " + bundle.getLocation(), ioe); 172 } 173 if (is == null) { return; } 174 try { 175 DsoApplication application = DsoApplication.Factory.parse(is); 176 if (application != null) { 177 ConfigLoader loader = new ConfigLoader(configHelper, logger); 178 loader.loadDsoConfig(application); 179 logger.info("Module configuration loaded for " + bundle.getSymbolicName()); 180 } 182 } catch (IOException ioe) { 183 logger.warn("Unable to read configuration from bundle: " + bundle.getSymbolicName(), ioe); 184 } catch (XmlException xmle) { 185 logger.warn("Unable to parse configuration from bundle: " + bundle.getSymbolicName(), xmle); 186 } catch (ConfigurationSetupException cse) { 187 logger.warn("Unable to load configuration from bundle: " + bundle.getSymbolicName(), cse); 188 } finally { 189 if (is != null) { 190 try { 191 is.close(); 192 } catch (IOException ex) { 193 } 195 } 196 } 197 } 198 199 public static InputStream getJarResource(final URL location, final String resource) throws IOException { 200 final JarInputStream jis = new JarInputStream (location.openStream()); 201 for (JarEntry entry = jis.getNextJarEntry(); entry != null; entry = jis.getNextJarEntry()) { 202 if (entry.getName().equals(resource)) { return jis; } 203 } 204 return null; 205 } 206 207 } 208 | Popular Tags |