blob: c4fd110213fdaa49e3fcf7b26632a5cc817c7891 [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed 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.woody.binding;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
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.cocoon.woody.CacheManager;
import org.apache.cocoon.woody.datatype.DatatypeManager;
import org.apache.cocoon.woody.util.DomHelper;
import org.apache.cocoon.woody.util.SimpleServiceSelector;
import org.apache.excalibur.source.Source;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
/**
* JXPathBindingManager provides an implementation of {@link BindingManager}by
* usage of the <a href="http://jakarta.apache.org/commons/jxpath/index.html">
* JXPath package </a>.
*
* @version CVS $Id: JXPathBindingManager.java,v 1.22 2004/03/05 13:02:27 bdelacretaz Exp $
*/
public class JXPathBindingManager extends AbstractLogEnabled implements
BindingManager, Serviceable, Disposable, Initializable, Configurable,
ThreadSafe {
private static final String PREFIX = "WoodyBinding:";
private ServiceManager serviceManager;
private DatatypeManager datatypeManager;
private Configuration configuration;
private SimpleServiceSelector bindingBuilderSelector;
private CacheManager cacheManager;
public void service(ServiceManager serviceManager) throws ServiceException {
this.serviceManager = serviceManager;
this.datatypeManager = (DatatypeManager) serviceManager
.lookup(DatatypeManager.ROLE);
this.cacheManager = (CacheManager) serviceManager
.lookup(CacheManager.ROLE);
}
public void configure(Configuration configuration)
throws ConfigurationException {
this.configuration = configuration;
}
public void initialize() throws Exception {
bindingBuilderSelector = new SimpleServiceSelector("binding",
JXPathBindingBuilderBase.class);
bindingBuilderSelector.enableLogging(getLogger());
bindingBuilderSelector.configure(configuration.getChild("bindings"));
}
public Binding createBinding(Source source) throws BindingException {
Binding binding = (Binding) this.cacheManager.get(source, PREFIX);
if (binding == null) {
try {
InputSource is = new InputSource(source.getInputStream());
is.setSystemId(source.getURI());
Document doc = DomHelper.parse(is);
Element rootElm = doc.getDocumentElement();
if (BindingManager.NAMESPACE.equals(rootElm.getNamespaceURI())) {
binding = getBuilderAssistant()
.getBindingForConfigurationElement(rootElm);
((JXPathBindingBase) binding).enableLogging(getLogger());
if (getLogger().isDebugEnabled()) {
getLogger().debug(
"Creation of new Binding finished. " + binding);
}
} else {
if (getLogger().isDebugEnabled()) {
getLogger()
.debug(
"Root Element of said binding file is in wrong namespace.");
}
}
this.cacheManager.set(binding, source, PREFIX);
} catch (BindingException e) {
throw e;
} catch (Exception e) {
throw new BindingException("Error creating binding from "
+ source.getURI(), e);
}
}
return binding;
}
private Assistant getBuilderAssistant() {
return new Assistant();
}
public void dispose() {
this.bindingBuilderSelector.dispose();
this.bindingBuilderSelector = null;
this.serviceManager.release(this.datatypeManager);
this.datatypeManager = null;
this.cacheManager = null;
}
/**
* Assistant Inner class discloses enough features to the created
* childBindings to recursively
*
* This patterns was chosen to prevent Inversion Of Control between this
* factory and its builder classes (that could be provided by third
* parties.)
*/
/*
* NOTE: To get access to the logger in this inner class you must not call
* getLogger() as with JDK 1.3 this gives a NoSuchMethod error. You need to
* implement an explicit access method for the logger in the outer class.
*/
public class Assistant {
private JXPathBindingBuilderBase getBindingBuilder(String bindingType)
throws BindingException {
try {
return (JXPathBindingBuilderBase) bindingBuilderSelector
.select(bindingType);
} catch (ServiceException e) {
throw new BindingException(
"Cannot handle binding element with " + "name \""
+ bindingType + "\".", e);
}
}
/**
* Creates a {@link Binding}following the specification in the
* provided config element.
*/
public JXPathBindingBase getBindingForConfigurationElement(
Element configElm) throws BindingException {
String bindingType = configElm.getLocalName();
JXPathBindingBuilderBase bindingBuilder = getBindingBuilder(bindingType);
JXPathBindingBase childBinding = bindingBuilder.buildBinding(
configElm, this);
return childBinding;
}
/**
* Makes an array of childBindings for the child-elements of the
* provided configuration element.
*/
public JXPathBindingBase[] makeChildBindings(Element parentElement)
throws BindingException {
if (parentElement != null) {
Element[] childElements = DomHelper.getChildElements(
parentElement, BindingManager.NAMESPACE);
if (childElements.length > 0) {
JXPathBindingBase[] childBindings = new JXPathBindingBase[childElements.length];
for (int i = 0; i < childElements.length; i++) {
childBindings[i] = getBindingForConfigurationElement(childElements[i]);
}
return childBindings;
}
}
return null;
}
public DatatypeManager getDatatypeManager() {
return datatypeManager;
}
public ServiceManager getServiceManager() {
return serviceManager;
}
}
}