001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package com.sun.rave.web.ui.component.util;
042:
043: import com.sun.rave.web.ui.component.ChildManager;
044: import com.sun.rave.web.ui.component.ComplexComponent;
045: import com.sun.rave.web.ui.component.util.descriptors.ComponentType;
046: import com.sun.rave.web.ui.component.util.descriptors.LayoutComponent;
047: import com.sun.rave.web.ui.component.util.descriptors.LayoutElement;
048: import com.sun.rave.web.ui.util.VariableResolver;
049:
050: import java.beans.Beans;
051: import java.util.HashMap;
052: import java.util.Iterator;
053: import java.util.Map;
054: import java.util.Properties;
055:
056: import javax.faces.FactoryFinder;
057: import javax.faces.component.UIComponent;
058: import javax.faces.component.EditableValueHolder;
059: import javax.faces.component.UIForm;
060: import javax.faces.component.ValueHolder;
061: import javax.faces.context.FacesContext;
062: import javax.faces.convert.Converter;
063: import javax.faces.el.ValueBinding;
064: import javax.faces.event.PhaseListener;
065: import javax.faces.lifecycle.Lifecycle;
066: import javax.faces.lifecycle.LifecycleFactory;
067: import javax.faces.webapp.UIComponentTag;
068: import javax.servlet.http.HttpServletRequest;
069:
070: /**
071: * Utility class that contains helper methods for components.
072: *
073: * @author Ken Paulsen
074: */
075: public class Util {
076:
077: /**
078: * <p> This constructor is here to prevent this class from being
079: * instantiated. It only contains static methods.</p>
080: */
081: private Util() {
082: }
083:
084: /**
085: * <p> Return a child with the specified component id from the specified
086: * component. If not found, return <code>null</code>.</p>
087: *
088: * <p> This method will NOT create a new <code>UIComponent</code>.</p>
089: *
090: * @param parent <code>UIComponent</code> to be searched
091: * @param id Component id (or facet name) to search for
092: *
093: * @return The child <code>UIComponent</code> if it exists, null otherwise.
094: */
095: public static UIComponent getChild(UIComponent parent, String id) {
096: return findChild(parent, id, id);
097: }
098:
099: /**
100: * <p> Return a child with the specified component id (or facetName) from
101: * the specified component. If not found, return <code>null</code>.
102: * <code>facetName</code> or <code>id</code> may be null to avoid
103: * searching the facet Map or the <code>parent</code>'s children.</p>
104: *
105: * <p> This method will NOT create a new <code>UIComponent</code>.</p>
106: *
107: * @param parent <code>UIComponent</code> to be searched
108: * @param id id to search for
109: * @param facetName Facet name to search for
110: *
111: * @return The child <code>UIComponent</code> if it exists, null otherwise.
112: */
113: public static UIComponent findChild(UIComponent parent, String id,
114: String facetName) {
115: // Sanity Check
116: if (parent == null) {
117: return null;
118: }
119:
120: // First search for facet
121: UIComponent child = null;
122: if (facetName != null) {
123: child = (UIComponent) parent.getFacets().get(facetName);
124: if (child != null) {
125: return child;
126: }
127: }
128:
129: // Search for component by id
130: if (id != null) {
131: Iterator it = parent.getChildren().iterator();
132: while (it.hasNext()) {
133: child = (UIComponent) it.next();
134: if (id.equals(child.getId())) {
135: return (child);
136: }
137: }
138: }
139:
140: // Not found, return null
141: return null;
142: }
143:
144: /**
145: * <p> This method finds or creates a child <code>UIComponent</code>
146: * identified by the given id. If the child is not found, it will
147: * attempt to create it using the provided {@link com.sun.rave.web.ui.component.util.factories.ComponentFactory}
148: * (<code>factoryClass</code>).</p>
149: *
150: * <p> If there are <code>Properties</code> to be set on the UIComponent,
151: * this method should generally be avoided. It is preferable to use
152: * the {@link #getChild(UIComponent, String, String, Properties)}
153: * form of <code>getChild</code>.</p>
154: *
155: * <p> <code>
156: * // Example (no properties):<br>
157: * UIComponent child = Util.getChild(component, "jklLabel", "{@link com.sun.rave.web.ui.component.util.factories.LabelFactory com.sun.rave.web.ui.component.util.factories.LabelFactory}");<br>
158: * ((Label)child).setText("JKL Label:");<br>
159: * ((Label)child).setFor("jkl");<br>
160: * <br>
161: * {@link LayoutComponent#encodeChild(FacesContext, UIComponent) LayoutComponent.encodeChild}(context, child);
162: * </code></p>
163: *
164: * @param parent Parent <code>UIComponent</code>
165: * @param id Identifier for the child <code>UIComponent</code>
166: * @param factoryClass Full {@link com.sun.rave.web.ui.component.util.factories.ComponentFactory} class name
167: *
168: * @return The child UIComponent that was found or created.
169: *
170: * @see #getChild(UIComponent, String, String, Properties)
171: */
172: public static UIComponent getChild(UIComponent parent, String id,
173: String factoryClass) {
174: return getChild(parent, id, factoryClass, id);
175: }
176:
177: /**
178: * <p> Same as {@link #getChild(UIComponent, String, String)} except that
179: * it allows you to specify a facetName different than the id. If
180: * null is supplied, it won't save the component as a facet.</p>
181: *
182: * @param parent Parent <code>UIComponent</code>
183: * @param id Identifier for the child <code>UIComponent</code>
184: * @param factoryClass Full {@link com.sun.rave.web.ui.component.util.factories.ComponentFactory} class name
185: * @param facetName The facet name (null means don't store it)
186: *
187: * @return The child UIComponent that was found or created.
188: *
189: * @see #getChild(UIComponent, String, String)
190: */
191: public static UIComponent getChild(UIComponent parent, String id,
192: String factoryClass, String facetName) {
193: return getChild(parent, id, getComponentType(factoryClass),
194: null, facetName);
195: }
196:
197: /**
198: * <p> This method finds or creates a child <code>UIComponent</code>
199: * identified by the given id. If the child is not found, it will
200: * attempt to create it using the provided {@link com.sun.rave.web.ui.component.util.factories.ComponentFactory}
201: * (<code>factoryClass</code>). It will also initialize the
202: * <code>UIComponent</code> using the provided set of
203: * <code>Properties</code>.</p>
204: *
205: * <p> <code>
206: * // Example (with properties):<br>
207: * Properties props = new Properties();<br>
208: * props.setProperty("text", "ABC Label:");<br>
209: * props.setProperty("for", "abc");<br>
210: * UIComponent child = Util.getChild(component, "abcLabel", "{@link com.sun.rave.web.ui.component.util.factories.LabelFactory com.sun.rave.web.ui.component.util.factories.LabelFactory}", props);<br>
211: * <br>
212: * {@link LayoutComponent#encodeChild(FacesContext, UIComponent) LayoutComponent.encodeChild}(context, child);
213: * </code></p>
214: *
215: * @param parent Parent <code>UIComponent</code>
216: * @param id Identifier for the child <code>UIComponent</code>
217: * @param factoryClass Full {@link com.sun.rave.web.ui.component.util.factories.ComponentFactory} class name
218: * @param properties <code>java.util.Properties</code> needed to
219: * create and/or initialize the
220: * <code>UIComponent</code>
221: *
222: * @return The child UIComponent that was found or created.
223: */
224: public static UIComponent getChild(UIComponent parent, String id,
225: String factoryClass, Properties properties) {
226: return getChild(parent, id, factoryClass, properties, id);
227: }
228:
229: /**
230: * <p> Same as {@link #getChild(UIComponent, String, String, Properties)}
231: * except that it allows you to specify a facetName different than the
232: * id. If null is supplied, it won't save the component as a
233: * facet.</p>
234: *
235: * @param parent Parent <code>UIComponent</code>
236: * @param id Identifier for the child <code>UIComponent</code>
237: * @param factoryClass Full {@link com.sun.rave.web.ui.component.util.factories.ComponentFactory} class name
238: * @param properties <code>java.util.Properties</code> needed to
239: * create and/or initialize the
240: * <code>UIComponent</code>
241: * @param facetName The facet name (null means don't store it)
242: *
243: * @return The child UIComponent that was found or created.
244: */
245: public static UIComponent getChild(UIComponent parent, String id,
246: String factoryClass, Properties properties, String facetName) {
247: return getChild(parent, id, getComponentType(factoryClass),
248: properties, facetName);
249: }
250:
251: /**
252: * <p> This method finds or creates a child <code>UIComponent</code>
253: * identified by the given id. If the child is not found, it will
254: * attempt to create it using the provided {@link ComponentType}
255: * (<code>type</code>). It will also initialize the
256: * <code>UIComponent</code> using the provided set of
257: * <code>properties</code>.</p>
258: *
259: * @param parent Parent <code>UIComponent</code>
260: * @param id Identifier for the child
261: * <code>UIComponent</code>
262: * @param type The <code>ComponentType</code> class name
263: * @param properties Properties needed to create and/or initialize
264: * the <code>UIComponent</code>
265: * @param facetName The facet name (null means don't store it)
266: *
267: * @return The child <code>UIComponent</code> that was found or created.
268: */
269: private static UIComponent getChild(UIComponent parent, String id,
270: ComponentType type, Properties properties, String facetName) {
271: LayoutComponent desc = new LayoutComponent(null, id, type);
272: if (properties != null) {
273: desc.setOptions(properties);
274: }
275: if (facetName != null) {
276: // Add the facetName to use
277: // FIXME: Decide if this should have its own method
278: desc.addOption(LayoutComponent.FACET_NAME, facetName);
279: }
280:
281: return getChild(parent, desc);
282: }
283:
284: /**
285: * <p> This method creates a {@link ComponentType} instance from the given
286: * <code>factoryClass</code>. It will first check its cache to see if
287: * one has already been created. If not, it will create one and add
288: * to the cache for future use.</p>
289: *
290: * <p> This method sets <code>factoryClass</code> for the
291: * {@link ComponentType} id.</p>
292: *
293: * @param facatoryClass The full classname of the
294: * {@link com.sun.rave.web.ui.component.util.factories.ComponentFactory}.
295: *
296: * @return A ComponentType instance for <code>factoryClass</code>.
297: */
298: private static ComponentType getComponentType(String factoryClass) {
299: // Check the cache
300: ComponentType type = (ComponentType) _types.get(factoryClass);
301: if (type == null) {
302: // Not in the cache... add it...
303: type = new ComponentType(factoryClass, factoryClass);
304: Map newMap = new HashMap(_types);
305: newMap.put(factoryClass, type);
306: _types = newMap;
307: }
308:
309: // Return the ComponentType
310: return type;
311: }
312:
313: /**
314: * <p> This method finds or creates a child <code>UIComponent</code>
315: * identified by the given id. If the child is not found, it will
316: * attempt to create it using the provided {@link LayoutComponent}
317: * (<code>descriptor</code>). It will also initialize the
318: * <code>UIComponent</code> using the options set on the
319: * {@link LayoutComponent}.</p>
320: *
321: * <p> If <code>parent</code> implements {@link ChildManager}, then the
322: * responsibility of finding and creating the child will be delegated
323: * to the {@link ChildManager} <code>UIComponent</code>.</p>
324: *
325: * <p> If you are constructing and populating a LayoutComponent before
326: * calling this method, there are a few features that should be noted.
327: * Besides <code>id</code> and <code>type</code> which can be set in
328: * the LayoutComponent constructor, you can also set
329: * <code>options</code>, and
330: * {@link com.sun.rave.web.ui.component.util.event.Handler}'s.</p>
331: *
332: * <p> <code>Options</code> may be set via
333: * {@link LayoutComponent#setOptions(Map)}. These options will be
334: * applied to the <code>UIComponent</code> and may also be used by the
335: * {@link com.sun.rave.web.ui.component.util.factories.ComponentFactory} while instantiating the
336: * <code>UIComponent</code>.</p>
337: *
338: * <p> {@link com.sun.rave.web.ui.component.util.event.Handler}'s can be
339: * supplied by calling
340: * {@link LayoutComponent#setHandlers(String, List)}. The
341: * <code>type</code> must match the event name which invokes the
342: * <code>List</code> of handlers you provide. The
343: * <code>Renderer</code> for this <code>UIComponent</code> is
344: * responsible for declaring and dispatching events.
345: * {@link com.sun.rave.web.ui.renderer.template.TemplateRenderer} will
346: * invoke <code>beforeCreate</code> and <code>afterCreate</code>
347: * events for each child it creates (such as the one being requested
348: * here).</p>
349: *
350: * <p> <code>
351: * // Example (with LayoutComponent):<br>
352: * {@link ComponentType} type = new {@link ComponentType#ComponentType(String, String) ComponentType}("LabelFactory", "{@link com.sun.rave.web.ui.component.util.factories.LabelFactory com.sun.rave.web.ui.component.util.factories.LabelFactory}");<br>
353: * {@link LayoutComponent} descriptor = new {@link LayoutComponent#LayoutComponent(LayoutElement, String, ComponentType) LayoutComponent}(null, "abcLabel", type);<br>
354: * {@link LayoutComponent#addOption(String, Object) descriptor.addOption}("text", "ABC Label:");<br>
355: * {@link LayoutComponent#addOption(String, Object) descriptor.addOption}("for", "abc");<br>
356: * UIComponent child = Util.getChild(component, descriptor);<br>
357: * <br>
358: * {@link LayoutComponent#encodeChild(FacesContext, UIComponent) LayoutComponent.encodeChild}(context, child);
359: * </code></p>
360: *
361: * @param parent Parent <code>UIComponent</code>
362: * @param descriptor The {@link LayoutComponent} describing the
363: * <code>UIComponent</code>
364: *
365: * @return The child <code>UIComponent</code> that was found or created.
366: */
367: public static UIComponent getChild(UIComponent parent,
368: LayoutComponent descriptor) {
369: FacesContext context = FacesContext.getCurrentInstance();
370: // First check to see if the UIComponent can create its own children
371: if (parent instanceof ChildManager) {
372: return ((ChildManager) parent)
373: .getChild(context, descriptor);
374: }
375:
376: // Make sure it doesn't already exist
377: String childId = descriptor.getId(context, parent);
378: UIComponent childComponent = findChild(parent, childId,
379: (String) descriptor.getEvaluatedOption(context,
380: LayoutComponent.FACET_NAME, null));
381: if (childComponent != null) {
382: return childComponent;
383: }
384:
385: // Not found, create a new UIComponent
386: return createChildComponent(context, descriptor, parent);
387: }
388:
389: /**
390: * <p> This method creates a child <code>UIComponent</code> by using the
391: * provided {@link LayoutComponent} (<code>descriptor</code>). It
392: * will associate the parent and the newly created
393: * <code>UIComponent</code>.</p>
394: *
395: * <p> It is recommended that this method NOT be called from a Renderer.
396: * It should not be called if you have not yet checked to see if a
397: * child UIComponent with the requested ID already exists.</p>
398: *
399: * @param context The <code>FacesContext</code> object.
400: * @param descriptor The {@link LayoutComponent} describing the
401: * <code>UIComponent</code> to be created.
402: * @param parent Parent <code>UIComponent</code>.
403: *
404: * @return A new <code>UIComponent</code> based on the provided
405: * {@link LayoutComponent}.
406: *
407: * @throws IllegalArgumentException Thrown if descriptor equals null.
408: *
409: * @see #getChild(UIComponent, LayoutComponent)
410: * @see #getChild(UIComponent, String, String, Properties)
411: * @see LayoutComponent#getType()
412: * @see ComponentType#getFactory()
413: * @see com.sun.rave.web.ui.component.util.factories.ComponentFactory#create(FacesContext, LayoutComponent, UIComponent)
414: */
415: public static UIComponent createChildComponent(
416: FacesContext context, LayoutComponent descriptor,
417: UIComponent parent) {
418: // Make sure a LayoutComponent was provided.
419: if (descriptor == null) {
420: throw new IllegalArgumentException(
421: "'descriptor' cannot be null!");
422: }
423:
424: // Create & return the child UIComponent
425: return descriptor.getType().getFactory().create(context,
426: descriptor, parent);
427: }
428:
429: /**
430: * <p> This util method will set the given key/value on the
431: * <code>UIComponent</code>. It will resolve all $...{...}
432: * expressions, and convert the String into a
433: * <code>ValueBinding</code> if a <code>ValueBinding</code> is
434: * detected. The return value will be a <code>ValueBinding</code> or
435: * the value.</p>
436: *
437: * @param context <code>FacesContext</code>
438: * @param key The Property name to set
439: * @param value The Property value to set
440: * @param desc The {@link LayoutElement} associated with the
441: * <code>UIComponent</code>
442: * @param component The <code>UIComponent</code>
443: *
444: * @return A ValueBinding, or the evaulated value (if no value binding is
445: * present).
446: */
447: public static Object setOption(FacesContext context, String key,
448: Object value, LayoutElement desc, UIComponent component) {
449: // Invoke our own EL. This is needed b/c JSF's EL is designed for
450: // Bean getters only. It does not get CONSTANTS or pull data from
451: // other sources (such as session, request attributes, etc., etc.)
452: // Resolve our variables now because we cannot depend on the
453: // individual components to do this. We may want to find a way to
454: // make this work as a regular ValueBinding expression... but for
455: // now, we'll just resolve it here.
456: value = VariableResolver.resolveVariables(context, desc,
457: component, value);
458: if (value == null) {
459: // It is possible to resolve an expression to null
460: return null;
461: }
462:
463: // Next check to see if the value contains a JSF ValueBinding
464: String strVal = value.toString();
465: if (UIComponentTag.isValueReference(strVal)) {
466: ValueBinding vb = context.getApplication()
467: .createValueBinding(strVal);
468: if (component != null) {
469: component.setValueBinding(key, vb);
470: }
471: value = vb;
472: } else {
473: // In JSF, you must directly modify the attribute Map
474: if (component != null) {
475: component.getAttributes().put(key, value);
476: }
477: }
478: return value;
479: }
480:
481: /**
482: * <p>Helper method to obtain containing <code>UIForm</code>.</p>
483: *
484: * @param context <code>FacesContext</code> for the request we are
485: * processing.
486: * @param component <code>UIComponent</code> to find form from.
487: *
488: * @return Returns the <code>UIForm</code> component that contains this element
489: */
490: public static UIComponent getForm(FacesContext context,
491: UIComponent component) {
492: //make sure component is not null
493: if (component != null) {
494: //make sure we don't already have a form
495: if (component instanceof UIForm) {
496: return component;
497: }
498:
499: UIComponent form = component;
500: do {
501: form = form.getParent();
502: if (form != null && form instanceof UIForm) {
503: return form;
504: }
505: } while (form != null);
506: }
507: return null;
508: }
509:
510: /**
511: * <p>Gets the form id from the containing <code>UIForm</code>.</p>
512: *
513: * @param context FacesContext for the request we are processing.
514: * @param component UIComponent to find form from.
515: *
516: * @return Returns the id of the <code>UIForm</code> that contains this
517: * element.
518: */
519: public static String getFormName(FacesContext context,
520: UIComponent component) {
521: UIComponent form = getForm(context, component);
522: if (form != null) {
523: return form.getClientId(context);
524: }
525: return null;
526: }
527:
528: /**
529: * <p> This method will attempt to resolve EL strings in the given
530: * value.</p>
531: *
532: * @param context The <code>FacesContext</code>
533: * @param elt The LayoutElement associated w/ the expression
534: * @param parent The parent <code>UIComponent</code>. This is used
535: * because the current UIComponent is typically
536: * unknown (or not even created yet).
537: * @param value The String to resolve
538: *
539: * @return The evaluated value (may be null).
540: */
541: public static Object resolveValue(FacesContext context,
542: LayoutElement elt, UIComponent parent, String value) {
543: // Invoke our own EL. This is needed b/c JSF's EL is designed for
544: // Bean getters only. It does not get CONSTANTS or pull data from
545: // other sources without adding a custom VariableResolver and/or
546: // PropertyResolver. Eventually we may want to find a good way to
547: // make this work as a regular ValueBinding expression... but for
548: // now, we'll just resolve it this way.
549: Object result = VariableResolver.resolveVariables(context, elt,
550: parent, value);
551:
552: // Next check to see if the value contains a JSF ValueBinding
553: if (result != null) {
554: String strVal = result.toString();
555: if (UIComponentTag.isValueReference(strVal)) {
556: ValueBinding vb = context.getApplication()
557: .createValueBinding(strVal);
558: result = vb.getValue(context);
559: }
560: }
561:
562: // Return the result
563: return result;
564: }
565:
566: /**
567: * <p>Return the base URI for the view identifier of the current view.</p>
568: *
569: * @param context <code>FacesContext</code> for the current request
570: */
571: public static String getBase(FacesContext context) {
572:
573: return getContext(context) + context.getViewRoot().getViewId();
574:
575: }
576:
577: /**
578: * <p>Return an absolute URL to our server and context path.</p>
579: *
580: * @param context <code>FacesContext</code> for the current request
581: */
582: public static String getContext(FacesContext context) {
583:
584: // FIXME - design time FacesContext needs better instrumentaiton?
585: if (Beans.isDesignTime()) {
586: return "http://localhost:18080/myapp";
587: }
588:
589: // FIXME - portlet environment variation?
590: HttpServletRequest request = (HttpServletRequest) context
591: .getExternalContext().getRequest();
592: StringBuffer sb = new StringBuffer(request.getScheme());
593: sb.append("://"); //NOI18N
594: sb.append(request.getServerName());
595: if ("http".equals(request.getScheme()) && //NOI18N
596: (80 == request.getServerPort())) {
597: ;
598: } else if ("https".equals(request.getScheme()) && //NOI18N
599: (443 == request.getServerPort())) {
600: ;
601: } else {
602: sb.append(":" + request.getServerPort()); //NOI18N
603: }
604: sb.append(request.getContextPath());
605: return sb.toString();
606:
607: }
608:
609: public static String getActionURL(FacesContext context, String url) {
610: return context.getApplication().getViewHandler().getActionURL(
611: context, url);
612: }
613:
614: /**
615: * <p> Return whether the given <code>UIComponent</code> is "visible".
616: * If the property is null, it will return true. Otherwise the value
617: * of the property is returned.</p>
618: *
619: * @param component The <code>UIComponent</code> to check
620: *
621: * @return True if the property is null or true, false otherwise.
622: */
623: public static boolean isVisible(UIComponent component) {
624: Object visible = component.getAttributes().get("visible"); //NOI18N
625: if (visible == null)
626: return true;
627: else
628: return ((Boolean) visible).booleanValue();
629: }
630:
631: /**
632: * Add a PhaseListener.
633: *
634: * @param phaseListener PhaseListener instance.
635: */
636: public static void addPhaseListener(PhaseListener phaseListener) {
637:
638: LifecycleFactory factory = (LifecycleFactory) FactoryFinder
639: .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
640: Lifecycle lifecycle = factory
641: .getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
642: lifecycle.addPhaseListener(phaseListener);
643: }
644:
645: /**
646: * Remove a PhaseListener.
647: *
648: * @param phaseListener PhaseListener instance.
649: */
650: public static void removePhaseListener(PhaseListener phaseListener) {
651:
652: LifecycleFactory factory = (LifecycleFactory) FactoryFinder
653: .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
654: Lifecycle lifecycle = factory
655: .getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
656: lifecycle.removePhaseListener(phaseListener);
657: }
658:
659: /**
660: *
661: * <p>This Map caches ComponentTypes by their factoryClass name.</p>
662: */
663: private static Map _types = new HashMap();
664:
665: }
|