source: java/main/src/main/java/com/framsticks/running/ExternalProcess.java @ 103

Last change on this file since 103 was 103, checked in by psniegowski, 11 years ago

HIGHLIGHTS:

  • add auto loading and saving algorithms between

frams files format and Java classes

  • respect ValueChange? events in GUI (do not reload object)
  • support results of procedures in Java server
  • make Experiment automatically convert between frams file and NetFile? object
  • add MessageLogger? (compatible with original frams server messages)
  • WorkPackageLogic? now validates results, is able to discard them, reschedule

whole package, or only uncomputed remainder

CHANGELOG:
Show just a short description in PrimeExperiment?.

Add primes_changed event to the PrimeExperiment?.

Make WorkPackageLogic? robust to frams server returning invalid results.

Add MessageLogger? to logics.

Add NetFile? interface. Support Messages from server.

Minor changes to connections.

Merge results in the PrimeExperiment?.

More netload class->file conversion to Simulator.

Move netsave parsing to Simulator.

Fix bug with inverted ordering of events firing in Experiment.

Minor changes.

Minor logging changes.

Use AccessOperations?.convert in NetLoadSaveLogic?

NetLoadSaveLogic? now encloses the conversion.

Use more generic AccessOperations? saveAll and loadAll in PrimePackage?.

Add Result class for enclosing of call invocations' results.

Improve feature request handling in Connections.

Use AccessOperations?.convert in RemoteTree? events parsing.

Minor change.

Add some information params to Java server root and CLI objects.

A draft implementation of loadAll algorithm.

That algorithm tries to load objects into a tree structure.

Add AccessOperationsTest? test.

Develop WorkPackageLogic?.

  • add state tracking fields
  • add work package generation

Add utility class SimplePrimitive?.

Meant for Java backend classes, enclose a single primitive value
and set of listeners.

Improve primitive value refresh in GUI.

When ValueChange? found in called event, do not reload whole
object, but only update GUI (no communication is performed).

Use ValueChange? in the TestClass? test.

Minor changes.

Sending all packages in PrimeExperiment? to the frams servers.

Develop AccessOperations?.loadComposites().

Remove addAccess from MultiParamLoader? interface.

There is now no default AccessProvider? in MultiParamLoader?.
User must explicitely set AccessStash? or Registry.

Improve saving algorithms in AccessOperations?.

