Skip to content

Commit 26e7d96

Browse files
authored
Split project settings and app settings into separate classes (#724)
* Split project settings and app settings into separate classes Move port validation to GripServer and common CLI to the helper class Make project settings reflect command-line port option No longer serializes the server port. Use the command-line option or the settings dialog to set it. Fixes #708 Enable projects to be uploaded via HTTP in UI mode * Move *BeanInfo classes to UI module. Fixes #717 * Ignore all unknown tags in save files
1 parent 92c589c commit 26e7d96

23 files changed

+327
-163
lines changed

core/src/main/java/edu/wpi/grip/core/CoreCommandLineHelper.java

+61
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
package edu.wpi.grip.core;
22

3+
import edu.wpi.grip.core.events.AppSettingsChangedEvent;
4+
import edu.wpi.grip.core.http.GripServer;
5+
import edu.wpi.grip.core.serialization.Project;
6+
import edu.wpi.grip.core.settings.AppSettings;
7+
import edu.wpi.grip.core.settings.SettingsProvider;
8+
39
import com.google.common.annotations.VisibleForTesting;
10+
import com.google.common.eventbus.EventBus;
411

512
import org.apache.commons.cli.CommandLine;
613
import org.apache.commons.cli.DefaultParser;
@@ -9,13 +16,19 @@
916
import org.apache.commons.cli.Options;
1017
import org.apache.commons.cli.ParseException;
1118

19+
import java.io.File;
20+
import java.io.IOException;
1221
import java.util.List;
22+
import java.util.logging.Level;
23+
import java.util.logging.Logger;
1324

1425
/**
1526
* A helper class for command line options for GRIP.
1627
*/
1728
public class CoreCommandLineHelper {
1829

30+
private static final Logger logger = Logger.getLogger("CommandLine");
31+
1932
public static final String FILE_OPTION = "f"; // "f" for "file"
2033
public static final String PORT_OPTION = "p"; // "p" for "port"
2134
public static final String HELP_OPTION = "h"; // "h" for "help" (this is standard)
@@ -134,4 +147,52 @@ void exit() {
134147
System.exit(0);
135148
}
136149

150+
/**
151+
* Tries to load a file from the command line arguments. Does nothing if no file was specified.
152+
*
153+
* @param args the parsed command line arguments
154+
* @param project the project to load the file into
155+
*
156+
* @throws IOException if the file couldn't be loaded
157+
*/
158+
public void loadFile(CommandLine args, Project project) throws IOException {
159+
if (args.hasOption(FILE_OPTION)) {
160+
String file = args.getOptionValue(FILE_OPTION);
161+
try {
162+
project.open(new File(file));
163+
} catch (IOException e) {
164+
logger.log(Level.WARNING, "Invalid file: " + file, e);
165+
throw e;
166+
}
167+
}
168+
}
169+
170+
/**
171+
* Tries to set the internal server port from the command line arguments. Does nothing if no port
172+
* was specified.
173+
*
174+
* @param args the parsed command line arguments
175+
* @param settingsProvider the app's settings provider
176+
* @param eventBus the app's event bus
177+
*/
178+
public void setServerPort(CommandLine args,
179+
SettingsProvider settingsProvider,
180+
EventBus eventBus) {
181+
if (args.hasOption(PORT_OPTION)) {
182+
try {
183+
int port = Integer.parseInt(args.getOptionValue(PORT_OPTION));
184+
if (!GripServer.isPortValid(port)) {
185+
logger.warning("Not a valid port: " + port);
186+
} else {
187+
logger.info("Setting server port: " + port);
188+
AppSettings settings = settingsProvider.getAppSettings().clone();
189+
settings.setServerPort(port);
190+
eventBus.post(new AppSettingsChangedEvent(settings));
191+
}
192+
} catch (NumberFormatException e) {
193+
logger.warning("Not a valid port: " + args.getOptionValue(PORT_OPTION));
194+
}
195+
}
196+
}
197+
137198
}

core/src/main/java/edu/wpi/grip/core/Main.java

+5-25
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import edu.wpi.grip.core.operations.Operations;
99
import edu.wpi.grip.core.operations.network.GripNetworkModule;
1010
import edu.wpi.grip.core.serialization.Project;
11+
import edu.wpi.grip.core.settings.SettingsProvider;
1112
import edu.wpi.grip.core.sources.GripSourcesHardwareModule;
1213

1314
import com.google.common.eventbus.EventBus;
@@ -19,7 +20,6 @@
1920

2021
import org.apache.commons.cli.CommandLine;
2122

22-
import java.io.File;
2323
import java.io.IOException;
2424
import java.util.logging.Level;
2525
import java.util.logging.Logger;
@@ -38,6 +38,8 @@ public class Main {
3838
@Inject
3939
private PipelineRunner pipelineRunner;
4040
@Inject
41+
private SettingsProvider settingsProvider;
42+
@Inject
4143
private EventBus eventBus;
4244
@Inject
4345
private Operations operations;
@@ -66,30 +68,8 @@ public void start(String[] args) throws IOException, InterruptedException {
6668
CoreCommandLineHelper commandLineHelper = new CoreCommandLineHelper();
6769
CommandLine parsedArgs = commandLineHelper.parse(args);
6870

69-
// Parse the save file option
70-
if (parsedArgs.hasOption(CoreCommandLineHelper.FILE_OPTION)) {
71-
// Open a project from a .grip file specified on the command line
72-
String file = parsedArgs.getOptionValue(CoreCommandLineHelper.FILE_OPTION);
73-
logger.log(Level.INFO, "Loading file " + file);
74-
project.open(new File(file));
75-
}
76-
77-
// Set the port AFTER loading the project to override the saved port number
78-
if (parsedArgs.hasOption(CoreCommandLineHelper.PORT_OPTION)) {
79-
try {
80-
int port = Integer.parseInt(parsedArgs.getOptionValue(CoreCommandLineHelper.PORT_OPTION));
81-
if (port < 1024 || port > 65535) {
82-
logger.warning("Not a valid port: " + port);
83-
} else {
84-
// Valid port; set it (Note: this doesn't check to see if the port is available)
85-
logger.info("Running server on port " + port);
86-
gripServer.setPort(port);
87-
}
88-
} catch (NumberFormatException e) {
89-
logger.warning(
90-
"Not a valid port: " + parsedArgs.getOptionValue(CoreCommandLineHelper.PORT_OPTION));
91-
}
92-
}
71+
commandLineHelper.loadFile(parsedArgs, project);
72+
commandLineHelper.setServerPort(parsedArgs, settingsProvider, eventBus);
9373

9474
// This will throw an exception if the port specified by the save file or command line
9575
// argument is already taken. Since we have to have the server running to handle remotely

core/src/main/java/edu/wpi/grip/core/Pipeline.java

+15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package edu.wpi.grip.core;
22

3+
import edu.wpi.grip.core.events.AppSettingsChangedEvent;
34
import edu.wpi.grip.core.events.ConnectionAddedEvent;
45
import edu.wpi.grip.core.events.ConnectionRemovedEvent;
56
import edu.wpi.grip.core.events.ProjectSettingsChangedEvent;
@@ -8,6 +9,7 @@
89
import edu.wpi.grip.core.events.StepAddedEvent;
910
import edu.wpi.grip.core.events.StepMovedEvent;
1011
import edu.wpi.grip.core.events.StepRemovedEvent;
12+
import edu.wpi.grip.core.settings.AppSettings;
1113
import edu.wpi.grip.core.settings.ProjectSettings;
1214
import edu.wpi.grip.core.settings.SettingsProvider;
1315
import edu.wpi.grip.core.sockets.InputSocket;
@@ -64,6 +66,8 @@ public class Pipeline implements ConnectionValidator, SettingsProvider, StepInde
6466
private transient EventBus eventBus;
6567
private final transient ReadWriteLock stepLock = new ReentrantReadWriteLock();
6668
private ProjectSettings settings = new ProjectSettings();
69+
@XStreamOmitField
70+
private transient AppSettings appSettings = new AppSettings(); // Do not serialize this field
6771

6872
/**
6973
* Locks the resource with the specified lock and performs the function. When the function is
@@ -188,6 +192,11 @@ public ProjectSettings getProjectSettings() {
188192
return settings;
189193
}
190194

195+
@Override
196+
public AppSettings getAppSettings() {
197+
return appSettings;
198+
}
199+
191200
@SuppressWarnings("unchecked")
192201
@Override
193202
public boolean canConnect(OutputSocket<?> outputSocket, InputSocket<?> inputSocket) {
@@ -391,4 +400,10 @@ public void onConnectionRemoved(ConnectionRemovedEvent event) {
391400
public void onProjectSettingsChanged(ProjectSettingsChangedEvent event) {
392401
this.settings = event.getProjectSettings();
393402
}
403+
404+
@Subscribe
405+
public void onAppSettingsChanged(AppSettingsChangedEvent event) {
406+
this.appSettings = event.getAppSettings();
407+
}
408+
394409
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package edu.wpi.grip.core.events;
2+
3+
import edu.wpi.grip.core.settings.AppSettings;
4+
5+
import static com.google.common.base.Preconditions.checkNotNull;
6+
7+
/**
8+
* An event fired when the app settings are changed.
9+
*/
10+
public class AppSettingsChangedEvent {
11+
12+
private final AppSettings appSettings;
13+
14+
public AppSettingsChangedEvent(AppSettings appSettings) {
15+
this.appSettings = checkNotNull(appSettings, "appSettings");
16+
}
17+
18+
public AppSettings getAppSettings() {
19+
return appSettings;
20+
}
21+
22+
}

core/src/main/java/edu/wpi/grip/core/http/GripServer.java

+42-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package edu.wpi.grip.core.http;
22

3-
import edu.wpi.grip.core.events.ProjectSettingsChangedEvent;
3+
import edu.wpi.grip.core.events.AppSettingsChangedEvent;
44
import edu.wpi.grip.core.exception.GripServerException;
55
import edu.wpi.grip.core.settings.SettingsProvider;
66

@@ -48,11 +48,17 @@ public class GripServer {
4848
* Possible lifecycle states of the server.
4949
*/
5050
public enum State {
51-
/** The server has not been started yet. */
51+
/**
52+
* The server has not been started yet.
53+
*/
5254
PRE_RUN,
53-
/** The server is currently running. */
55+
/**
56+
* The server is currently running.
57+
*/
5458
RUNNING,
55-
/** The server was running and has been stopped. */
59+
/**
60+
* The server was running and has been stopped.
61+
*/
5662
STOPPED
5763
}
5864

@@ -100,6 +106,32 @@ public enum State {
100106
*/
101107
public static final String DATA_PATH = ROOT_PATH + "/data";
102108

109+
/**
110+
* The default port the server should run on.
111+
*/
112+
public static final int DEFAULT_PORT = 8080;
113+
114+
/**
115+
* The lowest valid TCP port number.
116+
*/
117+
private static final int MIN_PORT = 1024;
118+
119+
/**
120+
* The highest valid TCP port number.
121+
*/
122+
private static final int MAX_PORT = 65535;
123+
124+
/**
125+
* Checks if the given TCP port is valid for a server to run on. This doesn't check availability.
126+
*
127+
* @param port the port to check
128+
*
129+
* @return true if the port is valid, false if not
130+
*/
131+
public static boolean isPortValid(int port) {
132+
return port >= MIN_PORT && port <= MAX_PORT;
133+
}
134+
103135
public interface JettyServerFactory {
104136
Server create(int port);
105137
}
@@ -116,7 +148,7 @@ public Server create(int port) {
116148
GripServer(ContextStore contextStore,
117149
JettyServerFactory serverFactory,
118150
SettingsProvider settingsProvider) {
119-
this.port = settingsProvider.getProjectSettings().getServerPort();
151+
this.port = settingsProvider.getAppSettings().getServerPort();
120152
this.serverFactory = serverFactory;
121153
this.server = serverFactory.create(port);
122154
this.server.setHandler(handlers);
@@ -213,6 +245,9 @@ public State getState() {
213245
* @param port the new port to run on.
214246
*/
215247
public void setPort(int port) {
248+
if (!isPortValid(port)) {
249+
throw new IllegalArgumentException("Invalid port: " + port);
250+
}
216251
stop();
217252
server = serverFactory.create(port);
218253
server.setHandler(handlers);
@@ -228,11 +263,10 @@ public int getPort() {
228263
}
229264

230265
@Subscribe
231-
public void settingsChanged(ProjectSettingsChangedEvent event) {
232-
int port = event.getProjectSettings().getServerPort();
266+
public void settingsChanged(AppSettingsChangedEvent event) {
267+
int port = event.getAppSettings().getServerPort();
233268
if (port != getPort()) {
234269
setPort(port);
235-
start();
236270
}
237271
}
238272

Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package edu.wpi.grip.core.http;
22

33
import edu.wpi.grip.core.serialization.Project;
4-
import edu.wpi.grip.core.util.GripMode;
54

65
import com.google.inject.Inject;
76
import com.google.inject.Singleton;
@@ -22,13 +21,11 @@
2221
public class HttpPipelineSwitcher extends PedanticHandler {
2322

2423
private final Project project;
25-
private final GripMode mode;
2624

2725
@Inject
28-
HttpPipelineSwitcher(ContextStore store, Project project, GripMode mode) {
26+
HttpPipelineSwitcher(ContextStore store, Project project) {
2927
super(store, GripServer.PIPELINE_UPLOAD_PATH, true);
3028
this.project = project;
31-
this.mode = mode;
3229
}
3330

3431
@Override
@@ -41,24 +38,8 @@ protected void handleIfPassed(String target,
4138
baseRequest.setHandled(true);
4239
return;
4340
}
44-
switch (mode) {
45-
case HEADLESS:
46-
project.open(new String(IOUtils.toByteArray(request.getInputStream()), "UTF-8"));
47-
response.setStatus(HttpServletResponse.SC_CREATED);
48-
baseRequest.setHandled(true);
49-
break;
50-
case GUI:
51-
// Don't run in GUI mode, it doesn't make much sense and can easily deadlock if pipelines
52-
// are rapidly posted.
53-
// Intentional fall-through to default
54-
default:
55-
// Don't know the mode or the mode is unsupported; let the client know
56-
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
57-
sendTextContent(response,
58-
String.format("GRIP is not in the correct mode: should be HEADLESS, but is %s", mode),
59-
CONTENT_TYPE_PLAIN_TEXT);
60-
baseRequest.setHandled(true);
61-
break;
62-
}
41+
project.open(new String(IOUtils.toByteArray(request.getInputStream()), "UTF-8"));
42+
response.setStatus(HttpServletResponse.SC_CREATED);
43+
baseRequest.setHandled(true);
6344
}
6445
}

core/src/main/java/edu/wpi/grip/core/serialization/Project.java

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public void initialize(StepConverter stepConverter,
4949
ConnectionConverter connectionConverter,
5050
ProjectSettingsConverter projectSettingsConverter) {
5151
xstream.setMode(XStream.NO_REFERENCES);
52+
xstream.ignoreUnknownElements(); // ignores all unknown tags
5253
xstream.registerConverter(stepConverter);
5354
xstream.registerConverter(sourceConverter);
5455
xstream.registerConverter(socketConverter);

0 commit comments

Comments
 (0)