|
What this is
Other links
The source code/* * Copyright 1999-2004 The Apache Software Foundation * * Licensed 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.ByteArrayInputStream; import java.io.IOException; import java.net.InetAddress; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.PrivilegedExceptionAction; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedAction; import javax.management.MBeanServer; import javax.management.ObjectName; import org.apache.commons.modeler.Registry; import org.apache.coyote.ActionCode; import org.apache.coyote.ActionHook; import org.apache.coyote.Adapter; import org.apache.coyote.ProtocolHandler; import org.apache.coyote.Request; import org.apache.coyote.Response; import org.apache.jk.common.HandlerRequest; import org.apache.jk.common.JkInputStream; import org.apache.jk.common.MsgAjp; 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.buf.ByteChunk; import org.apache.tomcat.util.buf.C2BConverter; import org.apache.tomcat.util.buf.MessageBytes; import org.apache.tomcat.util.http.HttpMessages; import org.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.net.SSLSupport; /** Plugs Jk2 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, ActionHook, org.apache.coyote.OutputBuffer, org.apache.coyote.InputBuffer { protected static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(JkCoyoteHandler.class); // Set debug on this logger to see the container request time private static org.apache.commons.logging.Log logTime= org.apache.commons.logging.LogFactory.getLog( "org.apache.jk.REQ_TIME" ); // ----------------------------------------------------------- DoPrivileged private final class StatusLinePrivilegedAction implements PrivilegedAction { int status; StatusLinePrivilegedAction(int status) { this.status = status; } public Object run() { return HttpMessages.getMessage(status); } } int headersMsgNote; int c2bConvertersNote; int tmpMessageBytesNote; int utfC2bNote; int obNote; int epNote; int inputStreamNote; private boolean paused = false; Adapter adapter; protected JkMain jkMain=null; public final int JK_STATUS_NEW=0; public final int JK_STATUS_HEAD=1; public final int JK_STATUS_CLOSED=2; /** 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) ; } /** 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(); headersMsgNote=wEnv.getNoteId( WorkerEnv.ENDPOINT_NOTE, "headerMsg" ); tmpMessageBytesNote=wEnv.getNoteId( WorkerEnv.ENDPOINT_NOTE, "tmpMessageBytes" ); utfC2bNote=wEnv.getNoteId( WorkerEnv.ENDPOINT_NOTE, "utfC2B" ); epNote=wEnv.getNoteId( WorkerEnv.ENDPOINT_NOTE, "ep" ); obNote=wEnv.getNoteId( WorkerEnv.ENDPOINT_NOTE, "coyoteBuffer" ); inputStreamNote= wEnv.getNoteId( WorkerEnv.ENDPOINT_NOTE, "jkInputStream"); } catch( Exception ex ) { ex.printStackTrace(); } } public void start() { try { if( oname != null && getJkMain().getDomain() == null) { try { Registry.getRegistry().registerComponent(getJkMain(), oname.getDomain(), "JkMain", "type=JkMain"); } catch (Exception e) { log.error( "Error registering jkmain " + e ); } } getJkMain().start(); } catch( Exception ex ) { ex.printStackTrace(); } } 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(); } // -------------------- OutputBuffer implementation -------------------- public int doWrite(ByteChunk chunk, Response res) throws IOException { if (!res.isCommitted()) { // Send the connector a request for commit. The connector should // then validate the headers, send them (using sendHeader) and // set the filters accordingly. res.sendHeaders(); } MsgContext ep=(MsgContext)res.getNote( epNote ); MsgAjp msg=(MsgAjp)ep.getNote( headersMsgNote ); int len=chunk.getLength(); byte buf[]=msg.getBuffer(); // 4 - hardcoded, byte[] marshalling overhead int chunkSize=buf.length - msg.getHeaderLength() - 4; int off=0; while( len > 0 ) { int thisTime=len; if( thisTime > chunkSize ) { thisTime=chunkSize; } len-=thisTime; msg.reset(); msg.appendByte( HandlerRequest.JK_AJP13_SEND_BODY_CHUNK); if( log.isDebugEnabled() ) log.debug("doWrite " + off + " " + thisTime + " " + len ); msg.appendBytes( chunk.getBytes(), chunk.getOffset() + off, thisTime ); off+=thisTime; ep.setType( JkHandler.HANDLE_SEND_PACKET ); ep.getSource().invoke( msg, ep ); } return 0; } public int doRead(ByteChunk chunk, Request req) throws IOException { Response res=req.getResponse(); if( log.isDebugEnabled() ) log.debug("doRead " + chunk.getBytes() + " " + chunk.getOffset() + " " + chunk.getLength()); MsgContext ep=(MsgContext)res.getNote( epNote ); JkInputStream jkIS=(JkInputStream)ep.getNote( inputStreamNote ); // return jkIS.read( chunk.getBytes(), chunk.getOffset(), chunk.getLength()); return jkIS.doRead( chunk ); } // -------------------- Jk handler implementation -------------------- // Jk Handler mehod public int invoke( Msg msg, MsgContext ep ) throws IOException { if( logTime.isDebugEnabled() ) ep.setLong( MsgContext.TIMER_PRE_REQUEST, System.currentTimeMillis()); org.apache.coyote.Request req=(org.apache.coyote.Request)ep.getRequest(); org.apache.coyote.Response res=req.getResponse(); res.setHook( this ); if( log.isDebugEnabled() ) log.debug( "Invoke " + req + " " + res + " " + req.requestURI().toString()); res.setOutputBuffer( this ); req.setInputBuffer( this ); if( ep.getNote( headersMsgNote ) == null ) { Msg msg2=new MsgAjp(); ep.setNote( headersMsgNote, msg2 ); } res.setNote( epNote, ep ); ep.setStatus( JK_STATUS_HEAD ); try { adapter.service( req, res ); } catch( Exception ex ) { ex.printStackTrace(); } if(ep.getStatus() != JK_STATUS_CLOSED) { res.finish(); } ep.setStatus( JK_STATUS_NEW ); req.recycle(); req.updateCounters(); res.recycle(); return OK; } private void appendHead(org.apache.coyote.Response res) throws IOException { if( log.isDebugEnabled() ) log.debug("COMMIT sending headers " + res + " " + res.getMimeHeaders() ); C2BConverter c2b=(C2BConverter)res.getNote( utfC2bNote ); if( c2b==null ) { if(System.getSecurityManager() != null) { try { c2b = (C2BConverter) AccessController.doPrivileged( new PrivilegedExceptionAction () { public Object run() throws IOException{ return new C2BConverter( "UTF8" ); } }); } catch(PrivilegedActionException pae) { Exception ex = pae.getException(); if(ex instanceof IOException) throw (IOException)ex; } } else { c2b=new C2BConverter( "UTF8" ); } res.setNote( utfC2bNote, c2b ); } MsgContext ep=(MsgContext)res.getNote( epNote ); MsgAjp msg=(MsgAjp)ep.getNote( headersMsgNote ); msg.reset(); msg.appendByte(HandlerRequest.JK_AJP13_SEND_HEADERS); msg.appendInt( res.getStatus() ); MessageBytes mb=(MessageBytes)ep.getNote( tmpMessageBytesNote ); if( mb==null ) { mb=new MessageBytes(); ep.setNote( tmpMessageBytesNote, mb ); } String message=res.getMessage(); if( message==null ){ if( System.getSecurityManager() != null ) { message = (String)AccessController.doPrivileged( new StatusLinePrivilegedAction(res.getStatus())); } else { message= HttpMessages.getMessage(res.getStatus()); } } else { message = message.replace('\n', ' ').replace('\r', ' '); } mb.setString( message ); c2b.convert( mb ); msg.appendBytes(mb); // XXX add headers MimeHeaders headers=res.getMimeHeaders(); String contentType = res.getContentType(); if( contentType != null ) { headers.setValue("Content-Type").setString(contentType); } String contentLanguage = res.getContentLanguage(); if( contentLanguage != null ) { headers.setValue("Content-Language").setString(contentLanguage); } int contentLength = res.getContentLength(); if( contentLength >= 0 ) { headers.setValue("Content-Length").setInt(contentLength); } int numHeaders = headers.size(); msg.appendInt(numHeaders); for( int i=0; i |
... this post is sponsored by my books ... | |
![]() #1 New Release! |
![]() FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.