KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > transport > http > SimpleAxisServer


1 /*
2  * Copyright 2001-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.axis.transport.http;
18
19 import org.apache.axis.components.logger.LogFactory;
20 import org.apache.axis.components.threadpool.ThreadPool;
21 import org.apache.axis.server.AxisServer;
22 import org.apache.axis.session.Session;
23 import org.apache.axis.session.SimpleSession;
24 import org.apache.axis.utils.Messages;
25 import org.apache.axis.utils.Options;
26 import org.apache.axis.utils.NetworkUtils;
27 import org.apache.axis.collections.LRUMap;
28 import org.apache.axis.EngineConfiguration;
29 import org.apache.axis.management.ServiceAdmin;
30 import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
31 import org.apache.commons.logging.Log;
32
33 import java.net.MalformedURLException JavaDoc;
34 import java.net.ServerSocket JavaDoc;
35 import java.net.Socket JavaDoc;
36 import java.util.Map JavaDoc;
37 import java.io.IOException JavaDoc;
38 import java.io.File JavaDoc;
39
40 /**
41  * This is a simple implementation of an HTTP server for processing
42  * SOAP requests via Apache's xml-axis. This is not intended for production
43  * use. Its intended uses are for demos, debugging, and performance
44  * profiling.
45  *
46  * Note this classes uses static objects to provide a thread pool, so you should
47  * not use multiple instances of this class in the same JVM/classloader unless
48  * you want bad things to happen at shutdown.
49  * @author Sam Ruby (ruby@us.ibm.com)
50  * @author Rob Jellinghaus (robj@unrealities.com)
51  * @author Alireza Taherkordi (a_taherkordi@users.sourceforge.net)
52  */

