View Javadoc

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          // Evaluate XPath expression
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          // Write output
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 }