org.apache.axis.transport.http.SimpleAxisServer Maven / Gradle / Ivy
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.axis.transport.http;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.components.threadpool.ThreadPool;
import org.apache.axis.server.AxisServer;
import org.apache.axis.session.Session;
import org.apache.axis.session.SimpleSession;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.Options;
import org.apache.axis.utils.NetworkUtils;
import org.apache.axis.collections.LRUMap;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.management.ServiceAdmin;
import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
import org.apache.commons.logging.Log;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.io.IOException;
import java.io.File;
/**
* This is a simple implementation of an HTTP server for processing
* SOAP requests via Apache's xml-axis. This is not intended for production
* use. Its intended uses are for demos, debugging, and performance
* profiling.
*
* Note this classes uses static objects to provide a thread pool, so you should
* not use multiple instances of this class in the same JVM/classloader unless
* you want bad things to happen at shutdown.
* @author Sam Ruby ([email protected])
* @author Rob Jellinghaus ([email protected])
* @author Alireza Taherkordi ([email protected])
*/
public class SimpleAxisServer implements Runnable {
protected static Log log =
LogFactory.getLog(SimpleAxisServer.class.getName());
// session state.
// This table maps session keys (random numbers) to SimpleAxisSession objects.
//
// There is a simple LRU based session cleanup mechanism, but if clients are not
// passing cookies, then a new session will be created for *every* request.
private Map sessions;
//Maximum capacity of the LRU Map used for session cleanup
private int maxSessions;
public static final int MAX_SESSIONS_DEFAULT = 100;
/**
* get the thread pool
* @return
*/
public static ThreadPool getPool() {
return pool;
}
/**
* pool of threads
*/
private static ThreadPool pool;
/** Are we doing threads?
* */
private static boolean doThreads = true;
/* Are we doing sessions?
Set this to false if you don't want any session overhead.
*/
private static boolean doSessions = true;
/**
* create a server with the default threads and sessions.
*/
public SimpleAxisServer() {
this(ThreadPool.DEFAULT_MAX_THREADS);
}
/**
* Create a server with a configurable pool side; sessions set to the default
* limit
* @param maxPoolSize maximum thread pool size
*/
public SimpleAxisServer(int maxPoolSize) {
this(maxPoolSize, MAX_SESSIONS_DEFAULT);
}
/**
* Constructor
* @param maxPoolSize max number of threads
* @param maxSessions maximum sessions
*/
public SimpleAxisServer(int maxPoolSize, int maxSessions) {
this.maxSessions = maxSessions;
sessions = new LRUMap(maxSessions);
pool = new ThreadPool(maxPoolSize);
}
/**
* stop the server if not already told to.
* @throws Throwable
*/
protected void finalize() throws Throwable {
stop();
super.finalize();
}
/**
* get max session count
* @return
*/
public int getMaxSessions() {
return maxSessions;
}
/**
* Resize the session map
* @param maxSessions maximum sessions
*/
public void setMaxSessions(int maxSessions) {
this.maxSessions = maxSessions;
((LRUMap)sessions).setMaximumSize(maxSessions);
}
//---------------------------------------------------
protected boolean isSessionUsed() {
return doSessions;
}
/**
* turn threading on or off. This sets a static value
* @param value
*/
public void setDoThreads(boolean value) {
doThreads = value ;
}
public boolean getDoThreads() {
return doThreads ;
}
public EngineConfiguration getMyConfig() {
return myConfig;
}
public void setMyConfig(EngineConfiguration myConfig) {
this.myConfig = myConfig;
}
/**
* demand create a session if there is not already one for the string
* @param cooky
* @return a session.
*/
protected Session createSession(String cooky) {
// is there a session already?
Session session = null;
if (sessions.containsKey(cooky)) {
session = (Session) sessions.get(cooky);
} else {
// no session for this cooky, bummer
session = new SimpleSession();
// ADD CLEANUP LOGIC HERE if needed
sessions.put(cooky, session);
}
return session;
}
// What is our current session index?
// This is a monotonically increasing, non-thread-safe integer
// (thread safety not considered crucial here)
public static int sessionIndex = 0;
// Axis server (shared between instances)
private static AxisServer myAxisServer = null;
private EngineConfiguration myConfig = null;
/**
* demand create an axis server; return an existing one if one exists.
* The configuration for the axis server is derived from #myConfig if not null,
* the default config otherwise.
* @return
*/
public synchronized AxisServer getAxisServer() {
if (myAxisServer == null) {
if (myConfig == null) {
myConfig = EngineConfigurationFactoryFinder.newFactory().getServerEngineConfig();
}
myAxisServer = new AxisServer(myConfig);
ServiceAdmin.setEngine(myAxisServer, NetworkUtils.getLocalHostname() + "@" + serverSocket.getLocalPort());
}
return myAxisServer;
}
/**
are we stopped?
latch to true if stop() is called
*/
private boolean stopped = false;
/**
* Accept requests from a given TCP port and send them through the
* Axis engine for processing.
*/
public void run() {
log.info(Messages.getMessage("start01", "SimpleAxisServer",
new Integer(getServerSocket().getLocalPort()).toString(),getCurrentDirectory()));
// Accept and process requests from the socket
while (!stopped) {
Socket socket = null;
try {
socket = serverSocket.accept();
} catch (java.io.InterruptedIOException iie) {
} catch (Exception e) {
log.debug(Messages.getMessage("exception00"), e);
break;
}
if (socket != null) {
SimpleAxisWorker worker = new SimpleAxisWorker(this, socket);
if (doThreads) {
pool.addWorker(worker);
} else {
worker.run();
}
}
}
log.info(Messages.getMessage("quit00", "SimpleAxisServer"));
}
/**
* Gets the current directory
* @return current directory
*/
private String getCurrentDirectory() {
return System.getProperty("user.dir");
}
/**
* per thread socket information
*/
private ServerSocket serverSocket;
/**
* Obtain the serverSocket that that SimpleAxisServer is listening on.
*/
public ServerSocket getServerSocket() {
return serverSocket;
}
/**
* Set the serverSocket this server should listen on.
* (note : changing this will not affect a running server, but if you
* stop() and then start() the server, the new socket will be used).
*/
public void setServerSocket(ServerSocket serverSocket) {
this.serverSocket = serverSocket;
}
/**
* Start this server.
*
* Spawns a worker thread to listen for HTTP requests.
*
* @param daemon a boolean indicating if the thread should be a daemon.
*/
public void start(boolean daemon) throws Exception {
stopped=false;
if (doThreads) {
Thread thread = new Thread(this);
thread.setDaemon(daemon);
thread.start();
} else {
run();
}
}
/**
* Start this server as a NON-daemon.
*/
public void start() throws Exception {
start(false);
}
/**
* Stop this server. Can be called safely if the system is already stopped,
* or if it was never started.
*
* This will interrupt any pending accept().
*/
public void stop() {
//recognise use before we are live
if(stopped ) {
return;
}
/*
* Close the server socket cleanly, but avoid fresh accepts while
* the socket is closing.
*/
stopped = true;
try {
if(serverSocket != null) {
serverSocket.close();
}
} catch (IOException e) {
log.info(Messages.getMessage("exception00"), e);
} finally {
serverSocket=null;
}
log.info(Messages.getMessage("quit00", "SimpleAxisServer"));
//shut down the pool
pool.shutdown();
}
/**
* Server process.
*/
public static void main(String args[]) {
Options opts = null;
try {
opts = new Options(args);
} catch (MalformedURLException e) {
log.error(Messages.getMessage("malformedURLException00"), e);
return;
}
String maxPoolSize = opts.isValueSet('t');
if (maxPoolSize==null) maxPoolSize = ThreadPool.DEFAULT_MAX_THREADS + "";
String maxSessions = opts.isValueSet('m');
if (maxSessions==null) maxSessions = MAX_SESSIONS_DEFAULT + "";
SimpleAxisServer sas = new SimpleAxisServer(Integer.parseInt(maxPoolSize),
Integer.parseInt(maxSessions));
try {
doThreads = (opts.isFlagSet('t') > 0);
int port = opts.getPort();
ServerSocket ss = null;
// Try five times
final int retries = 5;
for (int i = 0; i < retries; i++) {
try {
ss = new ServerSocket(port);
break;
} catch (java.net.BindException be){
log.debug(Messages.getMessage("exception00"), be);
if (i < (retries-1)) {
// At 3 second intervals.
Thread.sleep(3000);
} else {
throw new Exception(Messages.getMessage("unableToStartServer00",
Integer.toString(port)));
}
}
}
sas.setServerSocket(ss);
sas.start();
} catch (Exception e) {
log.error(Messages.getMessage("exception00"), e);
return;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy