Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/sun/facelets/impl/DefaultFacelet.java


1   /**
2    * Licensed under the Common Development and Distribution License,
3    * you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at
5    * 
6    *   http://www.sun.com/cddl/
7    *   
8    * Unless required by applicable law or agreed to in writing, software
9    * distributed under the License is distributed on an "AS IS" BASIS,
10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
11   * implied. See the License for the specific language governing
12   * permissions and limitations under the License.
13   */
14  
15  package com.sun.facelets.impl;
16  
17  import java.io.Externalizable;
18  import java.io.IOException;
19  import java.io.ObjectInput;
20  import java.io.ObjectOutput;
21  import java.net.URL;
22  import java.text.DateFormat;
23  import java.text.SimpleDateFormat;
24  import java.util.Collection;
25  import java.util.Date;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.WeakHashMap;
30  import java.util.logging.Level;
31  import java.util.logging.Logger;
32  
33  import javax.el.ELException;
34  import javax.el.ExpressionFactory;
35  import javax.faces.FacesException;
36  import javax.faces.component.UIComponent;
37  import javax.faces.context.FacesContext;
38  
39  import com.sun.facelets.Facelet;
40  import com.sun.facelets.FaceletContext;
41  import com.sun.facelets.FaceletException;
42  import com.sun.facelets.FaceletHandler;
43  import com.sun.facelets.tag.jsf.ComponentSupport;
44  
45  /**
46   * Default Facelet implementation.
47   * 
48   * @author Jacob Hookom
49   * @version $Id: DefaultFacelet.java,v 1.9 2006/04/03 05:10:38 jhook Exp $
50   */
51  final class DefaultFacelet extends Facelet {
52  
53      private final Logger log = Logger.getLogger("facelets.facelet");
54  
55      private final static String APPLIED_KEY = "com.sun.facelets.APPLIED";
56  
57      private final String alias;
58  
59      private final ExpressionFactory elFactory;
60  
61      private final DefaultFaceletFactory factory;
62  
63      private final long createTime;
64  
65      private final long refreshPeriod;
66  
67      private final Map relativePaths;
68  
69      private final FaceletHandler root;
70  
71      private final URL src;
72  
73      public DefaultFacelet(DefaultFaceletFactory factory, ExpressionFactory el,
74              URL src, String alias, FaceletHandler root) {
75          this.factory = factory;
76          this.elFactory = el;
77          this.src = src;
78          this.root = root;
79          this.alias = alias;
80          this.createTime = System.currentTimeMillis();
81          this.refreshPeriod = this.factory.getRefreshPeriod();
82          this.relativePaths = new WeakHashMap();
83      }
84  
85      /**
86       * @see com.sun.facelets.Facelet#apply(javax.faces.context.FacesContext,
87       *      javax.faces.component.UIComponent)
88       */
89      public void apply(FacesContext facesContext, UIComponent parent)
90              throws IOException, FacesException, FaceletException, ELException {
91          DefaultFaceletContext ctx = new DefaultFaceletContext(facesContext,
92                  this);
93          this.refresh(parent);
94          ComponentSupport.markForDeletion(parent);
95          this.root.apply(ctx, parent);
96          ComponentSupport.finalizeForDeletion(parent);
97          this.markApplied(parent);
98      }
99  
100     private final void refresh(UIComponent c) {
101         if (this.refreshPeriod > 0) {
102 
103             // finally remove any children marked as deleted
104             int sz = c.getChildCount();
105             if (sz > 0) {
106                 UIComponent cc = null;
107                 List cl = c.getChildren();
108                 ApplyToken token;
109                 while (--sz >= 0) {
110                     cc = (UIComponent) cl.get(sz);
111                     if (!cc.isTransient()) {
112                         token = (ApplyToken) cc.getAttributes().get(APPLIED_KEY);
113                         if (token != null && token.time < this.createTime
114                                 && token.alias.equals(this.alias)) {
115                             if (log.isLoggable(Level.INFO)) {
116                                 DateFormat df = SimpleDateFormat.getTimeInstance();
117                                 log.info("Facelet[" + this.alias
118                                         + "] was modified @ "
119                                         + df.format(new Date(this.createTime))
120                                         + ", flushing component applied @ "
121                                         + df.format(new Date(token.time)));
122                             }
123                             cl.remove(sz);
124                         }
125                     }
126                 }
127             }
128 
129             // remove any facets marked as deleted
130             if (c.getFacets().size() > 0) {
131                 Collection col = c.getFacets().values();
132                 UIComponent fc;
133                 ApplyToken token;
134                 for (Iterator itr = col.iterator(); itr.hasNext();) {
135                     fc = (UIComponent) itr.next();
136                     if (!fc.isTransient()) {
137                         token = (ApplyToken) fc.getAttributes().get(APPLIED_KEY);
138                         if (token != null && token.time < this.createTime
139                                 && token.alias.equals(this.alias)) {
140                             if (log.isLoggable(Level.INFO)) {
141                                 DateFormat df = SimpleDateFormat.getTimeInstance();
142                                 log.info("Facelet[" + this.alias
143                                         + "] was modified @ "
144                                         + df.format(new Date(this.createTime))
145                                         + ", flushing component applied @ "
146                                         + df.format(new Date(token.time)));
147                             }
148                             itr.remove();
149                         }
150                     }
151                 }
152             }
153         }
154     }
155 
156     private final void markApplied(UIComponent parent) {
157         if (this.refreshPeriod > 0) {
158             Iterator itr = parent.getFacetsAndChildren();
159             UIComponent c;
160             Map attr;
161             ApplyToken token = new ApplyToken(this.alias, System
162                     .currentTimeMillis()
163                     + this.refreshPeriod);
164             while (itr.hasNext()) {
165                 c = (UIComponent) itr.next();
166                 if (!c.isTransient()) {
167                     attr = c.getAttributes();
168                     if (!attr.containsKey(APPLIED_KEY)) {
169                         attr.put(APPLIED_KEY, token);
170                     }
171                 }
172             }
173         }
174     }
175 
176     /**
177      * Return the alias name for error messages and logging
178      * 
179      * @return alias name
180      */
181     public String getAlias() {
182         return this.alias;
183     }
184 
185     /**
186      * Return this Facelet's ExpressionFactory instance
187      * 
188      * @return internal ExpressionFactory instance
189      */
190     public ExpressionFactory getExpressionFactory() {
191         return this.elFactory;
192     }
193 
194     /**
195      * The time when this Facelet was created, NOT the URL source code
196      * 
197      * @return final timestamp of when this Facelet was created
198      */
199     public long getCreateTime() {
200         return this.createTime;
201     }
202 
203     /**
204      * Delegates resolution to DefaultFaceletFactory reference. Also, caches
205      * URLs for relative paths.
206      * 
207      * @param path
208      *            a relative url path
209      * @return URL pointing to destination
210      * @throws IOException
211      *             if there is a problem creating the URL for the path specified
212      */
213     private URL getRelativePath(String path) throws IOException {
214         URL url = (URL) this.relativePaths.get(path);
215         if (url == null) {
216             url = this.factory.resolveURL(this.src, path);
217             this.relativePaths.put(path, url);
218         }
219         return url;
220     }
221 
222     /**
223      * The URL this Facelet was created from.
224      * 
225      * @return the URL this Facelet was created from
226      */
227     public URL getSource() {
228         return this.src;
229     }
230 
231     /**
232      * Given the passed FaceletContext, apply our child FaceletHandlers to the
233      * passed parent
234      * 
235      * @see FaceletHandler#apply(FaceletContext, UIComponent)
236      * @param ctx
237      *            the FaceletContext to use for applying our FaceletHandlers
238      * @param parent
239      *            the parent component to apply changes to
240      * @throws IOException
241      * @throws FacesException
242      * @throws FaceletException
243      * @throws ELException
244      */
245     private void include(DefaultFaceletContext ctx, UIComponent parent)
246             throws IOException, FacesException, FaceletException, ELException {
247         this.refresh(parent);
248         this.root.apply(new DefaultFaceletContext(ctx, this), parent);
249         this.markApplied(parent);
250     }
251 
252     /**
253      * Used for delegation by the DefaultFaceletContext. First pulls the URL
254      * from {@link #getRelativePath(String) getRelativePath(String)}, then
255      * calls
256      * {@link #include(FaceletContext, UIComponent, URL) include(FaceletContext, UIComponent, URL)}.
257      * 
258      * @see FaceletContext#includeFacelet(UIComponent, String)
259      * @param ctx
260      *            FaceletContext to pass to the included Facelet
261      * @param parent
262      *            UIComponent to apply changes to
263      * @param path
264      *            relative path to the desired Facelet from the FaceletContext
265      * @throws IOException
266      * @throws FacesException
267      * @throws FaceletException
268      * @throws ELException
269      */
270     public void include(DefaultFaceletContext ctx, UIComponent parent, String path)
271             throws IOException, FacesException, FaceletException, ELException {
272         URL url = this.getRelativePath(path);
273         this.include(ctx, parent, url);
274     }
275 
276     /**
277      * Grabs a DefaultFacelet from referenced DefaultFaceletFacotry
278      * 
279      * @see DefaultFaceletFactory#getFacelet(URL)
280      * @param ctx
281      *            FaceletContext to pass to the included Facelet
282      * @param parent
283      *            UIComponent to apply changes to
284      * @param url
285      *            URL source to include Facelet from
286      * @throws IOException
287      * @throws FacesException
288      * @throws FaceletException
289      * @throws ELException
290      */
291     public void include(DefaultFaceletContext ctx, UIComponent parent, URL url)
292             throws IOException, FacesException, FaceletException, ELException {
293         DefaultFacelet f = (DefaultFacelet) this.factory.getFacelet(url);
294         f.include(ctx, parent);
295     }
296 
297     private static class ApplyToken implements Externalizable {
298         public String alias;
299 
300         public long time;
301 
302         public ApplyToken() {
303         }
304 
305         public ApplyToken(String alias, long time) {
306             this.alias = alias;
307             this.time = time;
308         }
309 
310         public void readExternal(ObjectInput in) throws IOException,
311                 ClassNotFoundException {
312             this.alias = in.readUTF();
313             this.time = in.readLong();
314         }
315 
316         public void writeExternal(ObjectOutput out) throws IOException {
317             out.writeUTF(this.alias);
318             out.writeLong(this.time);
319         }
320     }
321 
322     public String toString() {
323         return this.alias;
324     }
325 }