1 /***
2 * Created on 2005-02-07
3 * @author Philippe Lefebvre <philippe.lefebvre@gmail.com>
4 */
5 package net.sf.xtract;
6
7 import java.io.File;
8 import java.io.FileInputStream;
9 import java.io.FileNotFoundException;
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.io.OutputStream;
13 import java.io.StringWriter;
14 import java.io.Writer;
15 import java.net.URLDecoder;
16 import java.util.concurrent.ExecutionException;
17 import java.util.logging.Level;
18 import java.util.logging.Logger;
19
20 import javax.servlet.ServletException;
21 import javax.servlet.http.HttpServlet;
22 import javax.servlet.http.HttpServletRequest;
23 import javax.servlet.http.HttpServletResponse;
24 import javax.xml.transform.OutputKeys;
25 import javax.xml.transform.Result;
26 import javax.xml.transform.Source;
27 import javax.xml.transform.Transformer;
28 import javax.xml.transform.TransformerException;
29 import javax.xml.transform.TransformerFactory;
30 import javax.xml.transform.dom.DOMSource;
31 import javax.xml.transform.stream.StreamResult;
32 import javax.xml.xpath.XPath;
33 import javax.xml.xpath.XPathConstants;
34 import javax.xml.xpath.XPathExpression;
35 import javax.xml.xpath.XPathExpressionException;
36 import javax.xml.xpath.XPathFactory;
37
38 import org.w3c.dom.Document;
39 import org.w3c.dom.Node;
40 import org.w3c.dom.NodeList;
41
42 /***
43 * TODO Document XtractServlet
44 */
45 public class XtractServlet extends HttpServlet {
46
47 private static final long serialVersionUID = 1L;
48 private static final String PACKAGE_NAME = XtractServlet.class.getPackage().getName();
49 private static final Logger sLogger = Logger.getLogger(PACKAGE_NAME);
50
51 private static final TransformerFactory lTransformerFactory = TransformerFactory.newInstance();
52 private static final XPathFactory sXPathFactory = XPathFactory.newInstance();
53
54 private final DocumentCache mDocumentCache = new DocumentCache(10);
55
56 /***
57 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
58 */
59 protected void doGet(HttpServletRequest pRequest,
60 HttpServletResponse pResponse) throws ServletException, IOException {
61
62 String lFilename = ".." + pRequest.getRequestURI();
63 String lQuery = pRequest.getQueryString();
64 String lRealPath = getServletContext().getRealPath(lFilename);
65 File lFile = new File(lRealPath);
66
67 if (lQuery == null || lQuery.length() == 0) {
68
69 pResponse.setContentType("text/xml");
70
71 try {
72 OutputStream lOut = pResponse.getOutputStream();
73 InputStream lIn = new FileInputStream(lFile);
74 copy(lIn, lOut);
75 lIn.close();
76 lOut.close();
77 } catch (FileNotFoundException e) {
78 pResponse.sendError(HttpServletResponse.SC_NOT_FOUND, lFilename);
79 } catch (IOException e) {
80 String lMsg = "The XML document could not be read";
81 sLogger.log(Level.WARNING, lMsg, e);
82 pResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, lMsg);
83 }
84
85 } else {
86
87 pResponse.setContentType("text/plain");
88 String lQueryDecoded = URLDecoder.decode(lQuery, "UTF-8");
89
90 try {
91
92
93 XPath lXPath = sXPathFactory.newXPath();
94 XPathExpression lXPathExpression = lXPath.compile(lQueryDecoded);
95 Document lDocument = mDocumentCache.getDocument(lFile);
96 NodeList lNodeList = (NodeList) lXPathExpression.evaluate(lDocument, XPathConstants.NODESET);
97
98
99 Writer lOut = pResponse.getWriter();
100 for (int i = 0; i < lNodeList.getLength(); i++) {
101 Node lNode = lNodeList.item(i);
102 lOut.write(toXML(lNode));
103 lOut.write('\n');
104 }
105 lOut.close();
106
107 } catch (XPathExpressionException e) {
108 String lMsg = lQueryDecoded + " is not a valid XPath expression";
109 pResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, lMsg);
110 sLogger.log(Level.FINE, "Invalid XPath expression: " + lQueryDecoded);
111 } catch (FileNotFoundException e) {
112 pResponse.sendError(HttpServletResponse.SC_NOT_FOUND, lFilename);
113 sLogger.log(Level.FINE, "File Not Found: " + lFilename);
114 } catch (TransformerException e) {
115 String lMsg = "Failed to transform DOM tree to XML.";
116 sLogger.log(Level.SEVERE, lMsg, e);
117 pResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
118 } catch (IOException e) {
119 String lMsg = "Failed to write to output stream.";
120 sLogger.log(Level.SEVERE, lMsg, e);
121 pResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
122 } catch (ExecutionException e) {
123 String lMsg = "Failed to instantiate XML parser.";
124 sLogger.log(Level.SEVERE, lMsg, e);
125 pResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
126 } catch (InterruptedException e) {
127 String lMsg = "Thread has been interrupted.";
128 sLogger.log(Level.WARNING, lMsg, e);
129 pResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
130 }
131
132 }
133
134 }
135
136 private static void copy(InputStream pIn, OutputStream pOut) throws IOException {
137 byte[] lBuffer = new byte[32 * 1024];
138 int lRead = pIn.read(lBuffer);
139 while (lRead != -1) {
140 pOut.write(lBuffer, 0, lRead);
141 lRead = pIn.read(lBuffer);
142 }
143 }
144
145 private static String toXML(Node pNode) throws TransformerException {
146 StringWriter lWriter = new StringWriter();
147
148 Source lSource = new DOMSource(pNode);
149 Result lResult = new StreamResult(lWriter);
150
151 Transformer lTransformer = lTransformerFactory.newTransformer();
152 lTransformer.setOutputProperty(OutputKeys.METHOD, "xml");
153 lTransformer.setOutputProperty(OutputKeys.INDENT, "yes");
154 lTransformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
155 lTransformer.transform(lSource, lResult);
156
157 return lWriter.toString();
158 }
159
160 }