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.skin;
20  
21  import java.util.Iterator;
22  import java.util.Map;
23  import java.util.WeakHashMap;
24  
25  import javax.faces.context.ExternalContext;
26  import javax.faces.context.FacesContext;
27  
28  import org.apache.myfaces.trinidad.logging.TrinidadLogger;
29  
30  
31  /**
32   * All methods in this class dealing with skin management activities such as loading, creating,
33   * managing and disposing skins are deprecated. It is recommended to use SkinProvider instead of
34   * SkinFactory for the deprecated APIs. SkinProvider introduces lazy / on-demand loading of skins as
35   * opposed to eager loading done by SkinFactory. SkinProvider also introduces the flexibility to
36   * create and manage external skin repositories. Thus we have better manageability of Skins and
37   * clear separation of external skins and trinidad provided / supported skins.
38   * <p/>
39   * SkinFactory exists today to provide SkinProvider implementers an easy way to create a Skin object
40   * without having to implement Skin interface.This is done using SkinFactory#createSkin API. Skin
41   * object created using this API can be used by the SkinProvider implementation's
42   * SkinProvider#getSkin methods. SkinProvider implementation should take care of managing the skin
43   * and destroy it when required.
44   * <p/>
45   * Creating a Skin using this SkinFactory#createSkin API is different from adding a Skin into
46   * SkinFactory using SkinFactory#addSkin. With SkinFactory#createSkin the responsibility of managing
47   * the Skin and returning is in response to SkinProvider#getSkin calls is with the SkinProvider and
48   * with SkinFactory#addSkin, this responsibility is with the SkinFactory.
49   *
50   * @see SkinProvider
51   * @see Skin
52   * @see SkinMetadata
53   */
54  abstract public class SkinFactory
55  {
56    /**
57     * Retrieve the current SkinFactory.
58     */
59    static public SkinFactory getFactory()
60    {
61      synchronized (_FACTORIES)
62      {
63        return _FACTORIES.get(_getClassLoader());
64      }
65    }
66  
67    /**
68     * Store the current SkinFactory.
69     */
70    static public void setFactory(SkinFactory factory)
71    {
72      synchronized (_FACTORIES)
73      {
74        ClassLoader cl = _getClassLoader();
75        if (_FACTORIES.get(cl) != null)
76        {
77          throw new IllegalStateException(_LOG.getMessage(
78            "FACTORY_ALREADY_AVAILABlE_FOR_THIS_CLASS_LOADER"));
79        }
80  
81        _FACTORIES.put(cl, factory);
82      }
83    }
84  
85    /**
86     * Creates a Skin based on the supplied base skin information and skinMetadata information. This
87     * API can be used by SkinProvider implementers to create Skin objects which their SkinProvider
88     * implementation supports. As a minimum, the user of this API should pass information to obtain
89     * the base skin through 'baseSkinMetadata' and provide information such as id, family, renderkit
90     * etc for the new skin through 'skinMetadata'.
91     *
92     * @param externalContext  valid ExternalContext
93     * @param baseSkinMetadata {@link SkinMetadata} metadata to find the base skin for the new skin to
94     *                         be created. The user should pass enough information to pick the base
95     *                         skin with id / family / version / renderkit. Base skin is obtained
96     *                         using SkinProvider#getSkin API.
97     * @param skinMetadata     {@link SkinMetadata} metadata to create new Skin. The user should pass
98     *                         all information such as id, family, version, renderkit, styleSheetName,
99     *                         features, metadata etc. for the new skin.
100    * @return a new skin {@link Skin} object created using the skinMetadata {@link SkinMetadata}
101    * supplied
102    * @throws IllegalArgumentException if the baseSkinId contained in the supplied skinMetadata did
103    *                                  not match the id of the baseSkin obtained using
104    *                                  baseSkinMetadata
105    * @throws ClassCastException       if SkinProvider does not provide as matching base skin as per
106    *                                  metadata passed in baseSkinMetadata
107    */
108   public Skin createSkin(
109     ExternalContext externalContext,
110     SkinMetadata baseSkinMetadata,
111     SkinMetadata skinMetadata)
112   {
113     throw new UnsupportedOperationException(_LOG.getMessage("SKIN_FACTORY_NO_CREATE_SKIN_SUPPORT",
114                                                             this));
115   }
116 
117   /**
118    * Creates a Skin based on the supplied base skin information and skinMetadata information. This
119    * API can be used by SkinProvider implementers to create Skin objects which their SkinProvider
120    * implementation supports. As a minimum, the user of this API should pass information such as
121    * baseSkinId, id, family, renderkit etc for the new skin through 'skinMetadata'.
122    *
123    * @param externalContext valid ExternalContext
124    * @param skinMetadata    {@link SkinMetadata} metadata to create new Skin. The user should
125    *                        pass all information such as baseSkinId, id, family, version, renderkit,
126    *                        styleSheetName, features, metadata etc. for the new skin. baseSkinId is
127    *                        mandatory, since it is used to query the base skin for the new skin
128    *                        using SkinProvider#getSkin API.
129    * @return a new skin {@link Skin} object created using the skinMetadata {@link SkinMetadata}
130    * supplied
131    * @throws IllegalArgumentException if the baseSkinId contained in the supplied skinMetadata did
132    *                                  not match the id of the baseSkin obtained from
133    *                                  SkinProvider#getSkin
134    */
135   public Skin createSkin(ExternalContext externalContext, SkinMetadata skinMetadata)
136   {
137     throw new UnsupportedOperationException(_LOG.getMessage("SKIN_FACTORY_NO_CREATE_SKIN_SUPPORT",
138                                                             this));
139   }
140 
141   /**
142    * Reloads the skins that was registered with this factory. Subclassers can choose to provide the
143    * implementation.
144    *
145    * @deprecated use SkinProvider SPI to deal with externals skins this functionality will now be
146    * replaced by having the SkinProvider implementations reloading skins themselves as and when
147    * required.
148    */
149   @Deprecated
150   public void reload()
151   {
152     _LOG.warning("SKIN_FACTORY_NO_RELOAD_SUPPORT", this);
153   }
154 
155   /**
156    * <p>Register the specified {@link Skin} instance, associated with the specified
157    * <code>skinId</code>, to be supported by this {@link SkinFactory}, replacing any previously
158    * registered {@link Skin} for this identifier.</p>
159    *
160    * @param skinId Identifier of the {@link Skin} to register
161    * @param skin   {@link Skin} instance that we are registering
162    * @deprecated use SkinProvider SPI to deal with externals skins Implementing SkinProvider and
163    * exposing skins using SkinProvider#getSkin() method is recommended than using this API to make
164    * skins available at runtime.
165    */
166   @Deprecated
167   public abstract void addSkin(String skinId, Skin skin);
168 
169 
170   /**
171    * <p>Return a {@link Skin} instance for the specified skinId. If there is no registered {@link
172    * Skin} for the specified identifier, return <code>null</code>.  The set of available skin
173    * identifiers is available via the <code>getSkinIds()</code> method.</p>
174    *
175    * @param context FacesContext for the request currently being processed, or <code>null</code> if
176    *                none is available.
177    * @param skinId  Skin identifier of the requested {@link Skin} instance
178    * @deprecated use SkinProvider#getSkin method to query skins
179    */
180   @Deprecated
181   public abstract Skin getSkin(FacesContext context, String skinId);
182 
183   /**
184    * <p>Return a {@link Skin} instance for the specified skinFamily and renderKitId. If there is no
185    * registered {@link Skin} for the specified identifier, return <code>null</code>.  The set of
186    * available skin identifiers is available via the <code>getSkinIds()</code> method.</p>
187    *
188    * @param context     FacesContext for the request currently being processed, or <code>null</code>
189    *                    if none is available.
190    * @param family      family of the requested {@link Skin} instance
191    * @param renderKitId RenderKit identifier of the requested {@link Skin} instance
192    * @deprecated use SkinProvider#getSkin method to query skins
193    */
194   @Deprecated
195   public abstract Skin getSkin(
196     FacesContext context,
197     String family,
198     String renderKitId);
199 
200 
201 
202   /**
203    * <p>Return a {@link Skin} instance for the specified skinFamily and renderKitId, and skin
204    * version. The best matched skin is returned. If there is no registered {@link Skin} for the
205    * specified identifier, return <code>null</code>.  The set of available skin identifiers is
206    * available via the <code>getSkinIds()</code> method.</p>
207    *
208    * @param context     FacesContext for the request currently being processed, or <code>null</code>
209    *                    if none is available.
210    * @param family      family of the requested {@link Skin} instance
211    * @param renderKitId RenderKit identifier of the requested {@link Skin} instance
212    * @param version     A string that denotes the skin version name. It can be "default" or the name
213    *                    of the version (see the Skin's SkinVersion#getName) or null which returns
214    *                    the skin with no version set.
215    * @deprecated use SkinProvider#getSkin method to query skins
216    */
217   @Deprecated
218   public abstract Skin getSkin(
219     FacesContext context,
220     String family,
221     String renderKitId,
222     String version);
223 
224   /**
225    * <p>Return an <code>Iterator</code> over the set of skin identifiers registered with this
226    * factory. </p>
227    *
228    * @deprecated use SkinProvider#getSkinMetadata to get the list of skins supported
229    */
230   @Deprecated
231   public abstract Iterator<String> getSkinIds();
232 
233 
234   static private ClassLoader _getClassLoader()
235   {
236     return Thread.currentThread().getContextClassLoader();
237   }
238 
239   private static final Map<ClassLoader, SkinFactory> _FACTORIES =
240     new WeakHashMap<ClassLoader, SkinFactory>();
241   private static final TrinidadLogger                _LOG       =
242     TrinidadLogger.createTrinidadLogger(SkinFactory.class);
243 }