KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icesoft > faces > application > D2DViewHandler


1 /*
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * "The contents of this file are subject to the Mozilla Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
11  * License for the specific language governing rights and limitations under
12  * the License.
13  *
14  * The Original Code is ICEfaces 1.5 open source software code, released
15  * November 5, 2006. The Initial Developer of the Original Code is ICEsoft
16  * Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
17  * 2004-2006 ICEsoft Technologies Canada, Corp. All Rights Reserved.
18  *
19  * Contributor(s): _____________________.
20  *
21  * Alternatively, the contents of this file may be used under the terms of
22  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
23  * License), in which case the provisions of the LGPL License are
24  * applicable instead of those above. If you wish to allow use of your
25  * version of this file only under the terms of the LGPL License and not to
26  * allow others to use your version of this file under the MPL, indicate
27  * your decision by deleting the provisions above and replace them with
28  * the notice and other provisions required by the LGPL License. If you do
29  * not delete the provisions above, a recipient may use your version of
30  * this file under either the MPL or the LGPL License."
31  *
32  */

33
34 package com.icesoft.faces.application;
35
36 import com.icesoft.faces.component.NamespacingViewRoot;
37 import com.icesoft.faces.context.BridgeExternalContext;
38 import com.icesoft.faces.context.BridgeFacesContext;
39 import com.icesoft.faces.context.DOMResponseWriter;
40 import com.icesoft.faces.webapp.http.servlet.ServletExternalContext;
41 import com.icesoft.faces.webapp.parser.JspPageToDocument;
42 import com.icesoft.faces.webapp.parser.Parser;
43 import com.icesoft.faces.webapp.parser.ImplementationUtil;
44 import com.icesoft.faces.webapp.xmlhttp.PersistentFacesCommonlet;
45 import com.icesoft.jasper.Constants;
46 import com.icesoft.util.SeamUtilities;
47 import org.apache.commons.logging.Log;
48 import org.apache.commons.logging.LogFactory;
49
50 import javax.faces.FacesException;
51 import javax.faces.application.StateManager;
52 import javax.faces.application.ViewHandler;
53 import javax.faces.component.NamingContainer;
54 import javax.faces.component.StateHolder;
55 import javax.faces.component.UIComponent;
56 import javax.faces.component.UIData;
57 import javax.faces.component.UIViewRoot;
58 import javax.faces.context.ExternalContext;
59 import javax.faces.context.FacesContext;
60 import javax.faces.context.ResponseWriter;
61 import javax.faces.render.RenderKitFactory;
62 import java.beans.Beans JavaDoc;
63 import java.io.IOException JavaDoc;
64 import java.io.InputStream JavaDoc;
65 import java.io.InputStreamReader JavaDoc;
66 import java.io.Reader JavaDoc;
67 import java.net.URI JavaDoc;
68 import java.net.URISyntaxException JavaDoc;
69 import java.net.URL JavaDoc;
70 import java.net.URLConnection JavaDoc;
71 import java.net.URLEncoder JavaDoc;
72 import java.util.Arrays JavaDoc;
73 import java.util.HashMap JavaDoc;
74 import java.util.Iterator JavaDoc;
75 import java.util.Locale JavaDoc;
76 import java.util.Map JavaDoc;
77
78 /**
79  * <B>D2DViewHandler</B> is the ICEfaces ViewHandler implementation
80  *
81  * @see javax.faces.application.ViewHandler
82  */

