001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.catalina.connector;
018:
019: import java.util.Iterator;
020: import java.util.Set;
021:
022: import javax.management.MBeanServer;
023: import javax.management.MBeanServerNotification;
024: import javax.management.Notification;
025: import javax.management.NotificationListener;
026: import javax.management.ObjectInstance;
027: import javax.management.ObjectName;
028:
029: import org.apache.juli.logging.Log;
030: import org.apache.juli.logging.LogFactory;
031:
032: import org.apache.tomcat.util.http.mapper.Mapper;
033: import org.apache.tomcat.util.modeler.Registry;
034:
035: import org.apache.tomcat.util.res.StringManager;
036:
037: /**
038: * Mapper listener.
039: *
040: * @author Remy Maucherat
041: * @author Costin Manolache
042: */
043: public class MapperListener implements NotificationListener {
044: private static Log log = LogFactory.getLog(MapperListener.class);
045:
046: // ----------------------------------------------------- Instance Variables
047: /**
048: * Associated mapper.
049: */
050: protected Mapper mapper = null;
051:
052: /**
053: * MBean server.
054: */
055: protected MBeanServer mBeanServer = null;
056:
057: /**
058: * The string manager for this package.
059: */
060: private StringManager sm = StringManager
061: .getManager(Constants.Package);
062:
063: // It should be null - and fail if not set
064: private String domain = "*";
065: private String engine = "*";
066:
067: // ----------------------------------------------------------- Constructors
068:
069: /**
070: * Create mapper listener.
071: */
072: public MapperListener(Mapper mapper) {
073: this .mapper = mapper;
074: }
075:
076: // --------------------------------------------------------- Public Methods
077:
078: public String getDomain() {
079: return domain;
080: }
081:
082: public void setDomain(String domain) {
083: this .domain = domain;
084: }
085:
086: public String getEngine() {
087: return engine;
088: }
089:
090: public void setEngine(String engine) {
091: this .engine = engine;
092: }
093:
094: /**
095: * Initialize associated mapper.
096: */
097: public void init() {
098:
099: try {
100:
101: mBeanServer = Registry.getRegistry(null, null)
102: .getMBeanServer();
103:
104: registerEngine();
105:
106: // Query hosts
107: String onStr = domain + ":type=Host,*";
108: ObjectName objectName = new ObjectName(onStr);
109: Set set = mBeanServer.queryMBeans(objectName, null);
110: Iterator iterator = set.iterator();
111: while (iterator.hasNext()) {
112: ObjectInstance oi = (ObjectInstance) iterator.next();
113: registerHost(oi.getObjectName());
114: }
115:
116: // Query contexts
117: onStr = "*:j2eeType=WebModule,*";
118: objectName = new ObjectName(onStr);
119: set = mBeanServer.queryMBeans(objectName, null);
120: iterator = set.iterator();
121: while (iterator.hasNext()) {
122: ObjectInstance oi = (ObjectInstance) iterator.next();
123: registerContext(oi.getObjectName());
124: }
125:
126: // Query wrappers
127: onStr = "*:j2eeType=Servlet,*";
128: objectName = new ObjectName(onStr);
129: set = mBeanServer.queryMBeans(objectName, null);
130: iterator = set.iterator();
131: while (iterator.hasNext()) {
132: ObjectInstance oi = (ObjectInstance) iterator.next();
133: registerWrapper(oi.getObjectName());
134: }
135:
136: onStr = "JMImplementation:type=MBeanServerDelegate";
137: objectName = new ObjectName(onStr);
138: mBeanServer.addNotificationListener(objectName, this , null,
139: null);
140:
141: } catch (Exception e) {
142: log.warn("Error registering contexts", e);
143: }
144:
145: }
146:
147: /**
148: * unregister this from JMImplementation:type=MBeanServerDelegate
149: */
150: public void destroy() {
151: try {
152:
153: ObjectName objectName = new ObjectName(
154: "JMImplementation:type=MBeanServerDelegate");
155: mBeanServer.removeNotificationListener(objectName, this );
156: } catch (Exception e) {
157: log.warn("Error unregistering MBeanServerDelegate", e);
158: }
159: }
160:
161: // ------------------------------------------- NotificationListener Methods
162:
163: public void handleNotification(Notification notification,
164: java.lang.Object handback) {
165:
166: if (notification instanceof MBeanServerNotification) {
167: ObjectName objectName = ((MBeanServerNotification) notification)
168: .getMBeanName();
169: String j2eeType = objectName.getKeyProperty("j2eeType");
170: String engineName = null;
171: if (j2eeType != null) {
172: if ((j2eeType.equals("WebModule"))
173: || (j2eeType.equals("Servlet"))) {
174: if (mBeanServer.isRegistered(objectName)) {
175: try {
176: engineName = (String) mBeanServer
177: .getAttribute(objectName,
178: "engineName");
179: } catch (Exception e) {
180: // Ignore
181: }
182: }
183: }
184: }
185:
186: // At deployment time, engineName is always = null.
187: if ((!"*".equals(domain))
188: && (!domain.equals(objectName.getDomain()))
189: && ((!domain.equals(engineName)) && (engineName != null))) {
190: return;
191: }
192: if (log.isDebugEnabled())
193: log.debug("Handle " + objectName + " type : "
194: + notification.getType());
195: if (notification.getType().equals(
196: MBeanServerNotification.REGISTRATION_NOTIFICATION)) {
197: String type = objectName.getKeyProperty("type");
198: if ("Host".equals(type)
199: && domain.equals(objectName.getDomain())) {
200: try {
201: registerHost(objectName);
202: } catch (Exception e) {
203: log.warn(
204: "Error registering Host " + objectName,
205: e);
206: }
207: }
208:
209: if (j2eeType != null) {
210: if (j2eeType.equals("WebModule")) {
211: try {
212: registerContext(objectName);
213: } catch (Throwable t) {
214: log.warn("Error registering Context "
215: + objectName, t);
216: }
217: } else if (j2eeType.equals("Servlet")) {
218: try {
219: registerWrapper(objectName);
220: } catch (Throwable t) {
221: log.warn("Error registering Wrapper "
222: + objectName, t);
223: }
224: }
225: }
226: } else if (notification
227: .getType()
228: .equals(
229: MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) {
230: String type = objectName.getKeyProperty("type");
231: if ("Host".equals(type)
232: && domain.equals(objectName.getDomain())) {
233: try {
234: unregisterHost(objectName);
235: } catch (Exception e) {
236: log.warn("Error unregistering Host "
237: + objectName, e);
238: }
239: }
240:
241: if (j2eeType != null) {
242: if (j2eeType.equals("WebModule")) {
243: try {
244: unregisterContext(objectName);
245: } catch (Throwable t) {
246: log.warn("Error unregistering webapp "
247: + objectName, t);
248: }
249: }
250: }
251: }
252: }
253:
254: }
255:
256: // ------------------------------------------------------ Protected Methods
257:
258: private void registerEngine() throws Exception {
259: ObjectName engineName = new ObjectName(domain + ":type=Engine");
260: if (!mBeanServer.isRegistered(engineName))
261: return;
262: String defaultHost = (String) mBeanServer.getAttribute(
263: engineName, "defaultHost");
264: ObjectName hostName = new ObjectName(domain + ":type=Host,"
265: + "host=" + defaultHost);
266: if (!mBeanServer.isRegistered(hostName)) {
267:
268: // Get the hosts' list
269: String onStr = domain + ":type=Host,*";
270: ObjectName objectName = new ObjectName(onStr);
271: Set set = mBeanServer.queryMBeans(objectName, null);
272: Iterator iterator = set.iterator();
273: String[] aliases;
274: boolean isRegisteredWithAlias = false;
275:
276: while (iterator.hasNext()) {
277:
278: if (isRegisteredWithAlias)
279: break;
280:
281: ObjectInstance oi = (ObjectInstance) iterator.next();
282: hostName = oi.getObjectName();
283: aliases = (String[]) mBeanServer.invoke(hostName,
284: "findAliases", null, null);
285:
286: for (int i = 0; i < aliases.length; i++) {
287: if (aliases[i].equalsIgnoreCase(defaultHost)) {
288: isRegisteredWithAlias = true;
289: break;
290: }
291: }
292: }
293:
294: if (!isRegisteredWithAlias && log.isWarnEnabled())
295: log.warn(sm.getString(
296: "mapperListener.unknownDefaultHost",
297: defaultHost));
298: }
299: // This should probablt be called later
300: if (defaultHost != null) {
301: mapper.setDefaultHostName(defaultHost);
302: }
303: }
304:
305: /**
306: * Register host.
307: */
308: private void registerHost(ObjectName objectName) throws Exception {
309: String name = objectName.getKeyProperty("host");
310: if (name != null) {
311: String[] aliases = (String[]) mBeanServer.invoke(
312: objectName, "findAliases", null, null);
313: mapper.addHost(name, aliases, objectName);
314: if (log.isDebugEnabled())
315: log.debug(sm.getString("mapperListener.registerHost",
316: name, domain));
317:
318: }
319: }
320:
321: /**
322: * Unregister host.
323: */
324: private void unregisterHost(ObjectName objectName) throws Exception {
325: String name = objectName.getKeyProperty("host");
326: mapper.removeHost(name);
327: if (log.isDebugEnabled())
328: log.debug(sm.getString("mapperListener.unregisterHost",
329: name, domain));
330: }
331:
332: /**
333: * Register context.
334: */
335: private void registerContext(ObjectName objectName)
336: throws Exception {
337:
338: String name = objectName.getKeyProperty("name");
339:
340: // If the domain is the same with ours or the engine
341: // name attribute is the same... - then it's ours
342: String targetDomain = objectName.getDomain();
343: if (!domain.equals(targetDomain)) {
344: try {
345: targetDomain = (String) mBeanServer.getAttribute(
346: objectName, "engineName");
347: } catch (Exception e) {
348: // Ignore
349: }
350: if (!domain.equals(targetDomain)) {
351: // not ours
352: return;
353: }
354: }
355:
356: String hostName = null;
357: String contextName = null;
358: if (name.startsWith("//")) {
359: name = name.substring(2);
360: }
361: int slash = name.indexOf("/");
362: if (slash != -1) {
363: hostName = name.substring(0, slash);
364: contextName = name.substring(slash);
365: } else {
366: return;
367: }
368: // Special case for the root context
369: if (contextName.equals("/")) {
370: contextName = "";
371: }
372:
373: if (log.isDebugEnabled())
374: log.debug(sm.getString("mapperListener.registerContext",
375: contextName));
376:
377: Object context = mBeanServer.invoke(objectName,
378: "findMappingObject", null, null);
379: //mBeanServer.getAttribute(objectName, "mappingObject");
380: javax.naming.Context resources = (javax.naming.Context) mBeanServer
381: .invoke(objectName, "findStaticResources", null, null);
382: //mBeanServer.getAttribute(objectName, "staticResources");
383: String[] welcomeFiles = (String[]) mBeanServer.getAttribute(
384: objectName, "welcomeFiles");
385:
386: mapper.addContext(hostName, contextName, context, welcomeFiles,
387: resources);
388:
389: }
390:
391: /**
392: * Unregister context.
393: */
394: private void unregisterContext(ObjectName objectName)
395: throws Exception {
396:
397: String name = objectName.getKeyProperty("name");
398:
399: // If the domain is the same with ours or the engine
400: // name attribute is the same... - then it's ours
401: String targetDomain = objectName.getDomain();
402: if (!domain.equals(targetDomain)) {
403: try {
404: targetDomain = (String) mBeanServer.getAttribute(
405: objectName, "engineName");
406: } catch (Exception e) {
407: // Ignore
408: }
409: if (!domain.equals(targetDomain)) {
410: // not ours
411: return;
412: }
413: }
414:
415: String hostName = null;
416: String contextName = null;
417: if (name.startsWith("//")) {
418: name = name.substring(2);
419: }
420: int slash = name.indexOf("/");
421: if (slash != -1) {
422: hostName = name.substring(0, slash);
423: contextName = name.substring(slash);
424: } else {
425: return;
426: }
427: // Special case for the root context
428: if (contextName.equals("/")) {
429: contextName = "";
430: }
431: if (log.isDebugEnabled())
432: log.debug(sm.getString("mapperListener.unregisterContext",
433: contextName));
434:
435: mapper.removeContext(hostName, contextName);
436:
437: }
438:
439: /**
440: * Register wrapper.
441: */
442: private void registerWrapper(ObjectName objectName)
443: throws Exception {
444:
445: // If the domain is the same with ours or the engine
446: // name attribute is the same... - then it's ours
447: String targetDomain = objectName.getDomain();
448: if (!domain.equals(targetDomain)) {
449: try {
450: targetDomain = (String) mBeanServer.getAttribute(
451: objectName, "engineName");
452: } catch (Exception e) {
453: // Ignore
454: }
455: if (!domain.equals(targetDomain)) {
456: // not ours
457: return;
458: }
459:
460: }
461:
462: String wrapperName = objectName.getKeyProperty("name");
463: String name = objectName.getKeyProperty("WebModule");
464:
465: String hostName = null;
466: String contextName = null;
467: if (name.startsWith("//")) {
468: name = name.substring(2);
469: }
470: int slash = name.indexOf("/");
471: if (slash != -1) {
472: hostName = name.substring(0, slash);
473: contextName = name.substring(slash);
474: } else {
475: return;
476: }
477: // Special case for the root context
478: if (contextName.equals("/")) {
479: contextName = "";
480: }
481: if (log.isDebugEnabled())
482: log.debug(sm.getString("mapperListener.registerWrapper",
483: wrapperName, contextName));
484:
485: String[] mappings = (String[]) mBeanServer.invoke(objectName,
486: "findMappings", null, null);
487: Object wrapper = mBeanServer.invoke(objectName,
488: "findMappingObject", null, null);
489:
490: for (int i = 0; i < mappings.length; i++) {
491: boolean jspWildCard = (wrapperName.equals("jsp") && mappings[i]
492: .endsWith("/*"));
493: mapper.addWrapper(hostName, contextName, mappings[i],
494: wrapper, jspWildCard);
495: }
496:
497: }
498:
499: }
|