View Javadoc

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   * Main core class which runs daemon.
32   *
33   * @author aka50
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       * {@inheritDoc}
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       * {@inheritDoc}
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       * {@inheritDoc}
91       */
92      public void afterRun() {
93          _alive.set(false);
94          if (LOG.isDebugEnabled())
95              LOG.debug("Stopped...");
96      }
97  
98      /**
99       * Stops daemon task
100      *
101      * @return ...
102      */
103     public boolean stop() {
104         _alive.set(false);
105         _coreTaskExecutor.cancel(_launcher);
106         return true;
107     }
108 
109 
110     /**
111      * Method setCommandExecutor sets the commandExecutor of this Il2DaemonTask object.
112      *
113      * @param commandExecutor the commandExecutor of this Il2DaemonTask object.
114      */
115     @Required
116     public void setCommandExecutor(CommandExecutor commandExecutor) {
117         _commandExecutor = commandExecutor;
118     }
119 
120     /**
121      * Method setMissionsDir sets the il2ServerMissionsHome of this Il2DaemonTask object.
122      *
123      * @param il2ServerMissionsHome the il2ServerMissionsHome of this Il2DaemonTask object.
124      */
125     @Required
126     public void setMissionsDir(File il2ServerMissionsHome) {
127         _il2ServerMissionsHome = il2ServerMissionsHome;
128     }
129 
130     /**
131      * Method setMissionProvider sets the missionProvider of this Il2DaemonTask object.
132      *
133      * @param missionProvider the missionProvider of this Il2DaemonTask object.
134      */
135     @Required
136     public void setMissionProvider(MissionProvider missionProvider) {
137         _missionProvider = missionProvider;
138     }
139 
140     /**
141      * Method setEventProcessor sets the eventProcessor of this Il2DaemonTask object.
142      *
143      * @param eventProcessor the eventProcessor of this Il2DaemonTask object.
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          * {@inheritDoc}
165          */
166         public void preRun() throws Exception {
167 
168             _missionData = _missionProvider.getNextMission();
169             if (_missionData == null) {
170                 // TODO: think about what to do if missions not available...
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                 // Stop previous mission
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          * {@inheritDoc}
207          */
208         public void run() throws Exception {
209 
210             Date stopDate = new DateTime().plus(_missionData.getMissionDuration()).toDate();
211             _timer.schedule(new TimerTask() {
212                 /**
213                  * @see java.util.TimerTask#run()
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          * {@inheritDoc}
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; // make compiler happy
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          * Helper method for writing file from bytes.
254          *
255          * @param fname    of type String
256          * @param byteData of type byte[]
257          * @throws java.io.IOException when
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 }