Java tutorial
/* * ==================================================================== * * 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.common; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import org.apache.jk.core.JkHandler; import org.apache.jk.core.Msg; import org.apache.jk.core.MsgContext; import org.apache.tomcat.util.threads.ThreadPool; import org.apache.tomcat.util.threads.ThreadPoolRunnable; /** Pass messages using unix domain sockets. * * @author Costin Manolache */ public class ChannelUn extends JniHandler { static final int CH_OPEN = 4; static final int CH_CLOSE = 5; static final int CH_READ = 6; static final int CH_WRITE = 7; String file; ThreadPool tp; /* ==================== Tcp socket options ==================== */ public ThreadPool getThreadPool() { return tp; } public void setFile(String f) { file = f; } public String getFile() { return file; } /* ==================== ==================== */ int socketNote = 1; int isNote = 2; int osNote = 3; int localId = 0; public void init() throws IOException { if (file == null) { log.debug("No file, disabling unix channel"); return; //throw new IOException( "No file for the unix socket channel"); } if (wEnv != null && wEnv.getLocalId() != 0) { localId = wEnv.getLocalId(); } if (localId != 0) { file = file + localId; } File socketFile = new File(file); if (!socketFile.isAbsolute()) { String home = wEnv.getJkHome(); if (home == null) { log.debug("No jkhome"); } else { File homef = new File(home); socketFile = new File(homef, file); log.debug("Making the file absolute " + socketFile); } } if (!socketFile.exists()) { try { FileOutputStream fos = new FileOutputStream(socketFile); fos.write(1); fos.close(); } catch (Throwable t) { log.error("Attempting to create the file failed, disabling channel" + socketFile); return; } } // The socket file cannot be removed ... if (!socketFile.delete()) { log.error("Can't remove socket file " + socketFile); return; } super.initNative("channel.un:" + file); if (apr == null || !apr.isLoaded()) { log.debug("Apr is not available, disabling unix channel "); apr = null; return; } // Set properties and call init. setNativeAttribute("file", file); // unixListenSocket=apr.unSocketListen( file, 10 ); setNativeAttribute("listen", "10"); // setNativeAttribute( "debug", "10" ); // Initialize the thread pool and execution chain if (next == null && wEnv != null) { if (nextName != null) setNext(wEnv.getHandler(nextName)); if (next == null) next = wEnv.getHandler("dispatch"); if (next == null) next = wEnv.getHandler("request"); } tp = new ThreadPool(); super.initJkComponent(); log.info("JK: listening on unix socket: " + file); // Run a thread that will accept connections. tp.start(); AprAcceptor acceptAjp = new AprAcceptor(this); tp.runIt(acceptAjp); } public void destroy() throws IOException { if (apr == null) return; try { if (tp != null) tp.shutdown(); //apr.unSocketClose( unixListenSocket,3); super.destroyJkComponent(); } catch (Exception e) { e.printStackTrace(); } } /** Open a connection - since we're listening that will block in accept */ public int open(MsgContext ep) throws IOException { // Will associate a jk_endpoint with ep and call open() on it. // jk_channel_un will accept a connection and set the socket info // in the endpoint. MsgContext will represent an active connection. return super.nativeDispatch(ep.getMsg(0), ep, CH_OPEN, 1); } public void close(MsgContext ep) throws IOException { super.nativeDispatch(ep.getMsg(0), ep, CH_CLOSE, 1); } public int send(Msg msg, MsgContext ep) throws IOException { return super.nativeDispatch(msg, ep, CH_WRITE, 0); } public int receive(Msg msg, MsgContext ep) throws IOException { int rc = super.nativeDispatch(msg, ep, CH_READ, 1); if (rc != 0) { log.error("receive error: " + rc, new Throwable()); return -1; } msg.processHeader(); if (log.isDebugEnabled()) log.debug("receive: total read = " + msg.getLen()); return msg.getLen(); } boolean running = true; /** Accept incoming connections, dispatch to the thread pool */ void acceptConnections() { if (apr == null) return; if (log.isDebugEnabled()) log.debug("Accepting ajp connections on " + file); while (running) { try { MsgContext ep = this.createMsgContext(); // blocking - opening a server connection. int status = this.open(ep); if (status != 0 && status != 2) { log.error("Error acceptin connection on " + file); break; } // if( log.isDebugEnabled() ) // log.debug("Accepted ajp connections "); AprConnection ajpConn = new AprConnection(this, ep); tp.runIt(ajpConn); } catch (Exception ex) { ex.printStackTrace(); } } } /** Process a single ajp connection. */ void processConnection(MsgContext ep) { if (log.isDebugEnabled()) log.debug("New ajp connection "); try { MsgAjp recv = new MsgAjp(); while (running) { int res = this.receive(recv, ep); if (res < 0) { // EOS break; } ep.setType(0); log.debug("Process msg "); int status = next.invoke(recv, ep); } if (log.isDebugEnabled()) log.debug("Closing un channel"); this.close(ep); } catch (Exception ex) { ex.printStackTrace(); } } public int invoke(Msg msg, MsgContext ep) throws IOException { int type = ep.getType(); switch (type) { case JkHandler.HANDLE_RECEIVE_PACKET: return receive(msg, ep); case JkHandler.HANDLE_SEND_PACKET: return send(msg, ep); case JkHandler.HANDLE_FLUSH: return OK; } // return next.invoke( msg, ep ); return OK; } private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory .getLog(ChannelUn.class); } class AprAcceptor implements ThreadPoolRunnable { ChannelUn wajp; AprAcceptor(ChannelUn wajp) { this.wajp = wajp; } public Object[] getInitData() { return null; } public void runIt(Object thD[]) { wajp.acceptConnections(); } } class AprConnection implements ThreadPoolRunnable { ChannelUn wajp; MsgContext ep; AprConnection(ChannelUn wajp, MsgContext ep) { this.wajp = wajp; this.ep = ep; } public Object[] getInitData() { return null; } public void runIt(Object perTh[]) { wajp.processConnection(ep); } }