UartBus source documentation
UartbusAttachProcess.java
1 package eu.javaexperience.electronic.uartbus.cli.apps;
2 
6 
7 import java.io.BufferedReader;
8 import java.io.IOException;
9 import java.io.InputStreamReader;
10 import java.io.OutputStream;
11 import java.lang.ProcessBuilder.Redirect;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.StringTokenizer;
16 
17 import eu.javaexperience.cli.CliEntry;
18 import eu.javaexperience.cli.CliTools;
23 import eu.javaexperience.log.JavaExperienceLoggingFacility;
24 
26 {
27  public static final CliEntry<String> PROGRAM = CliEntry.createFirstArgParserEntry
28  (
29  (e)->e,
30  "Application with arguments",
31  "a", "-program"
32  );
33 
34  protected static final CliEntry[] PROG_CLI_ENTRIES =
35  {
36  RPC_HOST,
37  RPC_PORT,
38  LOOPBACK,
39  PROGRAM
40  };
41 
42 
43  public static void main(String[] args) throws Exception
44  {
45  JavaExperienceLoggingFacility.addStdOut();
46  Map<String, List<String>> pa = CliTools.parseCliOpts(args);
47  String un = CliTools.getFirstUnknownParam(pa, PROG_CLI_ENTRIES);
48  if(null != un)
49  {
50  CliTools.printHelpAndExit("UartbusAttachProcess", 1, PROG_CLI_ENTRIES);
51  }
52 
53  String prog = PROGRAM.tryParse(pa);
54 
55  if(null == prog)
56  {
57  System.err.println("No program specified");
58  CliTools.printHelpAndExit("UartbusAttachProcess", 1, PROG_CLI_ENTRIES);
59  }
60 
61  ProcessBuilder pb = new ProcessBuilder(translateCommandline(prog));
62  pb.redirectError(Redirect.INHERIT);
63  Process proc = pb.start();
64 
66  (
67  RPC_HOST.tryParseOrDefault(pa, "127.0.0.1"),
68  RPC_PORT.tryParseOrDefault(pa, 2112),
69  (connection)->
70  {
71  if(LOOPBACK.hasOption(pa))
72  {
73  try
74  {
75  connection.setAttribute("loopback_send_packets", "true");
76  }
77  catch (IOException e1)
78  {
79  e1.printStackTrace();
80  }
81  }
82  },
83  false
84  );
85 
86  rpc.getPacketStreamer().addEventListener
87  (
88  e ->
89  {
90  //write to process
91  try
92  {
93  OutputStream os = proc.getOutputStream();
94  String write = UartbusTools.formatColonData(e)+"\n";
95  //System.out.print("> "+write);
96  os.write(write.getBytes());
97  os.flush();
98  }
99  catch (IOException e1)
100  {
101  e1.printStackTrace();
102  }
103  }
104  );
105 
106  rpc.startStreaming();
107 
108  UartbusConnection conn = rpc.getApi();
109 
110  BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
111  String line = null;
112 
113  while(null != (line = br.readLine()))
114  {
115  try
116  {
117  //System.out.println("< "+line);
118  conn.sendPacket(UartbusTools.parseColonData(line));
119  }
120  catch(Exception e)
121  {
122  e.printStackTrace();
123  }
124  }
125 
126  System.out.println("Process STDOUT closed");
127  proc.waitFor();
128  }
129 
130  /**
131  * https://stackoverflow.com/questions/3259143/split-a-string-containing-command-line-parameters-into-a-string-in-java
132  * [code borrowed from ant.jar]
133  * Crack a command line.
134  * @param toProcess the command line to process.
135  * @return the command line broken into strings.
136  * An empty or null toProcess parameter results in a zero sized array.
137  */
138  public static String[] translateCommandline(String toProcess) {
139  if (toProcess == null || toProcess.length() == 0) {
140  //no command? no string
141  return new String[0];
142  }
143  // parse with a simple finite state machine
144 
145  final int normal = 0;
146  final int inQuote = 1;
147  final int inDoubleQuote = 2;
148  int state = normal;
149  final StringTokenizer tok = new StringTokenizer(toProcess, "\"\' ", true);
150  final ArrayList<String> result = new ArrayList<String>();
151  final StringBuilder current = new StringBuilder();
152  boolean lastTokenHasBeenQuoted = false;
153 
154  while (tok.hasMoreTokens()) {
155  String nextTok = tok.nextToken();
156  switch (state) {
157  case inQuote:
158  if ("\'".equals(nextTok)) {
159  lastTokenHasBeenQuoted = true;
160  state = normal;
161  } else {
162  current.append(nextTok);
163  }
164  break;
165  case inDoubleQuote:
166  if ("\"".equals(nextTok)) {
167  lastTokenHasBeenQuoted = true;
168  state = normal;
169  } else {
170  current.append(nextTok);
171  }
172  break;
173  default:
174  if ("\'".equals(nextTok)) {
175  state = inQuote;
176  } else if ("\"".equals(nextTok)) {
177  state = inDoubleQuote;
178  } else if (" ".equals(nextTok)) {
179  if (lastTokenHasBeenQuoted || current.length() != 0) {
180  result.add(current.toString());
181  current.setLength(0);
182  }
183  } else {
184  current.append(nextTok);
185  }
186  lastTokenHasBeenQuoted = false;
187  break;
188  }
189  }
190  if (lastTokenHasBeenQuoted || current.length() != 0) {
191  result.add(current.toString());
192  }
193  if (state == inQuote || state == inDoubleQuote) {
194  throw new RuntimeException("unbalanced quotes in " + toProcess);
195  }
196  return result.toArray(new String[result.size()]);
197  }
198 }