org.apache.jk.apr.AprImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.jk.apr.AprImpl.java

Source

/*
 * ====================================================================
 *
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * [Additional notices, if required by prior licensing conditions]
 *
 */

package org.apache.jk.apr;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Hashtable;
import org.apache.jk.core.JkHandler;
import org.apache.jk.core.MsgContext;

/** Implements the interface with the APR library. This is for internal-use
 *  only. The goal is to use 'natural' mappings for user code - for example
 *  java.net.Socket for unix-domain sockets, etc. 
 * 
 */
public class AprImpl extends JkHandler { // This will be o.a.t.util.handler.TcHandler - lifecycle and config
    static AprImpl aprSingleton = null;

    String baseDir;
    String aprHome;
    String soExt = "so";

    static boolean ok = true;
    boolean initialized = false;
    // Handlers for native callbacks
    Hashtable jkHandlers = new Hashtable();

    // Name of the so used in inprocess mode 
    String jniModeSo = "inprocess";
    // name of the so used by java. If not set we'll loadLibrary("jkjni" ),
    // if set we load( nativeSo )
    String nativeSo;

    public AprImpl() {
        aprSingleton = this;
    }

    // -------------------- Properties --------------------

    /** Native libraries are located based on base dir.
     *  XXX Add platform, version, etc
     */
    public void setBaseDir(String s) {
        baseDir = s;
    }

    public void setSoExt(String s) {
        soExt = s;
    }

    // XXX maybe install the jni lib in apr-home ?
    public void setAprHome(String s) {
        aprHome = s;
    }

    /** Add a Handler for jni callbacks.
     */
    public void addJkHandler(String type, JkHandler cb) {
        jkHandlers.put(type, cb);
    }

    /** Name of the so used in inprocess mode
     */
    public void setJniModeSo(String jniModeSo) {
        this.jniModeSo = jniModeSo;
    }

    /** name of the so used by java. If not set we'll loadLibrary("jkjni" ),
    if set we load( nativeSo )
    */
    public void setNativeSo(String nativeSo) {
        this.nativeSo = nativeSo;
    }

    /** Sets the System.out stream */

    public static void setOut(String filename) {
        try {
            if (filename != null) {
                System.setOut(new PrintStream(new FileOutputStream(filename)));
            }
        } catch (Throwable th) {
        }
    }

    /** Sets the System.err stream */

    public static void setErr(String filename) {
        try {
            if (filename != null) {
                System.setErr(new PrintStream(new FileOutputStream(filename)));
            }
        } catch (Throwable th) {
        }
    }

    // -------------------- Apr generic utils --------------------
    /** Initialize APR
     */
    public native int initialize();

    public native int terminate();

    /* -------------------- Access to the jk_env_t -------------------- */

    /* The jk_env_t provide temporary storage ( pool ), logging, common services
     */

    /* Return a jk_env_t, used to keep the execution context ( temp pool, etc )
     */
    public native long getJkEnv();

    /** Clean the temp pool, put back the env in the pool
     */
    public native void releaseJkEnv(long xEnv);

    /* -------------------- Interface to the jk_bean object -------------------- */
    /* Each jk component is 'wrapped' as a bean, with a specified lifecycle
     *
     */

    /** Get a native component
     *  @return 0 if the component is not found.
     */
    public native long getJkHandler(long xEnv, String compName);

    public native long createJkHandler(long xEnv, String compName);

    public native int jkSetAttribute(long xEnv, long componentP, String name, String val);

    public native String jkGetAttribute(long xEnv, long componentP, String name);

    public native int jkInit(long xEnv, long componentP);

    public native int jkDestroy(long xEnv, long componentP);

    /** Send the packet to the C side. On return it contains the response
     *  or indication there is no response. Asymetrical because we can't
     *  do things like continuations.
     */
    public static native int jkInvoke(long xEnv, long componentP, long endpointP, int code, byte data[], int off,
            int len, int raw);

    /** Recycle an endpoint after use.
     */
    public native void jkRecycle(long xEnv, long endpointP);

