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:
018: package org.apache.catalina.valves;
019:
020: import java.io.IOException;
021:
022: import javax.management.MBeanRegistration;
023: import javax.management.MBeanServer;
024: import javax.management.MalformedObjectNameException;
025: import javax.management.ObjectName;
026: import javax.servlet.ServletException;
027:
028: import org.apache.catalina.CometEvent;
029: import org.apache.catalina.Contained;
030: import org.apache.catalina.Container;
031: import org.apache.catalina.Context;
032: import org.apache.catalina.Engine;
033: import org.apache.catalina.Host;
034: import org.apache.catalina.Pipeline;
035: import org.apache.catalina.Valve;
036: import org.apache.catalina.Wrapper;
037: import org.apache.catalina.connector.Request;
038: import org.apache.catalina.connector.Response;
039: import org.apache.catalina.core.ContainerBase;
040: import org.apache.catalina.util.StringManager;
041: import org.apache.juli.logging.Log;
042: import org.apache.juli.logging.LogFactory;
043:
044: /**
045: * Convenience base class for implementations of the <b>Valve</b> interface.
046: * A subclass <strong>MUST</strong> implement an <code>invoke()</code>
047: * method to provide the required functionality, and <strong>MAY</strong>
048: * implement the <code>Lifecycle</code> interface to provide configuration
049: * management and lifecycle support.
050: *
051: * @author Craig R. McClanahan
052: * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
053: */
054:
055: public abstract class ValveBase implements Contained, Valve,
056: MBeanRegistration {
057: private static Log log = LogFactory.getLog(ValveBase.class);
058:
059: //------------------------------------------------------ Instance Variables
060:
061: /**
062: * The Container whose pipeline this Valve is a component of.
063: */
064: protected Container container = null;
065:
066: /**
067: * Container log
068: */
069: protected Log containerLog = null;
070:
071: /**
072: * Descriptive information about this Valve implementation. This value
073: * should be overridden by subclasses.
074: */
075: protected static String info = "org.apache.catalina.core.ValveBase/1.0";
076:
077: /**
078: * The next Valve in the pipeline this Valve is a component of.
079: */
080: protected Valve next = null;
081:
082: /**
083: * The string manager for this package.
084: */
085: protected final static StringManager sm = StringManager
086: .getManager(Constants.Package);
087:
088: //-------------------------------------------------------------- Properties
089:
090: /**
091: * Return the Container with which this Valve is associated, if any.
092: */
093: public Container getContainer() {
094:
095: return (container);
096:
097: }
098:
099: /**
100: * Set the Container with which this Valve is associated, if any.
101: *
102: * @param container The new associated container
103: */
104: public void setContainer(Container container) {
105:
106: this .container = container;
107:
108: }
109:
110: /**
111: * Return descriptive information about this Valve implementation.
112: */
113: public String getInfo() {
114:
115: return (info);
116:
117: }
118:
119: /**
120: * Return the next Valve in this pipeline, or <code>null</code> if this
121: * is the last Valve in the pipeline.
122: */
123: public Valve getNext() {
124:
125: return (next);
126:
127: }
128:
129: /**
130: * Set the Valve that follows this one in the pipeline it is part of.
131: *
132: * @param valve The new next valve
133: */
134: public void setNext(Valve valve) {
135:
136: this .next = valve;
137:
138: }
139:
140: //---------------------------------------------------------- Public Methods
141:
142: /**
143: * Execute a periodic task, such as reloading, etc. This method will be
144: * invoked inside the classloading context of this container. Unexpected
145: * throwables will be caught and logged.
146: */
147: public void backgroundProcess() {
148: }
149:
150: /**
151: * The implementation-specific logic represented by this Valve. See the
152: * Valve description for the normal design patterns for this method.
153: * <p>
154: * This method <strong>MUST</strong> be provided by a subclass.
155: *
156: * @param request The servlet request to be processed
157: * @param response The servlet response to be created
158: *
159: * @exception IOException if an input/output error occurs
160: * @exception ServletException if a servlet error occurs
161: */
162: public abstract void invoke(Request request, Response response)
163: throws IOException, ServletException;
164:
165: /**
166: * Process a Comet event. This method will rarely need to be provided by
167: * a subclass, unless it needs to reassociate a particular object with
168: * the thread that is processing the request.
169: *
170: * @param request The servlet request to be processed
171: * @param response The servlet response to be created
172: *
173: * @exception IOException if an input/output error occurs, or is thrown
174: * by a subsequently invoked Valve, Filter, or Servlet
175: * @exception ServletException if a servlet error occurs, or is thrown
176: * by a subsequently invoked Valve, Filter, or Servlet
177: */
178: public void event(Request request, Response response,
179: CometEvent event) throws IOException, ServletException {
180: // Perform the request
181: getNext().event(request, response, event);
182: }
183:
184: /**
185: * Return a String rendering of this object.
186: */
187: public String toString() {
188: StringBuffer sb = new StringBuffer(this .getClass().getName());
189: sb.append("[");
190: if (container != null)
191: sb.append(container.getName());
192: sb.append("]");
193: return (sb.toString());
194: }
195:
196: // -------------------- JMX and Registration --------------------
197: protected String domain;
198: protected ObjectName oname;
199: protected MBeanServer mserver;
200: protected ObjectName controller;
201:
202: public ObjectName getObjectName() {
203: return oname;
204: }
205:
206: public void setObjectName(ObjectName oname) {
207: this .oname = oname;
208: }
209:
210: public String getDomain() {
211: return domain;
212: }
213:
214: public ObjectName preRegister(MBeanServer server, ObjectName name)
215: throws Exception {
216: oname = name;
217: mserver = server;
218: domain = name.getDomain();
219:
220: return name;
221: }
222:
223: public void postRegister(Boolean registrationDone) {
224: }
225:
226: public void preDeregister() throws Exception {
227: }
228:
229: public void postDeregister() {
230: }
231:
232: public ObjectName getController() {
233: return controller;
234: }
235:
236: public void setController(ObjectName controller) {
237: this .controller = controller;
238: }
239:
240: /** From the name, extract the parent object name
241: *
242: * @param valveName The valve name
243: * @return ObjectName The parent name
244: */
245: public ObjectName getParentName(ObjectName valveName) {
246:
247: return null;
248: }
249:
250: public ObjectName createObjectName(String domain, ObjectName parent)
251: throws MalformedObjectNameException {
252: Container container = this .getContainer();
253: if (container == null || !(container instanceof ContainerBase))
254: return null;
255: this .containerLog = container.getLogger();
256: ContainerBase containerBase = (ContainerBase) container;
257: Pipeline pipe = containerBase.getPipeline();
258: Valve valves[] = pipe.getValves();
259:
260: /* Compute the "parent name" part */
261: String parentName = "";
262: if (container instanceof Engine) {
263: } else if (container instanceof Host) {
264: parentName = ",host=" + container.getName();
265: } else if (container instanceof Context) {
266: String path = ((Context) container).getPath();
267: if (path.length() < 1) {
268: path = "/";
269: }
270: Host host = (Host) container.getParent();
271: parentName = ",path=" + path + ",host=" + host.getName();
272: } else if (container instanceof Wrapper) {
273: Context ctx = (Context) container.getParent();
274: String path = ctx.getPath();
275: if (path.length() < 1) {
276: path = "/";
277: }
278: Host host = (Host) ctx.getParent();
279: parentName = ",servlet=" + container.getName() + ",path="
280: + path + ",host=" + host.getName();
281: }
282: log.debug("valve parent=" + parentName + " " + parent);
283:
284: String className = this .getClass().getName();
285: int period = className.lastIndexOf('.');
286: if (period >= 0)
287: className = className.substring(period + 1);
288:
289: int seq = 0;
290: for (int i = 0; i < valves.length; i++) {
291: // Find other valves with the same name
292: if (valves[i] == this ) {
293: break;
294: }
295: if (valves[i] != null
296: && valves[i].getClass() == this .getClass()) {
297: log.debug("Duplicate " + valves[i] + " " + this + " "
298: + container);
299: seq++;
300: }
301: }
302: String ext = "";
303: if (seq > 0) {
304: ext = ",seq=" + seq;
305: }
306:
307: ObjectName objectName = new ObjectName(domain
308: + ":type=Valve,name=" + className + ext + parentName);
309: log.debug("valve objectname = " + objectName);
310: return objectName;
311: }
312:
313: // -------------------- JMX data --------------------
314:
315: public ObjectName getContainerName() {
316: if (container == null)
317: return null;
318: return ((ContainerBase) container).getJmxName();
319: }
320: }
|