CompositeResourceLoader.java revision 56ed4167b942ec265f9cee70ac4d71d10b3835ce
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2010 Google Inc.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * you may not use this file except in compliance with the License.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * You may obtain a copy of the License at
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://www.apache.org/licenses/LICENSE-2.0
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Unless required by applicable law or agreed to in writing, software
11a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch * distributed under the License is distributed on an "AS IS" BASIS,
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See the License for the specific language governing permissions and
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * limitations under the License.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochpackage com.google.clearsilver.jsilver.resourceloader;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import com.google.clearsilver.jsilver.exceptions.JSilverTemplateNotFoundException;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.io.FilterReader;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.io.IOException;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.io.Reader;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.ArrayList;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.util.List;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ResourceLoader composed of other ResourceLoaders. When a resource is loaded, it will search
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * through each ResourceLoader until it finds something.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see ResourceLoader
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public class CompositeResourceLoader implements ResourceLoader {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private final List<ResourceLoader> loaders = new ArrayList<ResourceLoader>();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public CompositeResourceLoader(Iterable<ResourceLoader> loaders) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ResourceLoader loader : loaders) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      add(loader);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public CompositeResourceLoader(ResourceLoader... loaders) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ResourceLoader loader : loaders) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      add(loader);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public void add(ResourceLoader loader) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loaders.add(loader);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public Reader open(String name) throws IOException {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ResourceLoader loader : loaders) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Reader reader = loader.open(name);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (reader != null) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return new ReaderTracer(reader, loader);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return null;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  @Override
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public Reader openOrFail(String name) throws JSilverTemplateNotFoundException, IOException {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Reader reader = open(name);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (reader == null) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      throw new JSilverTemplateNotFoundException(name);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return reader;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public void close(Reader reader) throws IOException {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(reader instanceof ReaderTracer)) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      throw new IllegalArgumentException("I can't close a reader I didn't open.");
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reader.close();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /**
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   * We return the filename as the key of uniqueness as we assume that if this
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * CompositeResourceLoader is in use, then there won't be another ResourceLoader that we are
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * competing against. If we did need to worry about it we would want to prepend the key from
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * above.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @Override
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public Object getKey(String filename) {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return filename;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Return the first non-null version identifier found among the ResourceLoaders, using the same
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   * search order as {@link #open(String)}.
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   */
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  @Override
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public Object getResourceVersionId(String filename) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (ResourceLoader loader : loaders) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Object currentKey = loader.getResourceVersionId(filename);
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (currentKey != null) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return currentKey;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return null;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Wraps a reader, associating it with the original ResourceLoader - this is necessary so when
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * close() is called, we delegate back to original ResourceLoader.
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   */
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  private static class ReaderTracer extends FilterReader {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private final ResourceLoader originalLoader;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public ReaderTracer(Reader in, ResourceLoader originalLoader) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      super(in);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this.originalLoader = originalLoader;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void close() throws IOException {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      originalLoader.close(in);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)