/* * JBoss, Home of Professional Open Source. * Copyright 2013, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.narayana.osgi.jta.internal; import javax.transaction.TransactionManager; import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.UserTransaction; import java.util.ArrayList; import java.util.Dictionary; import java.util.Enumeration; import java.util.Hashtable; import java.util.List; import java.util.Properties; import com.arjuna.ats.arjuna.coordinator.TransactionReaper; import com.arjuna.ats.arjuna.coordinator.TxControl; import com.arjuna.ats.arjuna.objectstore.StoreManager; import com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBrowser; import com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBrowserMBean; import com.arjuna.ats.jbossatx.jta.RecoveryManagerService; import com.arjuna.ats.jbossatx.jta.TransactionManagerService; import com.arjuna.ats.jta.common.JTAEnvironmentBean; import com.arjuna.ats.jta.common.jtaPropertyManager; import com.arjuna.common.util.propertyservice.PropertiesFactory; import org.jboss.narayana.osgi.jta.ObjStoreBrowserService; import org.jboss.tm.XAResourceRecovery; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.service.log.LogService; import org.osgi.util.tracker.ServiceTracker; import org.osgi.util.tracker.ServiceTrackerCustomizer; public class OsgiServer implements ServiceTrackerCustomizer<XAResourceRecovery, XAResourceRecovery> { private final BundleContext bundleContext; private final Dictionary<String, ?> configuration; List<ServiceRegistration> registrations; ServiceTracker<XAResourceRecovery, XAResourceRecovery> resourceRecoveryTracker; TransactionManagerService transactionManagerService; RecoveryManagerService recoveryManagerService; ObjStoreBrowserService objStoreBrowserService; public OsgiServer(BundleContext bundleContext, Dictionary<String, ?> configuration) { this.bundleContext = bundleContext; this.configuration = configuration; } public void start() throws Exception { ClassLoader ctxLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); doStart(); } finally { Thread.currentThread().setContextClassLoader(ctxLoader); } } public void doStart() throws Exception { Properties properties = PropertiesFactory.getDefaultProperties(); if (configuration != null) { for (Enumeration<String> keyEnum = configuration.keys(); keyEnum.hasMoreElements(); ) { String key = keyEnum.nextElement(); String val = configuration.get(key).toString(); properties.put(key, val); } } OsgiTransactionManager transactionManager = new OsgiTransactionManager(); JTAEnvironmentBean jtaEnvironmentBean = jtaPropertyManager.getJTAEnvironmentBean(); jtaEnvironmentBean.setTransactionManager(transactionManager); jtaEnvironmentBean.setUserTransaction(transactionManager); RecoveryManagerService rmSvc = new RecoveryManagerService(); rmSvc.create(); recoveryManagerService = rmSvc; resourceRecoveryTracker = new ServiceTracker<>(bundleContext, XAResourceRecovery.class, this); TransactionManagerService tmSvc = new TransactionManagerService(); tmSvc.setTransactionSynchronizationRegistry(jtaEnvironmentBean.getTransactionSynchronizationRegistry()); tmSvc.create(); transactionManagerService = tmSvc; ObjStoreBrowser osb = new ObjStoreBrowser(); osb.setExposeAllRecordsAsMBeans(true); objStoreBrowserService = new ObjStoreBrowserImpl(osb); resourceRecoveryTracker.open(); transactionManagerService.start(); recoveryManagerService.start(); objStoreBrowserService.start(); register(TransactionManager.class, transactionManagerService.getTransactionManager()); register(TransactionSynchronizationRegistry.class, transactionManagerService.getTransactionSynchronizationRegistry()); register(UserTransaction.class, transactionManagerService.getUserTransaction()); register(ObjStoreBrowserService.class, objStoreBrowserService); try { registrations.add(PlatformTransactionManagerImple.register( bundleContext, (OsgiTransactionManager) transactionManagerService.getTransactionManager())); } catch (Throwable t) { // Ignore, this is most certainly spring-tx which is not available } } public void stop() { ClassLoader ctxLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); doStop(); } finally { Thread.currentThread().setContextClassLoader(ctxLoader); } } protected void doStop() { if (registrations != null) { for (ServiceRegistration reg : registrations) { try { reg.unregister(); } catch (Throwable t) { warn("Error unregistering service", t); } } registrations = null; } if (transactionManagerService != null) { try { try { transactionManagerService.stop(); } finally { transactionManagerService.destroy(); } } catch (Throwable t) { warn("Error stopping transaction manager service", t); } finally { transactionManagerService = null; } } if (recoveryManagerService != null) { try { try { recoveryManagerService.stop(); } finally { recoveryManagerService.destroy(); } } catch (Throwable t) { warn("Error stopping recovery manager service", t); } finally { recoveryManagerService = null; } } if (resourceRecoveryTracker != null) { try { resourceRecoveryTracker.close(); } catch (Throwable t) { warn("Error stopping resource recovery tracker", t); } finally { resourceRecoveryTracker = null; } } if (objStoreBrowserService != null) { try { objStoreBrowserService.stop(); } catch (Throwable t) { warn("Error stopping object browser", t); } finally { objStoreBrowserService = null; } } TransactionReaper.terminate(false); TxControl.disable(true); StoreManager.shutdown(); } protected <T> void register(Class<T> clazz, T service) { Hashtable<String, String> props = new Hashtable<>(); props.put("provider", "narayana"); ServiceRegistration<T> registration = bundleContext.registerService(clazz, service, props); if (registrations == null) { registrations = new ArrayList<>(); } registrations.add(registration); } protected void warn(String message, Throwable t) { ServiceReference<LogService> ref = bundleContext.getServiceReference(LogService.class); if (ref != null) { LogService svc = bundleContext.getService(ref); svc.log(LogService.LOG_WARNING, message, t); bundleContext.ungetService(ref); } } @Override public XAResourceRecovery addingService(ServiceReference<XAResourceRecovery> reference) { final XAResourceRecovery resourceRecovery = bundleContext.getService(reference); recoveryManagerService.addXAResourceRecovery(resourceRecovery); return resourceRecovery; } @Override public void modifiedService(ServiceReference<XAResourceRecovery> reference, XAResourceRecovery service) { } @Override public void removedService(ServiceReference<XAResourceRecovery> reference, XAResourceRecovery resourceRecovery) { recoveryManagerService.removeXAResourceRecovery(resourceRecovery); bundleContext.ungetService(reference); } }