You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ode.apache.org by va...@apache.org on 2011/01/06 18:44:08 UTC
svn commit: r1055956 - in /ode/branches/ode-1.3.5.x/jbi-bundle/src/main:
java/org/apache/ode/jbi/osgi/ java/org/apache/ode/jbi/osgi/deployer/
resources/META-INF/spring/
Author: vanto
Date: Thu Jan 6 17:44:08 2011
New Revision: 1055956
URL: http://svn.apache.org/viewvc?rev=1055956&view=rev
Log:
ODE-901: Improved handling of SMX4 BPEL bundles. Big thanks to Kurt Westerfeld.
Added:
ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/
ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeDeployedBundle.java
ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtender.java
ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtenderImpl.java
ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtenderThreadFactory.java
Modified:
ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/ServiceUnitActivator.java
ode/branches/ode-1.3.5.x/jbi-bundle/src/main/resources/META-INF/spring/ode-jbi.xml
Modified: ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/ServiceUnitActivator.java
URL: http://svn.apache.org/viewvc/ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/ServiceUnitActivator.java?rev=1055956&r1=1055955&r2=1055956&view=diff
==============================================================================
--- ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/ServiceUnitActivator.java (original)
+++ ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/ServiceUnitActivator.java Thu Jan 6 17:44:08 2011
@@ -19,101 +19,27 @@
package org.apache.ode.jbi.osgi;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Enumeration;
+import java.util.logging.Logger;
-import javax.jbi.component.Component;
-import javax.jbi.component.ServiceUnitManager;
-
-import org.apache.commons.io.IOUtils;
-import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
+
/**
- * @author mproch
+ * This class is now deprecated in favor of using OdeExtender service, which watches
+ * deployment of bundles and manages start/stop/install/uninstall/update from OSGi
+ * to ODE.
*
+ * @deprecated
+ * @see OdeExtenderImpl
*/
public class ServiceUnitActivator implements BundleActivator {
-
- File rootDir;
- String generatedName;
+ private static final Logger LOG = Logger.getLogger(ServiceUnitActivator.class.getName());
public void start(BundleContext context) throws Exception {
- generatedName = context.getBundle().getSymbolicName();
- rootDir = context.getDataFile("bpelData");
- rootDir.mkdirs();
- Enumeration<?> en = context.getBundle().findEntries("/", "*", false);
- while (en.hasMoreElements()) {
- copyOne(rootDir, (URL) en.nextElement());
- }
- ServiceReference[] refs = context.getAllServiceReferences(
- "javax.jbi.component.Component", "(&(NAME=OdeBpelEngine))");
- if (refs == null || refs.length != 1) {
- throw new RuntimeException("no appropriate service :(");
- }
- ServiceUnitManager suM = ((Component) context.getService(refs[0]))
- .getServiceUnitManager();
- ClassLoader l = Thread.currentThread().getContextClassLoader();
- try {
- ClassLoader suL = suM.getClass().getClassLoader();
- Thread.currentThread().setContextClassLoader(new BundleClassLoader(suL, context.getBundle()));
- suM.deploy(generatedName, rootDir.getAbsolutePath());
- suM.init(generatedName, rootDir.getAbsolutePath());
- suM.start(generatedName);
- } finally {
- Thread.currentThread().setContextClassLoader(l);
- }
-
- }
-
- private void copyOne(File dest, URL url) throws Exception {
- File d = new File(dest, url.getPath());
- InputStream str = url.openStream();
- if (str != null) {
- FileWriter wr = new FileWriter(d);
- try {
- IOUtils.copy(str, wr);
- } finally {
- wr.flush();
- wr.close();
- }
- }
+ LOG.warning("Use of " + this.getClass().getName() + " has been deprecated. BPEL bundle deployment is now handled by the ODE extender service. Remove Bundle-Activator from OSGi manifest for bundle: " + context.getBundle().getSymbolicName());
}
public void stop(BundleContext context) throws Exception {
- ServiceReference[] refs = context.getAllServiceReferences(
- "javax.jbi.component.Component", "(&(NAME=OdeBpelEngine))");
- if (refs == null || refs.length != 1) {
- throw new RuntimeException("no appropriate service :(");
- }
- ServiceUnitManager suM = ((Component) context.getService(refs[0]))
- .getServiceUnitManager();
- suM.shutDown(generatedName);
- suM.undeploy(generatedName, rootDir.getAbsolutePath());
-
}
-
- public class BundleClassLoader extends ClassLoader {
- private final Bundle delegate;
-
- public BundleClassLoader(ClassLoader parent, Bundle delegate) {
- super(parent);
- this.delegate = delegate;
- }
-
- @Override
- public Class<?> loadClass(String name) throws ClassNotFoundException {
- try {
- return getParent().loadClass(name);
- } catch (Exception e) {
- return delegate.loadClass(name);
- }
- }
- }
-
}
Added: ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeDeployedBundle.java
URL: http://svn.apache.org/viewvc/ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeDeployedBundle.java?rev=1055956&view=auto
==============================================================================
--- ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeDeployedBundle.java (added)
+++ ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeDeployedBundle.java Thu Jan 6 17:44:08 2011
@@ -0,0 +1,304 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.ode.jbi.osgi.deployer;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.FilenameFilter;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.jbi.component.Component;
+import javax.jbi.component.ComponentLifeCycle;
+import javax.jbi.component.ServiceUnitManager;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.xml.namespace.QName;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.ode.bpel.iapi.ProcessStore;
+import org.apache.ode.jbi.OdeContext;
+import org.osgi.framework.Bundle;
+
+public class OdeDeployedBundle {
+ private static final Logger LOG = Logger.getLogger(OdeDeployedBundle.class.getName());
+ private boolean updated;
+ private Bundle bundle;
+ private OdeExtenderImpl odeRegistrationService;
+ private File rootDir;
+ private String duName;
+ private String name;
+
+ OdeDeployedBundle(Bundle bundle, OdeExtenderImpl odeRegistrationService) {
+ if (LOG.isLoggable(Level.FINE))
+ LOG.fine("Initialized ODE service unit deployer for bundle: " + bundle.getSymbolicName());
+ this.bundle = bundle;
+ this.odeRegistrationService = odeRegistrationService;
+ }
+
+ String getName() {
+ if (this.name == null)
+ this.name = this.bundle.getSymbolicName();
+ return this.name;
+ }
+
+ private String getDUName() {
+ if (this.duName == null)
+ this.duName = getName() + "-" + bundle.getVersion().getMicro();
+ return this.duName;
+ }
+
+ private File getRootDir() {
+ if (this.rootDir == null && this.bundle.getBundleContext() != null)
+ this.rootDir = this.bundle.getBundleContext().getDataFile("bpelData/" + getDUName());
+ return this.rootDir;
+ }
+
+ void doStart() throws Exception {
+ // If we are already started, don't bother starting again.
+ LOG.info("Starting ODE service unit: " + getName());
+
+ // Wait until ODE is available before starting.
+ waitAvailable();
+
+ // Do we need to undeploy first?
+ boolean needUpdate = updated;
+ boolean forceDeploy = needUpdate;
+ this.updated = false;
+
+ // Do deploy.
+ this.deploy(this.bundle, this.odeRegistrationService.getOdeComponent().getServiceUnitManager(), forceDeploy, needUpdate);
+ }
+
+ void doStop() throws Exception {
+ LOG.info("Stopping ODE service unit: " + getName());
+ this.shutdown(this.bundle, this.odeRegistrationService.getOdeComponent().getServiceUnitManager());
+ }
+
+ void doInstall() throws Exception {
+ LOG.info("Installing ODE service unit: " + getName());
+ }
+
+ void doUninstall() throws Exception {
+ LOG.info("Uninstalling ODE service unit: " + getName());
+ this.undeploy(this.bundle, this.odeRegistrationService.getOdeComponent().getServiceUnitManager());
+ }
+
+ void doUpdate() throws Exception {
+ LOG.info("Updating ODE service unit: " + getName());
+
+ // We simply mark the update state of this bundle so that on next start, we do a redeploy
+ updated = true;
+ }
+
+ private void deploy(Bundle bundle, ServiceUnitManager suM, boolean forceDeploy, boolean undeploy) throws Exception {
+ // Do deployment.
+ File rootDir = getRootDir();
+ String duName = getDUName();
+ boolean needDeploy = rootDir.mkdirs() || forceDeploy;
+ if (LOG.isLoggable(Level.FINE))
+ LOG.fine("Exploding content to " + rootDir + " for " + duName);
+ Enumeration<?> en = bundle.findEntries("/", "*", false);
+ while (en.hasMoreElements())
+ needDeploy |= copyOne(rootDir, (URL) en.nextElement());
+
+ // Now start it.
+ ClassLoader l = Thread.currentThread().getContextClassLoader();
+ try {
+ ClassLoader suL = suM.getClass().getClassLoader();
+ Thread.currentThread().setContextClassLoader(new BundleClassLoader(suL, bundle));
+ try {
+ // Try first an init/start, which will fail if the process isn't
+ // here.
+ if (needDeploy) {
+ // If deployed, undeploy first.
+ if (undeploy && isDeployed(duName)) {
+ // Do the undeploy to service unit manager.
+ LOG.info("Performing undeploy " + duName + " from dir " + rootDir);
+ suM.undeploy(duName, rootDir.getAbsolutePath());
+
+ // Now, remove any .cbp files.
+ File[] cbpFiles = rootDir.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.endsWith(".cbp");
+ }
+ });
+ for (File cbpFile : cbpFiles) {
+ LOG.info("Removing compiled bpel process: " + cbpFile);
+ cbpFile.delete();
+ }
+ }
+
+ LOG.info("Deploying " + duName + " to dir " + rootDir);
+ suM.deploy(duName, rootDir.getAbsolutePath());
+ }
+ suM.init(duName, rootDir.getAbsolutePath());
+ suM.start(duName);
+ } catch (javax.jbi.management.DeploymentException e) {
+ LOG.log(Level.WARNING, "Deploy failed; could not deploy/start this bundle: " + this.getName(), e);
+ throw e;
+ }
+ } finally {
+ Thread.currentThread().setContextClassLoader(l);
+ }
+ }
+
+ private boolean isDeployed(String processName) {
+ boolean Result = true;
+ try {
+ // Get the "ProcessStore" interface by grabbing the internal field
+ // of OdeContext and querying for the processes. Could also use PMAPI here,
+ // but in any case we just need to know if the process exists in a deployed state.
+ //
+ // TODO: add a OdeContext.getStore() method to clean this up.
+ OdeContext inst = OdeContext.getInstance();
+ Field _store = inst.getClass().getDeclaredField("_store");
+ _store.setAccessible(true);
+ ProcessStore ps = (ProcessStore) _store.get(inst);
+ List<QName> processes = ps.listProcesses(processName);
+ Result = processes != null && !processes.isEmpty();
+ } catch (Exception e) {
+ LOG.log(Level.WARNING, "Could not determine deployment state for process: " + processName, e);
+ }
+ return Result;
+ }
+
+ private boolean copyOne(File dest, URL url) throws Exception {
+ File d = new File(dest, url.getPath());
+ boolean needDeploy = !d.exists();
+ long length = d.exists() ? d.length() : 0L;
+ InputStream str = url.openStream();
+ if (str != null) {
+ FileWriter wr = new FileWriter(d);
+ try {
+ IOUtils.copy(str, wr);
+ } finally {
+ wr.flush();
+ wr.close();
+ }
+
+ // If file is zero-length (which is the case handling a directory),
+ // just remove it.
+ if (d.exists() && d.length() == 0) {
+ d.delete();
+ needDeploy = false;
+ } else
+ needDeploy |= length != d.length();
+ }
+ return needDeploy;
+ }
+
+ private void shutdown(Bundle bundle, ServiceUnitManager suM) throws Exception {
+ String duName = getDUName();
+ if (suM != null) {
+ suM.stop(duName);
+ suM.shutDown(duName);
+ } else {
+ LOG.warning("Could not shutdown this process (" + duName + ") because ode component was never located");
+ }
+ }
+
+ private void undeploy(Bundle bundle, ServiceUnitManager suM) throws Exception {
+ String duName = getDUName();
+ if (suM != null) {
+ if (isDeployed(duName)) {
+ // Use ODE's classloader to avoid class loading from the bundle
+ // being undeployed.
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(suM.getClass().getClassLoader());
+ File rootDir = getRootDir();
+ LOG.info("Performing undeploy " + duName + " from dir " + rootDir);
+ suM.undeploy(duName, rootDir.getAbsolutePath());
+ } finally {
+ Thread.currentThread().setContextClassLoader(classLoader);
+ }
+ }
+ } else {
+ LOG.warning("Could not shutdown this process (" + duName + ") because ode component was never located");
+ }
+ }
+
+ public class BundleClassLoader extends ClassLoader {
+ private final Bundle delegate;
+
+ public BundleClassLoader(ClassLoader parent, Bundle delegate) {
+ super(parent);
+ this.delegate = delegate;
+ }
+
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ try {
+ return getParent().loadClass(name);
+ } catch (Exception e) {
+ return delegate.loadClass(name);
+ }
+ }
+ }
+
+ private void waitAvailable() throws InterruptedException {
+ /**
+ * We need to wait until the service unit manager is available before
+ * proceeding. Also, since the ode component itself does an asynchronous
+ * start with respect to this bundle, we need to wait until it is done
+ * initializing. This would be much cleaner if we could simply
+ * call "isStarted" on OdeLifeCycle, which maintains a started state.
+ *
+ * If we do not wait until the ode component is started, deployments
+ * will fail sporadically because of asynchronous start race conditions.
+ */
+ boolean showedWait = false;
+ while (this.odeRegistrationService.getOdeComponent().getServiceUnitManager() == null || !isStarted(this.odeRegistrationService.getOdeComponent())) {
+
+ // Do a wait.
+ if (!showedWait) {
+ LOG.info("Waiting for ODE to arrive (" + getName() + ")...");
+ showedWait = true;
+ }
+ Thread.sleep(500L);
+ }
+ }
+
+ private boolean isStarted(Component odeComponent) {
+
+ boolean Result = true;
+ try {
+ // Get the ODE component started state by grabbing the internal field
+ // of OdeLifeCycle. We cannot rely on the started state of the ODE
+ // component bundle.
+ //
+ // TODO: add OdeLifeCycle.isStarted() and do a cast of odeComponent.getLifeCycle() accordingly.
+ ComponentLifeCycle inst = odeComponent.getLifeCycle();
+ Field _started = inst.getClass().getDeclaredField("_started");
+ _started.setAccessible(true);
+ Result = Boolean.TRUE.equals(_started.get(inst));
+ } catch (Exception e) {
+ LOG.log(Level.WARNING, "Could not determine started state for ode component", e);
+ }
+ return Result;
+ }
+}
Added: ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtender.java
URL: http://svn.apache.org/viewvc/ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtender.java?rev=1055956&view=auto
==============================================================================
--- ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtender.java (added)
+++ ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtender.java Thu Jan 6 17:44:08 2011
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.ode.jbi.osgi.deployer;
+
+import org.osgi.framework.Bundle;
+
+public interface OdeExtender {
+ public Bundle[] getBundles();
+}
Added: ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtenderImpl.java
URL: http://svn.apache.org/viewvc/ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtenderImpl.java?rev=1055956&view=auto
==============================================================================
--- ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtenderImpl.java (added)
+++ ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtenderImpl.java Thu Jan 6 17:44:08 2011
@@ -0,0 +1,295 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.ode.jbi.osgi.deployer;
+
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.jbi.component.Component;
+
+import org.apache.ode.jbi.osgi.ServiceUnitActivator;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Constants;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.osgi.context.BundleContextAware;
+
+public class OdeExtenderImpl implements OdeExtender, InitializingBean, DisposableBean, BundleContextAware {
+ private static final Logger LOG = Logger.getLogger(OdeExtenderImpl.class.getName());
+ private static final String SU_ACTIVATOR_DEPRECATED = ServiceUnitActivator.class.getName();
+ private BundleContext bundleContext;
+ private BundleTracker tracker;
+ private Component odeComponent;
+ private Executor executor;
+
+ public OdeExtenderImpl() {
+ }
+
+ @Override
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ // Create our executor.
+ executor = Executors.newSingleThreadExecutor(new OdeExtenderThreadFactory("ODE Extender"));
+
+ // Start tracking bundles. We are looking for /deploy.xml as a signature
+ // to deploy the ODE BPEL bundle, if the bundle has at least one .bpel
+ // file.
+ int stateMask = Bundle.STARTING | Bundle.ACTIVE | Bundle.STOPPING | Bundle.INSTALLED | Bundle.UNINSTALLED;
+ this.tracker = new BundleTracker(this.bundleContext, stateMask, new ODEBundleTrackerCustomizer());
+ this.tracker.open();
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ // Close the tracker.
+ BundleTracker tracker = this.tracker;
+ this.tracker = null;
+ if (tracker != null)
+ tracker.close();
+
+ // Drop our thread pool.
+ this.executor = null;
+ }
+
+ @Override
+ public Bundle[] getBundles() {
+ return this.tracker.getBundles();
+ }
+
+ public void setOdeComponent(Component odeComponent) {
+ this.odeComponent = odeComponent;
+ }
+
+ public Component getOdeComponent() {
+ return odeComponent;
+ }
+
+ private boolean isBPELBundle(Bundle bundle) {
+ boolean Result = false;
+
+ // First see if there is a deploy.xml.
+ URL entry = bundle.getEntry("deploy.xml");
+ if (entry != null) {
+ // Next, check if there's at least one BPEL file.
+ @SuppressWarnings("rawtypes")
+ Enumeration bpelFiles = bundle.findEntries("/", "*.bpel", false);
+ if (bpelFiles != null && bpelFiles.hasMoreElements()) {
+ // Make sure there's a symbolic name.
+ if (bundle.getSymbolicName() != null) {
+ // Make sure there's no bundle activator.
+ // NOTE: if the "ServiceUnitActivator" is found, we hijack those bundles as well and manage them.
+ Dictionary<?, ?> headers = bundle.getHeaders();
+ Object activator = null;
+ if (headers == null || (activator = headers.get(Constants.BUNDLE_ACTIVATOR)) == null || SU_ACTIVATOR_DEPRECATED.equals(activator)) {
+ if (LOG.isLoggable(Level.FINE))
+ LOG.fine("Recognized ODE deployment bundle: " + bundle.getSymbolicName());
+ Result = true;
+ } else
+ LOG.warning("Ignoring ODE bundle " + bundle.getSymbolicName() + " which has custom activator: " + activator);
+ } else
+ LOG.warning("Ignoring ODE bundle " + bundle.getBundleId() + " which has no OSGi symbolic name");
+ }
+ }
+
+ return Result;
+ }
+
+ private class ODEBundleTrackerCustomizer implements BundleTrackerCustomizer {
+ private Map<Long, OdeDeployedBundle> bundles = new ConcurrentHashMap<Long, OdeDeployedBundle>();
+
+ @Override
+ public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+ }
+
+ @Override
+ public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+ if (event != null) {
+ if (LOG.isLoggable(Level.FINE))
+ LOG.fine("Received " + getEventType(event.getType()) + " event for bundle: " + bundle.getSymbolicName());
+ switch (event.getType()) {
+ case BundleEvent.STARTED:
+ executor.execute(new Start((OdeDeployedBundle) object));
+ break;
+ case BundleEvent.STOPPING:
+ executor.execute(new Stop((OdeDeployedBundle) object));
+ break;
+ case BundleEvent.INSTALLED:
+ executor.execute(new Install((OdeDeployedBundle) object));
+ break;
+ case BundleEvent.UNINSTALLED:
+ executor.execute(new Uninstall((OdeDeployedBundle) object));
+ break;
+ case BundleEvent.UPDATED:
+ executor.execute(new Update((OdeDeployedBundle) object));
+ break;
+ }
+
+ // Do this outside the try/catch above. Last chance to drop a
+ // bundle.
+ if (event.getType() == BundleEvent.UNINSTALLED)
+ bundles.remove(bundle.getBundleId());
+ }
+ }
+
+ private String getEventType(int type) {
+ switch (type) {
+ case BundleEvent.INSTALLED:
+ return "installed";
+ case BundleEvent.LAZY_ACTIVATION:
+ return "lazy activation";
+ case BundleEvent.RESOLVED:
+ return "resolved";
+ case BundleEvent.STARTED:
+ return "started";
+ case BundleEvent.STARTING:
+ return "starting";
+ case BundleEvent.STOPPED:
+ return "stopped";
+ case BundleEvent.STOPPING:
+ return "stopping";
+ case BundleEvent.UNINSTALLED:
+ return "uninstalled";
+ case BundleEvent.UNRESOLVED:
+ return "unresolved";
+ case BundleEvent.UPDATED:
+ return "updated";
+ }
+ return "(unknown: " + type + ")";
+ }
+
+ @Override
+ public Object addingBundle(Bundle bundle, BundleEvent event) {
+ Object Result = null;
+
+ // Is this a BPEL bundle?
+ if (isBPELBundle(bundle)) {
+ // Found BPEL signature; setup deployer.
+ OdeDeployedBundle deployer = bundles.get(bundle.getBundleId());
+ if (deployer == null)
+ bundles.put(bundle.getBundleId(), deployer = new OdeDeployedBundle(bundle, OdeExtenderImpl.this));
+ Result = deployer;
+
+ // Is this an initial bundle?
+ if (event == null) {
+ // If the bundle is active, then we didn't start it. So
+ // start it now.
+ if (bundle.getState() == Bundle.ACTIVE)
+ executor.execute(new Start(deployer));
+ } else
+ modifiedBundle(bundle, event, deployer);
+ }
+
+ return Result;
+ }
+ }
+
+ private static abstract class OperationClosure implements Runnable {
+ protected OdeDeployedBundle target;
+
+ OperationClosure(OdeDeployedBundle target) {
+ this.target = target;
+ }
+
+ @Override
+ public final void run() {
+ String name = Thread.currentThread().getName();
+ try {
+ Thread.currentThread().setName(name + ":" + getClass().getSimpleName() + ":" + target.getName());
+ perform();
+ } catch (Exception e) {
+ LOG.log(Level.WARNING, "Could not perform '" + getClass().getSimpleName() + "' operation on bundle: " + target.getName(), e);
+ } finally {
+ Thread.currentThread().setName(name);
+ }
+ }
+
+ protected abstract void perform() throws Exception;
+ }
+
+ private static class Start extends OperationClosure {
+ Start(OdeDeployedBundle target) {
+ super(target);
+ }
+
+ @Override
+ protected void perform() throws Exception {
+ target.doStart();
+ }
+ }
+
+ private static class Stop extends OperationClosure {
+ Stop(OdeDeployedBundle target) {
+ super(target);
+ }
+
+ @Override
+ protected void perform() throws Exception {
+ target.doStop();
+ }
+ }
+
+ private static class Install extends OperationClosure {
+ Install(OdeDeployedBundle target) {
+ super(target);
+ }
+
+ @Override
+ protected void perform() throws Exception {
+ target.doInstall();
+ }
+ }
+
+ private static class Uninstall extends OperationClosure {
+ Uninstall(OdeDeployedBundle target) {
+ super(target);
+ }
+
+ @Override
+ protected void perform() throws Exception {
+ target.doUninstall();
+ }
+ }
+
+ private static class Update extends OperationClosure {
+ Update(OdeDeployedBundle target) {
+ super(target);
+ }
+
+ @Override
+ protected void perform() throws Exception {
+ target.doUpdate();
+ }
+ }
+}
Added: ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtenderThreadFactory.java
URL: http://svn.apache.org/viewvc/ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtenderThreadFactory.java?rev=1055956&view=auto
==============================================================================
--- ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtenderThreadFactory.java (added)
+++ ode/branches/ode-1.3.5.x/jbi-bundle/src/main/java/org/apache/ode/jbi/osgi/deployer/OdeExtenderThreadFactory.java Thu Jan 6 17:44:08 2011
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.ode.jbi.osgi.deployer;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+public class OdeExtenderThreadFactory implements ThreadFactory {
+ private final ThreadFactory factory = Executors.defaultThreadFactory();
+ private final String name;
+
+ public OdeExtenderThreadFactory(String name) {
+ this.name = name;
+ }
+
+ public Thread newThread(Runnable r) {
+ final Thread t = factory.newThread(r);
+ t.setName(name);
+ t.setDaemon(true);
+ return t;
+ }
+}
Modified: ode/branches/ode-1.3.5.x/jbi-bundle/src/main/resources/META-INF/spring/ode-jbi.xml
URL: http://svn.apache.org/viewvc/ode/branches/ode-1.3.5.x/jbi-bundle/src/main/resources/META-INF/spring/ode-jbi.xml?rev=1055956&r1=1055955&r2=1055956&view=diff
==============================================================================
--- ode/branches/ode-1.3.5.x/jbi-bundle/src/main/resources/META-INF/spring/ode-jbi.xml (original)
+++ ode/branches/ode-1.3.5.x/jbi-bundle/src/main/resources/META-INF/spring/ode-jbi.xml Thu Jan 6 17:44:08 2011
@@ -63,5 +63,18 @@
<prop key="ode-jbi.jca.port">0</prop>
<prop key="javax.persistence.provider">org.apache.openjpa.persistence.PersistenceProviderImpl</prop>
</osgix:cm-properties>
-
+
+ <!-- ODE Extender Service -->
+ <bean id="ode-extender-service" class="org.apache.ode.jbi.osgi.deployer.OdeExtenderImpl">
+ <property name="odeComponent">
+ <ref bean="ode-jbi-component" />
+ </property>
+ </bean>
+
+ <osgi:service ref="ode-extender-service">
+ <osgi:interfaces>
+ <value>org.apache.ode.jbi.osgi.deployer.OdeExtender</value>
+ </osgi:interfaces>
+ </osgi:service>
+
</beans>