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