/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.cocoon.template.script; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.ServiceSelector; import org.apache.avalon.framework.service.Serviceable; import org.apache.avalon.framework.thread.ThreadSafe; import org.apache.cocoon.ProcessingException; import org.apache.cocoon.components.source.SourceUtil; import org.apache.cocoon.template.environment.ParsingContext; import org.apache.cocoon.template.expression.StringTemplateParser; import org.apache.cocoon.template.script.event.StartDocument; import org.apache.excalibur.source.Source; import org.apache.excalibur.source.SourceException; import org.apache.excalibur.source.SourceResolver; import org.apache.excalibur.source.SourceValidity; import org.apache.excalibur.store.Store; import org.xml.sax.Locator; import org.xml.sax.SAXParseException; /** * @version $Id$ */ public class DefaultScriptManager extends AbstractLogEnabled implements Serviceable, Disposable, ScriptManager, ThreadSafe { private ServiceManager manager; private final static String JX_STORE_PREFIX = "jxtg:"; private Store store; private InstructionFactory instructionFactory; private ServiceSelector stringTemplateParserSelector; private StringTemplateParser stringTemplateParser; private String stringTemplateParserName = "jxtg"; public DefaultScriptManager() { } /** * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager) */ public void service(ServiceManager manager) throws ServiceException { this.manager = manager; this.store = (Store) this.manager.lookup(Store.TRANSIENT_STORE); this.instructionFactory = (InstructionFactory) this.manager.lookup(InstructionFactory.ROLE); this.stringTemplateParserSelector = (ServiceSelector) this.manager.lookup(StringTemplateParser.ROLE + "Selector"); this.stringTemplateParser = (StringTemplateParser) this.stringTemplateParserSelector .select(this.stringTemplateParserName); } /** * @see org.apache.avalon.framework.activity.Disposable#dispose() */ public void dispose() { if ( this.manager != null ) { this.manager.release(this.store); this.manager.release(this.instructionFactory); if ( this.stringTemplateParserSelector != null ) { this.stringTemplateParserSelector.release(this.stringTemplateParser); this.manager.release(this.stringTemplateParserSelector); this.stringTemplateParserSelector = null; this.stringTemplateParser = null; } this.store = null; this.instructionFactory = null; this.manager = null; } } private Store getStore() { return store; } public StartDocument resolveTemplate(String uri) throws SAXParseException, ProcessingException { return resolveTemplate(uri, null); } public StartDocument resolveTemplate(String uri, Locator location) throws SAXParseException, ProcessingException { Source input = null; StartDocument doc = null; SourceResolver resolver = null; try { resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE); input = resolver.resolveURI(uri); SourceValidity validity = null; String storeUri = JX_STORE_PREFIX + input.getURI(); doc = (StartDocument) getStore().get(storeUri); // TODO: why was this previously in synchronized( getCache() )? if (doc != null) { boolean recompile = false; if (doc.getSourceValidity() == null) { recompile = true; } else { int valid = doc.getSourceValidity().isValid(); if (valid == SourceValidity.UNKNOWN) { validity = input.getValidity(); valid = doc.getSourceValidity().isValid(validity); } if (valid != SourceValidity.VALID) { recompile = true; } } if (recompile) { doc = null; // recompile } } if (doc == null) { Parser parser = new Parser(new ParsingContext(this.stringTemplateParser, this.instructionFactory)); // call getValidity before using the stream is faster if // the source is a SitemapSource if (validity == null) { validity = input.getValidity(); } SourceUtil.parse(manager, input, parser); doc = parser.getStartEvent(); doc.setUri(input.getURI()); doc.setSourceValidity(validity); getStore().store(storeUri, doc); } } catch (SourceException se) { throw SourceUtil.handle("Error during resolving of '" + uri + "'.", se); } catch (Exception exc) { throw new SAXParseException(exc.getMessage(), location, exc); } finally { if (input != null) resolver.release(input); if (resolver != null) manager.release(resolver); } return doc; } }