Skip to content

Commit ebe2d79

Browse files
authored
Merge pull request #98 from cisco-system-traffic-generator/trex-daemon-control
Trex daemon control
2 parents 617e9d6 + e7bd365 commit ebe2d79

17 files changed

+1468
-2
lines changed

build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ dependencies {
8888
compile group: 'org.testng', name: 'testng', version:'6.9.10'
8989
compile group: 'net.java.dev.jna', name: 'jna', version: '4.4.0'
9090
compile group: 'net.java.dev.jna', name: 'jna-platform', version: '4.4.0'
91-
91+
compile group: 'com.github.arteam', name: 'simple-json-rpc-client', version: '0.9'
92+
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.6'
9293

9394
testCompile group: 'junit', name: 'junit', version: '4.12'
9495
testCompile "org.testfx:testfx-core:4.0.+"

src/main/java/com/exalttech/trex/application/guice/StatelessGUIModule.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.cisco.trex.stl.gui.storages.StatsStorage;
66
import com.cisco.trex.stl.gui.util.RunningConfiguration;
77
import com.exalttech.trex.core.RPCMethods;
8+
import com.exalttech.trex.ui.controllers.daemon.InterfaceInfoProvider;
89
import com.exalttech.trex.ui.views.streams.builder.ProtocolDataView;
910
import com.google.common.eventbus.EventBus;
1011
import com.google.inject.AbstractModule;
@@ -20,5 +21,6 @@ protected void configure() {
2021
bind(ProtocolDataView.class).toProvider(ProtocolDataViewProvider.class);
2122
bind(StatsStorage.class).in(Singleton.class);
2223
bind(IDataCompressor.class).to(TRexDataCompressor.class);
24+
bind(InterfaceInfoProvider.class).in(Singleton.class);
2325
}
2426
}

src/main/java/com/exalttech/trex/ui/controllers/MainViewController.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ public class MainViewController implements Initializable, EventHandler<KeyEvent>
220220
private DialogWindow captureWindow;
221221
private DialogWindow preferencesWindow;
222222
private DialogWindow dashboardWindow;
223+
private DialogWindow trexDaemonWindow;
223224

224225
private SystemInfoReq systemInfoReq = null;
225226
private PacketTableView tableView;
@@ -1795,6 +1796,32 @@ public void handleDevicesTreeArrowClicked(MouseEvent event) {
17951796
treeviewOpened = !treeviewOpened;
17961797
}
17971798

