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 }