View Javadoc
1   /*
2    * JaspertReports JSF Plugin Copyright (C) 2011 A. Alonso Dominguez
3    *
4    * This library is free software; you can redistribute it and/or modify it
5    * under the terms of the GNU Lesser General Public License as published by
6    * the Free Software Foundation; either version 2.1 of the License, or (at
7    * your option) any later version. This library is distributed in the hope
8    * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9    * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   *
11   * See the GNU Lesser General Public License for more details. You should have
12   * received a copy of the GNU Lesser General Public License along with this
13   * library; if not, write to the Free Software Foundation, Inc., 59 Temple
14   * Place, Suite 330, Boston, MA 02111-1307 USA A.
15   *
16   * Alonso Dominguez
17   * alonsoft@users.sf.net
18   */
19  package net.sf.jasperreports.jsf.engine.converters;
20  
21  import net.sf.jasperreports.jsf.engine.JRDataSourceWrapper;
22  import java.io.File;
23  import java.io.FileInputStream;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.net.URL;
27  import java.text.MessageFormat;
28  import java.util.ArrayList;
29  import java.util.List;
30  import java.util.logging.Level;
31  import java.util.logging.Logger;
32  
33  import javax.faces.component.UIComponent;
34  import javax.faces.component.UIParameter;
35  import javax.faces.context.FacesContext;
36  import javax.xml.parsers.DocumentBuilder;
37  import javax.xml.parsers.DocumentBuilderFactory;
38  import javax.xml.parsers.ParserConfigurationException;
39  import javax.xml.transform.dom.DOMSource;
40  import javax.xml.transform.sax.SAXSource;
41  import javax.xml.transform.stream.StreamSource;
42  
43  import net.sf.jasperreports.engine.JRDataSource;
44  import net.sf.jasperreports.engine.JREmptyDataSource;
45  import net.sf.jasperreports.engine.JRException;
46  import net.sf.jasperreports.engine.data.JRXmlDataSource;
47  import net.sf.jasperreports.jsf.Constants;
48  import net.sf.jasperreports.jsf.context.JRFacesContext;
49  import net.sf.jasperreports.jsf.engine.Source;
50  import net.sf.jasperreports.jsf.engine.SourceException;
51  import net.sf.jasperreports.jsf.resource.Resource;
52  
53  import org.w3c.dom.Document;
54  import org.xml.sax.InputSource;
55  import org.xml.sax.SAXException;
56  
57  import static net.sf.jasperreports.jsf.util.ComponentUtil.*;
58  
59  /**
60   * Converter implementation which obtains an XML data source
61   * from an existant resource.
62   *
63   * @author A. Alonso Dominguez
64   */
65  public final class XmlSourceConverter extends SourceConverterBase {
66  
67      /**
68  	 * 
69  	 */
70  	private static final long serialVersionUID = -5512987093226353550L;
71  	private static final Logger logger = Logger.getLogger(
72              XmlSourceConverter.class.getPackage().getName(),
73              Constants.LOG_MESSAGES_BUNDLE);
74  
75      @Override
76      protected Source createSource(FacesContext context,
77              UIComponent component, Object value)
78      throws SourceException {
79          JRDataSource dataSource;
80  
81          final Document xmlDocument;
82          try {
83              xmlDocument = getXmlDocument(context, component, value);
84          } catch (final ParserConfigurationException ex) {
85              throw new SourceException(ex);
86          } catch (final SAXException ex) {
87              throw new SourceException(ex);
88          } catch (final IOException ex) {
89              throw new SourceException(ex);
90          }
91  
92          if (xmlDocument == null) {
93              if (logger.isLoggable(Level.WARNING)) {
94                  logger.log(Level.WARNING, "JRJSF_0020",
95                          component.getClientId(context));
96              }
97              dataSource = new JREmptyDataSource();
98          } else {
99              final String query = getStringAttribute(component, "query", null);
100             try {
101                 if ((query != null) && (query.length() > 0)) {
102                     dataSource = new JRXmlDataSource(xmlDocument,
103                             parseQuery(component, query));
104                 } else {
105                     dataSource = new JRXmlDataSource(xmlDocument);
106                 }
107             } catch (final JRException e) {
108                 throw new SourceException(e);
109             }
110         }
111 
112         return new JRDataSourceWrapper(dataSource);
113     }
114 
115     protected Document getXmlDocument(final FacesContext context,
116             UIComponent component, Object value)
117             throws ParserConfigurationException, SAXException, IOException {
118         if (value == null) {
119             return null;
120         }
121 
122         Document document;
123         // First of all detect pre-built doms
124         if (value instanceof Document) {
125             document = (Document) value;
126         } else if (value instanceof DOMSource) {
127             final DOMSource source = (DOMSource) value;
128             final DocumentBuilder builder = getDocumentBuilder();
129             document = builder.newDocument();
130             document.appendChild(source.getNode());
131         } else if ((value instanceof InputSource)
132                 || (value instanceof SAXSource)) {
133             InputSource inputSource;
134             if (value instanceof SAXSource) {
135                 final SAXSource source = (SAXSource) value;
136                 inputSource = source.getInputSource();
137             } else {
138                 inputSource = (InputSource) value;
139             }
140             final DocumentBuilder builder = getDocumentBuilder();
141             document = builder.parse(inputSource);
142         } else {
143             InputStream stream = null;
144             boolean closeStream = true;
145             if (value instanceof StreamSource) {
146                 final StreamSource source = (StreamSource) value;
147                 stream = source.getInputStream();
148             } else if (value instanceof File) {
149                 stream = new FileInputStream((File) value);
150             } else if (value instanceof URL) {
151                 stream = ((URL) value).openStream();
152             } else if (value instanceof String) {
153                 final JRFacesContext jrContext =
154                         JRFacesContext.getInstance(context);
155                 final Resource resource = jrContext.createResource(context,
156                         component, (String) value);
157                 stream = resource.getInputStream();
158             } else if (value instanceof InputStream) {
159                 stream = (InputStream) value;
160                 closeStream = false;
161             }
162 
163             if (stream == null) {
164                 throw new SourceException("Unrecognized XML "
165                         + "value source type: " + value.getClass().getName());
166             }
167 
168             try {
169                 final DocumentBuilder builder = getDocumentBuilder();
170                 document = builder.parse(stream);
171             } finally {
172                 if (stream != null && closeStream) {
173                     try {
174                         stream.close();
175                     } catch (final IOException e) { ; }
176                 }
177                 stream = null;
178             }
179         }
180 
181         return document;
182     }
183 
184     private String parseQuery(UIComponent component, final String query) {
185         final List<Object> params = new ArrayList<Object>();
186 
187         for (final UIComponent kid : component.getChildren()) {
188             if (!(kid instanceof UIParameter)) {
189                 continue;
190             }
191 
192             final Object value = ((UIParameter) kid).getValue();
193             params.add(value);
194         }
195 
196         return MessageFormat.format(query,
197                 params.toArray(new Object[params.size()]));
198     }
199 
200     private DocumentBuilder getDocumentBuilder()
201             throws ParserConfigurationException {
202         final DocumentBuilderFactory builderFactory =
203                 DocumentBuilderFactory.newInstance();
204         return builderFactory.newDocumentBuilder();
205     }
206 
207 }