/* * 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.forms.binding.library; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.component.Component; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; 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.Serviceable; import org.apache.avalon.framework.thread.ThreadSafe; import org.apache.excalibur.source.Source; import org.apache.excalibur.source.SourceResolver; import org.apache.cocoon.forms.CacheManager; import org.apache.cocoon.forms.binding.JXPathBindingManager; import org.apache.cocoon.forms.util.DomHelper; import org.apache.cocoon.util.location.LocationImpl; import org.w3c.dom.Document; import org.xml.sax.InputSource; /** * @version $Id$ */ public class LibraryManagerImpl extends AbstractLogEnabled implements LibraryManager, Serviceable, Configurable, Disposable, ThreadSafe, Component { protected static final String PREFIX = "CocoonFormBindingLibrary:"; private ServiceManager manager; private CacheManager cacheManager; private JXPathBindingManager bindingManager; public void configure(Configuration configuration) throws ConfigurationException { // TODO Read config to "preload" libraries } public void service(ServiceManager serviceManager) throws ServiceException { this.manager = serviceManager; this.cacheManager = (CacheManager)serviceManager.lookup(CacheManager.ROLE); } public void setBindingManager(JXPathBindingManager bindingManager) { this.bindingManager = bindingManager; } public Library get(String sourceURI) throws LibraryException { return get(sourceURI, null); } public Library get(String sourceURI, String baseURI) throws LibraryException { SourceResolver sourceResolver = null; Source source = null; try { try { sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); source = sourceResolver.resolveURI(sourceURI, baseURI, null); } catch (Exception e) { throw new LibraryException("Unable to resolve library.", e, new LocationImpl("[LibraryManager]", sourceURI)); } Library lib = (Library) this.cacheManager.get(source, PREFIX); if (lib != null && lib.dependenciesHaveChanged()) { if (getLogger().isDebugEnabled()) { getLogger().debug("Library IS REMOVED from cache: '" + sourceURI + "' relative to '" + baseURI + "'"); } this.cacheManager.remove(source, PREFIX); // evict? return null; } if (getLogger().isDebugEnabled()) { if (lib != null) { getLogger().debug("Library IS in cache: '" + sourceURI + "' relative to '" + baseURI + "'"); } else { getLogger().debug("Library IS NOT in cache: '" + sourceURI + "' relative to '" + baseURI + "'"); } } return lib; } finally { if (source != null) { sourceResolver.release(source); } if (sourceResolver != null) { manager.release(sourceResolver); } } } public Library load(String sourceURI) throws LibraryException { return load(sourceURI, null); } public Library load(String sourceURI, String baseURI) throws LibraryException { SourceResolver sourceResolver = null; Source source = null; if (getLogger().isDebugEnabled()) { getLogger().debug("Loading library: '" + sourceURI + "' relative to '" + baseURI + "'"); } try { try { sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); source = sourceResolver.resolveURI(sourceURI, baseURI, null); } catch (Exception e) { throw new LibraryException("Unable to resolve library.", e, new LocationImpl("[LibraryManager]", sourceURI)); } Library lib = (Library) this.cacheManager.get(source, PREFIX); if (lib != null && lib.dependenciesHaveChanged()) { if (getLogger().isDebugEnabled()) { getLogger().debug("Library IS EXPIRED in cache: '" + sourceURI + "' relative to '" + baseURI + "'"); } lib = null; } if (lib == null) { if (getLogger().isDebugEnabled()) { getLogger().debug("Library IS NOT in cache, loading: '" + sourceURI + "' relative to '" + baseURI + "'"); } try { InputSource inputSource = new InputSource(source.getInputStream()); inputSource.setSystemId(source.getURI()); Document doc = DomHelper.parse(inputSource, this.manager); lib = newLibrary(); lib.buildLibrary(doc.getDocumentElement()); this.cacheManager.set(lib,source,PREFIX); } catch (Exception e) { throw new LibraryException("Unable to load library.", e, new LocationImpl("[LibraryManager]", source.getURI())); } } return lib; } finally { if (source != null) { sourceResolver.release(source); } if (sourceResolver != null) { manager.release(sourceResolver); } } } public Library newLibrary() { Library lib = new Library(this, bindingManager.getBuilderAssistant()); lib.enableLogging(getLogger()); if (getLogger().isDebugEnabled()) { getLogger().debug("Created new library! " + lib); } return lib; } public void dispose() { this.manager.release(this.cacheManager); this.cacheManager = null; this.manager = null; } public void debug(String msg) { if(getLogger().isDebugEnabled()) { getLogger().debug(msg); } } }