1 /* 2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab 3 * Copyright (C) 2010 - Calixte DENIZET 4 * 5 * Copyright (C) 2012 - 2016 - Scilab Enterprises 6 * 7 * This file is hereby licensed under the terms of the GNU GPL v2.0, 8 * pursuant to article 5.3.4 of the CeCILL v.2.1. 9 * This file was originally licensed under the terms of the CeCILL v2.1, 10 * and continues to be available under such terms. 11 * For more information, see the COPYING file which you should have received 12 * along with this program. 13 * 14 */ 15 16 package org.scilab.modules.helptools.scilab; 17 18 import java.io.BufferedReader; 19 import java.io.InputStreamReader; 20 import java.io.IOException; 21 import java.io.Reader; 22 import java.io.OutputStreamWriter; 23 import java.io.Writer; 24 import java.net.Socket; 25 import java.net.ServerSocket; 26 import java.nio.charset.Charset; 27 import java.util.HashMap; 28 import java.util.Map; 29 import java.util.Stack; 30 31 /** 32 * Server to colorize Scilab code. 33 * The string passed to the server must be terminated with an EOF or a null char "\0". 34 */ 35 public final class ScilabCodeServer { 36 37 private static final int DEFAULTMAXHANDLERS = 5; 38 39 private Stack<HTMLWithStyleScilabCodeHandler> stack = new Stack<HTMLWithStyleScilabCodeHandler>(); 40 private String prim; 41 private String macro; 42 private int maxHandler; 43 44 /** 45 * Main method 46 * @param args the command line arguments 47 */ main(String[] args)48 public static void main(String[] args) { 49 Map<String, String> map = parseCommandLine(args); 50 if (map.containsKey("help")) { 51 System.out.println("Usage scicodeserver [OPTION]..."); 52 System.out.println("Create a multi-thread server to colorize Scilab code"); 53 System.out.println(""); 54 System.out.println("-port An integer giving the port where to listen to"); 55 System.out.println("-sciprim A file containing the list of the Scilab primitives"); 56 System.out.println("-scimacro A file containing the list of the Scilab macros"); 57 System.out.println("-maxhandlers An integer giving the maximum of Scilab code handlers"); 58 System.out.println(" which must be kept in memory (5 by default)"); 59 System.out.println(""); 60 System.out.println("Report bugs on: <http://bugzilla.scilab.org>"); 61 System.out.println("Project page: <http://forge.scilab.org/index.php/p/scidoc>"); 62 return; 63 } 64 65 if (!map.containsKey("port")) { 66 System.err.println("No port"); 67 System.err.println("Use the option -help"); 68 return; 69 } 70 71 int max = DEFAULTMAXHANDLERS; 72 if (map.containsKey("maxhandlers")) { 73 try { 74 max = Integer.parseInt(map.get("maxhandlers")); 75 } catch (Exception e) { 76 System.err.println("The option -maxhandlers expects a positive integer"); 77 return; 78 } 79 } 80 81 int port = 0; 82 if (map.containsKey("port")) { 83 try { 84 port = Integer.parseInt(map.get("port")); 85 } catch (Exception e) { 86 System.err.println("The option -port expects a positive integer"); 87 return; 88 } 89 } 90 91 ScilabCodeServer scs = new ScilabCodeServer(map.get("sciprim"), map.get("scimacro"), max); 92 try { 93 ServerSocket server = new ServerSocket(port); 94 while (true) { 95 new ScilabCodeThread(server.accept(), scs); 96 } 97 } catch (IOException e) { 98 e.printStackTrace(); 99 } 100 } 101 102 /** 103 * Private constructor 104 * @param primFile the filename containing the list of the scilab built-in commands 105 * @param macroFile the filename containing the list of the scilab macros 106 * @param maxHandler the maximum handlers which must be cached 107 */ ScilabCodeServer(String primFile, String macroFile, int maxHandler)108 private ScilabCodeServer(String primFile, String macroFile, int maxHandler) { 109 this.prim = primFile; 110 this.macro = macroFile; 111 this.maxHandler = maxHandler; 112 } 113 114 /** 115 * Get an handler. The stack is synchronized. 116 * @return an handler 117 */ getHandler()118 private HTMLWithStyleScilabCodeHandler getHandler() { 119 synchronized (stack) { 120 if (stack.isEmpty()) { 121 return new HTMLWithStyleScilabCodeHandler(prim, macro); 122 } 123 return stack.pop(); 124 } 125 } 126 127 /** 128 * Push an handler in the stack to cach it. The stack is synchronized. 129 * @param h the handler 130 */ pushHandler(HTMLWithStyleScilabCodeHandler h)131 private void pushHandler(HTMLWithStyleScilabCodeHandler h) { 132 synchronized (stack) { 133 if (stack.size() < maxHandler) { 134 stack.push(h); 135 } 136 } 137 } 138 139 /** 140 * @param in the input 141 * @param out the output 142 * @throws IOException 143 */ convert(Reader in, Writer out)144 private void convert(Reader in, Writer out) throws IOException { 145 HTMLWithStyleScilabCodeHandler handler = getHandler(); 146 handler.convert(in, out); 147 pushHandler(handler); 148 } 149 150 /** 151 * Parse the command line 152 * @param args the arguments 153 * @return the options with their argument in a map 154 */ parseCommandLine(String[] args)155 private static Map<String, String> parseCommandLine(String[] args) { 156 String option = null; 157 boolean in = false; 158 Map<String, String> map = new HashMap<String, String>(); 159 for (int i = 0; i < args.length; i++) { 160 if (args[i].length() >= 2 && args[i].charAt(0) == '-') { 161 if (option != null) { 162 map.put(option, ""); 163 } 164 if (args[i].charAt(1) == '-') { 165 option = args[i].substring(2); 166 } else { 167 option = args[i].substring(1); 168 } 169 } else { 170 if (option != null) { 171 map.put(option, args[i]); 172 option = null; 173 } else if (!in) { 174 map.put("input", args[i]); 175 in = true; 176 } else { 177 System.err.println("Not an argument " + args[i]); 178 return null; 179 } 180 } 181 } 182 if (option != null) { 183 map.put(option, ""); 184 } 185 186 return map; 187 } 188 189 /** 190 * Inner class 191 */ 192 private static class ScilabCodeThread implements Runnable { 193 194 private Reader in; 195 private Writer out; 196 private Socket sock; 197 private ScilabCodeServer scs; 198 199 /** 200 * Default constructor 201 * @param sock the socket where to read and write 202 * @param scs the server 203 */ ScilabCodeThread(Socket sock, ScilabCodeServer scs)204 ScilabCodeThread(Socket sock, ScilabCodeServer scs) { 205 this.sock = sock; 206 this.scs = scs; 207 try { 208 in = new BufferedReader(new InputStreamReader(sock.getInputStream(), Charset.forName("UTF-8"))); 209 out = new OutputStreamWriter(sock.getOutputStream(), Charset.forName("UTF-8")); 210 } catch (IOException e) { 211 e.printStackTrace(); 212 } 213 new Thread(this).start(); 214 } 215 run()216 public void run() { 217 try { 218 scs.convert(in, out); 219 out.flush(); 220 out.close(); 221 in.close(); 222 sock.close(); 223 } catch (IOException e) { 224 e.printStackTrace(); 225 } 226 } 227 } 228 } 229