File size: 5.4 KB
Line 
1package com.framsticks.running;
2
3import java.io.BufferedReader;
4import java.io.File;
5import java.io.IOException;
6import java.io.InputStreamReader;
7import java.io.OutputStreamWriter;
8import java.io.PrintWriter;
9import java.util.ArrayList;
10import java.util.List;
11
12
13import org.apache.logging.log4j.Logger;
14import org.apache.logging.log4j.LogManager;
15
16import com.framsticks.core.ValueChange;
17import com.framsticks.params.EventListener;
18import com.framsticks.params.EventListeners;
19import com.framsticks.params.ParamFlags;
20import com.framsticks.params.annotations.AutoAppendAnnotation;
21import com.framsticks.params.annotations.FramsClassAnnotation;
22import com.framsticks.params.annotations.ParamAnnotation;
23import com.framsticks.util.FramsticksException;
24import com.framsticks.util.dispatching.AbstractJoinable;
25import com.framsticks.util.dispatching.Dispatching;
26import com.framsticks.util.dispatching.Joinable;
27import com.framsticks.util.dispatching.JoinableParent;
28import com.framsticks.util.dispatching.JoinableState;
29import com.framsticks.util.dispatching.RunAt;
30import com.framsticks.util.dispatching.Thread;
31import com.framsticks.util.dispatching.ThrowExceptionHandler;
32import com.framsticks.util.io.Encoding;
33
34@FramsClassAnnotation
35public class ExternalProcess extends AbstractJoinable implements JoinableParent {
36        private static final Logger log = LogManager.getLogger(ExternalProcess.class);
37
38        protected List<String> arguments = new ArrayList<>();
39        protected Process process;
40        protected final ProcessBuilder builder = new ProcessBuilder();
41        protected Thread<ExternalProcess> readerThread = new Thread<ExternalProcess>();
42
43        protected PrintWriter input;
44        protected BufferedReader output;
45        protected Integer exitCode;
46        protected String echoInput;
47
48        protected final EventListeners<ValueChange> listeners = new EventListeners<>();
49
50        @AutoAppendAnnotation
51        @ParamAnnotation(id = "line_output")
52        public void addOutputListener(EventListener<ValueChange> listener) {
53                synchronized (listeners) {
54                        listeners.add(listener);
55                }
56        }
57
58        @ParamAnnotation(id = "line_output")
59        public void removeOutputListener(EventListener<ValueChange> listener) {
60                synchronized (listeners) {
61                        listeners.remove(listener);
62                }
63        }
64
65        /**
66         *
67         */
68        public ExternalProcess() {
69                super();
70                setName("process");
71                arguments.add(null);
72                builder.redirectErrorStream(true);
73        }
74
75        /**
76         * @return the command
77         */
78        @ParamAnnotation(flags = ParamFlags.USERREADONLY)
79        public String getCommand() {
80                return arguments.get(0);
81        }
82
83        /**
84         * @param command the command to set
85         */
86        @ParamAnnotation
87        public void setCommand(String command) {
88                arguments.set(0, command);
89        }
90
91        protected void readerTask() {
92
93                log.debug("reading output from " + this);
94                String line;
95                try {
96                        try {
97                                while ((line = output.readLine()) != null) {
98                                        log.trace("read line: {}", line);
99                                        synchronized (listeners) {
100                                                listeners.actionForAll(new ValueChange(line));
101                                        }
102                                }
103                        } catch (IOException e) {
104                                throw new FramsticksException().msg("failed to read line from output of process").cause(e);
105                        }
106                        try {
107                                exitCode = process.waitFor();
108                        } catch (InterruptedException e) {
109                                throw new FramsticksException().msg("failed to wait for process").cause(e);
110                        }
111                        log.info("process ended {}", this);
112                        // process = null;
113                } catch (FramsticksException e) {
114                        log.error("exception caught in process {}", this, e);
115                }
116                interruptJoinable();
117                // finish();
118        }
119
120        @ParamAnnotation(flags = ParamFlags.USERREADONLY)
121        public void setDirectory(String directory) {
122                builder.directory(new File(directory));
123        }
124
125        @ParamAnnotation
126        public String getDirectory() {
127                return builder.directory() != null ? builder.directory().getName() : ".";
128        }
129
130        @Override
131        protected void joinableStart() {
132                log.info("running process {}", this);
133                builder.command(arguments);
134                try {
135                        process = builder.start();
136                        input = new PrintWriter(new OutputStreamWriter(process.getOutputStream(), Encoding.getDefaultCharset()));
137                        output = new BufferedReader(new InputStreamReader(process.getInputStream(), Encoding.getDefaultCharset()));
138
139                } catch (IOException e) {
140                        throw new FramsticksException().msg("failed to start process").cause(e);
141                }
142
143                readerThread.dispatch(new RunAt<ExternalProcess>(ThrowExceptionHandler.getInstance()) {
144
145                        @Override
146                        protected void runAt() {
147                                readerTask();
148                        }
149
150                });
151                Dispatching.use(readerThread, this);
152
153                if (echoInput != null) {
154                        input.println(echoInput);
155                        input.flush();
156                }
157        }
158
159        @Override
160        public String toString() {
161                return getName() + arguments;
162        }
163
164        /**
165         * @return the input
166         */
167        public PrintWriter getInput() {
168                return input;
169        }
170
171        /**
172         * @return the echoInput
173         */
174        @ParamAnnotation(flags = ParamFlags.USERREADONLY)
175        public String getEchoInput() {
176                return echoInput;
177        }
178
179        /**
180         * @param echoInput the echoInput to set
181         */
182        @ParamAnnotation
183        public void setEchoInput(String echoInput) {
184                this.echoInput = echoInput;
185        }
186
187        @Override
188        protected void joinableInterrupt() {
189                process.destroy();
190                Dispatching.drop(readerThread, this);
191                // finish();
192        }
193
194        @Override
195        @ParamAnnotation(flags = ParamFlags.USERREADONLY)
196        public String getName() {
197                return readerThread.getName();
198        }
199
200        /**
201         * @param name the name to set
202         */
203        @ParamAnnotation
204        public void setName(String name) {
205                readerThread.setName(name);
206        }
207
208        @Override
209        protected void joinableFinish() {
210
211        }
212
213        @Override
214        protected void joinableJoin() throws InterruptedException {
215                Dispatching.join(readerThread);
216        }
217
218        @Override
219        public void childChangedState(Joinable joinable, JoinableState state) {
220                proceedToState(state);
221        }
222
223
224
225}
Note: See TracBrowser for help on using the repository browser.