169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.tools.web; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.net.*; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.*; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Date; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.*; 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * A web server for running sample programs. 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This enables a Java program to instrument class files loaded by 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * web browsers for applets. Since the (standard) security manager 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * does not allow an applet to create and use a class loader, 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * instrumenting class files must be done by this web server. 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p><b>Note:</b> although this class is included in the Javassist API, 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * it is provided as a sample implementation of the web server using 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist. Especially, there might be security flaws in this server. 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Please use this with YOUR OWN RISK. 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class Webserver { 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ServerSocket socket; 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ClassPool classPool; 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected Translator translator; 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private final static byte[] endofline = { 0x0d, 0x0a }; 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private final static int typeHtml = 1; 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private final static int typeClass = 2; 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private final static int typeGif = 3; 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private final static int typeJpeg = 4; 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private final static int typeText = 5; 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If this field is not null, the class files taken from 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>ClassPool</code> are written out under the directory 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * specified by this field. The directory name must not end 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * with a directory separator. 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public String debugDir = null; 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The top directory of html (and .gif, .class, ...) files. 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It must end with the directory separator such as "/". 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * (For portability, "/" should be used as the directory separator. 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist automatically translates "/" into a platform-dependent 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * character.) 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If this field is null, the top directory is the current one where 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the JVM is running. 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If the given URL indicates a class file and the class file 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is not found under the directory specified by this variable, 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * then <code>Class.getResourceAsStream()</code> is called 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for searching the Java class paths. 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public String htmlfileBase = null; 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Starts a web server. 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The port number is specified by the first argument. 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static void main(String[] args) throws IOException { 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (args.length == 1) { 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Webserver web = new Webserver(args[0]); 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal web.run(); 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.err.println( 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "Usage: java javassist.tools.web.Webserver <port number>"); 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs a web server. 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param port port number 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Webserver(String port) throws IOException { 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this(Integer.parseInt(port)); 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs a web server. 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param port port number 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Webserver(int port) throws IOException { 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal socket = new ServerSocket(port); 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal classPool = null; 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal translator = null; 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Requests the web server to use the specified 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>ClassPool</code> object for obtaining a class file. 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void setClassPool(ClassPool loader) { 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal classPool = loader; 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Adds a translator, which is called whenever a client requests 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a class file. 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param cp the <code>ClassPool</code> object for obtaining 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a class file. 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param t a translator. 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void addTranslator(ClassPool cp, Translator t) 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws NotFoundException, CannotCompileException 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal classPool = cp; 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal translator = t; 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal t.start(classPool); 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Closes the socket. 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void end() throws IOException { 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal socket.close(); 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Prints a log message. 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void logging(String msg) { 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.println(msg); 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Prints a log message. 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void logging(String msg1, String msg2) { 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.print(msg1); 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.print(" "); 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.println(msg2); 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Prints a log message. 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void logging(String msg1, String msg2, String msg3) { 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.print(msg1); 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.print(" "); 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.print(msg2); 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.print(" "); 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.println(msg3); 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Prints a log message with indentation. 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void logging2(String msg) { 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.print(" "); 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.out.println(msg); 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Begins the HTTP service. 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void run() { 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.err.println("ready to service..."); 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ServiceThread th = new ServiceThread(this, socket.accept()); 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal th.start(); 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (IOException e) { 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal logging(e.toString()); 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal final void process(Socket clnt) throws IOException { 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal InputStream in = new BufferedInputStream(clnt.getInputStream()); 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String cmd = readLine(in); 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal logging(clnt.getInetAddress().getHostName(), 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new Date().toString(), cmd); 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (skipLine(in) > 0){ 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal OutputStream out = new BufferedOutputStream(clnt.getOutputStream()); 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal doReply(in, out, cmd); 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (BadHttpRequest e) { 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal replyError(out, e); 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.flush(); 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal in.close(); 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.close(); 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clnt.close(); 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private String readLine(InputStream in) throws IOException { 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer buf = new StringBuffer(); 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int c; 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while ((c = in.read()) >= 0 && c != 0x0d) 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal buf.append((char)c); 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal in.read(); /* skip 0x0a (LF) */ 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return buf.toString(); 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int skipLine(InputStream in) throws IOException { 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int c; 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int len = 0; 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while ((c = in.read()) >= 0 && c != 0x0d) 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++len; 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal in.read(); /* skip 0x0a (LF) */ 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return len; 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Proceses a HTTP request from a client. 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param out the output stream to a client 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param cmd the command received from a client 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void doReply(InputStream in, OutputStream out, String cmd) 23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException, BadHttpRequest 23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int len; 24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int fileType; 24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String filename, urlName; 24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (cmd.startsWith("GET /")) 24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal filename = urlName = cmd.substring(5, cmd.indexOf(' ', 5)); 24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new BadHttpRequest(); 24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (filename.endsWith(".class")) 24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal fileType = typeClass; 25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (filename.endsWith(".html") || filename.endsWith(".htm")) 25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal fileType = typeHtml; 25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (filename.endsWith(".gif")) 25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal fileType = typeGif; 25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (filename.endsWith(".jpg")) 25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal fileType = typeJpeg; 25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal fileType = typeText; // or textUnknown 25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal len = filename.length(); 26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (fileType == typeClass 26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal && letUsersSendClassfile(out, filename, len)) 26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal checkFilename(filename, len); 26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (htmlfileBase != null) 26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal filename = htmlfileBase + filename; 26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (File.separatorChar != '/') 26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal filename = filename.replace('/', File.separatorChar); 27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal File file = new File(filename); 27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (file.canRead()) { 27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sendHeader(out, file.length(), fileType); 27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal FileInputStream fin = new FileInputStream(file); 27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] filebuffer = new byte[4096]; 27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal len = fin.read(filebuffer); 27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (len <= 0) 27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(filebuffer, 0, len); 28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal fin.close(); 28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // If the file is not found under the html-file directory, 28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // then Class.getResourceAsStream() is tried. 29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (fileType == typeClass) { 29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal InputStream fin 29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = getClass().getResourceAsStream("/" + urlName); 29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (fin != null) { 29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ByteArrayOutputStream barray = new ByteArrayOutputStream(); 29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] filebuffer = new byte[4096]; 29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal len = fin.read(filebuffer); 29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (len <= 0) 30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal barray.write(filebuffer, 0, len); 30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] classfile = barray.toByteArray(); 30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sendHeader(out, classfile.length, typeClass); 30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(classfile); 30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal fin.close(); 30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new BadHttpRequest(); 31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void checkFilename(String filename, int len) 31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws BadHttpRequest 31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < len; ++i) { 32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c = filename.charAt(i); 32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!Character.isJavaIdentifierPart(c) && c != '.' && c != '/') 32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new BadHttpRequest(); 32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (filename.indexOf("..") >= 0) 32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new BadHttpRequest(); 32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private boolean letUsersSendClassfile(OutputStream out, 33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String filename, int length) 33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException, BadHttpRequest 33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (classPool == null) 33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] classfile; 33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String classname 33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = filename.substring(0, length - 6).replace('/', '.'); 33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (translator != null) 34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal translator.onLoad(classPool, classname); 34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass c = classPool.get(classname); 34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal classfile = c.toBytecode(); 34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (debugDir != null) 34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c.writeFile(debugDir); 34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (Exception e) { 34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new BadHttpRequest(e); 35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sendHeader(out, classfile.length, typeClass); 35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(classfile); 35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return true; 35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void sendHeader(OutputStream out, long dataLength, int filetype) 35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException 35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write("HTTP/1.0 200 OK".getBytes()); 36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(endofline); 36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write("Content-Length: ".getBytes()); 36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(Long.toString(dataLength).getBytes()); 36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(endofline); 36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (filetype == typeClass) 36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write("Content-Type: application/octet-stream".getBytes()); 36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (filetype == typeHtml) 36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write("Content-Type: text/html".getBytes()); 36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (filetype == typeGif) 37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write("Content-Type: image/gif".getBytes()); 37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (filetype == typeJpeg) 37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write("Content-Type: image/jpg".getBytes()); 37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (filetype == typeText) 37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write("Content-Type: text/plain".getBytes()); 37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(endofline); 37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(endofline); 37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void replyError(OutputStream out, BadHttpRequest e) 38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException 38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal logging2("bad request: " + e.toString()); 38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write("HTTP/1.0 400 Bad Request".getBytes()); 38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(endofline); 38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(endofline); 38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write("<H1>Bad Request</H1>".getBytes()); 38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalclass ServiceThread extends Thread { 39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Webserver web; 39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Socket sock; 39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public ServiceThread(Webserver w, Socket s) { 39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal web = w; 39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sock = s; 39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void run() { 40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal web.process(sock); 40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (IOException e) { 40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 408