1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.geronimo.concurrent.impl.thread; 18 19 import java.util.List; 20 import java.util.Properties; 21 22 import org.apache.commons.logging.Log; 23 import org.apache.commons.logging.LogFactory; 24 import org.apache.geronimo.concurrent.ManagedContextHandler; 25 import org.apache.geronimo.concurrent.ManagedContextHandlerChain; 26 import org.apache.geronimo.concurrent.impl.ContextHandlerUtils; 27 import org.apache.geronimo.concurrent.impl.GBeanBuilder; 28 import org.apache.geronimo.concurrent.impl.NotificationHelper; 29 import org.apache.geronimo.concurrent.naming.ModuleAwareResourceSource; 30 import org.apache.geronimo.gbean.AbstractName; 31 import org.apache.geronimo.gbean.GBeanData; 32 import org.apache.geronimo.gbean.GBeanInfo; 33 import org.apache.geronimo.gbean.GBeanInfoBuilder; 34 import org.apache.geronimo.gbean.GBeanLifecycle; 35 import org.apache.geronimo.kernel.Kernel; 36 import org.apache.geronimo.management.EventProvider; 37 import org.apache.geronimo.management.ManagedConstants; 38 39 public class ManagedThreadFactoryGBean 40 extends GBeanBuilder 41 implements GBeanLifecycle, 42 GeronimoManagedThreadFactorySource, 43 ModuleAwareResourceSource, 44 EventProvider, 45 org.apache.geronimo.management.ManagedThreadFactory { 46 47 private final static Log LOG = LogFactory.getLog(ManagedThreadFactoryGBean.class); 48 49 public static final GBeanInfo GBEAN_INFO; 50 51 private AbstractName name; 52 53 private GeronimoManagedThreadFactory threadFactory; 54 55 private ManagedContextHandlerChain mainContextHandler; 56 57 private String groupName; 58 private boolean daemonThread; 59 private int threadPriority; 60 private long hungTaskThreshold; 61 62 private long hungTaskMonitorFrequency; 63 64 private NotificationHelper notificationHelper; 65 66 public ManagedThreadFactoryGBean(Kernel kernel, 67 ClassLoader classLoader, 68 AbstractName name, 69 String[] contextHandlerClasses, 70 String groupName, 71 int threadPriority, 72 boolean daemonThread, 73 long hungTaskThreshold, 74 long hungTaskMonitorFrequency) { 75 super(kernel, classLoader); 76 this.name = name; 77 78 this.notificationHelper = new NotificationHelper(kernel, name); 79 80 List<ManagedContextHandler> handlers = 81 ContextHandlerUtils.loadHandlers(classLoader, contextHandlerClasses); 82 83 this.mainContextHandler = new ManagedContextHandlerChain(handlers); 84 85 this.groupName = groupName; 86 this.daemonThread = daemonThread; 87 this.threadPriority = getThreadPriority(threadPriority); 88 this.hungTaskThreshold = hungTaskThreshold; 89 this.hungTaskMonitorFrequency = getHungTaskMonitorFrequency(hungTaskMonitorFrequency); 90 } 91 92 private static int getThreadPriority(int threadPriority) { 93 return (threadPriority <= 0) ? Thread.NORM_PRIORITY : threadPriority; 94 } 95 96 private static long getHungTaskMonitorFrequency(long hungTaskMonitorFrequency) { 97 return (hungTaskMonitorFrequency <= 0) ? 1000 * 60 : hungTaskMonitorFrequency; 98 } 99 100 private void sendNotification(ManagedThreadGBean threadGBean) { 101 if (this.notificationHelper.isNotificationSupported()) { 102 Properties userData = new Properties(); 103 userData.setProperty("managedthread", threadGBean.getObjectName()); 104 105 this.notificationHelper.sendNotification(ManagedConstants.NEW_THREAD_EVENT, userData); 106 } 107 } 108 109 protected void addThreadGBean(GeronimoManagedThread thread) { 110 AbstractName aName = kernel.getNaming().createRootName(name.getArtifact(), thread.getName(), ManagedConstants.MANAGED_THREAD); 111 GBeanData threadData = new GBeanData(aName, ManagedThreadGBean.getGBeanInfo()); 112 113 try { 114 // use either addGBeanKernel() or addGBeanConfiguration() 115 addGBeanKernel(aName, threadData); 116 117 ManagedThreadGBean threadGBean = (ManagedThreadGBean)kernel.getGBean(aName); 118 threadGBean.verifyObjectName(); 119 120 // let gbean know about the thread 121 threadGBean.setManagedThread(thread); 122 // let thread know about the gbean 123 thread.setGbean(threadGBean); 124 125 // send JMX notification 126 sendNotification(threadGBean); 127 128 } catch (Exception e) { 129 LOG.warn("Failed to add thread gbean", e); 130 } 131 } 132 133 protected void removeThreadGBean(GeronimoManagedThread thread) { 134 AbstractName gbeanName = thread.getGbean().getName(); 135 136 removeGBeanKernel(gbeanName); 137 } 138 139 public synchronized GeronimoManagedThreadFactory getManagedThreadFactory() { 140 if (this.threadFactory == null) { 141 // create the factory 142 this.threadFactory = new GeronimoManagedThreadFactory(this); 143 144 this.threadFactory.setThreadGroup(groupName); 145 this.threadFactory.setDaemonThread(daemonThread); 146 this.threadFactory.setThreadPriority(getThreadPriority(threadPriority)); 147 this.threadFactory.setHungTaskThreshold(hungTaskThreshold); 148 this.threadFactory.setHungTaskMonitorFrequency(getHungTaskMonitorFrequency(hungTaskMonitorFrequency)); 149 } 150 151 return this.threadFactory; 152 } 153 154 public Object $getResource(AbstractName moduleID) { 155 GeronimoManagedThreadFactory threadFactory = getManagedThreadFactory(); 156 return new StandaloneManagedThreadFactory(threadFactory, this.mainContextHandler, moduleID); 157 } 158 159 public void doStart() throws Exception { 160 } 161 162 public void doFail() { 163 if (this.threadFactory != null) { 164 this.threadFactory.shutdown(); 165 } 166 } 167 168 public void doStop() throws Exception { 169 doFail(); 170 } 171 172 public String[] getThreads() { 173 if (this.threadFactory != null) { 174 return this.threadFactory.getThreads(); 175 } else { 176 return new String [] {}; 177 } 178 } 179 180 public String[] getHungTaskThreads() { 181 if (this.threadFactory != null) { 182 return this.threadFactory.getHungTaskThreads(); 183 } else { 184 return new String [] {}; 185 } 186 } 187 188 public int getPriority() { 189 return this.threadPriority; 190 } 191 192 public boolean getDaemon() { 193 return this.daemonThread; 194 } 195 196 public long getHungTaskThreshold() { 197 return this.hungTaskThreshold; 198 } 199 200 public long getHungTaskMonitorFrequency() { 201 return this.hungTaskMonitorFrequency; 202 } 203 204 public AbstractName getName() { 205 return this.name; 206 } 207 208 public String getObjectName() { 209 return this.name.getObjectName().getCanonicalName(); 210 } 211 212 public String[] getEventTypes() { 213 return new String[] { ManagedConstants.NEW_THREAD_EVENT }; 214 } 215 216 public boolean isEventProvider() { 217 return true; 218 } 219 220 public boolean isStateManageable() { 221 return true; 222 } 223 224 public boolean isStatisticsProvider() { 225 return false; 226 } 227 228 protected void verifyObjectName() { 229 GBeanBuilder.verifyObjectName(getObjectName(), 230 ManagedConstants.MANAGED_THREAD_FACTORY, 231 ManagedConstants.MANAGED_THREAD_FACTORY); 232 } 233 234 static { 235 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(ManagedThreadFactoryGBean.class, ManagedConstants.MANAGED_THREAD_FACTORY); 236 237 infoFactory.addAttribute("classLoader", ClassLoader.class, false, false); 238 infoFactory.addAttribute("abstractName", AbstractName.class, false, false); 239 infoFactory.addAttribute("kernel", Kernel.class, false, false); 240 241 infoFactory.addAttribute("contextHandlers", String[].class, true, false); 242 243 infoFactory.addAttribute("groupName", String.class, true); 244 infoFactory.addAttribute("priority", int.class, true); 245 infoFactory.addAttribute("daemon", boolean.class, true); 246 infoFactory.addAttribute("hungTaskThreshold", long.class, true); 247 infoFactory.addAttribute("hungTaskMonitorFrequency", long.class, true); 248 249 infoFactory.addInterface(GeronimoManagedThreadFactorySource.class); 250 infoFactory.addInterface(org.apache.geronimo.management.ManagedThreadFactory.class); 251 252 infoFactory.setConstructor(new String[]{"kernel", 253 "classLoader", 254 "abstractName", 255 "contextHandlers", 256 "groupName", 257 "priority", 258 "daemon", 259 "hungTaskThreshold", 260 "hungTaskMonitorFrequency"}); 261 262 GBEAN_INFO = infoFactory.getBeanInfo(); 263 } 264 265 public static GBeanInfo getGBeanInfo() { 266 return GBEAN_INFO; 267 } 268 269 }