001package runwar.options;
002
003import java.io.File;
004import java.io.IOException;
005import java.net.MalformedURLException;
006import java.util.ArrayList;
007import java.util.Iterator;
008
009import runwar.LaunchUtil;
010import runwar.Server;
011import runwar.logging.Logger;
012import net.minidev.json.JSONObject;
013import net.minidev.json.JSONValue;
014import net.minidev.json.parser.ParseException;
015
016public class ConfigParser {
017
018    private static Logger log = Logger.getLogger("RunwarLogger");
019    private ServerOptions serverOptions;
020
021    public ConfigParser(File config){
022        parseOptions(config);
023        if(serverOptions != null) {
024            serverOptions.setConfigFile(config);
025        }
026    }
027
028    public ServerOptions getServerOptions(){
029        return serverOptions;
030    }
031    
032    private ServerOptions parseOptions(File config) {
033        JSONObject jsonConfig = null;
034        String configFilePath = "unknown";
035        try {
036            configFilePath = config.getCanonicalPath();
037            jsonConfig = (JSONObject) JSONValue.parseWithException(LaunchUtil.readFile(config));
038        } catch (ParseException | IOException e1) {
039            System.out.println("Could not load " + configFilePath + " : " + e1.getMessage());
040            throw new RuntimeException("Could not load " + configFilePath + " : " + e1.getMessage());
041        }
042        if(jsonConfig != null){
043            serverOptions = new ServerOptions();
044            JSONOption serverConfig = new JSONOption(jsonConfig);
045            if (serverConfig.hasOption("help")) {
046                printUsage("Options",0);
047            }
048            if (serverConfig.hasOption("loglevel")) {
049                serverOptions.setLoglevel(serverConfig.getOptionValue("loglevel"));
050            }
051
052            if (serverConfig.hasOption("name")) {
053                serverOptions.setServerName(serverConfig.getOptionValue("name"));
054            }
055
056            if (serverConfig.hasOption("debug")) {
057                Boolean debug= Boolean.valueOf(serverConfig.getOptionValue("debug"));
058                serverOptions.setDebug(debug);
059                if(debug)serverOptions.setLoglevel("DEBUG");
060                if(serverConfig.hasOption("loglevel")) {
061                    System.out.println("Warning:  debug overrides loglevel (both are specified, setting level to DEBUG)");
062                }
063            }
064
065            if (serverConfig.hasOption("background")) {
066                serverOptions.setBackground(Boolean.valueOf(serverConfig.getOptionValue("background")));
067            }
068            if (serverConfig.hasOption("libs")) {
069                String[] list = serverConfig.getOptionValue("libs").split(",");
070                for (String path : list) {
071                    File lib = new File(path);
072                    if (!lib.exists() || !lib.isDirectory())
073                        printUsage("No such lib directory "+path,1);
074                }               
075                serverOptions.setLibDirs(serverConfig.getOptionValue("libs"));
076            }
077            if (serverConfig.hasOption("welcomefiles")) {
078                serverOptions.setWelcomeFiles(serverConfig.getOptionValue("welcomefiles").split(","));
079            }
080
081            if (serverConfig.hasOption("jar")) {
082                 File jar = new File(serverConfig.getOptionValue("jar"));
083                    try {
084                        serverOptions.setJarURL(jar.toURI().toURL());
085                        if (!jar.exists() || jar.isDirectory())
086                            printUsage("No such jar "+jar,1);
087                    } catch (MalformedURLException e) {
088                        printUsage("No such jar "+jar,1);
089                        e.printStackTrace();
090                    }
091            }
092            
093            if (serverConfig.hasOption("timeout")) {
094                serverOptions.setLaunchTimeout(((Number)serverConfig.getParsedOptionValue("timeout")).intValue() * 1000);
095            }
096            if (serverConfig.hasOption("password")) {
097                serverOptions.setStopPassword(serverConfig.getOptionValue("password").toCharArray());
098            }
099            if (serverConfig.hasOption("stop-port")) {
100                serverOptions.setSocketNumber(((Number)serverConfig.getParsedOptionValue("stop-port")).intValue());
101            }
102            if (serverConfig.hasOption("war")) {
103                String warPath = serverConfig.getOptionValue("war");
104                serverOptions.setWarFile(getFile(warPath));
105            } else if (!serverConfig.hasOption("stop") && !serverConfig.hasOption("c")) {
106                printUsage("Must specify -war path/to/war, or -stop [-stop-socket]",1);
107            } 
108            if(serverConfig.hasOption("D")){
109                final String[] properties = serverConfig.getOptionValue("D").split(" ");
110                for (int i = 0; i < properties.length; i++) {
111                    log.debugf("setting system property: %s", properties[i].toString()+'='+properties[i+1].toString());
112                    System.setProperty(properties[i].toString(),properties[i+1].toString());
113                    i++;
114                }
115            }
116
117            if (serverConfig.hasOption("webxmlpath")) {
118                String webXmlPath = serverConfig.getOptionValue("webxmlpath");
119                File webXmlFile = new File(webXmlPath);
120                if(webXmlFile.exists()) {
121                    serverOptions.setWebXmlFile(webXmlFile);
122                } else {
123                    throw new RuntimeException("Could not find web.xml! " + webXmlPath);
124                }
125            }
126
127            if (serverConfig.hasOption("stop")) {
128                serverOptions.setAction("stop");
129                String[] values = serverConfig.getOptionValue("stop").split(" ");
130                if(values != null && values.length > 0) {
131                    serverOptions.setSocketNumber(Integer.parseInt(values[0])); 
132                }
133                if(values != null && values.length >= 1) {
134                    serverOptions.setStopPassword(values[1].toCharArray()); 
135                }
136            } else {
137                serverOptions.setAction("start");
138            }
139
140            if (serverConfig.hasOption("context")) {
141                serverOptions.setContextPath(serverConfig.getOptionValue("context"));
142            }
143            if (serverConfig.hasOption("host")) {
144                serverOptions.setHost(serverConfig.getOptionValue("host"));
145            }
146            if (serverConfig.hasOption("port")) {
147                serverOptions.setPortNumber(((Number)serverConfig.getParsedOptionValue("port")).intValue());
148            }
149            if (serverConfig.hasOption("ajpport")) {
150                serverOptions.setEnableHTTP(false)
151                    .setEnableAJP(true).setAJPPort(((Number)serverConfig.getParsedOptionValue("ajpport")).intValue());
152            }
153            if (serverConfig.hasOption("sslport")) {
154                serverOptions.setEnableHTTP(false).setEnableSSL(true).setSSLPort(((Number)serverConfig.getParsedOptionValue("sslport")).intValue());
155            }
156            if (serverConfig.hasOption("sslcert")) {
157                serverOptions.setSSLCertificate(getFile(serverConfig.getOptionValue("sslcert")));
158                if (!serverConfig.hasOption("sslkey") || !serverConfig.hasOption("sslkey")) {
159                    throw new RuntimeException("Using a SSL certificate requires -sslkey /path/to/file and -sslkeypass pass**** arguments!");   
160                }
161            }
162            if (serverConfig.hasOption("sslkey")) {
163                serverOptions.setSSLKey(getFile(serverConfig.getOptionValue("sslkey")));
164            }
165            if (serverConfig.hasOption("sslkeypass")) {
166                serverOptions.setSSLKeyPass(serverConfig.getOptionValue("sslkeypass").toCharArray());
167            }
168            if (serverConfig.hasOption("enableajp")) {
169                serverOptions.setEnableAJP(Boolean.valueOf(serverConfig.getOptionValue("enableajp")));
170            }
171            if (serverConfig.hasOption("enablessl")) {
172                serverOptions.setEnableHTTP(false).setEnableSSL(Boolean.valueOf(serverConfig.getOptionValue("enablessl")));
173            }
174            if (serverConfig.hasOption("enablehttp")) {
175                serverOptions.setEnableHTTP(Boolean.valueOf(serverConfig.getOptionValue("enablehttp")));
176            }
177            if (serverConfig.hasOption("urlrewritefile")) {
178                serverOptions.setURLRewriteFile(getFile(serverConfig.getOptionValue("urlrewritefile")));
179            }
180            if (serverConfig.hasOption("urlrewriteenable")) {
181                serverOptions.setEnableURLRewrite(Boolean.valueOf(serverConfig.getOptionValue("urlrewriteenable")));
182            }
183            if (serverConfig.hasOption("logdir")) {
184                serverOptions.setLogDir(serverConfig.getOptionValue("logdir"));
185            } else {
186                if(serverOptions.getWarFile() != null){
187                    File warFile = serverOptions.getWarFile();
188                    String logDir;
189                    if(warFile.isDirectory() && new File(warFile,"WEB-INF").exists()) {
190                        logDir = warFile.getPath() + "/WEB-INF/logs/";
191                    } else {
192                        String serverConfigDir = System.getProperty("cfml.server.config.dir");
193                        if(serverConfigDir == null) {
194                            logDir = new File(Server.getThisJarLocation().getParentFile(),"server/log/").getAbsolutePath();
195                        } else {
196                            logDir = new File(serverConfigDir,"log/").getAbsolutePath();                        
197                        }
198                    }
199                    serverOptions.setLogDir(logDir);
200                }
201            }
202            if(serverOptions.getWarFile() != null){
203                serverOptions.setCfmlDirs(serverOptions.getWarFile().getAbsolutePath());
204            }
205            if (serverConfig.hasOption("dirs")) {
206                serverOptions.setCfmlDirs(serverConfig.getOptionValue("dirs"));
207            }
208            if (serverConfig.hasOption("requestlog")) {
209                serverOptions.setKeepRequestLog(Boolean.valueOf(serverConfig.getOptionValue("requestlog")));
210            }
211            
212            if (serverConfig.hasOption("open-browser")) {
213                serverOptions.setOpenbrowser(Boolean.valueOf(serverConfig.getOptionValue("open")));
214            }
215            if (serverConfig.hasOption("open-url")) {
216                serverOptions.setOpenbrowserURL(serverConfig.getOptionValue("open-url"));
217            }
218
219            if (serverConfig.hasOption("pidfile")) {
220                serverOptions.setPidFile(serverConfig.getOptionValue("pidfile"));
221            }
222
223            if (serverConfig.hasOption("processname")) {
224                serverOptions.setProcessName(serverConfig.getOptionValue("processname"));
225            }
226
227            if (serverConfig.hasOption("trayconfig")) {
228                serverOptions.setTrayConfig(getFile(serverConfig.getOptionValue("trayconfig")));
229            }
230
231            if (serverConfig.hasOption("statusfile")) {
232                serverOptions.setStatusFile(getFile(serverConfig.getOptionValue("statusfile")));
233            }
234            
235            if (serverConfig.hasOption("icon")) {
236                serverOptions.setIconImage(serverConfig.getOptionValue("icon"));
237            }
238
239            if (serverConfig.hasOption("cfengine")) {
240                serverOptions.setCFEngineName(serverConfig.getOptionValue("cfengine"));
241            }
242            if (serverConfig.hasOption("cfserverconf")) {
243                serverOptions.setCFMLServletConfigServerDir(serverConfig.getOptionValue("cfserverconf"));
244            }
245            if (serverConfig.hasOption("cfwebconf")) {
246                serverOptions.setCFMLServletConfigWebDir(serverConfig.getOptionValue("cfwebconf"));
247            }
248            if (serverConfig.hasOption("directoryindex")) {
249                serverOptions.setDirectoryListingEnabled(Boolean.valueOf(serverConfig.getOptionValue("directoryindex")));
250            }
251            if (serverConfig.hasOption("cache")) {
252                serverOptions.setCacheEnabled(Boolean.valueOf(serverConfig.getOptionValue("cache")));
253            }
254            if (serverConfig.hasOption("customstatus")) {
255                serverOptions.setCustomHTTPStatusEnabled(Boolean.valueOf(serverConfig.getOptionValue("customstatus")));
256            }
257            if (serverConfig.hasOption("transferminsize")) {
258                serverOptions.setTransferMinSize(Long.valueOf(serverConfig.getOptionValue("transferminsize")));
259            }
260            if (serverConfig.hasOption("sendfile")) {
261                serverOptions.setSendfileEnabled(Boolean.valueOf(serverConfig.getOptionValue("sendfile")));
262            }
263            if (serverConfig.hasOption("gzip")) {
264                serverOptions.setGzipEnabled(Boolean.valueOf(serverConfig.getOptionValue("gzip")));
265            }
266            if (serverConfig.hasOption("mariadb4j")) {
267                serverOptions.setMariaDB4jEnabled(Boolean.valueOf(serverConfig.getOptionValue("mariadb4j")));
268            }
269            if (serverConfig.hasOption("mariadb4jport") && serverConfig.getOptionValue("mariadb4jport").length() > 0) {
270                serverOptions.setMariaDB4jPort(Integer.valueOf(serverConfig.getOptionValue("mariadb4jport")));
271            }
272            if (serverConfig.hasOption("mariadb4jbasedir") && serverConfig.getOptionValue("mariadb4jbasedir").length() > 0) {
273                serverOptions.setMariaDB4jBaseDir(new File(serverConfig.getOptionValue("mariadb4jbasedir")));
274            }
275            if (serverConfig.hasOption("mariadb4jdatadir") && serverConfig.getOptionValue("mariadb4jdatadir").length() > 0) {
276                serverOptions.setMariaDB4jDataDir(new File(serverConfig.getOptionValue("mariadb4jdatadir")));
277            }
278            if (serverConfig.hasOption("mariadb4jimport") && serverConfig.getOptionValue("mariadb4jimport").length() > 0) {
279                serverOptions.setMariaDB4jImportSQLFile(new File(serverConfig.getOptionValue("mariadb4jimport")));
280            }
281
282            if(serverOptions.getLoglevel().equals("DEBUG")) {
283                Iterator<String> optionsIterator = serverConfig.getOptions().iterator();
284                while(optionsIterator.hasNext()) {
285                    log.debug(optionsIterator.next());
286                }
287            }            
288        }
289        return serverOptions;
290    }
291    
292    private void printUsage(String string, int exitCode) {
293        CommandLineHandler.printUsage(string, exitCode);
294    }
295
296    private File getFile(String filePath) {
297        return CommandLineHandler.getFile(filePath);
298    }
299    
300    private class JSONOption {
301        private JSONObject jsonConfig;
302
303        public JSONOption(JSONObject jsonConfig) {
304            this.jsonConfig = jsonConfig;
305        }
306
307        public Number getParsedOptionValue(String string) {
308            return Integer.parseInt(getOptionValue(string));
309        }
310
311        public ArrayList<String> getOptions() {
312            Iterator<String> keys = jsonConfig.keySet().iterator();
313            ArrayList<String> options = new ArrayList<String>();
314            while(keys.hasNext()) {
315                String key = keys.next();
316                options.add(key+"="+jsonConfig.get(key).toString());
317            }
318            return options;
319        }
320
321        public String getOptionValue(String key) {
322            if(hasOption(key)){
323              return jsonConfig.get(key).toString();
324            }
325            return null;
326        }
327
328        public boolean hasOption(String key) {
329            return jsonConfig.containsKey(key);
330        }
331    }
332
333}