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