1799+
/**
1800+
* Handle menu item connect to TRex Daemon
1801+
*
1802+
* @param actionEvent
1803+
*/
1804+
@FXML
1805+
public void handleTRexDaemonItemClick(ActionEvent actionEvent) {
1806+
try {
1807+
if (trexDaemonWindow == null) {
1808+
trexDaemonWindow = new DialogWindow(
1809+
"TRexDaemonDialog.fxml",
1810+
"TRex Daemon",
1811+
50,
1812+
10,
1813+
1200,
1814+
750,
1815+
true,
1816+
TrexApp.getPrimaryStage()
1817+
);
1818+
}
1819+
trexDaemonWindow.show(false);
1820+
} catch (IOException ex) {
1821+
LOG.error("Error opening TRex Daemon view", ex);
1822+
}
1823+
}
1824+
17981825
/**
17991826
* Enumerator that present Context menu item type
18001827
*/
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
package com.exalttech.trex.ui.controllers.daemon;
2+
3+
import com.google.common.net.InetAddresses;
4+
import javafx.beans.property.SimpleBooleanProperty;
5+
import javafx.beans.value.ObservableBooleanValue;
6+
import javafx.collections.FXCollections;
7+
import javafx.collections.ObservableList;
8+
9+
import java.text.MessageFormat;
10+
import java.util.*;
11+
import java.util.regex.Pattern;
12+
import java.util.stream.Collectors;
13+
14+
15+
public class ConfigNode {
16+
@FunctionalInterface
17+
public interface Validator {
18+
/**
19+
* Validates given value. If doesn't throw then it's value is valid
20+
* @param value
21+
* @throws Exception
22+
*/
23+
void validate(Object value) throws Exception;
24+
}
25+
26+
private MetaField meta;
27+
28+
private ObservableList<ConfigNode> children = FXCollections.observableArrayList();
29+
private ConfigNode parent;
30+
31+
private boolean removable;
32+
private SimpleBooleanProperty mandatoryProperty = new SimpleBooleanProperty();
33+
34+
private Object value;
35+
36+
private Map<MetaField.Type, Validator> validationMap = new HashMap<>();
37+
38+
39+
public ConfigNode(MetaField meta, ConfigNode parent, boolean removable) {
40+
this.removable = removable;
41+
this.parent = parent;
42+
this.meta = meta;
43+
44+
initValidator();
45+
46+
if (getType() == MetaField.Type.OBJECT) {
47+
this.meta.attributes.forEach(metaField -> {
48+
ConfigNode child = new ConfigNode(metaField, this);
49+
this.children.add(child);
50+
});
51+
}
52+
53+
mandatoryProperty.setValue(isMandatory());
54+
55+
}
56+
57+
public ConfigNode(MetaField meta, ConfigNode parent) {
58+
this(meta, parent, false);
59+
}
60+
61+
public ConfigNode(MetaField meta) {
62+
this(meta, null, false);
63+
}
64+
65+
private void initValidator() {
66+
validationMap.put(MetaField.Type.STRING, val -> { String casted = (String) value; });
67+
validationMap.put(MetaField.Type.NUMBER, val -> Integer.parseInt((String) value));
68+
validationMap.put(MetaField.Type.FLOAT, val -> Float.parseFloat((String) value));
69+
validationMap.put(MetaField.Type.BOOLEAN, val -> { boolean casted = (boolean) value; });
70+
validationMap.put(MetaField.Type.IP, val -> InetAddresses.forString((String) value));
71+
validationMap.put(MetaField.Type.MAC, val -> {
72+
if (!Pattern.matches("^([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})$", (String) value)) {
73+
throw new Exception();
74+
}
75+
});
76+
77+
validationMap.put(MetaField.Type.LIST, val -> {
78+
for (ConfigNode node : children) {
79+
if (!node.validateValue()) {
80+
throw new Exception();
81+
}
82+
}
83+
});
84+
85+
validationMap.put(MetaField.Type.OBJECT, val -> {
86+
for (ConfigNode node : children) {
87+
if (!node.validateValue()) {
88+
throw new Exception();
89+
}
90+
}
91+
});
92+
}
93+
94+
public MetaField.Type getType() {
95+
return meta.type;
96+
}
97+
98+
public boolean isMandatory() {
99+
if (meta.mandatory_if_not_set == null) {
100+
return meta.mandatory;
101+
} else {
102+
return !isDependencySpecified();
103+
}
104+
}
105+
106+
private boolean isDependencySpecified() {
107+
return parent.getChildren()
108+
.stream()
109+
.filter(sibling -> sibling.getId().equals(meta.mandatory_if_not_set))
110+
.anyMatch(sibling -> sibling.getValue() != null);
111+
}
112+
113+
public ObservableBooleanValue mandatoryProperty() {
114+
return mandatoryProperty;
115+
}
116+
117+
public String getDefaultValue() {
118+
return meta.default_value;
119+
}
120+
121+
public String getName() {
122+
return meta.name;
123+
}
124+
125+
public String getDescription() {
126+
return meta.description;
127+
}
128+
129+
public String getId() {
130+
return meta.id;
131+
}
132+
133+
public void setValue(Object newValue) {
134+
if (getType() == MetaField.Type.LIST) {
135+
List<Object> newChildren = ((List<Object>) newValue);
136+
newChildren.forEach(x -> {
137+
ConfigNode configNode = addListItem();
138+
configNode.setValue(x);
139+
});
140+
} else if (getType() == MetaField.Type.OBJECT){
141+
Map<String, Object> newMap = (Map<String, Object>) newValue;
142+
for (Map.Entry<String, Object> entry : newMap.entrySet()) {
143+
children.stream()
144+
.filter(x -> x.getId().equals(entry.getKey()))
145+
.findFirst()
146+
.ifPresent(x -> x.setValue(entry.getValue()));
147+
}
148+
} else {
149+
value = newValue;
150+
}
151+
152+
if (getParent() != null) {
153+
getParent().updateDependencies();
154+
}
155+
}
156+
157+
public Object getValue() {
158+
if (getType() == MetaField.Type.LIST) {
159+
List<Object> childrenValues = getChildren().stream()
160+
.map(ConfigNode::getValue)
161+
.filter(Objects::nonNull)
162+
.collect(Collectors.toList());
163+
164+
if (childrenValues.isEmpty()) {
165+
return null;
166+
}
167+
return childrenValues;
168+
169+
} else if (getType() == MetaField.Type.OBJECT) {
170+
Map<String, Object> childrenMap = new LinkedHashMap<>();
171+
getChildren().stream()
172+
.filter(field -> field.getValue() != null)
173+
.forEach(field -> childrenMap.put(field.meta.id, field.getValue()));
174+
175+
if (childrenMap.isEmpty()) {
176+
return null;
177+
}
178+
return childrenMap;
179+
180+
} else {
181+
try {
182+
if (getType() == MetaField.Type.NUMBER) {
183+
return Integer.parseInt((String) value);
184+
} else if (getType() == MetaField.Type.FLOAT) {
185+
return Float.parseFloat((String) value);
186+
}
187+
} catch (Exception ignored) {
188+
189+
}
190+
return value;
191+
}
192+
}
193+
194+
private void updateDependencies() {
195+
getChildren().forEach(x -> x.mandatoryProperty.setValue(x.isMandatory()));
196+
}
197+
198+
public boolean validateValue() {
199+
if (getValue() == null) {
200+
return !isMandatory();
201+
}
202+
203+
try {
204+
validationMap.get(getType()).validate(value);
205+
return true;
206+
} catch (Exception ex) {
207+
return false;
208+
}
209+
}
210+
211+
public List<String> getValidationErrors() {
212+
List<String> errors = new ArrayList<>();
213+
for (ConfigNode node : this.children) {
214+
errors.addAll(node.getValidationErrors());
215+
}
216+
217+
if (errors.isEmpty()) {
218+
String idDescription = getIdDescription();
219+
220+
if (getValue() == null && isMandatory()) {
221+
errors.add(MessageFormat.format("Field {0} ({1}) is mandatory, it must be specified",
222+
getName(),
223+
idDescription
224+
));
225+
} else if (!validateValue()) {
226+
errors.add(MessageFormat.format("Field {0} ({1}) equals \"{2}\", and cannot be parsed as {3}",
227+
getName(),
228+
idDescription,
229+
value,
230+
getType().toString()
231+
));
232+
}
233+
}
234+
235+
return errors;
236+
}
237+
238+
private String getIdDescription() {
239+
if (getParent() != null) {
240+
if (getParent().getType() == MetaField.Type.LIST) {
241+
return getParent().getIdDescription() + "[" + getParent().getChildren().indexOf(this) + "]";
242+
} else {
243+
return getParent().getIdDescription() + "." + getId();
244+
}
245+
} else {
246+
return getId();
247+
}
248+
}
249+
250+
public ConfigNode getParent() {
251+
return parent;
252+
}
253+
254+
public ObservableList<ConfigNode> getChildren() {
255+
return children;
256+
}
257+
258+
public ConfigNode addListItem() {
259+
ConfigNode newChild = new ConfigNode(meta.item, this, true);
260+
children.add(newChild);
261+
return newChild;
262+
}
263+
264+
public boolean isRemovable() {
265+
return removable;
266+
}
267+
}

0 commit comments

Comments
 (0)