View Javadoc
1   
2   package com.nilhcem.fakesmtp.core;
3   
4   import ch.qos.logback.classic.Level;
5   import ch.qos.logback.classic.Logger;
6   import com.nilhcem.fakesmtp.model.UIModel;
7   import org.apache.commons.cli.CommandLine;
8   import org.apache.commons.cli.CommandLineParser;
9   import org.apache.commons.cli.GnuParser;
10  import org.apache.commons.cli.HelpFormatter;
11  import org.apache.commons.cli.Options;
12  import org.apache.commons.cli.ParseException;
13  import org.slf4j.LoggerFactory;
14  
15  import java.util.ArrayList;
16  import java.util.Arrays;
17  import java.util.List;
18  import java.util.Locale;
19  
20  /**
21   * Handles command line arguments.
22   *
23   * @author Nilhcem
24   * @since 1.3
25   */
26  public enum ArgsHandler {
27  	INSTANCE;
28  
29  	private static final String OPT_EMAILS_DIR_SHORT = "o";
30  	private static final String OPT_EMAILS_DIR_LONG = "output-dir";
31  	private static final String OPT_EMAILS_DESC = "Emails output directory";
32  
33  	private static final String OPT_AUTOSTART_SHORT = "s";
34  	private static final String OPT_AUTOSTART_LONG = "start-server";
35  	private static final String OPT_AUTOSTART_DESC = "Automatically starts the SMTP server at launch";
36  
37  	private static final String OPT_PORT_SHORT = "p";
38  	private static final String OPT_PORT_LONG = "port";
39  	private static final String OPT_PORT_DESC = "SMTP port number";
40  
41  	private static final String OPT_BACKGROUNDSTART_SHORT = "b";
42  	private static final String OPT_BACKGROUNDSTART_LONG = "background";
43  	private static final String OPT_BACKGROUNDSTART_DESC = "If specified, does not start the GUI. Must be used with the -" + OPT_AUTOSTART_SHORT + " (--" +  OPT_AUTOSTART_LONG + ") argument";
44  
45  	private static final String OPT_RELAYDOMAINS_SHORT = "r";
46  	private static final String OPT_RELAYDOMAINS_LONG = "relay-domains";
47  	private static final String OPT_RELAYDOMAINS_DESC = "Comma separated email domain(s) for which relay is accepted. If not specified, relays to any domain. If specified, relays only emails matching these domain(s), dropping (not saving) others";
48  	private static final String OPT_RELAYDOMAINS_SEPARATOR = ",";
49  
50  	private static final String OPT_MEMORYMODE_SHORT = "m";
51  	private static final String OPT_MEMORYMODE_LONG = "memory-mode";
52  	private static final String OPT_MEMORYMODE_DESC = "Disable the persistence in order to avoid the overhead that it adds";
53  
54  	private static final String OPT_BINDADDRESS_SHORT = "a";
55  	private static final String OPT_BINDADDRESS_LONG = "bind-address";
56  	private static final String OPT_BINDADDRESS_DESC = "IP address or hostname to bind to. Binds to all local IP addresses if not specified. Only works together with the -" + OPT_BACKGROUNDSTART_SHORT + " (--" +  OPT_BACKGROUNDSTART_LONG + ") argument.";
57  
58  	private static final String OPT_EMLVIEWER_SHORT = "e";
59  	private static final String OPT_EMLVIEWER_LONG = "eml-viewer";
60  	private static final String OPT_EMLVIEWER_DESC = "Executable of program used for viewing emails";
61  
62  	private final Options options;
63  
64  	private String port;
65  	private String bindAddress;
66  	private String outputDirectory;
67  	private String emlViewer;
68  	private boolean backgroundStart;
69  	private boolean startServerAtLaunch;
70  	private boolean memoryModeEnabled;
71  
72  	/**
73  	 * Handles command line arguments.
74  	 */
75  	ArgsHandler() {
76  		options = new Options();
77  		options.addOption(OPT_EMAILS_DIR_SHORT, OPT_EMAILS_DIR_LONG, true, OPT_EMAILS_DESC);
78  		options.addOption(OPT_AUTOSTART_SHORT, OPT_AUTOSTART_LONG, false, OPT_AUTOSTART_DESC);
79  		options.addOption(OPT_PORT_SHORT, OPT_PORT_LONG, true, OPT_PORT_DESC);
80  		options.addOption(OPT_BINDADDRESS_SHORT, OPT_BINDADDRESS_LONG, true, OPT_BINDADDRESS_DESC);
81  		options.addOption(OPT_BACKGROUNDSTART_SHORT, OPT_BACKGROUNDSTART_LONG, false, OPT_BACKGROUNDSTART_DESC);
82  		options.addOption(OPT_RELAYDOMAINS_SHORT, OPT_RELAYDOMAINS_LONG, true, OPT_RELAYDOMAINS_DESC);
83  		options.addOption(OPT_MEMORYMODE_SHORT, OPT_MEMORYMODE_LONG, false, OPT_MEMORYMODE_DESC);
84  		options.addOption(OPT_EMLVIEWER_SHORT, OPT_EMLVIEWER_LONG, true, OPT_EMLVIEWER_DESC);
85  	}
86  
87  	/**
88  	 * Interprets command line arguments.
89  	 *
90  	 * @param args program's arguments.
91  	 * @throws ParseException when arguments are invalid.
92  	 */
93  	public void handleArgs(String[] args) throws ParseException {
94  		CommandLineParser parser = new GnuParser();
95  		CommandLine cmd = parser.parse(options, args);
96  
97  		outputDirectory = cmd.getOptionValue(OPT_EMAILS_DIR_SHORT);
98  		if (outputDirectory != null) {
99  			UIModel.INSTANCE.setSavePath(outputDirectory);
100 		}
101 
102 		port = cmd.getOptionValue(OPT_PORT_SHORT);
103 		bindAddress = cmd.getOptionValue(OPT_BINDADDRESS_SHORT);
104 		startServerAtLaunch = cmd.hasOption(OPT_AUTOSTART_SHORT);
105 		backgroundStart = cmd.hasOption(OPT_BACKGROUNDSTART_SHORT);
106 		memoryModeEnabled = cmd.hasOption(OPT_MEMORYMODE_SHORT);
107 		emlViewer = cmd.getOptionValue(OPT_EMLVIEWER_SHORT);
108 
109 		// Change SMTP server log level to info if memory mode was enabled to improve performance
110 		if (memoryModeEnabled) {
111 			((Logger) LoggerFactory.getLogger(org.subethamail.smtp.server.Session.class)).setLevel(Level.INFO);
112 		}
113 
114 		String relaydomains = cmd.getOptionValue(OPT_RELAYDOMAINS_SHORT);
115 		if (relaydomains != null) {
116 			List<String> domains = new ArrayList<String>();
117 			for (String domain : Arrays.asList(relaydomains.split(OPT_RELAYDOMAINS_SEPARATOR))) {
118 				domains.add(domain.trim());
119 			}
120 			UIModel.INSTANCE.setRelayDomains(domains);
121 		}
122 	}
123 
124 	/**
125 	 * Displays the app's usage in the standard output.
126 	 */
127 	public void displayUsage() {
128 		HelpFormatter formatter = new HelpFormatter();
129 		formatter.printHelp(String.format(Locale.US, "java -jar %s [OPTION]...", getJarName()), options);
130 	}
131 
132 	/**
133 	 * @return whether or not the SMTP server must be started automatically at launch.
134 	 */
135 	public boolean shouldStartServerAtLaunch() {
136 		return startServerAtLaunch;
137 	}
138 
139 	/**
140 	 * @return whether or not the SMTP server must be running without a GUI, only if started at launch (if {@code shouldStartServerAtLaunch()} returns true}).
141 	 * @see #shouldStartServerAtLaunch
142 	 */
143 	public boolean shouldStartInBackground() {
144 		return startServerAtLaunch && backgroundStart;
145 	}
146 
147 	/**
148 	 * @return the port, as specified by the user, or a {@code null} string if unspecified.
149 	 */
150 	public String getPort() {
151 		return port;
152 	}
153 
154 	/**
155 	 * @return the bind address, as specified by the user, or a {@code null} string if unspecified.
156 	 */
157 	public String getBindAddress() {
158 		return bindAddress;
159 	}
160 
161 	/**
162 	 * @return the output directory, as specified by the user, or a {@code null} string if unspecified.
163 	 */
164 	public String getOutputDirectory() {
165 		return outputDirectory;
166 	}
167 
168 	/**
169 	 * @return whether or not the SMTP server should disable the persistence in order to avoid the overhead that it adds.
170 	 * This is particularly useful when we launch performance tests that massively send emails.
171 	 */
172 	public boolean memoryModeEnabled() {
173 		return memoryModeEnabled;
174 	}
175 
176 	/**
177 	 * @return the name of executable used for viewing eml files, as specified by the user, or a {@code null} string if unspecified.
178 	 */
179 	public String getEmlViewer() {
180 		return emlViewer;
181 	}
182 
183 	/**
184 	 * @return the file name of the program.
185 	 */
186 	private String getJarName() {
187 		return new java.io.File(
188 				ArgsHandler.class.getProtectionDomain()
189 				.getCodeSource()
190 				.getLocation()
191 				.getPath())
192 		.getName();
193 	}
194 }