/* ======================================================================== * PlantUML : a free UML diagram generator * ======================================================================== * * (C) Copyright 2009-2017, Arnaud Roques * * Project Info: http://plantuml.com * * If you like this project or if you find it useful, you can support us at: * * http://plantuml.com/patreon (only 1$ per month!) * http://plantuml.com/paypal * * This file is part of PlantUML. * * PlantUML is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * PlantUML 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. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * * Original Author: Arnaud Roques * * */ package net.sourceforge.plantuml; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import net.sourceforge.plantuml.api.ApiWarning; import net.sourceforge.plantuml.command.regex.Matcher2; import net.sourceforge.plantuml.command.regex.MyPattern; import net.sourceforge.plantuml.command.regex.Pattern2; import net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils; import net.sourceforge.plantuml.preproc.Defines; import net.sourceforge.plantuml.stats.StatsUtils; public class Option { private final List excludes = new ArrayList(); private final List config = new ArrayList(); private final Map defines = new LinkedHashMap(); private String charset; private boolean computeurl = false; private boolean decodeurl = false; private boolean pipe = false; private String pipeDelimitor; private boolean pipeMap = false; private boolean pipeNoStdErr = false; private boolean syntax = false; private boolean checkOnly = false; private OptionPreprocOutputMode preprocessorOutput = null; private boolean failfast = false; private boolean failfast2 = false; private boolean pattern = false; private boolean duration = false; private boolean debugsvek = false; private boolean splash = false; private boolean textProgressBar = false; private int nbThreads = 0; private int ftpPort = -1; private boolean hideMetadata = false; private boolean checkMetadata = false; private int imageIndex = 0; private File outputDir = null; private File outputFile = null; private String filename; private final List result = new ArrayList(); public Option() { } private FileFormatOption fileFormatOption = new FileFormatOption(FileFormat.PNG); @Deprecated @ApiWarning(willBeRemoved = "in next major release") final public void setFileFormat(FileFormat fileFormat) { setFileFormatOption(new FileFormatOption(fileFormat)); } final public void setFileFormatOption(FileFormatOption newFormat) { this.fileFormatOption = newFormat; } public Option(String... arg) throws InterruptedException, IOException { if (arg.length == 0) { OptionFlags.getInstance().setGui(true); } for (int i = 0; i < arg.length; i++) { String s = arg[i]; if (s.equalsIgnoreCase("-headless")) { // Useless because done in Run.java if (i != 0) { Log.error("Warning: -headless flag must be the first one in the command line"); } System.setProperty("java.awt.headless", "true"); } else if (s.equalsIgnoreCase("-tsvg") || s.equalsIgnoreCase("-svg")) { setFileFormatOption(new FileFormatOption(FileFormat.SVG)); } else if (s.equalsIgnoreCase("-tsvg:nornd") || s.equalsIgnoreCase("-svg:nornd")) { setFileFormatOption(new FileFormatOption(FileFormat.SVG)); } else if (s.equalsIgnoreCase("-thtml") || s.equalsIgnoreCase("-html")) { setFileFormatOption(new FileFormatOption(FileFormat.HTML)); } else if (s.equalsIgnoreCase("-tscxml") || s.equalsIgnoreCase("-scxml")) { setFileFormatOption(new FileFormatOption(FileFormat.SCXML)); } else if (s.equalsIgnoreCase("-txmi") || s.equalsIgnoreCase("-xmi")) { setFileFormatOption(new FileFormatOption(FileFormat.XMI_STANDARD)); } else if (s.equalsIgnoreCase("-txmi:argo") || s.equalsIgnoreCase("-xmi:argo")) { setFileFormatOption(new FileFormatOption(FileFormat.XMI_ARGO)); } else if (s.equalsIgnoreCase("-txmi:star") || s.equalsIgnoreCase("-xmi:star")) { setFileFormatOption(new FileFormatOption(FileFormat.XMI_STAR)); } else if (s.equalsIgnoreCase("-teps") || s.equalsIgnoreCase("-eps")) { setFileFormatOption(new FileFormatOption(FileFormat.EPS)); } else if (s.equalsIgnoreCase("-teps:text") || s.equalsIgnoreCase("-eps:text")) { setFileFormatOption(new FileFormatOption(FileFormat.EPS_TEXT)); } else if (s.equalsIgnoreCase("-ttxt") || s.equalsIgnoreCase("-txt")) { setFileFormatOption(new FileFormatOption(FileFormat.ATXT)); } else if (s.equalsIgnoreCase("-tutxt") || s.equalsIgnoreCase("-utxt")) { setFileFormatOption(new FileFormatOption(FileFormat.UTXT)); } else if (s.equalsIgnoreCase("-braille") || s.equalsIgnoreCase("-tbraille")) { setFileFormatOption(new FileFormatOption(FileFormat.BRAILLE_PNG)); } else if (s.equalsIgnoreCase("-png") || s.equalsIgnoreCase("-tpng")) { setFileFormatOption(new FileFormatOption(FileFormat.PNG)); } else if (s.equalsIgnoreCase("-vdx") || s.equalsIgnoreCase("-tvdx")) { setFileFormatOption(new FileFormatOption(FileFormat.VDX)); } else if (s.equalsIgnoreCase("-latex") || s.equalsIgnoreCase("-tlatex")) { setFileFormatOption(new FileFormatOption(FileFormat.LATEX)); } else if (s.equalsIgnoreCase("-latex:nopreamble") || s.equalsIgnoreCase("-tlatex:nopreamble")) { setFileFormatOption(new FileFormatOption(FileFormat.LATEX_NO_PREAMBLE)); } else if (s.equalsIgnoreCase("-base64") || s.equalsIgnoreCase("-tbase64")) { setFileFormatOption(new FileFormatOption(FileFormat.BASE64)); } else if (s.equalsIgnoreCase("-pdf") || s.equalsIgnoreCase("-tpdf")) { setFileFormatOption(new FileFormatOption(FileFormat.PDF)); } else if (s.equalsIgnoreCase("-overwrite")) { OptionFlags.getInstance().setOverwrite(true); } else if (s.equalsIgnoreCase("-output") || s.equalsIgnoreCase("-o")) { i++; if (i == arg.length) { continue; } outputDir = new File(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg[i])); } else if (s.equalsIgnoreCase("-ofile")) { i++; if (i == arg.length) { continue; } outputFile = new File(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg[i])); } else if (s.equalsIgnoreCase("-graphvizdot") || s.equalsIgnoreCase("-graphviz_dot")) { i++; if (i == arg.length) { continue; } GraphvizUtils.setDotExecutable(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg[i])); } else if (s.equalsIgnoreCase("-charset")) { i++; if (i == arg.length) { continue; } charset = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg[i]); } else if (s.equalsIgnoreCase("-filename")) { i++; if (i == arg.length) { continue; } filename = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg[i]); } else if (s.startsWith("-o") && s.length() > 3) { s = s.substring(2); outputDir = new File(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(s)); } else if (s.equalsIgnoreCase("-recurse") || s.equalsIgnoreCase("-r")) { // recurse = true; } else if (s.equalsIgnoreCase("-exclude") || s.equalsIgnoreCase("-x")) { i++; if (i == arg.length) { continue; } excludes.add(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg[i])); } else if (s.equalsIgnoreCase("-nbthread") || s.equalsIgnoreCase("-nbthreads")) { i++; if (i == arg.length) { continue; } final String nb = arg[i]; if ("auto".equalsIgnoreCase(nb)) { this.nbThreads = defaultNbThreads(); } else if (nb.matches("\\d+")) { this.nbThreads = Integer.parseInt(nb); } } else if (s.equalsIgnoreCase("-timeout")) { i++; if (i == arg.length) { continue; } final String timeSeconds = arg[i]; if (timeSeconds.matches("\\d+")) { OptionFlags.getInstance().setTimeoutMs(Integer.parseInt(timeSeconds) * 1000L); } } else if (s.equalsIgnoreCase("-failfast")) { this.failfast = true; } else if (s.equalsIgnoreCase("-failfast2")) { this.failfast2 = true; } else if (s.equalsIgnoreCase("-checkonly")) { this.checkOnly = true; } else if (s.equalsIgnoreCase("-config")) { i++; if (i == arg.length) { continue; } initConfig(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg[i])); } else if (s.startsWith("-I")) { initInclude(s.substring(2)); } else if (s.equalsIgnoreCase("-computeurl") || s.equalsIgnoreCase("-encodeurl")) { this.computeurl = true; } else if (s.startsWith("-x")) { s = s.substring(2); excludes.add(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(s)); } else if (s.equalsIgnoreCase("-verbose") || s.equalsIgnoreCase("-v")) { OptionFlags.getInstance().setVerbose(true); } else if (s.equalsIgnoreCase("-pipe") || s.equalsIgnoreCase("-p")) { pipe = true; } else if (s.equalsIgnoreCase("-pipedelimitor")) { i++; if (i == arg.length) { continue; } pipeDelimitor = arg[i]; } else if (s.equalsIgnoreCase("-pipemap")) { pipeMap = true; } else if (s.equalsIgnoreCase("-pipenostderr")) { pipeNoStdErr = true; } else if (s.equalsIgnoreCase("-pattern")) { pattern = true; } else if (s.equalsIgnoreCase("-syntax")) { syntax = true; OptionFlags.getInstance().setQuiet(true); } else if (s.equalsIgnoreCase("-duration")) { duration = true; } else if (s.equalsIgnoreCase("-debugsvek") || s.equalsIgnoreCase("-debug_svek")) { debugsvek = true; } else if (s.equalsIgnoreCase("-keepfiles") || s.equalsIgnoreCase("-keepfile")) { System.err.println("-keepfiles option has been removed. Please consider -debugsvek instead"); } else if (s.equalsIgnoreCase("-metadata")) { OptionFlags.getInstance().setExtractFromMetadata(true); } else if (s.equalsIgnoreCase("-logdata")) { i++; if (i == arg.length) { continue; } OptionFlags.getInstance().setLogData( new File(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg[i]))); } else if (s.equalsIgnoreCase("-word")) { OptionFlags.getInstance().setWord(true); OptionFlags.getInstance().setQuiet(true); this.charset = "UTF-8"; } else if (s.equalsIgnoreCase("-quiet")) { OptionFlags.getInstance().setQuiet(true); } else if (s.equalsIgnoreCase("-decodeurl")) { this.decodeurl = true; } else if (s.equalsIgnoreCase("-version")) { OptionPrint.printVersion(); } else if (s.matches("(?i)^-li[sc][ea]n[sc]e\\s*$")) { OptionPrint.printLicense(); } else if (s.equalsIgnoreCase("-checkversion")) { OptionPrint.checkVersion(); } else if (s.startsWith("-D")) { manageDefine(s.substring(2)); } else if (s.startsWith("-S")) { manageSkinParam(s.substring(2)); } else if (s.equalsIgnoreCase("-testdot")) { OptionPrint.printTestDot(); } else if (s.equalsIgnoreCase("-about") || s.equalsIgnoreCase("-author") || s.equalsIgnoreCase("-authors")) { OptionPrint.printAbout(); } else if (s.equalsIgnoreCase("-help") || s.equalsIgnoreCase("-h") || s.equalsIgnoreCase("-?")) { OptionPrint.printHelp(); } else if (s.equalsIgnoreCase("-language")) { OptionPrint.printLanguage(); } else if (s.equalsIgnoreCase("-gui")) { OptionFlags.getInstance().setGui(true); } else if (s.equalsIgnoreCase("-encodesprite")) { OptionFlags.getInstance().setEncodesprite(true); // } else if (s.equalsIgnoreCase("-nosuggestengine")) { // OptionFlags.getInstance().setUseSuggestEngine(false); } else if (s.equalsIgnoreCase("-printfonts")) { OptionFlags.getInstance().setPrintFonts(true); } else if (s.equalsIgnoreCase("-dumphtmlstats")) { OptionFlags.getInstance().setDumpHtmlStats(true); } else if (s.equalsIgnoreCase("-dumpstats")) { OptionFlags.getInstance().setDumpStats(true); } else if (s.equalsIgnoreCase("-loopstats")) { OptionFlags.getInstance().setLoopStats(true); } else if (s.equalsIgnoreCase("-enablestats")) { OptionFlags.getInstance().setEnableStats(true); } else if (s.equalsIgnoreCase("-disablestats")) { OptionFlags.getInstance().setEnableStats(false); } else if (s.equalsIgnoreCase("-extractstdlib")) { OptionFlags.getInstance().setExtractStdLib(true); } else if (s.equalsIgnoreCase("-stdlib")) { OptionFlags.getInstance().setStdLib(true); } else if (s.equalsIgnoreCase("-clipboard")) { OptionFlags.getInstance().setClipboard(true); } else if (s.equalsIgnoreCase("-clipboardloop")) { OptionFlags.getInstance().setClipboardLoop(true); } else if (s.equalsIgnoreCase("-htmlstats")) { StatsUtils.setHtmlStats(true); } else if (s.equalsIgnoreCase("-xmlstats")) { StatsUtils.setXmlStats(true); } else if (s.equalsIgnoreCase("-realtimestats")) { StatsUtils.setRealTimeStats(true); } else if (s.equalsIgnoreCase("-useseparatorminus")) { OptionFlags.getInstance().setFileSeparator("-"); } else if (s.equalsIgnoreCase("-splash")) { splash = true; } else if (s.equalsIgnoreCase("-progress")) { textProgressBar = true; } else if (s.equalsIgnoreCase("-nometadata")) { hideMetadata = true; } else if (s.equalsIgnoreCase("-preproc")) { preprocessorOutput = OptionPreprocOutputMode.NORMAL; } else if (s.equalsIgnoreCase("-cypher")) { preprocessorOutput = OptionPreprocOutputMode.CYPHER; } else if (s.equalsIgnoreCase("-checkmetadata")) { checkMetadata = true; } else if (s.equalsIgnoreCase("-pipeimageindex")) { i++; if (i == arg.length) { continue; } final String nb = arg[i]; if (nb.matches("\\d+")) { this.imageIndex = Integer.parseInt(nb); } } else if (StringUtils.goLowerCase(s).startsWith("-ftp")) { final int x = s.indexOf(':'); if (x == -1) { this.ftpPort = 4242; } else { this.ftpPort = Integer.parseInt(s.substring(x + 1)); } } else if (s.startsWith("-c")) { s = s.substring(2); config.add(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(s)); } else { result.add(s); } } } public int getFtpPort() { return ftpPort; } private void addInConfig(final FileReader source) throws IOException { BufferedReader br = null; try { br = new BufferedReader(source); String s = null; while ((s = br.readLine()) != null) { config.add(s); } } finally { if (br != null) { br.close(); } } } public void initConfig(String filename) throws IOException { addInConfig(new FileReader(filename)); } private void initInclude(String filename) throws IOException { if (filename.contains("*")) { final FileGroup group = new FileGroup(filename, Collections. emptyList(), null); for (File f : group.getFiles()) { addInConfig(new FileReader(f)); } } else { addInConfig(new FileReader(filename)); } } private void manageDefine(String s) { final Pattern2 p = MyPattern.cmpile("^(\\w+)(?:=(.*))?$"); final Matcher2 m = p.matcher(s); if (m.find()) { define(m.group(1), m.group(2)); } } private void manageSkinParam(String s) { final Pattern2 p = MyPattern.cmpile("^(\\w+)(?:=(.*))?$"); final Matcher2 m = p.matcher(s); if (m.find()) { skinParam(m.group(1), m.group(2)); } } private void skinParam(String var, String value) { if (var != null && value != null) { config.add("skinparamlocked " + var + " " + value); } } public final File getOutputDir() { return outputDir; } public final static String getPattern() { return "(?i)^.*\\.(txt|tex|java|htm|html|c|h|cpp|apt|pu|pump|hpp|hh)$"; } public void setOutputDir(File f) { outputDir = f; } public final List getExcludes() { return Collections.unmodifiableList(excludes); } public Defines getDefaultDefines(File f) { final Defines result = Defines.createWithFileName(f); for (Map.Entry ent : defines.entrySet()) { result.define(ent.getKey(), Arrays.asList(ent.getValue()), false); } return result; } public Defines getDefaultDefines() { final Defines result = Defines.createEmpty(); result.overrideFilename(filename); for (Map.Entry ent : defines.entrySet()) { result.define(ent.getKey(), Arrays.asList(ent.getValue()), false); } return result; } public void define(String name, String value) { defines.put(name, value); } public List getConfig() { return Collections.unmodifiableList(config); } public final List getResult() { return Collections.unmodifiableList(result); } public final String getCharset() { return charset; } public void setCharset(String s) { this.charset = s; } public final boolean isComputeurl() { return computeurl; } public final boolean isDecodeurl() { return decodeurl; } public final boolean isPipe() { return pipe; } public final boolean isPipeMap() { return pipeMap; } public final boolean isSyntax() { return syntax; } public final boolean isPattern() { return pattern; } public FileFormatOption getFileFormatOption() { if (debugsvek) { fileFormatOption.setDebugSvek(true); } if (hideMetadata) { fileFormatOption.hideMetadata(); } return fileFormatOption; } public final boolean isDuration() { return duration; } public final int getNbThreads() { return nbThreads; } public final void setNbThreads(int nb) { this.nbThreads = nb; } public static int defaultNbThreads() { return Runtime.getRuntime().availableProcessors(); } public final boolean isCheckOnly() { return checkOnly; } public final void setCheckOnly(boolean checkOnly) { this.checkOnly = checkOnly; } public final boolean isFailfastOrFailfast2() { return failfast || failfast2; } public final boolean isFailfast2() { return failfast2; } public final void setFailfast(boolean failfast) { this.failfast = failfast; } public final void setFailfast2(boolean failfast2) { this.failfast2 = failfast2; } public final File getOutputFile() { return outputFile; } public final void setDebugSvek(boolean debugsvek) { this.debugsvek = debugsvek; } boolean isDebugSvek() { return debugsvek; } public final boolean isSplash() { return splash; } public final void setSplash(boolean splash) { this.splash = splash; } public final boolean isTextProgressBar() { return textProgressBar; } public String getPipeDelimitor() { return pipeDelimitor; } public final boolean isPipeNoStdErr() { return pipeNoStdErr; } public final int getImageIndex() { return imageIndex; } public final void setFilename(String filename) { this.filename = filename; } public final boolean isCheckMetadata() { return checkMetadata; } public final OptionPreprocOutputMode getPreprocessorOutputMode() { return preprocessorOutput; } // public final void setPreprocessorOutput(boolean preprocessorOutput) { // this.preprocessorOutput = preprocessorOutput; // } }