001: /*
002: *
003: * Copyright 2007 Florin T.PATRASCU
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.jpublish.view.stringtemplate;
020:
021: import com.anthonyeden.lib.config.Configuration;
022: import com.anthonyeden.lib.config.ConfigurationException;
023: import com.anthonyeden.lib.util.ClassUtilities;
024: import org.antlr.stringtemplate.StringTemplate;
025: import org.antlr.stringtemplate.StringTemplateGroup;
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.jpublish.JPublishContext;
029: import org.jpublish.Repository;
030: import org.jpublish.SiteContext;
031: import org.jpublish.util.*;
032: import org.jpublish.view.ViewRenderException;
033: import org.jpublish.view.ViewRenderer;
034:
035: import java.io.*;
036: import java.util.HashMap;
037: import java.util.Iterator;
038: import java.util.List;
039: import java.util.Map;
040:
041: /**
042: * A simple StringTemplate viewer
043: *
044: * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
045: * @since $Revision$ (created: Aug 18, 2007 1:56:15 PM)
046: */
047: public class StringTemplateViewRenderer implements ViewRenderer {
048: public static final Log log = LogFactory
049: .getLog(StringTemplateViewRenderer.class);
050: public static final String EMPTY_STRING = "";
051:
052: private SiteContext siteContext;
053: private int refreshInterval = 0;
054: private Class lexer;
055: private boolean initialized;
056: private Map stGroups = new HashMap();
057: private static final String TEMPLATE_PROTOCOL_NAME = "template";
058: private static final String DEFAULT_TEMPLATE_LEXER = "org.antlr.stringtemplate.language.DefaultTemplateLexer";
059:
060: /**
061: * Set the SiteContext.
062: *
063: * @param siteContext The SiteContext
064: */
065: public void setSiteContext(SiteContext siteContext) {
066: this .siteContext = siteContext;
067: }
068:
069: /**
070: * Initialize the StringTemplate ViewRenderer.
071: *
072: * @throws Exception Any Exception
073: */
074: public void init() throws Exception {
075:
076: }
077:
078: /**
079: * Render the view.
080: *
081: * @param context The JPublishContext
082: * @param path The path to the template
083: * @param in The Reader to read view template from
084: * @param out The Writer to write the rendered view
085: * @throws java.io.IOException
086: * @throws org.jpublish.view.ViewRenderException
087: *
088: */
089: public void render(JPublishContext context, String path, Reader in,
090: Writer out) throws ViewRenderException, IOException {
091:
092: CharacterEncodingMap characterEncodingMap = siteContext
093: .getCharacterEncodingManager().getMap(path);
094: String encoding = characterEncodingMap.getPageEncoding();
095:
096: if (!initialized) {
097: preInit();
098: initialized = true;
099: }
100:
101: if (log.isDebugEnabled()) {
102: log.debug("render(" + path + ")");
103: log.debug("Character encoding: " + encoding);
104: }
105:
106: Map model = new HashMap();
107: Object[] keys = context.getKeys();
108: for (int i = 0; i < keys.length; i++) {
109: String key = (String) keys[i];
110: model.put(key, context.get(key));
111: }
112:
113: String stgName = TEMPLATE_PROTOCOL_NAME;
114: String stPath = EMPTY_STRING;
115:
116: try {
117: InternalURI uri = InternalURIParser.getInstance().parse(
118: path);
119: String protocol = uri.getProtocol();
120:
121: if (protocol.equalsIgnoreCase(TEMPLATE_PROTOCOL_NAME)) {
122: // nothing for now
123: } else if (protocol.equalsIgnoreCase("repository")) {
124: stgName = ((RepositoryURI) uri).getRepositoryName();
125: } else {
126: throw new Exception("Protocol " + protocol
127: + " not supported");
128: }
129:
130: stPath = uri.getPath();
131: int delim = stPath.indexOf(".");
132: if (delim >= 0) {
133: stPath = stPath.substring(0, delim);
134: }
135: } catch (Exception e) {
136: e.printStackTrace();
137: }
138:
139: StringTemplateGroup stg = (StringTemplateGroup) stGroups
140: .get(stgName);
141: StringTemplate st = stg.getInstanceOf(stPath, model);
142: FileCopyUtils.copy(st.toString(), out);
143: }
144:
145: /**
146: * Render the view.
147: *
148: * @param context The JPublishContext
149: * @param path The path to the template
150: * @param in The InputStream to read view template from
151: * @param out The OutputStream to write the rendered view
152: * @throws java.io.IOException
153: * @throws org.jpublish.view.ViewRenderException
154: *
155: */
156: public void render(JPublishContext context, String path,
157: InputStream in, OutputStream out) throws IOException,
158: ViewRenderException {
159: render(context, path, new InputStreamReader(in),
160: new OutputStreamWriter(out));
161: }
162:
163: /**
164: * Load the configuration for the Stringtemplate Viewer.
165: *
166: * @param configuration The configuration object
167: */
168: public void loadConfiguration(Configuration configuration)
169: throws ConfigurationException {
170:
171: String lexerClassName = EMPTY_STRING;
172: refreshInterval = Integer.parseInt(configuration.getChildValue(
173: "refresh-interval", "0"));
174:
175: if (configuration.getChild("lexer") == null) {
176: lexerClassName = DEFAULT_TEMPLATE_LEXER;
177: } else {
178: lexerClassName = configuration.getChild("lexer")
179: .getAttribute("class", DEFAULT_TEMPLATE_LEXER);
180: }
181:
182: try {
183: lexer = ClassUtilities.loadClass(lexerClassName);
184: } catch (ClassNotFoundException e) {
185: throw new ConfigurationException(
186: "Stringtemplate Lexer class not found: "
187: + lexerClassName);
188: }
189: }
190:
191: public boolean isCacheEnabled() {
192: return refreshInterval > 0;
193: }
194:
195: /**
196: * this method will create one StringTemplateGroup for every JPublish repository and it will also
197: * create one for the JPublish template repository.
198: */
199: public void preInit() {
200: stGroups.put(TEMPLATE_PROTOCOL_NAME, new StringTemplateGroup(
201: TEMPLATE_PROTOCOL_NAME, siteContext
202: .getRealTemplateRoot().getAbsolutePath()));
203:
204: List repositories = siteContext.getRepositories();
205: log.info("StringTemplate initialization begins ...");
206: for (int i = 0; i < repositories.size(); i++) {
207: Repository repository = (Repository) repositories.get(i);
208: StringTemplateGroup stg = null;
209: try {
210: stg = new StringTemplateGroup(repository.getName(),
211: repository.pathToFile(EMPTY_STRING)
212: .getAbsolutePath(), lexer);
213: stg.setRefreshInterval(refreshInterval);
214: } catch (Exception e) {
215: e.printStackTrace();
216: }
217: stGroups.put(stg.getName(), stg);
218: }
219:
220: log.info("Available template groups:");
221: Iterator it = stGroups.values().iterator();
222: while (it.hasNext()) {
223: StringTemplateGroup stg = (StringTemplateGroup) it.next();
224: log.info("- group: '" + stg.getName() + "', location: "
225: + stg.getRootDir());
226: }
227:
228: log.info(" Lexer used: " + lexer);
229: log.info(" templates cache refresh interval: "
230: + refreshInterval);
231: log.info("StringTemplate Viewer is now available.");
232:
233: }
234: }
|