Author: craigmcc Date: Tue Jan 2 11:02:36 2007 New Revision: 491897 URL: http://svn.apache.org/viewvc?view=rev&rev=491897 Log: Beginnings of support for optional parsing of faces-config.xml files (SHALE-262) to register components, converters, renderers, and validators. Hasn't been tested yet other than being able to instantiate the helper, but that will come next.
Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/ConfigParser.java (with props) shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/package.html (with props) shale/framework/trunk/shale-test/src/test/java/org/apache/shale/test/config/ shale/framework/trunk/shale-test/src/test/java/org/apache/shale/test/config/ConfigParserTestCase.java (with props) Modified: shale/framework/trunk/shale-test/pom.xml Modified: shale/framework/trunk/shale-test/pom.xml URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/pom.xml?view=diff&rev=491897&r1=491896&r2=491897 ============================================================================== --- shale/framework/trunk/shale-test/pom.xml (original) +++ shale/framework/trunk/shale-test/pom.xml Tue Jan 2 11:02:36 2007 @@ -34,6 +34,14 @@ <dependencies> + <!-- Required only for using the org.apache.shale.test.config package --> + <dependency> + <groupId>commons-digester</groupId> + <artifactId>commons-digester</artifactId> + <version>1.8</version> + <optional>true</optional> + </dependency> + <dependency> <groupId>htmlunit</groupId> <artifactId>htmlunit</artifactId> Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/ConfigParser.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/ConfigParser.java?view=auto&rev=491897 ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/ConfigParser.java (added) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/ConfigParser.java Tue Jan 2 11:02:36 2007 @@ -0,0 +1,411 @@ +/* + * 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.shale.test.config; + +import java.io.IOException; +import java.net.URL; +import javax.faces.FactoryFinder; +import javax.faces.application.Application; +import javax.faces.application.ApplicationFactory; +import javax.faces.render.RenderKit; +import javax.faces.render.RenderKitFactory; +import javax.faces.render.Renderer; +import org.apache.commons.digester.Digester; +import org.apache.commons.digester.Rule; +import org.apache.shale.test.mock.MockRenderKit; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +/** + * <p>Utility class to parse JavaServer Faces configuration resources, and + * register JSF artifacts with the mock object hierarchy.</p> + * + * <p>The following artifacts are registered:</p> + * <ul> + * <li><code>Converter</code> (by-id and by-class)</li> + * <li><code>RenderKit</code> and <code>Renderer</code></li> + * <li><code>UIComponent</code></li> + * <li><code>Validator</code></li> + * </ul> + * + * <p>Note that any declared <em>factory</em> instances are explicitly + * <strong>NOT</strong> registered, allowing the mock object hierarchy + * of the Shale Test Framework to manage these APIs.</p> + * + * <p><strong>USAGE NOTE</strong> - If you are using an instance of this + * class within a subclass of <code>AbstractJsfTestCase</code> or + * <code>AbstractJmockJsfTestCase</code>, be sure you have completed the + * <code>setUp()</code> processing in this base class before calling one + * of the <code>parse()</code> methods.</p> + */ +public final class ConfigParser { + + + // ------------------------------------------------------------ Constructors + + + /** Creates a new instance of ConfigParser */ + public ConfigParser() { + } + + + // ------------------------------------------------------ Instance Variables + + + /** + * <p>The <code>Digester</code> instance we will use for parsing.</p> + */ + private Digester digester = null; + + + // ------------------------------------------------------- Public Properties + + + // ---------------------------------------------------------- Public Methods + + + /** + * <p>Parse the specified JavaServer Faces configuration resource, causing + * the appropriate JSF artifacts to be registered with the mock object + * hierarchy.</p> + * + * @param url <code>URL</code> of the configuration resource to parse + * + * @exception IOException if an input/output error occurs + * @exception SAXException if a parsing error occurs + */ + public void parse(URL url) throws IOException, SAXException { + + // Acquire and configure the Digester instance we will use + Digester digester = digester(); + ApplicationFactory factory = (ApplicationFactory) + FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY); + Application application = factory.getApplication(); + digester.push(application); + + // Perform the required parsing + try { + digester.parse(url); + } finally { + digester.clear(); + } + + } + + + /** + * <p>Parse the specified set of JavaServer Faces configuration resources, + * in the listed order, causing the appropriate JSF artifacts to be registered + * with the mock object hierarchy.</p> + * + * @param urls <code>URL</code>s of the configuration resources to parse + * + * @exception IOException if an input/output error occurs + * @exception SAXException if a parsing error occurs + */ + public void parse(URL[] urls) throws IOException, SAXException { + + for (int i = 0; i < urls.length; i++) { + parse(urls[i]); + } + + } + + + // --------------------------------------------------------- Private Methods + + + /** + * <p>Return the <code>Digester</code> instance we will use for parsing, + * creating and configuring a new instance if necessary.</p> + */ + private Digester digester() { + + if (this.digester == null) { + this.digester = new Digester(); + digester.addRule("faces-config/component", new ComponentRule()); + digester.addCallMethod + ("faces-config/component/component-type", "setComponentType", 0); + digester.addCallMethod + ("faces-config/component/component-class", "setComponentClass", 0); + digester.addRule("faces-config/converter", new ValidatorRule()); + digester.addCallMethod + ("faces-config/converter/converter-id", "setConverterId", 0); + digester.addCallMethod + ("faces-config/converter/converter-class", "setConverterClass", 0); + digester.addCallMethod + ("faces-config/converter/converter-for-class", "setConverterForClass", 0); + digester.addRule("faces-config/render-kit", new RenderKitRule()); + digester.addRule("faces-config/render-kit/render-kit-id", new RenderKitIdRule()); + digester.addRule("faces-config/validator", new ValidatorRule()); + digester.addCallMethod + ("faces-config/validator/validator-id", "setValidatorId", 0); + digester.addCallMethod + ("faces-config/validator/validator-class", "setValidatorClass", 0); + } + return this.digester; + + } + + + // --------------------------------------------------------- Private Classes + + + /** + * <p>Data bean that stores information related to a component.</p> + */ + class ComponentBean { + + private String componentClass; + public String getComponentClass() { + return this.componentClass; + } + public void setComponentClass(String componentClass) { + this.componentClass = componentClass; + } + + private String componentType; + public String getComponentType() { + return this.componentType; + } + public void setComponentType(String componentType) { + this.componentType = componentType; + } + + } + + + /** + * <p>Digester <code>Rule</code> for processing components.</p> + */ + class ComponentRule extends Rule { + + public void begin(String namespace, String name, Attributes attributes) { + getDigester().push(new ComponentBean()); + } + + public void end(String namespace, String name) { + ComponentBean bean = (ComponentBean) getDigester().pop(); + Application application = (Application) getDigester().peek(); + application.addComponent(bean.getComponentType(), bean.getComponentClass()); + } + + } + + + /** + * <p>Data bean that stores information related to a converter.</p> + */ + class ConverterBean { + + private String converterClass; + public String getConverterClass() { + return this.converterClass; + } + public void setConverterClass(String converterClass) { + this.converterClass = converterClass; + } + + private String converterForClass; + public String getConverterForClass() { + return this.converterForClass; + } + public void setConverterForClass(String converterForClass) { + this.converterForClass = converterForClass; + } + + private String converterId; + public String getConverterId() { + return this.converterId; + } + public void setConverterId(String converterId) { + this.converterId = converterId; + } + + } + + + /** + * <p>Digester <code>Rule</code> for processing converers.</p> + */ + class ConverterRule extends Rule { + + public void begin(String namespace, String name, Attributes attributes) { + getDigester().push(new ConverterBean()); + } + + public void end(String namespace, String name) { + ConverterBean bean = (ConverterBean) getDigester().pop(); + Application application = (Application) getDigester().peek(); + if (bean.getConverterId() != null) { + application.addConverter(bean.getConverterId(), bean.getConverterClass()); + } else { + Class clazz = null; + try { + clazz = this.getClass().getClassLoader().loadClass(bean.getConverterForClass()); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(bean.getConverterForClass(), e); + } + application.addConverter(clazz, bean.getConverterClass()); + } + } + + } + + + /** + * <p>Digester <code>Rule</code> for processing render kits.</p> + */ + class RenderKitRule extends Rule { + + public void begin(String namespace, String name, Attributes attributes) { + RenderKitFactory factory = (RenderKitFactory) + FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY); + getDigester().push(factory.getRenderKit(null, RenderKitFactory.HTML_BASIC_RENDER_KIT)); + } + + public void end(String namespace, String name) { + getDigester().pop(); + } + + } + + + /** + * <p>Digester <code>Rule</code> for processing render kit identifiers.</p> + */ + class RenderKitIdRule extends Rule { + + public void body(String namespace, String name, String text) { + String renderKitId = text.trim(); + RenderKitFactory factory = (RenderKitFactory) + FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY); + RenderKit renderKit = factory.getRenderKit(null, renderKitId); + if (renderKit == null) { + renderKit = new MockRenderKit(); + factory.addRenderKit(renderKitId, renderKit); + } + digester.pop(); + digester.push(renderKit); + } + + } + + + /** + * <p>Data bean that stores information related to a renderer.</p> + */ + class RendererBean { + + private String componentFamily; + public String getComponentFamily() { + return this.componentFamily; + } + public void setComponentFamily(String componentFamily) { + this.componentFamily = componentFamily; + } + + private String rendererClass; + public String getRendererClass() { + return this.rendererClass; + } + public void setRendererClass(String rendererClass) { + this.rendererClass = rendererClass; + } + + private String rendererType; + public String getRendererType() { + return this.rendererType; + } + public void setRendererType(String rendererType) { + this.rendererType = rendererType; + } + + } + + + /** + * <p>Digester <code>Rule</code> for processing renderers.</p> + */ + class RendererRule extends Rule { + + public void begin(String namespace, String name, Attributes attributes) { + getDigester().push(new RendererBean()); + } + + public void end(String namespace, String name) { + RendererBean bean = (RendererBean) getDigester().pop(); + RenderKit kit = (RenderKit) getDigester().peek(); + Renderer renderer = null; + Class clazz = null; + try { + clazz = this.getClass().getClassLoader().loadClass(bean.getRendererClass()); + renderer = (Renderer) clazz.newInstance(); + } catch (Exception e) { + throw new IllegalArgumentException(bean.getRendererClass(), e); + } + kit.addRenderer(bean.getComponentFamily(), bean.getRendererType(), + renderer); + } + + } + + + /** + * <p>Data bean that stores information related to a validator.</p> + */ + class ValidatorBean { + + private String validatorClass; + public String getValidatorClass() { + return this.validatorClass; + } + public void setValidatorClass(String validatorClass) { + this.validatorClass = validatorClass; + } + + private String validatorId; + public String getValidatorId() { + return this.validatorId; + } + public void setValidatorId(String validatorId) { + this.validatorId = validatorId; + } + + } + + + /** + * <p>Digester <code>Rule</code> for processing validators.</p> + */ + class ValidatorRule extends Rule { + + public void begin(String namespace, String name, Attributes attributes) { + getDigester().push(new ValidatorBean()); + } + + public void end(String namespace, String name) { + ValidatorBean bean = (ValidatorBean) getDigester().pop(); + Application application = (Application) getDigester().peek(); + application.addValidator(bean.getValidatorId(), bean.getValidatorClass()); + } + + } + + +} Propchange: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/ConfigParser.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/ConfigParser.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/package.html URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/package.html?view=auto&rev=491897 ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/package.html (added) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/package.html Tue Jan 2 11:02:36 2007 @@ -0,0 +1,30 @@ +<body> +<!-- + 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. +--> +<p>This package contains a utility class, +<a href="ConfigParser.html">ConfigParser</a>, which provides a +<code>parse()</code> method that can parse JavaServer Faces configuration +resources. It supports the registration, in the mock object hierarchy +set up by an instance of <code>AbstractJsfTestCase</code> or +<code>AbstractJmockJsfTestCase</code>, of the following JSF artifacts:</p> +<ul> + <li><code>Converter</code> (by-id and by-class)</li> + <li><code>RenderKit</code> and <code>Renderer</code></li> + <li><code>UIComponent</code></li> + <li><code>Validator</code></li> +</ul> +</body> Propchange: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/package.html ------------------------------------------------------------------------------ svn:eol-style = native Propchange: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/config/package.html ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: shale/framework/trunk/shale-test/src/test/java/org/apache/shale/test/config/ConfigParserTestCase.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/test/java/org/apache/shale/test/config/ConfigParserTestCase.java?view=auto&rev=491897 ============================================================================== --- shale/framework/trunk/shale-test/src/test/java/org/apache/shale/test/config/ConfigParserTestCase.java (added) +++ shale/framework/trunk/shale-test/src/test/java/org/apache/shale/test/config/ConfigParserTestCase.java Tue Jan 2 11:02:36 2007 @@ -0,0 +1,89 @@ +/* + * 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.shale.test.config; + +import junit.framework.Test; +import junit.framework.TestSuite; +import org.apache.shale.test.base.AbstractJsfTestCase; + +/** + * <p>Unit tests for the configuration parser utility class.</p> + */ +public class ConfigParserTestCase extends AbstractJsfTestCase { + + + // ------------------------------------------------------------ Constructors + + + // Construct a new instance of this test case. + public ConfigParserTestCase(String name) { + super(name); + } + + + // ---------------------------------------------------- Overall Test Methods + + + // Set up instance variables required by this test case. + protected void setUp() throws Exception { + + super.setUp(); + parser = new ConfigParser(); + + } + + + // Return the tests included in this test case. + public static Test suite() { + + return (new TestSuite(ConfigParserTestCase.class)); + + } + + + // Tear down instance variables required by this test case. + protected void tearDown() throws Exception { + + parser = null; + super.tearDown(); + + } + + + // ------------------------------------------------------ Instance Variables + + + // ConfigParser instance under test + ConfigParser parser = null; + + + // ------------------------------------------------- Individual Test Methods + + + // Test a pristine instance + public void testPristine() { + + assertNotNull(parser); + + } + + + // --------------------------------------------------------- Private Methods + + +} Propchange: shale/framework/trunk/shale-test/src/test/java/org/apache/shale/test/config/ConfigParserTestCase.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: shale/framework/trunk/shale-test/src/test/java/org/apache/shale/test/config/ConfigParserTestCase.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL