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
18 package org.apache.jk.server;
19
20 import java.io.IOException;
21 import java.util.Iterator;
22
23 import javax.management.MBeanServer;
24 import javax.management.ObjectName;
25
26 import org.apache.coyote.Adapter;
27 import org.apache.coyote.ProtocolHandler;
28 import org.apache.coyote.Request;
29 import org.apache.coyote.Response;
30 import org.apache.coyote.RequestInfo;
31 import org.apache.coyote.Constants;
32 import org.apache.jk.core.JkHandler;
33 import org.apache.jk.core.Msg;
34 import org.apache.jk.core.MsgContext;
35 import org.apache.tomcat.util.modeler.Registry;
36
37 /** Plugs Jk into Coyote. Must be named "type=JkHandler,name=container"
38 *
39 * jmx:notification-handler name="org.apache.jk.SEND_PACKET
40 * jmx:notification-handler name="org.apache.coyote.ACTION_COMMIT
41 */
42 public class JkCoyoteHandler extends JkHandler implements ProtocolHandler {
43 protected static org.apache.juli.logging.Log log
44 = org.apache.juli.logging.LogFactory.getLog(JkCoyoteHandler.class);
45 // Set debug on this logger to see the container request time
46
47 // ----------------------------------------------------------- DoPrivileged
48 private boolean paused = false;
49 int epNote;
50 Adapter adapter;
51 protected JkMain jkMain=null;
52
53 /** Set a property. Name is a "component.property". JMX should
54 * be used instead.
55 */
56 public void setProperty( String name, String value ) {
57 if( log.isTraceEnabled())
58 log.trace("setProperty " + name + " " + value );
59 getJkMain().setProperty( name, value );
60 properties.put( name, value );
61 }
62
63 public String getProperty( String name ) {
64 return properties.getProperty(name) ;
65 }
66
67 public Iterator getAttributeNames() {
68 return properties.keySet().iterator();
69 }
70
71 /** Pass config info
72 */
73 public void setAttribute( String name, Object value ) {
74 if( log.isDebugEnabled())
75 log.debug("setAttribute " + name + " " + value );
76 if( value instanceof String )
77 this.setProperty( name, (String)value );
78 }
79
80 /**
81 * Retrieve config info.
82 * Primarily for use with the admin webapp.
83 */
84 public Object getAttribute( String name ) {
85 return getJkMain().getProperty(name);
86 }
87
88 /** The adapter, used to call the connector
89 */
90 public void setAdapter(Adapter adapter) {
91 this.adapter=adapter;
92 }
93
94 public Adapter getAdapter() {
95 return adapter;
96 }
97
98 public JkMain getJkMain() {
99 if( jkMain == null ) {
100 jkMain=new JkMain();
101 jkMain.setWorkerEnv(wEnv);
102
103 }
104 return jkMain;
105 }
106
107 boolean started=false;
108
109 /** Start the protocol
110 */
111 public void init() {
112 if( started ) return;
113
114 started=true;
115
116 if( wEnv==null ) {
117 // we are probably not registered - not very good.
118 wEnv=getJkMain().getWorkerEnv();
119 wEnv.addHandler("container", this );
120 }
121
122 try {
123 // jkMain.setJkHome() XXX;
124
125 getJkMain().init();
126
127 } catch( Exception ex ) {
128 log.error("Error during init",ex);
129 }
130 }
131
132 public void start() {
133 try {
134 if( oname != null && getJkMain().getDomain() == null) {
135 try {
136 ObjectName jkmainOname =
137 new ObjectName(oname.getDomain() + ":type=JkMain");
138 Registry.getRegistry(null, null)
139 .registerComponent(getJkMain(), jkmainOname, "JkMain");
140 } catch (Exception e) {
141 log.error( "Error registering jkmain " + e );
142 }
143 }
144 getJkMain().start();
145 } catch( Exception ex ) {
146 log.error("Error during startup",ex);
147 }
148 }
149
150 public void pause() throws Exception {
151 if(!paused) {
152 paused = true;
153 getJkMain().pause();
154 }
155 }
156
157 public void resume() throws Exception {
158 if(paused) {
159 paused = false;
160 getJkMain().resume();
161 }
162 }
163
164 public void destroy() {
165 if( !started ) return;
166
167 started = false;
168 getJkMain().stop();
169 }
170
171
172 // -------------------- Jk handler implementation --------------------
173 // Jk Handler mehod
174 public int invoke( Msg msg, MsgContext ep )
175 throws IOException {
176 if( ep.isLogTimeEnabled() )
177 ep.setLong( MsgContext.TIMER_PRE_REQUEST, System.currentTimeMillis());
178
179 Request req=ep.getRequest();
180 Response res=req.getResponse();
181
182 if( log.isDebugEnabled() )
183 log.debug( "Invoke " + req + " " + res + " " + req.requestURI().toString());
184
185 res.setNote( epNote, ep );
186 ep.setStatus( MsgContext.JK_STATUS_HEAD );
187 RequestInfo rp = req.getRequestProcessor();
188 rp.setStage(Constants.STAGE_SERVICE);
189 try {
190 adapter.service( req, res );
191 } catch( Exception ex ) {
192 log.info("Error servicing request " + req,ex);
193 }
194 if(ep.getStatus() != MsgContext.JK_STATUS_CLOSED) {
195 res.finish();
196 }
197
198 req.updateCounters();
199 req.recycle();
200 res.recycle();
201 ep.recycle();
202 if( ep.getStatus() == MsgContext.JK_STATUS_ERROR ) {
203 return ERROR;
204 }
205 ep.setStatus( MsgContext.JK_STATUS_NEW );
206 rp.setStage(Constants.STAGE_KEEPALIVE);
207 return OK;
208 }
209
210
211 public ObjectName preRegister(MBeanServer server,
212 ObjectName oname) throws Exception
213 {
214 // override - we must be registered as "container"
215 this.name="container";
216 return super.preRegister(server, oname);
217 }
218 }