Coverage Report - no.sesat.search.view.velocity.URLResourceLoader
 
Classes in this File Line Coverage Branch Coverage Complexity
URLResourceLoader
0%
0/48
0%
0/8
2.333
URLResourceLoader$1
N/A
N/A
2.333
URLResourceLoader$Context
N/A
N/A
2.333
URLResourceLoader$DefaultContext
0%
0/5
N/A
2.333
 
 1  
 /* Copyright (2007-2008) Schibsted Søk AS
 2  
  * This file is part of SESAT.
 3  
  *
 4  
  *   SESAT is free software: you can redistribute it and/or modify
 5  
  *   it under the terms of the GNU Affero General Public License as published by
 6  
  *   the Free Software Foundation, either version 3 of the License, or
 7  
  *   (at your option) any later version.
 8  
  *
 9  
  *   SESAT is distributed in the hope that it will be useful,
 10  
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  
  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  
  *   GNU Affero General Public License for more details.
 13  
  *
 14  
  *   You should have received a copy of the GNU Affero General Public License
 15  
  *   along with SESAT.  If not, see <http://www.gnu.org/licenses/>.
 16  
  */
 17  
 package no.sesat.search.view.velocity;
 18  
 
 19  
 import java.io.IOException;
 20  
 import java.net.URL;
 21  
 import java.net.MalformedURLException;
 22  
 import java.io.InputStream;
 23  
 import java.util.regex.Matcher;
 24  
 import no.sesat.search.http.HTTPClient;
 25  
 import no.sesat.search.site.config.UrlResourceLoader;
 26  
 import no.sesat.search.site.Site;
 27  
 import org.apache.log4j.Logger;
 28  
 import org.apache.velocity.runtime.resource.Resource;
 29  
 import org.apache.velocity.runtime.resource.loader.ResourceLoader;
 30  
 import org.apache.velocity.exception.ResourceNotFoundException;
 31  
 import org.apache.commons.collections.ExtendedProperties;
 32  
 
 33  
 /**
 34  
  * This is a simple URL-based loader.
 35  
  * ORIGINAL FROM http://svn.apache.org/repos/asf/jakarta/velocity/engine/trunk/whiteboard/geir/URLResourceLoader.java
 36  
  *
 37  
  * original version Id: URLResourceLoader.java,v 1.3 2004/03/19 17:13:40 dlr Exp
 38  
  *
 39  
  *
 40  
  *
 41  
  * MODIFIED TO SUIT SCHIBSTEDSØK's NEEDS.
 42  
  * There was a choice here to implement all the URL handling stuff from scratch or to plug into the existing
 43  
  * functionality found in no.schibstedsøk.front.search.configuration.loader
 44  
  * Since this class is hidden between the velocity API it made more sense to go from scratch to best
 45  
  * meet velocity's requirements...
 46  
  *
 47  
  *
 48  
  * @version $Id: URLResourceLoader.java,v 1.3 2004/03/19 17:13:40 dlr Exp $
 49  
  */
 50  
 public class URLResourceLoader extends ResourceLoader {
 51  
 
 52  
     public interface Context{
 53  
         boolean doesUrlExist(final URL url);
 54  
         URL getURL(final String resource, final Site site);
 55  
     }
 56  
 
 57  
     // Constants -----------------------------------------------------
 58  
 
 59  0
     private static final Logger LOG = Logger.getLogger(URLResourceLoader.class);
 60  
 
 61  
     private static final String ERR_RESOURCE_NOT_FOUND = "Cannot find resource ";
 62  
     private static final String DEBUG_LOOKING_FOR = "Looking for ";
 63  
     private static final String DEBUG_EXISTS = "Positive HEAD on ";
 64  
     private static final String DEBUG_FULL_URL_IS = "Real URL is ";
 65  
     private static final String DEBUG_HOST_HEADER_IS = "URL's host-header is ";
 66  
     private static final String DEBUG_DOESNT_EXIST = "Using fallback URL";
 67  
 
 68  
 
 69  
     // Attributes ----------------------------------------------------
 70  
 
 71  
     private Site site;
 72  
 
 73  
 
 74  
     // Static --------------------------------------------------------
 75  
 
 76  0
     private static Context context = new DefaultContext();
 77  
 
 78  
     // Allows the tests to switch the Velocity ResourceLoader over to a file based one.
 79  
     static void setContext(final Context context){
 80  0
         URLResourceLoader.context = context;
 81  0
     }
 82  
 
 83  
     // Constructors --------------------------------------------------
 84  
 
 85  
 
 86  0
     public URLResourceLoader(){}
 87  
 
 88  0
     public URLResourceLoader(final Site site){
 89  0
         this.site= site;
 90  0
     }
 91  
 
 92  
     // Public --------------------------------------------------------
 93  
 
 94  
     /** {@inheritDoc}
 95  
      */
 96  
     public void init(final ExtendedProperties configuration) {
 97  
         // the engine's properties actually come from the RuntimeServices *not* the ExtendedProperties
 98  0
         site = (Site)rsvc.getProperty(Site.NAME_KEY);
 99  0
     }
 100  
 
 101  
     /**
 102  
      * Get an InputStream so that the Runtime can build a
 103  
      * template with it.
 104  
      *
 105  
      * @param url  url of template to fetch bytestream of
 106  
      * @return InputStream containing the template
 107  
      * @throws ResourceNotFoundException if template not found
 108  
      *         in the file template path.
 109  
      */
 110  
      public /*synchronized*/ InputStream getResourceStream(final String url) throws ResourceNotFoundException{
 111  
 
 112  0
         LOG.trace("start getResourceStream( " + url + " )");
 113  
         try{
 114  0
             synchronized( url.intern() ){
 115  0
                 return getStream(findUrl(url, site));
 116  0
             }
 117  
 
 118  0
         }catch( IOException e ){
 119  0
             throw new ResourceNotFoundException( ERR_RESOURCE_NOT_FOUND + url );
 120  
         }
 121  
     }
 122  
 
 123  
     /** {@inheritDoc}
 124  
      */
 125  
     public boolean isSourceModified(Resource resource){
 126  
 
 127  0
         final boolean result =  getLastModified(resource) > resource.getLastModified();
 128  0
         LOG.debug("isSourceModified( "+resource.getName()+" ): "+result);
 129  0
         return result;
 130  
     }
 131  
 
 132  
     /** {@inheritDoc}
 133  
      */
 134  
     public long getLastModified(Resource resource){
 135  
         try{
 136  0
             final URL url = findUrl(resource.getName(), site);
 137  0
             final HTTPClient client = HTTPClient.instance(url, "localhost");
 138  
 
 139  0
             return client.getLastModified("");
 140  0
         }catch( ResourceNotFoundException e ){
 141  0
             LOG.error( ERR_RESOURCE_NOT_FOUND + resource.getName() );
 142  0
         }catch( IOException e ){
 143  0
             LOG.error( ERR_RESOURCE_NOT_FOUND + resource.getName() );
 144  0
         }
 145  0
         return 0;
 146  
     }
 147  
 
 148  
 
 149  
     // Package protected ---------------------------------------------
 150  
 
 151  
     // Protected -----------------------------------------------------
 152  
 
 153  
     // Private -------------------------------------------------------
 154  
 
 155  
     private static URL findUrl(final String url, final Site currentSite) throws ResourceNotFoundException{
 156  
 
 157  
         try{
 158  0
             LOG.trace(DEBUG_LOOKING_FOR + url );
 159  0
             return findUrlImpl(url, currentSite);
 160  
 
 161  0
         }catch( IOException e ){
 162  0
             throw new ResourceNotFoundException( ERR_RESOURCE_NOT_FOUND + url );
 163  
         }
 164  
     }
 165  
 
 166  
     private static URL findUrlImpl(final String url, final Site currentSite)
 167  
             throws IOException, ResourceNotFoundException {
 168  
 
 169  0
         final URL u = context.getURL(url, currentSite);
 170  
 
 171  0
         if (context.doesUrlExist(u)) {
 172  0
             return u;
 173  
         } else {
 174  0
             final Site parent = currentSite.getParent();
 175  
 
 176  0
             if (null == parent) {
 177  0
                 throw new ResourceNotFoundException( ERR_RESOURCE_NOT_FOUND + url );
 178  
             }
 179  
 
 180  0
             if (LOG.isTraceEnabled()) {
 181  0
                 LOG.trace(DEBUG_DOESNT_EXIST + parent.getName());
 182  
             }
 183  
 
 184  
             // Recursively look for the resource in ancestor sites.
 185  0
             return findUrlImpl(getFallbackURL(url, currentSite, parent), parent);
 186  
         }
 187  
     }
 188  
 
 189  
     private static String getFallbackURL(final String url, final Site currSite, final Site ancestorSite) {
 190  
 
 191  0
         final String oldUrl = currSite.getName() + currSite.getConfigContext();
 192  0
         final String newUrl = ancestorSite.getName() + ancestorSite.getConfigContext();
 193  
 
 194  0
         return url.replaceFirst(Matcher.quoteReplacement(oldUrl), newUrl);
 195  
     }
 196  
 
 197  
 
 198  
     private static InputStream getStream(final URL url) throws IOException{
 199  
 
 200  0
         final HTTPClient client = HTTPClient.instance(url, "localhost");
 201  
         try{
 202  0
             return client.getBufferedStream("");
 203  0
         }catch(IOException ioe){
 204  0
             throw client.interceptIOException(ioe);
 205  
         }
 206  
     }
 207  
 
 208  
 
 209  
     // Inner classes -------------------------------------------------
 210  
 
 211  0
     private static final class DefaultContext implements Context{
 212  
         public boolean doesUrlExist(final URL url) {
 213  0
             return UrlResourceLoader.doesUrlExist(url);
 214  
         }
 215  
 
 216  
         public URL getURL(final String resource, final Site site) {
 217  
             try {
 218  0
                 return new URL(resource);
 219  0
             } catch (MalformedURLException e) {
 220  0
                 throw new ResourceNotFoundException(e);
 221  
             }
 222  
         }
 223  
     }
 224  
 }
 225