1 package org.dfdaemon.il2.core;
2
3 import org.apache.commons.logging.Log;
4 import org.apache.commons.logging.LogFactory;
5 import org.dfdaemon.il2.api.command.reply.MissionInfo;
6 import org.dfdaemon.il2.api.command.request.MissionActionCmd;
7 import org.dfdaemon.il2.api.event.Event;
8 import org.dfdaemon.il2.spi.command.CommandExecutor;
9 import org.dfdaemon.il2.spi.event.EventProcessor;
10 import org.dfdaemon.il2.core.task.CoreTask;
11 import org.dfdaemon.il2.core.task.CoreTaskExecutionCallback;
12 import org.dfdaemon.il2.core.task.CoreTaskExecutor;
13 import org.dfdaemon.il2.core.task.CoreTaskExecutorAware;
14 import org.dfdaemon.il2.spi.mission.MissionData;
15 import org.dfdaemon.il2.spi.mission.MissionProvider;
16 import org.joda.time.DateTime;
17 import org.joda.time.format.DateTimeFormat;
18 import org.joda.time.format.DateTimeFormatter;
19 import org.springframework.beans.factory.annotation.Required;
20
21 import java.io.File;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.util.Date;
25 import java.util.Timer;
26 import java.util.TimerTask;
27 import java.util.concurrent.CountDownLatch;
28 import java.util.concurrent.atomic.AtomicBoolean;
29
30
31
32
33
34
35 public class Il2DaemonTask implements CoreTask, CoreTaskExecutorAware {
36
37 private static final Log LOG = LogFactory.getLog(Il2DaemonTask.class);
38 private CoreTaskExecutor _coreTaskExecutor;
39
40 private EventProcessor _eventProcessor;
41 private CommandExecutor _commandExecutor;
42
43 private File _il2ServerMissionsHome;
44 private MissionProvider _missionProvider;
45
46 private final MissionLauncher _launcher = new MissionLauncher();
47
48 private final AtomicBoolean _alive = new AtomicBoolean(true);
49
50
51
52
53 public void preRun() throws Exception {
54 if (LOG.isDebugEnabled())
55 LOG.debug("Initializing...");
56
57 if (!_il2ServerMissionsHome.exists() || !_il2ServerMissionsHome.isDirectory()) {
58 throw new Il2DaemonException(
59 _il2ServerMissionsHome.getAbsolutePath() + " should be directory and should exists");
60 }
61 _eventProcessor.addEventConsumer(new EventConsumer());
62 }
63
64
65
66
67 public void run() throws Exception {
68 if (LOG.isInfoEnabled())
69 LOG.info("Starting...");
70 while (_alive.get()) {
71 _coreTaskExecutor.submit(_launcher, new CoreTaskExecutionCallback() {
72 public void onTaskCrash(final CoreTask task, final Throwable t) {
73 if (LOG.isErrorEnabled())
74 LOG.error("launcher failed, finishing...");
75 _alive.set(false);
76 }
77
78 public void onTaskCompletition(final CoreTask task) {
79 if (LOG.isDebugEnabled())
80 LOG.debug("callback: mission finished");
81
82 }
83 });
84 _coreTaskExecutor.awaitCompletition(_launcher);
85 }
86 }
87
88
89
90
91
92 public void afterRun() {
93 _alive.set(false);
94 if (LOG.isDebugEnabled())
95 LOG.debug("Stopped...");
96 }
97
98
99
100
101
102
103 public boolean stop() {
104 _alive.set(false);
105 _coreTaskExecutor.cancel(_launcher);
106 return true;
107 }
108
109
110
111
112
113
114
115 @Required
116 public void setCommandExecutor(CommandExecutor commandExecutor) {
117 _commandExecutor = commandExecutor;
118 }
119
120
121
122
123
124
125 @Required
126 public void setMissionsDir(File il2ServerMissionsHome) {
127 _il2ServerMissionsHome = il2ServerMissionsHome;
128 }
129
130
131
132
133
134
135 @Required
136 public void setMissionProvider(MissionProvider missionProvider) {
137 _missionProvider = missionProvider;
138 }
139
140
141
142
143
144
145 @Required
146 public void setEventProcessor(EventProcessor eventProcessor) {
147 _eventProcessor = eventProcessor;
148 }
149
150 public void setCoreTaskExecutor(CoreTaskExecutor coreTaskExecutor) {
151 _coreTaskExecutor = coreTaskExecutor;
152 }
153
154 private class MissionLauncher implements CoreTask {
155
156 private final Log _log = LogFactory.getLog(MissionLauncher.class);
157
158 private final DateTimeFormatter _fileNameFormatter = DateTimeFormat.forPattern("yyyyMMdd-HHmmssSSS");
159 private final Timer _timer = new Timer();
160 private MissionData _missionData;
161 private final CountDownLatch _latch = new CountDownLatch(1);
162
163
164
165
166 public void preRun() throws Exception {
167
168 _missionData = _missionProvider.getNextMission();
169 if (_missionData == null) {
170
171 throw new Il2DaemonException("Can't get mission from mission service");
172 }
173 String name = _il2ServerMissionsHome + "/" + _fileNameFormatter.print(new DateTime());
174 try {
175 if (_log.isInfoEnabled())
176 _log.info("Loading mission: " + name + ".mis");
177 writeFile(name + ".mis", _missionData.getMissionFile());
178
179 for (String locale : _missionData.getMissionProperties().keySet()) {
180 String suffix = "";
181 if (!locale.toLowerCase().equals("default")) {
182 suffix = locale.toLowerCase();
183 }
184 writeFile(name + suffix + ".properties", _missionData.getMissionProperties().get(locale));
185 }
186
187
188 MissionInfo missionInfo = _commandExecutor.executeCommand(new MissionActionCmd(MissionActionCmd.Action.END));
189 if (_log.isInfoEnabled())
190 _log.info(missionInfo);
191
192 missionInfo = _commandExecutor.executeCommand(new MissionActionCmd(MissionActionCmd.Action.BEGIN, name));
193 if (missionInfo.getState() != MissionInfo.MissionState.PLAYING) {
194 throw new Il2DaemonException("Mission start failed");
195 }
196 if (_log.isInfoEnabled())
197 _log.info("Started mission: " + name + ".mis");
198 _missionProvider.missionStarted(_missionData.getMissionId());
199 } catch (Exception e) {
200 _missionProvider.missionFailed(_missionData.getMissionId(), e.getMessage());
201 throw new Il2DaemonException(e);
202 }
203 }
204
205
206
207
208 public void run() throws Exception {
209
210 Date stopDate = new DateTime().plus(_missionData.getMissionDuration()).toDate();
211 _timer.schedule(new TimerTask() {
212
213
214
215 public void run() {
216 if (_log.isInfoEnabled())
217 _log.info("Stopping mission: stop date reached");
218 _latch.countDown();
219 }
220 }, stopDate);
221 if (_log.isInfoEnabled())
222 _log.info("Mission stop date: " + stopDate);
223 _latch.await();
224 }
225
226
227
228
229 public void afterRun() throws InterruptedException {
230 try {
231 _timer.purge();
232 if (_log.isInfoEnabled())
233 _log.info("Stopping mission");
234 MissionInfo i = _commandExecutor.executeCommand(
235 new MissionActionCmd(MissionActionCmd.Action.END));
236 assert i != null;
237 if (_log.isInfoEnabled())
238 _log.info("Stopping mission done");
239 } finally {
240 if (_missionData != null)
241 _missionProvider.missionFinished(_missionData.getMissionId());
242 }
243 }
244
245 public boolean stop() {
246 if (_log.isInfoEnabled())
247 _log.info("Stopping mission: stop requested");
248 _latch.countDown();
249 return true;
250 }
251
252
253
254
255
256
257
258
259 private void writeFile(String fname, byte[] byteData) throws IOException {
260 File f;
261 f = new File(fname);
262 if (f.exists())
263 f.delete();
264 f.createNewFile();
265 FileOutputStream fileOutputStream = new FileOutputStream(f);
266 fileOutputStream.write(byteData);
267 fileOutputStream.close();
268 }
269
270 }
271
272 class EventConsumer implements org.dfdaemon.il2.spi.event.EventConsumer {
273 public void handle(Event event) {
274 LOG.debug("Processing: " + event);
275 }
276 }
277 }