001package org.javasimon.console.action; 002 003import org.javasimon.Sample; 004import org.javasimon.Simon; 005import org.javasimon.console.Action; 006import org.javasimon.console.ActionContext; 007import org.javasimon.console.ActionException; 008import org.javasimon.console.SimonType; 009import org.javasimon.console.SimonTypeFactory; 010import org.javasimon.console.TimeFormatType; 011import org.javasimon.console.reflect.Getter; 012import org.javasimon.console.reflect.GetterFactory; 013import org.javasimon.console.text.Stringifier; 014import org.javasimon.console.text.StringifierFactory; 015import org.w3c.dom.Document; 016import org.w3c.dom.Element; 017 018import java.io.IOException; 019import java.util.Iterator; 020 021import javax.servlet.ServletException; 022import javax.xml.parsers.DocumentBuilder; 023import javax.xml.parsers.DocumentBuilderFactory; 024import javax.xml.parsers.ParserConfigurationException; 025import javax.xml.transform.Transformer; 026import javax.xml.transform.TransformerException; 027import javax.xml.transform.TransformerFactory; 028import javax.xml.transform.dom.DOMSource; 029import javax.xml.transform.stream.StreamResult; 030 031/** 032 * Base for actions returning data in XML format. 033 * 034 * @author gquintana 035 */ 036public abstract class AbstractXmlAction extends Action { 037 038 protected AbstractXmlAction(ActionContext context) { 039 super(context); 040 } 041 042 /** Converter Object → HTML String. */ 043 protected final StringifierFactory stringifierFactory = new StringifierFactory(); 044 045 @Override 046 public void readParameters() { 047 final TimeFormatType timeFormat = getContext().getParameterAsEnum("timeFormat", TimeFormatType.class, TimeFormatType.MILLISECOND); 048 stringifierFactory.init(timeFormat, 049 StringifierFactory.ISO_DATE_PATTERN, 050 StringifierFactory.READABLE_NUMBER_PATTERN 051 ); 052 } 053 054 /** 055 * Transforms a Simon into a JSON object. 056 * 057 * @param simon Simon 058 * @return JSON object 059 */ 060 @SuppressWarnings("unchecked") 061 protected Element createElement(Document document, Simon simon) { 062 // Simon type is used as element name 063 Sample sample = simon.sample(); 064 SimonType lType = SimonTypeFactory.getValueFromInstance(sample); 065 Element element = document.createElement(lType.name().toLowerCase()); 066 // Only to have the name as first attribute 067 element.setAttribute("name", sample.getName()); 068 // Export properties using reflection 069 for (Getter getter : GetterFactory.getGetters(sample.getClass())) { 070 Object propertyValue = getter.get(sample); 071 if (propertyValue != null) { 072 Stringifier propertyStringifier = stringifierFactory 073 .getStringifier(getter.getType(), getter.getSubType()); 074 if (propertyStringifier != null) { 075 element.setAttribute(getter.getName(), propertyStringifier.toString(propertyValue)); 076 } 077 } 078 } 079 // Export attribute map 080 Iterator<String> attributeNameIter = simon.getAttributeNames(); 081 while (attributeNameIter.hasNext()) { 082 String attributeName = attributeNameIter.next(); 083 Object attributeValue = simon.getAttribute(attributeName); 084 if (attributeValue != null) { 085 Stringifier attributeStringifier = stringifierFactory 086 .getStringifier(attributeValue.getClass()); 087 if (attributeStringifier != null) { 088 Element attributeElt = document.createElement("attribute"); 089 attributeElt.setAttribute("name", attributeName); 090 attributeElt.setAttribute("value", attributeStringifier.toString(attributeValue)); 091 element.appendChild(attributeElt); 092 } 093 } 094 095 } 096 return element; 097 098 } 099 100 @Override 101 public void execute() throws ServletException, IOException, ActionException { 102 dontCache(); 103 getContext().setContentType("text/xml"); 104 try { 105 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); 106 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); 107 Document document = documentBuilder.newDocument(); 108 fillDocument(document); 109 TransformerFactory transformerFactory = TransformerFactory.newInstance(); 110 Transformer transformer = transformerFactory.newTransformer(); 111 transformer.transform(new DOMSource(document), 112 new StreamResult(getContext().getOutputStream())); 113 } catch (ParserConfigurationException | TransformerException parserConfigurationException) { 114 throw new ActionException("XML Parser error", parserConfigurationException); 115 } finally { 116 getContext().getOutputStream().flush(); 117 } 118 } 119 120 protected abstract void fillDocument(Document document); 121}