Home | History | Annotate | Download | only in resourceloader
      1 /*
      2  * Copyright (C) 2010 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.clearsilver.jsilver.resourceloader;
     18 
     19 import com.google.clearsilver.jsilver.exceptions.JSilverTemplateNotFoundException;
     20 
     21 import java.io.FilterReader;
     22 import java.io.IOException;
     23 import java.io.Reader;
     24 import java.util.ArrayList;
     25 import java.util.List;
     26 
     27 /**
     28  * ResourceLoader composed of other ResourceLoaders. When a resource is loaded, it will search
     29  * through each ResourceLoader until it finds something.
     30  *
     31  * @see ResourceLoader
     32  */
     33 public class CompositeResourceLoader implements ResourceLoader {
     34 
     35   private final List<ResourceLoader> loaders = new ArrayList<ResourceLoader>();
     36 
     37   public CompositeResourceLoader(Iterable<ResourceLoader> loaders) {
     38     for (ResourceLoader loader : loaders) {
     39       add(loader);
     40     }
     41   }
     42 
     43   public CompositeResourceLoader(ResourceLoader... loaders) {
     44     for (ResourceLoader loader : loaders) {
     45       add(loader);
     46     }
     47   }
     48 
     49   public void add(ResourceLoader loader) {
     50     loaders.add(loader);
     51   }
     52 
     53   public Reader open(String name) throws IOException {
     54     for (ResourceLoader loader : loaders) {
     55       Reader reader = loader.open(name);
     56       if (reader != null) {
     57         return new ReaderTracer(reader, loader);
     58       }
     59     }
     60     return null;
     61   }
     62 
     63   @Override
     64   public Reader openOrFail(String name) throws JSilverTemplateNotFoundException, IOException {
     65     Reader reader = open(name);
     66     if (reader == null) {
     67       throw new JSilverTemplateNotFoundException(name);
     68     } else {
     69       return reader;
     70     }
     71   }
     72 
     73   public void close(Reader reader) throws IOException {
     74     if (!(reader instanceof ReaderTracer)) {
     75       throw new IllegalArgumentException("I can't close a reader I didn't open.");
     76     }
     77     reader.close();
     78   }
     79 
     80   /**
     81    * We return the filename as the key of uniqueness as we assume that if this
     82    * CompositeResourceLoader is in use, then there won't be another ResourceLoader that we are
     83    * competing against. If we did need to worry about it we would want to prepend the key from
     84    * above.
     85    */
     86   @Override
     87   public Object getKey(String filename) {
     88     return filename;
     89   }
     90 
     91   /**
     92    * Return the first non-null version identifier found among the ResourceLoaders, using the same
     93    * search order as {@link #open(String)}.
     94    */
     95   @Override
     96   public Object getResourceVersionId(String filename) {
     97     for (ResourceLoader loader : loaders) {
     98       Object currentKey = loader.getResourceVersionId(filename);
     99       if (currentKey != null) {
    100         return currentKey;
    101       }
    102     }
    103     return null;
    104   }
    105 
    106   /**
    107    * Wraps a reader, associating it with the original ResourceLoader - this is necessary so when
    108    * close() is called, we delegate back to original ResourceLoader.
    109    */
    110   private static class ReaderTracer extends FilterReader {
    111 
    112     private final ResourceLoader originalLoader;
    113 
    114     public ReaderTracer(Reader in, ResourceLoader originalLoader) {
    115       super(in);
    116       this.originalLoader = originalLoader;
    117     }
    118 
    119     public void close() throws IOException {
    120       originalLoader.close(in);
    121     }
    122   }
    123 
    124 }
    125