| 43 | | protected final static Logger log = Logger.getLogger("xtc.factory"); |
|---|
| 44 | | |
|---|
| 45 | | private Compiler compiler; |
|---|
| 46 | | |
|---|
| 47 | | private Map templates; |
|---|
| 48 | | |
|---|
| 49 | | private Map relativeLocations; |
|---|
| 50 | | |
|---|
| 51 | | private Resolver resolver; |
|---|
| 52 | | |
|---|
| 53 | | private long refreshPeriod; |
|---|
| 54 | | |
|---|
| 55 | | public DefaultTemplateFactory() throws IOException { |
|---|
| 56 | | this(Compiler.getInstance(), new ClassLoaderResolver()); |
|---|
| 57 | | } |
|---|
| 58 | | |
|---|
| 59 | | public DefaultTemplateFactory(Compiler compiler, Resolver resolver) |
|---|
| 60 | | throws IOException { |
|---|
| 61 | | this(compiler, resolver, -1); |
|---|
| 62 | | } |
|---|
| 63 | | |
|---|
| 64 | | public DefaultTemplateFactory(Compiler compiler, Resolver resolver, |
|---|
| 65 | | long refreshPeriod) { |
|---|
| 66 | | ParameterCheck.notNull("compiler", compiler); |
|---|
| 67 | | ParameterCheck.notNull("resolver", resolver); |
|---|
| 68 | | this.compiler = compiler; |
|---|
| 69 | | this.templates = new HashMap(); |
|---|
| 70 | | this.relativeLocations = new HashMap(); |
|---|
| 71 | | setResolver(resolver); |
|---|
| 72 | | // this.location = url; |
|---|
| 73 | | log.fine("Using ResourceResolver: " + resolver); |
|---|
| 74 | | this.refreshPeriod = (refreshPeriod > 0) ? refreshPeriod * 1000 : -1; |
|---|
| 75 | | log.fine("Using Refresh Period: " + this.refreshPeriod); |
|---|
| 76 | | } |
|---|
| 77 | | |
|---|
| 78 | | public void setResolver(Resolver resolver) { |
|---|
| 79 | | this.resolver = resolver; |
|---|
| 80 | | } |
|---|
| 81 | | |
|---|
| 82 | | public Template getTemplate(String uri) throws IOException, |
|---|
| 83 | | TemplateException, ELException { |
|---|
| 84 | | URL url = (URL) this.relativeLocations.get(uri); |
|---|
| 85 | | if (url == null) { |
|---|
| 86 | | url = this.resolveURL(null, 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.getTemplate(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 Template from the passed URL. This method checks if the cached |
|---|
| 125 | | * Template 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 Template instance |
|---|
| 131 | | * @throws IOException |
|---|
| 132 | | * @throws TemplateException |
|---|
| 133 | | * @throws ELException |
|---|
| 134 | | */ |
|---|
| 135 | | protected Template getTemplate(URL url) throws IOException, |
|---|
| 136 | | TemplateException, ELException { |
|---|
| 137 | | ParameterCheck.notNull("url", url); |
|---|
| 138 | | DefaultTemplate f = (DefaultTemplate) this.templates.get(url); |
|---|
| 139 | | if (f == null || this.needsToBeRefreshed(f)) { |
|---|
| 140 | | f = this.createTemplate(url); |
|---|
| 141 | | this.templates.put(url, f); |
|---|
| 142 | | } |
|---|
| 143 | | return f; |
|---|
| 144 | | } |
|---|
| 145 | | |
|---|
| 146 | | /** |
|---|
| 147 | | * Template method for determining if the Template needs to be refreshed. |
|---|
| 148 | | * |
|---|
| 149 | | * @param template |
|---|
| 150 | | * Template that could have expired |
|---|
| 151 | | * @return true if it needs to be refreshed |
|---|
| 152 | | */ |
|---|
| 153 | | protected boolean needsToBeRefreshed(DefaultTemplate template) |
|---|
| 154 | | throws TemplateException { |
|---|
| 155 | | if (this.refreshPeriod != -1) { |
|---|
| 156 | | long ttl = template.getCreateTime() + this.refreshPeriod; |
|---|
| 157 | | if (System.currentTimeMillis() > ttl) { |
|---|
| 158 | | try { |
|---|
| 159 | | long atl = template.getSource().openConnection() |
|---|
| 160 | | .getLastModified(); |
|---|
| 161 | | return atl > ttl; |
|---|
| 162 | | } catch (Exception e) { |
|---|
| 163 | | throw new TemplateException( |
|---|
| 164 | | "Error Checking Last Modified for " |
|---|
| 165 | | + template.getAlias(), e); |
|---|
| 166 | | } |
|---|
| 167 | | } |
|---|
| 168 | | } |
|---|
| 169 | | return false; |
|---|
| 170 | | } |
|---|
| 171 | | |
|---|
| 172 | | /** |
|---|
| 173 | | * Uses the internal Compiler reference to build a Template given the passed |
|---|
| 174 | | * URL. |
|---|
| 175 | | * |
|---|
| 176 | | * @param url |
|---|
| 177 | | * source |
|---|
| 178 | | * @return a Template instance |
|---|
| 179 | | * @throws IOException |
|---|
| 180 | | * @throws TemplateException |
|---|
| 181 | | * @throws ELException |
|---|
| 182 | | */ |
|---|
| 183 | | private DefaultTemplate createTemplate(URL url) throws IOException, |
|---|
| 184 | | TemplateException, ELException { |
|---|
| 185 | | if (log.isLoggable(Level.FINE)) { |
|---|
| 186 | | log.fine("Creating Template for: " + url); |
|---|
| 187 | | } |
|---|
| 188 | | String alias = url.toString(); |
|---|
| 189 | | try { |
|---|
| 190 | | TemplateHandler h = this.compiler.compile(url, alias); |
|---|
| 191 | | DefaultTemplate f = new DefaultTemplate(this, this.compiler |
|---|
| 192 | | .createExpressionFactory(), url, alias, h); |
|---|
| 193 | | return f; |
|---|
| 194 | | } catch (FileNotFoundException fnfe) { |
|---|
| 195 | | if (log.isLoggable(Level.WARNING)) { |
|---|
| 196 | | log.warning(alias + " not found at " + url.toExternalForm()); |
|---|
| 197 | | } |
|---|
| 198 | | throw new FileNotFoundException("Template Not Found: " |
|---|
| 199 | | + url.toExternalForm()); |
|---|
| 200 | | } |
|---|
| 201 | | } |
|---|
| 202 | | |
|---|
| 203 | | /** |
|---|
| 204 | | * Compiler this factory uses |
|---|
| 205 | | * |
|---|
| 206 | | * @return final Compiler instance |
|---|
| 207 | | */ |
|---|
| 208 | | public Compiler getCompiler() { |
|---|
| 209 | | return this.compiler; |
|---|
| 210 | | } |
|---|
| 211 | | |
|---|
| 212 | | public long getRefreshPeriod() { |
|---|
| 213 | | return refreshPeriod; |
|---|
| 214 | | } |
|---|
| | 43 | protected final static Logger log = Logger.getLogger("xtc.factory"); |
|---|
| | 44 | |
|---|
| | 45 | private Compiler compiler; |
|---|
| | 46 | |
|---|
| | 47 | private Map templates; |
|---|
| | 48 | |
|---|
| | 49 | private Map relativeLocations; |
|---|
| | 50 | |
|---|
| | 51 | private Resolver resolver; |
|---|
| | 52 | |
|---|
| | 53 | private long refreshPeriod; |
|---|
| | 54 | |
|---|
| | 55 | public DefaultTemplateFactory() throws IOException { |
|---|
| | 56 | this(Compiler.getInstance(), new ClassLoaderResolver()); |
|---|
| | 57 | } |
|---|
| | 58 | |
|---|
| | 59 | public DefaultTemplateFactory(Compiler compiler, Resolver resolver) |
|---|
| | 60 | throws IOException { |
|---|
| | 61 | this(compiler, resolver, -1); |
|---|
| | 62 | } |
|---|
| | 63 | |
|---|
| | 64 | public DefaultTemplateFactory(Compiler compiler, Resolver resolver, |
|---|
| | 65 | long refreshPeriod) { |
|---|
| | 66 | ParameterCheck.notNull("compiler", compiler); |
|---|
| | 67 | ParameterCheck.notNull("resolver", resolver); |
|---|
| | 68 | this.compiler = compiler; |
|---|
| | 69 | this.templates = new HashMap(); |
|---|
| | 70 | this.relativeLocations = new HashMap(); |
|---|
| | 71 | setResolver(resolver); |
|---|
| | 72 | // this.location = url; |
|---|
| | 73 | log.fine("Using ResourceResolver: " + resolver); |
|---|
| | 74 | this.refreshPeriod = (refreshPeriod > 0) ? refreshPeriod * 1000 : -1; |
|---|
| | 75 | log.fine("Using Refresh Period: " + this.refreshPeriod); |
|---|
| | 76 | } |
|---|
| | 77 | |
|---|
| | 78 | public void setResolver(Resolver resolver) { |
|---|
| | 79 | this.resolver = resolver; |
|---|
| | 80 | } |
|---|
| | 81 | |
|---|
| | 82 | public Template getTemplate(String uri) throws IOException, |
|---|
| | 83 | TemplateException, ELException { |
|---|
| | 84 | URL url = (URL) this.relativeLocations.get(uri); |
|---|
| | 85 | if (url == null) { |
|---|
| | 86 | url = this.resolveURL(null, 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.getTemplate(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 Template from the passed URL. This method checks if the cached |
|---|
| | 125 | * Template 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 Template instance |
|---|
| | 131 | * @throws IOException |
|---|
| | 132 | * @throws TemplateException |
|---|
| | 133 | * @throws ELException |
|---|
| | 134 | */ |
|---|
| | 135 | protected Template getTemplate(URL url) throws IOException, |
|---|
| | 136 | TemplateException, ELException { |
|---|
| | 137 | ParameterCheck.notNull("url", url); |
|---|
| | 138 | DefaultTemplate f = (DefaultTemplate) this.templates.get(url); |
|---|
| | 139 | if (f == null || this.needsToBeRefreshed(f)) { |
|---|
| | 140 | f = this.createTemplate(url); |
|---|
| | 141 | this.templates.put(url, f); |
|---|
| | 142 | } |
|---|
| | 143 | return f; |
|---|
| | 144 | } |
|---|
| | 145 | |
|---|
| | 146 | /** |
|---|
| | 147 | * Template method for determining if the Template needs to be refreshed. |
|---|
| | 148 | * |
|---|
| | 149 | * @param template |
|---|
| | 150 | * Template that could have expired |
|---|
| | 151 | * @return true if it needs to be refreshed |
|---|
| | 152 | */ |
|---|
| | 153 | protected boolean needsToBeRefreshed(DefaultTemplate template) |
|---|
| | 154 | throws TemplateException { |
|---|
| | 155 | if (this.refreshPeriod != -1) { |
|---|
| | 156 | long ttl = template.getCreateTime() + this.refreshPeriod; |
|---|
| | 157 | if (System.currentTimeMillis() > ttl) { |
|---|
| | 158 | try { |
|---|
| | 159 | long atl = template.getSource().openConnection() |
|---|
| | 160 | .getLastModified(); |
|---|
| | 161 | return atl > ttl; |
|---|
| | 162 | } catch (Exception e) { |
|---|
| | 163 | throw new TemplateException( |
|---|
| | 164 | "Error Checking Last Modified for " |
|---|
| | 165 | + template.getAlias(), e); |
|---|
| | 166 | } |
|---|
| | 167 | } |
|---|
| | 168 | } |
|---|
| | 169 | return false; |
|---|
| | 170 | } |
|---|
| | 171 | |
|---|
| | 172 | /** |
|---|
| | 173 | * Uses the internal Compiler reference to build a Template given the passed |
|---|
| | 174 | * URL. |
|---|
| | 175 | * |
|---|
| | 176 | * @param url |
|---|
| | 177 | * source |
|---|
| | 178 | * @return a Template instance |
|---|
| | 179 | * @throws IOException |
|---|
| | 180 | * @throws TemplateException |
|---|
| | 181 | * @throws ELException |
|---|
| | 182 | */ |
|---|
| | 183 | private DefaultTemplate createTemplate(URL url) throws IOException, |
|---|
| | 184 | TemplateException, ELException { |
|---|
| | 185 | if (log.isLoggable(Level.FINE)) { |
|---|
| | 186 | log.fine("Creating Template for: " + url); |
|---|
| | 187 | } |
|---|
| | 188 | String alias = url.toString(); |
|---|
| | 189 | try { |
|---|
| | 190 | TemplateHandler h = this.compiler.compile(url, alias); |
|---|
| | 191 | DefaultTemplate f = new DefaultTemplate(this, this.compiler |
|---|
| | 192 | .createExpressionFactory(), url, alias, h); |
|---|
| | 193 | return f; |
|---|
| | 194 | } catch (FileNotFoundException fnfe) { |
|---|
| | 195 | if (log.isLoggable(Level.WARNING)) { |
|---|
| | 196 | log.warning(alias + " not found at " + url.toExternalForm()); |
|---|
| | 197 | } |
|---|
| | 198 | throw new FileNotFoundException("Template Not Found: " |
|---|
| | 199 | + url.toExternalForm()); |
|---|
| | 200 | } |
|---|
| | 201 | } |
|---|
| | 202 | |
|---|
| | 203 | /** |
|---|
| | 204 | * Compiler this factory uses |
|---|
| | 205 | * |
|---|
| | 206 | * @return final Compiler instance |
|---|
| | 207 | */ |
|---|
| | 208 | public Compiler getCompiler() { |
|---|
| | 209 | return this.compiler; |
|---|
| | 210 | } |
|---|
| | 211 | |
|---|
| | 212 | public long getRefreshPeriod() { |
|---|
| | 213 | return refreshPeriod; |
|---|
| | 214 | } |
|---|
| | 215 | |
|---|
| | 216 | public void setRefreshPeriod(long refreshPeriod) { |
|---|
| | 217 | this.refreshPeriod = refreshPeriod; |
|---|
| | 218 | } |
|---|