1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.myfaces.trinidad.change;
20
21 import java.io.Serializable;
22 import javax.faces.component.UIComponent;
23 import javax.faces.context.FacesContext;
24
25 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
26
27 /**
28 * Proxy class representing the state of the UIComponent.
29 * 'state' here means the state as served by saveState() method in interface
30 * javax.faces.component.StateHolder.
31 * @version $Name: $ ($Revision: adfrt/faces/adf-faces-api/src/main/java/oracle/adf/view/faces/change/ChangeComponentProxy.java#0 $) $Date: 10-nov-2005.19:09:57 $
32 * @todo =-=pu: saveState() just saves the state of this component, what if we
33 * were to represent a component subtree in ChangeComponentProxy. We would
34 * need to do things similar to UIComponent.processSaveState() does with the
35 * exception that we disregard the 'transient' attribute in the algorithm.
36 */
37 class ChangeComponentProxy implements Serializable
38 {
39 /**
40 * Constructs an ChangeComponentProxy with the specified UIComponent instance.
41 * @throws IllegalArgumentException if specified uiComponent were to be null.
42 */
43 public ChangeComponentProxy(
44 FacesContext facesContext,
45 UIComponent uiComponent)
46 {
47 if (uiComponent == null)
48 throw new IllegalArgumentException(_LOG.getMessage(
49 "CANNOT_CONSTRUCT_CHANGECOMPONENTPROXY_WITH_NULL_UICOMPONENT"));
50 _class = uiComponent.getClass();
51 _className = _class.getName();
52 _state = uiComponent.saveState(facesContext);
53 }
54
55 /**
56 * Creates a new UIComponent, corresponding to this proxy, restores its state
57 * and returns the same. Returns 'null' if this process fails for any reason.
58 */
59 public UIComponent createComponent()
60 {
61 UIComponent uic = null;
62 Class<? extends UIComponent> clazz = _getComponentClass();
63 if (clazz == null)
64 {
65 // An error must have already been logged in _getComponentClass();
66 return null;
67 }
68
69 try
70 {
71 uic = clazz.newInstance();
72 uic.restoreState(FacesContext.getCurrentInstance(), _state);
73 }
74 catch (InstantiationException ie)
75 {
76 _LOG.warning("ERR_CREATE_NEW_COMPONENT_INSTANCE", clazz.getName());
77 _LOG.warning(ie);
78 }
79 catch (IllegalAccessException iae)
80 {
81 _LOG.warning("ERR_CREATE_NEW_COMPONENT_INSTANCE", clazz.getName());
82 _LOG.warning(iae);
83 }
84 return uic;
85 }
86
87 @SuppressWarnings("unchecked")
88 private Class<? extends UIComponent> _getComponentClass()
89 {
90 Class<? extends UIComponent> clazz = _class;
91 if (clazz == null)
92 {
93 try
94 {
95 ClassLoader cl = Thread.currentThread().getContextClassLoader();
96 clazz = (Class<? extends UIComponent>)cl.loadClass(_className);
97 _class = clazz;
98 }
99 catch (ClassNotFoundException e)
100 {
101 _LOG.severe(e);
102 }
103 }
104
105 return clazz;
106 }
107
108 private static final TrinidadLogger _LOG =
109 TrinidadLogger.createTrinidadLogger(ChangeComponentProxy.class);
110
111 // FindBugs claims this as "Transient field that isn't set
112 // by deserialization", but _getComponentClass() lazily restores it
113 private transient Class<? extends UIComponent> _class;
114 private String _className;
115 private Object _state;
116
117 private static final long serialVersionUID = 1L;
118 }