/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package javax.faces.component;
import java.beans.*;
import java.lang.reflect.*;
import java.lang.annotation.Annotation;
import java.io.*;
import java.util.*;
import java.util.logging.*;
import javax.el.*;
import javax.faces.*;
import javax.faces.application.*;
import javax.faces.component.html.*;
import javax.faces.context.*;
import javax.faces.el.*;
import javax.faces.event.*;
import javax.faces.render.*;
public abstract class UIComponentBase extends UIComponent
{
private static final UIComponent []NULL_FACETS_AND_CHILDREN
= new UIComponent[0];
private static final FacesListener []NULL_FACES_LISTENERS
= new FacesListener[0];
private static final HashMap<String,Integer> _rendererToCodeMap
= new HashMap<String,Integer>();
private static final HashMap<Integer,String> _codeToRendererMap
= new HashMap<Integer,String>();
private static final WeakHashMap<Class,HashMap<String,Property>> _compMap
= new WeakHashMap<Class,HashMap<String,Property>>();
private String _id;
private String _clientId;
private UIComponent _parent;
private String _rendererType;
private ValueExpression _rendererTypeExpr;
private boolean _isTransient;
private Boolean _isRendered;
private ValueExpression _isRenderedExpr;
private ValueExpression _bindingExpr;
private ComponentList _children;
private ComponentMap _facets;
private UIComponent []_facetsAndChildren;
private AttributeMap _attributeMap;
private FacesListener []_facesListeners
= NULL_FACES_LISTENERS;
public Map<String,Object> getAttributes()
{
if (_attributeMap == null)
_attributeMap = new AttributeMap(this);
return _attributeMap;
}
/**
* @deprecated
*/
public ValueBinding getValueBinding(String name)
{
ValueExpression expr = getValueExpression(name);
if (expr == null)
return null;
else if (expr instanceof ValueExpressionAdapter)
return ((ValueExpressionAdapter) expr).getBinding();
else
return new ValueBindingAdapter(expr);
}
/**
* @deprecated
*/
public void setValueBinding(String name, ValueBinding binding)
{
setValueExpression(name, new ValueExpressionAdapter(binding));
}
/**
* Returns the value expression for an attribute
*
* @param name the name of the attribute to get
*/
@Override
public ValueExpression getValueExpression(String name)
{
if (name == null)
throw new NullPointerException();
if ("rendered".equals(name))
return _isRenderedExpr;
else if ("rendererType".equals(name))
return _rendererTypeExpr;
else if ("binding".equals(name))
return _bindingExpr;
if (bindings != null)
return bindings.get(name);
else
return null;
}
/**
* Sets the value expression for an attribute
*
* @param name the name of the attribute to set
* @param expr the value expression
*/
@Override
public void setValueExpression(String name, ValueExpression expr)
{
if (name.equals("id"))
throw new IllegalArgumentException("'id' is not a valid ValueExpression name.");
else if (name.equals("parent"))
throw new IllegalArgumentException("'parent' is not a valid ValueExpression name.");
if ("rendered".equals(name)) {
if (expr.isLiteralText()) {
_isRendered = Util.booleanValueOf(expr.getValue(null));
return;
}
else
_isRenderedExpr = expr;
}
else if ("rendererType".equals(name)) {
if (expr.isLiteralText()) {
_rendererType = String.valueOf(expr.getValue(null));
return;
}
else
_rendererTypeExpr = expr;
}
else if ("binding".equals(name)) {
_bindingExpr = expr;
}
try {
if (expr != null) {
if (expr.isLiteralText()) {
getAttributes().put(name, expr.getValue(null));
}
else {
if (bindings == null)
bindings = new HashMap<String,ValueExpression>();
bindings.put(name, expr);
}
}
else if (bindings != null)
bindings.remove(name);
} catch (ELException e) {
throw new FacesException(e);
}
}
/**
* Returns the client-specific id for the component.
*/
@Override
public String getClientId(FacesContext context)
{
if (context == null)
throw new NullPointerException();
if (_clientId != null)
return _clientId;
String parentId = null;
for (UIComponent ptr = getParent(); ptr != null; ptr = ptr.getParent()) {
if (ptr instanceof NamingContainer) {
parentId = ptr.getContainerClientId(context);
break;
}
}
String myId = _id;
if (myId == null) {
myId = context.getViewRoot().createUniqueId();
}
if (parentId != null)
myId = parentId + NamingContainer.SEPARATOR_CHAR + myId;
Renderer renderer = getRenderer(context);
if (renderer != null)
_clientId = renderer.convertClientId(context, myId);
else
_clientId = myId;
return _clientId;
}
public String getId()
{
return _id;
}
public void setId(String id)
{
if (id == null) {
_id = null;
_clientId = null;
return;
}
int len = id.length();
if (len == 0)
throw new IllegalArgumentException();
char ch = id.charAt(0);
if (! ('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'))
throw new IllegalArgumentException();
for (int i = 1; i < len; i++) {
ch = id.charAt(i);
if (! ('a' <= ch && ch <= 'z'
|| 'A' <= ch && ch <= 'Z'
|| '0' <= ch && ch <= '9'
|| ch == '_'
|| ch == '-'))
throw new IllegalArgumentException();
}
_id = id;
_clientId = null;
}
public UIComponent getParent()
{
return _parent;
}
public void setParent(UIComponent parent)
{
_parent = parent;
}
public boolean isRendered()
{
if (_isRendered != null)
return _isRendered;
else if (_isRenderedExpr != null)
return Util.evalBoolean(_isRenderedExpr, getFacesContext());
else
return true;
}
public void setRendered(boolean isRendered)
{
_isRendered = isRendered;
}
public String getRendererType()
{
if (_rendererType != null)
return _rendererType;
else if (_rendererTypeExpr != null)
return Util.evalString(_rendererTypeExpr, getFacesContext());
else
return null;
}
public void setRendererType(String rendererType)
{
_rendererType = rendererType;
}
public boolean getRendersChildren()
{
Renderer renderer = getRenderer(getFacesContext());
if (renderer != null)
return renderer.getRendersChildren();
else
return false;
}
public List<UIComponent> getChildren()
{
if (_children == null)
_children = new ComponentList(this);
return _children;
}
public int getChildCount()
{
if (_children != null)
return _children.size();
else
return 0;
}
public UIComponent findComponent(String expr)
{
UIComponent base = null;
String []values = expr.split(":");
if (values[0].equals("")) {
for (base = this; base.getParent() != null; base = base.getParent()) {
}
}
else {
for (base = this;
base.getParent() != null && ! (base instanceof NamingContainer);
base = base.getParent()) {
}
}
for (int i = 0; i < values.length; i++) {
String v = values[i];
if ("".equals(v))
continue;
base = findComponent(base, v);
if (i + 1 == values.length)
return base;
if (base == null)
return base;
if (! (base instanceof NamingContainer)) {
throw new IllegalArgumentException("'" + v + "' in expression '" + expr + "' does not match an intermediate NamingContainer.");
}
}
return base;
}
private static UIComponent findComponent(UIComponent comp, String id)
{
if (id.equals(comp.getId()))
return comp;
Iterator iter = comp.getFacetsAndChildren();
while (iter.hasNext()) {
UIComponent child = (UIComponent) iter.next();
if (id.equals(child.getId()))
return child;
if (! (child instanceof NamingContainer)) {
UIComponent desc = findComponent(child, id);
if (desc != null)
return desc;
}
}
return null;
}
public Map<String,UIComponent> getFacets()
{
if (_facets == null)
_facets = new ComponentMap(this);
return _facets;
}
public UIComponent getFacet(String name)
{
if (_facets != null)
return _facets.get(name);
else
return null;
}
public Iterator<UIComponent> getFacetsAndChildren()
{
return new FacetAndChildIterator(getFacetsAndChildrenArray());
}
UIComponent []getFacetsAndChildrenArray()
{
if (_facetsAndChildren == null) {
if (_children == null && _facets == null)
_facetsAndChildren = NULL_FACETS_AND_CHILDREN;
else {
int facetCount = getFacetCount();
int childCount = getChildCount();
_facetsAndChildren = new UIComponent[facetCount + childCount];
int i = 0;
if (_facets != null) {
for (UIComponent facet : _facets.values()) {
_facetsAndChildren[i++] = facet;
}
}
for (int j = 0; j < childCount; j++) {
_facetsAndChildren[i++] = _children.get(j);
}
}
}
return _facetsAndChildren;
}
//
// Listeners, broadcast and event handling
//
protected void addFacesListener(FacesListener listener)
{
if (listener == null)
throw new NullPointerException();
int length = _facesListeners.length;
FacesListener[] newListeners = new FacesListener[length + 1];
System.arraycopy(_facesListeners, 0, newListeners, 0, length);
newListeners[length] = listener;
_facesListeners = newListeners;
}
protected FacesListener []getFacesListeners(Class cl)
{
if (FacesListener.class.equals(cl))
return _facesListeners;
int count = 0;
for (int i = _facesListeners.length - 1; i >= 0; i--) {
if (cl.isAssignableFrom(_facesListeners[i].getClass()))
count++;
}
FacesListener []array = (FacesListener []) Array.newInstance(cl, count);
count = 0;
for (int i = _facesListeners.length - 1; i >= 0; i--) {
if (cl.isAssignableFrom(_facesListeners[i].getClass())) {
array[count++] = _facesListeners[i];
}
}
return array;
}
protected void removeFacesListener(FacesListener listener)
{
if (listener == null)
throw new NullPointerException();
int length = _facesListeners.length;
for (int i = 0; i < length; i++) {
if (listener.equals(_facesListeners[i])) {
FacesListener []newListeners = new FacesListener[length - 1];
System.arraycopy(_facesListeners, 0, newListeners, 0, i);
System.arraycopy(_facesListeners, i + 1, newListeners, i,
length - i - 1);
_facesListeners = newListeners;
return;
}
}
}
public void queueEvent(FacesEvent event)
{
UIComponent parent = getParent();
if (parent != null)
parent.queueEvent(event);
else
throw new IllegalStateException();
}
public void broadcast(FacesEvent event)
throws AbortProcessingException
{
for (int i = 0; i < _facesListeners.length; i++) {
if (event.isAppropriateListener(_facesListeners[i])) {
event.processListener(_facesListeners[i]);
}
}
}
//
// decoding
//
/**
* Recursively calls the decodes for any children, then calls
* decode().
*/
public void processDecodes(FacesContext context)
{
if (context == null)
throw new NullPointerException();
if (! isRendered())
return;
for (UIComponent child : getFacetsAndChildrenArray()) {
child.processDecodes(context);
}
try {
decode(context);
} catch (RuntimeException e) {
context.renderResponse();
throw e;
}
}
/**
* Decodes the value of the component.
*/
@Override
public void decode(FacesContext context)
{
Renderer renderer = getRenderer(context);
if (renderer != null)
renderer.decode(context, this);
}
//
// Validation
//
@Override
public void processValidators(FacesContext context)
{
if (context == null)
throw new NullPointerException();
if (! isRendered())
return;
for (UIComponent child : getFacetsAndChildrenArray()) {
child.processValidators(context);
}
}
//
// Model updates
//
public void processUpdates(FacesContext context)
{
if (context == null)
throw new NullPointerException();
if (! isRendered())
return;
for (UIComponent child : getFacetsAndChildrenArray()) {
child.processUpdates(context);
}
}
//
// Encoding
//
/**
* Starts the output rendering for the encoding.
*/
public void encodeBegin(FacesContext context)
throws IOException
{
if (context == null)
throw new NullPointerException();
if (! isRendered())
return;
try {
Renderer renderer = getRenderer(context);
if (renderer != null)
renderer.encodeBegin(context, this);
} catch (IOException e) {
if (e.getMessage().startsWith("id="))
throw e;
else
throw new IOExceptionWrapper("id=" + getClientId(context)
+ " " + e.toString(), e);
} catch (RuntimeException e) {
if (e.getMessage() != null
&& e.getMessage().startsWith("id="))
throw e;
else
throw new FacesException("id=" + getClientId(context)
+ " " + e.toString(), e);
}
}
public void encodeChildren(FacesContext context)
throws IOException
{
if (context == null)
throw new NullPointerException();
if (! isRendered())
return;
Renderer renderer = getRenderer(context);
if (renderer != null)
renderer.encodeChildren(context, this);
}
public void encodeEnd(FacesContext context)
throws IOException
{
if (context == null)
throw new NullPointerException();
if (! isRendered())
return;
Renderer renderer = getRenderer(context);
if (renderer != null)
renderer.encodeEnd(context, this);
}
@Override
protected FacesContext getFacesContext()
{
return FacesContext.getCurrentInstance();
}
@Override
protected Renderer getRenderer(FacesContext context)
{
String rendererType = getRendererType();
if (rendererType == null)
return null;
RenderKit renderKit = context.getRenderKit();
if (renderKit != null)
return renderKit.getRenderer(getFamily(), getRendererType());
else
return null;
}
//
// Save the state of the component
//
public Object processSaveState(FacesContext context)
{
if (context == null)
throw new NullPointerException();
if (isTransient())
return null;
UIComponent []facetsAndChildren = getFacetsAndChildrenArray();
Object []childSaveState = null;
int childSize = getChildCount();
int facetSize = getFacetCount();
int k = 1;
if (childSize > 0) {
List<UIComponent> children = getChildren();
for (int i = 0; i < childSize; i++) {
UIComponent child = children.get(i);
if (child.isTransient())
continue;
k++;
Object childState = child.processSaveState(context);
if (childState != null) {
if (childSaveState == null)
childSaveState = new Object[1 + childSize + 2 * facetSize];
childSaveState[k - 1] = childState;
}
}
}
if (facetSize > 0) {
Map<String,UIComponent> facetMap = getFacets();
for (Map.Entry<String,UIComponent> entry : facetMap.entrySet()) {
UIComponent facet = entry.getValue();
if (facet.isTransient())
continue;
k += 2;
Object facetState = facet.processSaveState(context);
if (facetState != null) {
if (childSaveState == null)
childSaveState = new Object[1 + childSize + 2 * facetSize];
childSaveState[k - 2] = entry.getKey();
childSaveState[k - 1] = facetState;
}
}
}
Object selfSaveState = saveState(context);
if (childSaveState != null) {
childSaveState[0] = selfSaveState;
return childSaveState;
}
else
return new Object[] { selfSaveState };
}
public void processRestoreState(FacesContext context,
Object state)
{
if (context == null)
throw new NullPointerException();
if (isTransient())
return;
UIComponent []facetsAndChildren = getFacetsAndChildrenArray();
Object []baseState = (Object []) state;
if (baseState == null)
return;
restoreState(context, baseState[0]);
if (baseState.length == 1)
return;
int childSize = getChildCount();
int facetSize = getFacetCount();
int k = 1;
if (childSize > 0) {
List<UIComponent> children = getChildren();
for (int i = 0; i < childSize; i++) {
UIComponent child = children.get(i);
if (child.isTransient()) {
continue;
}
k++;
Object childState;
if (k <= baseState.length)
childState = baseState[k - 1];
else
childState = null;
if (childState != null)
child.processRestoreState(context, childState);
}
}
if (facetSize > 0) {
Map<String,UIComponent> facetMap = getFacets();
for (; k < baseState.length; k += 2) {
String facetName = (String) baseState[k];
Object facetState = baseState[k + 1];
if (facetName != null && facetState != null) {
UIComponent facet = facetMap.get(facetName);
if (facet != null)
facet.processRestoreState(context, facetState);
}
}
}
}
public Object saveState(FacesContext context)
{
Integer rendererCode = _rendererToCodeMap.get(_rendererType);
String rendererString = null;
if (rendererCode == null)
rendererString = _rendererType;
Object []savedListeners = saveListeners(context);
Object []savedBindings = saveBindings(context);
return new Object[] {
_id,
savedBindings,
_isRendered,
rendererCode,
rendererString,
(_attributeMap != null ? _attributeMap.saveState(context) : null),
savedListeners,
};
}
private Object []saveBindings(FacesContext context) {
if (bindings == null)
return null;
Set<String> keys = bindings.keySet();
Object [] result = new Object [keys.size() * 2];
int index = 0;
for (String key : keys) {
result [index++] = key;
ValueExpression valueExpression = bindings.get(key);
result [index++] = saveAttachedState(context, valueExpression);
}
return result;
}
private void restoreBindings(FacesContext context, Object stateObj) {
Object [] state = (Object []) stateObj;
if (state.length == 0) return;
bindings = new HashMap<String, ValueExpression>();
for (int i = 0; i < state.length / 2; i++) {
int index = i * 2;
String key = (String) state[index];
ValueExpression valueExpression
= (ValueExpression) restoreAttachedState(context, state [index + 1]);
bindings.put(key, valueExpression);
}
}
private Object []saveListeners(FacesContext context)
{
if (_facesListeners.length > 0) {
Object []savedListeners = new Object[2 * _facesListeners.length];
for (int i = 0; i < _facesListeners.length; i++) {
FacesListener listener = _facesListeners[i];
int index = 2 * i;
if (listener instanceof java.io.Serializable) {
savedListeners[index] = java.io.Serializable.class;
savedListeners[index + 1] = listener;
} else if (listener instanceof StateHolder) {
savedListeners[index] = listener.getClass();
StateHolder holder = (StateHolder) listener;
savedListeners[index + 1] = holder.saveState(context);
} else {
savedListeners[index] = listener.getClass();
}
}
return savedListeners;
}
return null;
}
public void restoreState(FacesContext context, Object stateObj)
{
Object []state = (Object []) stateObj;
_id = (String) state[0];
Object []savedBindings = (Object[]) state[1];
if (savedBindings != null)
restoreBindings(context, savedBindings);
if (bindings != null) {
for (Map.Entry<String,ValueExpression> entry : bindings.entrySet()) {
setValueExpression(entry.getKey(), entry.getValue());
}
}
_isRendered = (Boolean) state[2];
Integer rendererCode = (Integer) state[3];
String rendererString = (String) state[4];
if (rendererCode != null)
_rendererType = _codeToRendererMap.get(rendererCode);
else
_rendererType = rendererString;
Object extMapState = state[5];
if (extMapState != null) {
if (_attributeMap == null)
_attributeMap = new AttributeMap(this);
_attributeMap.restoreState(context, extMapState);
}
Object []savedListeners = (Object []) state[6];
restoreListeners(context, savedListeners);
}
private void restoreListeners(FacesContext context, Object[] savedListeners)
{
if (savedListeners != null) {
_facesListeners = new FacesListener[savedListeners.length / 2];
for (int i = 0; i < _facesListeners.length; i++) {
int index = 2 * i;
Class cl = (Class) savedListeners[index];
try {
if (java.io.Serializable.class.equals(cl)) {
_facesListeners[i] = (FacesListener) savedListeners[index + 1];
}
else {
FacesListener listener = (FacesListener) cl.newInstance();
if (listener instanceof StateHolder) {
StateHolder holder = (StateHolder) listener;
holder.restoreState(context, savedListeners[index + 1]);
}
_facesListeners[i] = listener;
}
}
catch (Exception e) {
throw new FacesException(e);
}
}
}
}
private Object saveExprMap(FacesContext context,
Map<String,ValueExpression> exprMap)
{
if (exprMap == null)
return null;
int size = exprMap.size();
Object []values = new Object[3 * size];
int i = 0;
for (Map.Entry<String,ValueExpression> entry : exprMap.entrySet()) {
values[i++] = entry.getKey();
ValueExpression expr = entry.getValue();
values[i++] = expr.getExpressionString();
values[i++] = expr.getExpectedType();
}
return values;
}
private HashMap<String,ValueExpression>
restoreExprMap(FacesContext context, Object value)
{
if (value == null)
return null;
Object []state = (Object[]) value;
HashMap<String,ValueExpression> map
= new HashMap<String,ValueExpression>();
Application app = context.getApplication();
ExpressionFactory exprFactory = app.getExpressionFactory();
int i = 0;
while (i < state.length) {
String key = (String) state[i++];
String exprString = (String) state[i++];
Class type = (Class) state[i++];
ValueExpression expr
= exprFactory.createValueExpression(context.getELContext(),
exprString,
type);
map.put(key, expr);
}
return map;
}
public void setTransient(boolean isTransient)
{
_isTransient = isTransient;
}
public boolean isTransient()
{
return _isTransient;
}
private void removeChild(UIComponent child)
{
if (_children != null) {
if (_children.remove(child))
return;
}
if (_facets != null) {
for (Map.Entry<String,UIComponent> entry : _facets.entrySet()) {
if (entry.getValue() == child) {
_facets.remove(entry.getKey());
return;
}
}
}
}
public static Object saveAttachedState(FacesContext context,
Object attachedObject)
{
if (attachedObject == null)
return null;
else if (attachedObject instanceof List) {
List list = (List) attachedObject;
ArrayList values = new ArrayList();
int len = list.size();
for (int i = 0; i < len; i++) {
values.add(saveAttachedState(context, list.get(i)));
}
return values;
}
else if (attachedObject instanceof StateHolder)
return new StateHandle(context, attachedObject);
else if (attachedObject instanceof Serializable)
return attachedObject;
else
return new StateHandle(context, attachedObject);
}
public static Object restoreAttachedState(FacesContext context,
Object stateObject)
{
if (stateObject == null)
return null;
else if (stateObject instanceof List) {
List list = (List) stateObject;
ArrayList values = new ArrayList();
int size = list.size();
for (int i = 0; i < size; i++) {
values.add(restoreAttachedState(context, list.get(i)));
}
return values;
}
else if (stateObject instanceof StateHandle)
return ((StateHandle) stateObject).restore(context);
else
return stateObject;
}
private static class StateHandle implements java.io.Serializable {
private Class _class;
private Object _state;
public StateHandle()
{
}
public StateHandle(FacesContext context, Object value)
{
_class = value.getClass();
if (value instanceof StateHolder)
_state = ((StateHolder) value).saveState(context);
}
public Object restore(FacesContext context)
{
try {
Object value = _class.newInstance();
if (value instanceof StateHolder)
((StateHolder) value).restoreState(context, _state);
return value;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private static class ComponentList extends AbstractList<UIComponent>
implements java.io.Serializable
{
private ArrayList<UIComponent> _list = new ArrayList<UIComponent>();
private UIComponentBase _parent;
ComponentList(UIComponentBase parent)
{
_parent = parent;
}
@Override
public boolean add(UIComponent child)
{
setParent(child);
_parent._facetsAndChildren = null;
boolean result = _list.add(child);
FacesContext context = FacesContext.getCurrentInstance();
return result;
}
@Override
public void add(int i, UIComponent child)
{
_list.add(i, child);
setParent(child);
_parent._facetsAndChildren = null;
}
@Override
public boolean addAll(int i, Collection<? extends UIComponent> list)
{
boolean isChange = false;
for (UIComponent child : list) {
setParent(child);
_list.add(i++, child);
isChange = true;
}
_parent._facetsAndChildren = null;
return isChange;
}
private boolean isPostback(FacesContext context) {
RenderKitFactory factory
= (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
String renderKitId = context.getViewRoot().getRenderKitId();
RenderKit renderKit = factory.getRenderKit(context, renderKitId);
if (renderKit == null)
renderKit = factory.getRenderKit(context, RenderKitFactory.HTML_BASIC_RENDER_KIT);
return renderKit.getResponseStateManager().isPostback(context);
}
@Override
public UIComponent set(int i, UIComponent child)
{
UIComponent old = _list.remove(i);
if (old != null)
old.setParent(null);
setParent(child);
_list.add(i, child);
_parent._facetsAndChildren = null;
return old;
}
@Override
public UIComponent remove(int i)
{
UIComponent old = _list.remove(i);
if (old != null) {
old.setParent(null);
}
_parent._facetsAndChildren = null;
return old;
}
@Override
public boolean remove(Object v)
{
UIComponent comp = (UIComponent) v;
if (_list.remove(comp)) {
comp.setParent(null);
_parent._facetsAndChildren = null;
return true;
}
else
return false;
}
@Override
public UIComponent get(int i)
{
return _list.get(i);
}
private void setParent(UIComponent child)
{
UIComponent parent = child.getParent();
if (parent == null) {
}
else if (parent instanceof UIComponentBase) {
((UIComponentBase) parent).removeChild(child);
}
else {
parent.getChildren().remove(child);
}
child.setParent(_parent);
}
public int size()
{
return _list.size();
}
public boolean isEmpty()
{
return _list.isEmpty();
}
public Iterator<UIComponent> iterator()
{
return _list.iterator();
}
}
public String toString()
{
return getClass().getName() + "[" + getId() + "]";
}
private static class ComponentMap extends HashMap<String,UIComponent>
{
private UIComponentBase _parent;
ComponentMap(UIComponentBase parent)
{
_parent = parent;
}
@Override
public UIComponent put(String key, UIComponent o)
{
if (key == null)
throw new NullPointerException();
_parent._facetsAndChildren = null;
UIComponent child = o;
UIComponent parent = child.getParent();
if (parent instanceof UIComponentBase) {
((UIComponentBase) parent).removeChild(child);
}
child.setParent(_parent);
UIComponent oldChild = super.put(key, o);
if (oldChild != null && oldChild != o) {
oldChild.setParent(null);
}
return oldChild;
}
@Override
public UIComponent remove(Object key)
{
if (key == null)
throw new NullPointerException();
_parent._facetsAndChildren = null;
UIComponent oldChild = super.remove(key);
if (oldChild != null) {
oldChild.setParent(null);
}
return oldChild;
}
}
private static class FacetAndChildIterator
implements Iterator<UIComponent> {
private final UIComponent []_children;
private int _index;
FacetAndChildIterator(UIComponent []children)
{
_children = children;
}
public boolean hasNext()
{
return _index < _children.length;
}
public UIComponent next()
{
if (_index < _children.length)
return _children[_index++];
else
return null;
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
private static class AttributeMap extends AbstractMap<String,Object>
implements Serializable
{
private final transient HashMap<String,Property> _propertyMap;
private HashMap<String,Object> _extMap;
private Object _obj;
AttributeMap(Object obj)
{
_obj = obj;
Class cl = obj.getClass();
synchronized (cl) {
HashMap<String,Property> propMap = _compMap.get(cl);
if (propMap == null) {
propMap = introspectComponent(cl);
_compMap.put(cl, propMap);
}
_propertyMap = propMap;
}
}
Object saveState(FacesContext context)
{
return _extMap;
}
void restoreState(FacesContext context, Object state)
{
_extMap = (HashMap<String,Object>) state;
}
public boolean containsKey(String name)
{
Property prop = _propertyMap.get(name);
if (prop != null)
return false;
else if (_extMap != null)
return _extMap.containsKey(name);
else
return false;
}
@Override
public Object get(Object v)
{
String name = (String) v;
Property prop = _propertyMap.get(name);
if (prop == null) {
if (_extMap != null)
return _extMap.get(name);
else {
// XXX: ValueExpression?
return null;
}
}
Method getter = prop.getGetter();
if (getter == null)
throw new IllegalArgumentException(name + " is not readable");
try {
return getter.invoke(_obj);
} catch (InvocationTargetException e) {
throw new FacesException(e.getCause());
} catch (Exception e) {
throw new FacesException(e);
}
}
@Override
public Object put(String name, Object value)
{
if (name == null || value == null)
throw new NullPointerException();
Property prop = _propertyMap.get(name);
if (prop == null) {
if (_extMap == null)
_extMap = new HashMap<String,Object>(8);
return _extMap.put(name, value);
}
if (prop.getSetter() == null)
throw new IllegalArgumentException(name + " is not writable");
try {
return prop.getSetter().invoke(_obj, value);
} catch (Exception e) {
throw new FacesException(e);
}
}
@Override
public Object remove(Object name)
{
Property prop = _propertyMap.get(name);
if (prop == null) {
if (_extMap != null)
return _extMap.remove(name);
else
return null;
}
throw new IllegalArgumentException(name + " cannot be removed");
}
public Set<Map.Entry<String,Object>> entrySet()
{
if (_extMap != null)
return _extMap.entrySet();
else
return Collections.EMPTY_SET;
}
private static HashMap<String,Property> introspectComponent(Class cl)
{
HashMap<String,Property> map = new HashMap<String,Property>();
try {
BeanInfo info = Introspector.getBeanInfo(cl, Object.class);
for (PropertyDescriptor propDesc : info.getPropertyDescriptors()) {
Property prop = new Property(propDesc.getReadMethod(),
propDesc.getWriteMethod());
map.put(propDesc.getName(), prop);
}
} catch (Exception e) {
throw new FacesException(e);
}
return map;
}
}
private static class Property {
private final Method _getter;
private final Method _setter;
Property(Method getter, Method setter)
{
_getter = getter;
_setter = setter;
}
public Method getGetter()
{
return _getter;
}
public Method getSetter()
{
return _setter;
}
}
private static class ValueExpressionAdapter
extends ValueExpression
implements StateHolder
{
private ValueBinding _binding;
private boolean _isTransient;
ValueExpressionAdapter()
{
}
ValueExpressionAdapter(ValueBinding binding)
{
_binding = binding;
}
ValueBinding getBinding()
{
return _binding;
}
public Object getValue(ELContext elContext)
{
return _binding.getValue(FacesContext.getCurrentInstance());
}
public void setValue(ELContext elContext, Object value)
{
_binding.setValue(FacesContext.getCurrentInstance(), value);
}
public boolean isReadOnly(ELContext elContext)
{
return _binding.isReadOnly(FacesContext.getCurrentInstance());
}
public Class getType(ELContext elContext)
{
return _binding.getType(FacesContext.getCurrentInstance());
}
public Class getExpectedType()
{
return Object.class;
}
public boolean isLiteralText()
{
return false;
}
public int hashCode()
{
return _binding.getExpressionString().hashCode();
}
public boolean equals(Object o)
{
if (! (o instanceof ValueExpression))
return false;
ValueExpression expr = (ValueExpression) o;
return getExpressionString().equals(expr.getExpressionString());
}
public String getExpressionString()
{
return _binding.getExpressionString();
}
public Object saveState(FacesContext context)
{
return saveAttachedState(context, _binding);
}
public void restoreState(FacesContext context, Object state)
{
_binding = (ValueBinding) restoreAttachedState(context, state);
}
public boolean isTransient()
{
return _isTransient;
}
public void setTransient(boolean isTransient)
{
_isTransient = isTransient;
}
public String toString()
{
return "ValueExpressionAdapter[" + getExpressionString() + "]";
}
}
private static class ValueBindingAdapter extends ValueBinding
{
private final ValueExpression _expr;
ValueBindingAdapter(ValueExpression expr)
{
_expr = expr;
}
public Object getValue(FacesContext context)
throws EvaluationException
{
return _expr.getValue(context.getELContext());
}
public void setValue(FacesContext context, Object value)
throws EvaluationException
{
_expr.setValue(context.getELContext(), value);
}
public boolean isReadOnly(FacesContext context)
throws EvaluationException
{
return _expr.isReadOnly(context.getELContext());
}
public Class getType(FacesContext context)
throws EvaluationException
{
return _expr.getType(context.getELContext());
}
public String getExpressionString()
{
return _expr.getExpressionString();
}
public String toString()
{
return "ValueBindingAdapter[" + _expr + "]";
}
}
static class IOExceptionWrapper extends IOException {
private Throwable _cause;
IOExceptionWrapper(String msg, Throwable cause)
{
super(msg);
_cause = cause;
}
public Throwable getCause()
{
return _cause;
}
}
private static final void addRendererCode(String renderer)
{
if (renderer == null || _rendererToCodeMap.get(renderer) != null)
return;
Integer code = _rendererToCodeMap.size() + 1;
_rendererToCodeMap.put(renderer, code);
_codeToRendererMap.put(code, renderer);
}
static {
addRendererCode(new UIColumn().getRendererType());
addRendererCode(new UICommand().getRendererType());
addRendererCode(new UIData().getRendererType());
addRendererCode(new UIForm().getRendererType());
addRendererCode(new UIGraphic().getRendererType());
addRendererCode(new UIInput().getRendererType());
addRendererCode(new UIMessage().getRendererType());
addRendererCode(new UIMessages().getRendererType());
addRendererCode(new UINamingContainer().getRendererType());
addRendererCode(new UIOutput().getRendererType());
addRendererCode(new UIPanel().getRendererType());
addRendererCode(new UIParameter().getRendererType());
addRendererCode(new UISelectBoolean().getRendererType());
addRendererCode(new UISelectItem().getRendererType());
addRendererCode(new UISelectItems().getRendererType());
addRendererCode(new UISelectMany().getRendererType());
addRendererCode(new UISelectOne().getRendererType());
addRendererCode(new UIViewRoot().getRendererType());
addRendererCode(new HtmlColumn().getRendererType());
addRendererCode(new HtmlCommandButton().getRendererType());
addRendererCode(new HtmlCommandLink().getRendererType());
addRendererCode(new HtmlDataTable().getRendererType());
addRendererCode(new HtmlForm().getRendererType());
addRendererCode(new HtmlGraphicImage().getRendererType());
addRendererCode(new HtmlInputHidden().getRendererType());
addRendererCode(new HtmlInputSecret().getRendererType());
addRendererCode(new HtmlInputText().getRendererType());
addRendererCode(new HtmlInputTextarea().getRendererType());
addRendererCode(new HtmlMessage().getRendererType());
addRendererCode(new HtmlMessages().getRendererType());
addRendererCode(new HtmlOutputFormat().getRendererType());
addRendererCode(new HtmlOutputLabel().getRendererType());
addRendererCode(new HtmlOutputLink().getRendererType());
addRendererCode(new HtmlOutputText().getRendererType());
addRendererCode(new HtmlPanelGrid().getRendererType());
addRendererCode(new HtmlPanelGroup().getRendererType());
addRendererCode(new HtmlSelectBooleanCheckbox().getRendererType());
addRendererCode(new HtmlSelectManyCheckbox().getRendererType());
addRendererCode(new HtmlSelectManyListbox().getRendererType());
addRendererCode(new HtmlSelectManyMenu().getRendererType());
addRendererCode(new HtmlSelectOneListbox().getRendererType());
addRendererCode(new HtmlSelectOneMenu().getRendererType());
addRendererCode(new HtmlSelectOneRadio().getRendererType());
}
}