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.generation;
018:
019: import org.apache.avalon.framework.component.Recomposable;
020: import org.apache.avalon.framework.component.ComponentManager;
021: import org.apache.avalon.framework.component.ComponentException;
022:
023: import org.apache.cocoon.caching.CacheValidity;
024: import org.apache.cocoon.caching.Cacheable;
025: import org.apache.cocoon.caching.CacheableProcessingComponent;
026: import org.apache.cocoon.components.language.generator.CompiledComponent;
027: import org.apache.cocoon.environment.Request;
028:
029: import org.apache.excalibur.source.SourceValidity;
030: import org.apache.excalibur.source.impl.validity.NOPValidity;
031:
032: import org.xml.sax.SAXException;
033: import org.xml.sax.helpers.AttributesImpl;
034:
035: import java.io.File;
036: import java.io.Serializable;
037:
038: /**
039: * Base implementation of <code>ServerPagesGenerator</code>. This class
040: * declares variables that must be explicitly initialized by code generators.
041: *
042: * @author <a href="mailto:ricardo@apache.org">Ricardo Rocha</a>
043: * @version CVS $Id: AbstractServerPage.java 433543 2006-08-22 06:22:54Z crossley $
044: */
045: public abstract class AbstractServerPage extends ServletGenerator
046: implements CompiledComponent, CacheableProcessingComponent,
047: Cacheable, Recomposable {
048: /**
049: * Code generators should produce a constructor
050: * block that initializes the generator's
051: * creation date and file dependency list.
052: * Example:
053: *
054: * {
055: * this.dateCreated = 958058788948L;
056: * this.dependencies = new File[] {
057: * new File("source.xml"),
058: * };
059: * }
060: *
061: */
062:
063: /** The creation date */
064: protected long dateCreated = -1L;
065: /** The dependency file list */
066: protected File[] dependencies = null;
067:
068: /**
069: * Recompose with the actual <code>ComponentManager</code> that should
070: * be used.
071: */
072: public void recompose(ComponentManager manager)
073: throws ComponentException {
074: this .manager = manager;
075: }
076:
077: /**
078: * Determines whether this generator's source files have changed
079: *
080: * @return Whether any of the files this generator depends on has changed
081: * since it was created
082: */
083: public boolean modifiedSince(long date) {
084: if (date == 0 || dateCreated < date) {
085: return true;
086: }
087:
088: for (int i = 0; i < dependencies.length; i++) {
089: if (dateCreated < dependencies[i].lastModified()) {
090: return true;
091: }
092: }
093:
094: return false;
095: }
096:
097: /**
098: * Determines whether generated content has changed since
099: * last invocation. Users may override this method to take
100: * advantage of SAX event cacheing
101: *
102: * @param request The request whose data must be inspected to assert whether
103: * dynamically generated content has changed
104: * @return Whether content has changes for this request's data
105: */
106: public boolean hasContentChanged(Request request) {
107: return true;
108: }
109:
110: /**
111: * Generate the unique key.
112: * This key must be unique inside the space of this component.
113: * This method must be invoked before the generateValidity() method.
114: *
115: * @return The generated key or <code>null</code> if the component
116: * is currently not cacheable.
117: */
118: public Serializable getKey() {
119: return null;
120: }
121:
122: /**
123: * Generate the validity object.
124: * Before this method can be invoked the generateKey() method
125: * must be invoked.
126: *
127: * @return The generated validity object, <code>NOPCacheValidity</code>
128: * is the default if hasContentChange() gives false otherwise
129: * <code>null</code> will be returned.
130: */
131: public SourceValidity getValidity() {
132: if (hasContentChanged(request))
133: return null;
134: else
135: return NOPValidity.SHARED_INSTANCE;
136: }
137:
138: // FIXME: Add more methods!
139: /* SAX Utility Methods */
140: /**
141: * Add an attribute
142: *
143: * @param attr The attribute list to add to
144: * @param name The attribute name
145: * @param value The attribute value
146: */
147: protected void attribute(AttributesImpl attr, String name,
148: String value) {
149: attr.addAttribute("", name, name, "CDATA", value);
150: }
151:
152: /**
153: * Start an element
154: *
155: * @param name The element name
156: * @param attr The element attributes
157: */
158: protected void start(String name, AttributesImpl attr)
159: throws SAXException {
160: this .contentHandler.startElement("", name, name, attr);
161: attr.clear();
162: }
163:
164: /**
165: * End an element
166: *
167: * @param name The element name
168: */
169: protected void end(String name) throws SAXException {
170: this .contentHandler.endElement("", name, name);
171: }
172:
173: /**
174: * Add character data
175: *
176: * @param data The character data
177: */
178: protected void characters(String data) throws SAXException {
179: this .contentHandler.characters(data.toCharArray(), 0, data
180: .length());
181: }
182:
183: /**
184: * Add a comment
185: *
186: * @param data The comment data
187: */
188: protected void comment(String data) throws SAXException {
189: this .lexicalHandler.comment(data.toCharArray(), 0, data
190: .length());
191: }
192:
193: /**
194: * Generates the unique key.
195: * This key must be unique inside the space of this component.
196: * Users may override this method to take
197: * advantage of SAX event cacheing
198: *
199: * @return A long representing the cache key (defaults to not cachable)
200: */
201: public long generateKey() {
202: return 0;
203: }
204:
205: /**
206: * Generate the validity object.
207: *
208: * @return The generated validity object, <code>NOPCacheValidity</code>
209: * is the default if hasContentChange() gives false otherwise
210: * <code>null</code> will be returned.
211: */
212: public CacheValidity generateValidity() {
213: if (hasContentChanged(request))
214: return null;
215: else
216: return NOPCacheValidity.CACHE_VALIDITY;
217: }
218:
219: }
220:
221: /**
222: * This is here to avaid references to the deprecated package.
223: * It is required to support the deprecated caching algorithm
224: */
225: final class NOPCacheValidity implements CacheValidity {
226:
227: public static final CacheValidity CACHE_VALIDITY = new NOPCacheValidity();
228:
229: public boolean isValid(CacheValidity validity) {
230: return validity instanceof NOPCacheValidity;
231: }
232:
233: public String toString() {
234: return "NOP Validity";
235: }
236: }
|