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

Quick Search    Search Deep

Source code: com/sun/facelets/impl/DefaultFaceletFactory.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.FileNotFoundException;
18  import java.io.IOException;
19  import java.net.URL;
20  import java.util.HashMap;
21  import java.util.Map;
22  import java.util.logging.Level;
23  import java.util.logging.Logger;
24  
25  import javax.el.ELException;
26  import javax.faces.FacesException;
27  import javax.faces.context.FacesContext;
28  
29  import com.sun.facelets.Facelet;
30  import com.sun.facelets.FaceletException;
31  import com.sun.facelets.FaceletFactory;
32  import com.sun.facelets.FaceletHandler;
33  import com.sun.facelets.compiler.Compiler;
34  import com.sun.facelets.util.ParameterCheck;
35  import com.sun.facelets.util.Resource;
36  
37  /**
38   * Default FaceletFactory implementation.
39   * 
40   * @author Jacob Hookom
41   * @version $Id: DefaultFaceletFactory.java,v 1.8 2006/05/03 04:30:13 jhook Exp $
42   */
43  public final class DefaultFaceletFactory extends FaceletFactory {
44  
45      protected final static Logger log = Logger.getLogger("facelets.factory");
46  
47      private final Compiler compiler;
48  
49      private final Map facelets;
50  
51      private final Map relativeLocations;
52      
53      private final ResourceResolver resolver;
54      
55      private final URL baseUrl;
56  
57      private final long refreshPeriod;
58  
59      public DefaultFaceletFactory(Compiler compiler, ResourceResolver resolver) throws IOException {
60          this(compiler, resolver, -1);
61      }
62  
63      public DefaultFaceletFactory(Compiler compiler, ResourceResolver resolver, long refreshPeriod) {
64          ParameterCheck.notNull("compiler", compiler);
65          ParameterCheck.notNull("resolver", resolver);
66          this.compiler = compiler;
67          this.facelets = new HashMap();
68          this.relativeLocations = new HashMap();
69          this.resolver = resolver;
70          this.baseUrl = resolver.resolveUrl("/");
71          //this.location = url;
72          log.fine("Using ResourceResolver: " + resolver);
73          this.refreshPeriod = (refreshPeriod > 0) ? refreshPeriod * 1000 : -1;
74          log.fine("Using Refresh Period: " + this.refreshPeriod);
75      }
76  
77      /*
78       * (non-Javadoc)
79       * 
80       * @see com.sun.facelets.FaceletFactory#getFacelet(java.lang.String)
81       */
82      public Facelet getFacelet(String uri) throws IOException, FaceletException,
83              FacesException, ELException {
84          URL url = (URL) this.relativeLocations.get(uri);
85          if (url == null) {
86              url = this.resolveURL(this.baseUrl, uri);
87              if (url != null) {
88                  this.relativeLocations.put(uri, url);
89              } else {
90                  throw new IOException("'" + uri + "' not found.");
91              }
92          }
93          return this.getFacelet(url);
94      }
95  
96      /**
97       * Resolves a path based on the passed URL. If the path starts with '/',
98       * then resolve the path against
99       * {@link javax.faces.context.ExternalContext#getResource(java.lang.String) javax.faces.context.ExternalContext#getResource(java.lang.String)}.
100      * Otherwise create a new URL via
101      * {@link URL#URL(java.net.URL, java.lang.String) URL(URL, String)}.
102      * 
103      * @param source
104      *            base to resolve from
105      * @param path
106      *            relative path to the source
107      * @return resolved URL
108      * @throws IOException
109      */
110     public URL resolveURL(URL source, String path) throws IOException {
111         if (path.startsWith("/")) {
112             URL url = this.resolver.resolveUrl(path);
113             if (url == null) {
114                 throw new FileNotFoundException(path
115                         + " Not Found in ExternalContext as a Resource");
116             }
117             return url;
118         } else {
119             return new URL(source, path);
120         }
121     }
122 
123     /**
124      * Create a Facelet from the passed URL. This method checks if the cached
125      * Facelet needs to be refreshed before returning. If so, uses the passed
126      * URL to build a new instance;
127      * 
128      * @param url
129      *            source url
130      * @return Facelet instance
131      * @throws IOException
132      * @throws FaceletException
133      * @throws FacesException
134      * @throws ELException
135      */
136     public Facelet getFacelet(URL url) throws IOException, FaceletException,
137             FacesException, ELException {
138         ParameterCheck.notNull("url", url);
139         DefaultFacelet f = (DefaultFacelet) this.facelets.get(url);
140         if (f == null || this.needsToBeRefreshed(f)) {
141             f = this.createFacelet(url);
142             this.facelets.put(url, f);
143         }
144         return f;
145     }
146 
147     /**
148      * Template method for determining if the Facelet needs to be refreshed.
149      * 
150      * @param facelet
151      *            Facelet that could have expired
152      * @return true if it needs to be refreshed
153      */
154     protected boolean needsToBeRefreshed(DefaultFacelet facelet) {
155         if (this.refreshPeriod != -1) {
156             long ttl = facelet.getCreateTime() + this.refreshPeriod;
157             if (System.currentTimeMillis() > ttl) {
158                 try {
159                     long atl = facelet.getSource().openConnection()
160                             .getLastModified();
161                     return atl > ttl;
162                 } catch (Exception e) {
163                     throw new FaceletException(
164                             "Error Checking Last Modified for "
165                                     + facelet.getAlias(), e);
166                 }
167             }
168         }
169         return false;
170     }
171 
172     /**
173      * Uses the internal Compiler reference to build a Facelet given the passed
174      * URL.
175      * 
176      * @param url
177      *            source
178      * @return a Facelet instance
179      * @throws IOException
180      * @throws FaceletException
181      * @throws FacesException
182      * @throws ELException
183      */
184     private DefaultFacelet createFacelet(URL url) throws IOException,
185             FaceletException, FacesException, ELException {
186         if (log.isLoggable(Level.FINE)) {
187             log.fine("Creating Facelet for: " + url);
188         }
189         String alias = "/"
190                 + url.getFile().replaceFirst(this.baseUrl.getFile(), "");
191         try {
192             FaceletHandler h = this.compiler.compile(url, alias);
193             DefaultFacelet f = new DefaultFacelet(this, this.compiler
194                     .createExpressionFactory(), url, alias, h);
195             return f;
196         } catch (FileNotFoundException fnfe) {
197             if (log.isLoggable(Level.WARNING)) {
198                 log.warning(alias + " not found at " + url.toExternalForm());
199             }
200             throw new FileNotFoundException("Facelet Not Found: " + url.toExternalForm());
201         }
202     }
203 
204     /**
205      * Compiler this factory uses
206      * 
207      * @return final Compiler instance
208      */
209     public Compiler getCompiler() {
210         return this.compiler;
211     }
212 
213     public long getRefreshPeriod() {
214         return refreshPeriod;
215     }
216 }