001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
003 * agreements. See the NOTICE file distributed with this work for additional information regarding
004 * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
005 * "License"); you may not use this file except in compliance with the License. You may obtain a
006 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable
007 * law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
008 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
009 * for the specific language governing permissions and limitations under the License.
010 */
011 package javax.portlet.faces;
012
013 import java.io.BufferedReader;
014 import java.io.IOException;
015 import java.io.InputStream;
016 import java.io.InputStreamReader;
017 import java.io.UnsupportedEncodingException;
018
019 import java.util.ArrayList;
020 import java.util.Enumeration;
021 import java.util.HashMap;
022 import java.util.List;
023 import java.util.Map;
024
025 import javax.portlet.ActionRequest;
026 import javax.portlet.ActionResponse;
027 import javax.portlet.EventRequest;
028 import javax.portlet.EventResponse;
029 import javax.portlet.GenericPortlet;
030 import javax.portlet.PortletConfig;
031 import javax.portlet.PortletContext;
032 import javax.portlet.PortletException;
033 import javax.portlet.PortletMode;
034 import javax.portlet.PortletRequest;
035 import javax.portlet.PortletRequestDispatcher;
036 import javax.portlet.PortletResponse;
037 import javax.portlet.RenderRequest;
038 import javax.portlet.RenderResponse;
039 import javax.portlet.ResourceRequest;
040 import javax.portlet.ResourceResponse;
041 import javax.portlet.WindowState;
042
043 /**
044 * The <code>GenericFacesPortlet</code> is provided to simplify development of a portlet that in
045 * whole or part relies on the Faces bridge to process requests. If all requests are to be handled
046 * by the bridge, <code>GenericFacesPortlet</code> is a turnkey implementation. Developers do not
047 * need to subclass it. However, if there are some situations where the portlet doesn't require
048 * bridge services then <code>GenericFacesPortlet</code> can be subclassed and overriden.
049 * <p>
050 * Since <code>GenericFacesPortlet</code> subclasses <code>GenericPortlet</code> care is taken
051 * to all subclasses to override naturally. For example, though <code>doDispatch()</code> is
052 * overriden, requests are only dispatched to the bridge from here if the <code>PortletMode</code>
053 * isn't <code>VIEW</code>, <code>EDIT</code>, or <code>HELP</code>.
054 * <p>
055 * The <code>GenericFacesPortlet</code> recognizes the following portlet initialization
056 * parameters:
057 * <ul>
058 * <li><code>javax.portlet.faces.defaultViewId.[<i>mode</i>]</code>: specifies on a per mode
059 * basis the default viewId the Bridge executes when not already encoded in the incoming request. A
060 * value must be defined for each <code>PortletMode</code> the <code>Bridge</code> is expected
061 * to process. </li>
062 * <li><code>javax.portlet.faces.excludedRequestAttributes</code>: specifies on a per portlet
063 * basis the set of request attributes the bridge is to exclude from its request scope. The
064 * value of this parameter is a comma delimited list of either fully qualified attribute names or
065 * a partial attribute name of the form <i>packageName.*</i>. In this later case all attributes
066 * exactly prefixed by <i>packageName</i> are excluded, non recursive.</li>
067 * <li><code>javax.portlet.faces.preserveActionParams</code>: specifies on a per portlet
068 * basis whether the bridge should preserve parameters received in an action request
069 * and restore them for use during subsequent renders.</li>
070 * <li><code>javax.portlet.faces.defaultContentType</code>: specifies on a per mode
071 * basis the content type the bridge should set for all render requests it processes. </li>
072 * <li><code>javax.portlet.faces.defaultCharacterSetEncoding</code>: specifies on a per mode
073 * basis the default character set encoding the bridge should set for all render requests it
074 * processes</li>
075 * </ul>
076 * The <code>GenericFacesPortlet</code> recognizes the following application
077 * (<code>PortletContext</code>) initialization parameters:
078 * <ul>
079 * <li><code>javax.portlet.faces.BridgeImplClass</code>: specifies the <code>Bridge</code>implementation
080 * class used by this portlet. Typically this initialization parameter isn't set as the
081 * <code>GenericFacesPortlet</code> defaults to finding the class name from the bridge
082 * configuration. However if more then one bridge is configured in the environment such
083 * per application configuration is necessary to force a specific bridge to be used.
084 * </li>
085 * </ul>
086 */
087 public class GenericFacesPortlet extends GenericPortlet
088 {
089 /** Application (PortletContext) init parameter that names the bridge class used
090 * by this application. Typically not used unless more then 1 bridge is configured
091 * in an environment as its more usual to rely on the self detection.
092 */
093 public static final String BRIDGE_CLASS = Bridge.BRIDGE_PACKAGE_PREFIX + "BridgeClassName";
094
095
096 /** Portlet init parameter that defines the default ViewId that should be used
097 * when the request doesn't otherwise convery the target. There must be one
098 * initialization parameter for each supported mode. Each parameter is named
099 * DEFAULT_VIEWID.<i>mode</i>, where <i>mode</i> is the name of the corresponding
100 * <code>PortletMode</code>
101 */
102 public static final String DEFAULT_VIEWID = Bridge.BRIDGE_PACKAGE_PREFIX + "defaultViewId";
103
104
105 /** Portlet init parameter that defines the render response ContentType the bridge
106 * sets prior to rendering. If not set the bridge uses the request's preferred
107 * content type.
108 */
109 public static final String DEFAULT_CONTENT_TYPE =
110 Bridge.BRIDGE_PACKAGE_PREFIX + "defaultContentType";
111
112 /** Portlet init parameter that defines the render response CharacterSetEncoding the bridge
113 * sets prior to rendering. Typcially only set when the jsp outputs an encoding other
114 * then the portlet container's and the portlet container supports response encoding
115 * transformation.
116 */
117 public static final String DEFAULT_CHARACTERSET_ENCODING =
118 Bridge.BRIDGE_PACKAGE_PREFIX + "defaultCharacterSetEncoding";
119
120 /** Portlet init parameter containing the setting for whether the <code>GenericFacesPortlet</code>
121 * overrides event processing by dispatching all events to the bridge or delegates
122 * all event processing to the <code>GenericPortlet</code>. Default is <code>true</code>.
123 */
124 public static final String BRIDGE_AUTO_DISPATCH_EVENTS = Bridge.BRIDGE_PACKAGE_PREFIX + "autoDispatchEvents";
125
126 /** Location of the services descriptor file in a brige installation that defines
127 * the class name of the bridge implementation.
128 */
129 public static final String BRIDGE_SERVICE_CLASSPATH =
130 "META-INF/services/javax.portlet.faces.Bridge";
131
132 private static final String LOGGING_ENABLED = "org.apache.myfaces.portlet.faces.loggingEnabled";
133
134 private Class<? extends Bridge> mFacesBridgeClass = null;
135 private Bridge mFacesBridge = null;
136 private HashMap<String, String> mDefaultViewIdMap = null;
137 private Object mLock = new Object(); // used to synchronize on when initializing the bridge.
138
139 /**
140 * Initialize generic faces portlet from portlet.xml
141 */
142 @SuppressWarnings("unchecked")
143 @Override
144 public void init(PortletConfig portletConfig) throws PortletException
145 {
146 super.init(portletConfig);
147
148 // Make sure the bridge impl class is defined -- if not then search for it
149 // using same search rules as Faces
150 String bridgeClassName = getBridgeClassName();
151
152 if (bridgeClassName != null)
153 {
154 try
155 {
156 ClassLoader loader = Thread.currentThread().getContextClassLoader();
157 mFacesBridgeClass = (Class<? extends Bridge>) loader.loadClass(bridgeClassName);
158 } catch (ClassNotFoundException cnfe)
159 {
160 throw new PortletException("Unable to load configured bridge class: " + bridgeClassName);
161 }
162 }
163 else
164 {
165 throw new PortletException("Can't locate configuration parameter defining the bridge class to use for this portlet:" + getPortletName());
166 }
167
168 // Get the other bridge configuration parameters and set as context attributes
169 List<String> excludedAttrs = getExcludedRequestAttributes();
170 if (excludedAttrs != null)
171 {
172 getPortletContext().setAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + getPortletName() + "." +
173 Bridge.EXCLUDED_REQUEST_ATTRIBUTES, excludedAttrs);
174 }
175
176 Boolean preserveActionParams = new Boolean(isPreserveActionParameters());
177 getPortletContext().setAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + getPortletName() + "." +
178 Bridge.PRESERVE_ACTION_PARAMS, preserveActionParams);
179
180 String defaultRenderKitId = getDefaultRenderKitId();
181 if (defaultRenderKitId != null)
182 {
183 getPortletContext().setAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + getPortletName() + "." +
184 Bridge.DEFAULT_RENDERKIT_ID, defaultRenderKitId);
185 }
186
187 Map defaultViewIdMap = getDefaultViewIdMap();
188 getPortletContext().setAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + getPortletName() + "." +
189 Bridge.DEFAULT_VIEWID_MAP, defaultViewIdMap);
190
191 BridgeEventHandler eventHandler = getBridgeEventHandler();
192 if (eventHandler != null)
193 {
194 getPortletContext().setAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + getPortletName() + "." +
195 Bridge.BRIDGE_EVENT_HANDLER, eventHandler);
196 }
197
198 BridgePublicRenderParameterHandler prpHandler = getBridgePublicRenderParameterHandler();
199 if (prpHandler != null)
200 {
201 getPortletContext().setAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + getPortletName() + "." +
202 Bridge.BRIDGE_PUBLIC_RENDER_PARAMETER_HANDLER, prpHandler);
203 }
204
205 // See if this portlet has enabled informational logging messages
206 String s = getPortletConfig().getInitParameter(LOGGING_ENABLED);
207 Boolean b = Boolean.valueOf(s);
208 getPortletContext().setAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + getPortletName() + "." +
209 LOGGING_ENABLED, b);
210
211 // Initialize the bridge as the double lock mechanism used for lazy instantiation doesn't (always) work in Java even if
212 // declared a volitle -- and the bridge is likely to be used anyway -- so why worry about it
213 initBridge();
214 }
215
216 /**
217 * Release resources, specifically it destroys the bridge.
218 */
219 @Override
220 public void destroy()
221 {
222 if (mFacesBridge != null)
223 {
224 mFacesBridge.destroy();
225 mFacesBridge = null;
226 mFacesBridgeClass = null;
227 }
228 mDefaultViewIdMap = null;
229
230 super.destroy();
231 }
232
233 /**
234 * If mode is VIEW, EDIT, or HELP -- defer to the doView, doEdit, doHelp so subclasses can
235 * override. Otherwise handle mode here if there is a defaultViewId mapping for it.
236 */
237 @Override
238 public void doDispatch(RenderRequest request, RenderResponse response) throws PortletException,
239 IOException
240 {
241 // Defer to helper methods for standard modes so subclasses can override
242 PortletMode mode = request.getPortletMode();
243 if (mode.equals(PortletMode.EDIT) || mode.equals(PortletMode.HELP) || mode.equals(PortletMode.VIEW))
244 {
245 super.doDispatch(request, response);
246 } else
247 {
248 // Bridge didn't process this one -- so forge ahead
249 if (!doRenderDispatchInternal(request, response))
250 {
251 super.doDispatch(request, response);
252 }
253 }
254 }
255
256 @Override
257 protected void doEdit(RenderRequest request, RenderResponse response) throws PortletException,
258 java.io.IOException
259 {
260 doRenderDispatchInternal(request, response);
261 }
262
263 @Override
264 protected void doHelp(RenderRequest request, RenderResponse response) throws PortletException,
265 java.io.IOException
266 {
267 doRenderDispatchInternal(request, response);
268 }
269
270 @Override
271 protected void doView(RenderRequest request, RenderResponse response) throws PortletException,
272 java.io.IOException
273 {
274 doRenderDispatchInternal(request, response);
275 }
276
277 @Override
278 public void processAction(ActionRequest request,
279 ActionResponse response) throws PortletException, IOException
280 {
281 doActionDispatchInternal(request, response);
282 }
283
284 /**
285 * Handles resource requests and dispatches to the Bridge
286 */
287 @Override
288 public void serveResource(ResourceRequest request,
289 ResourceResponse response) throws PortletException, IOException
290 {
291 doBridgeDispatch(request, response);
292
293 }
294
295 /**
296 * Returns an instance of a BridgeEventHandler used to process portlet events
297 * in a JSF environment.
298 * This default implementation looks for a portlet initParameter that
299 * names the class used to instantiate the handler.
300 * @return an instance of BridgeEventHandler or null if there is none.
301 */
302 public BridgeEventHandler getBridgeEventHandler()
303 {
304 String eventHandlerClass =
305 getPortletConfig().getInitParameter(Bridge.BRIDGE_PACKAGE_PREFIX + Bridge.BRIDGE_EVENT_HANDLER);
306 if (eventHandlerClass != null)
307 {
308 try
309 {
310 ClassLoader loader = Thread.currentThread().getContextClassLoader();
311 Class<? extends BridgeEventHandler> c =
312 (Class<? extends BridgeEventHandler>) loader.loadClass(eventHandlerClass);
313 return c.newInstance();
314 } catch (ClassNotFoundException cnfe)
315 {
316 // Do nothing and fall through to null check
317 // TODO: log something
318 } catch (InstantiationException ie)
319 {
320 // Do nothing and fall through to null check
321 // TODO: log something
322 } catch (Exception e)
323 {
324 // Do nothing and fall through to null check
325 // TODO: log something
326 }
327 }
328
329 return null;
330 }
331
332 /**
333 * Returns an instance of a BridgePublicRenderParameterHandler used to post
334 * process public render parameter changes that the bridge
335 * has pushed into mapped models.
336 * This default implementation looks for a portlet initParameter that
337 * names the class used to instantiate the handler.
338 * @return an instance of BridgeRenderParameterHandler or null if there is none.
339 */
340 public BridgePublicRenderParameterHandler getBridgePublicRenderParameterHandler()
341 {
342 String prpHandlerClass =
343 getPortletConfig().getInitParameter(Bridge.BRIDGE_PACKAGE_PREFIX + Bridge.BRIDGE_PUBLIC_RENDER_PARAMETER_HANDLER);
344 if (prpHandlerClass != null)
345 {
346 try
347 {
348 ClassLoader loader = Thread.currentThread().getContextClassLoader();
349 Class<? extends BridgePublicRenderParameterHandler> c =
350 (Class<? extends BridgePublicRenderParameterHandler>) loader.loadClass(prpHandlerClass);
351 return c.newInstance();
352 } catch (ClassNotFoundException cnfe)
353 {
354 // Do nothing and fall through to null check
355 // TODO: log something
356 } catch (InstantiationException ie)
357 {
358 // Do nothing and fall through to null check
359 // TODO: log something
360 } catch (Exception e)
361 {
362 // Do nothing and fall through to null check
363 // TODO: log something
364 }
365 }
366
367 return null;
368 }
369
370
371
372 /**
373 * Returns the set of RequestAttribute names that the portlet wants the bridge to
374 * exclude from its managed request scope. This default implementation picks up
375 * this list from the comma delimited init_param javax.portlet.faces.excludedRequestAttributes.
376 *
377 * @return a List containing the names of the attributes to be excluded. null if it can't be
378 * determined.
379 */
380 public List<String> getExcludedRequestAttributes()
381 {
382 String excludedAttrs =
383 getPortletConfig().getInitParameter(Bridge.BRIDGE_PACKAGE_PREFIX + Bridge.EXCLUDED_REQUEST_ATTRIBUTES);
384 if (excludedAttrs == null)
385 {
386 return null;
387 }
388
389 String[] attrArray = excludedAttrs.split(",");
390 // process comma delimited String into a List
391 ArrayList<String> list = new ArrayList(attrArray.length);
392 for (int i = 0; i < attrArray.length; i++)
393 {
394 list.add(attrArray[i].trim());
395 }
396 return list;
397 }
398
399 /**
400 * Returns a boolean indicating whether or not the bridge should preserve all the
401 * action parameters in the subsequent renders that occur in the same scope. This
402 * default implementation reads the values from the portlet init_param
403 * javax.portlet.faces.preserveActionParams. If not present, false is returned.
404 *
405 * @return a boolean indicating whether or not the bridge should preserve all the
406 * action parameters in the subsequent renders that occur in the same scope.
407 */
408 public boolean isPreserveActionParameters()
409 {
410 String preserveActionParams =
411 getPortletConfig().getInitParameter(Bridge.BRIDGE_PACKAGE_PREFIX +
412 Bridge.PRESERVE_ACTION_PARAMS);
413 if (preserveActionParams == null)
414 {
415 return false;
416 } else
417 {
418 return Boolean.parseBoolean(preserveActionParams);
419 }
420 }
421
422 /**
423 * Returns a String defining the default render kit id the bridge should ensure for this portlet.
424 * If non-null, this value is used to override any default render kit id set on an app wide basis
425 * in the faces-config.xml. This
426 * default implementation reads the values from the portlet init_param
427 * javax.portlet.faces.defaultRenderKitId. If not present, null is returned.
428 *
429 * @return a boolean indicating whether or not the bridge should preserve all the
430 * action parameters in the subsequent renders that occur in the same scope.
431 */
432 public String getDefaultRenderKitId()
433 {
434 return
435 getPortletConfig().getInitParameter(Bridge.BRIDGE_PACKAGE_PREFIX +
436 Bridge.DEFAULT_RENDERKIT_ID);
437 }
438
439 /**
440 * Returns the className of the bridge implementation this portlet uses. Subclasses override to
441 * alter the default behavior. Default implementation first checks for a portlet context init
442 * parameter: javax.portlet.faces.BridgeImplClass. If it doesn't exist then it looks for the
443 * resource file "META-INF/services/javax.portlet.faces.Bridge" using the current threads
444 * classloader and extracts the classname from the first line in that file.
445 *
446 * @return the class name of the Bridge class the GenericFacesPortlet uses. null if it can't be
447 * determined.
448 */
449 public String getBridgeClassName()
450 {
451 String bridgeClassName = getPortletConfig().getPortletContext().getInitParameter(BRIDGE_CLASS);
452
453 if (bridgeClassName == null)
454 {
455 bridgeClassName =
456 getFromServicesPath(getPortletConfig().getPortletContext(), BRIDGE_SERVICE_CLASSPATH);
457 }
458 return bridgeClassName;
459 }
460
461 /**
462 * @deprecated -- no longer used or called by the <code>GenericFacesPortlet</code>
463 * but retained in case a subclass has called it.
464 *
465 *
466 * @return request.getResponseContentType().
467 */
468 @Deprecated
469 public String getResponseContentType(PortletRequest request)
470 {
471 return request.getResponseContentType();
472 }
473
474 private boolean isInRequestedContentTypes(PortletRequest request, String contentTypeToCheck)
475 {
476 Enumeration e = request.getResponseContentTypes();
477 while (e.hasMoreElements())
478 {
479 if (contentTypeToCheck.equalsIgnoreCase((String) e.nextElement()))
480 {
481 return true;
482 }
483 }
484 return false;
485 }
486
487 /**
488 * @deprecated -- no longer used or called by the <code>GenericFacesPortlet</code>
489 * but retained in case a subclass has called it.
490 *
491 *
492 * @return null.
493 */
494 @Deprecated
495 public String getResponseCharacterSetEncoding(PortletRequest request)
496 {
497 return null;
498 }
499
500
501 /**
502 * Returns the defaultViewIdMap the bridge should use when its unable to resolve to a specific
503 * target in the incoming request. There is one entry per support <code>PortletMode
504 * </code>. The entry key is the name of the mode. The entry value is the default viewId
505 * for that mode.
506 *
507 * @return the defaultViewIdMap
508 */
509 public Map getDefaultViewIdMap()
510 {
511 if (mDefaultViewIdMap == null)
512 {
513 mDefaultViewIdMap = new HashMap<String, String>();
514 // loop through all portlet initialization parameters looking for those in the
515 // correct form
516 PortletConfig config = getPortletConfig();
517
518 Enumeration<String> e = config.getInitParameterNames();
519 int len = DEFAULT_VIEWID.length();
520 while (e.hasMoreElements())
521 {
522 String s = e.nextElement();
523 if (s.startsWith(DEFAULT_VIEWID) && s.length() > DEFAULT_VIEWID.length())
524 {
525 String viewId = config.getInitParameter(s);
526
527 // Don't add if there isn't a view
528 if (viewId == null || viewId.length() == 0) continue;
529
530 // extract the mode
531 s = s.substring(len + 1);
532 mDefaultViewIdMap.put(s, viewId);
533 }
534 }
535 }
536
537 return mDefaultViewIdMap;
538 }
539
540 /**
541 * Returns the value of the portlet initialization parameter
542 * <code>javax.portlet.faces.autoDispatchEvents</code> if non-null or
543 * <code>true</code>, otherwise.
544 *
545 * @return boolean indicating whether to auto-dispatch all events to the bridge
546 * or not.
547 */
548 public boolean isAutoDispatchEvents()
549 {
550 String configParam =
551 getPortletConfig().getInitParameter(BRIDGE_AUTO_DISPATCH_EVENTS);
552
553 if (configParam != null)
554 {
555 return Boolean.parseBoolean(configParam);
556 }
557 else
558 {
559 return true;
560 }
561 }
562
563 /**
564 * Returns an initialized bridge instance adequately prepared so the caller can
565 * call doFacesRequest directly without further initialization.
566 *
567 * @return instance of the bridge.
568 * @throws PortletException exception acquiring or initializting the bridge.
569 */
570 public Bridge getFacesBridge(PortletRequest request,
571 PortletResponse response) throws PortletException
572 {
573 initBridgeRequest(request, response);
574 return mFacesBridge;
575 }
576
577 public void processEvent(EventRequest request, EventResponse response)
578 throws PortletException, java.io.IOException
579 {
580 if (isAutoDispatchEvents())
581 {
582 try
583 {
584 getFacesBridge(request, response).doFacesRequest(request, response);
585 } catch (BridgeException e)
586 {
587 throw new PortletException("doBridgeDispatch failed: error from Bridge in executing the request",
588 e);
589 }
590 }
591 else
592 {
593 super.processEvent(request, response);
594 }
595 }
596
597 private boolean isNonFacesRequest(PortletRequest request, PortletResponse response)
598 {
599 // Non Faces request is identified by either the presence of the _jsfBridgeNonFacesView
600 // parameter or the request being for a portlet mode which doesn't have a default
601 // Faces view configured for it.
602 if (request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER) != null)
603 {
604 return true;
605 }
606
607 String modeDefaultViewId = mDefaultViewIdMap.get(request.getPortletMode().toString());
608 return modeDefaultViewId == null;
609 }
610
611 private void doActionDispatchInternal(ActionRequest request,
612 ActionResponse response) throws PortletException,
613 IOException
614 {
615 // First determine whether this is a Faces or nonFaces request
616 if (isNonFacesRequest(request, response))
617 {
618 throw new PortletException("GenericFacesPortlet: Action request is not for a Faces target. Such nonFaces requests must be handled by a subclass.");
619 } else
620 {
621 doBridgeDispatch(request, response);
622 }
623 }
624
625 private boolean doRenderDispatchInternal(RenderRequest request,
626 RenderResponse response) throws PortletException,
627 IOException
628 {
629 // First determine whether this is a Faces or nonFaces request
630 if (isNonFacesRequest(request, response))
631 {
632 return doNonFacesDispatch(request, response);
633 } else
634 {
635 WindowState state = request.getWindowState();
636 if (!state.equals(WindowState.MINIMIZED))
637 {
638 doBridgeDispatch(request, response);
639 }
640 return true;
641 }
642 }
643
644 private boolean doNonFacesDispatch(RenderRequest request,
645 RenderResponse response) throws PortletException
646 {
647 // Can only dispatch if the path is encoded in the request parameter
648 String targetPath = request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER);
649 if (targetPath == null)
650 {
651 // Didn't handle this request
652 return false;
653 }
654
655 try
656 {
657 PortletRequestDispatcher dispatcher =
658 this.getPortletContext().getRequestDispatcher(targetPath);
659 dispatcher.forward(request, response);
660 return true;
661 } catch (Exception e)
662 {
663 throw new PortletException("Unable to dispatch to: " + targetPath, e);
664 }
665 }
666
667 private void doBridgeDispatch(RenderRequest request,
668 RenderResponse response) throws PortletException
669 {
670 try
671 {
672 getFacesBridge(request, response).doFacesRequest(request, response);
673 } catch (BridgeException e)
674 {
675 throw new PortletException("doBridgeDispatch failed: error from Bridge in executing the request",
676 e);
677 }
678
679 }
680
681 private void doBridgeDispatch(ActionRequest request,
682 ActionResponse response) throws PortletException
683 {
684 try
685 {
686 getFacesBridge(request, response).doFacesRequest(request, response);
687 } catch (BridgeException e)
688 {
689 throw new PortletException("doBridgeDispatch failed: error from Bridge in executing the request",
690 e);
691 }
692
693 }
694
695 private void doBridgeDispatch(ResourceRequest request,
696 ResourceResponse response) throws PortletException
697 {
698 try
699 {
700 getFacesBridge(request, response).doFacesRequest(request, response);
701 } catch (BridgeException e)
702 {
703 throw new PortletException("doBridgeDispatch failed: error from Bridge in executing the request",
704 e);
705 }
706
707 }
708
709 private void initBridgeRequest(PortletRequest request,
710 PortletResponse response) throws PortletException
711 {
712 // Now do any per request initialization
713 // In this case look to see if the request is encoded (usually
714 // from a NonFaces view response) with the specific Faces
715 // view to execute.
716 String view = request.getParameter(Bridge.FACES_VIEW_ID_PARAMETER);
717 if (view != null)
718 {
719 request.setAttribute(Bridge.VIEW_ID, view);
720 } else
721 {
722 view = request.getParameter(Bridge.FACES_VIEW_PATH_PARAMETER);
723 if (view != null)
724 {
725 request.setAttribute(Bridge.VIEW_PATH, view);
726 }
727 }
728 }
729
730 private void initBridge() throws PortletException
731 {
732 // Ensure te Bridge has been constrcuted and initialized
733 if (mFacesBridge == null)
734 {
735 try
736 {
737 // ensure we only ever create/init one bridge per portlet
738 if (mFacesBridge == null)
739 {
740 mFacesBridge = mFacesBridgeClass.newInstance();
741 mFacesBridge.init(getPortletConfig());
742 }
743 }
744 catch (Exception e)
745 {
746 throw new PortletException("doBridgeDisptach: error instantiating the bridge class", e);
747 }
748 }
749 }
750
751 private String getFromServicesPath(PortletContext context, String resourceName)
752 {
753 // Check for a services definition
754 String result = null;
755 BufferedReader reader = null;
756 InputStream stream = null;
757 try
758 {
759 ClassLoader cl = Thread.currentThread().getContextClassLoader();
760 if (cl == null)
761 {
762 return null;
763 }
764
765 stream = cl.getResourceAsStream(resourceName);
766 if (stream != null)
767 {
768 // Deal with systems whose native encoding is possibly
769 // different from the way that the services entry was created
770 try
771 {
772 reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
773 } catch (UnsupportedEncodingException e)
774 {
775 reader = new BufferedReader(new InputStreamReader(stream));
776 }
777 result = reader.readLine();
778 if (result != null)
779 {
780 result = result.trim();
781 }
782 reader.close();
783 reader = null;
784 stream = null;
785 }
786 } catch (IOException e)
787 {
788 } catch (SecurityException e)
789 {
790 } finally
791 {
792 if (reader != null)
793 {
794 try
795 {
796 reader.close();
797 stream = null;
798 } catch (Throwable t)
799 {
800 ;
801 }
802 reader = null;
803 }
804 if (stream != null)
805 {
806 try
807 {
808 stream.close();
809 } catch (Throwable t)
810 {
811 ;
812 }
813 stream = null;
814 }
815 }
816 return result;
817 }
818
819 }