User: oberg
Date: 00/06/16 06:10:35
Added: src/main/org/jboss/web ThreadPool.java WebServer.java
WebService.java WebServiceMBean.java
Removed: src/main/org/jboss/web WebProvider.java
WebProviderMBean.java
Log:
Added configuration service
Changed interceptors to be messagebased
Added mini webserver
Changed server bootstrap process
Revision Changes Path
1.1 jboss/src/main/org/jboss/web/ThreadPool.java
Index: ThreadPool.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.web;
import java.util.Stack;
/**
* <description>
*
* @see <related>
* @author Rickard �berg ([EMAIL PROTECTED])
* @version $Revision: 1.1 $
*/
public class ThreadPool
{
// Constants -----------------------------------------------------
// Attributes ----------------------------------------------------
Stack pool = new Stack();
int maxSize = 10;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
public ThreadPool()
{
}
// Public --------------------------------------------------------
public synchronized void clear()
{
for (int i = 0; i < pool.size(); i++)
{
Worker w = (Worker)pool.get(i);
w.stop();
}
}
public void setMaximumSize(int size)
{
maxSize = size;
}
public synchronized void run(Runnable work)
{
if (pool.size() == 0)
{
new Worker().run(work);
} else
{
Worker w = (Worker)pool.pop();
w.run(work);
}
}
// Package protected ---------------------------------------------
synchronized void returnWorker(Worker w)
{
if (pool.size() < maxSize)
pool.push(w);
else
w.die();
}
// Inner classes -------------------------------------------------
class Worker
extends Thread
{
boolean running = true;
Runnable runner;
Worker()
{
start();
}
public synchronized void die()
{
running = false;
}
public synchronized void run(Runnable runner)
{
this.runner = runner;
notifyAll();
}
public void run()
{
while (running)
{
// Wait for work to become available
synchronized (this)
{
try
{
wait(5000);
} catch (InterruptedException e)
{
// Ignore
}
}
// If work is available then execute it
if (runner != null)
{
try
{
runner.run();
} catch (Exception e)
{
e.printStackTrace();
}
// Clear work
runner = null;
}
// Return to pool
returnWorker(this);
}
}
}
}
1.1 jboss/src/main/org/jboss/web/WebServer.java
Index: WebServer.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.web;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* A mini webserver that should be embedded in another application. It can server
any file that is available from
* classloaders that are registered with it, including class-files.
*
* Its primary purpose is to simplify dynamic class-loading in RMI. Create an
instance of it, register a classloader
* with your classes, start it, and you'll be able to let RMI-clients dynamically
download classes from it.
*
* It is configured by editing either the dynaserver.default file in
dynaserver.jar (not recommended),
* or by adding a file dynaserver.properties in the same location as the
dynaserver.jar file (recommended).
* It can also be configured by calling any methods programmatically prior to
startup.
*
* @author $Author: oberg $
* @version $Revision: 1.1 $
*/
public class WebServer
implements Runnable
{
// Constants -----------------------------------------------------
// Attributes ----------------------------------------------------
private int port = 8080;
private ArrayList classLoaders = new ArrayList();
private ServerSocket server = null;
private boolean debug = false; // The server shows some debugging info if this is
true
private static Properties mimeTypes = new Properties(); // The MIME type mapping
private ThreadPool threadPool = new ThreadPool();
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
// Public --------------------------------------------------------
public void setPort(int p)
{
port = p;
}
public int getPort()
{
return port;
}
public void setDebug(boolean d)
{
debug = d;
}
public boolean isDebug()
{
return debug;
}
public void addMimeType(String extension, String type)
{
mimeTypes.put(extension,type);
}
public void start()
throws IOException
{
try
{
server = null;
server = new ServerSocket(getPort());
debug("Started on port " + getPort());
listen();
} catch (IOException e)
{
debug("Could not start on port " + getPort());
throw e;
}
}
public void stop()
{
try
{
ServerSocket srv = server;
server = null;
srv.close();
} catch (Exception e) {}
}
public void addClassLoader(ClassLoader cl)
{
classLoaders.add(cl);
}
public void removeClassLoader(ClassLoader cl)
{
classLoaders.remove(cl);
}
// Runnable implementation ---------------------------------------
public void run()
{
Socket socket = null;
// Accept a connection
try
{
socket = server.accept();
} catch (IOException e)
{
if (server == null) return; // Stopped by normal means
debug("DynaServer stopped: " + e.getMessage());
e.printStackTrace();
debug("Restarting DynaServer");
try
{
start();
return;
} catch (IOException ex)
{
debug("Restart failed");
return;
}
}
// Create a new thread to accept the next connection
listen();
try
{
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
try
{
// Get path to class file from header
BufferedReader in = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String path = getPath(in);
byte[] bytes;
if (path.endsWith(".class")) // Class
{
String className = path.substring(0, path.length()-6).replace('/','.');
// Try getting class
URL clazzUrl = null;
for (int i = 0; i < classLoaders.size(); i++)
{
try
{
Class clazz =
((ClassLoader)classLoaders.get(i)).loadClass(className);
clazzUrl =
clazz.getProtectionDomain().getCodeSource().getLocation();
if (clazzUrl.getFile().endsWith(".jar"))
clazzUrl = new URL("jar:"+clazzUrl+"!/"+path);
else
clazzUrl = new URL(clazzUrl, path);
break;
} catch (Exception e)
{
e.printStackTrace();
}
}
if (clazzUrl == null)
throw new Exception("Class not found:"+className);
// Retrieve bytecodes
bytes = getBytes(clazzUrl);
} else // Resource
{
// Try getting resource
URL resourceUrl = null;
for (int i = 0; i < classLoaders.size(); i++)
{
try
{
resourceUrl =
((ClassLoader)classLoaders.get(i)).getResource(path);
if (resourceUrl != null)
break;
} catch (Exception e)
{
e.printStackTrace();
}
}
if (resourceUrl == null)
throw new Exception("File not found:"+path);
// Retrieve bytes
bytes = getBytes(resourceUrl);
}
// Send bytecodes in response (assumes HTTP/1.0 or later)
try
{
out.writeBytes("HTTP/1.0 200 OK\r\n");
out.writeBytes("Content-Length: " + bytes.length +
"\r\n");
out.writeBytes("Content-Type: "+getMimeType(path)+"\r\n\r\n");
out.write(bytes);
out.flush();
} catch (IOException ie)
{
return;
}
} catch (Exception e)
{
try
{
// Write out error response
out.writeBytes("HTTP/1.0 400 " + e.getMessage() + "\r\n");
out.writeBytes("Content-Type: text/html\r\n\r\n");
out.flush();
} catch (IOException ex)
{
// Ignore
}
}
} catch (IOException ex)
{
// eat exception (could log error to log file, but
// write out to stdout for now).
debug("error writing response: " + ex.getMessage());
ex.printStackTrace();
} finally
{
try
{
socket.close();
} catch (IOException e)
{
}
}
}
// Y overrides ---------------------------------------------------
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
protected void debug(String msg)
{
if (isDebug())
System.out.println(msg);
}
protected void listen()
{
threadPool.run(this);
}
/**
* Returns the path to the class file obtained from
* parsing the HTML header.
*/
protected String getPath(BufferedReader in)
throws IOException
{
String line = in.readLine();
int idx = line.indexOf(" ")+1;
return line.substring(idx+1,line.indexOf(" ",idx)); // The file minus the
leading /
}
protected byte[] getBytes(URL url)
throws Exception
{
InputStream in = new BufferedInputStream(url.openStream());
debug("Retrieving "+url.toString());
ByteArrayOutputStream out = new ByteArrayOutputStream();
int data;
while ((data = in.read()) != -1)
{
out.write(data);
}
return out.toByteArray();
}
protected String getMimeType(String path)
{
String type = mimeTypes.getProperty(path.substring(path.lastIndexOf(".")));
if (type == null)
return "text/html";
else
return type;
}
// Private -------------------------------------------------------
// Inner classes -------------------------------------------------
}
1.1 jboss/src/main/org/jboss/web/WebService.java
Index: WebService.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.web;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.InetAddress;
import java.util.Properties;
import java.util.Enumeration;
import javax.management.*;
import org.jboss.logging.Log;
import org.jboss.util.ServiceMBeanSupport;
/**
* <description>
*
* @see <related>
* @author Rickard �berg ([EMAIL PROTECTED])
* @version $Revision: 1.1 $
*/
public class WebService
extends ServiceMBeanSupport
implements WebServiceMBean
{
// Constants -----------------------------------------------------
// Attributes ----------------------------------------------------
WebServer server;
Log log = new Log(getName());
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
public WebService()
{
this.server = new WebServer();
// Load the file mime.types into the mapping list
Properties mimeTypes = new Properties();
try
{
mimeTypes.load(getClass().getResourceAsStream("mime.types"));
Enumeration keys = mimeTypes.keys();
while (keys.hasMoreElements())
{
String extension = (String)keys.nextElement();
String type = mimeTypes.getProperty(extension);
server.addMimeType(extension, type);
}
} catch (IOException e)
{
e.printStackTrace(System.err);
}
}
// Public --------------------------------------------------------
public ObjectName getObjectName(MBeanServer server, ObjectName name)
throws javax.management.MalformedObjectNameException
{
return new ObjectName(OBJECT_NAME);
}
public String getName()
{
return "Webserver";
}
public void startService()
throws Exception
{
server.start();
// Set codebase
String host = System.getProperty("java.rmi.server.hostname");
if (host ==null) host = InetAddress.getLocalHost().getHostName();
String codebase = "http://"+host+":"+getPort()+"/";
System.setProperty("java.rmi.server.codebase", codebase);
log.log("Codebase set to "+codebase);
log.log("Started webserver on port "+server.getPort());
}
public void stopService()
{
server.stop();
}
public void addClassLoader(ClassLoader cl)
{
server.addClassLoader(cl);
}
public void removeClassLoader(ClassLoader cl)
{
server.removeClassLoader(cl);
}
public void setPort(int port)
{
server.setPort(port);
}
public int getPort()
{
return server.getPort();
}
// Protected -----------------------------------------------------
}
1.1 jboss/src/main/org/jboss/web/WebServiceMBean.java
Index: WebServiceMBean.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.web;
/**
* <description>
*
* @see <related>
* @author Rickard �berg ([EMAIL PROTECTED])
* @version $Revision: 1.1 $
*/
public interface WebServiceMBean
extends org.jboss.util.ServiceMBean
{
// Constants -----------------------------------------------------
public static final String OBJECT_NAME = ":service=Webserver";
// Public --------------------------------------------------------
public void addClassLoader(ClassLoader cl);
public void removeClassLoader(ClassLoader cl);
public void setPort(int port);
public int getPort();
}