| /* |
| * 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.components.language.markup.xsp; |
| |
| |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.apache.avalon.framework.CascadingRuntimeException; |
| import org.apache.avalon.framework.component.ComponentManager; |
| import org.apache.avalon.framework.component.ComponentSelector; |
| import org.apache.avalon.framework.configuration.Configuration; |
| import org.apache.avalon.framework.service.ServiceManager; |
| import org.apache.avalon.framework.service.ServiceSelector; |
| |
| import org.apache.cocoon.components.modules.input.InputModule; |
| |
| import org.xml.sax.ContentHandler; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.AttributesImpl; |
| |
| /** |
| * Helper class that caches references to InputModules for use in |
| * XSPs. Works in conjunction with the input.xsl |
| * logicsheet. References are obtained the first time a module is |
| * accessed and kept until the page is completely displayed. |
| * |
| * @author <a href="mailto:haul@apache.org">Christian Haul</a> |
| * @version CVS $Id: XSPModuleHelper.java,v 1.8 2004/03/05 13:02:47 bdelacretaz Exp $ |
| */ |
| public class XSPModuleHelper { |
| |
| protected final static String INPUT_MODULE_SELECTOR = InputModule.ROLE+"Selector"; |
| |
| private static final String PREFIX = "input"; |
| private static final String URI = "http://apache.org/cocoon/xsp/input/1.0"; |
| |
| /* Operation codes */ |
| private final static int OP_GET = 0; |
| private final static int OP_VALUES = 1; |
| private final static int OP_NAMES = 2; |
| |
| private Map inputModules; |
| private ComponentManager componentManager; |
| private ComponentSelector componentInputSelector; |
| private ServiceManager serviceManager; |
| private ServiceSelector serviceInputSelector; |
| |
| |
| /** |
| * Get the input module |
| */ |
| private InputModule getInputModule(String name) |
| throws CascadingRuntimeException { |
| if ( this.inputModules == null ) { |
| throw new RuntimeException("ModuleHelper is not setup correctly."); |
| } |
| InputModule module = (InputModule) this.inputModules.get(name); |
| if ( module == null ) { |
| try { |
| if ( this.componentManager != null ) { |
| if (this.componentInputSelector.hasComponent(name)) { |
| module = (InputModule) this.componentInputSelector.select(name); |
| } |
| } else { |
| if (this.serviceInputSelector.isSelectable(name)) { |
| module = (InputModule) this.serviceInputSelector.select(name); |
| } |
| } |
| } catch (Exception e) { |
| throw new CascadingRuntimeException("Unable to lookup input module " + name, e); |
| } |
| if ( module == null ) { |
| throw new RuntimeException("No such InputModule: "+name); |
| } |
| this.inputModules.put(name, module); |
| } |
| return module; |
| } |
| |
| /** |
| * Capsules use of an InputModule. Does all the lookups and so |
| * on. Returns either an Object, an Object[], or an Iterator, |
| * depending on the method called i.e. the op specified. The |
| * second module is preferred and has an non null name. If an |
| * exception is encountered, a warn message is printed and null is |
| * returned. |
| * @param op an <code>int</code> value encoding the desired operation |
| * @param name a <code>String</code> value holding the name of the |
| * InputModule |
| * @param attr a <code>String</code> value holding the name of the |
| * attribute to return. Is disregarded when attribute names is |
| * requested. |
| * @param objectModel a <code>Map</code> value holding the current |
| * ObjectModel |
| * @return an <code>Object</code> value |
| * @exception CascadingRuntimeException if an error occurs. The real |
| * exception can be obtained with <code>getCause</code>. |
| */ |
| private Object get(int op, String name, String attr, Map objectModel, Configuration conf) throws CascadingRuntimeException { |
| |
| Object value = null; |
| final InputModule input = this.getInputModule(name); |
| |
| try { |
| |
| switch (op) { |
| case OP_GET: |
| value = input.getAttribute(attr, conf, objectModel); |
| break; |
| case OP_VALUES: |
| value = input.getAttributeValues(attr, conf, objectModel); |
| break; |
| case OP_NAMES: |
| value = input.getAttributeNames(conf, objectModel); |
| break; |
| } |
| |
| } catch (Exception e) { |
| throw new CascadingRuntimeException("Error accessing attribute '"+attr+"' from input module '"+name+"'. "+e.getMessage(), e); |
| } |
| |
| return value; |
| } |
| |
| private Object get(int op, String name, String attr, Map objectModel) throws RuntimeException { |
| return get(op, name, attr, objectModel, null); |
| } |
| |
| |
| |
| /** |
| * Initializes the instance for first use. Stores references to |
| * component manager and component selector in instance |
| * |
| * @param manager a <code>ComponentManager</code> value |
| * @exception RuntimeException if an error occurs |
| * @deprecated Use the {@link #setup(ServiceManager)} method instead |
| */ |
| public void setup(ComponentManager manager) throws RuntimeException { |
| |
| this.inputModules = new HashMap(); |
| this.componentManager = manager; |
| try { |
| this.componentInputSelector = (ComponentSelector) this.componentManager.lookup(INPUT_MODULE_SELECTOR); |
| } catch (Exception e) { |
| throw new CascadingRuntimeException("Could not obtain selector for InputModule.",e); |
| } |
| } |
| |
| /** |
| * Initializes the instance for first use. Stores references to |
| * service manager and service selector in instance |
| * |
| * @param manager a <code>ServiceManager</code> value |
| * @exception RuntimeException if an error occurs |
| */ |
| public void setup(ServiceManager manager) throws RuntimeException { |
| |
| this.inputModules = new HashMap(); |
| this.serviceManager = manager; |
| try { |
| this.serviceInputSelector = (ServiceSelector) this.serviceManager.lookup(INPUT_MODULE_SELECTOR); |
| } catch (Exception e) { |
| throw new CascadingRuntimeException("Could not obtain selector for InputModule.",e); |
| } |
| } |
| |
| |
| /** |
| * Get a single attribute value from a module. Uses cached |
| * reference if existing. |
| * |
| * @param objectModel a <code>Map</code> value |
| * @param conf a <code>Configuration</code> containing the module dynamic configuration (aka modeConf) |
| * @param module a <code>String</code> value holding the module name |
| * @param name a <code>String</code> value holding the attribute name |
| * @param deflt an <code>Object</code> value holding a default value |
| * @return an <code>Object</code> value |
| * @exception RuntimeException if an error occurs |
| */ |
| public Object getAttribute(Map objectModel, Configuration conf, String module, String name, Object deflt) throws RuntimeException { |
| |
| Object result = this.get(OP_GET, module, name, objectModel, conf); |
| if (result == null) result = deflt; |
| return result; |
| } |
| |
| /** |
| * Get a single attribute value from a module. Same as {@link |
| * #getAttribute(Map, Configuration, String, String, Object)} with a |
| * <code>null</code> configuration. |
| */ |
| public Object getAttribute(Map objectModel, String module, String name, Object deflt) throws RuntimeException { |
| return getAttribute(objectModel, null, module, name, deflt); |
| } |
| |
| |
| /** |
| * Get an array of values from a module. Uses cached reference if |
| * existing. |
| * |
| * @param objectModel a <code>Map</code> value |
| * @param conf a <code>Configuration</code> containing the module dynamic configuration (aka modeConf) |
| * @param module a <code>String</code> value holding the module name |
| * @param name a <code>String</code> value holding the attribute name |
| * @param deflt an <code>Object[]</code> value holding a default value |
| * @return an <code>Object[]</code> value |
| * @exception RuntimeException if an error occurs |
| */ |
| public Object[] getAttributeValues(Map objectModel, Configuration conf, String module, String name, Object[] deflt) throws RuntimeException { |
| |
| Object[] result = (Object[]) this.get(OP_VALUES, module, name, objectModel, conf); |
| if (result == null) result = deflt; |
| return result; |
| } |
| |
| /** |
| * Get an array of values from a module. Same as |
| * {@link #getAttributeValues(Map, Configuration, String, String, Object[])} |
| * with a <code>null</code> configuration. |
| */ |
| public Object[] getAttributeValues(Map objectModel, String module, String name, Object[] deflt) throws RuntimeException { |
| return getAttributeValues(objectModel, null, module, name, deflt); |
| } |
| |
| /** |
| * Output the request attribute values for a given name to the |
| * content handler. |
| * |
| * @param objectModel The Map objectModel |
| * @param contentHandler The SAX content handler |
| * @param module a <code>String</code> value holding the module name |
| * @param name a <code>String</code> value holding the attribute name |
| * @exception SAXException If a SAX error occurs |
| * @exception RuntimeException if an error occurs |
| */ |
| public void getAttributeValues(Map objectModel, ContentHandler contentHandler, String module, String name ) |
| throws SAXException, RuntimeException { |
| |
| AttributesImpl attr = new AttributesImpl(); |
| XSPObjectHelper.addAttribute(attr, "name", name); |
| |
| XSPObjectHelper.start(URI, PREFIX, contentHandler, |
| "attribute-values", attr); |
| |
| Object[] values = this.getAttributeValues(objectModel, module, name, null); |
| |
| if (values != null) { |
| for (int i = 0; i < values.length; i++) { |
| XSPObjectHelper.elementData(URI, PREFIX, contentHandler, |
| "value", String.valueOf(values[i])); |
| } |
| } |
| |
| XSPObjectHelper.end(URI, PREFIX, contentHandler, "attribute-values"); |
| } |
| |
| |
| /** |
| * Get an iterator to a collection of attribute names from a |
| * module. |
| * |
| * @param objectModel a <code>Map</code> value |
| * @param module the module's name |
| * @return an <code>Iterator</code> value |
| * @exception RuntimeException if an error occurs |
| */ |
| public Iterator getAttributeNames(Map objectModel, Configuration conf, String module) throws RuntimeException { |
| |
| return (Iterator) this.get(OP_NAMES, module, null, objectModel); |
| } |
| |
| /** Get an iterator to a collection of attribute names from a module. Same |
| * as {@link #getAttributeNames(Map, Configuration, String)} with a |
| * <code>null</code> configuration. |
| */ |
| public Iterator getAttributeNames(Map objectModel, String module) throws RuntimeException { |
| return getAttributeNames(objectModel, (Configuration)null, module); |
| } |
| |
| /** |
| * Output attribute names for a given request |
| * |
| * @param objectModel The Map objectModel |
| * @param contentHandler The SAX content handler |
| * @param module the module's name |
| * @exception SAXException If a SAX error occurs |
| * @exception RuntimeException if an error occurs |
| */ |
| public void getAttributeNames(Map objectModel, ContentHandler contentHandler, String module) |
| throws SAXException, RuntimeException { |
| |
| XSPObjectHelper.start(URI, PREFIX, contentHandler, "attribute-names"); |
| |
| Iterator iter = this.getAttributeNames(objectModel, module); |
| while (iter.hasNext()) { |
| String name = (String) iter.next(); |
| XSPObjectHelper.elementData(URI, PREFIX, contentHandler, "name", name); |
| } |
| |
| XSPObjectHelper.end(URI, PREFIX, contentHandler, "attribute-names"); |
| } |
| |
| |
| |
| /** |
| * Releases all obtained module references. |
| * |
| * @exception RuntimeException if an error occurs |
| */ |
| public void releaseAll() throws RuntimeException { |
| |
| if ( this.inputModules != null ) { |
| // test for component manager |
| if ( this.componentManager != null ) { |
| try { |
| Iterator iter = this.inputModules.keySet().iterator(); |
| while (iter.hasNext()) { |
| this.componentInputSelector.release((InputModule) this.inputModules.get(iter.next())); |
| } |
| this.inputModules = null; |
| this.componentManager.release(this.componentInputSelector); |
| this.componentManager = null; |
| this.inputModules = null; |
| } catch (Exception e) { |
| throw new CascadingRuntimeException("Could not release InputModules.",e); |
| } |
| |
| } |
| if ( this.serviceManager != null ) { |
| try { |
| Iterator iter = this.inputModules.keySet().iterator(); |
| while (iter.hasNext()) { |
| this.serviceInputSelector.release(this.inputModules.get(iter.next())); |
| } |
| this.inputModules = null; |
| this.serviceManager.release(this.serviceInputSelector); |
| this.serviceManager = null; |
| this.inputModules = null; |
| } catch (Exception e) { |
| throw new CascadingRuntimeException("Could not release InputModules.",e); |
| } |
| |
| } |
| } |
| } |
| } |