/src/server/xmlprovider/src/keymind/keywatch/bundles/provider/xmlrpc/FileHandler.java

http://keywatch.googlecode.com/ · Java · 427 lines · 274 code · 71 blank · 82 comment · 39 complexity · b88a72b61649ddbc3bb4ad6d3dea00e4 MD5 · raw file

  1. /**
  2. * -----------------------------------------------------------------------------------------------
  3. * File: FileHandler.java
  4. * Created 26.jun.2006
  5. *
  6. *
  7. * Copyright (c) 2007 by Keymind Computing as.
  8. * All rights reserved.
  9. *
  10. * This file is subject to the terms and conditions of the Apache Licence 2.0.
  11. * See the file LICENCE in the main directory of the Keywatch distribution for more details.
  12. *
  13. * Revision History (use svn log or TortoiseSVN):
  14. * $URL: http://keywatch.googlecode.com/svn/trunk/src/server/xmlprovider/src/keymind/keywatch/bundles/provider/xmlrpc/FileHandler.java $
  15. * $Date: 2009-12-14 18:16:33 +0100 (Mon, 14 Dec 2009) $
  16. * -----------------------------------------------------------------------------------------------
  17. */
  18. package keymind.keywatch.bundles.provider.xmlrpc;
  19. import keymind.keywatch.common.Log;
  20. import keymind.keywatch.domainmodel.eventDomain.Context;
  21. import keymind.keywatch.domainmodel.eventDomain.Event;
  22. import keymind.keywatch.domainmodel.eventDomain.Severity;
  23. import keymind.keywatch.domainmodel.eventDomain.Task;
  24. import keymind.keywatch.services.eventmanagement.IEventManagement;
  25. import org.w3c.dom.DOMException;
  26. import org.w3c.dom.Document;
  27. import org.w3c.dom.Node;
  28. import org.xml.sax.InputSource;
  29. import javax.xml.parsers.DocumentBuilder;
  30. import javax.xml.parsers.DocumentBuilderFactory;
  31. import javax.xml.parsers.ParserConfigurationException;
  32. import java.io.*;
  33. import java.util.Date;
  34. import java.util.zip.ZipEntry;
  35. import java.util.zip.ZipInputStream;
  36. /**
  37. * Internal class that handles incoming event files
  38. */
  39. public class FileHandler
  40. {
  41. static DocumentBuilderFactory factory =
  42. DocumentBuilderFactory.newInstance();
  43. private static Context ctx = null;
  44. private static Activator xmlProvider = null;
  45. private static IEventManagement eventManager = null;
  46. static final int SLEEP_ZIPPING = 50;
  47. static final int BUFSIZE_ZIP = 1024;
  48. /**
  49. * C'tor
  50. */
  51. public FileHandler()
  52. {
  53. // Initialize singletons
  54. if(xmlProvider == null)
  55. {
  56. ctx = KeyXmlRpcServer.getCtx();
  57. xmlProvider = KeyXmlRpcServer.getXmlProvider();
  58. eventManager = KeyXmlRpcServer.getEventManager();
  59. }
  60. }
  61. /**
  62. * Receives a file via XmlRpc form a connected client.
  63. *
  64. * @param inputFile Contents of the file
  65. * @param inputFileName The name of the file as it is on the client
  66. * @return true if filetransfer went OK, false otherwise
  67. * @throws Exception if a problem occurs.
  68. */
  69. public boolean ReceiveFile(byte[] inputFile, String inputFileName) throws Exception
  70. {
  71. boolean retVal;
  72. try
  73. {
  74. // We add a timestamp, since all incoming zip files have the same name (error.zip)
  75. long now = System.currentTimeMillis();
  76. // Create events directory if missing
  77. File f = new File(Constants.PROVIDER_DIR_EVENT);
  78. f.mkdir();
  79. String fullname = Constants.PROVIDER_DIR_EVENT + "/" +
  80. now + "_" + inputFileName;
  81. FileOutputStream outStream = new FileOutputStream(fullname);
  82. for (int i = 0; i < inputFile.length; i++)
  83. {
  84. outStream.write(inputFile[i]);
  85. }
  86. outStream.close();
  87. // If it's a zip file, extract files and remove it
  88. if (fullname.toLowerCase().endsWith(Constants.PROVIDER_EXT_ZIP))
  89. {
  90. boolean allOK = processZipFiles(fullname);
  91. // If the quarantine is active, move the zip file there, else delete it
  92. File originalZip = new File(fullname);
  93. // Save a copy if one or more xml's are malformed
  94. if (!allOK)
  95. {
  96. File errorDir = new File(Constants.PROVIDER_DIR_ERRORXML);
  97. errorDir.mkdir();
  98. File errorFile = new File(Constants.PROVIDER_DIR_ERRORXML +
  99. "/" + now + "_" + inputFileName);
  100. originalZip.renameTo(errorFile);
  101. }
  102. }
  103. retVal = true;
  104. }
  105. catch (Exception ex)
  106. {
  107. ex.printStackTrace();
  108. retVal = false;
  109. }
  110. return retVal;
  111. }// ReceiveFile
  112. /**
  113. * Helper that unpacks a zip file
  114. *
  115. * @param destinationPath Destination directory
  116. * @param filename Name of zip file (fully qualified)
  117. */
  118. void extractZipFiles(String destinationPath, String filename)
  119. {
  120. try
  121. {
  122. byte[] buf = new byte[BUFSIZE_ZIP];
  123. ZipInputStream zipinputstream = new ZipInputStream(new FileInputStream(filename));
  124. ZipEntry zipentry = zipinputstream.getNextEntry();
  125. while (zipentry != null)
  126. {
  127. String entryName = zipentry.getName();
  128. int n = 0;
  129. FileOutputStream fileoutputstream = null;
  130. File newFile = new File(entryName);
  131. String directory = newFile.getParent();
  132. if (directory == null)
  133. {
  134. if (newFile.isDirectory())
  135. {
  136. break;
  137. }
  138. }
  139. fileoutputstream = new FileOutputStream(destinationPath + entryName);
  140. while ((n = zipinputstream.read(buf, 0, BUFSIZE_ZIP)) > -1)
  141. {
  142. fileoutputstream.write(buf, 0, n);
  143. }
  144. fileoutputstream.close();
  145. zipinputstream.closeEntry();
  146. zipentry = zipinputstream.getNextEntry();
  147. }// foreach entry
  148. zipinputstream.close();
  149. }
  150. catch (Exception e)
  151. {
  152. e.printStackTrace();
  153. }
  154. }// void extractZipFiles
  155. /**
  156. * Process xml files in-memory
  157. *
  158. * @param zipfile Name of zip-file
  159. * @return boolean value showing if the parsing happend correctly
  160. */
  161. boolean processZipFiles(String zipfile)
  162. {
  163. // Set to false if any of the files doesn't parse correctly
  164. boolean res = true;
  165. try
  166. {
  167. byte[] buf = new byte[BUFSIZE_ZIP];
  168. ZipInputStream zipinputstream = new ZipInputStream(new FileInputStream(zipfile));
  169. ZipEntry zipentry = zipinputstream.getNextEntry();
  170. while (zipentry != null)
  171. {
  172. String entryName = zipentry.getName();
  173. int n = 0;
  174. File newFile = new File(entryName);
  175. String directory = newFile.getParent();
  176. if (directory == null)
  177. {
  178. if (newFile.isDirectory())
  179. {
  180. break;
  181. }
  182. }
  183. ByteArrayOutputStream outstream = new ByteArrayOutputStream();
  184. while ((n = zipinputstream.read(buf, 0, BUFSIZE_ZIP)) > -1)
  185. {
  186. outstream.write(buf, 0, n);
  187. }
  188. String xml = outstream.toString();
  189. Event event = parse(xml);
  190. // Prepare next entry
  191. outstream.close();
  192. zipinputstream.closeEntry();
  193. zipentry = zipinputstream.getNextEntry();
  194. // Add event
  195. if (event != null)
  196. {
  197. try
  198. {
  199. eventManager.putEvent(new Context(), event);
  200. }
  201. catch (Exception ex)
  202. {
  203. // We trust putEvent to do the proper logging
  204. res = false;
  205. }
  206. }
  207. else
  208. {
  209. // The XML must've been malformed
  210. res = false;
  211. }
  212. // Be nice to the server; pause between each xml file.
  213. Thread.sleep(SLEEP_ZIPPING);
  214. }// foreach entry
  215. zipinputstream.close();
  216. }
  217. catch (Exception e)
  218. {
  219. e.printStackTrace();
  220. }
  221. return res;
  222. }// void extractZipFiles
  223. /**
  224. * Get node text
  225. * @param node XML node
  226. * @return Text string
  227. * @throws DOMException Thrown on error
  228. */
  229. public static String getTextContent(Node node) throws DOMException
  230. {
  231. String textContent = "";
  232. if (node.getNodeType() == Node.ATTRIBUTE_NODE)
  233. {
  234. textContent = node.getNodeValue();
  235. }
  236. else
  237. {
  238. Node child = node.getFirstChild();
  239. if (child != null)
  240. {
  241. Node sibling = child.getNextSibling();
  242. if (sibling != null)
  243. {
  244. StringBuffer sb = new StringBuffer();
  245. getTextContent(node, sb);
  246. textContent = sb.toString();
  247. }
  248. else
  249. {
  250. if (child.getNodeType() == Node.TEXT_NODE || child.getNodeType() == Node.CDATA_SECTION_NODE)
  251. {
  252. textContent = child.getNodeValue();
  253. }
  254. else
  255. {
  256. textContent = getTextContent(child);
  257. }
  258. }
  259. }
  260. }
  261. return textContent;
  262. }
  263. /**
  264. * Get node text
  265. *
  266. * @param node XML node
  267. * @return Text string
  268. * @throws DOMException Thrown on error
  269. */
  270. private static void getTextContent(Node node, StringBuffer sb) throws DOMException
  271. {
  272. Node child = node.getFirstChild();
  273. while (child != null)
  274. {
  275. if (child.getNodeType() == Node.TEXT_NODE)
  276. {
  277. sb.append(child.getNodeValue());
  278. }
  279. else
  280. {
  281. getTextContent(child, sb);
  282. }
  283. child = child.getNextSibling();
  284. }
  285. }
  286. /**
  287. * Parse event XML
  288. *
  289. * @param xml XML string
  290. * @return Object representation of the event XML
  291. * @throws javax.xml.parsers.ParserConfigurationException Thrown on parse error
  292. */
  293. public Event parse(String xml) throws ParserConfigurationException
  294. {
  295. Event res;
  296. DocumentBuilder builder = factory.newDocumentBuilder();
  297. try
  298. {
  299. StringReader reader = new StringReader(xml);
  300. InputSource inputSource = new InputSource(reader);
  301. Document doc = builder.parse(inputSource);
  302. res = new Event();
  303. Severity severity = new Severity();
  304. String severityStr = getTextContent(doc.getElementsByTagName(
  305. Constants.PROVIDER_XMLTAG_SEVERITY).item(0));
  306. res.setSeverity(severity);
  307. severity.setEnumerator(Integer.parseInt(severityStr));
  308. res.setCreated(new Date(System.currentTimeMillis()));
  309. res.setShortDescription(getTextContent(
  310. doc.getElementsByTagName(Constants.PROVIDER_XMLTAG_MESSAGE).item(0)));
  311. res.setLongDescription(getTextContent(
  312. doc.getElementsByTagName(Constants.PROVIDER_XMLTAG_DESCRIPTION).item(0)));
  313. // For now we use the job signature as the event name
  314. res.setName(getTextContent(
  315. doc.getElementsByTagName(Constants.PROVIDER_XMLTAG_JOB).item(0)));
  316. // Attempt to set source task as precisely as possible. If the event comes from a job we
  317. // have not seen yet, we have no option but to use the root provider as source.
  318. Task rootTask = xmlProvider.getRootTask(ctx);
  319. Task source = null;
  320. try
  321. {
  322. String hostname = getTextContent(doc.getElementsByTagName(
  323. Constants.PROVIDER_XMLTAG_HOST).item(0));
  324. res.setHost(hostname);
  325. // Set source; if the event name is not set (not a job), use the agent as source
  326. String agentName = rootTask.getName() + "/" + hostname;
  327. if (res.getName() == null || res.getName().length() == 0)
  328. {
  329. source = KeyXmlRpcServer.findByName(rootTask, agentName);
  330. }
  331. else
  332. {
  333. source = KeyXmlRpcServer.findByName(
  334. KeyXmlRpcServer.findByName(rootTask, agentName), res.getName());
  335. }
  336. }
  337. catch (Exception ex)
  338. {
  339. // Suppressed; missing host is allowed
  340. }
  341. // Fall back to provider if source couldn't be deduced
  342. if (source == null)
  343. {
  344. source = xmlProvider.getRootTask(ctx);
  345. }
  346. res.setProvider(source);
  347. }
  348. catch (Exception ex)
  349. {
  350. res = null;
  351. // Couldn't parse
  352. Log.error(Constants.PROVIDER_XMLPARSER_ERROR_PREFIX + ex.toString());
  353. }
  354. return res;
  355. }
  356. }// class FileHandler