53 public class SimpleAxisServer implements Runnable JavaDoc {
54     protected static Log log =
55             LogFactory.getLog(SimpleAxisServer.class.getName());
56
57     // session state.
58
// This table maps session keys (random numbers) to SimpleAxisSession objects.
59
//
60
// There is a simple LRU based session cleanup mechanism, but if clients are not
61
// passing cookies, then a new session will be created for *every* request.
62
private Map sessions;
63     //Maximum capacity of the LRU Map used for session cleanup
64
private int maxSessions;
65     public static final int MAX_SESSIONS_DEFAULT = 100;
66
67     /**
68      * get the thread pool
69      * @return
70      */

71     public static ThreadPool getPool() {
72         return pool;
73     }
74
75     /**
76      * pool of threads
77      */

78     private static ThreadPool pool;
79
80     /** Are we doing threads?
81      * */

82     private static boolean doThreads = true;
83
84     /* Are we doing sessions?
85      Set this to false if you don't want any session overhead.
86      */

87     private static boolean doSessions = true;
88
89     /**
90      * create a server with the default threads and sessions.
91      */

92     public SimpleAxisServer() {
93         this(ThreadPool.DEFAULT_MAX_THREADS);
94     }
95
96     /**
97      * Create a server with a configurable pool side; sessions set to the default
98      * limit
99      * @param maxPoolSize maximum thread pool size
100      */

101     public SimpleAxisServer(int maxPoolSize) {
102         this(maxPoolSize, MAX_SESSIONS_DEFAULT);
103     }
104     
105     /**
106      * Constructor
107      * @param maxPoolSize max number of threads
108      * @param maxSessions maximum sessions
109      */

110     public SimpleAxisServer(int maxPoolSize, int maxSessions) {
111         this.maxSessions = maxSessions;
112         sessions = new LRUMap(maxSessions);
113         pool = new ThreadPool(maxPoolSize);
114     }
115
116
117     /**
118      * stop the server if not already told to.
119      * @throws Throwable
120      */

121     protected void finalize() throws Throwable JavaDoc {
122         stop();
123         super.finalize();
124     }
125
126     /**
127      * get max session count
128      * @return
129      */

130     public int getMaxSessions() {
131         return maxSessions;
132     }
133
134     /**
135      * Resize the session map
136      * @param maxSessions maximum sessions
137      */

138     public void setMaxSessions(int maxSessions) {
139         this.maxSessions = maxSessions;
140         ((LRUMap)sessions).setMaximumSize(maxSessions);
141     }
142      //---------------------------------------------------
143

144     protected boolean isSessionUsed() {
145         return doSessions;
146     }
147
148     /**
149      * turn threading on or off. This sets a static value
150      * @param value
151      */

152     public void setDoThreads(boolean value) {
153         doThreads = value ;
154     }
155
156     public boolean getDoThreads() {
157         return doThreads ;
158     }
159
160     public EngineConfiguration getMyConfig() {
161         return myConfig;
162     }
163
164     public void setMyConfig(EngineConfiguration myConfig) {
165         this.myConfig = myConfig;
166     }
167
168     /**
169      * demand create a session if there is not already one for the string
170      * @param cooky
171      * @return a session.
172      */

173     protected Session createSession(String JavaDoc cooky) {
174
175         // is there a session already?
176
Session session = null;
177         if (sessions.containsKey(cooky)) {
178             session = (Session) sessions.get(cooky);
179         } else {
180             // no session for this cooky, bummer
181
session = new SimpleSession();
182
183             // ADD CLEANUP LOGIC HERE if needed
184
sessions.put(cooky, session);
185         }
186         return session;
187     }
188
189     // What is our current session index?
190
// This is a monotonically increasing, non-thread-safe integer
191
// (thread safety not considered crucial here)
192
public static int sessionIndex = 0;
193
194     // Axis server (shared between instances)
195
private static AxisServer myAxisServer = null;
196
197     private EngineConfiguration myConfig = null;
198
199     /**
200      * demand create an axis server; return an existing one if one exists.
201      * The configuration for the axis server is derived from #myConfig if not null,
202      * the default config otherwise.
203      * @return
204      */

205     public synchronized AxisServer getAxisServer() {
206         if (myAxisServer == null) {
207             if (myConfig == null) {
208                 myConfig = EngineConfigurationFactoryFinder.newFactory().getServerEngineConfig();
209             }
210             myAxisServer = new AxisServer(myConfig);
211             ServiceAdmin.setEngine(myAxisServer, NetworkUtils.getLocalHostname() + "@" + serverSocket.getLocalPort());
212         }
213         return myAxisServer;
214     }
215
216     /**
217     are we stopped?
218     latch to true if stop() is called
219      */

220     private boolean stopped = false;
221
222     /**
223      * Accept requests from a given TCP port and send them through the
224      * Axis engine for processing.
225      */

226     public void run() {
227         log.info(Messages.getMessage("start01", "SimpleAxisServer",
228                 new Integer JavaDoc(getServerSocket().getLocalPort()).toString(),getCurrentDirectory()));
229
230         // Accept and process requests from the socket
231
while (!stopped) {
232             Socket JavaDoc socket = null;
233             try {
234                 socket = serverSocket.accept();
235             } catch (java.io.InterruptedIOException JavaDoc iie) {
236             } catch (Exception JavaDoc e) {
237                 log.debug(Messages.getMessage("exception00"), e);
238                 break;
239             }
240             if (socket != null) {
241                 SimpleAxisWorker worker = new SimpleAxisWorker(this, socket);
242                 if (doThreads) {
243                     pool.addWorker(worker);
244                 } else {
245                     worker.run();
246                 }
247             }
248         }
249         log.info(Messages.getMessage("quit00", "SimpleAxisServer"));
250     }
251
252     /**
253      * Gets the current directory
254      * @return current directory
255      */

256     private String JavaDoc getCurrentDirectory() {
257         return System.getProperty("user.dir");
258     }
259
260     /**
261      * per thread socket information
262      */

263
264     private ServerSocket JavaDoc serverSocket;
265
266     /**
267      * Obtain the serverSocket that that SimpleAxisServer is listening on.
268      */

269     public ServerSocket JavaDoc getServerSocket() {
270         return serverSocket;
271     }
272
273     /**
274      * Set the serverSocket this server should listen on.
275      * (note : changing this will not affect a running server, but if you
276      * stop() and then start() the server, the new socket will be used).
277      */

278     public void setServerSocket(ServerSocket JavaDoc serverSocket) {
279         this.serverSocket = serverSocket;
280     }
281
282     /**
283      * Start this server.
284      *
285      * Spawns a worker thread to listen for HTTP requests.
286      *
287      * @param daemon a boolean indicating if the thread should be a daemon.
288      */

289     public void start(boolean daemon) throws Exception JavaDoc {
290         stopped=false;
291         if (doThreads) {
292             Thread JavaDoc thread = new Thread JavaDoc(this);
293             thread.setDaemon(daemon);
294             thread.start();
295         } else {
296             run();
297         }
298     }
299
300     /**
301      * Start this server as a NON-daemon.
302      */

303     public void start() throws Exception JavaDoc {
304         start(false);
305     }
306
307     /**
308      * Stop this server. Can be called safely if the system is already stopped,
309      * or if it was never started.
310      *
311      * This will interrupt any pending accept().
312      */

313     public void stop() {
314         //recognise use before we are live
315
if(stopped ) {
316             return;
317         }
318         /*
319          * Close the server socket cleanly, but avoid fresh accepts while
320          * the socket is closing.
321          */

322         stopped = true;
323
324         try {
325             if(serverSocket != null) {
326                 serverSocket.close();
327             }
328         } catch (IOException JavaDoc e) {
329             log.info(Messages.getMessage("exception00"), e);
330         } finally {
331             serverSocket=null;
332         }
333
334         log.info(Messages.getMessage("quit00", "SimpleAxisServer"));
335
336         //shut down the pool
337
pool.shutdown();
338     }
339
340     /**
341      * Server process.
342      */

343     public static void main(String JavaDoc args[]) {
344
345         Options opts = null;
346         try {
347             opts = new Options(args);
348         } catch (MalformedURLException JavaDoc e) {
349             log.error(Messages.getMessage("malformedURLException00"), e);
350             return;
351         }
352
353         String JavaDoc maxPoolSize = opts.isValueSet('t');
354         if (maxPoolSize==null) maxPoolSize = ThreadPool.DEFAULT_MAX_THREADS + "";
355
356         String JavaDoc maxSessions = opts.isValueSet('m');
357         if (maxSessions==null) maxSessions = MAX_SESSIONS_DEFAULT + "";
358
359         SimpleAxisServer sas = new SimpleAxisServer(Integer.parseInt(maxPoolSize),
360                                                         Integer.parseInt(maxSessions));
361
362         try {
363             doThreads = (opts.isFlagSet('t') > 0);
364
365             int port = opts.getPort();
366             ServerSocket JavaDoc ss = null;
367             // Try five times
368
final int retries = 5;
369             for (int i = 0; i < retries; i++) {
370                 try {
371                     ss = new ServerSocket JavaDoc(port);
372                     break;
373                 } catch (java.net.BindException JavaDoc be){
374                     log.debug(Messages.getMessage("exception00"), be);
375                     if (i < (retries-1)) {
376                         // At 3 second intervals.
377
Thread.sleep(3000);
378                     } else {
379                         throw new Exception JavaDoc(Messages.getMessage("unableToStartServer00",
380                                            Integer.toString(port)));
381                     }
382                 }
383             }
384             sas.setServerSocket(ss);
385             sas.start();
386         } catch (Exception JavaDoc e) {
387             log.error(Messages.getMessage("exception00"), e);
388             return;
389         }
390     }
391 }
392
Popular Tags