/cc.creativecomputing/src/cc/creativecomputing/app/CCWatchDog.java

http://creativecomputing.googlecode.com/ · Java · 236 lines · 159 code · 45 blank · 32 comment · 31 complexity · d3e722b0fafd0d8106b371b82ed91d99 MD5 · raw file

  1. /*
  2. * Copyright (c) 2009 Christian Riekoff <info@texone.org>
  3. *
  4. * This file is free software: you may copy, redistribute and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation, either version 2 of the License, or (at your
  7. * option) any later version.
  8. *
  9. * This file is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * This file incorporates work covered by the following copyright and
  18. * permission notice:
  19. */
  20. package cc.creativecomputing.app;
  21. import java.util.ArrayList;
  22. import java.util.HashMap;
  23. import java.util.List;
  24. import java.util.Map;
  25. import java.util.Scanner;
  26. import cc.creativecomputing.xml.CCXMLElement;
  27. import cc.creativecomputing.xml.CCXMLIO;
  28. /**
  29. * @author info
  30. *
  31. */
  32. public class CCWatchDog extends Thread{
  33. private interface CCWatchDogCommandHandler{
  34. public void onCommand(final String theValue);
  35. }
  36. private class CCWatchDogFrameRateRestart implements CCWatchDogCommandHandler{
  37. private float _myMinFrameRate;
  38. private CCWatchDogFrameRateRestart(final float theMinFrameRate) {
  39. _myMinFrameRate = theMinFrameRate;
  40. }
  41. /* (non-Javadoc)
  42. * @see cc.creativecomputing.app.CCWatchDog.CCWatchDogCommandHandler#onCommand(java.lang.String)
  43. */
  44. public void onCommand(String theValue) {
  45. try {
  46. float myFrameRate = Float.parseFloat(theValue);
  47. if(myFrameRate < _myMinFrameRate)endProcess();
  48. } catch (NumberFormatException e) {
  49. System.out.println("# COULD NOT READ FRAMERATE:"+theValue);
  50. }
  51. }
  52. }
  53. private int _myTime;
  54. private int _myStartTime;
  55. private int _myRestartTime;
  56. private int _myWaitTime;
  57. private boolean _myStartedProcess;
  58. private int _myOffTime = 0;
  59. private int _myMaxOffTime = -1;
  60. private String _myClassName;
  61. private List<String> _myLibraries = new ArrayList<String>();
  62. private List<String> _myVirtualMachineOptions = new ArrayList<String>();
  63. private Map<String, List<CCWatchDogCommandHandler>> _myCommandHandlerMap = new HashMap<String, List<CCWatchDogCommandHandler>>();
  64. private ProcessBuilder _myProcessBuilder;
  65. private Process _myProcess;
  66. public CCWatchDog() {
  67. super();
  68. loadSettings("process.xml");
  69. List<String> myArgumentList = new ArrayList<String>();
  70. myArgumentList.add("java");
  71. myArgumentList.add("-cp");
  72. myArgumentList.addAll(_myLibraries);
  73. myArgumentList.addAll(_myVirtualMachineOptions);
  74. myArgumentList.add(_myClassName);
  75. _myProcessBuilder = new ProcessBuilder(myArgumentList);
  76. _myStartedProcess = false;
  77. _myWaitTime = _myStartTime;
  78. }
  79. private void loadSettings(final String theFile) {
  80. CCXMLElement myProcessXML = CCXMLIO.createXMLElement(theFile);
  81. CCXMLElement myStartTimeXML = myProcessXML.child("starttime");
  82. if(myStartTimeXML != null)_myStartTime = myStartTimeXML.intContent(0);
  83. CCXMLElement myRestartTimeXML = myProcessXML.child("restarttime");
  84. if(myRestartTimeXML != null)_myRestartTime = myRestartTimeXML.intContent(0);
  85. CCXMLElement myClassNameXML = myProcessXML.child("class");
  86. if(myClassNameXML == null)throw new RuntimeException("You have to define a class to start inside the process.xml!");
  87. _myClassName = myClassNameXML.content();
  88. CCXMLElement myClassPathXML = myProcessXML.child("classpath");
  89. if(myClassPathXML == null)throw new RuntimeException("You have to define a classpath inside the process.xml!");
  90. for(CCXMLElement myLibXML:myClassPathXML) {
  91. _myLibraries.add(myLibXML.content());
  92. }
  93. CCXMLElement myVMParametersXML = myProcessXML.child("vm_options");
  94. if(myVMParametersXML != null) {
  95. for(CCXMLElement myVMParameterXML:myVMParametersXML) {
  96. _myVirtualMachineOptions.add(myVMParameterXML.content());
  97. }
  98. }
  99. CCXMLElement myRestartOptionsXML = myProcessXML.child("restart");
  100. if(myRestartOptionsXML != null) {
  101. if(myRestartOptionsXML.hasAttribute("minFrameRate")) {
  102. addCommandHandler("-frameRate", new CCWatchDogFrameRateRestart(myRestartOptionsXML.floatAttribute("minFrameRate")));
  103. }
  104. if(myRestartOptionsXML.hasAttribute("maxOffTime")) {
  105. _myMaxOffTime = myRestartOptionsXML.intAttribute("maxOffTime");
  106. }
  107. }
  108. }
  109. private void addCommandHandler(final String theCommand, final CCWatchDogCommandHandler theCommandHandler) {
  110. if(!_myCommandHandlerMap.containsKey(theCommand)) {
  111. _myCommandHandlerMap.put(theCommand, new ArrayList<CCWatchDogCommandHandler>());
  112. }
  113. _myCommandHandlerMap.get(theCommand).add(theCommandHandler);
  114. }
  115. private void parseTextLine(final String theLine) {
  116. if(!theLine.startsWith("-")) {
  117. System.out.println(theLine);
  118. return;
  119. }
  120. String[] myCommandArray = theLine.split(" ",2);
  121. String myCommand = myCommandArray[0];
  122. String myValue = "";
  123. if(myCommandArray.length > 1) {
  124. myValue = myCommandArray[0];
  125. }
  126. List<CCWatchDogCommandHandler> myCommandHandlers = _myCommandHandlerMap.get(myCommand);
  127. if(myCommandHandlers != null) {
  128. for(CCWatchDogCommandHandler myCommandHandler:myCommandHandlers) {
  129. myCommandHandler.onCommand(myValue);
  130. }
  131. }
  132. }
  133. /**
  134. * Ends the active process and sets the parameters so that the process will be restarted
  135. */
  136. private void endProcess() {
  137. _myProcess.destroy();
  138. }
  139. public void run() {
  140. try {
  141. while (true) {
  142. System.out.println(_myTime);
  143. long myTime = System.currentTimeMillis();
  144. if(!_myStartedProcess && _myTime >= _myWaitTime * 1000) {
  145. _myProcess = _myProcessBuilder.start();
  146. _myStartedProcess = true;
  147. }
  148. if(_myStartedProcess) {
  149. try {
  150. System.out.println(_myProcess.exitValue());
  151. System.out.println("RESTART");
  152. _myWaitTime = _myRestartTime;
  153. _myStartedProcess = false;
  154. _myTime = 0;
  155. } catch (IllegalThreadStateException e) {
  156. // ignore this process is still running which is exactly what we want
  157. }
  158. Scanner scanner = new Scanner(_myProcess.getInputStream());
  159. while (scanner.hasNextLine()) {
  160. _myOffTime = 0;
  161. parseTextLine(scanner.nextLine());
  162. }
  163. scanner = new Scanner(_myProcess.getErrorStream());
  164. while (scanner.hasNextLine())
  165. System.out.println(scanner.nextLine());
  166. }
  167. Thread.sleep(10);
  168. _myTime += System.currentTimeMillis() - myTime;
  169. _myOffTime += System.currentTimeMillis() - myTime;
  170. if(_myMaxOffTime > 0 && _myOffTime > _myMaxOffTime) {
  171. endProcess();
  172. }
  173. }
  174. } catch (Exception e) {
  175. // TODO Auto-generated catch block
  176. e.printStackTrace();
  177. }
  178. }
  179. public static void main(String[] args) {
  180. CCWatchDog myWatchDog = new CCWatchDog();
  181. myWatchDog.start();
  182. while(true) {
  183. try {
  184. Thread.sleep(10);
  185. } catch (InterruptedException e) {
  186. // TODO Auto-generated catch block
  187. e.printStackTrace();
  188. }
  189. }
  190. }
  191. }