KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jk > common > ChannelJni


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.jk.common;
18
19 import java.io.IOException JavaDoc;
20
21 import org.apache.jk.core.JkHandler;
22 import org.apache.jk.core.Msg;
23 import org.apache.jk.core.MsgContext;
24 import org.apache.jk.core.JkChannel;
25
26 import org.apache.coyote.Request;
27 /** Pass messages using jni
28  *
29  * @author Costin Manolache
30  */

31 public class ChannelJni extends JniHandler implements JkChannel {
32     int receivedNote=1;
33
34     public ChannelJni() {
35         // we use static for now, it's easier on the C side.
36
// Easy to change after we get everything working
37
}
38
39     public void init() throws IOException JavaDoc {
40         super.initNative("channel.jni:jni");
41
42         if( apr==null ) return;
43         
44         // We'll be called from C. This deals with that.
45
apr.addJkHandler( "channelJni", this );
46         log.info("JK: listening on channel.jni:jni" );
47         
48         if( next==null ) {
49             if( nextName!=null )
50                 setNext( wEnv.getHandler( nextName ) );
51             if( next==null )
52                 next=wEnv.getHandler( "dispatch" );
53             if( next==null )
54                 next=wEnv.getHandler( "request" );
55             if( log.isDebugEnabled() )
56                 log.debug("Setting default next " + next.getClass().getName());
57         }
58     }
59
60     /** Receives does nothing - send will put the response
61      * in the same buffer
62      */

63     public int receive( Msg msg, MsgContext ep )
64         throws IOException JavaDoc
65     {
66         Msg sentResponse=(Msg)ep.getNote( receivedNote );
67         ep.setNote( receivedNote, null );
68
69         if( sentResponse == null ) {
70             if( log.isDebugEnabled() )
71                 log.debug("No send() prior to receive(), no data buffer");
72             // No sent() was done prior to receive.
73
msg.reset();
74             msg.end();
75             sentResponse = msg;
76         }
77         
78         sentResponse.processHeader();
79
80         if( log.isTraceEnabled() )
81             sentResponse.dump("received response ");
82
83         if( msg != sentResponse ) {
84             log.error( "Error, in JNI mode the msg used for receive() must be identical with the one used for send()");
85         }
86         
87         return 0;
88     }
89
90     /** Send the packet. XXX This will modify msg !!!
91      * We could use 2 packets, or sendAndReceive().
92      *
93      */

94     public int send( Msg msg, MsgContext ep )
95         throws IOException JavaDoc
96     {
97         ep.setNote( receivedNote, null );
98         if( log.isDebugEnabled() ) log.debug("ChannelJni.send: " + msg );
99
100         int rc=super.nativeDispatch( msg, ep, JK_HANDLE_JNI_DISPATCH, 0);
101
102         // nativeDispatch will put the response in the same buffer.
103
// Next receive() will just get it from there. Very tricky to do
104
// things in one thread instead of 2.
105
ep.setNote( receivedNote, msg );
106         
107         return rc;
108     }
109
110     public int flush(Msg msg, MsgContext ep) throws IOException JavaDoc {
111         ep.setNote( receivedNote, null );
112         return OK;
113     }
114
115     public boolean isSameAddress(MsgContext ep) {
116         return true;
117     }
118
119     public void registerRequest(Request req, MsgContext ep, int count) {
120         // Not supported.
121
}
122
123     public String JavaDoc getChannelName() {
124         return getName();
125     }
126     /** Receive a packet from the C side. This is called from the C
127      * code using invocation, but only for the first packet - to avoid
128      * recursivity and thread problems.
129      *
130      * This may look strange, but seems the best solution for the
131      * problem ( the problem is that we don't have 'continuation' ).
132      *
133      * sendPacket will move the thread execution on the C side, and
134      * return when another packet is available. For packets that
135      * are one way it'll return after it is processed too ( having
136      * 2 threads is far more expensive ).
137      *
138      * Again, the goal is to be efficient and behave like all other
139      * Channels ( so the rest of the code can be shared ). Playing with
140      * java objects on C is extremely difficult to optimize and do
141      * right ( IMHO ), so we'll try to keep it simple - byte[] passing,
142      * the conversion done in java ( after we know the encoding and
143      * if anyone asks for it - same lazy behavior as in 3.3 ).
144      */

145     public int invoke(Msg msg, MsgContext ep ) throws IOException JavaDoc {
146         if( apr==null ) return -1;
147         
148         long xEnv=ep.getJniEnv();
149         long cEndpointP=ep.getJniContext();
150
151         int type=ep.getType();
152         if( log.isDebugEnabled() ) log.debug("ChannelJni.invoke: " + ep + " " + type);
153
154         switch( type ) {
155         case JkHandler.HANDLE_RECEIVE_PACKET:
156             return receive( msg, ep );
157         case JkHandler.HANDLE_SEND_PACKET:
158             return send( msg, ep );
159         case JkHandler.HANDLE_FLUSH:
160             return flush(msg, ep);
161         }
162
163         // Reset receivedNote. It'll be visible only after a SEND and before a receive.
164
ep.setNote( receivedNote, null );
165
166         // Default is FORWARD - called from C
167
try {
168             // first, we need to get an endpoint. It should be
169
// per/thread - and probably stored by the C side.
170
if( log.isDebugEnabled() ) log.debug("Received request " + xEnv);
171             
172             // The endpoint will store the message pt.
173
msg.processHeader();
174
175             if( log.isTraceEnabled() ) msg.dump("Incoming msg ");
176
177             int status= next.invoke( msg, ep );
178             
179             if( log.isDebugEnabled() ) log.debug("after processCallbacks " + status);
180             
181             return status;
182         } catch( Exception JavaDoc ex ) {
183             ex.printStackTrace();
184         }
185         return 0;
186     }
187
188     private static org.apache.commons.logging.Log log=
189         org.apache.commons.logging.LogFactory.getLog( ChannelJni.class );
190
191 }
192
Popular Tags