0001: /*
0002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003: *
0004: * This file is part of Resin(R) Open Source
0005: *
0006: * Each copy or derived work must preserve the copyright notice and this
0007: * notice unmodified.
0008: *
0009: * Resin Open Source is free software; you can redistribute it and/or modify
0010: * it under the terms of the GNU General Public License version 2
0011: * as published by the Free Software Foundation.
0012: *
0013: * Resin Open Source is distributed in the hope that it will be useful,
0014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0016: * of NON-INFRINGEMENT. See the GNU General Public License for more
0017: * details.
0018: *
0019: * You should have received a copy of the GNU General Public License
0020: * along with Resin Open Source; if not, write to the
0021: *
0022: * Free Software Foundation, Inc.
0023: * 59 Temple Place, Suite 330
0024: * Boston, MA 02111-1307 USA
0025: *
0026: * @author Scott Ferguson
0027: */
0028:
0029: package javax.faces.component;
0030:
0031: import java.beans.*;
0032: import java.lang.reflect.*;
0033:
0034: import java.io.*;
0035: import java.util.*;
0036: import java.util.logging.*;
0037:
0038: import javax.el.*;
0039:
0040: import javax.faces.*;
0041: import javax.faces.application.*;
0042: import javax.faces.component.html.*;
0043: import javax.faces.context.*;
0044: import javax.faces.el.*;
0045: import javax.faces.event.*;
0046: import javax.faces.render.*;
0047:
0048: public abstract class UIComponentBase extends UIComponent {
0049: private static final Logger log = Logger
0050: .getLogger(UIComponentBase.class.getName());
0051:
0052: private static final UIComponent[] NULL_FACETS_AND_CHILDREN = new UIComponent[0];
0053:
0054: private static final FacesListener[] NULL_FACES_LISTENERS = new FacesListener[0];
0055:
0056: private static final HashMap<String, Integer> _rendererToCodeMap = new HashMap<String, Integer>();
0057:
0058: private static final HashMap<Integer, String> _codeToRendererMap = new HashMap<Integer, String>();
0059:
0060: private static final WeakHashMap<Class, HashMap<String, Property>> _compMap = new WeakHashMap<Class, HashMap<String, Property>>();
0061:
0062: private String _id;
0063: private String _clientId;
0064:
0065: private UIComponent _parent;
0066:
0067: private String _rendererType;
0068: private ValueExpression _rendererTypeExpr;
0069:
0070: private boolean _isTransient;
0071:
0072: private Boolean _isRendered;
0073: private ValueExpression _isRenderedExpr;
0074:
0075: private ValueExpression _bindingExpr;
0076:
0077: private ComponentList _children;
0078: private ComponentMap _facets;
0079:
0080: private UIComponent[] _facetsAndChildren;
0081:
0082: private AttributeMap _attributeMap;
0083:
0084: protected Map<String, ValueExpression> _bindings;
0085:
0086: private FacesListener[] _facesListeners = NULL_FACES_LISTENERS;
0087:
0088: public Map<String, Object> getAttributes() {
0089: if (_attributeMap == null)
0090: _attributeMap = new AttributeMap(this );
0091:
0092: return _attributeMap;
0093: }
0094:
0095: @Deprecated
0096: public ValueBinding getValueBinding(String name) {
0097: ValueExpression expr = getValueExpression(name);
0098:
0099: if (expr == null)
0100: return null;
0101: else if (expr instanceof ValueExpressionAdapter)
0102: return ((ValueExpressionAdapter) expr).getBinding();
0103: else
0104: return new ValueBindingAdapter(expr);
0105: }
0106:
0107: @Deprecated
0108: public void setValueBinding(String name, ValueBinding binding) {
0109: setValueExpression(name, new ValueExpressionAdapter(binding));
0110: }
0111:
0112: /**
0113: * Returns the value expression for an attribute
0114: *
0115: * @param name the name of the attribute to get
0116: */
0117: @Override
0118: public ValueExpression getValueExpression(String name) {
0119: if (name == null)
0120: throw new NullPointerException();
0121:
0122: if ("rendered".equals(name))
0123: return _isRenderedExpr;
0124: else if ("rendererType".equals(name))
0125: return _rendererTypeExpr;
0126: else if ("binding".equals(name))
0127: return _bindingExpr;
0128:
0129: if (_bindings != null)
0130: return _bindings.get(name);
0131: else
0132: return null;
0133: }
0134:
0135: /**
0136: * Sets the value expression for an attribute
0137: *
0138: * @param name the name of the attribute to set
0139: * @param expr the value expression
0140: */
0141: @Override
0142: public void setValueExpression(String name, ValueExpression expr) {
0143: if (name.equals("id"))
0144: throw new IllegalArgumentException(
0145: "'id' is not a valid ValueExpression name.");
0146: else if (name.equals("parent"))
0147: throw new IllegalArgumentException(
0148: "'parent' is not a valid ValueExpression name.");
0149:
0150: if ("rendered".equals(name)) {
0151: if (expr.isLiteralText()) {
0152: _isRendered = Util.booleanValueOf(expr.getValue(null));
0153: return;
0154: } else
0155: _isRenderedExpr = expr;
0156: } else if ("rendererType".equals(name)) {
0157: if (expr.isLiteralText()) {
0158: _rendererType = String.valueOf(expr.getValue(null));
0159: return;
0160: } else
0161: _rendererTypeExpr = expr;
0162: } else if ("binding".equals(name)) {
0163: _bindingExpr = expr;
0164: }
0165:
0166: try {
0167: if (expr != null) {
0168: if (expr.isLiteralText()) {
0169: getAttributes().put(name, expr.getValue(null));
0170: } else {
0171: if (_bindings == null)
0172: _bindings = new HashMap<String, ValueExpression>();
0173:
0174: _bindings.put(name, expr);
0175: }
0176: } else if (_bindings != null)
0177: _bindings.remove(name);
0178: } catch (ELException e) {
0179: throw new FacesException(e);
0180: }
0181: }
0182:
0183: /**
0184: * Returns the client-specific id for the component.
0185: */
0186: @Override
0187: public String getClientId(FacesContext context) {
0188: if (context == null)
0189: throw new NullPointerException();
0190:
0191: if (_clientId != null)
0192: return _clientId;
0193:
0194: String parentId = null;
0195:
0196: for (UIComponent ptr = getParent(); ptr != null; ptr = ptr
0197: .getParent()) {
0198: if (ptr instanceof NamingContainer) {
0199: parentId = ptr.getContainerClientId(context);
0200: break;
0201: }
0202: }
0203:
0204: String myId = _id;
0205:
0206: if (myId == null) {
0207: myId = context.getViewRoot().createUniqueId();
0208: }
0209:
0210: if (parentId != null)
0211: myId = parentId + NamingContainer.SEPARATOR_CHAR + myId;
0212:
0213: Renderer renderer = getRenderer(context);
0214:
0215: if (renderer != null)
0216: _clientId = renderer.convertClientId(context, myId);
0217: else
0218: _clientId = myId;
0219:
0220: return _clientId;
0221: }
0222:
0223: public String getFamily() {
0224: return null;
0225: }
0226:
0227: public String getId() {
0228: return _id;
0229: }
0230:
0231: public void setId(String id) {
0232: if (id == null) {
0233: _id = null;
0234: _clientId = null;
0235: return;
0236: }
0237:
0238: int len = id.length();
0239:
0240: if (len == 0)
0241: throw new IllegalArgumentException();
0242:
0243: char ch = id.charAt(0);
0244:
0245: if (!('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'))
0246: throw new IllegalArgumentException();
0247:
0248: for (int i = 1; i < len; i++) {
0249: ch = id.charAt(i);
0250:
0251: if (!('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z'
0252: || '0' <= ch && ch <= '9' || ch == '_' || ch == '-'))
0253: throw new IllegalArgumentException();
0254: }
0255:
0256: _id = id;
0257: _clientId = null;
0258: }
0259:
0260: public UIComponent getParent() {
0261: return _parent;
0262: }
0263:
0264: public void setParent(UIComponent parent) {
0265: _parent = parent;
0266: }
0267:
0268: public boolean isRendered() {
0269: if (_isRendered != null)
0270: return _isRendered;
0271: else if (_isRenderedExpr != null)
0272: return Util.evalBoolean(_isRenderedExpr, getFacesContext());
0273: else
0274: return true;
0275: }
0276:
0277: public void setRendered(boolean isRendered) {
0278: _isRendered = isRendered;
0279: }
0280:
0281: public String getRendererType() {
0282: if (_rendererType != null)
0283: return _rendererType;
0284: else if (_rendererTypeExpr != null)
0285: return Util
0286: .evalString(_rendererTypeExpr, getFacesContext());
0287: else
0288: return null;
0289: }
0290:
0291: public void setRendererType(String rendererType) {
0292: _rendererType = rendererType;
0293: }
0294:
0295: public boolean getRendersChildren() {
0296: Renderer renderer = getRenderer(getFacesContext());
0297:
0298: if (renderer != null)
0299: return renderer.getRendersChildren();
0300: else
0301: return false;
0302: }
0303:
0304: public List<UIComponent> getChildren() {
0305: if (_children == null)
0306: _children = new ComponentList(this );
0307:
0308: return _children;
0309: }
0310:
0311: public int getChildCount() {
0312: if (_children != null)
0313: return _children.size();
0314: else
0315: return 0;
0316: }
0317:
0318: public UIComponent findComponent(String expr) {
0319: UIComponent base = null;
0320:
0321: String[] values = expr.split(":");
0322:
0323: if (values[0].equals("")) {
0324: for (base = this ; base.getParent() != null; base = base
0325: .getParent()) {
0326: }
0327: } else {
0328: for (base = this ; base.getParent() != null
0329: && !(base instanceof NamingContainer); base = base
0330: .getParent()) {
0331: }
0332: }
0333:
0334: for (int i = 0; i < values.length; i++) {
0335: String v = values[i];
0336:
0337: if ("".equals(v))
0338: continue;
0339:
0340: base = findComponent(base, v);
0341:
0342: if (i + 1 == values.length)
0343: return base;
0344:
0345: if (!(base instanceof NamingContainer)) {
0346: throw new IllegalArgumentException(
0347: "'"
0348: + v
0349: + "' in expression '"
0350: + expr
0351: + "' does not match an intermediate NamingContainer.");
0352: }
0353: }
0354:
0355: return base;
0356: }
0357:
0358: private static UIComponent findComponent(UIComponent comp, String id) {
0359: if (id.equals(comp.getId()))
0360: return comp;
0361:
0362: Iterator iter = comp.getFacetsAndChildren();
0363: while (iter.hasNext()) {
0364: UIComponent child = (UIComponent) iter.next();
0365:
0366: if (id.equals(child.getId()))
0367: return child;
0368:
0369: if (!(child instanceof NamingContainer)) {
0370: UIComponent desc = findComponent(child, id);
0371:
0372: if (desc != null)
0373: return desc;
0374: }
0375: }
0376:
0377: return null;
0378: }
0379:
0380: public Map<String, UIComponent> getFacets() {
0381: if (_facets == null)
0382: _facets = new ComponentMap(this );
0383:
0384: return _facets;
0385: }
0386:
0387: public UIComponent getFacet(String name) {
0388: if (_facets != null)
0389: return _facets.get(name);
0390: else
0391: return null;
0392: }
0393:
0394: public Iterator<UIComponent> getFacetsAndChildren() {
0395: return new FacetAndChildIterator(getFacetsAndChildrenArray());
0396: }
0397:
0398: UIComponent[] getFacetsAndChildrenArray() {
0399: if (_facetsAndChildren == null) {
0400: if (_children == null && _facets == null)
0401: _facetsAndChildren = NULL_FACETS_AND_CHILDREN;
0402: else {
0403: int facetCount = getFacetCount();
0404: int childCount = getChildCount();
0405:
0406: _facetsAndChildren = new UIComponent[facetCount
0407: + childCount];
0408:
0409: int i = 0;
0410: if (_facets != null) {
0411: for (UIComponent facet : _facets.values()) {
0412: _facetsAndChildren[i++] = facet;
0413: }
0414: }
0415:
0416: for (int j = 0; j < childCount; j++) {
0417: _facetsAndChildren[i++] = _children.get(j);
0418: }
0419: }
0420: }
0421:
0422: return _facetsAndChildren;
0423: }
0424:
0425: //
0426: // Listeners, broadcast and event handling
0427: //
0428:
0429: protected void addFacesListener(FacesListener listener) {
0430: if (listener == null)
0431: throw new NullPointerException();
0432:
0433: int length = _facesListeners.length;
0434:
0435: FacesListener[] newListeners = new FacesListener[length + 1];
0436:
0437: System.arraycopy(_facesListeners, 0, newListeners, 0, length);
0438:
0439: newListeners[length] = listener;
0440:
0441: _facesListeners = newListeners;
0442: }
0443:
0444: protected FacesListener[] getFacesListeners(Class cl) {
0445: if (FacesListener.class.equals(cl))
0446: return _facesListeners;
0447:
0448: int count = 0;
0449: for (int i = _facesListeners.length - 1; i >= 0; i--) {
0450: if (cl.isAssignableFrom(_facesListeners[i].getClass()))
0451: count++;
0452: }
0453:
0454: FacesListener[] array = (FacesListener[]) Array.newInstance(cl,
0455: count);
0456: count = 0;
0457: for (int i = _facesListeners.length - 1; i >= 0; i--) {
0458: if (cl.isAssignableFrom(_facesListeners[i].getClass())) {
0459: array[count++] = _facesListeners[i];
0460: }
0461: }
0462:
0463: return array;
0464: }
0465:
0466: protected void removeFacesListener(FacesListener listener) {
0467: if (listener == null)
0468: throw new NullPointerException();
0469:
0470: int length = _facesListeners.length;
0471: for (int i = 0; i < length; i++) {
0472: if (listener.equals(_facesListeners[i])) {
0473: FacesListener[] newListeners = new FacesListener[length - 1];
0474: System
0475: .arraycopy(_facesListeners, 0, newListeners, 0,
0476: i);
0477: System.arraycopy(_facesListeners, i + 1, newListeners,
0478: i, length - i - 1);
0479:
0480: _facesListeners = newListeners;
0481:
0482: return;
0483: }
0484: }
0485: }
0486:
0487: public void queueEvent(FacesEvent event) {
0488: UIComponent parent = getParent();
0489:
0490: if (parent != null)
0491: parent.queueEvent(event);
0492: else
0493: throw new IllegalStateException();
0494: }
0495:
0496: public void broadcast(FacesEvent event)
0497: throws AbortProcessingException {
0498: for (int i = 0; i < _facesListeners.length; i++) {
0499: if (event.isAppropriateListener(_facesListeners[i])) {
0500: event.processListener(_facesListeners[i]);
0501: }
0502: }
0503: }
0504:
0505: //
0506: // decoding
0507: //
0508:
0509: /**
0510: * Recursively calls the decodes for any children, then calls
0511: * decode().
0512: */
0513: public void processDecodes(FacesContext context) {
0514: if (context == null)
0515: throw new NullPointerException();
0516:
0517: if (!isRendered())
0518: return;
0519:
0520: for (UIComponent child : getFacetsAndChildrenArray()) {
0521: child.processDecodes(context);
0522: }
0523:
0524: try {
0525: decode(context);
0526: } catch (RuntimeException e) {
0527: log.log(Level.WARNING, e.toString(), e);
0528:
0529: context.renderResponse();
0530:
0531: throw e;
0532: }
0533: }
0534:
0535: /**
0536: * Decodes the value of the component.
0537: */
0538: @Override
0539: public void decode(FacesContext context) {
0540: Renderer renderer = getRenderer(context);
0541:
0542: if (renderer != null)
0543: renderer.decode(context, this );
0544: }
0545:
0546: //
0547: // Validation
0548: //
0549:
0550: @Override
0551: public void processValidators(FacesContext context) {
0552: if (context == null)
0553: throw new NullPointerException();
0554:
0555: if (!isRendered())
0556: return;
0557:
0558: for (UIComponent child : getFacetsAndChildrenArray()) {
0559: child.processValidators(context);
0560: }
0561: }
0562:
0563: //
0564: // Model updates
0565: //
0566:
0567: public void processUpdates(FacesContext context) {
0568: if (context == null)
0569: throw new NullPointerException();
0570:
0571: if (!isRendered())
0572: return;
0573:
0574: for (UIComponent child : getFacetsAndChildrenArray()) {
0575: child.processUpdates(context);
0576: }
0577: }
0578:
0579: //
0580: // Encoding
0581: //
0582:
0583: /**
0584: * Starts the output rendering for the encoding.
0585: */
0586: public void encodeBegin(FacesContext context) throws IOException {
0587: if (context == null)
0588: throw new NullPointerException();
0589:
0590: if (!isRendered())
0591: return;
0592:
0593: try {
0594: Renderer renderer = getRenderer(context);
0595:
0596: if (renderer != null)
0597: renderer.encodeBegin(context, this );
0598:
0599: } catch (IOException e) {
0600: if (e.getMessage().startsWith("id="))
0601: throw e;
0602: else
0603: throw new IOExceptionWrapper("id="
0604: + getClientId(context) + " " + e.toString(), e);
0605: } catch (RuntimeException e) {
0606: if (e.getMessage() != null
0607: && e.getMessage().startsWith("id="))
0608: throw e;
0609: else
0610: throw new FacesException("id=" + getClientId(context)
0611: + " " + e.toString(), e);
0612: }
0613: }
0614:
0615: public void encodeChildren(FacesContext context) throws IOException {
0616: if (context == null)
0617: throw new NullPointerException();
0618:
0619: if (!isRendered())
0620: return;
0621:
0622: Renderer renderer = getRenderer(context);
0623:
0624: if (renderer != null)
0625: renderer.encodeChildren(context, this );
0626: }
0627:
0628: public void encodeEnd(FacesContext context) throws IOException {
0629: if (context == null)
0630: throw new NullPointerException();
0631:
0632: if (!isRendered())
0633: return;
0634:
0635: Renderer renderer = getRenderer(context);
0636:
0637: if (renderer != null)
0638: renderer.encodeEnd(context, this );
0639: }
0640:
0641: @Override
0642: protected FacesContext getFacesContext() {
0643: return FacesContext.getCurrentInstance();
0644: }
0645:
0646: @Override
0647: protected Renderer getRenderer(FacesContext context) {
0648: String rendererType = getRendererType();
0649:
0650: if (rendererType == null)
0651: return null;
0652:
0653: RenderKit renderKit = context.getRenderKit();
0654:
0655: if (renderKit != null)
0656: return renderKit
0657: .getRenderer(getFamily(), getRendererType());
0658: else
0659: return null;
0660: }
0661:
0662: //
0663: // Save the state of the component
0664: //
0665:
0666: public Object processSaveState(FacesContext context) {
0667: if (context == null)
0668: throw new NullPointerException();
0669:
0670: if (isTransient())
0671: return null;
0672:
0673: UIComponent[] facetsAndChildren = getFacetsAndChildrenArray();
0674:
0675: Object[] childSaveState = null;
0676:
0677: int childSize = getChildCount();
0678: int facetSize = getFacetCount();
0679: int k = 1;
0680:
0681: if (childSize > 0) {
0682: List<UIComponent> children = getChildren();
0683:
0684: for (int i = 0; i < childSize; i++) {
0685: UIComponent child = children.get(i);
0686:
0687: if (child.isTransient())
0688: continue;
0689:
0690: k++;
0691:
0692: Object childState = child.processSaveState(context);
0693:
0694: if (childState != null) {
0695: if (childSaveState == null)
0696: childSaveState = new Object[1 + childSize + 2
0697: * facetSize];
0698:
0699: childSaveState[k - 1] = childState;
0700: }
0701: }
0702: }
0703:
0704: if (facetSize > 0) {
0705: Map<String, UIComponent> facetMap = getFacets();
0706:
0707: for (Map.Entry<String, UIComponent> entry : facetMap
0708: .entrySet()) {
0709: UIComponent facet = entry.getValue();
0710:
0711: if (facet.isTransient())
0712: continue;
0713:
0714: k += 2;
0715:
0716: Object facetState = facet.processSaveState(context);
0717:
0718: if (facetState != null) {
0719: if (childSaveState == null)
0720: childSaveState = new Object[1 + childSize + 2
0721: * facetSize];
0722:
0723: childSaveState[k - 2] = entry.getKey();
0724: childSaveState[k - 1] = facetState;
0725: }
0726: }
0727: }
0728:
0729: Object selfSaveState = saveState(context);
0730:
0731: if (childSaveState != null) {
0732: childSaveState[0] = selfSaveState;
0733: return childSaveState;
0734: } else
0735: return new Object[] { selfSaveState };
0736: }
0737:
0738: public void processRestoreState(FacesContext context, Object state) {
0739: if (context == null)
0740: throw new NullPointerException();
0741:
0742: if (isTransient())
0743: return;
0744:
0745: UIComponent[] facetsAndChildren = getFacetsAndChildrenArray();
0746:
0747: Object[] baseState = (Object[]) state;
0748:
0749: if (baseState == null)
0750: return;
0751:
0752: restoreState(context, baseState[0]);
0753:
0754: if (baseState.length == 1)
0755: return;
0756:
0757: int childSize = getChildCount();
0758: int facetSize = getFacetCount();
0759: int k = 1;
0760:
0761: if (childSize > 0) {
0762: List<UIComponent> children = getChildren();
0763:
0764: for (int i = 0; i < childSize; i++) {
0765: UIComponent child = children.get(i);
0766:
0767: if (child.isTransient()) {
0768: continue;
0769: }
0770:
0771: k++;
0772:
0773: Object childState;
0774:
0775: if (k <= baseState.length)
0776: childState = baseState[k - 1];
0777: else
0778: childState = null;
0779:
0780: if (childState != null)
0781: child.processRestoreState(context, childState);
0782: }
0783: }
0784:
0785: if (facetSize > 0) {
0786: Map<String, UIComponent> facetMap = getFacets();
0787:
0788: for (; k < baseState.length; k += 2) {
0789: String facetName = (String) baseState[k];
0790: Object facetState = baseState[k + 1];
0791:
0792: if (facetName != null && facetState != null) {
0793: UIComponent facet = facetMap.get(facetName);
0794:
0795: if (facet != null)
0796: facet.processRestoreState(context, facetState);
0797: }
0798: }
0799: }
0800: }
0801:
0802: public Object saveState(FacesContext context) {
0803: Integer rendererCode = _rendererToCodeMap.get(_rendererType);
0804: String rendererString = null;
0805:
0806: if (rendererCode == null)
0807: rendererString = _rendererType;
0808:
0809: Object[] savedListeners = saveListeners(context);
0810:
0811: return new Object[] {
0812: _id,
0813: _bindings,
0814: _isRendered,
0815: rendererCode,
0816: rendererString,
0817: (_attributeMap != null ? _attributeMap
0818: .saveState(context) : null), savedListeners, };
0819: }
0820:
0821: private Object[] saveListeners(FacesContext context) {
0822: if (_facesListeners.length > 0) {
0823: Object[] savedListeners = new Object[2 * _facesListeners.length];
0824:
0825: for (int i = 0; i < _facesListeners.length; i++) {
0826: FacesListener listener = _facesListeners[i];
0827:
0828: int index = 2 * i;
0829:
0830: savedListeners[index] = listener.getClass();
0831:
0832: if (listener instanceof StateHolder) {
0833: StateHolder holder = (StateHolder) listener;
0834:
0835: savedListeners[index + 1] = holder
0836: .saveState(context);
0837: }
0838: }
0839:
0840: return savedListeners;
0841: }
0842:
0843: return null;
0844: }
0845:
0846: public void restoreState(FacesContext context, Object stateObj) {
0847: Object[] state = (Object[]) stateObj;
0848:
0849: _id = (String) state[0];
0850: _bindings = (Map) state[1];
0851:
0852: if (_bindings != null) {
0853: for (Map.Entry<String, ValueExpression> entry : _bindings
0854: .entrySet()) {
0855: setValueExpression(entry.getKey(), entry.getValue());
0856: }
0857: }
0858:
0859: _isRendered = (Boolean) state[2];
0860:
0861: Integer rendererCode = (Integer) state[3];
0862: String rendererString = (String) state[4];
0863:
0864: if (rendererCode != null)
0865: _rendererType = _codeToRendererMap.get(rendererCode);
0866: else
0867: _rendererType = rendererString;
0868:
0869: Object extMapState = state[5];
0870:
0871: if (extMapState != null) {
0872: if (_attributeMap == null)
0873: _attributeMap = new AttributeMap(this );
0874:
0875: _attributeMap.restoreState(context, extMapState);
0876: }
0877:
0878: Object[] savedListeners = (Object[]) state[6];
0879:
0880: restoreListeners(context, savedListeners);
0881: }
0882:
0883: private void restoreListeners(FacesContext context,
0884: Object[] savedListeners) {
0885: if (savedListeners != null) {
0886: _facesListeners = new FacesListener[savedListeners.length / 2];
0887:
0888: for (int i = 0; i < _facesListeners.length; i++) {
0889: int index = 2 * i;
0890:
0891: Class cl = (Class) savedListeners[index];
0892:
0893: try {
0894: FacesListener listener = (FacesListener) cl
0895: .newInstance();
0896:
0897: if (listener instanceof StateHolder) {
0898: StateHolder holder = (StateHolder) listener;
0899:
0900: holder.restoreState(context,
0901: savedListeners[index + 1]);
0902: }
0903:
0904: _facesListeners[i] = listener;
0905: } catch (Exception e) {
0906: throw new FacesException(e);
0907: }
0908: }
0909: }
0910: }
0911:
0912: private Object saveExprMap(FacesContext context,
0913: Map<String, ValueExpression> exprMap) {
0914: if (exprMap == null)
0915: return null;
0916:
0917: int size = exprMap.size();
0918:
0919: Object[] values = new Object[3 * size];
0920:
0921: int i = 0;
0922: for (Map.Entry<String, ValueExpression> entry : exprMap
0923: .entrySet()) {
0924: values[i++] = entry.getKey();
0925:
0926: ValueExpression expr = entry.getValue();
0927: values[i++] = expr.getExpressionString();
0928: values[i++] = expr.getExpectedType();
0929: }
0930:
0931: return values;
0932: }
0933:
0934: private HashMap<String, ValueExpression> restoreExprMap(
0935: FacesContext context, Object value) {
0936: if (value == null)
0937: return null;
0938:
0939: Object[] state = (Object[]) value;
0940:
0941: HashMap<String, ValueExpression> map = new HashMap<String, ValueExpression>();
0942:
0943: Application app = context.getApplication();
0944: ExpressionFactory exprFactory = app.getExpressionFactory();
0945:
0946: int i = 0;
0947: while (i < state.length) {
0948: String key = (String) state[i++];
0949: String exprString = (String) state[i++];
0950: Class type = (Class) state[i++];
0951:
0952: ValueExpression expr = exprFactory.createValueExpression(
0953: context.getELContext(), exprString, type);
0954:
0955: map.put(key, expr);
0956: }
0957:
0958: return map;
0959: }
0960:
0961: public void setTransient(boolean isTransient) {
0962: _isTransient = isTransient;
0963: }
0964:
0965: public boolean isTransient() {
0966: return _isTransient;
0967: }
0968:
0969: private void removeChild(UIComponent child) {
0970: if (_children != null) {
0971: if (_children.remove(child))
0972: return;
0973: }
0974:
0975: if (_facets != null) {
0976: for (Map.Entry<String, UIComponent> entry : _facets
0977: .entrySet()) {
0978: if (entry.getValue() == child) {
0979: _facets.remove(entry.getKey());
0980: return;
0981: }
0982: }
0983: }
0984: }
0985:
0986: public static Object saveAttachedState(FacesContext context,
0987: Object attachedObject) {
0988: if (attachedObject == null)
0989: return null;
0990: else if (attachedObject instanceof List) {
0991: List list = (List) attachedObject;
0992:
0993: ArrayList values = new ArrayList();
0994: int len = list.size();
0995:
0996: for (int i = 0; i < len; i++) {
0997: values.add(saveAttachedState(context, list.get(i)));
0998: }
0999:
1000: return values;
1001: } else if (attachedObject instanceof StateHolder)
1002: return new StateHandle(context, attachedObject);
1003: else if (attachedObject instanceof Serializable)
1004: return attachedObject;
1005: else
1006: return new StateHandle(context, attachedObject);
1007: }
1008:
1009: public static Object restoreAttachedState(FacesContext context,
1010: Object stateObject) {
1011: if (stateObject == null)
1012: return null;
1013: else if (stateObject instanceof List) {
1014: List list = (List) stateObject;
1015:
1016: ArrayList values = new ArrayList();
1017: int size = list.size();
1018:
1019: for (int i = 0; i < size; i++) {
1020: values.add(restoreAttachedState(context, list.get(i)));
1021: }
1022:
1023: return values;
1024: } else if (stateObject instanceof StateHandle)
1025: return ((StateHandle) stateObject).restore(context);
1026: else
1027: return stateObject;
1028: }
1029:
1030: private static class StateHandle implements java.io.Serializable {
1031: private Class _class;
1032: private Object _state;
1033:
1034: public StateHandle() {
1035: }
1036:
1037: public StateHandle(FacesContext context, Object value) {
1038: _class = value.getClass();
1039:
1040: if (value instanceof StateHolder)
1041: _state = ((StateHolder) value).saveState(context);
1042: }
1043:
1044: public Object restore(FacesContext context) {
1045: try {
1046: Object value = _class.newInstance();
1047:
1048: if (value instanceof StateHolder)
1049: ((StateHolder) value).restoreState(context, _state);
1050:
1051: return value;
1052: } catch (Exception e) {
1053: throw new RuntimeException(e);
1054: }
1055: }
1056: }
1057:
1058: private static class ComponentList extends
1059: AbstractList<UIComponent> implements java.io.Serializable {
1060: private ArrayList<UIComponent> _list = new ArrayList<UIComponent>();
1061:
1062: private UIComponentBase _parent;
1063:
1064: ComponentList(UIComponentBase parent) {
1065: _parent = parent;
1066: }
1067:
1068: @Override
1069: public boolean add(UIComponent o) {
1070: UIComponent child = (UIComponent) o;
1071:
1072: setParent(child);
1073:
1074: _parent._facetsAndChildren = null;
1075:
1076: return _list.add(o);
1077: }
1078:
1079: @Override
1080: public void add(int i, UIComponent o) {
1081: UIComponent child = (UIComponent) o;
1082:
1083: _list.add(i, o);
1084:
1085: setParent(child);
1086:
1087: _parent._facetsAndChildren = null;
1088: }
1089:
1090: @Override
1091: public boolean addAll(int i,
1092: Collection<? extends UIComponent> list) {
1093: boolean isChange = false;
1094:
1095: for (UIComponent child : list) {
1096: setParent(child);
1097:
1098: _list.add(i++, child);
1099:
1100: isChange = true;
1101: }
1102:
1103: _parent._facetsAndChildren = null;
1104:
1105: return isChange;
1106: }
1107:
1108: @Override
1109: public UIComponent set(int i, UIComponent o) {
1110: UIComponent child = (UIComponent) o;
1111:
1112: UIComponent old = _list.remove(i);
1113:
1114: if (old != null)
1115: old.setParent(null);
1116:
1117: setParent(child);
1118:
1119: _list.add(i, child);
1120:
1121: _parent._facetsAndChildren = null;
1122:
1123: return old;
1124: }
1125:
1126: @Override
1127: public UIComponent remove(int i) {
1128: UIComponent old = _list.remove(i);
1129:
1130: if (old != null) {
1131: UIComponent parent = old.getParent();
1132:
1133: old.setParent(null);
1134: }
1135:
1136: _parent._facetsAndChildren = null;
1137:
1138: return old;
1139: }
1140:
1141: @Override
1142: public boolean remove(Object v) {
1143: UIComponent comp = (UIComponent) v;
1144:
1145: if (_list.remove(comp)) {
1146: comp.setParent(null);
1147:
1148: _parent._facetsAndChildren = null;
1149:
1150: return true;
1151: } else
1152: return false;
1153: }
1154:
1155: @Override
1156: public UIComponent get(int i) {
1157: return _list.get(i);
1158: }
1159:
1160: private void setParent(UIComponent child) {
1161: UIComponent parent = child.getParent();
1162:
1163: if (parent == null) {
1164: } else if (parent instanceof UIComponentBase) {
1165: ((UIComponentBase) parent).removeChild(child);
1166: } else {
1167: parent.getChildren().remove(child);
1168: }
1169:
1170: child.setParent(_parent);
1171: }
1172:
1173: public int size() {
1174: return _list.size();
1175: }
1176:
1177: public boolean isEmpty() {
1178: return _list.isEmpty();
1179: }
1180:
1181: public Iterator<UIComponent> iterator() {
1182: return _list.iterator();
1183: }
1184: }
1185:
1186: public String toString() {
1187: return getClass().getName() + "[" + getId() + "]";
1188: }
1189:
1190: private static class ComponentMap extends
1191: HashMap<String, UIComponent> {
1192: private UIComponent _parent;
1193:
1194: ComponentMap(UIComponent parent) {
1195: _parent = parent;
1196: }
1197:
1198: @Override
1199: public UIComponent put(String key, UIComponent o) {
1200: if (key == null)
1201: throw new NullPointerException();
1202:
1203: UIComponent child = (UIComponent) o;
1204:
1205: UIComponent parent = child.getParent();
1206: if (parent instanceof UIComponentBase) {
1207: ((UIComponentBase) parent).removeChild(child);
1208: }
1209:
1210: child.setParent(_parent);
1211:
1212: UIComponent oldChild = super .put(key, o);
1213:
1214: if (oldChild != null && oldChild != o) {
1215: oldChild.setParent(null);
1216: }
1217:
1218: return oldChild;
1219: }
1220:
1221: @Override
1222: public UIComponent remove(Object key) {
1223: if (key == null)
1224: throw new NullPointerException();
1225:
1226: UIComponent oldChild = super .remove(key);
1227:
1228: if (oldChild != null) {
1229: oldChild.setParent(null);
1230: }
1231:
1232: return oldChild;
1233: }
1234: }
1235:
1236: private static class FacetAndChildIterator implements
1237: Iterator<UIComponent> {
1238: private final UIComponent[] _children;
1239: private int _index;
1240:
1241: FacetAndChildIterator(UIComponent[] children) {
1242: _children = children;
1243: }
1244:
1245: public boolean hasNext() {
1246: return _index < _children.length;
1247: }
1248:
1249: public UIComponent next() {
1250: if (_index < _children.length)
1251: return _children[_index++];
1252: else
1253: return null;
1254: }
1255:
1256: public void remove() {
1257: throw new UnsupportedOperationException();
1258: }
1259: }
1260:
1261: private static class AttributeMap extends
1262: AbstractMap<String, Object> implements Serializable {
1263: private final transient HashMap<String, Property> _propertyMap;
1264: private HashMap<String, Object> _extMap;
1265: private Object _obj;
1266:
1267: AttributeMap(Object obj) {
1268: _obj = obj;
1269:
1270: Class cl = obj.getClass();
1271:
1272: synchronized (cl) {
1273: HashMap<String, Property> propMap = _compMap.get(cl);
1274:
1275: if (propMap == null) {
1276: propMap = introspectComponent(cl);
1277: _compMap.put(cl, propMap);
1278: }
1279:
1280: _propertyMap = propMap;
1281: }
1282: }
1283:
1284: Object saveState(FacesContext context) {
1285: return _extMap;
1286: }
1287:
1288: void restoreState(FacesContext context, Object state) {
1289: _extMap = (HashMap<String, Object>) state;
1290: }
1291:
1292: public boolean containsKey(String name) {
1293: Property prop = _propertyMap.get(name);
1294:
1295: if (prop != null)
1296: return false;
1297: else if (_extMap != null)
1298: return _extMap.containsKey(name);
1299: else
1300: return false;
1301: }
1302:
1303: @Override
1304: public Object get(Object v) {
1305: String name = (String) v;
1306:
1307: Property prop = _propertyMap.get(name);
1308:
1309: if (prop == null) {
1310: if (_extMap != null)
1311: return _extMap.get(name);
1312: else {
1313: // XXX: ValueExpression?
1314: return null;
1315: }
1316: }
1317:
1318: Method getter = prop.getGetter();
1319:
1320: if (getter == null)
1321: throw new IllegalArgumentException(name
1322: + " is not readable");
1323:
1324: try {
1325: return getter.invoke(_obj);
1326: } catch (InvocationTargetException e) {
1327: throw new FacesException(e.getCause());
1328: } catch (Exception e) {
1329: throw new FacesException(e);
1330: }
1331: }
1332:
1333: @Override
1334: public Object put(String name, Object value) {
1335: if (name == null || value == null)
1336: throw new NullPointerException();
1337:
1338: Property prop = _propertyMap.get(name);
1339:
1340: if (prop == null) {
1341: if (_extMap == null)
1342: _extMap = new HashMap<String, Object>(8);
1343:
1344: return _extMap.put(name, value);
1345: }
1346:
1347: if (prop.getSetter() == null)
1348: throw new IllegalArgumentException(name
1349: + " is not writable");
1350:
1351: try {
1352: return prop.getSetter().invoke(_obj, value);
1353: } catch (Exception e) {
1354: throw new FacesException(e);
1355: }
1356: }
1357:
1358: @Override
1359: public Object remove(Object name) {
1360: Property prop = _propertyMap.get(name);
1361:
1362: if (prop == null) {
1363: if (_extMap != null)
1364: return _extMap.remove(name);
1365: else
1366: return null;
1367: }
1368:
1369: throw new IllegalArgumentException(name
1370: + " cannot be removed");
1371: }
1372:
1373: public Set<Map.Entry<String, Object>> entrySet() {
1374: if (_extMap != null)
1375: return _extMap.entrySet();
1376: else
1377: return Collections.EMPTY_SET;
1378: }
1379:
1380: private static HashMap<String, Property> introspectComponent(
1381: Class cl) {
1382: HashMap<String, Property> map = new HashMap<String, Property>();
1383:
1384: try {
1385: BeanInfo info = Introspector.getBeanInfo(cl,
1386: Object.class);
1387:
1388: for (PropertyDescriptor propDesc : info
1389: .getPropertyDescriptors()) {
1390: Property prop = new Property(propDesc
1391: .getReadMethod(), propDesc.getWriteMethod());
1392:
1393: map.put(propDesc.getName(), prop);
1394: }
1395: } catch (Exception e) {
1396: throw new FacesException(e);
1397: }
1398:
1399: return map;
1400: }
1401: }
1402:
1403: private static class Property {
1404: private final Method _getter;
1405: private final Method _setter;
1406:
1407: Property(Method getter, Method setter) {
1408: _getter = getter;
1409: _setter = setter;
1410: }
1411:
1412: public Method getGetter() {
1413: return _getter;
1414: }
1415:
1416: public Method getSetter() {
1417: return _setter;
1418: }
1419: }
1420:
1421: private static class ValueExpressionAdapter extends ValueExpression {
1422: private final ValueBinding _binding;
1423:
1424: ValueExpressionAdapter(ValueBinding binding) {
1425: _binding = binding;
1426: }
1427:
1428: ValueBinding getBinding() {
1429: return _binding;
1430: }
1431:
1432: public Object getValue(ELContext elContext) {
1433: return _binding.getValue(FacesContext.getCurrentInstance());
1434: }
1435:
1436: public void setValue(ELContext elContext, Object value) {
1437: _binding.setValue(FacesContext.getCurrentInstance(), value);
1438: }
1439:
1440: public boolean isReadOnly(ELContext elContext) {
1441: return _binding.isReadOnly(FacesContext
1442: .getCurrentInstance());
1443: }
1444:
1445: public Class getType(ELContext elContext) {
1446: return _binding.getType(FacesContext.getCurrentInstance());
1447: }
1448:
1449: public Class getExpectedType() {
1450: return Object.class;
1451: }
1452:
1453: public boolean isLiteralText() {
1454: return false;
1455: }
1456:
1457: public int hashCode() {
1458: return _binding.getExpressionString().hashCode();
1459: }
1460:
1461: public boolean equals(Object o) {
1462: if (!(o instanceof ValueExpression))
1463: return false;
1464:
1465: ValueExpression expr = (ValueExpression) o;
1466:
1467: return getExpressionString().equals(
1468: expr.getExpressionString());
1469: }
1470:
1471: public String getExpressionString() {
1472: return _binding.getExpressionString();
1473: }
1474:
1475: public String toString() {
1476: return "ValueExpressionAdapter[" + getExpressionString()
1477: + "]";
1478: }
1479: }
1480:
1481: private static class ValueBindingAdapter extends ValueBinding {
1482: private final ValueExpression _expr;
1483:
1484: ValueBindingAdapter(ValueExpression expr) {
1485: _expr = expr;
1486: }
1487:
1488: public Object getValue(FacesContext context)
1489: throws EvaluationException {
1490: return _expr.getValue(context.getELContext());
1491: }
1492:
1493: public void setValue(FacesContext context, Object value)
1494: throws EvaluationException {
1495: _expr.setValue(context.getELContext(), value);
1496: }
1497:
1498: public boolean isReadOnly(FacesContext context)
1499: throws EvaluationException {
1500: return _expr.isReadOnly(context.getELContext());
1501: }
1502:
1503: public Class getType(FacesContext context)
1504: throws EvaluationException {
1505: return _expr.getType(context.getELContext());
1506: }
1507:
1508: public String getExpressionString() {
1509: return _expr.getExpressionString();
1510: }
1511:
1512: public String toString() {
1513: return "ValueBindingAdapter[" + _expr + "]";
1514: }
1515: }
1516:
1517: static class IOExceptionWrapper extends IOException {
1518: private Throwable _cause;
1519:
1520: IOExceptionWrapper(String msg, Throwable cause) {
1521: super (msg);
1522:
1523: _cause = cause;
1524: }
1525:
1526: public Throwable getCause() {
1527: return _cause;
1528: }
1529: }
1530:
1531: private static final void addRendererCode(String renderer) {
1532: if (renderer == null
1533: || _rendererToCodeMap.get(renderer) != null)
1534: return;
1535:
1536: Integer code = _rendererToCodeMap.size() + 1;
1537:
1538: _rendererToCodeMap.put(renderer, code);
1539: _codeToRendererMap.put(code, renderer);
1540: }
1541:
1542: static {
1543: addRendererCode(new UIColumn().getRendererType());
1544: addRendererCode(new UICommand().getRendererType());
1545: addRendererCode(new UIData().getRendererType());
1546: addRendererCode(new UIForm().getRendererType());
1547: addRendererCode(new UIGraphic().getRendererType());
1548: addRendererCode(new UIInput().getRendererType());
1549: addRendererCode(new UIMessage().getRendererType());
1550: addRendererCode(new UIMessages().getRendererType());
1551: addRendererCode(new UINamingContainer().getRendererType());
1552: addRendererCode(new UIOutput().getRendererType());
1553: addRendererCode(new UIPanel().getRendererType());
1554: addRendererCode(new UIParameter().getRendererType());
1555: addRendererCode(new UISelectBoolean().getRendererType());
1556: addRendererCode(new UISelectItem().getRendererType());
1557: addRendererCode(new UISelectItems().getRendererType());
1558: addRendererCode(new UISelectMany().getRendererType());
1559: addRendererCode(new UISelectOne().getRendererType());
1560: addRendererCode(new UIViewRoot().getRendererType());
1561:
1562: addRendererCode(new HtmlColumn().getRendererType());
1563: addRendererCode(new HtmlCommandButton().getRendererType());
1564: addRendererCode(new HtmlCommandLink().getRendererType());
1565: addRendererCode(new HtmlDataTable().getRendererType());
1566: addRendererCode(new HtmlForm().getRendererType());
1567: addRendererCode(new HtmlGraphicImage().getRendererType());
1568: addRendererCode(new HtmlInputHidden().getRendererType());
1569: addRendererCode(new HtmlInputSecret().getRendererType());
1570: addRendererCode(new HtmlInputText().getRendererType());
1571: addRendererCode(new HtmlInputTextarea().getRendererType());
1572: addRendererCode(new HtmlMessage().getRendererType());
1573: addRendererCode(new HtmlMessages().getRendererType());
1574: addRendererCode(new HtmlOutputFormat().getRendererType());
1575: addRendererCode(new HtmlOutputLabel().getRendererType());
1576: addRendererCode(new HtmlOutputLink().getRendererType());
1577: addRendererCode(new HtmlOutputText().getRendererType());
1578: addRendererCode(new HtmlPanelGrid().getRendererType());
1579: addRendererCode(new HtmlPanelGroup().getRendererType());
1580: addRendererCode(new HtmlSelectBooleanCheckbox()
1581: .getRendererType());
1582: addRendererCode(new HtmlSelectManyCheckbox().getRendererType());
1583: addRendererCode(new HtmlSelectManyListbox().getRendererType());
1584: addRendererCode(new HtmlSelectManyMenu().getRendererType());
1585: addRendererCode(new HtmlSelectOneListbox().getRendererType());
1586: addRendererCode(new HtmlSelectOneMenu().getRendererType());
1587: addRendererCode(new HtmlSelectOneRadio().getRendererType());
1588: }
1589: }
|