001: package org.gomba;
002:
003: import java.io.ByteArrayInputStream;
004: import java.io.IOException;
005: import java.io.InputStream;
006: import java.util.HashMap;
007: import java.util.Iterator;
008: import java.util.Map;
009: import java.util.Properties;
010:
011: import javax.servlet.GenericServlet;
012: import javax.servlet.ServletConfig;
013: import javax.servlet.ServletException;
014: import javax.servlet.ServletRequest;
015: import javax.servlet.ServletResponse;
016: import javax.xml.parsers.DocumentBuilder;
017: import javax.xml.parsers.DocumentBuilderFactory;
018: import javax.xml.transform.OutputKeys;
019: import javax.xml.transform.Result;
020: import javax.xml.transform.Source;
021: import javax.xml.transform.Templates;
022: import javax.xml.transform.Transformer;
023: import javax.xml.transform.TransformerConfigurationException;
024: import javax.xml.transform.TransformerException;
025: import javax.xml.transform.TransformerFactory;
026: import javax.xml.transform.stream.StreamResult;
027: import javax.xml.transform.stream.StreamSource;
028:
029: import org.w3c.dom.Document;
030: import org.w3c.dom.Node;
031: import org.w3c.dom.NodeList;
032:
033: /**
034: * Servlet implementation to be used for automatic webservice documentation.
035: *
036: * <p>
037: * The generated documentation exposes sensitive information about the
038: * implementation of the web service. It is suggested that you don't allow
039: * public access to this resource.
040: * </p>
041: *
042: * <dl>
043: * <dt>xslt</dt>
044: * <dd>The XSLT stylesheet to apply to the default XML output. (Optional)</dd>
045: * <dt>xslt-params</dt>
046: * <dd>XSLT parameters in Java Properties format. (Optional)</dd>
047: * </dl>
048: *
049: * @author Daniele Galdi
050: * @version $Id: DocumentationServlet.java,v 1.5 2005/07/20 16:49:56 flaviotordini Exp $
051: */
052: public class DocumentationServlet extends GenericServlet {
053:
054: private final static String DEFAULT_XSLT = "/org/gomba/documentationServlet.xslt";
055:
056: /**
057: * The parsed XSLT stylesheet, if any.
058: */
059: private Templates templates;
060:
061: /**
062: * XSLT parameters.
063: */
064: private Map xsltFixedParameters;
065:
066: private HashMap validShowPath = new HashMap();
067:
068: /**
069: * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
070: */
071: public void init(ServletConfig config) throws ServletException {
072: super .init(config);
073:
074: InputStream is = getServletContext().getResourceAsStream(
075: "/WEB-INF/web.xml");
076:
077: if (is != null) {
078: DocumentBuilder builder;
079: try {
080: builder = DocumentBuilderFactory.newInstance()
081: .newDocumentBuilder();
082:
083: Document fileDoc = builder.parse(is);
084:
085: NodeList list = fileDoc
086: .getElementsByTagName("param-name");
087: for (int i = 0; i < list.getLength(); i++) {
088: Node node = list.item(i);
089: Node child = node.getFirstChild();
090: if (child.getNodeValue().trim().equals("query")) {
091: Node parent = node.getParentNode();
092: NodeList children = parent.getChildNodes();
093:
094: for (int j = 0; j < children.getLength(); j++) {
095: Node tmp = children.item(j);
096: if (tmp.getNodeName().equals("param-value")) {
097: String query = tmp.getFirstChild()
098: .getNodeValue().trim();
099: if (query.startsWith("/WEB-INF/")) {
100: validShowPath.put(query, query);
101: }
102: }
103: }
104: }
105: }
106: } catch (Exception e) {
107: throw new ServletException(
108: "Error during web.xml parsing", e);
109: }
110: }
111:
112: // XSLT
113: final String xsltStyleSheet = config.getInitParameter("xslt");
114:
115: if (xsltStyleSheet != null) {
116: // Create a templates object, which is the processed,
117: // thread-safe representation of the stylesheet.
118: is = getServletContext()
119: .getResourceAsStream(xsltStyleSheet);
120: } else {
121: is = DocumentationServlet.class
122: .getResourceAsStream(DEFAULT_XSLT);
123: }
124:
125: if (is == null) {
126: throw new ServletException("Cannot find stylesheet: "
127: + xsltStyleSheet);
128: }
129:
130: try {
131: TransformerFactory tfactory = TransformerFactory
132: .newInstance();
133: Source xslSource = new StreamSource(is);
134: if (xsltStyleSheet != null) {
135: // Note that if we don't do this, relative URLs can not be
136: // resolved correctly!
137: xslSource.setSystemId(getServletContext().getRealPath(
138: xsltStyleSheet));
139: }
140: this .templates = tfactory.newTemplates(xslSource);
141: } catch (TransformerConfigurationException tce) {
142: throw new ServletException(
143: "Error parsing XSLT stylesheet: " + xsltStyleSheet,
144: tce);
145: }
146:
147: // create a map of fixed xslt parameters
148: final String xsltParams = config
149: .getInitParameter("xslt-params");
150: if (xsltParams != null) {
151: try {
152: this .xsltFixedParameters = buildXsltFixedParams(xsltParams);
153: } catch (Exception e) {
154: throw new ServletException(
155: "Error parsing XSLT params: " + xsltParams, e);
156: }
157: }
158: }
159:
160: private static Map buildXsltFixedParams(String xsltParams)
161: throws IOException {
162: Properties parameters = new Properties();
163:
164: InputStream inputStream = new ByteArrayInputStream(xsltParams
165: .getBytes());
166: try {
167: parameters.load(inputStream);
168: } finally {
169: inputStream.close();
170: }
171:
172: return parameters;
173: }
174:
175: /**
176: * @see javax.servlet.Servlet#service(javax.servlet.ServletRequest,
177: * javax.servlet.ServletResponse)
178: */
179: public void service(ServletRequest request, ServletResponse response)
180: throws ServletException, IOException {
181: boolean identity = false;
182: String show = request.getParameter("show");
183:
184: if (show != null && !show.equals("/WEB-INF/web.xml")
185: && validShowPath.containsKey(show))
186: identity = true;
187: else
188: show = "/WEB-INF/web.xml";
189:
190: try {
191: Transformer t;
192: if (!identity && this .templates != null) {
193: // Create a transformer using our stylesheet
194: t = this .templates.newTransformer();
195:
196: // pass fixed XSLT parameters
197: if (this .xsltFixedParameters != null) {
198: for (Iterator i = this .xsltFixedParameters
199: .entrySet().iterator(); i.hasNext();) {
200: Map.Entry mapEntry = (Map.Entry) i.next();
201: t.setParameter((String) mapEntry.getKey(),
202: mapEntry.getValue());
203: }
204: }
205:
206: // TODO maybe we could also pass some dynamic values such as the
207: // request param or path info. But let's wait until the need
208: // arises...
209: } else {
210: // Create an "identity" transformer - copies input to output
211: t = TransformerFactory.newInstance().newTransformer();
212: }
213:
214: // Set trasformation output properties
215: t.setOutputProperty(OutputKeys.ENCODING, response
216: .getCharacterEncoding());
217:
218: InputStream is = getServletContext().getResourceAsStream(
219: show);
220:
221: if (is != null) {
222: // Create the trasformation result
223: Result result = new StreamResult(response
224: .getOutputStream());
225:
226: String mediaType = this .templates.getOutputProperties()
227: .getProperty(OutputKeys.MEDIA_TYPE);
228:
229: if (mediaType == null || identity) {
230: mediaType = "text/xml";
231: }
232: response.setContentType(mediaType);
233:
234: // Go!
235: t.transform(new StreamSource(is), result);
236: }
237: } catch (TransformerException e) {
238: log("Error", e);
239: }
240:
241: }
242: }
|