?? dynaserver.java
字號:
/*
* Copyright 2000 by dreamBean Software,
* All rights reserved.
*/
package com.dreambean.dynaserver;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* A mini webserver that can be embedded in another application as a JavaBean. It can serve 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.
*
* Note: the use of the synchronized is mainly due to the thread synch. issues with the JVM spec
*
* @author $Author: Rickard 謆erg (rickard@dreambean.com)$
* @version $Revision: 1.0$
*/
public final class DynaServer
{
// Constants -----------------------------------------------------
/**
* List of ports to try during portscan
* Try anonymous (0) if all else fails
*/
public final String PORTS = "8080,8081,8082,80,81,82,0";
/**
* Time out for server socket.
*/
public final int SO_TIMEOUT = 10000; // ServerSocket timeout to allow it to check "running" flag
// Attributes ----------------------------------------------------
private ArrayList classLoaders = new ArrayList();
private List requests = new ArrayList();
private int port = 8080;
private int backLog = 50; // Nr of requests to queue in ServerSocket. 50 is JDK default, so use that
private boolean portScan = true; // If port is taken, try to scan for free ones
private boolean debug = false; // The server shows some debugging info if this is true
private int nrOfHandlers = 5; // Nr of request handlers
private Properties mimeTypes = new Properties(); // The MIME type mapping
private boolean running;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
public DynaServer()
{
initMimetypes();
}
// Public --------------------------------------------------------
public synchronized void setPort(int p) { port = p; }
public synchronized int getPort() { return port; }
public synchronized void setPortScan(boolean portScan) { this.portScan = portScan; }
public synchronized boolean getPortScan() { return portScan; }
public synchronized void setBackLog(int b) { backLog = b; }
public synchronized int getBackLog() { return backLog; }
public synchronized void setDebug(boolean d) { debug = d; }
public synchronized boolean isDebug() { return debug; }
public synchronized void setNrOfHandlers(int nrOfHandlers) { this.nrOfHandlers = nrOfHandlers; }
public synchronized int getNrOfHandlers() { return nrOfHandlers; }
public synchronized boolean isRunning() { return running; }
public synchronized void start()
throws IOException
{
if (isRunning())
return;
try
{
running = true;
// Start socket listener
new RequestListener();
// Start request handlers
for (int i = 0; i < nrOfHandlers; i++)
{
new RequestHandler();
}
initCodebase();
debug("Started on port " + getPort());
} catch (IOException e)
{
debug("Could not start on port " + getPort());
throw e;
}
}
public synchronized void stop()
{
// Close already accepted requests
Iterator enum = requests.iterator();
while (enum.hasNext())
{
try
{
Socket request = (Socket)enum.next();
request.close();
} catch (IOException e)
{
// Ignore
}
}
// Change state to not running and notify handlers
running = false;
notifyAll();
try
{
wait(SO_TIMEOUT); // Wait for listener to finish
} catch (InterruptedException e)
{
// Ignore
}
}
public synchronized void addClassLoader(ClassLoader cl)
{
ArrayList arr = (ArrayList)classLoaders.clone();
arr.add(cl);
classLoaders = arr;
}
public synchronized void removeClassLoader(ClassLoader cl)
{
ArrayList arr = (ArrayList)classLoaders.clone();
arr.remove(cl);
classLoaders = arr;
}
public synchronized Collection getClassLoaders()
{
return classLoaders;
}
// Package protected ---------------------------------------------
synchronized void debug(String msg)
{
if (isDebug())
System.out.println(msg);
}
// Protected -----------------------------------------------------
/**
* Returns the path to the class file obtained from
* parsing the HTML header.
*/
protected String getMimeType(String path)
{
String ext = path.substring(path.lastIndexOf(".")+1);
String type = mimeTypes.getProperty(ext);
if (type == null)
{
debug("No MIME-type registered for:"+ext);
return "text/plain";
}
else
return type;
}
protected synchronized void addRequest(Socket request)
{
requests.add(request);
notifyAll();
}
protected synchronized Socket getRequest()
throws IllegalStateException
{
while (requests.isEmpty() && isRunning())
{
try
{
wait();
} catch (InterruptedException e)
{
// Ignore
}
}
if (isRunning())
return (Socket)requests.remove(0);
else
throw new IllegalStateException();
}
// Private -------------------------------------------------------
private void initCodebase()
{
// Compute codebase
String host = System.getProperty("java.rmi.server.hostname");
if (host ==null)
{
try
{
host = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e)
{
// Notify about problem, but ignore
debug("Could not get hostname");
}
}
String codebase = "http://"+host+":"+getPort()+"/";
// Try setting codebase if not set,
// or if different from computed codebase (port may have changed because of port scanning!)
String currentCodebase = System.getProperty("java.rmi.server.codebase");
if (currentCodebase == null || !currentCodebase.equals(codebase))
{
System.setProperty("java.rmi.server.codebase", codebase);
debug("Codebase set to "+codebase);
}
}
private void initMimetypes()
{
// Load the file mime.types into the mapping list
try
{
InputStream in = getClass().getResourceAsStream("/mime.types");
if (in != null)
mimeTypes.load(in);
else
System.err.println("No mime-type mappings found!");
} catch (IOException e)
{
e.printStackTrace(System.err);
}
}
// Inner classes -------------------------------------------------
class RequestListener
implements Runnable
{
ServerSocket serverSocket;
RequestListener()
throws IOException
{
try
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -