View Javadoc

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 }