83 public class D2DViewHandler extends ViewHandler {
84     // Log instance for this class
85
protected static Log log = LogFactory.getLog(D2DViewHandler.class);
86
87     static {
88         if (log.isInfoEnabled()) {
89             log.info(new ProductInfo().toString());//Announce ICEfaces
90
}
91     }
92
93     private final static String JavaDoc DELEGATE_NONIFACE =
94             "com.icesoft.faces.delegateNonIface";
95     private final static String JavaDoc ACTION_URL_SUFFIX =
96             "com.icesoft.faces.actionURLSuffix";
97     private final static String JavaDoc RELOAD_INTERVAL =
98             "com.icesoft.faces.reloadInterval";
99     private final static String JavaDoc DO_JSF_STATE_MANAGEMENT =
100             "com.icesoft.faces.doJSFStateManagement";
101     public final static String JavaDoc INCLUDE_OPEN_AJAX_HUB =
102             "com.icesoft.faces.openAjaxHub";
103     private final static String JavaDoc LAST_LOADED_KEY = "_lastLoaded";
104     private final static String JavaDoc LAST_CHECKED_KEY = "_lastChecked";
105     // Key for storing ICEfaces auxillary data in the session
106
public static final String JavaDoc DOM_CONTEXT_TABLE =
107             "com.icesoft.faces.sessionAuxiliaryData";
108     public static final String JavaDoc CHAR_ENCODING = "UTF-8";
109     public static final String JavaDoc HTML_CONTENT_TYPE =
110             "text/html;charset=" + CHAR_ENCODING;
111
112     public static final String JavaDoc DEFAULT_VIEW_ID = "default";
113
114     private String JavaDoc actionURLSuffix;
115     protected boolean delegateNonIface = false;
116     protected boolean delegateNonIfaceDefault = false;
117     protected boolean jsfStateManagement;
118     //reloadInterval internally in milliseconds
119
protected long reloadInterval;
120     protected long reloadIntervalDefault = 2;
121     private boolean parametersInitialized = false;
122
123     protected Parser parser;
124     private ViewHandler delegate;
125
126
127     public D2DViewHandler() {
128         try {
129             InputStream JavaDoc inputStream = this.getClass().getResourceAsStream("serializedTagToComponentMapFull.ser");
130             parser = new Parser(inputStream);
131         } catch (IOException JavaDoc e) {
132             throw new RuntimeException JavaDoc(e);
133         }
134     }
135
136     public D2DViewHandler(ViewHandler delegate) {
137         this();
138         this.delegate = delegate;
139     }
140
141     // Render the components
142
public void renderView(FacesContext context, UIViewRoot viewToRender)
143             throws IOException JavaDoc, FacesException {
144         initializeParameters(context);
145         if (delegateView(viewToRender.getViewId())) {
146             delegate.renderView(context, viewToRender);
147             return;
148         }
149
150         if (log.isTraceEnabled()) {
151             log.trace("renderView(FC,UIVR) BEFORE renderResponse " +
152                     "viewToRender.getViewId(): " + viewToRender.getViewId());
153         }
154         renderResponse(context);
155
156         if (jsfStateManagement) {
157             StateManager stateMgr = context.getApplication().getStateManager();
158             stateMgr.saveSerializedView(context);
159             // JSF 1.1 removes transient components here, but I don't think that 1.2 does
160
}
161
162        // This has been moved to the ServletView
163

164     }
165
166
167     /**
168      * Create a new ViewRoot
169      *
170      * @param context FacesContext
171      * @param viewId ViewId identifying the root
172      * @return A new viewRoot
173      */

174     public UIViewRoot createView(FacesContext context, String JavaDoc viewId) {
175         initializeParameters(context);
176
177         if (delegateView(viewId)) {
178             return delegate.createView(context, viewId);
179         }
180
181         UIViewRoot root = new NamespacingViewRoot(context);
182 // UIViewRoot root = new UIViewRoot();
183
root.setRenderKitId(RenderKitFactory.HTML_BASIC_RENDER_KIT);
184
185         Map JavaDoc contextServletTable =
186                 getContextServletTable(context);
187         if (null == viewId) {
188             root.setViewId("default");
189             context.setViewRoot(root);
190             contextServletTable
191                     .put(DOMResponseWriter.RESPONSE_VIEWROOT, root);
192             Locale JavaDoc locale = calculateLocale(context);
193             root.setLocale(locale);
194             return root;
195         }
196
197         root.setViewId(viewId);
198         context.setViewRoot(root);
199         contextServletTable.put(DOMResponseWriter.RESPONSE_VIEWROOT, root);
200
201         return root;
202     }
203
204     /**
205      * Restore the view if possible. This method can return null if
206      * no ViewRoot is available. The <code>LifeCycle</code> will call
207      * createView in this case.
208      *
209      * @param context FacesContext
210      * @param viewId ViewId identifying the view to restore
211      * @return UIViewRoot instance if found, null if none yet created,
212      * or if trying to model Seam JSF behaviour.
213      */

214     public UIViewRoot restoreView(FacesContext context, String JavaDoc viewId) {
215         this.initializeParameters(context);
216
217
218         if (delegateView(viewId)) {
219             return delegate.restoreView(context, viewId);
220         }
221
222         UIViewRoot currentRoot = context.getViewRoot();
223         //MyFaces expects path to match current view
224
ExternalContext externalContext = context.getExternalContext();
225
226         if (externalContext instanceof ServletExternalContext) {
227
228             ServletExternalContext servletExternalContext =
229                     (ServletExternalContext) externalContext;
230
231             servletExternalContext.setRequestServletPath(viewId);
232
233             if (null != externalContext.getRequestPathInfo()) {
234                 //it's not null, so must be valid to keep in synch for MyFaces
235
servletExternalContext.setRequestPathInfo(viewId);
236             }
237
238             if (SeamUtilities.isSeamEnvironment()) {
239                 if (servletExternalContext.getRequestParameterMap().remove(
240                         PersistentFacesCommonlet.SEAM_LIFECYCLE_SHORTCUT) != null) {
241
242                     if (log.isTraceEnabled()) {
243                         log.trace("Seam Keyword shortcut found, new ViewRoot");
244                     }
245                     return null;
246                 } else {
247                     if (log.isTraceEnabled()) {
248                         log.trace("No Seam Keyword shortcut found");
249                     }
250                 }
251             }
252         }
253
254         if (null != currentRoot &&
255                 mungeViewId(viewId)
256                         .equals(mungeViewId(
257                                 currentRoot.getViewId()))) {
258 // purgeSeamContexts(context, currentRoot);
259
return currentRoot;
260         }
261
262         Map JavaDoc contextServletTable =
263                 getContextServletTable(context);
264         Map JavaDoc domResponseContexts;
265         if (contextServletTable
266                 .containsKey(DOMResponseWriter.RESPONSE_CONTEXTS_TABLE)) {
267             domResponseContexts = (Map JavaDoc) contextServletTable
268                     .get(DOMResponseWriter.RESPONSE_CONTEXTS_TABLE);
269         } else {
270             domResponseContexts = new HashMap JavaDoc();
271             contextServletTable.put(DOMResponseWriter.RESPONSE_CONTEXTS_TABLE,
272                     domResponseContexts);
273         }
274
275         UIViewRoot root = null;
276
277         root = (UIViewRoot) contextServletTable
278                 .get(DOMResponseWriter.RESPONSE_VIEWROOT);
279
280         if ((null != root) && (null != viewId) &&
281                 (mungeViewId(viewId).equals(mungeViewId(root.getViewId())))) {
282         }
283
284         return root;
285     }
286
287
288     private static Map JavaDoc getContextServletTables(FacesContext context) {
289         Map JavaDoc sessionMap = context.getExternalContext().getSessionMap();
290         String JavaDoc viewNumber = "-";
291         if (context instanceof BridgeFacesContext) {
292             viewNumber = ((BridgeFacesContext) context).getViewNumber();
293         }
294
295         String JavaDoc treeKey = viewNumber + "/" + DOM_CONTEXT_TABLE;
296         Map JavaDoc contextTable;
297         if (sessionMap.containsKey(treeKey)) {
298             contextTable = (Map JavaDoc) sessionMap.get(treeKey);
299         } else {
300             contextTable = new HashMap JavaDoc();
301             sessionMap.put(treeKey, contextTable);
302         }
303
304         return contextTable;
305     }
306
307     public static Map JavaDoc getContextServletTable(FacesContext context) {
308         Map JavaDoc domContextTables = getContextServletTables(context);
309         String JavaDoc servletRequestPath =
310                 getServletRequestPath(context);
311         if (domContextTables.containsKey(servletRequestPath)) {
312             return (Map JavaDoc) domContextTables.get(servletRequestPath);
313         } else {
314             Map JavaDoc domContextTable = new HashMap JavaDoc();
315             domContextTables.put(servletRequestPath, domContextTable);
316             return domContextTable;
317         }
318     }
319
320     public static String JavaDoc getServletRequestPath(FacesContext context) {
321         if (Beans.isDesignTime()) {
322             //IDE scenario requires artificial path
323
return context.getViewRoot().getViewId();
324         }
325         ExternalContext externalContext = context.getExternalContext();
326         if (externalContext instanceof BridgeExternalContext) {
327             String JavaDoc uri = ((BridgeExternalContext) externalContext)
328                     .getRequestURI();
329             if (null == uri) {
330                 if (log.isWarnEnabled()) {
331                     log
332                             .warn("Failing over to default request path");
333                 }
334                 uri = "default";
335
336             }
337             return uri;
338         }
339         return (externalContext.getRequestContextPath() +
340                 externalContext.getRequestServletPath());
341     }
342
343     public static String JavaDoc getServletRequestPath(ExternalContext externalContext,
344                                                String JavaDoc viewId) {
345         if (externalContext == null) {
346             throw new IllegalStateException JavaDoc("ExternalContext is null");
347         }
348         return externalContext.getRequestContextPath() + viewId;
349     }
350
351     public String JavaDoc getActionURL(FacesContext context, String JavaDoc viewId) {
352         //Maybe should always use delegate
353
if (delegateView(viewId)) {
354             return delegate.getActionURL(context, viewId);
355         }
356
357         if (viewId.indexOf("://") >= 0) {
358             return viewId;
359         }
360
361         if (viewId.charAt(0) != '/') {
362             throw new IllegalArgumentException JavaDoc(
363                     "viewId " + viewId + "does not begin with '/'");
364         }
365
366         //remove extension and replace with parametrized suffix
367
if (null != actionURLSuffix) {
368             viewId =
369                     viewId.substring(0, viewId.lastIndexOf(".")) +
370                             actionURLSuffix;
371         }
372
373         return context.getExternalContext().getRequestContextPath() + viewId;
374     }
375
376     public String JavaDoc getResourceURL(FacesContext context, String JavaDoc path) {
377         //Context and resource must be non-null
378
if (context == null) {
379             throw new NullPointerException JavaDoc("context cannot be null");
380         }
381
382         if (path == null) {
383             throw new NullPointerException JavaDoc("path cannot be null");
384         }
385
386         //The URI class doesn't like resource with illegal characters so
387
//we need to do our own encoding.
388
path = encode(path);
389
390         ExternalContext extCtxt = context.getExternalContext();
391
392         // Components that render out links to resources like images, CSS,
393
// JavaScript, etc. must do it correctly. In a normal web app, there
394
// may not be much to do but in a portlet environment, we have to
395
// resolve these correctly.
396
if (isPortlet(extCtxt)) {
397             path = resolveFully(extCtxt, path);
398         } else {
399             //is it an absolute path?
400
if (path.startsWith("/")) {
401                 //resolve the path to the application's context
402
StringBuffer JavaDoc dir = new StringBuffer JavaDoc();
403                 int atoms = extCtxt.getRequestServletPath().split("/").length;
404                 while (atoms-- > 2) dir.append("../");
405                 path = URI.create(dir + "." + path).normalize().toString();
406             }
407             //else don't resolve (see: ViewHandler.getResourceURL javadocs)
408
}
409
410         return path;
411     }
412
413     private String JavaDoc encode(String JavaDoc path){
414         return path.trim().replaceAll(" ","%20");
415     }
416
417     private boolean isPortlet(ExternalContext extCtxt) {
418         return extCtxt.getRequestMap().get(Constants.PORTLET_KEY) != null;
419     }
420
421     /**
422      * Resolves references fragements to the full resource reference including
423      * the context path and the servlet path.
424      */

425     private String JavaDoc resolveFully(ExternalContext extCtxt, String JavaDoc resource) {
426
427         String JavaDoc context = extCtxt.getRequestContextPath();
428
429         //Absolute references are handled differently. For portlets, we just
430
//need to stick the context in front.
431
if( resource.startsWith("/") ){
432             return context + resource;
433         }
434
435         //For relative paths, we need to resolve them to the full path
436
String JavaDoc base = context + extCtxt.getRequestServletPath();
437         try {
438             URI JavaDoc baseURI = new URI JavaDoc(base);
439             URI JavaDoc resourceURI = new URI JavaDoc(resource);
440             URI JavaDoc resolvedURI = baseURI.resolve(resourceURI);
441             return resolvedURI.toString();
442
443         } catch (URISyntaxException JavaDoc e) {
444             if( log.isWarnEnabled() ){
445                 log.warn( "could not resolve URI's based on" +
446                           "\n context : " + extCtxt.getRequestContextPath() +
447                           "\n path : " + extCtxt.getRequestServletPath() +
448                           "\n resource: " + resource, e );
449             }
450             return resource;
451         }
452     }
453
454     protected long getTimeAttribute(UIComponent root, String JavaDoc key) {
455         Long JavaDoc timeLong = (Long JavaDoc) root.getAttributes().get(key);
456         long time = (null == timeLong) ? 0 :
457                 timeLong.longValue();
458         return time;
459     }
460
461     protected void renderResponse(FacesContext facesContext) throws IOException JavaDoc {
462         BridgeFacesContext context = (BridgeFacesContext) facesContext;
463         UIViewRoot root = context.getViewRoot();
464         String JavaDoc viewId = root.getViewId();
465
466         if (log.isTraceEnabled()) {
467             log.trace("Rendering " + root + " with " +
468                     root.getChildCount() + " children");
469         }
470
471         clearSession(context);
472         ResponseWriter responseWriter = context.createAndSetResponseWriter();
473
474         boolean reloadView = false;
475         URLConnection JavaDoc viewConnection = null;
476
477         if ((root.getChildCount() == 0) || (reloadInterval > -1)) {
478             // We have not parsed the page yet;
479
// Need an input stream for the page;
480
if (viewId.startsWith("/faces")) {
481                 viewId = viewId.substring(6);
482             }
483             if (viewId.endsWith(".jpg") || viewId.endsWith(".gif") ||
484                     viewId.endsWith(".png")) {
485                 context.getExternalContext().dispatch(viewId);
486                 return;
487             }
488             try {
489                 URL JavaDoc viewURL = context.getExternalContext().getResource(viewId);
490                 if (null == viewURL) {
491                     if (viewId.endsWith(".faces")) {
492                         viewId = truncate(".faces", viewId);
493                     } else if (viewId.endsWith(".jsf")) {
494                         viewId = truncate(".jsf", viewId);
495                     } else if (viewId.endsWith(".iface")) {
496                         viewId = truncate(".iface", viewId);
497                     } else if (viewId.endsWith(".jsp")) {
498                         //MyFaces thinks everything is a .jsp
499
viewId = truncate(".jsp", viewId);
500                     }
501
502                     viewId = viewId + ".jspx";
503                     viewURL = context.getExternalContext().getResource(viewId);
504                 }
505
506                 if (null == viewURL) {
507                     if (viewId.endsWith(".jspx")) {
508                         viewId = truncate(".jspx", viewId) +
509                                 ".jsp";
510                     }
511                     viewURL = context.getExternalContext().getResource(viewId);
512                 }
513
514
515                 long currentTime = System.currentTimeMillis();
516                 long lastLoaded = getTimeAttribute(root, LAST_LOADED_KEY);
517                 long lastChecked = getTimeAttribute(root, LAST_CHECKED_KEY);
518                 long lastModified = 0;
519
520                 //newly instantiated viewRoot will have lastChecked of 0
521
//and lastLoaded of 0
522
if (currentTime > lastChecked + reloadInterval) {
523                     viewConnection = viewURL.openConnection();
524                     lastModified = viewConnection.getLastModified();
525                     root.getAttributes().put(LAST_CHECKED_KEY,
526                             new Long JavaDoc(currentTime));
527                     if (lastModified > lastLoaded) {
528                         reloadView = true;
529                     }
530                 }
531
532             } catch (Exception JavaDoc e) {
533                 throw new FacesException("Can't find stream for " + viewId, e);
534             }
535         }
536
537         if (reloadView) {
538             Reader JavaDoc viewInput = null;
539
540             try {
541                 viewInput = new InputStreamReader JavaDoc(
542                         viewConnection.getInputStream(), CHAR_ENCODING);
543                 if (viewId.endsWith(".jsp")) {
544                     viewInput = JspPageToDocument.transform(viewInput);
545                 } else if (viewId.endsWith(".jspx")) {
546                     viewInput =
547                             JspPageToDocument.preprocessJspDocument(viewInput);
548                 }
549             } catch (Throwable JavaDoc e) {
550                 throw new FacesException("Can't read stream for " + viewId, e);
551             }
552
553             // Parse the page;
554
try {
555                 //TODO: pass viewInput as an InputStream in order to give to the XML parser a chance to
556
//TODO: read the encoding type declared in the xml processing instruction (<?xml version="1.0" charset="..."?>)
557
parser.parse(viewInput, context);
558                 root.getAttributes().put(LAST_LOADED_KEY,
559                         new Long JavaDoc(System.currentTimeMillis()));
560
561
562             } catch (Throwable JavaDoc e) {
563                 throw new FacesException("Can't parse stream for " + viewId +
564                         " " + e.getMessage(), e);
565             }
566
567             if (ImplementationUtil.isJSF12()) {
568                 if (log.isDebugEnabled()) {
569                     log.debug("Rendering outside ViewTag for JSF 1.2");
570                 }
571                 //JSF 1.2 ViewTag does not invoke rendering
572
responseWriter.startDocument();
573                 renderResponse(context, root);
574                 responseWriter.endDocument();
575             }
576
577         } else {
578             responseWriter.startDocument();
579             renderResponse(context, root);
580             responseWriter.endDocument();
581             tracePrintComponentTree(context);
582         }
583
584     }
585
586     protected void renderResponse(FacesContext context, UIComponent component)
587             throws IOException JavaDoc {
588         if (!component.isRendered())
589             return;
590
591         // UIViewRoot.encodeBegin(FacesContext) resets its counter for
592
// createUniqueId(), which we don't want, or else we get
593
// duplicate ids
594
boolean isUIViewRoot = component instanceof UIViewRoot;
595         if( !isUIViewRoot )
596             component.encodeBegin(context);
597
598         if (component.getRendersChildren()) {
599             component.encodeChildren(context);
600         } else {
601             Iterator JavaDoc kids = component.getChildren().iterator();
602             while (kids.hasNext()) {
603                 renderResponse(context, (UIComponent) kids.next());
604             }
605         }
606
607         if( !isUIViewRoot )
608             component.encodeEnd(context);
609
610         //Workaround so that MyFaces UIData will apply values to
611
//child components even if the tree is not restored via StateManager
612
if (component instanceof javax.faces.component.UIData) {
613             StateHolder stateHolder = (StateHolder) component;
614             stateHolder.restoreState(context, stateHolder.saveState(context));
615         }
616     }
617
618     protected void tracePrintComponentTree(FacesContext context) {
619         tracePrintComponentTree( context, context.getViewRoot() );
620     }
621
622     protected void tracePrintComponentTree(
623         FacesContext context, UIComponent component)
624     {
625         if (log.isTraceEnabled()) {
626             StringBuffer JavaDoc sb = new StringBuffer JavaDoc(4096);
627             sb.append("tracePrintComponentTree() vvvvvv\n");
628             tracePrintComponentTree(context, component, 0, sb, null);
629             log.trace(sb.toString());
630             log.trace("tracePrintComponentTree() ^^^^^^");
631         }
632     }
633
634     private void tracePrintComponentTree(
635         FacesContext context, UIComponent component,
636         int levels, StringBuffer JavaDoc sb, String JavaDoc facetName)
637     {
638         if( component == null ) {
639             sb.append("null\n");
640             return;
641         }
642         final String JavaDoc PREFIX_WHITESPACE = " ";
643         StringBuffer JavaDoc prefix = new StringBuffer JavaDoc(64);
644         for (int i = 0; i < levels; i++)
645             prefix.append(PREFIX_WHITESPACE);
646         prefix.append("<");
647         String JavaDoc compStr = component.toString();
648
649         StringBuffer JavaDoc open = new StringBuffer JavaDoc(512);
650         open.append(prefix);
651         open.append(compStr);
652         Map JavaDoc facetsMap = component.getFacets();
653         boolean hasKids = component.getChildCount() > 0;
654         boolean hasFacets = (facetsMap != null) && (facetsMap.size() > 0);
655         boolean hasUnderlings = hasKids | hasFacets;
656         if (!hasUnderlings)
657             open.append("/");
658         open.append(">");
659         if( facetName != null ) {
660             open.append(" facetName: ");
661             open.append(facetName);
662         }
663         open.append(" id: ");
664         open.append(component.getId());
665         if( component.getParent() != null ) {
666             open.append(" clientId: ");
667             open.append(component.getClientId(context));
668         }
669         if(hasKids) {
670             open.append(" kids: ");
671             open.append(Integer.toString(component.getChildCount()));
672         }
673         if(hasFacets) {
674             open.append(" facets: ");
675             open.append(Integer.toString(facetsMap.size()));
676         }
677         if(component.isTransient())
678             open.append(" TRANSIENT ");
679         sb.append(open.toString());
680         sb.append('\n');
681
682         if (hasUnderlings) {
683             if( hasFacets ) {
684                 Object JavaDoc[] facetKeys = facetsMap.keySet().toArray();
685                 Arrays.sort(facetKeys);
686                 for(int i = 0; i < facetKeys.length; i++) {
687                     tracePrintComponentTree(
688                         context, (UIComponent) facetsMap.get(facetKeys[i]),
689                         levels + 1, sb, facetKeys[i].toString());
690                 }
691             }
692             if( hasKids ) {
693                 Iterator JavaDoc kids = component.getChildren().iterator();
694                 while (kids.hasNext()) {
695                     tracePrintComponentTree(
696                         context, (UIComponent) kids.next(), levels + 1, sb, null);
697                 }
698             }
699
700             StringBuffer JavaDoc close = new StringBuffer JavaDoc(512);
701             close.append(prefix);
702             close.append("/");
703             close.append(compStr);
704             close.append(">");
705             sb.append(close);
706             sb.append('\n');
707         }
708     }
709
710     protected void clearSession(FacesContext context) {
711         Map JavaDoc contextServletTable =
712                 getContextServletTable(context);
713         contextServletTable.remove(DOMResponseWriter.RESPONSE_CONTEXTS_TABLE);
714         contextServletTable.remove(DOMResponseWriter.RESPONSE_VIEWROOT);
715         contextServletTable.remove(DOMResponseWriter.RESPONSE_DOM);
716     }
717
718     public void writeState(FacesContext context) throws IOException JavaDoc {
719         if (delegateView(context.getViewRoot().getViewId())) {
720             delegate.writeState(context);
721         }
722     }
723
724     public Locale JavaDoc calculateLocale(FacesContext context) {
725         Iterator JavaDoc locales = context.getExternalContext().getRequestLocales();
726
727         while (locales.hasNext()) {
728             Locale JavaDoc locale = (Locale JavaDoc) locales.next();
729             Iterator JavaDoc supportedLocales = context.getApplication()
730                     .getSupportedLocales();
731
732             while (supportedLocales.hasNext()) {
733                 Locale JavaDoc supportedLocale = (Locale JavaDoc) supportedLocales.next();
734                 if (locale.getLanguage()
735                         .equals(supportedLocale.getLanguage())) {
736
737                     if ((null == supportedLocale.getCountry()) ||
738                             ("".equals(supportedLocale.getCountry()))) {
739                         return supportedLocale;
740                     }
741
742                     if (locale.equals(supportedLocale)) {
743                         return supportedLocale;
744                     }
745
746                 }
747             }
748         }
749
750         Locale JavaDoc defaultLocale = context.getApplication().getDefaultLocale();
751         return (null == defaultLocale) ? Locale.getDefault() : defaultLocale;
752     }
753
754     public String JavaDoc calculateRenderKitId(FacesContext context) {
755         return delegate.calculateRenderKitId(context);
756     }
757
758     public static boolean isValueReference(String JavaDoc value) {
759         if ((value.indexOf("#{") != -1) &&
760                 (value.indexOf("#{") < value.indexOf('}'))) {
761             return true;
762         }
763         return false;
764     }
765
766     /**
767      * A dumber version (that can't find child components of the UIData
768      * component) of this method resides in UIComponentBase. The same is true
769      * for the private findComoponent in UIComponentBase - it is duplicated
770      * here.
771      *
772      * @param clientId
773      * @param base
774      */

775     public static UIComponent findComponent(String JavaDoc clientId, UIComponent base) {
776         // Set base, the parent component whose children are searched, to be the
777
// nearest parent that is either 1) the view root if the id expression
778
// is absolute (i.e. starts with the delimiter) or 2) the nearest parent
779
// NamingContainer if the expression is relative (doesn't start with
780
// the delimiter)
781
String JavaDoc delimeter = String.valueOf(NamingContainer.SEPARATOR_CHAR);
782         if (clientId.startsWith(delimeter)) {
783             // Absolute searches start at the root of the tree
784
while (base.getParent() != null) {
785                 base = base.getParent();
786             }
787             // Treat remainder of the expression as relative
788
clientId = clientId.substring(1);
789         } else {
790             // Relative expressions start at the closest NamingContainer or root
791
while (base.getParent() != null) {
792                 if (base instanceof NamingContainer) {
793                     break;
794                 }
795                 base = base.getParent();
796             }
797         }
798         // Evaluate the search expression (now guaranteed to be relative)
799
String JavaDoc id = null;
800         UIComponent result = null;
801         while (clientId.length() > 0) {
802             int separator = clientId.indexOf(NamingContainer.SEPARATOR_CHAR);
803             if (base instanceof UIData) {
804                 if (separator >= 0) {
805                     clientId = clientId.substring(separator + 1);
806                 }
807                 separator = clientId.indexOf(NamingContainer.SEPARATOR_CHAR);
808             }
809             if (separator >= 0) {
810                 id = clientId.substring(0, separator);
811                 clientId = clientId.substring(separator + 1);
812             } else {
813                 id = clientId;
814                 clientId = "";
815             }
816             result = findComponent(base, id);
817             if ((result == null) || (clientId.length() == 0)) {
818                 break; // Missing intermediate node or this is the last node
819
}
820             if (result instanceof NamingContainer) {
821                 result = findComponent(clientId, result);
822                 break;
823             }
824         }
825
826         return result;
827     }
828
829     private static String JavaDoc truncate(String JavaDoc remove, String JavaDoc input) {
830         return input.substring(0, input.length() - remove.length());
831     }
832
833     //Determine whether handling of the view should be delegated to
834
//the delegate ViewHandler
835
private boolean delegateView(String JavaDoc viewId) {
836         Map JavaDoc requestMap = FacesContext.getCurrentInstance()
837                 .getExternalContext().getRequestMap();
838         //If it's served by the PersistentFacesServlet, do not
839
//delegate
840
if (PersistentFacesCommonlet.PERSISTENT.equals(
841                 requestMap.get(PersistentFacesCommonlet.SERVLET_KEY))) {
842             return false;
843         }
844         if (delegateNonIface) {
845             return (!viewId.endsWith(".iface"));
846         }
847         return false;
848     }
849
850     private void initializeParameters(FacesContext context) {
851         if (parametersInitialized) {
852             return;
853         }
854
855         ExternalContext ec = context.getExternalContext();
856         String JavaDoc delegateNonIfaceParameter = ec.getInitParameter(DELEGATE_NONIFACE);
857         String JavaDoc reloadIntervalParameter = ec.getInitParameter(RELOAD_INTERVAL);
858         String JavaDoc jsfStateManagementParameter = ec.getInitParameter(DO_JSF_STATE_MANAGEMENT);
859         actionURLSuffix = ec.getInitParameter(ACTION_URL_SUFFIX);
860         delegateNonIface = delegateNonIfaceParameter == null ? delegateNonIfaceDefault : Boolean.valueOf(delegateNonIfaceParameter).booleanValue();
861         try {
862             reloadInterval = Long.parseLong(reloadIntervalParameter) * 1000;
863         } catch (NumberFormatException JavaDoc e) {
864             reloadInterval = reloadIntervalDefault * 1000;
865         }
866         jsfStateManagement = Boolean.valueOf(jsfStateManagementParameter).booleanValue();
867         if (!jsfStateManagement) {
868             log.debug("JSF State Management not provided");
869         }
870         parametersInitialized = true;
871     }
872
873     //MyFaces processes the viewId before passing it to the ViewHandler
874
//so we have no idea of knowing what it really is. This function
875
//mimics the MyFaces process so we can compare ids modulo it
876
private static String JavaDoc mungeViewId(String JavaDoc viewId) {
877         String JavaDoc defaultSuffix = FacesContext.getCurrentInstance()
878                 .getExternalContext()
879                 .getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
880         String JavaDoc suffix = defaultSuffix != null ?
881                 defaultSuffix : ViewHandler.DEFAULT_SUFFIX;
882
883         int dot = viewId.lastIndexOf('.');
884         if (dot == -1) {
885             log
886                     .error("Assumed extension mapping, but there is no extension in " +
887                             viewId);
888         } else {
889             viewId = viewId.substring(0, dot) + suffix;
890         }
891
892         return viewId;
893     }
894
895     private static UIComponent findComponent(UIComponent uiComponent,
896                                              String JavaDoc componentId) {
897         UIComponent component = null;
898         UIComponent child = null;
899
900         if (componentId.equals(uiComponent.getId())) {
901             return uiComponent;
902         }
903         Iterator JavaDoc children = uiComponent.getFacetsAndChildren();
904         while (children.hasNext() && (component == null)) {
905             child = (UIComponent) children.next();
906             if (!(child instanceof NamingContainer)) {
907                 component = findComponent(child, componentId);
908                 if (component != null) {
909                     break;
910                 }
911             } else if (componentId.endsWith(child.getId())) {
912                 component = child;
913                 break;
914             }
915         }
916         return component;
917     }
918 }
919
Popular Tags