Coverage Report - org.apache.myfaces.view.facelets.impl.DefaultFaceletFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultFaceletFactory
0%
0/154
0%
0/64
3.565
DefaultFaceletFactory$1
0%
0/2
N/A
3.565
DefaultFaceletFactory$2
0%
0/2
N/A
3.565
DefaultFaceletFactory$3
0%
0/2
N/A
3.565
 
 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.view.facelets.impl;
 20  
 
 21  
 import java.io.FileNotFoundException;
 22  
 import java.io.IOException;
 23  
 import java.lang.reflect.Method;
 24  
 import java.net.URL;
 25  
 import java.net.URLConnection;
 26  
 import java.util.HashMap;
 27  
 import java.util.Map;
 28  
 import java.util.logging.Level;
 29  
 import java.util.logging.Logger;
 30  
 import java.util.regex.Pattern;
 31  
 
 32  
 import javax.el.ELException;
 33  
 import javax.faces.FacesException;
 34  
 import javax.faces.FactoryFinder;
 35  
 import javax.faces.application.ViewResource;
 36  
 import javax.faces.context.FacesContext;
 37  
 import javax.faces.view.facelets.Facelet;
 38  
 import javax.faces.view.facelets.FaceletCache;
 39  
 import javax.faces.view.facelets.FaceletCacheFactory;
 40  
 import javax.faces.view.facelets.FaceletContext;
 41  
 import javax.faces.view.facelets.FaceletException;
 42  
 import javax.faces.view.facelets.FaceletHandler;
 43  
 import javax.faces.view.facelets.ResourceResolver;
 44  
 
 45  
 import org.apache.myfaces.shared.resource.ResourceLoaderUtils;
 46  
 import org.apache.myfaces.view.facelets.AbstractFaceletCache;
 47  
 import org.apache.myfaces.view.facelets.FaceletFactory;
 48  
 import org.apache.myfaces.view.facelets.compiler.Compiler;
 49  
 import org.apache.myfaces.view.facelets.util.ParameterCheck;
 50  
 
 51  
 /**
 52  
  * Default FaceletFactory implementation.
 53  
  * 
 54  
  * @author Jacob Hookom
 55  
  * @version $Id$
 56  
  */
 57  0
 public final class DefaultFaceletFactory extends FaceletFactory
 58  
 {
 59  
     private static final long INFINITE_DELAY = -1;
 60  
     private static final long NO_CACHE_DELAY = 0;
 61  
     
 62  
     //protected final Log log = LogFactory.getLog(DefaultFaceletFactory.class);
 63  0
     protected final Logger log = Logger.getLogger(DefaultFaceletFactory.class.getName());
 64  
 
 65  
     private URL _baseUrl;
 66  
 
 67  
     private Compiler _compiler;
 68  
     
 69  
     //private Map<String, DefaultFacelet> _facelets;
 70  
     
 71  
     //private Map<String, DefaultFacelet> _viewMetadataFacelets;
 72  
     
 73  
     private Map<String, DefaultFacelet> _compositeComponentMetadataFacelets;
 74  
 
 75  
     private long _refreshPeriod;
 76  
 
 77  
     private Map<String, URL> _relativeLocations;
 78  
 
 79  
     private javax.faces.view.facelets.ResourceResolver _resolver;
 80  
     private DefaultResourceResolver _defaultResolver;
 81  
     
 82  
     private FaceletCache<Facelet> _faceletCache;
 83  
     private AbstractFaceletCache<Facelet> _abstractFaceletCache;
 84  
     
 85  
     public DefaultFaceletFactory(Compiler compiler, ResourceResolver resolver) throws IOException
 86  
     {
 87  0
         this(compiler, resolver, -1);
 88  0
     }
 89  
 
 90  
     public DefaultFaceletFactory(Compiler compiler, ResourceResolver resolver, long refreshPeriod)
 91  0
     {
 92  0
         ParameterCheck.notNull("compiler", compiler);
 93  0
         ParameterCheck.notNull("resolver", resolver);
 94  
 
 95  0
         _compiler = compiler;
 96  
 
 97  
         //_facelets = new HashMap<String, DefaultFacelet>();
 98  
         
 99  
         //_viewMetadataFacelets = new HashMap<String, DefaultFacelet>();
 100  
         
 101  0
         _compositeComponentMetadataFacelets = new HashMap<String, DefaultFacelet>();
 102  
 
 103  0
         _relativeLocations = new HashMap<String, URL>();
 104  
 
 105  0
         _resolver = resolver;
 106  0
         if (_resolver instanceof DefaultResourceResolver)
 107  
         {
 108  0
             _defaultResolver = (DefaultResourceResolver) _resolver;
 109  
         }
 110  
 
 111  
         //_baseUrl = resolver.resolveUrl("/");
 112  
 
 113  0
         _refreshPeriod = refreshPeriod < 0 ? INFINITE_DELAY : refreshPeriod * 1000;
 114  
         
 115  
         // facelet cache. Lookup here, because after all this is a "part" of the facelet factory implementation.
 116  0
         FaceletCacheFactory cacheFactory
 117  
                 = (FaceletCacheFactory) FactoryFinder.getFactory(FactoryFinder.FACELET_CACHE_FACTORY);
 118  0
         _faceletCache = (FaceletCache<Facelet>) cacheFactory.getFaceletCache();
 119  
         
 120  0
         FaceletCache.MemberFactory<Facelet> faceletFactory = new FaceletCache.MemberFactory<Facelet>()
 121  0
         {
 122  
             public Facelet newInstance(URL url) throws IOException
 123  
             {
 124  0
                 return _createFacelet(url);
 125  
             }
 126  
         };
 127  0
         FaceletCache.MemberFactory<Facelet> viewMetadataFaceletFactory = new FaceletCache.MemberFactory<Facelet>()
 128  0
         {
 129  
             public Facelet newInstance(URL url) throws IOException
 130  
             {
 131  0
                 return _createViewMetadataFacelet(url);
 132  
             }
 133  
         };
 134  
         
 135  0
         if (_faceletCache instanceof AbstractFaceletCache)
 136  
         {
 137  0
             _abstractFaceletCache = (AbstractFaceletCache<Facelet>) _faceletCache;
 138  
             
 139  0
             FaceletCache.MemberFactory<Facelet> compositeComponentMetadataFaceletFactory = 
 140  
                 new FaceletCache.MemberFactory<Facelet>()
 141  0
             {
 142  
                 public Facelet newInstance(URL url) throws IOException
 143  
                 {
 144  0
                     return _createCompositeComponentMetadataFacelet(url);
 145  
                 }
 146  
             };
 147  
 
 148  
             try
 149  
             {
 150  0
                 Method setMemberFactoriesMethod = AbstractFaceletCache.class.getDeclaredMethod("setMemberFactories",
 151  
                         new Class[]{FaceletCache.MemberFactory.class, FaceletCache.MemberFactory.class, 
 152  
                                     FaceletCache.MemberFactory.class});
 153  0
                 setMemberFactoriesMethod.setAccessible(true);
 154  0
                 setMemberFactoriesMethod.invoke(_faceletCache, faceletFactory, viewMetadataFaceletFactory, 
 155  
                     compositeComponentMetadataFaceletFactory);
 156  
             } 
 157  0
             catch (Exception e)
 158  
             {
 159  0
                 throw new FacesException(
 160  
                     "Cannot call setMemberFactories method, Initialization of FaceletCache failed.",
 161  
                                          e);
 162  0
             }   
 163  0
         }
 164  
         else
 165  
         {
 166  
             // Note that FaceletCache.setMemberFactories method is protected, and this is the place where call
 167  
             // this method has sense, because DefaultFaceletFactory is the responsible to create Facelet instances.
 168  
             // The only way to do it is using reflection, and it has sense, because in this way it is possible to
 169  
             // setup a java SecurityManager that prevents call this method (because it is protected, and to do that
 170  
             // the code first check for "suppressAccessChecks" permission).
 171  
             try
 172  
             {
 173  0
                 Method setMemberFactoriesMethod = FaceletCache.class.getDeclaredMethod("setMemberFactories",
 174  
                         new Class[]{FaceletCache.MemberFactory.class, FaceletCache.MemberFactory.class});
 175  0
                 setMemberFactoriesMethod.setAccessible(true);
 176  0
                 setMemberFactoriesMethod.invoke(_faceletCache, faceletFactory, viewMetadataFaceletFactory);
 177  
             } 
 178  0
             catch (Exception e)
 179  
             {
 180  0
                 throw new FacesException(
 181  
                     "Cannot call setMemberFactories method, Initialization of FaceletCache failed.",
 182  
                                          e);
 183  0
             }            
 184  
         }
 185  
 
 186  0
         if (log.isLoggable(Level.FINE))
 187  
         {
 188  0
             log.fine("Using ResourceResolver: " + _resolver);
 189  0
             log.fine("Using Refresh Period: " + _refreshPeriod);
 190  
         }
 191  0
     }
 192  
 
 193  
     /**
 194  
      * Compiler this factory uses
 195  
      * 
 196  
      * @return final Compiler instance
 197  
      */
 198  
     public Compiler getCompiler()
 199  
     {
 200  0
         return _compiler;
 201  
     }
 202  
     
 203  
     private URL getBaseUrl()
 204  
     {
 205  0
         if (_baseUrl == null)
 206  
         {
 207  0
             _baseUrl = _resolver.resolveUrl("/");
 208  
         }
 209  0
         return _baseUrl;
 210  
     }
 211  
 
 212  
     /*
 213  
      * (non-Javadoc)
 214  
      * 
 215  
      * @see org.apache.myfaces.view.facelets.FaceletFactory#getFacelet(java.lang.String)
 216  
      */
 217  
     @Override
 218  
     public Facelet getFacelet(FacesContext facesContext, String uri) 
 219  
         throws IOException, FaceletException, FacesException, ELException
 220  
     {
 221  0
         URL url = (URL) _relativeLocations.get(uri);
 222  0
         if (url == null)
 223  
         {
 224  0
             url = resolveURL(facesContext, getBaseUrl(), uri);
 225  0
             if (url != null)
 226  
             {
 227  0
                 ViewResource viewResource = (ViewResource) facesContext.getAttributes().get(
 228  
                     FaceletFactory.LAST_RESOURCE_RESOLVED);
 229  0
                 if (viewResource != null)
 230  
                 {
 231  
                     // If a view resource has been used to resolve a resource, the cache is in
 232  
                     // the ResourceHandler implementation. No need to cache in _relativeLocations.
 233  
                 }
 234  
                 else
 235  
                 {
 236  0
                     Map<String, URL> newLoc = new HashMap<String, URL>(_relativeLocations);
 237  0
                     newLoc.put(uri, url);
 238  0
                     _relativeLocations = newLoc;
 239  
                 }
 240  0
             }
 241  
             else
 242  
             {
 243  0
                 throw new IOException("'" + uri + "' not found.");
 244  
             }
 245  
         }
 246  0
         return this.getFacelet(url);
 247  
     }
 248  
 
 249  
     /**
 250  
      * Create a Facelet from the passed URL. This method checks if the cached Facelet needs to be refreshed before
 251  
      * returning. If so, uses the passed URL to build a new instance;
 252  
      * 
 253  
      * @param url
 254  
      *            source url
 255  
      * @return Facelet instance
 256  
      * @throws IOException
 257  
      * @throws FaceletException
 258  
      * @throws FacesException
 259  
      * @throws ELException
 260  
      */
 261  
     @Override
 262  
     public Facelet getFacelet(URL url) throws IOException, FaceletException, FacesException, ELException
 263  
     {
 264  0
         return _faceletCache.getFacelet(url);
 265  
     }
 266  
     
 267  
     
 268  
     @Override
 269  
     public Facelet getFacelet(FaceletContext ctx, URL url) 
 270  
             throws IOException, FaceletException, FacesException, ELException
 271  
     {
 272  0
         if (_abstractFaceletCache != null)
 273  
         {
 274  0
             return _abstractFaceletCache.getFacelet(ctx, url);
 275  
         }
 276  
         else
 277  
         {
 278  0
             return _faceletCache.getFacelet(url);
 279  
         }
 280  
     }
 281  
 
 282  
     public long getRefreshPeriod()
 283  
     {
 284  0
         return _refreshPeriod;
 285  
     }
 286  
 
 287  
     /**
 288  
      * Resolves a path based on the passed URL. If the path starts with '/', then resolve the path against
 289  
      * {@link javax.faces.context.ExternalContext#getResource(java.lang.String)
 290  
      * javax.faces.context.ExternalContext#getResource(java.lang.String)}. Otherwise create a new URL via
 291  
      * {@link URL#URL(java.net.URL, java.lang.String) URL(URL, String)}.
 292  
      * 
 293  
      * @param source
 294  
      *            base to resolve from
 295  
      * @param path
 296  
      *            relative path to the source
 297  
      * @return resolved URL
 298  
      * @throws IOException
 299  
      */
 300  
     public URL resolveURL(FacesContext context, URL source, String path) throws IOException
 301  
     {
 302  0
         if (path.startsWith("/"))
 303  
         {
 304  0
             context.getAttributes().put(LAST_RESOURCE_RESOLVED, null);
 305  0
             URL url = resolveURL(context, path);
 306  0
             if (url == null)
 307  
             {
 308  0
                 throw new FileNotFoundException(path + " Not Found in ExternalContext as a Resource");
 309  
             }
 310  0
             return url;
 311  
         }
 312  
         else
 313  
         {
 314  0
             return new URL(source, path);
 315  
         }
 316  
     }
 317  
 
 318  
     /**
 319  
      * Template method for determining if the Facelet needs to be refreshed.
 320  
      * 
 321  
      * @param facelet
 322  
      *            Facelet that could have expired
 323  
      * @return true if it needs to be refreshed
 324  
      */
 325  
     protected boolean needsToBeRefreshed(DefaultFacelet facelet)
 326  
     {
 327  
         // if set to 0, constantly reload-- nocache
 328  0
         if (_refreshPeriod == NO_CACHE_DELAY)
 329  
         {
 330  0
             return true;
 331  
         }
 332  
 
 333  
         // if set to -1, never reload
 334  0
         if (_refreshPeriod == INFINITE_DELAY)
 335  
         {
 336  0
             return false;
 337  
         }
 338  
 
 339  0
         long target = facelet.getCreateTime() + _refreshPeriod;
 340  0
         if (System.currentTimeMillis() > target)
 341  
         {
 342  
             // Should check for file modification
 343  
 
 344  0
             URLConnection conn = null;
 345  
             try
 346  
             {
 347  0
                 conn = facelet.getSource().openConnection();
 348  0
                 long lastModified = ResourceLoaderUtils.getResourceLastModified(conn);
 349  
 
 350  0
                 return lastModified == 0 || lastModified > target;
 351  
             }
 352  0
             catch (IOException e)
 353  
             {
 354  0
                 throw new FaceletException("Error Checking Last Modified for " + facelet.getAlias(), e);
 355  
             }
 356  
             finally
 357  
             {
 358  0
                 if (conn != null)
 359  
                 {
 360  
                     try
 361  
                     {
 362  0
                         conn.getInputStream().close();
 363  
                     }
 364  0
                     catch (Exception e)
 365  
                     {
 366  
                         // Ignored
 367  0
                     }
 368  
                 }
 369  
             }
 370  
         }
 371  
 
 372  0
         return false;
 373  
     }
 374  
 
 375  
     /**
 376  
      * Uses the internal Compiler reference to build a Facelet given the passed URL.
 377  
      * 
 378  
      * @param url
 379  
      *            source
 380  
      * @return a Facelet instance
 381  
      * @throws IOException
 382  
      * @throws FaceletException
 383  
      * @throws FacesException
 384  
      * @throws ELException
 385  
      */
 386  
     private DefaultFacelet _createFacelet(URL url) throws IOException, FaceletException, FacesException, ELException
 387  
     {
 388  0
         if (log.isLoggable(Level.FINE))
 389  
         {
 390  0
             log.fine("Creating Facelet for: " + url);
 391  
         }
 392  
 
 393  0
         String alias = "/" + _removeFirst(url.getFile(), getBaseUrl().getFile());
 394  
         try
 395  
         {
 396  0
             FaceletHandler h = _compiler.compile(url, alias);
 397  0
             DefaultFacelet f = new DefaultFacelet(this, _compiler.createExpressionFactory(), url, alias, alias, h);
 398  0
             return f;
 399  
         }
 400  0
         catch (FileNotFoundException fnfe)
 401  
         {
 402  0
             throw new FileNotFoundException("Facelet " + alias + " not found at: " + url.toExternalForm());
 403  
         }
 404  
     }
 405  
     
 406  
     /**
 407  
      * @since 2.0
 408  
      * @param url
 409  
      * @return
 410  
      * @throws IOException
 411  
      * @throws FaceletException
 412  
      * @throws FacesException
 413  
      * @throws ELException
 414  
      */
 415  
     private DefaultFacelet _createViewMetadataFacelet(URL url)
 416  
             throws IOException, FaceletException, FacesException, ELException
 417  
     {
 418  0
         if (log.isLoggable(Level.FINE))
 419  
         {
 420  0
             log.fine("Creating Facelet used to create View Metadata for: " + url);
 421  
         }
 422  
 
 423  
         // The alias is used later for informative purposes, so we append 
 424  
         // some prefix to identify later where the errors comes from.
 425  0
         String faceletId = "/"+ _removeFirst(url.getFile(), getBaseUrl().getFile());
 426  0
         String alias = "/viewMetadata" + faceletId;
 427  
         try
 428  
         {
 429  0
             FaceletHandler h = _compiler.compileViewMetadata(url, alias);
 430  0
             DefaultFacelet f = new DefaultFacelet(this, _compiler.createExpressionFactory(), url, alias, 
 431  
                     faceletId, h);
 432  0
             return f;
 433  
         }
 434  0
         catch (FileNotFoundException fnfe)
 435  
         {
 436  0
             throw new FileNotFoundException("Facelet " + alias + " not found at: " + url.toExternalForm());
 437  
         }
 438  
 
 439  
     }
 440  
     
 441  
     /**
 442  
      * @since 2.0.1
 443  
      * @param url
 444  
      * @return
 445  
      * @throws IOException
 446  
      * @throws FaceletException
 447  
      * @throws FacesException
 448  
      * @throws ELException
 449  
      */
 450  
     private DefaultFacelet _createCompositeComponentMetadataFacelet(URL url)
 451  
             throws IOException, FaceletException, FacesException, ELException
 452  
     {
 453  0
         if (log.isLoggable(Level.FINE))
 454  
         {
 455  0
             log.fine("Creating Facelet used to create Composite Component Metadata for: " + url);
 456  
         }
 457  
 
 458  
         // The alias is used later for informative purposes, so we append 
 459  
         // some prefix to identify later where the errors comes from.
 460  0
         String alias = "/compositeComponentMetadata/" + _removeFirst(url.getFile(), getBaseUrl().getFile());
 461  
         try
 462  
         {
 463  0
             FaceletHandler h = _compiler.compileCompositeComponentMetadata(url, alias);
 464  0
             DefaultFacelet f = new DefaultFacelet(this, _compiler.createExpressionFactory(), url, alias,
 465  
                     alias, h, true);
 466  0
             return f;
 467  
         }
 468  0
         catch (FileNotFoundException fnfe)
 469  
         {
 470  0
             throw new FileNotFoundException("Facelet " + alias + " not found at: " + url.toExternalForm());
 471  
         }
 472  
     }
 473  
 
 474  
     /**
 475  
      * Works in the same way as getFacelet(String uri), but redirect
 476  
      * to getViewMetadataFacelet(URL url)
 477  
      * @since 2.0
 478  
      */
 479  
     @Override
 480  
     public Facelet getViewMetadataFacelet(FacesContext facesContext, String uri) 
 481  
         throws IOException
 482  
     {
 483  0
         URL url = (URL) _relativeLocations.get(uri);
 484  0
         if (url == null)
 485  
         {
 486  0
             url = resolveURL(facesContext, getBaseUrl(), uri);
 487  0
             ViewResource viewResource = (ViewResource) facesContext.getAttributes().get(
 488  
                 FaceletFactory.LAST_RESOURCE_RESOLVED);
 489  0
             if (url != null)
 490  
             {
 491  0
                 if (viewResource != null)
 492  
                 {
 493  
                     // If a view resource has been used to resolve a resource, the cache is in
 494  
                     // the ResourceHandler implementation. No need to cache in _relativeLocations.
 495  
                 }
 496  
                 else
 497  
                 {
 498  0
                     Map<String, URL> newLoc = new HashMap<String, URL>(_relativeLocations);
 499  0
                     newLoc.put(uri, url);
 500  0
                     _relativeLocations = newLoc;
 501  0
                 }
 502  
             }
 503  
             else
 504  
             {
 505  0
                 throw new IOException("'" + uri + "' not found.");
 506  
             }
 507  
         }
 508  0
         return this.getViewMetadataFacelet(url);
 509  
     }
 510  
 
 511  
     /**
 512  
      * @since 2.0
 513  
      */
 514  
     @Override
 515  
     public Facelet getViewMetadataFacelet(URL url) throws IOException,
 516  
             FaceletException, FacesException, ELException
 517  
     {
 518  0
         if (_abstractFaceletCache != null)
 519  
         {
 520  0
             return _abstractFaceletCache.getViewMetadataFacelet(url);
 521  
         }
 522  
         else
 523  
         {
 524  0
             return _faceletCache.getViewMetadataFacelet(url);
 525  
         }
 526  
     }
 527  
     
 528  
     /**
 529  
      * Works in the same way as getFacelet(String uri), but redirect
 530  
      * to getViewMetadataFacelet(URL url)
 531  
      * @since 2.0.1
 532  
      */
 533  
     @Override
 534  
     public Facelet getCompositeComponentMetadataFacelet(FacesContext facesContext, String uri)
 535  
         throws IOException
 536  
     {
 537  0
         URL url = (URL) _relativeLocations.get(uri);
 538  0
         if (url == null)
 539  
         {
 540  0
             url = resolveURL(facesContext, getBaseUrl(), uri);
 541  0
             ViewResource viewResource = (ViewResource) facesContext.getAttributes().get(
 542  
                 FaceletFactory.LAST_RESOURCE_RESOLVED);            
 543  0
             if (url != null)
 544  
             {
 545  0
                 if (viewResource != null)
 546  
                 {
 547  
                     // If a view resource has been used to resolve a resource, the cache is in
 548  
                     // the ResourceHandler implementation. No need to cache in _relativeLocations.
 549  
                 }
 550  
                 else
 551  
                 {
 552  0
                     Map<String, URL> newLoc = new HashMap<String, URL>(_relativeLocations);
 553  0
                     newLoc.put(uri, url);
 554  0
                     _relativeLocations = newLoc;
 555  0
                 }
 556  
             }
 557  
             else
 558  
             {
 559  0
                 throw new IOException("'" + uri + "' not found.");
 560  
             }
 561  
         }
 562  0
         return this.getCompositeComponentMetadataFacelet(url);
 563  
     }
 564  
 
 565  
     /**
 566  
      * @since 2.0.1
 567  
      */
 568  
     @Override
 569  
     public Facelet getCompositeComponentMetadataFacelet(URL url) throws IOException,
 570  
             FaceletException, FacesException, ELException
 571  
     {
 572  0
         if (_abstractFaceletCache != null)
 573  
         {
 574  0
             return _abstractFaceletCache.getCompositeComponentMetadataFacelet(url);
 575  
         }
 576  
         else
 577  
         {
 578  0
             ParameterCheck.notNull("url", url);
 579  
 
 580  0
             String key = url.toString();
 581  
 
 582  0
             DefaultFacelet f = _compositeComponentMetadataFacelets.get(key);
 583  
 
 584  0
             if (f == null || this.needsToBeRefreshed(f))
 585  
             {
 586  0
                 f = this._createCompositeComponentMetadataFacelet(url);
 587  0
                 if (_refreshPeriod != NO_CACHE_DELAY)
 588  
                 {
 589  0
                     Map<String, DefaultFacelet> newLoc
 590  
                             = new HashMap<String, DefaultFacelet>(_compositeComponentMetadataFacelets);
 591  0
                     newLoc.put(key, f);
 592  0
                     _compositeComponentMetadataFacelets = newLoc;
 593  
                 }
 594  
             }
 595  0
             return f;
 596  
         }
 597  
     }
 598  
     
 599  
     private URL resolveURL(FacesContext context, String path)
 600  
     {
 601  0
         if (_defaultResolver != null)
 602  
         {
 603  0
             return _defaultResolver.resolveUrl(context, path);
 604  
         }
 605  
         else
 606  
         {
 607  0
             return _resolver.resolveUrl(path);
 608  
         }
 609  
     }
 610  
 
 611  
     public Facelet compileComponentFacelet(String taglibURI, String tagName, Map<String,Object> attributes)
 612  
     {
 613  0
         FaceletHandler handler = _compiler.compileComponent(taglibURI, tagName, attributes);
 614  0
         String alias = "/component/oamf:"+tagName;
 615  0
         return new DefaultFacelet(this, _compiler.createExpressionFactory(), getBaseUrl(), alias, alias, handler);
 616  
     }
 617  
     
 618  
     /**
 619  
      * Removes the first appearance of toRemove in string.
 620  
      *
 621  
      * Works just like string.replaceFirst(toRemove, ""), except that toRemove
 622  
      * is not treated as a regex (which could cause problems with filenames).
 623  
      *
 624  
      * @param string
 625  
      * @param toRemove
 626  
      * @return
 627  
      */
 628  
     private String _removeFirst(String string, String toRemove)
 629  
     {
 630  
         // do exactly what String.replaceFirst(toRemove, "") internally does,
 631  
         // except treating the search as literal text and not as regex
 632  
 
 633  0
         return Pattern.compile(toRemove, Pattern.LITERAL).matcher(string).replaceFirst("");
 634  
     }
 635  
 
 636  
 }