001: package org.apache.velocity.runtime.resource.loader;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.io.InputStream;
023: import java.io.IOException;
024: import java.net.URL;
025: import java.net.URLConnection;
026: import java.util.HashMap;
027: import org.apache.commons.collections.ExtendedProperties;
028: import org.apache.commons.lang.StringUtils;
029: import org.apache.velocity.exception.ResourceNotFoundException;
030: import org.apache.velocity.runtime.resource.Resource;
031:
032: /**
033: * This is a simple URL-based loader.
034: *
035: * @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
036: * @author <a href="mailto:nbubna@apache.org">Nathan Bubna</a>
037: * @version $Id: URLResourceLoader.java 191743 2005-06-21 23:22:20Z dlr $
038: */
039: public class URLResourceLoader extends ResourceLoader {
040: private String[] roots = null;
041: protected HashMap templateRoots = null;
042:
043: /**
044: * @see org.apache.velocity.runtime.resource.loader.ResourceLoader#init(org.apache.commons.collections.ExtendedProperties)
045: */
046: public void init(ExtendedProperties configuration) {
047: log.trace("URLResourceLoader : initialization starting.");
048:
049: roots = configuration.getStringArray("root");
050:
051: if (log.isInfoEnabled()) {
052: for (int i = 0; i < roots.length; i++) {
053: log.info("URLResourceLoader : adding root '" + roots[i]
054: + "'");
055: }
056: }
057:
058: // init the template paths map
059: templateRoots = new HashMap();
060:
061: log.trace("URLResourceLoader : initialization complete.");
062: }
063:
064: /**
065: * Get an InputStream so that the Runtime can build a
066: * template with it.
067: *
068: * @param name name of template to fetch bytestream of
069: * @return InputStream containing the template
070: * @throws ResourceNotFoundException if template not found
071: * in the file template path.
072: */
073: public synchronized InputStream getResourceStream(String name)
074: throws ResourceNotFoundException {
075: if (StringUtils.isEmpty(name)) {
076: throw new ResourceNotFoundException(
077: "URLResourceLoader : No template name provided");
078: }
079:
080: InputStream inputStream = null;
081: Exception exception = null;
082: for (int i = 0; i < roots.length; i++) {
083: try {
084: URL u = new URL(roots[i] + name);
085: inputStream = u.openStream();
086:
087: if (inputStream != null) {
088: if (log.isDebugEnabled())
089: log.debug("URLResourceLoader: Found '" + name
090: + "' at '" + roots[i] + "'");
091:
092: // save this root for later re-use
093: templateRoots.put(name, roots[i]);
094: break;
095: }
096: } catch (IOException ioe) {
097: if (log.isDebugEnabled())
098: log.debug(
099: "URLResourceLoader: Exception when looking for '"
100: + name + "' at '" + roots[i] + "'",
101: ioe);
102:
103: // only save the first one for later throwing
104: if (exception == null) {
105: exception = ioe;
106: }
107: }
108: }
109:
110: // if we never found the template
111: if (inputStream == null) {
112: String msg;
113: if (exception == null) {
114: msg = "URLResourceLoader : Resource '" + name
115: + "' not found.";
116: } else {
117: msg = exception.getMessage();
118: }
119: // convert to a general Velocity ResourceNotFoundException
120: throw new ResourceNotFoundException(msg);
121: }
122:
123: return inputStream;
124: }
125:
126: /**
127: * Checks to see if a resource has been deleted, moved or modified.
128: *
129: * @param resource Resource The resource to check for modification
130: * @return boolean True if the resource has been modified, moved, or unreachable
131: */
132: public boolean isSourceModified(Resource resource) {
133: long fileLastModified = getLastModified(resource);
134: // if the file is unreachable or otherwise changed
135: if (fileLastModified == 0
136: || fileLastModified != resource.getLastModified()) {
137: return true;
138: }
139: return false;
140: }
141:
142: /**
143: * Checks to see when a resource was last modified
144: *
145: * @param resource Resource the resource to check
146: * @return long The time when the resource was last modified or 0 if the file can't be reached
147: */
148: public long getLastModified(Resource resource) {
149: // get the previously used root
150: String name = resource.getName();
151: String root = (String) templateRoots.get(name);
152:
153: try {
154: // get a connection to the URL
155: URL u = new URL(root + name);
156: URLConnection conn = u.openConnection();
157: return conn.getLastModified();
158: } catch (IOException ioe) {
159: // the file is not reachable at its previous address
160: log
161: .warn("URLResourceLoader: '" + name
162: + "' is no longer reachable at '" + root
163: + "'", ioe);
164: return 0;
165: }
166: }
167:
168: }
|