/* * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed 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. * * Contributors: * Stephane Lacoin */ package org.nuxeo.ecm.core.management.jtajca; import java.util.HashSet; import java.util.Set; import javax.inject.Inject; import javax.management.JMX; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.transaction.TransactionManager; import org.apache.commons.logging.LogFactory; import org.nuxeo.ecm.core.test.CoreFeature; import org.nuxeo.runtime.api.Framework; import org.nuxeo.runtime.jtajca.NuxeoContainer; import org.nuxeo.runtime.management.ManagementFeature; import org.nuxeo.runtime.management.ServerLocator; import org.nuxeo.runtime.test.runner.Deploy; import org.nuxeo.runtime.test.runner.Features; import org.nuxeo.runtime.test.runner.FeaturesRunner; import org.nuxeo.runtime.test.runner.LocalDeploy; import org.nuxeo.runtime.test.runner.SimpleFeature; import com.google.inject.Binder; import com.google.inject.name.Named; import com.google.inject.name.Names; @Features(ManagementFeature.class) @Deploy({ "org.nuxeo.runtime.jtajca", "org.nuxeo.runtime.datasource", "org.nuxeo.ecm.core.management.jtajca" }) @LocalDeploy({ "org.nuxeo.ecm.core.management.jtajca:login-config.xml" }) public class JtajcaManagementFeature extends SimpleFeature { protected static ObjectName nameOf(Class<?> itf) { try { return new ObjectName(Defaults.instance.name(itf, "*")); } catch (MalformedObjectNameException cause) { throw new AssertionError("Cannot name monitor", cause); } } protected <T> void bind(Binder binder, MBeanServer mbs, Class<T> type) { final Set<ObjectName> names = mbs.queryNames(nameOf(type), null); for (ObjectName name : names) { T instance = type.cast(JMX.newMXBeanProxy(mbs, name, type)); binder.bind(type).annotatedWith(Names.named(name.getKeyProperty("name"))).toInstance(instance); } } public static <T> T getInstanceNamedWithPrefix(Class<T> type, String prefix) { MBeanServer mbs = Framework.getService(ServerLocator.class).lookupServer(); Set<String> names = new HashSet<>(); for (ObjectName objectName : mbs.queryNames(nameOf(type), null)) { String name = objectName.getKeyProperty("name"); names.add(name); // for error case if (name.startsWith(prefix)) { return JMX.newMXBeanProxy(mbs, objectName, type); } } throw new RuntimeException("Found no bean with name prefix: " + prefix + " in available names: " + names); } CoreFeature core; Class<?> target; @Override public void start(FeaturesRunner runner) throws Exception { core = runner.getFeature(CoreFeature.class); target = runner.getTargetTestClass(); } @Override public void configure(FeaturesRunner runner, Binder binder) { if (core == null) { return; } // bind repository String repositoryName = core.getStorageConfiguration().getRepositoryName(); NuxeoContainer.getConnectionManager(repositoryName); MBeanServer mbs = Framework.getLocalService(ServerLocator.class).lookupServer(); bind(binder, mbs, ConnectionPoolMonitor.class); bind(binder, mbs, CoreSessionMonitor.class); TransactionManager tm = NuxeoContainer.getTransactionManager(); if (tm != null) { bind(binder, mbs, TransactionMonitor.class); binder.bind(TransactionManager.class).toInstance(tm); } } class TxChecker { @Inject @Named("default") TransactionMonitor monitor; void assertNoTransactions() { long count = monitor.getActiveCount(); if (count == 0) { LogFactory.getLog(JtajcaManagementFeature.class).debug(target + " was successful"); return; } throw new AssertionError(String.format("still have tx active (%d) %s", count, monitor.getActiveStatistics())); } public TxChecker(FeaturesRunner runner) { runner.getInjector().injectMembers(this); } } TxChecker txChecker; @Override public void beforeSetup(FeaturesRunner runner) throws Exception { if (core == null) { return; } txChecker = new TxChecker(runner); } @Override public void afterTeardown(FeaturesRunner runner) throws Exception { if (txChecker == null) { return; } try { txChecker.assertNoTransactions(); } finally { txChecker = null; } } }