001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.scripting.support;
018:
019: import java.io.File;
020: import java.io.FileNotFoundException;
021: import java.io.FileReader;
022: import java.io.IOException;
023: import java.io.InputStreamReader;
024: import java.io.Reader;
025:
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028:
029: import org.springframework.core.io.Resource;
030: import org.springframework.scripting.ScriptSource;
031: import org.springframework.util.Assert;
032: import org.springframework.util.FileCopyUtils;
033:
034: /**
035: * {@link org.springframework.scripting.ScriptSource} implementation
036: * based on Spring's {@link org.springframework.core.io.Resource}
037: * abstraction. Loads the script text from the underlying Resource's
038: * {@link org.springframework.core.io.Resource#getFile() File} or
039: * {@link org.springframework.core.io.Resource#getInputStream() InputStream},
040: * and tracks the last-modified timestamp of the file (if possible).
041: *
042: * @author Rob Harrop
043: * @author Juergen Hoeller
044: * @since 2.0
045: * @see org.springframework.core.io.Resource#getInputStream()
046: * @see org.springframework.core.io.Resource#getFile()
047: * @see org.springframework.core.io.ResourceLoader
048: */
049: public class ResourceScriptSource implements ScriptSource {
050:
051: /** Logger available to subclasses */
052: protected final Log logger = LogFactory.getLog(getClass());
053:
054: private final Resource resource;
055:
056: private long lastModified = -1;
057:
058: private final Object lastModifiedMonitor = new Object();
059:
060: /**
061: * Create a new ResourceScriptSource for the given resource.
062: * @param resource the Resource to load the script from
063: */
064: public ResourceScriptSource(Resource resource) {
065: Assert.notNull(resource, "Resource must not be null");
066: this .resource = resource;
067: }
068:
069: /**
070: * Return the {@link org.springframework.core.io.Resource} to load the
071: * script from.
072: */
073: public final Resource getResource() {
074: return this .resource;
075: }
076:
077: public String getScriptAsString() throws IOException {
078: File file = null;
079: try {
080: file = getResource().getFile();
081: } catch (IOException ex) {
082: if (logger.isDebugEnabled()) {
083: logger
084: .debug(
085: getResource()
086: + " could not be resolved in the file system - "
087: + "cannot store last-modified timestamp for obtained script",
088: ex);
089: }
090: }
091: synchronized (this .lastModifiedMonitor) {
092: this .lastModified = (file != null ? file.lastModified() : 0);
093: }
094: Reader reader = null;
095: if (file != null) {
096: try {
097: // Try to get a FileReader first: generally more reliable.
098: reader = new FileReader(file);
099: } catch (FileNotFoundException ex) {
100: if (logger.isDebugEnabled()) {
101: logger.debug("Could not open FileReader for "
102: + this .resource
103: + " - falling back to InputStreamReader",
104: ex);
105: }
106: }
107: }
108: if (reader == null) {
109: reader = new InputStreamReader(this .resource
110: .getInputStream());
111: }
112: return FileCopyUtils.copyToString(reader);
113: }
114:
115: public boolean isModified() {
116: synchronized (this .lastModifiedMonitor) {
117: return (this .lastModified < 0 || retrieveLastModifiedTime() > this .lastModified);
118: }
119: }
120:
121: /**
122: * Retrieve the current last-modified timestamp of the underlying resource.
123: * @return the current timestamp, or 0 if not determinable
124: */
125: protected long retrieveLastModifiedTime() {
126: try {
127: return getResource().getFile().lastModified();
128: } catch (IOException ex) {
129: if (logger.isDebugEnabled()) {
130: logger
131: .debug(
132: getResource()
133: + " could not be resolved in the file system - "
134: + "current timestamp not available for script modification check",
135: ex);
136: }
137: return 0;
138: }
139: }
140:
141: public String toString() {
142: return this.resource.toString();
143: }
144:
145: }
|