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.context;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.util.Collection;
24  import java.util.HashMap;
25  import java.util.Map;
26  import javax.faces.application.ViewHandler;
27  import javax.faces.context.ExternalContext;
28  
29  import javax.servlet.ServletContext;
30  import net.sf.jasperreports.jsf.Constants;
31  import net.sf.jasperreports.jsf.InvalidEnvironmentException;
32  
33  import net.sf.jasperreports.jsf.component.UIReport;
34  import net.sf.jasperreports.jsf.renderkit.ReportRenderer;
35  
36  /**
37   * Helper class that will provide with utility methods related with the
38   * treatment of the faces' ExternalContext.
39   *
40   * @author A. Alonso Dominguez
41   */
42  public abstract class ExternalContextHelper {
43  
44      /** Name of the Portlet class. */
45      private static final String PORTLET_CLASS = "javax.portlet.Portlet";
46  
47      /** Name of the ResourceURL class. */
48      private static final String PORTLET_RESOURCEURL_CLASS =
49              "javax.portlet.ResourceURL";
50  
51      /** Name of the Bridge class. */
52      private static final String BRIDGE_CLASS = "javax.portlet.faces.Bridge";
53      
54      protected static final int BUFFER_SIZE = 2014;
55  
56      /**
57       * Obtains the application local instance of the ExternalContextHelper.
58       *
59       * @param context the current ExternalContext
60       * @return an instance of the ExternalContextHelper
61       */
62      protected static ExternalContextHelper newInstance (
63              final ExternalContext context)
64      throws InvalidEnvironmentException {
65          ExternalContextHelper instance = null;
66          if (isServletContext(context)) {
67              instance = new ServletContextHelper();
68          } else if (isPortletAvailable()) {
69              String portletVersion = getPortletVersion();
70  
71              if (!"2.0".equals(portletVersion)) {
72                  throw new InvalidEnvironmentException("Incorrect portlet"
73                          + " version: " + portletVersion);
74              }
75  
76              if (!isFacesBridgeAvailable()) {
77                  throw new InvalidEnvironmentException("Portlet 2.0"
78                          + " environment detected but not Faces' bridge has"
79                          + " found. Please use a portlet faces bridge"
80                          + " compliant with JSR-329.");
81              }
82  
83              instance = new PortletContextHelper();
84          } else {
85              throw new IllegalArgumentException(
86                      "Unrecognized application context: " + 
87                      context.getContext().getClass().getName());
88          }
89          return instance;
90      }
91  
92      /**
93       * Detects if the faces bridge is available for this application.
94       *
95       * @return <code>true</code> if the faces bridge is available -
96       *         <code>false</code> otherwise
97       */
98      public static boolean isFacesBridgeAvailable() {
99          boolean bridgeAvailable = false;
100         try {
101             Class.forName(BRIDGE_CLASS);
102             bridgeAvailable = true;
103         } catch (final ClassNotFoundException e) {
104             bridgeAvailable = false;
105         } catch (final NoClassDefFoundError e) {
106             bridgeAvailable = false;
107         }
108         return bridgeAvailable;
109     }
110 
111     /**
112      * Detects if the portlet environment is available for this application.
113      *
114      * @return <code>true</code> if the Portlet environment is available -
115      *         <code>false</code> otherwise
116      */
117     public static boolean isPortletAvailable() {
118         boolean portletAvailable = false;
119         try {
120             Class.forName(PORTLET_CLASS);
121             portletAvailable = true;
122         } catch (final ClassNotFoundException e) {
123             portletAvailable = false;
124         } catch (final NoClassDefFoundError e) {
125             portletAvailable = false;
126         }
127         return portletAvailable;
128     }
129 
130     /**
131      * Obtains the current portlet version in use.
132      *
133      * @return the current portlet version
134      */
135     public static String getPortletVersion() {
136         final boolean portletAvailable = isPortletAvailable();
137 
138         String portletVersion = null;
139         try {
140             Class.forName(PORTLET_RESOURCEURL_CLASS);
141             portletVersion = "2.0";
142         } catch (final ClassNotFoundException e) {
143             portletVersion = portletAvailable ? "1.0" : null;
144         } catch (final NoClassDefFoundError e) {
145             portletVersion = portletAvailable ? "1.0" : null;
146         }
147 
148         return portletVersion;
149     }
150 
151     /**
152      * Detects if working with a servlet context.
153      *
154      * @param context the current ExternalContext
155      * @return <code>true</code> if the Portlet context is available -
156      *         <code>false</code> otherwise
157      */
158     public static boolean isServletContext(final ExternalContext context) {
159         final Object ctx = context.getContext();
160         return (ctx instanceof ServletContext);
161     }
162 
163     /**
164      * Protected constructor to prevent instantiation.
165      */
166     protected ExternalContextHelper() { }
167 
168     public abstract Collection<ContentType> getAcceptedContentTypes(
169     		final ExternalContext context);
170     
171     /**
172      * Creates a <code>ReportRenderRequest</code> based on the data code in the
173      * current ExternalContext.
174      *
175      * @param context the current ExternalContext
176      * @return A representation of the request render request
177      */
178     public abstract ReportRenderRequest restoreReportRequest(
179             ExternalContext context);
180 
181     /**
182      * Gets the request uri.
183      *
184      * @param context the context
185      * @return the request uri
186      */
187     public abstract String getRequestURI(final ExternalContext context);
188 
189     /**
190      * Obtains the server name of the current request.
191      *
192      * @param context the current ExternalContext
193      * @return the server name
194      */
195     public abstract String getRequestServerName(final ExternalContext context);
196 
197     /**
198      * Obtains the real path name of the resource local to the current context.
199      *
200      * @param context the current ExternalContext
201      * @param name the resource name
202      * @return the resource real path name
203      */
204     public abstract String getResourceRealPath(
205             final ExternalContext context, String name);
206 
207     /**
208      * Obtains the view chache map used to restore views which
209      * contains report references.
210      *
211      * @param context the current ExternalContext
212      * @return the view cache map
213      */
214     @SuppressWarnings({ "unchecked", "rawtypes" })
215     public final Map<String, String> getViewCacheMap(
216             final ExternalContext context) {
217         Map<String, String> cacheMap = (Map) context.getSessionMap()
218                 .get(Constants.VIEW_CACHE_KEY);
219         if (cacheMap == null) {
220             cacheMap = new HashMap<String, String>();
221             context.getSessionMap().put(
222                     Constants.VIEW_CACHE_KEY, cacheMap);
223         }
224         return cacheMap;
225     }
226 
227     /**
228      * Obtains the view identifier associated with the current request.
229      *
230      * @param context the current ExternalContext
231      * @return the view identifier
232      */
233     public final String getViewId(final ExternalContext context) {
234         String pathInfo = context.getRequestPathInfo();
235         String servletPath = context.getRequestServletPath();
236         if (pathInfo == null) {
237             String suffix = context.getInitParameter(
238                     ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
239             if (suffix == null || suffix.length() == 0) {
240                 suffix = ViewHandler.DEFAULT_SUFFIX;
241             }
242             return servletPath.substring(0, servletPath
243                     .lastIndexOf('.')) + suffix;
244         } else {
245             return pathInfo;
246         }
247     }
248 
249     /**
250      * Writes the report headers into the current response using the report
251      * renderer.
252      *
253      * @param context the current ExternalContext
254      * @param renderer the report renderer instance
255      * @param report the report component instance
256      * @throws IOException if any input or output error happens when writing
257      *         the report headers
258      */
259     public abstract void writeHeaders(ExternalContext context,
260             ReportRenderer renderer, UIReport report) throws IOException;
261 
262     /**
263      * Writes the report contents into the context response.
264      *
265      * @param context the context
266      * @param contentType the content type
267      * @param stream source from which read the data
268      * @throws IOException Signals that an I/O exception has occurred.
269      */
270     public abstract void writeResponse(
271     		final ExternalContext context,
272             final ContentType contentType, 
273             final InputStream stream) 
274     throws IOException;
275 
276 }