    // -------------------- Called from C --------------------
    // XXX Check security, add guard or other protection
    // It's better to do it the other way - on init 'push' AprImpl into
    // the native library, and have native code call instance methods.

    public static Object createJavaContext(String type, long cContext) {
        // XXX will be an instance method, fields accessible directly
        AprImpl apr = aprSingleton;
        JkHandler jkH = (JkHandler) apr.jkHandlers.get(type);
        if (jkH == null)
            return null;

        MsgContext ep = jkH.createMsgContext();

        ep.setSource(jkH);

        ep.setJniContext(cContext);
        return ep;
    }

    /** Return a buffer associated with the ctx.
     */
    public static byte[] getBuffer(Object ctx, int id) {
        return ((MsgContext) ctx).getBuffer(id);
    }

    public static int jniInvoke(long jContext, Object ctx) {
        try {
            MsgContext ep = (MsgContext) ctx;
            ep.setJniEnv(jContext);
            ep.setType(0);
            return ((MsgContext) ctx).execute();
        } catch (Throwable ex) {
            ex.printStackTrace();
            return -1;
        }
    }

    // -------------------- Initialization -------------------- 

    public void init() throws IOException {
        try {
            initialized = true;
            loadNative();

            initialize();
            jkSetAttribute(0, 0, "channel:jni", "starting");

            log.info("JK2: Initialized apr");

        } catch (Throwable t) {
            throw new IOException(t.toString());
        }
        ok = true;
    }

    public boolean isLoaded() {
        if (!initialized) {
            try {
                init();
            } catch (Throwable t) {
                log.info("Apr not loaded: " + t);
            }
        }
        return ok;
    }

    static boolean jniMode = false;

    public static void jniMode() {
        jniMode = true;
    }

    /** This method of loading the libs doesn't require setting
     *   LD_LIBRARY_PATH. Assuming a 'right' binary distribution,
     *   or a correct build all files will be in their right place.
     *
     *  The burden is on our code to deal with platform specific
     *  extensions and to keep the paths consistent - not easy, but
     *  worth it if it avoids one extra step for the user.
     *
     *  Of course, this can change to System.load() and putting the
     *  libs in LD_LIBRARY_PATH.
     */
    public void loadNative() throws Throwable {
        if (aprHome == null)
            aprHome = baseDir;

        // XXX Update for windows
        if (jniMode) {
            /* In JNI mode we use mod_jk for the native functions.
               This seems the cleanest solution that works with multiple
               VMs.
            */
            if (jniModeSo.equals("inprocess")) {
                ok = true;
                return;
            }
            try {
                log.info("Loading " + jniModeSo);
                if (jniModeSo != null)
                    System.load(jniModeSo);
            } catch (Throwable ex) {
                // ignore
                //ex.printStackTrace();
                return;
            }
            ok = true;
            return;
        }

        /*
          jkjni _must_ be linked with apr and crypt -
          this seem the only ( decent ) way to support JDK1.4 and
          JDK1.3 at the same time
          try {
              System.loadLibrary( "crypt" );
          } catch( Throwable ex ) {
              // ignore
              ex.printStackTrace();
          }
          try {
              System.loadLibrary( "apr" );
          } catch( Throwable ex ) {
              System.out.println("can't load apr, that's fine");
              ex.printStackTrace();
          }
        */
        try {
            if (nativeSo == null) {
                // This will load libjkjni.so or jkjni.dll in LD_LIBRARY_PATH
                log.debug("Loading jkjni from " + System.getProperty("java.library.path"));
                System.loadLibrary("jkjni");
            } else {
                System.load(nativeSo);
            }
        } catch (Throwable ex) {
            ok = false;
            //ex.printStackTrace();
            throw ex;
        }
    }

    public void loadNative(String libPath) {
        try {
            System.load(libPath);
        } catch (Throwable ex) {
            ok = false;
            if (log.isDebugEnabled())
                log.debug("Error loading native library ", ex);
        }
    }

    private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(AprImpl.class);
}