Save This Page
Home » apache-tomcat-6.0.16-src » org.apache.jk » common » [javadoc | source]
    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.common;
   19   
   20   import java.io.IOException;
   21   
   22   import javax.management.ObjectName;
   23   
   24   import org.apache.jk.apr.AprImpl;
   25   import org.apache.jk.core.JkHandler;
   26   import org.apache.jk.core.Msg;
   27   import org.apache.jk.core.MsgContext;
   28   import org.apache.jk.core.JkChannel;
   29   import org.apache.tomcat.util.buf.ByteChunk;
   30   import org.apache.tomcat.util.buf.C2BConverter;
   31   import org.apache.tomcat.util.buf.MessageBytes;
   32   import org.apache.tomcat.util.modeler.Registry;
   33   
   34   
   35   /**
   36    * Base class for components using native code ( libjkjni.so ).
   37    * It allows to access the jk_env and wrap ( 'box' ? ) a native
   38    * jk component, and call it's methods.
   39    *
   40    * Note that get/setAttribute are expensive ( Strings, etc ),
   41    * invoke() is were all optimizations are done. We do recycle
   42    * all memory on both C and java sides ( the only exception is
   43    * when we attempt pinning but the VM doesn't support it ). The
   44    * low level optimizations from ByteBuffer, etc are used to
   45    * reduce the overhead of passing strings.
   46    *
   47    * @author Costin Manolache
   48    */
   49   public class JniHandler extends JkHandler {
   50       protected AprImpl apr;
   51   
   52       // The native side handler
   53       protected long nativeJkHandlerP;
   54   
   55       protected String jkHome;
   56   
   57       // Dispatch table codes. Hardcoded for now, will change when we have more handlers.
   58       public static final int JK_HANDLE_JNI_DISPATCH=0x15;
   59       public static final int JK_HANDLE_SHM_DISPATCH=0x16;
   60   
   61   
   62       public static final int MSG_NOTE=0;
   63       public static final int MB_NOTE=2;
   64       private boolean paused = false;
   65   
   66   
   67       public JniHandler() {
   68       }
   69   
   70       /**
   71        */
   72       public void setJkHome( String s ) {
   73           jkHome=s;
   74       }
   75   
   76       public String getJkHome() {
   77           return jkHome;
   78       }
   79   
   80       /** You must call initNative() inside the component init()
   81        */
   82       public void init() throws IOException {
   83           // static field init, temp
   84       }
   85   
   86       protected void initNative(String nativeComponentName) {
   87           apr=(AprImpl)wEnv.getHandler("apr");
   88           if( apr==null ) {
   89               // In most cases we can just load it automatically.
   90               // that requires all libs to be installed in standard places
   91               // ( LD_LIBRARY_PATH, /usr/lib
   92               try {
   93                   apr=new AprImpl();
   94                   wEnv.addHandler("apr", apr);
   95                   apr.init();
   96                   if( oname != null ) {
   97                       ObjectName aprname=new ObjectName(oname.getDomain() +
   98                               ":type=JkHandler, name=apr");
   99                       Registry.getRegistry(null, null).registerComponent(apr, aprname, null);
  100                   }
  101               } catch( Throwable t ) {
  102                   log.debug("Can't load apr", t);
  103                   apr=null;
  104               }
  105           }
  106           if( apr==null || ! apr.isLoaded() ) {
  107               if( log.isDebugEnabled() )
  108                   log.debug("No apr, disabling jni proxy ");
  109               apr=null;
  110               return;
  111           }
  112   
  113           try {
  114               long xEnv=apr.getJkEnv();
  115               nativeJkHandlerP=apr.getJkHandler(xEnv, nativeComponentName );
  116               
  117               if( nativeJkHandlerP==0 ) {
  118                   log.debug("Component not found, creating it " + nativeComponentName );
  119                   nativeJkHandlerP=apr.createJkHandler(xEnv, nativeComponentName);
  120               }
  121               log.debug("Native proxy " + nativeJkHandlerP );
  122               apr.releaseJkEnv(xEnv);
  123           } catch( Throwable t ) {
  124               apr=null;
  125               log.info("Error calling apr ", t);
  126           }
  127      }
  128   
  129       public void appendString( Msg msg, String s, C2BConverter charsetDecoder)
  130           throws IOException
  131       {
  132           ByteChunk bc=charsetDecoder.getByteChunk();
  133           charsetDecoder.recycle();
  134           charsetDecoder.convert( s );
  135           charsetDecoder.flushBuffer();
  136           msg.appendByteChunk( bc );
  137       }
  138   
  139       public void pause() throws Exception {
  140           synchronized(this) {
  141               paused = true;
  142           }
  143       }
  144   
  145       public void resume() throws Exception {
  146           synchronized(this) {
  147               paused = false;
  148               notifyAll();
  149           }
  150       }
  151   
  152   
  153       /** Create a msg context to be used with the shm channel
  154        */
  155       public MsgContext createMsgContext() {
  156           if( nativeJkHandlerP==0 || apr==null  )
  157               return null;
  158   
  159           synchronized(this) {
  160               try{ 
  161                   while(paused) {
  162                       wait();
  163                   }
  164               }catch(InterruptedException ie) {
  165                   // Ignore, since it can't happen
  166               }
  167           }
  168   
  169           try {
  170               MsgContext msgCtx=new MsgContext();
  171               MsgAjp msg=new MsgAjp();
  172   
  173               msgCtx.setSource( (JkChannel)this );
  174               msgCtx.setWorkerEnv( wEnv );
  175   
  176               msgCtx.setNext( this );
  177   
  178               msgCtx.setMsg( MSG_NOTE, msg); // XXX Use noteId
  179   
  180               C2BConverter c2b=new C2BConverter(  "iso-8859-1" );
  181               msgCtx.setConverter( c2b );
  182   
  183               MessageBytes tmpMB= MessageBytes.newInstance();
  184               msgCtx.setNote( MB_NOTE, tmpMB );
  185               return msgCtx;
  186           } catch( Exception ex ) {
  187               log.error("Can't create endpoint", ex);
  188               return null;
  189           }
  190       }
  191   
  192       public void setNativeAttribute(String name, String val) throws IOException {
  193           if( apr==null ) return;
  194   
  195           if( nativeJkHandlerP == 0 ) {
  196               log.error( "Unitialized component " + name+ " " + val );
  197               return;
  198           }
  199   
  200           long xEnv=apr.getJkEnv();
  201   
  202           apr.jkSetAttribute( xEnv, nativeJkHandlerP, name, val );
  203   
  204           apr.releaseJkEnv( xEnv );
  205       }
  206   
  207       public void initJkComponent() throws IOException {
  208           if( apr==null ) return;
  209   
  210           if( nativeJkHandlerP == 0 ) {
  211               log.error( "Unitialized component " );
  212               return;
  213           }
  214   
  215           long xEnv=apr.getJkEnv();
  216   
  217           apr.jkInit( xEnv, nativeJkHandlerP );
  218   
  219           apr.releaseJkEnv( xEnv );
  220       }
  221   
  222       public void destroyJkComponent() throws IOException {
  223           if( apr==null ) return;
  224   
  225           if( nativeJkHandlerP == 0 ) {
  226               log.error( "Unitialized component " );
  227               return;
  228           }
  229   
  230           long xEnv=apr.getJkEnv();
  231   
  232           apr.jkDestroy( xEnv, nativeJkHandlerP );
  233   
  234           apr.releaseJkEnv( xEnv );
  235       }
  236   
  237   
  238   
  239       protected void setNativeEndpoint(MsgContext msgCtx) {
  240           long xEnv=apr.getJkEnv();
  241           msgCtx.setJniEnv( xEnv );
  242   
  243           long epP=apr.createJkHandler(xEnv, "endpoint");
  244           log.debug("create ep " + epP );
  245           if( epP == 0 ) return;
  246           apr.jkInit( xEnv, epP );
  247           msgCtx.setJniContext( epP );
  248   
  249       }
  250   
  251       protected void recycleNative(MsgContext ep) {
  252           apr.jkRecycle(ep.getJniEnv(), ep.getJniContext());
  253       }
  254   
  255       /** send and get the response in the same buffer. This calls the
  256       * method on the wrapped jk_bean object.
  257        */
  258       protected int nativeDispatch( Msg msg, MsgContext ep, int code, int raw )
  259           throws IOException
  260       {
  261           if( log.isDebugEnabled() )
  262               log.debug( "Sending packet " + code + " " + raw);
  263   
  264           if( raw == 0 ) {
  265               msg.end();
  266   
  267               if( log.isTraceEnabled() ) msg.dump("OUT:" );
  268           }
  269   
  270           // Create ( or reuse ) the jk_endpoint ( the native pair of
  271           // MsgContext )
  272           long xEnv=ep.getJniEnv();
  273           long nativeContext=ep.getJniContext();
  274           if( nativeContext==0 || xEnv==0 ) {
  275               setNativeEndpoint( ep );
  276               xEnv=ep.getJniEnv();
  277               nativeContext=ep.getJniContext();
  278           }
  279   
  280           if( xEnv==0 || nativeContext==0 || nativeJkHandlerP==0 ) {
  281               log.error("invokeNative: Null pointer ");
  282               return -1;
  283           }
  284   
  285           // Will process the message in the current thread.
  286           // No wait needed to receive the response, if any
  287           int status=AprImpl.jkInvoke( xEnv,
  288                                    nativeJkHandlerP,
  289                                    nativeContext,
  290                                    code, msg.getBuffer(), 0, msg.getLen(), raw );
  291   
  292           if( status != 0 && status != 2 ) {
  293               log.error( "nativeDispatch: error " + status, new Throwable() );
  294           }
  295   
  296           if( log.isDebugEnabled() ) log.debug( "Sending packet - done " + status);
  297           return status;
  298       }
  299   
  300       /** Base implementation for invoke. Dispatch the action to the native
  301       * code, where invoke() is called on the wrapped jk_bean.
  302       */
  303       public  int invoke(Msg msg, MsgContext ep )
  304           throws IOException
  305       {
  306           long xEnv=ep.getJniEnv();
  307           int type=ep.getType();
  308   
  309           int status=nativeDispatch(msg, ep, type, 0 );
  310   
  311           apr.jkRecycle(xEnv, ep.getJniContext());
  312           apr.releaseJkEnv( xEnv );
  313           return status;
  314       }
  315   
  316       private static org.apache.juli.logging.Log log=
  317           org.apache.juli.logging.LogFactory.getLog( JniHandler.class );
  318   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache.jk » common » [javadoc | source]