001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package org.terracotta.modules.configuration;
006:
007: import org.osgi.framework.Bundle;
008: import org.osgi.framework.BundleActivator;
009: import org.osgi.framework.BundleContext;
010: import org.osgi.framework.BundleException;
011: import org.osgi.framework.ServiceReference;
012:
013: import com.tc.bundles.BundleSpec;
014: import com.tc.object.bytecode.ByteCodeUtil;
015: import com.tc.object.config.LockDefinition;
016: import com.tc.object.config.StandardDSOClientConfigHelper;
017: import com.tc.object.config.TransparencyClassSpec;
018: import com.tc.util.Assert;
019:
020: import java.net.MalformedURLException;
021: import java.net.URL;
022:
023: public abstract class TerracottaConfiguratorModule implements
024: BundleActivator {
025:
026: protected StandardDSOClientConfigHelper configHelper;
027:
028: protected ServiceReference getConfigHelperReference(
029: BundleContext context) throws Exception {
030: final String CONFIGHELPER_CLASS_NAME = "com.tc.object.config.StandardDSOClientConfigHelper";
031: final ServiceReference configHelperRef = context
032: .getServiceReference(CONFIGHELPER_CLASS_NAME);
033: if (configHelperRef == null) {
034: throw new BundleException(
035: "Expected the "
036: + CONFIGHELPER_CLASS_NAME
037: + " service to be registered, was unable to find it");
038: }
039: return configHelperRef;
040: }
041:
042: public final void start(final BundleContext context)
043: throws Exception {
044: final ServiceReference configHelperRef = getConfigHelperReference(context);
045: configHelper = (StandardDSOClientConfigHelper) context
046: .getService(configHelperRef);
047: Assert.assertNotNull(configHelper);
048: addInstrumentation(context);
049: context.ungetService(configHelperRef);
050: registerModuleSpec(context);
051: }
052:
053: public void stop(final BundleContext context) throws Exception {
054: // Ignore this, we don't need to stop anything
055: }
056:
057: protected void addInstrumentation(final BundleContext context) {
058: // default empty body
059: }
060:
061: protected void registerModuleSpec(final BundleContext context) {
062: // default empty body
063: }
064:
065: protected final String getBundleJarUrl(final Bundle bundle) {
066: return "jar:" + bundle.getLocation() + "!/";
067: }
068:
069: protected final void addClassReplacement(final Bundle bundle,
070: final String originalClassName,
071: final String replacementClassName) {
072: String url = getBundleJarUrl(bundle)
073: + ByteCodeUtil
074: .classNameToFileName(replacementClassName);
075: try {
076: configHelper.addClassReplacement(originalClassName,
077: replacementClassName, new URL(url));
078: } catch (MalformedURLException e) {
079: throw new RuntimeException(
080: "Unexpected error while constructing the URL '"
081: + url + "'", e);
082: }
083: }
084:
085: /**
086: * Export the given class that normally resides in a config bundle (aka. integration module) to all classloaders that
087: * might try to load it. This is sort of like creating a jar containing the one given class and appending into the
088: * lookup path of every classloader
089: *
090: * NOTE: The export will only work for class loads that pass through java.lang.ClassLoader.loadClassInternal().
091: * Specifically if the loadClass() method is directly being invoked from code someplace, the class export will not
092: * function. Code that does a "new <exported class name>", or that uses java.lang.Class.forName(..) will work though
093: *
094: * @param classname the bundle class name to export
095: */
096: protected final void addExportedBundleClass(final Bundle bundle,
097: final String classname) {
098: String url = getBundleJarUrl(bundle)
099: + ByteCodeUtil.classNameToFileName(classname);
100: try {
101: configHelper.addClassResource(classname, new URL(url));
102: } catch (MalformedURLException e) {
103: throw new RuntimeException(
104: "Unexpected error while constructing the URL '"
105: + url + "'", e);
106: }
107: }
108:
109: /**
110: * Export the given class that normally resides in tc.jar to all classloaders that might try to load it. This is sort
111: * of like creating a jar containing the one given class and appending into the lookup path of every classloader
112: *
113: * NOTE: The export will only work for class loads that pass through java.lang.ClassLoader.loadClassInternal().
114: * Specifically if the loadClass() method is directly being invoked from code someplace, the class export will not
115: * function. Code that does a "new <exported class name>", or that uses java.lang.Class.forName(..) will work though
116: *
117: * @param classname the tc.jar class name to export
118: */
119: protected final void addExportedTcJarClass(final String classname) {
120: URL resource = TerracottaConfiguratorModule.class
121: .getClassLoader().getResource(
122: ByteCodeUtil.classNameToFileName(classname));
123:
124: if (resource == null) {
125: throw new RuntimeException("Exported TC jar class "
126: + classname + " does not exist.");
127: }
128:
129: configHelper.addClassResource(classname, resource);
130: }
131:
132: protected TransparencyClassSpec getOrCreateSpec(final String expr,
133: final boolean markAsPreInstrumented) {
134: final TransparencyClassSpec spec = configHelper
135: .getOrCreateSpec(expr);
136: if (markAsPreInstrumented)
137: spec.markPreInstrumented();
138: return spec;
139: }
140:
141: protected TransparencyClassSpec getOrCreateSpec(final String expr) {
142: return getOrCreateSpec(expr, true);
143: }
144:
145: protected void addLock(final String expr, final LockDefinition ld) {
146: configHelper.addLock(expr, ld);
147: }
148:
149: protected Bundle getExportedBundle(final BundleContext context,
150: String targetBundleName) {
151: // find the bundle that contains the replacement classes
152: Bundle[] bundles = context.getBundles();
153: Bundle bundle = null;
154: for (int i = 0; i < bundles.length; i++) {
155: if (BundleSpec.isMatchingSymbolicName(targetBundleName,
156: bundles[i].getSymbolicName())) {
157: bundle = bundles[i];
158: break;
159: }
160: }
161: return bundle;
162: }
163:
164: }
|