001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. 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: package org.apache.cocoon.template;
018:
019: import java.io.IOException;
020: import java.io.Serializable;
021: import java.util.HashMap;
022: import java.util.Map;
023:
024: import org.apache.avalon.framework.parameters.Parameters;
025: import org.apache.avalon.framework.service.ServiceException;
026: import org.apache.avalon.framework.service.ServiceManager;
027: import org.apache.cocoon.ProcessingException;
028: import org.apache.cocoon.caching.CacheableProcessingComponent;
029: import org.apache.cocoon.components.expression.ExpressionContext;
030: import org.apache.cocoon.environment.SourceResolver;
031: import org.apache.cocoon.generation.ServiceableGenerator;
032: import org.apache.cocoon.template.environment.ExecutionContext;
033: import org.apache.cocoon.template.environment.FlowObjectModelHelper;
034: import org.apache.cocoon.template.environment.JXCacheKey;
035: import org.apache.cocoon.template.environment.JXSourceValidity;
036: import org.apache.cocoon.template.expression.JXTExpression;
037: import org.apache.cocoon.template.script.Invoker;
038: import org.apache.cocoon.template.script.ScriptManager;
039: import org.apache.cocoon.template.script.event.Event;
040: import org.apache.cocoon.template.script.event.StartDocument;
041: import org.apache.cocoon.template.xml.AttributeAwareXMLConsumerImpl;
042: import org.apache.cocoon.xml.RedundantNamespacesFilter;
043: import org.apache.cocoon.xml.XMLConsumer;
044: import org.apache.excalibur.source.SourceValidity;
045: import org.xml.sax.SAXException;
046:
047: /**
048: * @cocoon.sitemap.component.documentation Provides a generic page template with
049: * embedded JSTL and XPath expression
050: * substitution to access data sent by
051: * Cocoon Flowscripts.
052: *
053: * @cocoon.sitemap.component.name jx
054: * @cocoon.sitemap.component.label content
055: * @cocoon.sitemap.component.logger sitemap.generator.jx
056: *
057: * @cocoon.sitemap.component.pooling.max 16
058: *
059: *
060: * @version $Id: JXTemplateGenerator.java 449189 2006-09-23 06:52:29Z crossley $
061: */
062: public class JXTemplateGenerator extends ServiceableGenerator implements
063: CacheableProcessingComponent {
064:
065: /** The namespace used by this generator */
066: public final static String NS = "http://apache.org/cocoon/templates/jx/1.0";
067:
068: public final static String CACHE_KEY = "cache-key";
069: public final static String VALIDITY = "cache-validity";
070:
071: private ExpressionContext expressionContext;
072: private ScriptManager scriptManager;
073:
074: private StartDocument startDocument;
075: private Map definitions;
076:
077: public XMLConsumer getConsumer() {
078: return this .xmlConsumer;
079: }
080:
081: /**
082: * @see org.apache.cocoon.generation.ServiceableGenerator#service(org.apache.avalon.framework.service.ServiceManager)
083: */
084: public void service(ServiceManager manager) throws ServiceException {
085: super .service(manager);
086: this .scriptManager = (ScriptManager) this .manager
087: .lookup(ScriptManager.ROLE);
088: }
089:
090: /**
091: * @see org.apache.cocoon.generation.ServiceableGenerator#dispose()
092: */
093: public void dispose() {
094: if (this .manager != null) {
095: this .manager.release(this .scriptManager);
096: this .scriptManager = null;
097: }
098: super .dispose();
099: }
100:
101: /**
102: * @see org.apache.cocoon.generation.AbstractGenerator#recycle()
103: */
104: public void recycle() {
105: this .startDocument = null;
106: this .expressionContext = null;
107: this .definitions = null;
108: super .recycle();
109: }
110:
111: /**
112: * @see org.apache.cocoon.generation.AbstractGenerator#setup(org.apache.cocoon.environment.SourceResolver, java.util.Map, java.lang.String, org.apache.avalon.framework.parameters.Parameters)
113: */
114: public void setup(SourceResolver resolver, Map objectModel,
115: String src, Parameters parameters)
116: throws ProcessingException, SAXException, IOException {
117:
118: super .setup(resolver, objectModel, src, parameters);
119: // src can be null if this generator is triggered by the jxt transformer (through the TransformerAdapter)
120: if (src != null) {
121: this .startDocument = scriptManager.resolveTemplate(src);
122: }
123:
124: this .expressionContext = FlowObjectModelHelper
125: .getFOMExpressionContext(objectModel, parameters);
126: this .definitions = new HashMap();
127: }
128:
129: /**
130: * @see org.apache.cocoon.generation.Generator#generate()
131: */
132: public void generate() throws IOException, SAXException,
133: ProcessingException {
134: performGeneration(this .startDocument, null);
135:
136: // no need to reference compiled script anymore
137: this .startDocument = null;
138: }
139:
140: public void performGeneration(Event startEvent, Event endEvent)
141: throws SAXException {
142: XMLConsumer consumer = new AttributeAwareXMLConsumerImpl(
143: new RedundantNamespacesFilter(this .xmlConsumer));
144: ((Map) expressionContext.get("cocoon")).put("consumer",
145: consumer);
146: Invoker.execute(consumer, this .expressionContext,
147: new ExecutionContext(this .definitions,
148: this .scriptManager, this .manager), null,
149: startEvent, null);
150: }
151:
152: /**
153: * @see org.apache.cocoon.caching.CacheableProcessingComponent#getKey()
154: */
155: public Serializable getKey() {
156: JXTExpression cacheKeyExpr = (JXTExpression) this .startDocument
157: .getTemplateProperty(JXTemplateGenerator.CACHE_KEY);
158: if (cacheKeyExpr == null) {
159: return null;
160: }
161: try {
162: final Serializable templateKey = (Serializable) cacheKeyExpr
163: .getValue(this .expressionContext);
164: if (templateKey != null) {
165: return new JXCacheKey(this .startDocument.getUri(),
166: templateKey);
167: }
168: } catch (Exception e) {
169: getLogger().error("error evaluating cache key", e);
170: }
171: return null;
172: }
173:
174: /**
175: * @see org.apache.cocoon.caching.CacheableProcessingComponent#getValidity()
176: */
177: public SourceValidity getValidity() {
178: JXTExpression validityExpr = (JXTExpression) this .startDocument
179: .getTemplateProperty(JXTemplateGenerator.VALIDITY);
180: if (validityExpr == null) {
181: return null;
182: }
183: try {
184: final SourceValidity sourceValidity = this .startDocument
185: .getSourceValidity();
186: final SourceValidity templateValidity = (SourceValidity) validityExpr
187: .getValue(this .expressionContext);
188: if (sourceValidity != null && templateValidity != null) {
189: return new JXSourceValidity(sourceValidity,
190: templateValidity);
191: }
192: } catch (Exception e) {
193: getLogger().error("error evaluating cache validity", e);
194: }
195: return null;
196: }
197: }
|