📄 classfileserver.java
字号:
/* * @<#>ClassFileServer.java version 0.0.2, 7/1/2001 * * THIS PROGRAM IS FREE SOFTWARE; YOU CAN DISTRIBUTE IT AND/OR * MODIFY IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE * AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION. * * THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, * BUT WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE * GNU GENERAL PUBLIC LICENSE FOR MORE DETAILS. * * Copyright (c) 2001 Wayne State University. All Rights Reserved. */package naplet.server;import java.io.*;import java.net.*;import naplet.NapletInternalError;/** * ClassServer is a class that provides the * basic functionality of a mini-webserver, specialized * to load class files and archived class files. * * The ClassServer creates a thread that listens on a socket * and accepts HTTP GET requests. The HTTP response contains the * bytecodes for the class that requested in the GET header. <p> * * For loading remote classes, an RMI application can use a concrete * subclass of this server in place of an HTTP server. <p> * * @version 0.0.2, 7/1/2001 * @author C. Xu, czxu@wayne.edu * */public class ClassFileServer implements Runnable { private static int DefaultServerPort = 2001; private static ClassFileServer instance = null; private int port; private String classpath; private ServerSocket server = null; /** * Constructs a ClassFileServer that listens on <b>port</b> and * obtains a class's bytecodes using the method <b>getBytes</b>. * It is a singleton instance class. * * @param port the port number * @param classpath the classpath where the server locates classes * @exception IOException if the ClassServer could not listen * on <b>port</b>. */ protected ClassFileServer(int port, String classpath) throws IOException { this.port = port; this.classpath = classpath; server = new ServerSocket(port); newListener(); } public static ClassFileServer getInstance(int port, String classpath) throws IOException { if (instance == null ) instance = new ClassFileServer(port, classpath); return instance; } /** * Returns an array of bytes containing the bytecodes for * the class represented by the argument <b>path</b>. * The <b>path</b> is a dot separated class name with * the ".class" extension removed. * * @return the bytecodes for the class * @exception ClassNotFoundException if the class corresponding * to <b>path</b> could not be loaded. * @exception IOException if error occurs reading the class */ public byte[] getBytes(String name) throws IOException, ClassNotFoundException { File f; System.out.println("reading: " + name); int index = name.lastIndexOf('.'); if (index!=-1) { f = new File(classpath + File.separator + name.substring(0,index).replace('.', File.separatorChar) + name.substring(index)); } else throw new NapletInternalError("Reading file(.class or .jar) error"); int length = (int)(f.length()); if (length == 0) { throw new IOException("File length is zero: " + name); } else { FileInputStream fin = new FileInputStream(f); DataInputStream in = new DataInputStream(fin); byte[] bytecodes = new byte[length]; in.readFully(bytecodes); return bytecodes; } } /** * The "listen" thread that accepts a connection to the * server, parses the header to obtain the class file name * and sends back the bytecodes for the class (or error * if the class 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 { DataOutputStream out = new DataOutputStream(socket.getOutputStream()); try { // get class name of the file from header InputStream in = socket.getInputStream(); String className = getClassName(in); // retrieve bytecodes byte[] bytecodes = getBytes(className); // send bytecodes in response (assumes HTTP/1.0 or later) try { out.writeBytes("HTTP/1.0 200 OK\r\n"); out.writeBytes("Content-Length: " + bytecodes.length + "\r\n"); out.writeBytes("Content-Type: application/java\r\n\r\n"); out.write(bytecodes); out.flush(); } catch (IOException ie) { return; } } catch (Exception e) { // 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) { // 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 class name of the file obtained from * parsing the HTML header. */ private static String getClassName(InputStream is) throws IOException { InputStreamReader r = new InputStreamReader(is); BufferedReader in = new BufferedReader( r ); String line = in.readLine(); String className = ""; // extract class from GET line if (line.startsWith("GET /")) { line = line.substring(5, line.length()-1).trim(); int index = line.indexOf(".class "); if (index != -1) { className = line.substring(0, index).replace('/', '.') + ".class"; } else { index = line.indexOf(".jar"); if (index!=-1) { className = line.substring(0, index).replace('/', '.') + ".jar"; } else { throw new IOException("Load non-class/jar file error"); } } } // eat the rest of header do { line = in.readLine(); } while ((line.length() != 0) && (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); if (className.length() != 0) { return className; } else { throw new IOException("Malformed Header"); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -