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

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

HIGHLIGHTS:

  • cleanup Instance management
    • extract Instance interface
    • extract Instance common algorithms to InstanceUtils?
  • fix closing issues: Ctrl+C or window close button

properly shutdown whole program

by Java Framsticks framework

  • fix parsing and printing of all request types
  • hide exception passing in special handle method of closures
    • substantially improve readability of closures
    • basically enable use of exception in asynchronous closures

(thrown exception is transported back to the caller)

  • implement call request on both sides

CHANGELOG:
Further improve calling.

Improve instance calling.

Calling is working on both sides.

Improve exception handling in testing.

Waiters do not supercede other apllication exception being thrown.

Finished parsing and printing of all request types (with tests).

Move implementation and tests of request parsing to Request.

Add tests for Requests.

Improve waits in asynchronours tests.

Extract more algorithms to InstanceUtils?.

Extract Instance.resolve to InstanceUtils?.

Improve naming.

Improve passing exception in InstanceClient?.

Hide calling of passed functor in StateCallback?.

Hide Exception passing in asynchronous closures.

Hide exception passing in Future.

Make ResponseCallback? an abstract class.

Make Future an abstract class.

Minor change.

Move getPath to Path.to()

Move bindAccess to InstanceUtils?.

Extract common things to InstanceUtils?.

Fix synchronization bug in Connection.

Move resolve to InstanceUtils?.

Allow names of Joinable to be dynamic.

Add support for set request server side.

More fixes in communication.

Fix issues with parsing in connection.

Cut new line characters when reading.

More improvements.

Migrate closures to FramsticksException?.

Several changes.

Extract resolveAndFetch to InstanceUtils? algorithms.

Test resolving and fetching.

More fixes with function signature deduction.

Do not print default values in SimpleAbstractAccess?.

Add test of FramsClass? printing.

Improve FramsticksException? messages.

Add explicit dispatcher synchronization feature.

Rework assertions in tests.

Previous solution was not generic enough.

Allow addition of joinables to collection after start.

Extract SimulatorInstance? from RemoteInstance?.

Remove PrivateJoinableCollection?.

Improve connections.

Move shutdown hook to inside the Monitor.

It should work in TestNG tests, but it seems that
hooks are not called.

In ServerTest? client connects to testing server.

Move socket initialization to receiver thread.

Add proper closing on Ctrl+C (don't use signals).

Fix bugs with server accepting connections.

Merge Entity into Joinable.

Reworking ServerInstance?.

Extract more algorithm to InstanceUtils?.

Extract some common functionality from AbstractInstance?.

Functions were placed in InstanceUtils?.

Hide registry of Instance.

Use ValueParam? in Instance interface.

Minor change.

Extract Instance interface.

Old Instance is now AbstractInstance?.

File size: 4.5 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.LinkedList;
11import java.util.List;
12
13
14import org.apache.log4j.Logger;
15
16import com.framsticks.params.annotations.AutoAppendAnnotation;
17import com.framsticks.params.annotations.FramsClassAnnotation;
18import com.framsticks.params.annotations.ParamAnnotation;
19import com.framsticks.util.FramsticksException;
20import com.framsticks.util.Misc;
21import com.framsticks.util.dispatching.AbstractJoinable;
22import com.framsticks.util.dispatching.Dispatching;
23import com.framsticks.util.dispatching.Joinable;
24import com.framsticks.util.dispatching.JoinableParent;
25import com.framsticks.util.dispatching.JoinableState;
26import com.framsticks.util.dispatching.RunAt;
27import com.framsticks.util.dispatching.Thread;
28import com.framsticks.util.io.Encoding;
29
30@FramsClassAnnotation
31public class ExternalProcess extends AbstractJoinable implements JoinableParent {
32        private static final Logger log = Logger.getLogger(ExternalProcess.class);
33
34        protected List<String> arguments = new ArrayList<>();
35        protected Process process;
36        protected final ProcessBuilder builder = new ProcessBuilder();
37        protected Thread<ExternalProcess> readerThread = new Thread<ExternalProcess>();
38
39        protected PrintWriter input;
40        protected BufferedReader output;
41        protected Integer exitCode;
42
43        protected final List<OutputListener> listeners = new LinkedList<>();
44
45        @AutoAppendAnnotation
46        public void addListener(OutputListener listener) {
47                synchronized (listeners) {
48                        listeners.add(listener);
49                }
50        }
51
52        /**
53         *
54         */
55        public ExternalProcess() {
56                super();
57                setName("process");
58                arguments.add(null);
59                builder.redirectErrorStream(true);
60        }
61
62        /**
63         * @return the command
64         */
65        @ParamAnnotation
66        public String getCommand() {
67                return arguments.get(0);
68        }
69
70        /**
71         * @param command the command to set
72         */
73        @ParamAnnotation
74        public void setCommand(String command) {
75                arguments.set(0, command);
76        }
77
78        protected void readerTask() {
79
80                String line;
81                try {
82                        try {
83                                while ((line = output.readLine()) != null) {
84                                        log.trace("read line: " + line);
85                                        synchronized (listeners) {
86                                                for (OutputListener l : listeners) {
87                                                        l.onLineRead(line);
88                                                }
89                                        }
90                                }
91                        } catch (IOException e) {
92                                throw new FramsticksException().msg("failed to read line from output of process").cause(e);
93                        }
94                        try {
95                                exitCode = process.waitFor();
96                        } catch (InterruptedException e) {
97                                throw new FramsticksException().msg("failed to wait for process").cause(e);
98                        }
99                        log.debug("process ended " + this);
100                        // process = null;
101                } catch (FramsticksException e) {
102                        log.error("exception caught in process " + this, e);
103                }
104                interrupt();
105                // finish();
106        }
107
108        @ParamAnnotation
109        public void setDirectory(String directory) {
110                builder.directory(new File(directory));
111        }
112
113        @ParamAnnotation
114        public String getDirectory() {
115                return builder.directory().getName();
116        }
117
118        @Override
119        protected void joinableStart() {
120                log.debug("running process with arguments: " + arguments);
121                builder.command(arguments);
122                try {
123                        process = builder.start();
124                        input = new PrintWriter(new OutputStreamWriter(process.getOutputStream(), Encoding.getDefaultCharset()));
125                        output = new BufferedReader(new InputStreamReader(process.getInputStream(), Encoding.getDefaultCharset()));
126
127                } catch (IOException e) {
128                        throw new FramsticksException().msg("failed to start process").cause(e);
129                }
130
131                readerThread.dispatch(new RunAt<ExternalProcess>() {
132
133                        @Override
134                        public void run() {
135                                readerTask();
136                        }
137
138                });
139                Dispatching.use(readerThread, this);
140        }
141
142        @Override
143        public String toString() {
144                return getName() + "[" + Misc.returnNotNull(getCommand(), "?") + "]";
145        }
146
147        /**
148         * @return the input
149         */
150        public PrintWriter getInput() {
151                return input;
152        }
153
154        @Override
155        protected void joinableInterrupt() {
156                process.destroy();
157                Dispatching.drop(readerThread, this);
158                // finish();
159        }
160
161        @Override
162        @ParamAnnotation
163        public String getName() {
164                return readerThread.getName();
165        }
166
167        /**
168         * @param name the name to set
169         */
170        @ParamAnnotation
171        public void setName(String name) {
172                readerThread.setName(name);
173        }
174
175        @Override
176        protected void joinableFinish() {
177
178        }
179
180        @Override
181        protected void joinableJoin() throws InterruptedException {
182                Dispatching.join(readerThread);
183        }
184
185        @Override
186        public void childChangedState(Joinable joinable, JoinableState state) {
187                proceedToState(state);
188        }
189
190
191
192}
Note: See TracBrowser for help on using the repository browser.