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.ByteArrayInputStream;
023: import java.io.InputStream;
024: import java.io.UnsupportedEncodingException;
025:
026: import org.apache.commons.collections.ExtendedProperties;
027: import org.apache.commons.lang.StringUtils;
028: import org.apache.velocity.exception.ResourceNotFoundException;
029: import org.apache.velocity.exception.VelocityException;
030: import org.apache.velocity.runtime.log.Log;
031: import org.apache.velocity.runtime.resource.Resource;
032: import org.apache.velocity.runtime.resource.util.StringResource;
033: import org.apache.velocity.runtime.resource.util.StringResourceRepository;
034: import org.apache.velocity.runtime.resource.util.StringResourceRepositoryImpl;
035: import org.apache.velocity.util.ClassUtils;
036:
037: /**
038: * Resource loader that works with Strings. Users should manually add
039: * resources to the repository that is know by the factory of this package.
040: *
041: * Below is an example configuration for this loader.
042: * Note that 'repositoryimpl' is not mandatory;
043: * if not provided, the factory will fall back on using the default
044: * implementation of this package.
045: *
046: * string.resource.loader.description = Velocity StringResource loader
047: * string.resource.loader.class = org.apache.velocity.runtime.resource.loader..StringResourceLoader
048: * string.resource.loader.repository.class = org.apache.velocity.runtime.resource.loader.StringResourceRepositoryImpl
049: *
050: * Resources can be added to the repository like this:
051: * <code>
052: * StringResourceRepository = StringResourceLoader.getRepository();
053: *
054: * String myTemplateName = "/somewhere/intherepo/name";
055: * String myTemplateBody = "Hi, ${username}... this is a some template!";
056: * vsRepository.putStringResource(myTemplateName, myTemplateBody);
057: * </code>
058: *
059: * After this, the templates can be retrieved as usual.
060: *
061: * @author <a href="mailto:eelco.hillenius@openedge.nl">Eelco Hillenius</a>
062: * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
063: * @version $Id: StringResourceLoader.java 479058 2006-11-25 00:26:32Z henning $
064: */
065: public class StringResourceLoader extends ResourceLoader {
066: /** Key to look up the repository implementation class. */
067: public static final String REPOSITORY_CLASS = "repository.class";
068:
069: /** The default implementation class. */
070: public static final String REPOSITORY_CLASS_DEFAULT = StringResourceRepositoryImpl.class
071: .getName();
072:
073: /** Key to look up the repository char encoding. */
074: public static final String REPOSITORY_ENCODING = "repository.encoding";
075:
076: /** The default repository encoding. */
077: public static final String REPOSITORY_ENCODING_DEFAULT = "UTF-8";
078:
079: /**
080: * Returns a reference to the Repository.
081: *
082: * @return A StringResourceRepository Reference.
083: */
084: public static StringResourceRepository getRepository() {
085: return RepositoryFactory.getRepository();
086: }
087:
088: /**
089: * @see org.apache.velocity.runtime.resource.loader.ResourceLoader#init(org.apache.commons.collections.ExtendedProperties)
090: */
091: public void init(final ExtendedProperties configuration) {
092: log.info("StringResourceLoader : initialization starting.");
093:
094: String repositoryClass = configuration.getString(
095: REPOSITORY_CLASS, REPOSITORY_CLASS_DEFAULT);
096: String encoding = configuration.getString(REPOSITORY_ENCODING,
097: REPOSITORY_ENCODING_DEFAULT);
098:
099: RepositoryFactory.setRepositoryClass(repositoryClass);
100: RepositoryFactory.setEncoding(encoding);
101: RepositoryFactory.init(log);
102:
103: log.info("StringResourceLoader : initialization complete.");
104: }
105:
106: /**
107: * Get an InputStream so that the Runtime can build a
108: * template with it.
109: *
110: * @param name name of template to get.
111: * @return InputStream containing the template.
112: * @throws ResourceNotFoundException Ff template not found
113: * in the RepositoryFactory.
114: */
115: public InputStream getResourceStream(final String name)
116: throws ResourceNotFoundException {
117: if (StringUtils.isEmpty(name)) {
118: throw new ResourceNotFoundException(
119: "No template name provided");
120: }
121:
122: StringResource resource = getRepository().getStringResource(
123: name);
124:
125: if (resource == null) {
126: throw new ResourceNotFoundException(
127: "Could not locate resource '" + name + "'");
128: }
129:
130: byte[] byteArray = null;
131:
132: try {
133: byteArray = resource.getBody().getBytes(
134: resource.getEncoding());
135: return new ByteArrayInputStream(byteArray);
136: } catch (UnsupportedEncodingException ue) {
137: throw new VelocityException(
138: "Could not convert String using encoding "
139: + resource.getEncoding(), ue);
140: }
141: }
142:
143: /**
144: * @see org.apache.velocity.runtime.resource.loader.ResourceLoader#isSourceModified(org.apache.velocity.runtime.resource.Resource)
145: */
146: public boolean isSourceModified(final Resource resource) {
147: StringResource original = null;
148: boolean result = true;
149:
150: original = getRepository()
151: .getStringResource(resource.getName());
152:
153: if (original != null) {
154: result = original.getLastModified() != resource
155: .getLastModified();
156: }
157:
158: return result;
159: }
160:
161: /**
162: * @see org.apache.velocity.runtime.resource.loader.ResourceLoader#getLastModified(org.apache.velocity.runtime.resource.Resource)
163: */
164: public long getLastModified(final Resource resource) {
165: StringResource original = null;
166:
167: original = getRepository()
168: .getStringResource(resource.getName());
169:
170: return (original != null) ? original.getLastModified() : 0;
171: }
172:
173: /**
174: * Factory for constructing and obtaining the instance of
175: * StringResourceRepository implementation.
176: *
177: * Users can provide their own implementation by setting the property 'repository.class'
178: * for the resource loader. Note that at this time only one instance of a
179: * string resource repository can be used in a single VM.
180: *
181: * @author <a href="mailto:eelco.hillenius@openedge.nl">Eelco Hillenius</a>
182: * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
183: * @version $Id: StringResourceLoader.java 479058 2006-11-25 00:26:32Z henning $
184: */
185: private static final class RepositoryFactory {
186: /**
187: * is the factory initialised properly?
188: */
189: private static boolean isInitialized = false;
190:
191: /**
192: * repository instance
193: */
194: private static StringResourceRepository repository = null;
195:
196: /**
197: * Sets the repository class.
198: *
199: * @param className class that implements StringResourceRepository.
200: */
201: public static void setRepositoryClass(final String className) {
202: if (isInitialized) {
203: throw new IllegalStateException(
204: "The RepositoryFactory has already been initialized!");
205: }
206:
207: try {
208: repository = (StringResourceRepository) ClassUtils
209: .getNewInstance(className);
210: } catch (ClassNotFoundException cnfe) {
211: throw new VelocityException("Could not find '"
212: + className + "'", cnfe);
213: } catch (IllegalAccessException iae) {
214: throw new VelocityException("Could not access '"
215: + className + "'", iae);
216: } catch (InstantiationException ie) {
217: throw new VelocityException("Could not instantiante '"
218: + className + "'", ie);
219: }
220: }
221:
222: /**
223: * Sets the current repository encoding.
224: *
225: * @param encoding The current repository encoding.
226: */
227: public static void setEncoding(final String encoding) {
228: if (repository == null) {
229: throw new IllegalStateException(
230: "The Repository class has not yet been set!");
231: }
232:
233: repository.setEncoding(encoding);
234: }
235:
236: /**
237: * Init the factory with the user given class name.
238: *
239: * @throws VelocityException If something goes wrong.
240: */
241: public static synchronized void init(final Log log)
242: throws VelocityException {
243: if (isInitialized) {
244: throw new IllegalStateException(
245: "Attempted to re-initialize Factory!");
246: }
247:
248: if (log.isInfoEnabled()) {
249: log.info("Using " + repository.getClass().getName()
250: + " as repository implementation");
251: log.info("Current repository encoding is "
252: + repository.getEncoding());
253: }
254: isInitialized = true;
255: }
256:
257: /**
258: * Get a reference to the repository.
259: * @return A StringResourceRepository implementation object.
260: */
261: public static StringResourceRepository getRepository() {
262: if (!isInitialized) {
263: throw new IllegalStateException(
264: "RepositoryFactory was not properly set up");
265: }
266: return repository;
267: }
268: }
269: }
|