diff --git a/app/src/processing/mode/javascript/BasicServer.java b/app/src/processing/mode/javascript/BasicServer.java index b02ccb192..18a135989 100644 --- a/app/src/processing/mode/javascript/BasicServer.java +++ b/app/src/processing/mode/javascript/BasicServer.java @@ -5,9 +5,9 @@ import java.net.*; import java.util.*; /** - * Based on Sun tutorial at: http://bit.ly/fpoHAF - * - * Changed to accept a document root. + * BasicServer, the server underneath JavaScript mode. + * Based on a Sun tutorial at: http://bit.ly/fpoHAF + * Changed to accept a document root. */ class BasicServer implements HttpConstants, Runnable { @@ -36,6 +36,11 @@ class BasicServer implements HttpConstants, Runnable private ArrayList addresses; + /** + * Constructor + * + * @param root the root folder to serve from + */ BasicServer ( File root ) { setRoot( root ); @@ -43,11 +48,21 @@ class BasicServer implements HttpConstants, Runnable findPort(); } + /** + * Getter, return the server root folder + * + * @return the root file + */ public File getRoot () { return virtualRoot; } - + + /** + * Set the root folder to a new dir + * + * @param root the new folder to server form + */ public void setRoot ( File root ) { if ( root.exists() && root.isDirectory() && root.canRead() ) @@ -60,24 +75,44 @@ class BasicServer implements HttpConstants, Runnable } } - public void addListener ( BasicServerListener l ) + /** + * Add a listener to this server for start/stop callbacks + * + * @param listener the listener to add, needs to implement interface BasicServerListener + */ + public void addListener ( BasicServerListener listener ) { if ( listeners == null ) listeners = new ArrayList(); - if ( l != null ) { - listeners.add( l ); + if ( listener != null ) { + listeners.add( listener ); } } + /** + * Get the timeout, the time span after which requests are discarded + * + * @return the timeout as int in milliseconds + */ public int getTimeout () { return timeout; } + /** + * Getter, returns the server address with port as URL string + * + * @return the server address as URL string + */ public String getAddress () { return localDomain + ":" + getPort() + "/"; } + /** + * Build a list of addresses that this machine is available under + * + * @return an ArrayList with 0 or more addresses as URL strings + */ public ArrayList getInetAddresses () { addresses = new ArrayList(); @@ -105,6 +140,9 @@ class BasicServer implements HttpConstants, Runnable return addresses; } + /** + * Look for and set to an available port + */ private void findPort () { ServerSocket ss = null; @@ -122,11 +160,21 @@ class BasicServer implements HttpConstants, Runnable } } + /** + * Getter, return the current port the server is available on + * + * @return the port number as int + */ public int getPort () { return port; } + /** + * Set the port number to a new one + * + * @param newPort the new port number as int, should be > 1024 and < 49151 + */ public void setPort ( int newPort ) { if ( !isRunning() ) @@ -151,7 +199,10 @@ class BasicServer implements HttpConstants, Runnable } } } - + + /** + * Start this server, starts internal thread + */ public void start () { if ( virtualRoot == null ) @@ -169,6 +220,9 @@ class BasicServer implements HttpConstants, Runnable * Checks to see if a specific port is available. * http://mina.apache.org/ * http://stackoverflow.com/questions/434718/sockets-discover-port-availability-using-java + * + * @param port a port number to test + * @return true if port number is available */ public static boolean available ( int port ) { @@ -209,7 +263,9 @@ class BasicServer implements HttpConstants, Runnable return false; } - + /** + * Restart the server + */ public void restart () { if ( running ) shutDown(); @@ -217,7 +273,10 @@ class BasicServer implements HttpConstants, Runnable start(); } - // http://bit.ly/eA8iGj + /** + * Stop the server + * With a little help from: http://bit.ly/eA8iGj + */ public void shutDown () { //System.out.println("Shutting down"); @@ -248,11 +307,22 @@ class BasicServer implements HttpConstants, Runnable } } + /** + * Getter, return if server is running + * + * @return true if server is running + */ public boolean isRunning () { return running && inited; } + /** + * interface Runnable + * Called on a new thread to do handle the requests coming in + * + * @see java.lang.Runnable + */ public void run () { try @@ -314,6 +384,9 @@ class BasicServer implements HttpConstants, Runnable } } +/** + * Worker class, handles the actual serving of files + */ class Worker extends BasicServer implements HttpConstants, Runnable { @@ -327,26 +400,50 @@ implements HttpConstants, Runnable private Socket socket; private boolean stopping = false; + + /* mapping of file extensions to content-types */ + static java.util.Hashtable map = new java.util.Hashtable(); + static { + fillMap(); + } + + /** + * Constructor + * + * @param root the root folder to serve from + */ Worker ( File root ) { super( root ); buf = new byte[BUF_SIZE]; socket = null; } - + + /** + * Set socket, this is the actual request + */ synchronized void setSocket( Socket s ) { socket = s; notify(); } - + + /** + * Try to stop it + */ synchronized void stop () { stopping = true; notify(); } - + + /** + * interface Runnable + * Called to do the heavy lifting + * + * @see java.lang.Runnable + */ public synchronized void run () { while ( true && !stopping ) @@ -376,6 +473,9 @@ implements HttpConstants, Runnable } } + /** + * Handle a request from a client + */ void handleClient() throws IOException { InputStream is = new BufferedInputStream( socket.getInputStream() ); @@ -500,6 +600,9 @@ outerloop: } } + /** + * Send the default headers to client + */ boolean printHeaders ( File targ, PrintStream ps ) throws IOException { boolean ret = false; @@ -560,7 +663,10 @@ outerloop: } return ret; } - + + /** + * Send 404 content to client + */ void send404(File targ, PrintStream ps) throws IOException { ps.write(EOL); @@ -568,14 +674,40 @@ outerloop: ps.println("Not Found\n\n"+ "The requested resource was not found.\n"); } - + + + /** + * Build list of contents and send it to client + */ + void listDirectory ( File dir, PrintStream ps ) throws IOException + { + ps.println("Directory listing

\n"); + ps.println("Parent Directory
\n"); + String[] list = dir.list(); + for (int i = 0; list != null && i < list.length; i++) { + File f = new File(dir, list[i]); + if (f.isDirectory()) { + ps.println(""+list[i]+"/
"); + } else { + ps.println(""+list[i]+"



" + (new Date()) + ""); + } + + /** + * + */ void logAndSendNop (PrintStream ps) throws IOException { ps.write(EOL); ps.write(EOL); ps.println("\n"); } - + + /** + * Send contents of a file to client + */ void sendFile(File targ, PrintStream ps) throws IOException { InputStream is = null; @@ -596,19 +728,19 @@ outerloop: is.close(); } } - - /* mapping of file extensions to content-types */ - static java.util.Hashtable map = new java.util.Hashtable(); - - static { - fillMap(); - } - - static void setSuffix(String k, String v) { + + /** + * Add a mapping of file extension to mime-type / content-type + */ + static void setSuffix ( String k, String v ) + { map.put(k, v); } - - static void fillMap() + + /** + * Add some default mappings + */ + static void fillMap () { // this probably can be shortened a lot since this is not a normal server .. setSuffix("", "content/unknown"); @@ -862,25 +994,13 @@ outerloop: setSuffix(".z", "application/x-compress"); setSuffix(".zip", "application/zip"); } - - void listDirectory ( File dir, PrintStream ps ) throws IOException - { - ps.println("Directory listing

\n"); - ps.println("Parent Directory
\n"); - String[] list = dir.list(); - for (int i = 0; list != null && i < list.length; i++) { - File f = new File(dir, list[i]); - if (f.isDirectory()) { - ps.println(""+list[i]+"/
"); - } else { - ps.println(""+list[i]+"



" + (new Date()) + ""); - } - } +/** + * Needed HTTP constants/codes + * + * @see Wikipedia: List of HTTP codes + */ interface HttpConstants { /** 2XX: generally "OK" */ public static final int HTTP_OK = 200; @@ -926,6 +1046,9 @@ interface HttpConstants { public static final int HTTP_VERSION = 505; } +/** + * Interface BasicServerListener + */ interface BasicServerListener { public abstract void serverStarted(); diff --git a/app/src/processing/mode/javascript/ServingEditor.java b/app/src/processing/mode/javascript/ServingEditor.java index fc510335e..1f133514e 100644 --- a/app/src/processing/mode/javascript/ServingEditor.java +++ b/app/src/processing/mode/javascript/ServingEditor.java @@ -11,6 +11,10 @@ import java.io.File; import java.io.IOException; import javax.swing.JOptionPane; +/** + * This is the basis for the JavaScript mode, an editor that serves files from a + * given root directory. + */ public abstract class ServingEditor extends Editor implements BasicServerListener { public final static String PROP_KEY_SERVER_PORT = "basicserver.port"; @@ -19,11 +23,24 @@ public abstract class ServingEditor extends Editor implements BasicServerListene public boolean showSizeWarning = true; + /** + * Constructor + * + * @param base the Processing Base this runs of + * @param path the path to a sketch to open + * @param editor state + * @param the mode to open in + * @see processing.app.Editor + * @see processing.app.Base + */ protected ServingEditor ( Base base, String path, EditorState state, Mode mode ) { super( base, path, state, mode ); } + /** + * Set the server port, shows an input dialog to enter a port number + */ protected void setServerPort () { String pString = null; @@ -71,26 +88,46 @@ public abstract class ServingEditor extends Editor implements BasicServerListene } } + /** + * Getter, returns the server port + * + * @return the server port as int or -1 + */ public int getServerPort () { if ( server != null ) return server.getPort(); return -1; } + /** + * Getter, returns the current server address + * + * @return the server address as URL string or null + */ public String getServerAddress () { if ( server != null && server.isRunning() ) return server.getAddress(); return null; } - + + /** + * Getter, returns the server + * + * @return the BasicServer of this editor + */ public BasicServer getServer () { return server; } + /** + * A toggle to start/stop the server + * + * @param root the root folder to start from if it needs to be started + */ protected void startStopServer ( File root ) { - if ( server != null && server.isRunning() ) + if ( serverRunning() ) { stopServer(); } @@ -100,6 +137,12 @@ public abstract class ServingEditor extends Editor implements BasicServerListene } } + /** + * Create a server to server from given root dir + * + * @param root the root folder to server from + * @return the BasicServer instance running or created + */ protected BasicServer createServer ( File root ) { if ( server != null ) return server; @@ -130,6 +173,12 @@ public abstract class ServingEditor extends Editor implements BasicServerListene return server; } + /** + * Start the internal server for this sketch. + * + * @param root the root folder for the server to serve from + * @return true if it was started anew, false if it was running + */ protected boolean startServer ( File root ) { if ( server != null && @@ -163,18 +212,29 @@ public abstract class ServingEditor extends Editor implements BasicServerListene return true; } + /** + * Check if server is running + * + * @return true if server is running + */ protected boolean serverRunning () { return server != null && server.isRunning(); } + /** + * Stop server + */ protected void stopServer () { - if ( server != null && server.isRunning() ) - server.shutDown(); - + if ( serverRunning() ) server.shutDown(); } + /** + * Create or get the sketch's properties file + * + * @return the sketch properties file or null + */ protected File getSketchPropertiesFile () { File sketchPropsFile = new File( getSketch().getFolder(), "sketch.properties"); @@ -191,16 +251,25 @@ public abstract class ServingEditor extends Editor implements BasicServerListene return sketchPropsFile; } + /** + * Open a new browser window or tab with the server address + */ protected void openBrowserForServer () { - if ( server != null && server.isRunning() ) + if ( serverRunning() ) { Base.openURL( server.getAddress() ); } } - // ---- interface BasicServerListener + // ------------------------------------------ + // interface BasicServerListener + // ------------------------------------------ + /** + * interface BasicServerListener + * Called after the server was started from the server thread + */ public void serverStarted () { String location = server.getAddress(); @@ -208,8 +277,12 @@ public abstract class ServingEditor extends Editor implements BasicServerListene openBrowserForServer(); } + /** + * interface BasicServerListener + * Called from server thread after the server stopped + */ public void serverStopped () { - statusNotice("Server stopped."); + statusNotice( "Server stopped." ); } } \ No newline at end of file