/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.jk.server; import java.io.IOException; import java.util.Iterator; import javax.management.MBeanServer; import javax.management.ObjectName; import org.apache.coyote.AbstractProtocol; import org.apache.coyote.Adapter; import org.apache.coyote.ProtocolHandler; import org.apache.coyote.Request; import org.apache.coyote.Response; import org.apache.coyote.RequestInfo; import org.apache.coyote.Constants; import org.apache.jk.common.ChannelNioSocket; import org.apache.jk.common.ChannelSocket; import org.apache.jk.core.JkHandler; import org.apache.jk.core.Msg; import org.apache.jk.core.MsgContext; import org.apache.jk.core.WorkerEnv; import org.apache.tomcat.util.modeler.Registry; /** Plugs Jk into Coyote. Must be named "type=JkHandler,name=container" * * jmx:notification-handler name="org.apache.jk.SEND_PACKET * jmx:notification-handler name="org.apache.coyote.ACTION_COMMIT */ public class JkCoyoteHandler extends JkHandler implements ProtocolHandler { protected static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog(JkCoyoteHandler.class); // Set debug on this logger to see the container request time /** * Unique ID for this connector. Only used if the connector is configured * to use a random port as the port will change if stop(), start() is * called. */ private int nameIndex = 0; public synchronized int getNameIndex() { if (nameIndex == 0) { nameIndex = AbstractProtocol.nextNameIndex(); } return nameIndex; } public int getLocalPort() { WorkerEnv wEnv = getJkMain().getWorkerEnv(); for( int i=0; i<wEnv.getHandlerCount(); i++ ) { JkHandler w = wEnv.getHandler(i); if( w instanceof ChannelSocket ) { return ((ChannelSocket) w).getPort(); } if( w instanceof ChannelNioSocket ) { return ((ChannelNioSocket) w).getPort(); } } return -1; } // ----------------------------------------------------------- DoPrivileged private boolean paused = false; int epNote; Adapter adapter; protected JkMain jkMain=null; /** Set a property. Name is a "component.property". JMX should * be used instead. */ public void setProperty( String name, String value ) { if( log.isTraceEnabled()) log.trace("setProperty " + name + " " + value ); getJkMain().setProperty( name, value ); properties.put( name, value ); } public String getProperty( String name ) { return properties.getProperty(name) ; } public Iterator getAttributeNames() { return properties.keySet().iterator(); } /** Pass config info */ public void setAttribute( String name, Object value ) { if( log.isDebugEnabled()) log.debug("setAttribute " + name + " " + value ); if( value instanceof String ) this.setProperty( name, (String)value ); } /** * Retrieve config info. * Primarily for use with the admin webapp. */ public Object getAttribute( String name ) { return getJkMain().getProperty(name); } /** The adapter, used to call the connector */ public void setAdapter(Adapter adapter) { this.adapter=adapter; } public Adapter getAdapter() { return adapter; } public JkMain getJkMain() { if( jkMain == null ) { jkMain=new JkMain(); jkMain.setWorkerEnv(wEnv); } return jkMain; } boolean started=false; /** Start the protocol */ public void init() { if( started ) return; started=true; if( wEnv==null ) { // we are probably not registered - not very good. wEnv=getJkMain().getWorkerEnv(); wEnv.addHandler("container", this ); } try { // jkMain.setJkHome() XXX; getJkMain().init(); } catch( Exception ex ) { log.error("Error during init",ex); } } public void start() { try { if( oname != null && getJkMain().getDomain() == null) { try { ObjectName jkmainOname = new ObjectName(oname.getDomain() + ":type=JkMain"); Registry.getRegistry(null, null) .registerComponent(getJkMain(), jkmainOname, "JkMain"); } catch (Exception e) { log.error( "Error registering jkmain " + e ); } } getJkMain().start(); } catch( Exception ex ) { log.error("Error during startup",ex); } } public void pause() throws Exception { if(!paused) { paused = true; getJkMain().pause(); } } public void resume() throws Exception { if(paused) { paused = false; getJkMain().resume(); } } public void destroy() { if( !started ) return; started = false; getJkMain().stop(); } // -------------------- Jk handler implementation -------------------- // Jk Handler mehod public int invoke( Msg msg, MsgContext ep ) throws IOException { if( ep.isLogTimeEnabled() ) ep.setLong( MsgContext.TIMER_PRE_REQUEST, System.currentTimeMillis()); Request req=ep.getRequest(); Response res=req.getResponse(); if( log.isDebugEnabled() ) log.debug( "Invoke " + req + " " + res + " " + req.requestURI().toString()); res.setNote( epNote, ep ); ep.setStatus( MsgContext.JK_STATUS_HEAD ); RequestInfo rp = req.getRequestProcessor(); rp.setStage(Constants.STAGE_SERVICE); try { adapter.service( req, res ); } catch( Throwable t ) { ep.setStatus(MsgContext.JK_STATUS_ERROR); log.info("Error servicing request " + req,t); } if(ep.getStatus() != MsgContext.JK_STATUS_CLOSED) { res.finish(); } req.updateCounters(); req.recycle(); res.recycle(); ep.recycle(); if( ep.getStatus() == MsgContext.JK_STATUS_ERROR ) { return ERROR; } ep.setStatus( MsgContext.JK_STATUS_NEW ); rp.setStage(Constants.STAGE_KEEPALIVE); return OK; } public ObjectName preRegister(MBeanServer server, ObjectName oname) throws Exception { // override - we must be registered as "container" this.name="container"; return super.preRegister(server, oname); } }