001/* 002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Florent Guillaume 016 */ 017package org.nuxeo.ecm.core.management.jtajca.internal; 018 019import java.util.HashMap; 020import java.util.Map; 021 022import javax.management.InstanceAlreadyExistsException; 023import javax.management.InstanceNotFoundException; 024import javax.management.JMException; 025import javax.management.MBeanRegistrationException; 026import javax.management.MBeanServer; 027import javax.management.MalformedObjectNameException; 028import javax.management.NotCompliantMBeanException; 029import javax.management.ObjectInstance; 030import javax.management.ObjectName; 031import javax.security.auth.login.LoginContext; 032import javax.security.auth.login.LoginException; 033import org.apache.commons.logging.Log; 034import org.apache.commons.logging.LogFactory; 035import org.apache.geronimo.connector.outbound.AbstractConnectionManager; 036import org.nuxeo.ecm.core.api.CoreInstance; 037import org.nuxeo.ecm.core.api.CoreSession; 038import org.nuxeo.ecm.core.api.NuxeoException; 039import org.nuxeo.ecm.core.management.jtajca.CoreSessionMonitor; 040import org.nuxeo.ecm.core.management.jtajca.Defaults; 041import org.nuxeo.ecm.core.management.jtajca.ConnectionPoolMonitor; 042import org.nuxeo.ecm.core.management.jtajca.TransactionMonitor; 043import org.nuxeo.ecm.core.repository.RepositoryService; 044import org.nuxeo.runtime.api.Framework; 045import org.nuxeo.runtime.jtajca.NuxeoContainer; 046import org.nuxeo.runtime.jtajca.NuxeoContainerListener; 047import org.nuxeo.runtime.management.ServerLocator; 048import org.nuxeo.runtime.metrics.MetricsService; 049import org.nuxeo.runtime.metrics.MetricsServiceImpl; 050import org.nuxeo.runtime.model.ComponentContext; 051import org.nuxeo.runtime.model.DefaultComponent; 052 053/** 054 * Component used to install/uninstall the monitors (transaction and connections). 055 * 056 * @since 5.6 057 */ 058public class DefaultMonitorComponent extends DefaultComponent { 059 060 private final ConnectionManagerUpdater cmUpdater = new ConnectionManagerUpdater(); 061 062 private class ConnectionManagerUpdater implements NuxeoContainerListener { 063 @Override 064 public void handleNewConnectionManager(String name, AbstractConnectionManager cm) { 065 ConnectionPoolMonitor monitor = new DefaultConnectionPoolMonitor(name, cm); 066 monitor.install(); 067 poolConnectionMonitors.put(name, monitor); 068 } 069 070 @Override 071 public void handleConnectionManagerReset(String name, AbstractConnectionManager cm) { 072 DefaultConnectionPoolMonitor monitor = (DefaultConnectionPoolMonitor) poolConnectionMonitors.get(name); 073 monitor.handleNewConnectionManager(cm); 074 } 075 076 @Override 077 public void handleConnectionManagerDispose(String name, AbstractConnectionManager mgr) { 078 ConnectionPoolMonitor monitor = poolConnectionMonitors.remove(name); 079 monitor.uninstall(); 080 } 081 082 } 083 084 protected final Log log = LogFactory.getLog(DefaultMonitorComponent.class); 085 086 protected CoreSessionMonitor coreSessionMonitor; 087 088 protected TransactionMonitor transactionMonitor; 089 090 protected Map<String, ConnectionPoolMonitor> poolConnectionMonitors = new HashMap<String, ConnectionPoolMonitor>(); 091 092 // don't use activate, it would be too early 093 @Override 094 public void applicationStarted(ComponentContext context) { 095 uninstall(); 096 install(); 097 } 098 099 @Override 100 public int getApplicationStartedOrder() { 101 // should deploy after metrics service 102 return ((MetricsServiceImpl) Framework.getRuntime().getComponent(MetricsService.class.getName())).getApplicationStartedOrder() + 1; 103 } 104 105 @Override 106 public void deactivate(ComponentContext context) { 107 uninstall(); 108 super.deactivate(context); 109 } 110 111 protected boolean installed; 112 113 protected void install() { 114 installed = true; 115 116 coreSessionMonitor = new DefaultCoreSessionMonitor(); 117 coreSessionMonitor.install(); 118 119 transactionMonitor = new DefaultTransactionMonitor(); 120 transactionMonitor.install(); 121 122 try { 123 installPoolMonitors(); 124 } catch (LoginException cause) { 125 log.warn("Cannot install storage monitors", cause); 126 } 127 128 } 129 130 protected void installPoolMonitors() throws LoginException { 131 NuxeoContainer.addListener(cmUpdater); 132 NuxeoException errors = new NuxeoException("Cannot install pool monitors"); 133 LoginContext loginContext = Framework.login(); 134 try { 135 for (String name : Framework.getLocalService(RepositoryService.class).getRepositoryNames()) { 136 try (CoreSession session = CoreInstance.openCoreSession(name)) {; 137 } catch (NuxeoException cause) { 138 errors.addSuppressed(cause); 139 } 140 } 141 } finally { 142 loginContext.logout(); 143 } 144 if (errors.getSuppressed().length > 0) { 145 throw errors; 146 } 147 } 148 149 /** 150 * Make sure we open the repository, to initialize its connection manager. 151 */ 152 protected void activateRepository(String repositoryName) { 153 try (CoreSession session = CoreInstance.openCoreSessionSystem(repositoryName)) { 154 // do nothing, just open and close 155 } 156 } 157 158 protected void uninstall() { 159 if (!installed) { 160 return; 161 } 162 installed = false; 163 NuxeoContainer.removeListener(cmUpdater); 164 for (ConnectionPoolMonitor storage : poolConnectionMonitors.values()) { 165 storage.uninstall(); 166 } 167 coreSessionMonitor.uninstall(); 168 transactionMonitor.uninstall(); 169 poolConnectionMonitors.clear(); 170 coreSessionMonitor = null; 171 transactionMonitor = null; 172 } 173 174 protected static ObjectInstance bind(Object managed) { 175 return bind(managed, "default"); 176 } 177 178 protected static ObjectInstance bind(Class<?> itf, Object managed) { 179 return bind(itf, managed, "default"); 180 } 181 182 protected static ObjectInstance bind(Object managed, String name) { 183 return bind(managed.getClass().getInterfaces()[0], managed, name); 184 } 185 186 protected static ObjectInstance bind(Class<?> itf, Object managed, String name) { 187 MBeanServer mbs = Framework.getLocalService(ServerLocator.class).lookupServer(); 188 name = Defaults.instance.name(itf, name); 189 try { 190 return mbs.registerMBean(managed, new ObjectName(name)); 191 } catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException 192 | MalformedObjectNameException e) { 193 throw new UnsupportedOperationException("Cannot bind " + managed + " on " + name, e); 194 } 195 } 196 197 protected static void unbind(ObjectInstance instance) { 198 MBeanServer mbs = Framework.getLocalService(ServerLocator.class).lookupServer(); 199 try { 200 mbs.unregisterMBean(instance.getObjectName()); 201 } catch (MBeanRegistrationException | InstanceNotFoundException e) { 202 throw new UnsupportedOperationException("Cannot unbind " + instance, e); 203 } 204 } 205 206}