001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.tomcat.catalina;
018:
019: import org.apache.catalina.Container;
020: import org.apache.catalina.LifecycleEvent;
021: import org.apache.catalina.LifecycleListener;
022: import org.apache.catalina.Service;
023: import org.apache.catalina.Lifecycle;
024: import org.apache.catalina.core.ContainerBase;
025: import org.apache.catalina.core.StandardContext;
026: import org.apache.catalina.core.StandardEngine;
027: import org.apache.catalina.core.StandardHost;
028: import org.apache.catalina.core.StandardServer;
029:
030: import java.beans.PropertyChangeEvent;
031: import java.beans.PropertyChangeListener;
032: import java.lang.reflect.Field;
033: import java.util.HashMap;
034: import java.util.Map;
035:
036: public class GlobalListenerSupport implements PropertyChangeListener,
037: LifecycleListener {
038: private final StandardServer standardServer;
039: private final ContextListener contextListener;
040:
041: public GlobalListenerSupport(StandardServer standardServer,
042: ContextListener contextListener) {
043: if (standardServer == null)
044: throw new NullPointerException("standardServer is null");
045: if (contextListener == null)
046: throw new NullPointerException("contextListener is null");
047: this .standardServer = standardServer;
048: this .contextListener = contextListener;
049: }
050:
051: public void lifecycleEvent(LifecycleEvent event) {
052: Object source = event.getSource();
053: if (source instanceof StandardContext) {
054: StandardContext standardContext = (StandardContext) source;
055: String type = event.getType();
056: if (Lifecycle.INIT_EVENT.equals(type)) {
057: contextListener.init(standardContext);
058: } else if (Lifecycle.BEFORE_START_EVENT.equals(type)) {
059: contextListener.beforeStart(standardContext);
060: } else if (Lifecycle.START_EVENT.equals(type)) {
061: contextListener.start(standardContext);
062: } else if (Lifecycle.AFTER_START_EVENT.equals(type)) {
063: contextListener.afterStart(standardContext);
064: } else if (Lifecycle.BEFORE_STOP_EVENT.equals(type)) {
065: contextListener.beforeStop(standardContext);
066: } else if (Lifecycle.STOP_EVENT.equals(type)) {
067: contextListener.stop(standardContext);
068: } else if (Lifecycle.AFTER_STOP_EVENT.equals(type)) {
069: contextListener.afterStop(standardContext);
070: } else if (Lifecycle.DESTROY_EVENT.equals(type)) {
071: contextListener.destroy(standardContext);
072: }
073: } else if (source instanceof StandardHost) {
074: StandardHost standardHost = (StandardHost) source;
075: String type = event.getType();
076: if (Lifecycle.PERIODIC_EVENT.equals(type)) {
077: contextListener.checkHost(standardHost);
078: }
079: } else if (source instanceof StandardServer) {
080: StandardServer standardServer = (StandardServer) source;
081: String type = event.getType();
082: if (Lifecycle.AFTER_STOP_EVENT.equals(type)) {
083: contextListener.afterStop(standardServer);
084: }
085: }
086: }
087:
088: public void start() {
089: // hook the hosts so we get notified before contexts are started
090: standardServer.addPropertyChangeListener(this );
091: standardServer.addLifecycleListener(this );
092: for (Service service : standardServer.findServices()) {
093: serviceAdded(service);
094: }
095: }
096:
097: public void stop() {
098: standardServer.removePropertyChangeListener(this );
099: }
100:
101: private void serviceAdded(Service service) {
102: Container container = service.getContainer();
103: if (container instanceof StandardEngine) {
104: StandardEngine engine = (StandardEngine) container;
105: engineAdded(engine);
106: }
107: }
108:
109: private void serviceRemoved(Service service) {
110: Container container = service.getContainer();
111: if (container instanceof StandardEngine) {
112: StandardEngine engine = (StandardEngine) container;
113: engineRemoved(engine);
114: }
115: }
116:
117: private void engineAdded(StandardEngine engine) {
118: addContextListener(engine);
119: for (Container child : engine.findChildren()) {
120: if (child instanceof StandardHost) {
121: StandardHost host = (StandardHost) child;
122: hostAdded(host);
123: }
124: }
125: }
126:
127: private void engineRemoved(StandardEngine engine) {
128: for (Container child : engine.findChildren()) {
129: if (child instanceof StandardHost) {
130: StandardHost host = (StandardHost) child;
131: hostRemoved(host);
132: }
133: }
134: }
135:
136: private void hostAdded(StandardHost host) {
137: addContextListener(host);
138: host.addLifecycleListener(this );
139: for (Container child : host.findChildren()) {
140: if (child instanceof StandardContext) {
141: StandardContext context = (StandardContext) child;
142: contextAdded(context);
143: }
144: }
145: }
146:
147: private void hostRemoved(StandardHost host) {
148: for (Container child : host.findChildren()) {
149: if (child instanceof StandardContext) {
150: StandardContext context = (StandardContext) child;
151: contextRemoved(context);
152: }
153: }
154: }
155:
156: private void contextAdded(StandardContext context) {
157: // put this class as the first listener so we can process the application before any classes are loaded
158: forceFirstLifecycleListener(context);
159: }
160:
161: private void forceFirstLifecycleListener(StandardContext context) {
162: LifecycleListener[] listeners = context
163: .findLifecycleListeners();
164:
165: // if we are already first return
166: if (listeners.length > 0 && listeners[0] == this ) {
167: return;
168: }
169:
170: // remove all of the current listeners
171: for (LifecycleListener listener : listeners) {
172: context.removeLifecycleListener(listener);
173: }
174:
175: // add this class (as first)
176: context.addLifecycleListener(this );
177:
178: // add back all listeners
179: for (LifecycleListener listener : listeners) {
180: if (listener != this ) {
181: context.addLifecycleListener(listener);
182: }
183: }
184: }
185:
186: @SuppressWarnings({"UnusedDeclaration"})
187: private void contextRemoved(StandardContext context) {
188: }
189:
190: public void propertyChange(PropertyChangeEvent event) {
191: if ("service".equals(event.getPropertyName())) {
192: Object oldValue = event.getOldValue();
193: Object newValue = event.getNewValue();
194: if (oldValue == null && newValue instanceof Service) {
195: serviceAdded((Service) newValue);
196: }
197: if (oldValue instanceof Service && newValue == null) {
198: serviceRemoved((Service) oldValue);
199: }
200: }
201: if ("children".equals(event.getPropertyName())) {
202: Object source = event.getSource();
203: Object oldValue = event.getOldValue();
204: Object newValue = event.getNewValue();
205: if (source instanceof StandardEngine) {
206: if (oldValue == null
207: && newValue instanceof StandardHost) {
208: hostAdded((StandardHost) newValue);
209: }
210: if (oldValue instanceof StandardHost
211: && newValue == null) {
212: hostRemoved((StandardHost) oldValue);
213: }
214: }
215: if (source instanceof StandardHost) {
216: if (oldValue == null
217: && newValue instanceof StandardContext) {
218: contextAdded((StandardContext) newValue);
219: }
220: if (oldValue instanceof StandardContext
221: && newValue == null) {
222: contextRemoved((StandardContext) oldValue);
223: }
224: }
225: }
226: }
227:
228: private void addContextListener(ContainerBase containerBase) {
229: try {
230: Field field = ContainerBase.class
231: .getDeclaredField("children");
232: field.setAccessible(true);
233: Map children = (Map) field.get(containerBase);
234: if (children instanceof GlobalListenerSupport.MoniterableHashMap) {
235: return;
236: }
237: children = new GlobalListenerSupport.MoniterableHashMap(
238: children, containerBase, "children", this );
239: field.set(containerBase, children);
240: } catch (Exception e) {
241: e.printStackTrace();
242: }
243:
244: }
245:
246: @SuppressWarnings({"unchecked"})
247: public static class MoniterableHashMap extends HashMap {
248: private final Object source;
249: private final String propertyName;
250: private final PropertyChangeListener listener;
251:
252: public MoniterableHashMap(Map m, Object source,
253: String propertyName, PropertyChangeListener listener) {
254: super (m);
255: this .source = source;
256: this .propertyName = propertyName;
257: this .listener = listener;
258: }
259:
260: public Object put(Object key, Object value) {
261: Object oldValue = super .put(key, value);
262: PropertyChangeEvent event = new PropertyChangeEvent(source,
263: propertyName, null, value);
264: listener.propertyChange(event);
265: return oldValue;
266: }
267:
268: public Object remove(Object key) {
269: Object value = super .remove(key);
270: PropertyChangeEvent event = new PropertyChangeEvent(source,
271: propertyName, value, null);
272: listener.propertyChange(event);
273: return value;
274: }
275: }
276: }
|