/*
* @(#)ClassServer.java 1.4 01/05/22
*
* Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* -Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any
* kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
* EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
* NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT
* OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
* ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
* SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
* THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or
* intended for use in the design, construction, operation or
* maintenance of any nuclear facility.
*/
import java.io.*;
import java.net.*;
import javax.net.*;
/*
* ClassServer.java -- a simple file server that can serve
* Http get request in both clear and secure channel
*/
/**
* Based on ClassServer.java in tutorial/rmi
*/
public abstract class ClassServer implements Runnable {
private ServerSocket server = null;
/**
* Constructs a ClassServer based on ss and
* obtains a file's bytecodes using the method getBytes.
*
*/
protected ClassServer(ServerSocket ss)
{
server = ss;
newListener();
}
/**
* Returns an array of bytes containing the bytes for
* the file represented by the argument path.
*
* @return the bytes for the file
* @exception FileNotFoundException if the file corresponding
* to path could not be loaded.
* @exception IOException if error occurs reading the class
*/
public abstract byte[] getBytes(String path)
throws IOException, FileNotFoundException;
/**
* The "listen" thread that accepts a connection to the
* server, parses the header to obtain the file name
* and sends back the bytes for the file (or error
* if the file is not found or the response was malformed).
*/
public void run()
{
Socket socket;
// accept a connection
try {
socket = server.accept();
} catch (IOException e) {
System.out.println("Class Server died: " + e.getMessage());
e.printStackTrace();
return;
}
// create a new thread to accept the next connection
newListener();
try {
OutputStream rawOut = socket.getOutputStream();
PrintWriter out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
rawOut)));
try {
// get path to class file from header
BufferedReader in =
new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String path = getPath(in);
// retrieve bytecodes
byte[] bytecodes = getBytes(path);
// send bytecodes in response (assumes HTTP/1.0 or later)
try {
out.print("HTTP/1.0 200 OK\r\n");
out.print("Content-Length: " + bytecodes.length +
"\r\n");
out.print("Content-Type: text/html\r\n\r\n");
out.flush();
rawOut.write(bytecodes);
rawOut.flush();
} catch (IOException ie) {
ie.printStackTrace();
return;
}
} catch (Exception e) {
e.printStackTrace();
// write out error response
out.println("HTTP/1.0 400 " + e.getMessage() + "\r\n");
out.println("Content-Type: text/html\r\n\r\n");
out.flush();
}
} catch (IOException ex) {
// eat exception (could log error to log file, but
// write out to stdout for now).
System.out.println("error writing response: " + ex.getMessage());
ex.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
}
}
}
/**
* Create a new thread to listen.
*/
private void newListener()
{
(new Thread(this)).start();
}
/**
* Returns the path to the file obtained from
* parsing the HTML header.
*/
private static String getPath(BufferedReader in)
throws IOException
{
String line = in.readLine();
String path = "";
// extract class from GET line
if (line.startsWith("GET /")) {
line = line.substring(5, line.length()-1).trim();
int index = line.indexOf(' ');
if (index != -1) {
path = line.substring(0, index);
}
}
// eat the rest of header
do {
line = in.readLine();
} while ((line.length() != 0) &&
(line.charAt(0) != '\r') && (line.charAt(0) != '\n'));
if (path.length() != 0) {
return path;
} else {
throw new IOException("Malformed Header");
}
}
}