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 17package com.google.clearsilver.jsilver.resourceloader; 18 19import com.google.clearsilver.jsilver.exceptions.JSilverTemplateNotFoundException; 20 21import java.io.FilterReader; 22import java.io.IOException; 23import java.io.Reader; 24import java.util.ArrayList; 25import 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 */ 33public 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