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.script;
018:
019: import org.apache.avalon.framework.activity.Disposable;
020: import org.apache.avalon.framework.logger.AbstractLogEnabled;
021: import org.apache.avalon.framework.service.ServiceException;
022: import org.apache.avalon.framework.service.ServiceManager;
023: import org.apache.avalon.framework.service.ServiceSelector;
024: import org.apache.avalon.framework.service.Serviceable;
025: import org.apache.avalon.framework.thread.ThreadSafe;
026: import org.apache.cocoon.ProcessingException;
027: import org.apache.cocoon.components.source.SourceUtil;
028: import org.apache.cocoon.template.environment.ParsingContext;
029: import org.apache.cocoon.template.expression.StringTemplateParser;
030: import org.apache.cocoon.template.script.event.StartDocument;
031: import org.apache.excalibur.source.Source;
032: import org.apache.excalibur.source.SourceException;
033: import org.apache.excalibur.source.SourceResolver;
034: import org.apache.excalibur.source.SourceValidity;
035: import org.apache.excalibur.store.Store;
036: import org.xml.sax.Locator;
037: import org.xml.sax.SAXParseException;
038:
039: /**
040: * @version $Id: DefaultScriptManager.java 449189 2006-09-23 06:52:29Z crossley $
041: */
042: public class DefaultScriptManager extends AbstractLogEnabled implements
043: Serviceable, Disposable, ScriptManager, ThreadSafe {
044:
045: private ServiceManager manager;
046: private final static String JX_STORE_PREFIX = "jxtg:";
047: private Store store;
048: private InstructionFactory instructionFactory;
049: private ServiceSelector stringTemplateParserSelector;
050: private StringTemplateParser stringTemplateParser;
051: private String stringTemplateParserName = "jxtg";
052:
053: public DefaultScriptManager() {
054: }
055:
056: /**
057: * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
058: */
059: public void service(ServiceManager manager) throws ServiceException {
060: this .manager = manager;
061: this .store = (Store) this .manager.lookup(Store.TRANSIENT_STORE);
062: this .instructionFactory = (InstructionFactory) this .manager
063: .lookup(InstructionFactory.ROLE);
064: this .stringTemplateParserSelector = (ServiceSelector) this .manager
065: .lookup(StringTemplateParser.ROLE + "Selector");
066: this .stringTemplateParser = (StringTemplateParser) this .stringTemplateParserSelector
067: .select(this .stringTemplateParserName);
068: }
069:
070: /**
071: * @see org.apache.avalon.framework.activity.Disposable#dispose()
072: */
073: public void dispose() {
074: if (this .manager != null) {
075: this .manager.release(this .store);
076: this .manager.release(this .instructionFactory);
077: if (this .stringTemplateParserSelector != null) {
078: this .stringTemplateParserSelector
079: .release(this .stringTemplateParser);
080: this .manager.release(this .stringTemplateParserSelector);
081: this .stringTemplateParserSelector = null;
082: this .stringTemplateParser = null;
083: }
084: this .store = null;
085: this .instructionFactory = null;
086: this .manager = null;
087: }
088: }
089:
090: private Store getStore() {
091: return store;
092: }
093:
094: public StartDocument resolveTemplate(String uri)
095: throws SAXParseException, ProcessingException {
096: return resolveTemplate(uri, null);
097: }
098:
099: public StartDocument resolveTemplate(String uri, Locator location)
100: throws SAXParseException, ProcessingException {
101: Source input = null;
102: StartDocument doc = null;
103: SourceResolver resolver = null;
104: try {
105: resolver = (SourceResolver) this .manager
106: .lookup(SourceResolver.ROLE);
107: input = resolver.resolveURI(uri);
108: SourceValidity validity = null;
109:
110: String storeUri = JX_STORE_PREFIX + input.getURI();
111: doc = (StartDocument) getStore().get(storeUri);
112:
113: // TODO: why was this previously in synchronized( getCache() )?
114: if (doc != null) {
115: boolean recompile = false;
116: if (doc.getSourceValidity() == null) {
117: recompile = true;
118: } else {
119: int valid = doc.getSourceValidity().isValid();
120: if (valid == SourceValidity.UNKNOWN) {
121: validity = input.getValidity();
122: valid = doc.getSourceValidity().isValid(
123: validity);
124: }
125: if (valid != SourceValidity.VALID) {
126: recompile = true;
127: }
128: }
129: if (recompile) {
130: doc = null; // recompile
131: }
132: }
133:
134: if (doc == null) {
135: Parser parser = new Parser(new ParsingContext(
136: this .stringTemplateParser,
137: this .instructionFactory));
138: // call getValidity before using the stream is faster if
139: // the source is a SitemapSource
140: if (validity == null) {
141: validity = input.getValidity();
142: }
143: SourceUtil.parse(manager, input, parser);
144: doc = parser.getStartEvent();
145: doc.setUri(input.getURI());
146: doc.setSourceValidity(validity);
147:
148: getStore().store(storeUri, doc);
149: }
150: } catch (SourceException se) {
151: throw SourceUtil.handle("Error during resolving of '" + uri
152: + "'.", se);
153: } catch (Exception exc) {
154: throw new SAXParseException(exc.getMessage(), location, exc);
155: } finally {
156: if (input != null)
157: resolver.release(input);
158: if (resolver != null)
159: manager.release(resolver);
160: }
161: return doc;
162: }
163: }
|