Revision: 463
Author: lincolnbaxter
Date: Thu Nov 4 13:06:12 2010
Log: * Added 'parentId' for Hierarchical Mappings in pretty-config.xml (#72)
* Added SPI hooks for ConfigurationProvider and ConfigurationPostProcessor
* Completely refactored PrettyConfigurator
* Can now be run in a pure servlet environment (without JSF)
http://code.google.com/p/prettyfaces/source/detail?r=463
Added:
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi/AnnotationConfigurationProvider.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi/ClassLoaderConfigurationProvider.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi/ContextSpecifiedConfigurationProvider.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi/DefaultXMLConfigurationProvider.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi/ParentingPostProcessor.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi/ValidatingPostProcessor.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/spi
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/spi/ConfigurationPostProcessor.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/spi/ConfigurationProvider.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/util/PhaseIdComparator.java
/prettyfaces/trunk/core/src/main/resources/META-INF/services/com.ocpsoft.pretty.faces.spi.ConfigurationPostProcessor
/prettyfaces/trunk/core/src/main/resources/META-INF/services/com.ocpsoft.pretty.faces.spi.ConfigurationProvider
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/MockClassLoader.java
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/spi
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/spi/ParentingPostProcessorTest.java
/prettyfaces/trunk/core/src/test/resources/META-INF
/prettyfaces/trunk/core/src/test/resources/META-INF/pretty-config.xml
/prettyfaces/trunk/core/src/test/resources/parenting-pretty-config.xml
Modified:
/prettyfaces/trunk/CHANGELOG.txt
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/PrettyException.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/annotation/URLAction.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/annotation/URLMapping.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/beans/ActionExecutor.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/DigesterPrettyConfigParser.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/PrettyConfigBuilder.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/PrettyConfigurator.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/annotation/PrettyAnnotationHandler.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/convert/CaseConverter.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/convert/PhaseIdConverter.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/convert/RedirectConverter.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/convert/TrailingSlashConverter.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/mapping/UrlAction.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/mapping/UrlMapping.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/servlet/WebXmlParser.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/el/LazyBeanNameFinder.java
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/url/URLPatternParser.java
/prettyfaces/trunk/core/src/main/resources/META-INF/ocpsoft-pretty-faces-3.1.1.xsd
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/beans/ActionExecutorTest.java
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/MappingDigesterPrettyConfigParserTest.java
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/MockFacesServletRegistration.java
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/PrettyConfiguratorTest.java
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/annotation/PrettyAnnotationHandlerTest.java
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/mapping/UrlActionTest.java
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/mapping/UrlMappingTest.java
/prettyfaces/trunk/impl-jsf11/src/test/resources/log4j.properties
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi/AnnotationConfigurationProvider.java
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,95 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package com.ocpsoft.pretty.faces.config.spi;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.ocpsoft.pretty.faces.config.PrettyConfig;
+import com.ocpsoft.pretty.faces.config.PrettyConfigBuilder;
+import com.ocpsoft.pretty.faces.config.annotation.ClassFinder;
+import com.ocpsoft.pretty.faces.config.annotation.PackageFilter;
+import com.ocpsoft.pretty.faces.config.annotation.PrettyAnnotationHandler;
+import com.ocpsoft.pretty.faces.config.annotation.WebClassesFinder;
+import com.ocpsoft.pretty.faces.config.annotation.WebLibFinder;
+import com.ocpsoft.pretty.faces.el.LazyBeanNameFinder;
+import com.ocpsoft.pretty.faces.spi.ConfigurationProvider;
+
+/**
+ * @author <a href="mailto:
lincol...@gmail.com">Lincoln Baxter, III</a>
+ *
+ */
+public class AnnotationConfigurationProvider implements
ConfigurationProvider
+{
+ private static final Log log =
LogFactory.getLog(AnnotationConfigurationProvider.class);
+
+ public static final String CONFIG_SCAN_LIB_DIR
= "com.ocpsoft.pretty.SCAN_LIB_DIRECTORY";
+ public static final String CONFIG_BASE_PACKAGES
= "com.ocpsoft.pretty.BASE_PACKAGES";
+
+ public PrettyConfig load(ServletContext servletContext)
+ {
+ String packageFilters =
servletContext.getInitParameter(CONFIG_BASE_PACKAGES);
+
+ if ((packageFilters != null) &&
packageFilters.trim().equalsIgnoreCase("none"))
+ {
+ log.debug("Annotation scanning has is disabled!");
+ return null;
+ }
+
+ PackageFilter packageFilter = new PackageFilter(packageFilters);
+ LazyBeanNameFinder beanNameFinder = new
LazyBeanNameFinder(servletContext);
+ PrettyAnnotationHandler annotationHandler = new
PrettyAnnotationHandler(beanNameFinder);
+
+ ClassLoader classloader =
Thread.currentThread().getContextClassLoader();
+ if (classloader == null)
+ {
+ classloader = this.getClass().getClassLoader();
+ }
+
+ List<ClassFinder> classFinders = new ArrayList<ClassFinder>();
+
+ // we will always scan /WEB-INF/classes
+ classFinders.add(new WebClassesFinder(servletContext, classloader,
packageFilter));
+
+ // does the user want to scan /WEB-INF/lib ?
+ String jarConfig =
servletContext.getInitParameter(CONFIG_SCAN_LIB_DIR);
+ if ((jarConfig != null) && jarConfig.trim().equalsIgnoreCase("true"))
+ {
+ classFinders.add(new WebLibFinder(servletContext, classloader,
packageFilter));
+ }
+
+ for (ClassFinder finder : classFinders)
+ {
+ finder.findClasses(annotationHandler);
+ }
+
+ PrettyConfigBuilder builder = new PrettyConfigBuilder();
+ annotationHandler.build(builder);
+ return builder.build();
+ }
+}
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi/ClassLoaderConfigurationProvider.java
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,109 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package com.ocpsoft.pretty.faces.config.spi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Enumeration;
+
+import javax.servlet.ServletContext;
+
+import org.xml.sax.SAXException;
+
+import com.ocpsoft.pretty.PrettyException;
+import com.ocpsoft.pretty.faces.config.DigesterPrettyConfigParser;
+import com.ocpsoft.pretty.faces.config.PrettyConfig;
+import com.ocpsoft.pretty.faces.config.PrettyConfigBuilder;
+import com.ocpsoft.pretty.faces.config.PrettyConfigParser;
+import com.ocpsoft.pretty.faces.spi.ConfigurationProvider;
+
+/**
+ * @author <a href="mailto:
lincol...@gmail.com">Lincoln Baxter, III</a>
+ *
+ */
+public class ClassLoaderConfigurationProvider implements
ConfigurationProvider
+{
+ public static final String PRETTY_CONFIG_RESOURCE
= "META-INF/pretty-config.xml";
+ public static final String CLASSPATH_CONFIG_ENABLED
= "com.ocpsoft.pretty.LOAD_CLASSPATH_CONFIG";
+
+ public PrettyConfig load(ServletContext context)
+ {
+ String enabled = context.getInitParameter(CLASSPATH_CONFIG_ENABLED);
+ if ((enabled != null) && "false".equalsIgnoreCase(enabled.trim()))
+ {
+ return null;
+ }
+
+ final PrettyConfigBuilder builder = new PrettyConfigBuilder();
+ PrettyConfigParser configParser = new DigesterPrettyConfigParser();
+ try
+ {
+ final Enumeration<URL> urls =
getClass().getClassLoader().getResources(PRETTY_CONFIG_RESOURCE);
+ if (urls != null)
+ {
+ while (urls.hasMoreElements())
+ {
+ final URL url = urls.nextElement();
+ if (url != null)
+ {
+ InputStream is = null;
+ try
+ {
+ is = openStream(url);
+ try
+ {
+ configParser.parse(builder, is);
+ }
+ catch (SAXException e)
+ {
+ throw new PrettyException("Failed to parse
PrettyFaces configuration from URL:" + url, e);
+ }
+ }
+ finally
+ {
+ if (is != null)
+ {
+ is.close();
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ throw new PrettyException("Could not get references to
PrettyFaces ClassLoader-configuration elements.", e);
+ }
+ return builder.build();
+ }
+
+ private InputStream openStream(final URL url) throws IOException
+ {
+ final URLConnection connection = url.openConnection();
+ connection.setUseCaches(false);
+ return connection.getInputStream();
+ }
+
+}
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi/ContextSpecifiedConfigurationProvider.java
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,120 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package com.ocpsoft.pretty.faces.config.spi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.ocpsoft.pretty.PrettyContext;
+import com.ocpsoft.pretty.PrettyException;
+import com.ocpsoft.pretty.faces.config.DigesterPrettyConfigParser;
+import com.ocpsoft.pretty.faces.config.PrettyConfig;
+import com.ocpsoft.pretty.faces.config.PrettyConfigBuilder;
+import com.ocpsoft.pretty.faces.config.PrettyConfigParser;
+import com.ocpsoft.pretty.faces.spi.ConfigurationProvider;
+
+/**
+ * Loads configuration files specified in web.xml init parameter
+ * {@link PrettyContext#CONFIG_KEY}
+ *
+ * @author <a href="mailto:
lincol...@gmail.com">Lincoln Baxter, III</a>
+ *
+ */
+public class ContextSpecifiedConfigurationProvider implements
ConfigurationProvider
+{
+ private static final Log log =
LogFactory.getLog(ContextSpecifiedConfigurationProvider.class);
+
+ public PrettyConfig load(ServletContext servletContext)
+ {
+ final PrettyConfigBuilder builder = new PrettyConfigBuilder();
+ PrettyConfigParser configParser = new DigesterPrettyConfigParser();
+ final List<String> configFilesList =
getConfigFilesList(servletContext);
+ for (final String configFilePath : configFilesList)
+ {
+ final InputStream is =
servletContext.getResourceAsStream(configFilePath);
+ if (is == null)
+ {
+ log.error("Pretty Faces config resource [" + configFilePath
+ "] not found.");
+ continue;
+ }
+
+ log.trace("Reading config [" + configFilePath + "].");
+
+ try
+ {
+ configParser.parse(builder, is);
+ }
+ catch (Exception e)
+ {
+ throw new PrettyException("Failed to parse PrettyFaces
configuration from " + configFilePath, e);
+ }
+ finally
+ {
+ try
+ {
+ is.close();
+ }
+ catch (IOException ignored)
+ {
+
+ }
+ }
+ }
+
+ return builder.build();
+ }
+
+ private List<String> getConfigFilesList(ServletContext context)
+ {
+ final String configFiles =
context.getInitParameter(PrettyContext.CONFIG_KEY);
+ final List<String> configFilesList = new ArrayList<String>();
+ if (configFiles != null)
+ {
+ final StringTokenizer st = new StringTokenizer(configFiles, ",",
false);
+ while (st.hasMoreTokens())
+ {
+ final String systemId = st.nextToken().trim();
+
+ if
(DefaultXMLConfigurationProvider.DEFAULT_PRETTY_FACES_CONFIG.equals(systemId))
+ {
+ log.warn("The file [" +
DefaultXMLConfigurationProvider.DEFAULT_PRETTY_FACES_CONFIG + "] has been
specified in the ["
+ + PrettyContext.CONFIG_KEY + "] context parameter of "
+ + "the deployment descriptor; this is unecessary and
will be ignored.");
+ }
+ else
+ {
+ configFilesList.add(systemId);
+ }
+ }
+ }
+ return configFilesList;
+ }
+}
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi/DefaultXMLConfigurationProvider.java
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,81 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package com.ocpsoft.pretty.faces.config.spi;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.ServletContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.ocpsoft.pretty.PrettyException;
+import com.ocpsoft.pretty.faces.config.DigesterPrettyConfigParser;
+import com.ocpsoft.pretty.faces.config.PrettyConfig;
+import com.ocpsoft.pretty.faces.config.PrettyConfigBuilder;
+import com.ocpsoft.pretty.faces.config.PrettyConfigParser;
+import com.ocpsoft.pretty.faces.spi.ConfigurationProvider;
+
+/**
+ * @author <a href="mailto:
lincol...@gmail.com">Lincoln Baxter, III</a>
+ *
+ */
+public class DefaultXMLConfigurationProvider implements
ConfigurationProvider
+{
+ private static final Log log =
LogFactory.getLog(DefaultXMLConfigurationProvider.class);
+
+ public static final String DEFAULT_PRETTY_FACES_CONFIG
= "/WEB-INF/pretty-config.xml";
+
+ public PrettyConfig load(ServletContext servletContext)
+ {
+ final PrettyConfigBuilder builder = new PrettyConfigBuilder();
+ PrettyConfigParser configParser = new DigesterPrettyConfigParser();
+ final InputStream is =
servletContext.getResourceAsStream(DEFAULT_PRETTY_FACES_CONFIG);
+ if (is != null)
+ {
+ log.trace("Reading config [" + DEFAULT_PRETTY_FACES_CONFIG
+ "].");
+
+ try
+ {
+ configParser.parse(builder, is);
+ }
+ catch (Exception e)
+ {
+ throw new PrettyException("Failed to parse PrettyFaces
configuration from " + DEFAULT_PRETTY_FACES_CONFIG, e);
+ }
+ finally
+ {
+ try
+ {
+ is.close();
+ }
+ catch (IOException ignored)
+ {
+ }
+ }
+ }
+
+ return builder.build();
+ }
+}
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi/ParentingPostProcessor.java
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,92 @@
+/*
+ * PrettyFaces is an OpenSource JSF library to create bookmarkable URLs.
+ * Copyright (C) 2010 - Lincoln Baxter, III <
lin...@ocpsoft.com> This
program
+ * is free software: you can redistribute it and/or modify it under the
terms of
+ * the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any
later
+ * version. This program is distributed in the hope that it will be
useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License
+ * for more details. You should have received a copy of the GNU Lesser
General
+ * Public License along with this program. If not, see the file
COPYING.LESSER3
+ * or visit the GNU website at <
http://www.gnu.org/licenses/>.
+ */
+
+package com.ocpsoft.pretty.faces.config.spi;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import com.ocpsoft.pretty.faces.config.PrettyConfig;
+import com.ocpsoft.pretty.faces.config.mapping.PathValidator;
+import com.ocpsoft.pretty.faces.config.mapping.UrlMapping;
+import com.ocpsoft.pretty.faces.spi.ConfigurationPostProcessor;
+
+/**
+ * @author <a href="mailto:
lincol...@gmail.com">Lincoln Baxter, III</a>
+ */
+public class ParentingPostProcessor implements ConfigurationPostProcessor
+{
+ public static final String HIERARCHY_ENABLED_PARAM
= "com.ocpsoft.pretty.INHERITABLE_CONFIG";
+ private final List<UrlMapping> seen = new ArrayList<UrlMapping>();
+
+ public PrettyConfig process(PrettyConfig config, Map<String, String>
parameters)
+ {
+ if (parameters.containsKey(HIERARCHY_ENABLED_PARAM)
&& "false".equalsIgnoreCase(parameters.get(HIERARCHY_ENABLED_PARAM).trim()))
+ {
+ return config;
+ }
+
+ List<UrlMapping> mappings = config.getMappings();
+ for (UrlMapping m : mappings)
+ {
+ createAncestry(config, m);
+ }
+ return config;
+ }
+
+ private void createAncestry(PrettyConfig config, UrlMapping m)
+ {
+ if (m.hasParent() && !seen.contains(m))
+ {
+ UrlMapping parent = config.getMappingById(m.getParentId());
+ if (parent.hasParent())
+ {
+ createAncestry(config, parent);
+ }
+ m.setPattern(parent.getPattern() + m.getPattern());
+ mergeValidators(parent, m);
+ seen.add(m);
+ }
+ }
+
+ private void mergeValidators(UrlMapping parent, UrlMapping child)
+ {
+ List<PathValidator> result = new ArrayList<PathValidator>();
+ List<PathValidator> validators = new ArrayList<PathValidator>();
+
+ validators.addAll(parent.getPathValidators());
+ validators.addAll(child.getPathValidators());
+
+ int i = 0;
+ for (PathValidator pv : validators)
+ {
+ PathValidator temp = copy(pv);
+ temp.setIndex(i++);
+ result.add(temp);
+ }
+
+ child.setPathValidators(result);
+ }
+
+ private PathValidator copy(PathValidator pathValidator)
+ {
+ PathValidator result = new PathValidator();
+ result.setIndex(pathValidator.getIndex());
+ result.setOnError(pathValidator.getOnError());
+ result.setValidatorIds(pathValidator.getValidatorIds());
+
result.setValidatorExpression(pathValidator.getValidatorExpression());
+ return result;
+ }
+}
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/spi/ValidatingPostProcessor.java
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,47 @@
+/*
+ * PrettyFaces is an OpenSource JSF library to create bookmarkable URLs.
+ * Copyright (C) 2009 - Lincoln Baxter, III <
lin...@ocpsoft.com> This
program
+ * is free software: you can redistribute it and/or modify it under the
terms of
+ * the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any
later
+ * version. This program is distributed in the hope that it will be
useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License
+ * for more details. You should have received a copy of the GNU Lesser
General
+ * Public License along with this program. If not, see the file
COPYING.LESSER3
+ * or visit the GNU website at <
http://www.gnu.org/licenses/>.
+ */
+
+package com.ocpsoft.pretty.faces.config.spi;
+
+import java.util.Map;
+
+import com.ocpsoft.pretty.faces.config.PrettyConfig;
+import com.ocpsoft.pretty.faces.config.mapping.UrlMapping;
+import com.ocpsoft.pretty.faces.spi.ConfigurationPostProcessor;
+
+/**
+ * Ensure that the configuration is properly constructed and compiles.
+ *
+ * @author <a href="mailto:
lincol...@gmail.com">Lincoln Baxter, III</a>
+ *
+ */
+public class ValidatingPostProcessor implements ConfigurationPostProcessor
+{
+ public static final String VALIDATION_ENABLED_PARAM
= "com.ocpsoft.pretty.VALIDATE_CONFIG";
+
+ public PrettyConfig process(PrettyConfig config, Map<String, String>
parameters)
+ {
+ if (parameters.containsKey(VALIDATION_ENABLED_PARAM)
&& "false".equalsIgnoreCase(parameters.get(VALIDATION_ENABLED_PARAM).trim()))
+ {
+ return config;
+ }
+
+ for (UrlMapping m : config.getMappings())
+ {
+ m.getPatternParser();
+ }
+
+ return config;
+ }
+}
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/spi/ConfigurationPostProcessor.java
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,38 @@
+/*
+ * PrettyFaces is an OpenSource JSF library to create bookmarkable URLs.
+ * Copyright (C) 2009 - Lincoln Baxter, III <
lin...@ocpsoft.com> This
program
+ * is free software: you can redistribute it and/or modify it under the
terms of
+ * the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any
later
+ * version. This program is distributed in the hope that it will be
useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License
+ * for more details. You should have received a copy of the GNU Lesser
General
+ * Public License along with this program. If not, see the file
COPYING.LESSER3
+ * or visit the GNU website at <
http://www.gnu.org/licenses/>.
+ */
+package com.ocpsoft.pretty.faces.spi;
+
+import java.util.Map;
+
+import com.ocpsoft.pretty.faces.config.PrettyConfig;
+
+/**
+ * Defines the interface to be used in performing post-config-parse step
+ * processing.
+ *
+ * @author <a href="mailto:
lincol...@gmail.com">Lincoln Baxter, III</a>
+ */
+public interface ConfigurationPostProcessor
+{
+
+ /**
+ * Process the given PrettyConfig, returning the modified configuration.
+ *
+ * @param config The config to process
+ * @param parameters The map of servlet context init parameters
+ * @return The processed configuration
+ */
+ PrettyConfig process(PrettyConfig config, Map<String, String>
parameters);
+
+}
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/spi/ConfigurationProvider.java
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,36 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package com.ocpsoft.pretty.faces.spi;
+
+import javax.servlet.ServletContext;
+
+import com.ocpsoft.pretty.faces.config.PrettyConfig;
+
+/**
+ * @author <a href="mailto:
lincol...@gmail.com">Lincoln Baxter, III</a>
+ *
+ */
+public interface ConfigurationProvider
+{
+ PrettyConfig load(ServletContext servletContext);
+}
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/util/PhaseIdComparator.java
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package com.ocpsoft.pretty.faces.util;
+
+import com.ocpsoft.pretty.faces.annotation.URLAction.PhaseId;
+
+/**
+ * @author <a href="mailto:
lincol...@gmail.com">Lincoln Baxter, III</a>
+ *
+ */
+public class PhaseIdComparator
+{
+
+ /**
+ * @param phaseId
+ * @param currentPhaseId
+ * @return
+ */
+ public static boolean equals(PhaseId phaseId, javax.faces.event.PhaseId
currentPhaseId)
+ {
+ switch (phaseId)
+ {
+ case ANY_PHASE:
+ return javax.faces.event.PhaseId.ANY_PHASE.equals(currentPhaseId);
+ case RESTORE_VIEW:
+ return
javax.faces.event.PhaseId.RESTORE_VIEW.equals(currentPhaseId);
+ case APPLY_REQUEST_VALUES:
+ return
javax.faces.event.PhaseId.APPLY_REQUEST_VALUES.equals(currentPhaseId);
+ case PROCESS_VALIDATIONS:
+ return
javax.faces.event.PhaseId.PROCESS_VALIDATIONS.equals(currentPhaseId);
+ case UPDATE_MODEL_VALUES:
+ return
javax.faces.event.PhaseId.UPDATE_MODEL_VALUES.equals(currentPhaseId);
+ case INVOKE_APPLICATION:
+ return
javax.faces.event.PhaseId.INVOKE_APPLICATION.equals(currentPhaseId);
+ case RENDER_RESPONSE:
+ return
javax.faces.event.PhaseId.RENDER_RESPONSE.equals(currentPhaseId);
+ }
+ return false;
+ }
+}
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/main/resources/META-INF/services/com.ocpsoft.pretty.faces.spi.ConfigurationPostProcessor
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,2 @@
+com.ocpsoft.pretty.faces.config.spi.ValidatingPostProcessor
+com.ocpsoft.pretty.faces.config.spi.ParentingPostProcessor
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/main/resources/META-INF/services/com.ocpsoft.pretty.faces.spi.ConfigurationProvider
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,4 @@
+com.ocpsoft.pretty.faces.config.spi.AnnotationConfigurationProvider
+com.ocpsoft.pretty.faces.config.spi.ClassLoaderConfigurationProvider
+com.ocpsoft.pretty.faces.config.spi.ContextSpecifiedConfigurationProvider
+com.ocpsoft.pretty.faces.config.spi.DefaultXMLConfigurationProvider
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/MockClassLoader.java
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,81 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package com.ocpsoft.pretty.faces.config;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+import
com.ocpsoft.pretty.faces.config.spi.ClassLoaderConfigurationProvider;
+
+/**
+ * @author <a href="mailto:
lincol...@gmail.com">Lincoln Baxter, III</a>
+ *
+ */
+public class MockClassLoader extends URLClassLoader
+{
+ private URL[] urls = null;
+
+ public MockClassLoader(URL... urls)
+ {
+ super(new URL[0], Thread.currentThread().getContextClassLoader());
+ this.urls = urls;
+ }
+
+ @Override
+ public Enumeration<URL> getResources(final String name) throws
IOException
+ {
+ if
(ClassLoaderConfigurationProvider.PRETTY_CONFIG_RESOURCE.equals(name))
+ {
+ return enumeration(urls);
+ }
+ else
+ {
+ return super.getResources(name);
+ }
+ }
+
+ private <T> Enumeration<T> enumeration(final T... elements)
+ {
+ return new Enumeration<T>()
+ {
+ private int index = 0;
+
+ public boolean hasMoreElements()
+ {
+ return index < elements.length;
+ }
+
+ public T nextElement()
+ {
+ if (!hasMoreElements())
+ {
+ throw new NoSuchElementException("No more elements exist.");
+ }
+ return elements[index++];
+ }
+ };
+ }
+}
=======================================
--- /dev/null
+++
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/spi/ParentingPostProcessorTest.java
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,108 @@
+/*
+ * PrettyFaces is an OpenSource JSF library to create bookmarkable URLs.
+ * Copyright (C) 2009 - Lincoln Baxter, III <
lin...@ocpsoft.com> This
program
+ * is free software: you can redistribute it and/or modify it under the
terms of
+ * the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any
later
+ * version. This program is distributed in the hope that it will be
useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License
+ * for more details. You should have received a copy of the GNU Lesser
General
+ * Public License along with this program. If not, see the file
COPYING.LESSER3
+ * or visit the GNU website at <
http://www.gnu.org/licenses/>.
+ */
+package com.ocpsoft.pretty.faces.config.spi;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+
+import org.easymock.EasyMock;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+import com.ocpsoft.pretty.PrettyContext;
+import com.ocpsoft.pretty.faces.config.DigesterPrettyConfigParser;
+import com.ocpsoft.pretty.faces.config.MockClassLoader;
+import com.ocpsoft.pretty.faces.config.MockFacesServletRegistration;
+import com.ocpsoft.pretty.faces.config.PrettyConfig;
+import com.ocpsoft.pretty.faces.config.PrettyConfigBuilder;
+import com.ocpsoft.pretty.faces.config.PrettyConfigurator;
+
+/**
+ * @author <a href="mailto:
lincol...@gmail.com">Lincoln Baxter, III</a>
+ */
+public class ParentingPostProcessorTest
+{
+ private final static Map servlets = new HashMap<String,
MockFacesServletRegistration>();
+ final ClassLoader mockResourceLoader = new MockClassLoader();
+
+ @BeforeClass
+ @SuppressWarnings("unchecked")
+ public static void beforeClass()
+ {
+ servlets.put("Faces Servlet", new MockFacesServletRegistration());
+ }
+
+ private final Enumeration<String> initParameterNames =
Collections.enumeration(new ArrayList<String>());
+
+ @Test
+ public void testParseParentIds() throws Exception
+ {
+
+ final PrettyConfigBuilder builder = new PrettyConfigBuilder();
+ new DigesterPrettyConfigParser().parse(builder,
getClass().getClassLoader().getResourceAsStream("parenting-pretty-config.xml"));
+ PrettyConfig config = builder.build();
+
+ assertEquals("", config.getMappingById("parent").getParentId());
+ assertEquals("parent", config.getMappingById("child").getParentId());
+ assertEquals("child",
config.getMappingById("grandchild").getParentId());
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testParentIdInheritsPatterns() throws SAXException,
IOException
+ {
+ final ServletContext servletContext =
EasyMock.createNiceMock(ServletContext.class);
+
+
EasyMock.expect(servletContext.getMajorVersion()).andReturn(3).anyTimes();
+
EasyMock.expect(servletContext.getServletRegistrations()).andReturn(servlets).anyTimes();
+
EasyMock.expect(servletContext.getClassLoader()).andReturn(mockResourceLoader).anyTimes();
+
EasyMock.expect(servletContext.getInitParameterNames()).andReturn(initParameterNames).anyTimes();
+
EasyMock.expect(servletContext.getInitParameter(PrettyContext.CONFIG_KEY)).andReturn(null).anyTimes();
+
EasyMock.expect(servletContext.getInitParameter(ClassLoaderConfigurationProvider.CLASSPATH_CONFIG_ENABLED)).andReturn("false").anyTimes();
+
EasyMock.expect(servletContext.getResourceAsStream(DefaultXMLConfigurationProvider.DEFAULT_PRETTY_FACES_CONFIG)).andReturn(mockPrettyConfigInputStream()).anyTimes();
+
+ final PrettyConfigurator configurator = new
PrettyConfigurator(servletContext);
+ EasyMock.replay(servletContext);
+ configurator.configure();
+
+ final PrettyConfig config = configurator.getConfig();
+
+ assertEquals(3, config.getMappings().size());
+ assertEquals("/parent",
config.getMappingById("parent").getPattern());
+ assertEquals("/parent/child/#{name}",
config.getMappingById("child").getPattern());
+ assertEquals("/parent/child/#{name}/grandchild/#{gname}",
config.getMappingById("grandchild").getPattern());
+
+ assertEquals(2,
config.getMappingById("grandchild").getPathValidators().size());
+ assertEquals("validator1",
config.getMappingById("grandchild").getPathValidators().get(0).getValidatorIds());
+ assertEquals("validator2",
config.getMappingById("grandchild").getPathValidators().get(1).getValidatorIds());
+ assertEquals(0,
config.getMappingById("grandchild").getPathValidators().get(0).getIndex());
+ assertEquals(1,
config.getMappingById("grandchild").getPathValidators().get(1).getIndex());
+ }
+
+ private InputStream mockPrettyConfigInputStream()
+ {
+ return
getClass().getClassLoader().getResourceAsStream("parenting-pretty-config.xml");
+ }
+
+}
=======================================
--- /dev/null
+++ /prettyfaces/trunk/core/src/test/resources/META-INF/pretty-config.xml
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<pretty-config xmlns="
http://ocpsoft.com/prettyfaces/3.1.1"
+ xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
http://ocpsoft.com/prettyfaces/3.1.1
+
http://ocpsoft.com/xml/ns/prettyfaces/ocpsoft-pretty-faces-3.1.1.xsd">
+
+ <url-mapping id="0">
+ <pattern value="/project/#{viewProjectBean.projectId}/" />
+ <view-id>
+ #{viewProjectBean.getPrettyTarget}
+ </view-id>
+ <action>#{viewProjectBean.authorize}</action>
+ <action>#{viewProjectBean.load}</action>
+ </url-mapping>
+ <url-mapping id="1" onPostback="false">
+ <pattern value="/project/#{addProjectBean.projectName}/" />
+ <view-id>
+ #{addProjectBean.getPrettyTarget}
+ </view-id>
+ <action onPostback="false">#{addProjectBean.authorize}</action>
+ <action onPostback="true">#{addProjectBean.create}</action>
+ </url-mapping>
+ <url-mapping id="2">
+ <pattern value="/project/#{addProjectBean.projectName}/" />
+ <view-id>
+ #{addProjectBean.getPrettyTarget}
+ </view-id>
+ <action>#{addProjectBean.authorize}</action>
+ <action phaseId="ANY_PHASE">#{addProjectBean.create}
+ </action>
+ </url-mapping>
+ <url-mapping id="3">
+ <pattern value="/project/#{addProjectBean.projectName}/" />
+ <view-id>
+ #{addProjectBean.getPrettyTarget}
+ </view-id>
+ <action>#{addProjectBean.authorize}</action>
+ <action phaseId="RENDER_RESPONSE">#{addProjectBean.create}
+ </action>
+ </url-mapping>
+ <url-mapping id="4">
+ <pattern value="/project/#{deleteUserBean.projectName}/delete" />
+ <query-param name="user">#{deleteUserBean.userName}
+ </query-param>
+ <view-id>
+ #{deleteUserBean.getPrettyTarget}
+ </view-id>
+ <action phaseId="RENDER_RESPONSE">#{deleteUserBean.delete}
+ </action>
+ </url-mapping>
+ <url-mapping id="5">
+ <pattern value="/project/#{deleteUserBean.projectName}/delete" />
+ <query-param name="user" decode="false">#{deleteUserBean.userName}
+ </query-param>
+ <view-id>
+ #{deleteUserBean.getPrettyTarget}
+ </view-id>
+ </url-mapping>
+ <url-mapping id="6">
+ <pattern value="/project/#{searchUserBean.projectName}/search" />
+ <query-param name="name">#{searchUserBean.userName}
+ </query-param>
+ <query-param name="gender">#{searchUserBean.userGender}
+ </query-param>
+ <view-id>/faces/search.jsf</view-id>
+ <action phaseId="RENDER_RESPONSE">#{searchUserBean.search}
+ </action>
+ </url-mapping>
+ <url-mapping id="7">
+ <pattern value="/project/#{viewUserBean.projectName}/view" />
+ <view-id>/faces/search.jsf</view-id>
+ <action phaseId="RENDER_RESPONSE">#{viewUserBean.load}</action>
+ </url-mapping>
+ <url-mapping id="8">
+ <pattern value="/some-view" />
+ <view-id>/faces/some-view.jsf</view-id>
+ <query-param
name="withoutAttribute">#{someBean.someProperty}</query-param>
+ <query-param name="attributeSetToFalse"
onPostback="false">#{someBean.someProperty}</query-param>
+ <query-param name="attributeSetToTrue"
onPostback="true">#{someBean.someProperty}</query-param>
+ </url-mapping>
+
+ <!-- Begin non-ordered mappings -->
+ <url-mapping id="validate">
+ <pattern value="/validate/#{validationBean.pathInput}">
+ <validate index="0" validatorIds="validator1"
onError="#{validationBean.handle}" />
+ <validate index="1" validatorIds="validator2"
onError="#{validationBean.handle2}"
+ validator="#{validationBean.validateMethod}"/>
+ </pattern>
+ <query-param name="p" validatorIds="validator1 validator2"
+ onError="pretty:demo" validator="#{validationBean.validateMethod}">
+ #{validationBean.queryInput}
+ </query-param>
+ <view-id> /faces/validate.jsf </view-id>
+ </url-mapping>
+</pretty-config>
=======================================
--- /dev/null
+++ /prettyfaces/trunk/core/src/test/resources/parenting-pretty-config.xml
Thu Nov 4 13:06:12 2010
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<pretty-config xmlns="
http://ocpsoft.com/prettyfaces/3.1.1"
+ xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
http://ocpsoft.com/prettyfaces/3.1.1
+
http://ocpsoft.com/xml/ns/prettyfaces/ocpsoft-pretty-faces-3.1.1.xsd">
+
+ <url-mapping id="parent">
+ <pattern value="/parent" />
+ <view-id>/parent.jsf</view-id>
+ </url-mapping>
+
+ <url-mapping id="child" parentId="parent">
+ <pattern value="/child/#{name}">
+ <validate index="0" validatorIds="validator1"
+ onError="#{validationBean.handle}" />
+ </pattern>
+ <view-id>/child.jsf</view-id>
+ </url-mapping>
+
+ <url-mapping id="grandchild" parentId="child">
+ <pattern value="/grandchild/#{gname}">
+ <validate index="0" validatorIds="validator2"
+ onError="#{validationBean.handle2}"
validator="#{validationBean.validateMethod}" />
+ </pattern>
+ <view-id>/grandchild.jsf</view-id>
+ </url-mapping>
+
+</pretty-config>
=======================================
--- /prettyfaces/trunk/CHANGELOG.txt Thu Nov 4 09:47:36 2010
+++ /prettyfaces/trunk/CHANGELOG.txt Thu Nov 4 13:06:12 2010
@@ -2,6 +2,11 @@
VERSION 3.1.1
------------------------------------
+Major:
+
+* Added 'parentId' for Hierarchical Mappings in pretty-config.xml (#72)
+* Can now be run in a pure servlet environment (without JSF)
+
Features & Enhancements:
* Added 'onPostback' configuration parameter for query parameters (#24)
@@ -9,10 +14,12 @@
* Added 'pretty:location' client behavior
* Added 'onPostback' configuration parameter for path parameters (#24)
* New method PrettyContext.sendError() to send custom HTTP status codes
(#66)
+* Added SPI hooks for ConfigurationProvider and ConfigurationPostProcessor
Regression Impact:
* Changed some method signatures in PrettyContext
* PrettyFilter no longer wraps application exceptions in ServletException
+* PrettyException no longer extends javax.faces.FacesException
Bugfixes:
* Fixed compatibility with Java 1.5
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/PrettyException.java
Thu May 13 09:52:33 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/PrettyException.java
Thu Nov 4 13:06:12 2010
@@ -3,7 +3,7 @@
/*
* PrettyFaces is an OpenSource JSF library to create bookmarkable URLs.
*
- * Copyright (C) 2009 - Lincoln Baxter, III <
lin...@ocpsoft.com>
+ * Copyright (C) 2010 - Lincoln Baxter, III <
lin...@ocpsoft.com>
*
* This program is free software: you can redistribute it and/or modify it
under
* the terms of the GNU Lesser General Public License as published by the
Free Software
@@ -19,35 +19,31 @@
* this program. If not, see the file COPYING.LESSER or visit the GNU
website at
* <
http://www.gnu.org/licenses/>.
*/
-import javax.faces.FacesException;
/**
- * Extends FacesException to provide consistent exception behavior. This
is a
- * Faces extension, after all
- *
* @author Lincoln Baxter, III <
lin...@ocpsoft.com>
*/
-public class PrettyException extends FacesException
-{
- private static final long serialVersionUID = 1478911690378316003L;
-
- public PrettyException()
- {
- super();
- }
-
- public PrettyException(final String message, final Throwable cause)
- {
- super(message, cause);
- }
-
- public PrettyException(final String message)
- {
- super(message);
- }
-
- public PrettyException(final Throwable cause)
- {
- super(cause);
- }
-}
+public class PrettyException extends RuntimeException
+{
+ private static final long serialVersionUID = 1478911690378316003L;
+
+ public PrettyException()
+ {
+ super();
+ }
+
+ public PrettyException(final String message, final Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public PrettyException(final String message)
+ {
+ super(message);
+ }
+
+ public PrettyException(final Throwable cause)
+ {
+ super(cause);
+ }
+}
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/annotation/URLAction.java
Wed Jun 30 11:26:10 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/annotation/URLAction.java
Thu Nov 4 13:06:12 2010
@@ -7,8 +7,6 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import javax.faces.render.ResponseStateManager;
-
/**
* <p>
* Specifies an action method to be called after URL parameters have been
parsed
@@ -16,9 +14,9 @@
* </p>
* <p>
* If the class containing the action method is annotated with a
- * {@link URLMapping} annotation, the action will automatically be added to
- * this mapping. You can also add the action to a foreign mapping by
referencing
- * it with the <code>mappingId</code> attribute.
+ * {@link URLMapping} annotation, the action will automatically be added
to this
+ * mapping. You can also add the action to a foreign mapping by
referencing it
+ * with the <code>mappingId</code> attribute.
* </p>
* <p>
* You can use {@link URLActions} as a container if you want to add
multiple
@@ -33,34 +31,23 @@
@Target(ElementType.METHOD)
@Inherited
@Documented
-public @interface URLAction {
+public @interface URLAction
+{
/**
* <p>
* For use with {@link URLAction#phaseId()}
* </p>
*/
- public enum PhaseId {
-
- ANY_PHASE(javax.faces.event.PhaseId.ANY_PHASE),
- RESTORE_VIEW(javax.faces.event.PhaseId.RESTORE_VIEW),
- APPLY_REQUEST_VALUES(javax.faces.event.PhaseId.APPLY_REQUEST_VALUES),
- PROCESS_VALIDATIONS(javax.faces.event.PhaseId.PROCESS_VALIDATIONS),
- UPDATE_MODEL_VALUES(javax.faces.event.PhaseId.UPDATE_MODEL_VALUES),
- INVOKE_APPLICATION(javax.faces.event.PhaseId.INVOKE_APPLICATION),
- RENDER_RESPONSE(javax.faces.event.PhaseId.RENDER_RESPONSE);
-
- private final javax.faces.event.PhaseId phaseId;
-
- private PhaseId(javax.faces.event.PhaseId phaseId)
- {
- this.phaseId = phaseId;
- }
-
- public javax.faces.event.PhaseId getPhaseId()
- {
- return phaseId;
- }
+ public enum PhaseId
+ {
+ ANY_PHASE,
+ RESTORE_VIEW,
+ APPLY_REQUEST_VALUES,
+ PROCESS_VALIDATIONS,
+ UPDATE_MODEL_VALUES,
+ INVOKE_APPLICATION,
+ RENDER_RESPONSE;
}
/**
@@ -78,7 +65,6 @@
* not occur on form postback.
* </p>
*
- * @see
ResponseStateManager#isPostback(javax.faces.context.FacesContext)
*/
boolean onPostback() default true;
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/annotation/URLMapping.java
Sat Oct 2 01:13:11 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/annotation/URLMapping.java
Thu Nov 4 13:06:12 2010
@@ -24,7 +24,8 @@
@Target(ElementType.TYPE)
@Inherited
@Documented
-public @interface URLMapping {
+public @interface URLMapping
+{
/**
* Each {@link URLMapping} must specify a unique id.
@@ -50,6 +51,23 @@
*/
String pattern();
+ /**
+ * <p>
+ * Specify an optional parent {@link URLMapping#id()} from which this
mapping
+ * will inherit the base pattern, and path parameter validators.
+ * </p>
+ *
+ * <strong>For example:</strong>
+ *
+ * <pre>
+ * <url-mapping id="store"> <br/> <pattern
value="/store/" /> <br/> <~-- Result: /store/
--><br/>
<view-id>/faces/shop/store.jsf</view-id><br/></url-mapping><br/><br/><url-mapping
parentId="store" id="category"> <br/> <pattern
value="/#{category}" /> <br/> <~-- Result:
/store/#{category} --><br/>
<view-id>/faces/shop/category.jsf</view-id><br/></url-mapping><br/><br/><url-mapping
parentId="category" id="item"> <br/> <pattern
value="/#{item}" /> <br/> <~-- Result:
/store/#{category}/#{item} --><br/>
<view-id>/faces/shop/item.jsf</view-id><br/></url-mapping><br/><br/><url-mapping
parentId="category" id="sales"> <br/> <pattern
value="/sales" /> <br/> <~-- Result:
/store/#{category}/sales --><br/>
<view-id>/faces/shop/sales.jsf</view-id><br/></url-mapping>
+ * </pre>
+ *
+ *
+ *
+ */
+ String parentId() default "";
+
/**
* <p>
* Specify the JSF ViewId displayed by this mapping, by either calling
an EL
@@ -58,12 +76,12 @@
* required.
* </p>
* <p>
- * The ViewId may be any resource located within the current Servlet
- * Context: E.g. PrettyFaces can also forward to a non-Faces servlet.
+ * The ViewId may be any resource located within the current Servlet
Context:
+ * E.g. PrettyFaces can also forward to a non-Faces servlet.
* </p>
*/
String viewId();
-
+
/**
* <p>
* Specify any number of pattern validators for this mapping.
Validators may
@@ -76,7 +94,7 @@
* </p>
*/
URLValidator[] validation() default {};
-
+
/**
* Enable or disable outbound URL rewriting for this mapping
(default: 'true'
* / enabled.) If enabled, any links matching the viewId specified will
be
@@ -84,21 +102,22 @@
* specified in the pattern.
*/
boolean outbound() default true;
-
+
/**
* <p>
- * The name that can be used to access instances of this bean in EL
expressions.
- * Setting this attribute is equivalent to adding a {@link URLBeanName}
annotation
- * to the class.
+ * The name that can be used to access instances of this bean in EL
+ * expressions. Setting this attribute is equivalent to adding a
+ * {@link URLBeanName} annotation to the class.
* </p>
+ *
* @see URLBeanName
*/
String beanName() default "";
-
+
/**
* <p>
- * Optional boolean (default true), if set to <code>false</code>,
- * path parameters will not be injected on form postbacks.
+ * Optional boolean (default true), if set to <code>false</code>, path
+ * parameters will not be injected on form postbacks.
* </p>
*/
boolean onPostback() default true;
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/beans/ActionExecutor.java
Wed Jun 30 11:26:10 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/beans/ActionExecutor.java
Thu Nov 4 13:06:12 2010
@@ -29,6 +29,7 @@
import com.ocpsoft.pretty.faces.util.FacesElUtils;
import com.ocpsoft.pretty.faces.util.FacesMessagesUtils;
import com.ocpsoft.pretty.faces.util.FacesStateUtils;
+import com.ocpsoft.pretty.faces.util.PhaseIdComparator;
/**
* @author Lincoln Baxter, III <
lin...@ocpsoft.com>
@@ -74,7 +75,7 @@
boolean shouldExecute(final UrlAction action, final PhaseId
currentPhaseId, final boolean isPostback)
{
boolean result = false;
- if (currentPhaseId.equals(action.getPhaseId()) ||
PhaseId.ANY_PHASE.equals(action.getPhaseId()))
+ if (PhaseIdComparator.equals(action.getPhaseId(), currentPhaseId) ||
PhaseIdComparator.equals(action.getPhaseId(), PhaseId.ANY_PHASE))
{
if (action.onPostback())
{
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/DigesterPrettyConfigParser.java
Wed Aug 4 12:20:11 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/DigesterPrettyConfigParser.java
Thu Nov 4 13:06:12 2010
@@ -17,13 +17,12 @@
import java.io.IOException;
import java.io.InputStream;
-import javax.faces.event.PhaseId;
-
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;
+import com.ocpsoft.pretty.faces.annotation.URLAction.PhaseId;
import com.ocpsoft.pretty.faces.config.convert.CaseConverter;
import com.ocpsoft.pretty.faces.config.convert.PhaseIdConverter;
import com.ocpsoft.pretty.faces.config.convert.RedirectConverter;
@@ -42,94 +41,93 @@
*/
public class DigesterPrettyConfigParser implements PrettyConfigParser
{
-
- private final Converter caseConverter = new CaseConverter();
- private final Converter trailingSlashConverter = new
TrailingSlashConverter();
- private final Converter phaseIdConverter = new PhaseIdConverter();
- private final Converter redirectConverter = new RedirectConverter();
-
- public void parse(final PrettyConfigBuilder builder, final InputStream
resource) throws IOException, SAXException
- {
- if (builder == null)
- {
- throw new IllegalArgumentException("Builder must not be
null.");
- }
- if (resource == null)
- {
- throw new IllegalArgumentException("Input stream must not be
null.");
- }
- final Digester digester = configureDigester(new Digester());
-
- ConvertUtils.register(caseConverter, Case.class);
- ConvertUtils.register(trailingSlashConverter, TrailingSlash.class);
- ConvertUtils.register(phaseIdConverter, PhaseId.class);
- ConvertUtils.register(redirectConverter, Redirect.class);
-
- digester.push(builder);
- digester.parse(resource);
- }
-
- /**
- * Configure the digester. Assume that the builder object will be
pushed
- * after this method is called.
- */
- private Digester configureDigester(final Digester digester)
- {
-
- /*
- * We use the context class loader to resolve classes.
- * This fixes ClassNotFoundExceptions on Geronimo.
- */
- digester.setUseContextClassLoader(true);
-
- /*
- * Parse RewriteRules
- */
- digester.addObjectCreate("pretty-config/rewrite",
RewriteRule.class);
- digester.addSetProperties("pretty-config/rewrite");
- digester.addSetNext("pretty-config/rewrite", "addRewriteRule");
-
- /*
- * Create Mapping Object
- */
- digester.addObjectCreate("pretty-config/url-mapping",
UrlMapping.class);
- digester.addSetProperties("pretty-config/url-mapping");
-
digester.addCallMethod("pretty-config/url-mapping/pattern", "setPattern",
1);
- digester.addCallParam("pretty-config/url-mapping/pattern",
0, "value");
-
digester.addCallMethod("pretty-config/url-mapping/pattern", "setPattern",
0);
-
- /*
- * Parse Path Validators
- */
-
digester.addObjectCreate("pretty-config/url-mapping/pattern/validate",
PathValidator.class);
-
digester.addSetProperties("pretty-config/url-mapping/pattern/validate");
-
digester.addSetNext("pretty-config/url-mapping/pattern/validate", "addPathValidator");
-
- /*
- * Parse Query Params
- */
- digester.addObjectCreate("pretty-config/url-mapping/query-param",
QueryParameter.class);
- digester.addSetProperties("pretty-config/url-mapping/query-param");
-
digester.addCallMethod("pretty-config/url-mapping/query-param", "setExpression",
0);
-
digester.addSetNext("pretty-config/url-mapping/query-param", "addQueryParam");
-
- /*
- * Parse Action Methods
- */
- digester.addObjectCreate("pretty-config/url-mapping/action",
UrlAction.class);
- digester.addSetProperties("pretty-config/url-mapping/action");
-
digester.addCallMethod("pretty-config/url-mapping/action", "setAction", 0);
-
digester.addSetNext("pretty-config/url-mapping/action", "addAction");
-
- /*
- * Parse View Id
- */
-
digester.addCallMethod("pretty-config/url-mapping/view-id", "setViewId", 0);
-
- /*
- * Add Mapping to Builder
- */
- digester.addSetNext("pretty-config/url-mapping", "addMapping");
- return digester;
- }
-}
+ private final Converter caseConverter = new CaseConverter();
+ private final Converter trailingSlashConverter = new
TrailingSlashConverter();
+ private final Converter phaseIdConverter = new PhaseIdConverter();
+ private final Converter redirectConverter = new RedirectConverter();
+
+ public void parse(final PrettyConfigBuilder builder, final InputStream
resource) throws IOException, SAXException
+ {
+ if (builder == null)
+ {
+ throw new IllegalArgumentException("Builder must not be null.");
+ }
+ if (resource == null)
+ {
+ throw new IllegalArgumentException("Input stream must not be
null.");
+ }
+ final Digester digester = configureDigester(new Digester());
+
+ ConvertUtils.register(caseConverter, Case.class);
+ ConvertUtils.register(trailingSlashConverter, TrailingSlash.class);
+ ConvertUtils.register(phaseIdConverter, PhaseId.class);
+ ConvertUtils.register(redirectConverter, Redirect.class);
+
+ digester.push(builder);
+ digester.parse(resource);
+ }
+
+ /**
+ * Configure the digester. Assume that the builder object will be pushed
+ * after this method is called.
+ */
+ private Digester configureDigester(final Digester digester)
+ {
+
+ /*
+ * We use the context class loader to resolve classes. This fixes
+ * ClassNotFoundExceptions on Geronimo.
+ */
+ digester.setUseContextClassLoader(true);
+
+ /*
+ * Parse RewriteRules
+ */
+ digester.addObjectCreate("pretty-config/rewrite", RewriteRule.class);
+ digester.addSetProperties("pretty-config/rewrite");
+ digester.addSetNext("pretty-config/rewrite", "addRewriteRule");
+
+ /*
+ * Create Mapping Object
+ */
+ digester.addObjectCreate("pretty-config/url-mapping",
UrlMapping.class);
+ digester.addSetProperties("pretty-config/url-mapping");
+
digester.addCallMethod("pretty-config/url-mapping/pattern", "setPattern",
1);
+ digester.addCallParam("pretty-config/url-mapping/pattern",
0, "value");
+
digester.addCallMethod("pretty-config/url-mapping/pattern", "setPattern",
0);
+
+ /*
+ * Parse Path Validators
+ */
+
digester.addObjectCreate("pretty-config/url-mapping/pattern/validate",
PathValidator.class);
+
digester.addSetProperties("pretty-config/url-mapping/pattern/validate");
+
digester.addSetNext("pretty-config/url-mapping/pattern/validate", "addPathValidator");
+
+ /*
+ * Parse Query Params
+ */
+ digester.addObjectCreate("pretty-config/url-mapping/query-param",
QueryParameter.class);
+ digester.addSetProperties("pretty-config/url-mapping/query-param");
+
digester.addCallMethod("pretty-config/url-mapping/query-param", "setExpression",
0);
+
digester.addSetNext("pretty-config/url-mapping/query-param", "addQueryParam");
+
+ /*
+ * Parse Action Methods
+ */
+ digester.addObjectCreate("pretty-config/url-mapping/action",
UrlAction.class);
+ digester.addSetProperties("pretty-config/url-mapping/action");
+
digester.addCallMethod("pretty-config/url-mapping/action", "setAction", 0);
+ digester.addSetNext("pretty-config/url-mapping/action", "addAction");
+
+ /*
+ * Parse View Id
+ */
+
digester.addCallMethod("pretty-config/url-mapping/view-id", "setViewId", 0);
+
+ /*
+ * Add Mapping to Builder
+ */
+ digester.addSetNext("pretty-config/url-mapping", "addMapping");
+ return digester;
+ }
+}
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/PrettyConfigBuilder.java
Thu May 13 09:52:33 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/PrettyConfigBuilder.java
Thu Nov 4 13:06:12 2010
@@ -35,32 +35,41 @@
*/
public class PrettyConfigBuilder
{
- private final List<UrlMapping> mappings = new LinkedList<UrlMapping>();
- private final List<RewriteRule> rewriteRules = new
LinkedList<RewriteRule>();
-
- public void addMapping(final UrlMapping mapping)
- {
- if (mapping == null)
- {
- throw new IllegalArgumentException("Mapping must not be
null.");
- }
- mappings.add(mapping);
- }
-
- public void addRewriteRule(final RewriteRule rule)
- {
- if (rule == null)
- {
- throw new IllegalArgumentException("RewriteRule must not be
null.");
- }
- rewriteRules.add(rule);
- }
-
- public PrettyConfig build()
- {
- final PrettyConfig config = new PrettyConfig();
- config.setMappings(mappings);
- config.setGlobalRewriteRules(rewriteRules);
- return config;
- }
-}
+ private final List<UrlMapping> mappings = new LinkedList<UrlMapping>();
+ private final List<RewriteRule> rewriteRules = new
LinkedList<RewriteRule>();
+
+ public void addFromConfig(PrettyConfig config)
+ {
+ if (config != null)
+ {
+ mappings.addAll(config.getMappings());
+ rewriteRules.addAll(config.getGlobalRewriteRules());
+ }
+ }
+
+ public void addMapping(final UrlMapping mapping)
+ {
+ if (mapping != null)
+ {
+ mappings.add(mapping);
+ }
+ }
+
+ public void addRewriteRule(final RewriteRule rule)
+ {
+ if (rule != null)
+ {
+ rewriteRules.add(rule);
+ }
+ }
+
+ public PrettyConfig build()
+ {
+ final PrettyConfig config = new PrettyConfig();
+
+ config.setMappings(mappings);
+ config.setGlobalRewriteRules(rewriteRules);
+
+ return config;
+ }
+}
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/PrettyConfigurator.java
Mon Oct 18 09:56:19 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/PrettyConfigurator.java
Thu Nov 4 13:06:12 2010
@@ -1,6 +1,6 @@
/*
* PrettyFaces is an OpenSource JSF library to create bookmarkable URLs.
- * Copyright (C) 2009 - Lincoln Baxter, III <
lin...@ocpsoft.com> This
program
+ * Copyright (C) 2010 - Lincoln Baxter, III <
lin...@ocpsoft.com> This
program
* is free software: you can redistribute it and/or modify it under the
terms of
* the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any
later
@@ -13,77 +13,39 @@
*/
package com.ocpsoft.pretty.faces.config;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.ArrayList;
import java.util.Enumeration;
-import java.util.List;
-import java.util.StringTokenizer;
+import java.util.HashMap;
+import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.xml.sax.SAXException;
import com.ocpsoft.pretty.PrettyContext;
import com.ocpsoft.pretty.PrettyException;
import com.ocpsoft.pretty.faces.DynaviewEngine;
-import com.ocpsoft.pretty.faces.config.annotation.ClassFinder;
-import com.ocpsoft.pretty.faces.config.annotation.PackageFilter;
-import com.ocpsoft.pretty.faces.config.annotation.PrettyAnnotationHandler;
-import com.ocpsoft.pretty.faces.config.annotation.WebClassesFinder;
-import com.ocpsoft.pretty.faces.config.annotation.WebLibFinder;
-import com.ocpsoft.pretty.faces.config.mapping.UrlMapping;
import com.ocpsoft.pretty.faces.config.servlet.WebXmlParser;
-import com.ocpsoft.pretty.faces.el.LazyBeanNameFinder;
+import com.ocpsoft.pretty.faces.spi.ConfigurationPostProcessor;
+import com.ocpsoft.pretty.faces.spi.ConfigurationProvider;
+import com.ocpsoft.pretty.faces.util.ServiceLoader;
/**
- * Implements the Pretty Faces configuration procedure.
- * <p>
- * At application startup time, before any requests are processed, Pretty
Faces
- * processes zero or more configuration resources, located according to the
- * following algorithm:
- * </p>
- * <ul>
- * <li>Search for classpath resources named
- * <code>META-INF/pretty-config.xml</code> in the ServletContext resource
paths
- * for this web application, and load each as a configuration
resource.</li>
- * <li>Check for the existence of a context initialization parameter named
- * <code>com.ocpsoft.pretty.CONFIG_FILES</code>. If it exists, treat it as
a
- * comma-delimited list of context relative resource paths (starting with a
- * <code>/</code>), and load each of the specified resources.</li>
- * <li>Check for the existence of a web application configuration resource
named
- * <code>/WEB-INF/pretty-config.xml</code>, and load it if the resource
exists.</li>
- * </ul>
- *
- * @author Aleksei Valikov
* @author <a href="mailto:
lincol...@gmail.com>Lincoln Baxter, III</a>
+ * @author Aleksei Valikov
*/
public class PrettyConfigurator
{
private static final Log log =
LogFactory.getLog(PrettyConfigurator.class);
- public static final String CONFIG_BASE_PACKAGES
= "com.ocpsoft.pretty.BASE_PACKAGES";
- public static final String CONFIG_SCAN_LIB_DIR
= "com.ocpsoft.pretty.SCAN_LIB_DIRECTORY";
-
- public static final String PRETTY_CONFIG_RESOURCE
= "META-INF/pretty-config.xml";
- public static final String DEFAULT_PRETTY_FACES_CONFIG
= "/WEB-INF/pretty-config.xml";
-
private final ServletContext servletContext;
- private final PrettyConfigParser configParser = new
DigesterPrettyConfigParser();
private final WebXmlParser webXmlParser = new WebXmlParser();
private final DynaviewEngine dynaview = new DynaviewEngine();
private PrettyConfig config;
- /**
- * Loads the Pretty Faces configuration.
- */
public PrettyConfigurator(final ServletContext servletContext)
{
this.servletContext = servletContext;
@@ -94,16 +56,22 @@
try
{
final PrettyConfigBuilder builder = new PrettyConfigBuilder();
-
- feedClassLoaderConfigs(builder);
- feedContextSpecifiedConfig(builder);
- feedWebAppConfig(builder);
- feedAnnotationConfigs(builder);
+ Map<String, String> initParameterMap =
buildInitParameterMap(servletContext);
+
+ ServiceLoader<ConfigurationProvider> configLoader =
ServiceLoader.load(ConfigurationProvider.class);
+ for (ConfigurationProvider p : configLoader)
+ {
+ builder.addFromConfig(p.load(servletContext));
+ }
config = builder.build();
config.setDynaviewId(getFacesDynaViewId());
- validateConfig(config);
+ ServiceLoader<ConfigurationPostProcessor> postProcessors =
ServiceLoader.load(ConfigurationPostProcessor.class);
+ for (ConfigurationPostProcessor p : postProcessors)
+ {
+ config = p.process(config, initParameterMap);
+ }
log.trace("Setting config into ServletContext");
servletContext.setAttribute(PrettyContext.CONFIG_KEY, config);
@@ -114,13 +82,21 @@
}
}
- private void validateConfig(PrettyConfig config)
- {
- for (UrlMapping m : config.getMappings())
- {
- m.getPatternParser();
+ private Map<String, String> buildInitParameterMap(ServletContext
context)
+ {
+ Map<String, String> result = new HashMap<String, String>();
+
+ Enumeration<String> names = context.getInitParameterNames();
+
+ while ((names != null) && names.hasMoreElements())
+ {
+ String name = names.nextElement();
+ String value = context.getInitParameter(name);
+
+ result.put(name, value);
}
+ return result;
}
private String getFacesDynaViewId()
@@ -135,206 +111,6 @@
throw new PrettyException("Could not retrieve DynaViewId.", e);
}
}
-
- private void feedClassLoaderConfigs(final PrettyConfigBuilder builder)
throws IOException, SAXException
- {
- final Enumeration<URL> urls =
getResourceLoader().getResources(PRETTY_CONFIG_RESOURCE);
- if (urls != null)
- {
- while (urls.hasMoreElements())
- {
- final URL url = urls.nextElement();
- if (url != null)
- {
- InputStream is = null;
- try
- {
- is = openStream(url);
- configParser.parse(builder, is);
- }
- finally
- {
- if (is != null)
- {
- try
- {
- is.close();
- }
- catch (IOException ignored)
- {
-
- }
- }
-
- }
- }
- }
- }
- }
-
- private void feedContextSpecifiedConfig(final PrettyConfigBuilder
builder) throws IOException, SAXException
- {
- final List<String> configFilesList = getConfigFilesList();
- for (final String systemId : configFilesList)
- {
- final InputStream is =
servletContext.getResourceAsStream(systemId);
- if (is == null)
- {
- log.error("Pretty Faces config resource [" + systemId + "] not
found.");
- continue;
- }
-
- log.trace("Reading config [" + systemId + "].");
-
- try
- {
- configParser.parse(builder, is);
- }
- finally
- {
- try
- {
- is.close();
- }
- catch (IOException ignored)
- {
-
- }
- }
- }
- }
-
- private List<String> getConfigFilesList()
- {
- final String configFiles =
servletContext.getInitParameter(PrettyContext.CONFIG_KEY);
- final List<String> configFilesList = new ArrayList<String>();
- if (configFiles != null)
- {
- final StringTokenizer st = new StringTokenizer(configFiles, ",",
false);
- while (st.hasMoreTokens())
- {
- final String systemId = st.nextToken().trim();
-
- if (DEFAULT_PRETTY_FACES_CONFIG.equals(systemId))
- {
- log.warn("The file [" + DEFAULT_PRETTY_FACES_CONFIG + "]
has been specified in the [" + PrettyContext.CONFIG_KEY + "] context
parameter of " + "the deployment descriptor. This will automatically be
removed, " + " otherwise, it would be loaded twice.");
- }
- else
- {
- configFilesList.add(systemId);
- }
- }
- }
- return configFilesList;
- }
-
- private void feedWebAppConfig(final PrettyConfigBuilder builder) throws
IOException, SAXException
- {
-
- final InputStream is =
servletContext.getResourceAsStream(DEFAULT_PRETTY_FACES_CONFIG);
- if (is != null)
- {
- log.trace("Reading config [" + DEFAULT_PRETTY_FACES_CONFIG
+ "].");
-
- try
- {
- configParser.parse(builder, is);
- }
- finally
- {
- try
- {
- is.close();
- }
- catch (IOException ignored)
- {
-
- }
- }
- }
- }
-
- /**
- * Method to process the PrettyFaces configuration via annotations.
- *
- * @param builder The builder to add mappings to
- */
- private void feedAnnotationConfigs(final PrettyConfigBuilder builder)
- {
-
- // get package filter configuration
- String filterConfig =
servletContext.getInitParameter(CONFIG_BASE_PACKAGES);
-
- // annotation scanning disabled?
- if ((filterConfig != null) &&
filterConfig.trim().equalsIgnoreCase("none"))
- {
- log.debug("Annotation scanning has is disabled!");
- return;
- }
-
- // build package filter
- PackageFilter packageFilter = new PackageFilter(filterConfig);
-
- // instance of the LazyBeanNameFinder used by LazyExpressions
- LazyBeanNameFinder beanNameFinder = new
LazyBeanNameFinder(servletContext);
-
- // handler class to process class found via ClassFinder
implementations
- PrettyAnnotationHandler annotationHandler = new
PrettyAnnotationHandler(beanNameFinder);
-
- // ClassLoader used by finder implementations
- ClassLoader classloader =
Thread.currentThread().getContextClassLoader();
- if (classloader == null)
- {
- classloader = this.getClass().getClassLoader();
- }
-
- // list of ClassFinders to use for the scanning process
- List<ClassFinder> classFinders = new ArrayList<ClassFinder>();
-
- // we will always scan /WEB-INF/classes
- classFinders.add(new WebClassesFinder(servletContext, classloader,
packageFilter));
-
- // does the user want to scan /WEB-INF/lib ?
- String jarConfig =
servletContext.getInitParameter(CONFIG_SCAN_LIB_DIR);
- if ((jarConfig != null) && jarConfig.trim().equalsIgnoreCase("true"))
- {
- classFinders.add(new WebLibFinder(servletContext, classloader,
packageFilter));
- }
-
- // run finders
- for (ClassFinder finder : classFinders)
- {
- finder.findClasses(annotationHandler);
- }
-
- // finally build mapping
- annotationHandler.build(builder);
- }
-
- /**
- * Return class loader to be used to resolve resources.
- *
- * @return Class loader to be used to resolve resources
- */
- protected ClassLoader getResourceLoader()
- {
- final ClassLoader resourceLoader =
Thread.currentThread().getContextClassLoader();
- return resourceLoader;
- }
-
- /**
- * Opens an input stream for the given URL.
- *
- * @param url target URL.
- * @return Opened input stream.
- * @throws IOException If connection could not be opened.
- */
- protected InputStream openStream(final URL url) throws IOException
- {
- final URLConnection connection = url.openConnection();
- connection.setUseCaches(false);
- return connection.getInputStream();
- }
public PrettyConfig getConfig()
{
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/annotation/PrettyAnnotationHandler.java
Sat Oct 2 01:13:11 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/annotation/PrettyAnnotationHandler.java
Thu Nov 4 13:06:12 2010
@@ -11,12 +11,12 @@
import org.apache.commons.logging.LogFactory;
import com.ocpsoft.pretty.faces.annotation.URLAction;
+import com.ocpsoft.pretty.faces.annotation.URLAction.PhaseId;
import com.ocpsoft.pretty.faces.annotation.URLActions;
import com.ocpsoft.pretty.faces.annotation.URLBeanName;
import com.ocpsoft.pretty.faces.annotation.URLMapping;
import com.ocpsoft.pretty.faces.annotation.URLQueryParameter;
import com.ocpsoft.pretty.faces.annotation.URLValidator;
-import com.ocpsoft.pretty.faces.annotation.URLAction.PhaseId;
import com.ocpsoft.pretty.faces.config.PrettyConfigBuilder;
import com.ocpsoft.pretty.faces.config.mapping.PathValidator;
import com.ocpsoft.pretty.faces.config.mapping.QueryParameter;
@@ -74,8 +74,7 @@
* method must be called for every class that should be scanner before
* finally calling {@link #build(PrettyConfigBuilder)}.
*
- * @param clazz
- * The class to scan
+ * @param clazz The class to scan
*/
public void processClass(Class clazz)
{
@@ -120,8 +119,7 @@
/**
* Checks the class for a {@link URLMapping} annotation.
*
- * @param clazz
- * Class to scan
+ * @param clazz Class to scan
* @return The mapping ID or <code>null</code> if no mapping was found
*/
private String processPrettyMappingAnnotation(Class clazz)
@@ -143,6 +141,7 @@
// create UrlMapping from annotation
UrlMapping mapping = new UrlMapping();
mapping.setId(mappingAnnotation.id());
+ mapping.setParentId(mappingAnnotation.parentId());
mapping.setPattern(mappingAnnotation.pattern());
mapping.setViewId(mappingAnnotation.viewId());
mapping.setOutbound(mappingAnnotation.outbound());
@@ -156,9 +155,9 @@
{
throw new IllegalArgumentException("Duplicated mapping id: " +
mapping.getId());
}
-
+
// At bean name to lookup map if it has been specified
- if (mappingAnnotation.beanName() != null &&
mappingAnnotation.beanName().length() > 0)
+ if ((mappingAnnotation.beanName() != null) &&
(mappingAnnotation.beanName().length() > 0))
{
beanNameMap.put(clazz, mappingAnnotation.beanName());
}
@@ -179,16 +178,16 @@
pathValidator.setIndex(validationAnnotation.index());
pathValidator.setOnError(validationAnnotation.onError());
pathValidator.setValidatorIds(join(validationAnnotation.validatorIds(), " "));
-
+
// optional validator method
if (!isBlank(validationAnnotation.validator()))
{
pathValidator.setValidatorExpression(new
ConstantExpression(validationAnnotation.validator()));
}
-
+
// add PathValidator to the mapping
mapping.getPathValidators().add(pathValidator);
-
+
}
// return mapping id
@@ -203,8 +202,7 @@
/**
* Checks the class for a {@link URLBeanName} annotation.
*
- * @param clazz
- * Class to scan
+ * @param clazz Class to scan
*/
private void processPrettyBeanAnnotation(Class clazz)
{
@@ -230,13 +228,11 @@
}
/**
- * Searches for {@link URLAction} or {@link URLActions} annotations on
- * a method.
+ * Searches for {@link URLAction} or {@link URLActions} annotations on a
+ * method.
*
- * @param method
- * Method to scan
- * @param classMappingId
- * The mapping ID of the class this method belongs to
+ * @param method Method to scan
+ * @param classMappingId The mapping ID of the class this method
belongs to
*/
private void processMethodAnnotations(Method method, String
classMappingId)
{
@@ -263,10 +259,8 @@
/**
* Searches for {@link URLQueryParameter} annotations on a single field.
*
- * @param field
- * Field to scan
- * @param classMappingId
- * The mapping ID of the class this method belongs to
+ * @param field Field to scan
+ * @param classMappingId The mapping ID of the class this method
belongs to
*/
private void processFieldAnnotations(Field field, String classMappingId)
{
@@ -328,12 +322,9 @@
* Creates a {@link UrlAction} object from the supplied {@link
URLAction}
* annotation
*
- * @param actionAnnotation
- * The annotation
- * @param method
- * The method that was annotated
- * @param classMappingId
- * the mapping ID of the current class
+ * @param actionAnnotation The annotation
+ * @param method The method that was annotated
+ * @param classMappingId the mapping ID of the current class
*/
private void processPrettyActionAnnotation(URLAction actionAnnotation,
Method method, String classMappingId)
{
@@ -372,14 +363,13 @@
/**
* Returns <code>true</code> for "blank" strings.
*
- * @param str
- * Input string
+ * @param str Input string
* @return <code>true</code> if string is <code>null</code> or trimmed
value
* is empty
*/
private static boolean isBlank(String str)
{
- return str == null || str.trim().length() == 0;
+ return (str == null) || (str.trim().length() == 0);
}
/**
@@ -387,8 +377,7 @@
* {@link PrettyConfigBuilder}. It should be called after all classes
has
* been scanned via {@link #processClass(Class)}.
*
- * @param builder
- * The builder to add the mappings to
+ * @param builder The builder to add the mappings to
*/
public void build(PrettyConfigBuilder builder)
{
@@ -403,6 +392,7 @@
/*
* Fail for unresolved mappings. This may happen when the user
places
* invalid mapping IDs in the mappingId attribute of
+ *
* @URLAction or @URLQueryParameter
*/
if (mapping == null)
@@ -414,7 +404,7 @@
// build UrlMapping
UrlAction urlAction = new UrlAction();
- urlAction.setPhaseId(actionSpec.getPhaseId().getPhaseId());
+ urlAction.setPhaseId(actionSpec.getPhaseId());
urlAction.setOnPostback(actionSpec.isOnPostback());
// try to get bean name
@@ -461,7 +451,7 @@
{
queryParam.setValidatorExpression(new
ConstantExpression(queryParamSpec.getValidator()));
}
-
+
// try to get bean name
Class<?> clazz = queryParamSpec.getOwnerClass();
@@ -492,10 +482,8 @@
* Creates a {@link PrettyExpression} for a class and component. This
method
* may return a {@link ConstantExpression} or a {@link LazyExpression}.
*
- * @param clazz
- * The class of the bean
- * @param component
- * the component (property or method name)
+ * @param clazz The class of the bean
+ * @param component the component (property or method name)
* @return The expression
*/
private PrettyExpression buildPrettyExpression(Class<?> clazz, String
component)
@@ -539,16 +527,15 @@
/**
* Joins the list of values.
*
- * @param values
- * values to join
- * @param separator
- * the separator to use
+ * @param values values to join
+ * @param separator the separator to use
* @return joined list of values
*/
private static String join(String[] values, String separator)
{
StringBuilder result = new StringBuilder();
- if(values != null) {
+ if (values != null)
+ {
for (int i = 0; i < values.length; i++)
{
if (i > 0)
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/convert/CaseConverter.java
Thu May 13 09:52:33 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/convert/CaseConverter.java
Thu Nov 4 13:06:12 2010
@@ -21,13 +21,13 @@
public class CaseConverter implements Converter
{
- @SuppressWarnings("unchecked")
- public Object convert(final Class type, final Object value)
- {
- if (value instanceof String)
- {
- return Enum.valueOf(Case.class, ((String)
value).toUpperCase());
- }
- throw new ConversionException("Could not convert value: [" + value
+ "] to Case type.");
- }
-}
+ @SuppressWarnings("rawtypes")
+ public Object convert(final Class type, final Object value)
+ {
+ if (value instanceof String)
+ {
+ return Enum.valueOf(Case.class, ((String) value).toUpperCase());
+ }
+ throw new ConversionException("Could not convert value: [" + value
+ "] to Case type.");
+ }
+}
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/convert/PhaseIdConverter.java
Thu May 13 09:52:33 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/convert/PhaseIdConverter.java
Thu Nov 4 13:06:12 2010
@@ -14,45 +14,45 @@
package com.ocpsoft.pretty.faces.config.convert;
-import javax.faces.event.PhaseId;
-
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.Converter;
+import com.ocpsoft.pretty.faces.annotation.URLAction.PhaseId;
+
public class PhaseIdConverter implements Converter
{
- @SuppressWarnings("unchecked")
- public Object convert(final Class type, final Object value)
- {
- PhaseId result = null;
- if ("ANY_PHASE".equals(value))
- {
- result = PhaseId.ANY_PHASE;
- }
- else if ("APPLY_REQUEST_VALUES".equals(value))
- {
- result = PhaseId.APPLY_REQUEST_VALUES;
- }
- else if ("PROCESS_VALIDATIONS".equals(value))
- {
- result = PhaseId.PROCESS_VALIDATIONS;
- }
- else if ("UPDATE_MODEL_VALUES".equals(value))
- {
- result = PhaseId.UPDATE_MODEL_VALUES;
- }
- else if ("INVOKE_APPLICATION".equals(value))
- {
- result = PhaseId.INVOKE_APPLICATION;
- }
- else if ("RENDER_RESPONSE".equals(value))
- {
- result = PhaseId.RENDER_RESPONSE;
- }
- else
- {
- throw new ConversionException("Could not convert value: [" +
value + "] to PhaseId type.");
- }
- return result;
- }
-}
+ @SuppressWarnings("rawtypes")
+ public Object convert(final Class type, final Object value)
+ {
+ PhaseId result = null;
+ if ("ANY_PHASE".equals(value))
+ {
+ result = PhaseId.ANY_PHASE;
+ }
+ else if ("APPLY_REQUEST_VALUES".equals(value))
+ {
+ result = PhaseId.APPLY_REQUEST_VALUES;
+ }
+ else if ("PROCESS_VALIDATIONS".equals(value))
+ {
+ result = PhaseId.PROCESS_VALIDATIONS;
+ }
+ else if ("UPDATE_MODEL_VALUES".equals(value))
+ {
+ result = PhaseId.UPDATE_MODEL_VALUES;
+ }
+ else if ("INVOKE_APPLICATION".equals(value))
+ {
+ result = PhaseId.INVOKE_APPLICATION;
+ }
+ else if ("RENDER_RESPONSE".equals(value))
+ {
+ result = PhaseId.RENDER_RESPONSE;
+ }
+ else
+ {
+ throw new ConversionException("Could not convert value: [" +
value + "] to FacesPhaseId type.");
+ }
+ return result;
+ }
+}
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/convert/RedirectConverter.java
Thu May 13 09:52:33 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/convert/RedirectConverter.java
Thu Nov 4 13:06:12 2010
@@ -21,7 +21,7 @@
public class RedirectConverter implements Converter
{
- @SuppressWarnings("unchecked")
+ @SuppressWarnings("rawtypes")
public Object convert(final Class type, final Object value)
{
if (value instanceof String)
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/convert/TrailingSlashConverter.java
Thu May 13 09:52:33 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/convert/TrailingSlashConverter.java
Thu Nov 4 13:06:12 2010
@@ -21,13 +21,13 @@
public class TrailingSlashConverter implements Converter
{
- @SuppressWarnings("unchecked")
- public Object convert(final Class type, final Object value)
- {
- if (value instanceof String)
- {
- return Enum.valueOf(TrailingSlash.class, ((String)
value).toUpperCase());
- }
- throw new ConversionException("Could not convert value: [" + value
+ "] to TrailingSlash type.");
- }
-}
+ @SuppressWarnings("rawtypes")
+ public Object convert(final Class type, final Object value)
+ {
+ if (value instanceof String)
+ {
+ return Enum.valueOf(TrailingSlash.class, ((String)
value).toUpperCase());
+ }
+ throw new ConversionException("Could not convert value: [" + value
+ "] to TrailingSlash type.");
+ }
+}
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/mapping/UrlAction.java
Wed Jun 30 11:26:10 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/mapping/UrlAction.java
Thu Nov 4 13:06:12 2010
@@ -13,8 +13,7 @@
*/
package com.ocpsoft.pretty.faces.config.mapping;
-import javax.faces.event.PhaseId;
-
+import com.ocpsoft.pretty.faces.annotation.URLAction.PhaseId;
import com.ocpsoft.pretty.faces.el.ConstantExpression;
import com.ocpsoft.pretty.faces.el.PrettyExpression;
@@ -38,8 +37,7 @@
* Creates a new {@link UrlAction} and creates a {@link
ConstantExpression}
* for the supplied EL method binding
*
- * @param action
- * String representation of the EL action method
+ * @param action String representation of the EL action method
*/
public UrlAction(final String action)
{
@@ -50,22 +48,19 @@
* Creates a new {@link UrlAction} and initialize it with the supplied
* {@link PrettyExpression}
*
- * @param action
- * The expression
+ * @param action The expression
*/
public UrlAction(final PrettyExpression action)
{
- this.action = action;
+ this.action = action;
}
/**
* Creates a new {@link UrlAction} and creates a {@link
ConstantExpression}
* for the supplied EL method binding
*
- * @param action
- * String representation of the EL action method
- * @param phaseId
- * Phase ID to set
+ * @param action String representation of the EL action method
+ * @param phaseId Phase ID to set
*/
public UrlAction(final String action, final PhaseId phaseId)
{
@@ -100,13 +95,14 @@
public void setAction(final PrettyExpression action)
{
- this.action = action;
- }
-
+ this.action = action;
+ }
+
/**
- * Extra setter method creating a {@link ConstantExpression}.
- * Used only for Digester only.
- * @param action String representation of the EL expression
+ * Extra setter method creating a {@link ConstantExpression}. Used only
for
+ * Digester only.
+ *
+ * @param action String representation of the EL expression
*/
public void setAction(final String action)
{
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/mapping/UrlMapping.java
Sat Oct 2 01:13:11 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/mapping/UrlMapping.java
Thu Nov 4 13:06:12 2010
@@ -27,6 +27,7 @@
public class UrlMapping
{
private String id = "";
+ private String parentId = "";
private boolean outbound = true;
private String viewId = "";
private List<UrlAction> actions = new ArrayList<UrlAction>();
@@ -34,6 +35,8 @@
private List<QueryParameter> queryParams = new
ArrayList<QueryParameter>();
private List<PathValidator> pathValidators = new
ArrayList<PathValidator>();
private boolean onPostback = true;
+ private URLPatternParser parser;
+ private boolean dirty = true;
public static final Comparator<UrlMapping> ORDINAL_COMPARATOR = new
Comparator<UrlMapping>()
{
@@ -51,8 +54,6 @@
}
};
- private URLPatternParser parser;
-
/**
* Return whether or not this Mapping requires DynaView capabilities
*
@@ -68,6 +69,10 @@
*/
public URLPatternParser getPatternParser()
{
+ if (((parser == null) || dirty) && (pattern != null))
+ {
+ this.parser = new URLPatternParser(pattern);
+ }
return parser;
}
@@ -161,7 +166,7 @@
public void setPattern(final String pattern)
{
this.pattern = pattern;
- this.parser = new URLPatternParser(pattern);
+ this.dirty = true;
}
public boolean addQueryParam(final QueryParameter param)
@@ -221,7 +226,7 @@
@Override
public String toString()
{
- return "UrlMapping [ " + "id=" + id + ", pattern=" + pattern + ",
viewId=" + viewId + ", actions=" + actions + ", outbound=" + outbound + ",
parser=" + parser + ", pathValidators=" + pathValidators + ", queryParams="
+ queryParams + "]";
+ return "UrlMapping [ " + "id=" + id + ", pattern=" + pattern + ",
parentId=" + parentId + ", viewId=" + viewId + ", actions=" + actions + ",
outbound=" + outbound + ", parser=" + parser + ", pathValidators=" +
pathValidators + ", queryParams=" + queryParams + "]";
}
public boolean isOutbound()
@@ -243,4 +248,19 @@
{
this.onPostback = onPostback;
}
-}
+
+ public String getParentId()
+ {
+ return parentId;
+ }
+
+ public void setParentId(String parentId)
+ {
+ this.parentId = parentId;
+ }
+
+ public boolean hasParent()
+ {
+ return (parentId != null) && !"".equals(parentId.trim());
+ }
+}
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/servlet/WebXmlParser.java
Thu Nov 4 09:47:36 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/config/servlet/WebXmlParser.java
Thu Nov 4 13:06:12 2010
@@ -28,7 +28,6 @@
import org.apache.commons.logging.LogFactory;
import org.xml.sax.SAXException;
-import com.ocpsoft.pretty.PrettyException;
import com.ocpsoft.pretty.faces.config.PrettyConfigParser;
import com.ocpsoft.pretty.faces.util.EmptyEntityResolver;
@@ -69,7 +68,7 @@
if (facesMapping == null)
{
- throw new PrettyException("Faces Servlet
(javax.faces.webapp.FacesServlet) not found in web context - cannot
configure PrettyFaces.");
+ log.warn("Faces Servlet (javax.faces.webapp.FacesServlet) not
found in web context - cannot configure PrettyFaces DynaView");
}
}
else
@@ -77,7 +76,7 @@
InputStream in = context.getResourceAsStream(WEB_XML_PATH);
if (in == null)
{
- throw new PrettyException("No " + WEB_XML_PATH + " found -
cannot configure PrettyFaces");
+ log.warn("No " + WEB_XML_PATH + " found - cannot configure
PrettyFaces DynaView");
}
WebXml webXml = new WebXml();
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/el/LazyBeanNameFinder.java
Fri Oct 15 15:52:28 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/el/LazyBeanNameFinder.java
Thu Nov 4 13:06:12 2010
@@ -75,9 +75,7 @@
{
resolvers.add(resolver);
}
-
- }
-
+ }
}
/**
=======================================
---
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/url/URLPatternParser.java
Tue Oct 19 09:11:21 2010
+++
/prettyfaces/trunk/core/src/main/java/com/ocpsoft/pretty/faces/url/URLPatternParser.java
Thu Nov 4 13:06:12 2010
@@ -283,4 +283,9 @@
{
return pathParameters.size();
}
-}
+
+ public Object getPattern()
+ {
+ return originalPattern;
+ }
+}
=======================================
---
/prettyfaces/trunk/core/src/main/resources/META-INF/ocpsoft-pretty-faces-3.1.1.xsd
Sat Oct 2 01:13:11 2010
+++
/prettyfaces/trunk/core/src/main/resources/META-INF/ocpsoft-pretty-faces-3.1.1.xsd
Thu Nov 4 13:06:12 2010
@@ -43,324 +43,322 @@
</xs:complexType>
<xs:complexType name="url-mapping">
- <xs:annotation>
- <xs:documentation>
- A PrettyFaces URL Mapping.
- </xs:documentation>
- </xs:annotation>
- <xs:sequence>
- <xs:element name="pattern" minOccurs="1" maxOccurs="1">
- <xs:annotation>
- <xs:documentation>
- Specify the pattern for which this URL will be
- matched.
-
- Any EL expressions #{someBean.paramName} found
- within the pattern will be processed as value
- injections. The URL will be parsed and the value
- found at the location of the EL expression will
- be injected into the location specified in that
- EL expression. Note: EL expressions will not
- match over the ‘/’ character.
-
- Additionally, each expression may specify a
- name, or only a name:
- #{myParam:someBean.paramName}, #{myParam} - this
- provides parameter access to non-JSF
- applications by adding the extracted value to
- the HttpServletRequest property Map.
-
- In order to take advantage of outbound-URL
- rewriting, the parameter name specified must
- match the parameter name used internally in the
- application.
- </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:annotation>
- <xs:documentation>
-
- The pattern for which this url-mapping will match and filter incoming
requests, and the pattern with which to generate outbound
links.</xs:documentation>
- </xs:annotation>
- <xs:sequence>
- <xs:element minOccurs="0" name="validate"
- maxOccurs="unbounded">
- <xs:annotation>
- <xs:documentation>
- Specify any number of pattern
- validators for this mapping.
- Validators may be attached to
- individual parameters in each
- dynamic URL.
- </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:annotation>
- <xs:documentation>A pattern
- validator for this mapping.
- Validators may be attached to
- individual parameters in each
- dynamic URL.</xs:documentation>
- </xs:annotation>
- <xs:attribute name="index"
- type="xs:int" use="required">
- <xs:annotation>
- <xs:documentation>
- The value index of the
- pattern on which this
- validator will operate.
-
- Eg:
-
- <pattern
-
value="/validate/#{validationBean.pathInput}/#{validationBean.pathInput2}">
- <validate index="0"
- validatorIds="validator1" />
- <validate index="1"
- validatorIds="validator2" />
- </pattern>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="validatorIds"
- type="xs:string">
- <xs:annotation>
- <xs:documentation>
- The IDs of the JSF Validator
- objects to attach and
- process before bean value
- injection.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="validator"
- type="xs:string">
- <xs:annotation>
- <xs:documentation>
- The validation method used to
- check the value before bean
- value injection.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="onError"
- type="xs:string">
- <xs:annotation>
- <xs:documentation>
- The pretty:mappingId or
- #{bean.method} to evaluate,
- should validation fail.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="value" use="required">
- <xs:annotation>
- <xs:documentation>Specify the pattern for which
this URL will be
- matched.
-
- Any EL expressions #{someBean.paramName} found
- within the pattern will be processed as value
- injections. The URL will be parsed and the value
- found at the location of the EL expression will
- be injected into the location specified in that
- EL expression. Note: EL expressions will not
- match over the ‘/’ character.
-
- Additionally, each expression may specify a
- name, or only a name:
- #{myParam:someBean.paramName}, #{myParam} - this
- provides parameter access to non-JSF
- applications by adding the extracted value to
- the HttpServletRequest property Map.
-
- In order to take advantage of outbound-URL
- rewriting, the parameter name specified must
- match the parameter name used internally in the
- application.</xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:string">
- <xs:whiteSpace value="collapse"></xs:whiteSpace>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="query-param" minOccurs="0"
- maxOccurs="unbounded">
- <xs:annotation>
- <xs:documentation>
- Defines a managed query parameter of the form
-
http://site.com/url?key=somevalue, where if the
- parameter exists, the value will be injected
- into the specified managed bean. This also
- handles JSF commandLink and AJAX <f:param>
- values.
- </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:annotation>
- <xs:documentation>
- Defines a managed query parameter of the form
-
http://site.com/url?key=somevalue, where if the
- parameter exists, the value will be injected
- into the specified managed bean. This also
- handles JSF commandLink and AJAX
- &lt;f:param&gt; values.
- </xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute name="name" use="required">
- <xs:annotation>
- <xs:documentation>
- The managed parameter name. This value
- corresponds to the named key
- HttpServletRequest.getRequestParameter(...)
- when extracting HTTP Request
- Parameters.
- </xs:documentation>
- </xs:annotation>
- <xs:simpleType>
- <xs:restriction base="xs:string"></xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="onPostback"
- type="xs:boolean">
- <xs:annotation>
- <xs:documentation>
- Optional boolean (default true), if
- set to false this query parameter will
- not be injected on form postbacks.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="onError"
- type="xs:string">
- <xs:annotation>
- <xs:documentation>
- The pretty:mappingId or #{bean.method}
- to evaluate, should validation fail.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="validatorIds"
- type="xs:string">
- <xs:annotation>
- <xs:documentation>
- The IDs of the JSF Validator objects
- to attach and process before bean
- value injection.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="validator"
- type="xs:string">
- <xs:annotation>
- <xs:documentation>
- The validation method used to
- check the value before bean
- value injection.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- </xs:element>
- <xs:element name="view-id" type="xs:string" minOccurs="1"
- maxOccurs="1">
- <xs:annotation>
- <xs:documentation>
- Specify the URI displayed by this mapping, by
- either calling an el Method (must return an
- object for which the toString() method will
- return the view Id) or by returning a literal
- String value. The ViewId may be any resource
- located within the current Servlet Context: E.g.
- PrettyFaces can also forward to a non-Faces
- servlet.
- </xs:documentation>
- </xs:annotation>
- </xs:element>
- <xs:element name="action" minOccurs="0"
- maxOccurs="unbounded">
- <xs:annotation>
- <xs:documentation>
- Specify an action method to be called after URL
- parameters have been parsed and assigned into
- beans.
- </xs:documentation>
- </xs:annotation>
- <xs:complexType>
- <xs:annotation>
- <xs:documentation>an action method to be called after
URL
- parameters have been parsed and assigned into
- beans.</xs:documentation></xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute name="phaseId">
- <xs:simpleType>
- <xs:restriction base="xs:string">
- <xs:enumeration
- value="RESTORE_VIEW" />
- <xs:enumeration
- value="APPLY_REQUEST_VALUES" />
- <xs:enumeration
- value="PROCESS_VALIDATIONS" />
- <xs:enumeration
- value="UPDATE_MODEL_VALUES" />
- <xs:enumeration
- value="INVOKE_APPLICATION" />
- <xs:enumeration
- value="RENDER_RESPONSE" />
- <xs:enumeration
- value="ANY_PHASE" />
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="onPostback"
- type="xs:boolean">
- </xs:attribute>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="id" type="xs:string">
- <xs:annotation>
- <xs:documentation>
- The unique identifier by which this url-mapping will
- be referenced in the application (e.g.: link
- components, navigation outcomes, etc...)
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="outbound" type="xs:boolean">
- <xs:annotation>
- <xs:documentation>Enable or disable outbound URL rewriting for this
mapping (default: 'true' / enabled.) If enabled, any links matching the
viewId specified will be rewritten (if possible) using parameters mapping
to named path parameters specified in the pattern.
-
-Eg, given the following mapping:
-<url-mapping id="singleItem" outbound="true">
-<pattern
value="/store/#{cat:catBean.category}/#{pid:productBean.productId}" />
-<viewId>/faces/store/viewProduct.jsf</viewId>
-</url-mapping>
-
-The following outbound rewrite will occur:
-/faces/product/viewProduct.jsf?cat=foods&pid=1234 =>
/store/foods/1234</xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="onPostback" type="xs:boolean">
- <xs:annotation>
- <xs:documentation>
- Optional boolean (default true), if set to false path parameters will
- not be injected on form postbacks.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
+ <xs:annotation>
+ <xs:documentation>
+ A PrettyFaces URL Mapping.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="pattern" minOccurs="1" maxOccurs="1">
+ <xs:annotation>
+ <xs:documentation>
+ Specify the pattern for which this URL will be
+ matched.
+
+ Any EL expressions #{someBean.paramName} found within
+ the pattern will be processed as value injections.
+ The URL will be parsed and the value found at the
+ location of the EL expression will be injected into
+ the location specified in that EL expression. Note:
+ EL expressions will not match over the ‘/’ character.
+
+ Additionally, each expression may specify a name, or
+ only a name: #{myParam:someBean.paramName},
+ #{myParam} - this provides parameter access to
+ non-JSF applications by adding the extracted value to
+ the HttpServletRequest property Map.
+
+ In order to take advantage of outbound-URL rewriting,
+ the parameter name specified must match the parameter
+ name used internally in the application.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:annotation>
+ <xs:documentation>
+
+ The pattern for which this url-mapping will match
+ and filter incoming requests, and the pattern with
+ which to generate outbound links.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element minOccurs="0" name="validate"
+ maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>
+ Specify any number of pattern validators for
+ this mapping. Validators may be attached to
+ individual parameters in each dynamic URL.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:annotation>
+ <xs:documentation>
+ A pattern validator for this mapping.
+ Validators may be attached to individual
+ parameters in each dynamic URL.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:attribute name="index" type="xs:int"
+ use="required">
+ <xs:annotation>
+ <xs:documentation>
+ The value index of the pattern on
+ which this validator will operate.
+
+ Eg:
+
+ <pattern
+
value="/validate/#{validationBean.pathInput}/#{validationBean.pathInput2}">
+ <validate index="0"
+ validatorIds="validator1" />
+ <validate index="1"
+ validatorIds="validator2" />
+ </pattern>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="validatorIds"
+ type="xs:string">
+ <xs:annotation>
+ <xs:documentation>
+ The IDs of the JSF Validator objects
+ to attach and process before bean
+ value injection.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="validator"
+ type="xs:string">
+ <xs:annotation>
+ <xs:documentation>
+ The validation method used to check
+ the value before bean value injection.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="onError"
+ type="xs:string">
+ <xs:annotation>
+ <xs:documentation>
+ The pretty:mappingId or #{bean.method}
+ to evaluate, should validation fail.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="value" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ Specify the pattern for which this URL will be
+ matched.
+
+ Any EL expressions #{someBean.paramName} found
+ within the pattern will be processed as value
+ injections. The URL will be parsed and the
+ value found at the location of the EL
+ expression will be injected into the location
+ specified in that EL expression. Note: EL
+ expressions will not match over the ‘/’
+ character.
+
+ Additionally, each expression may specify a
+ name, or only a name:
+ #{myParam:someBean.paramName}, #{myParam} -
+ this provides parameter access to non-JSF
+ applications by adding the extracted value to
+ the HttpServletRequest property Map.
+
+ In order to take advantage of outbound-URL
+ rewriting, the parameter name specified must
+ match the parameter name used internally in the
+ application.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:whiteSpace value="collapse"></xs:whiteSpace>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="query-param" minOccurs="0"
+ maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>
+ Defines a managed query parameter of the form
+
http://site.com/url?key=somevalue, where if the
+ parameter exists, the value will be injected into the
+ specified managed bean. This also handles JSF
+ commandLink and AJAX <f:param> values.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:annotation>
+ <xs:documentation>
+ Defines a managed query parameter of the form
+
http://site.com/url?key=somevalue, where if the
+ parameter exists, the value will be injected into
+ the specified managed bean. This also handles JSF
+ commandLink and AJAX &lt;f:param&gt;
+ values.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="name" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ The managed parameter name. This value
+ corresponds to the named key
+ HttpServletRequest.getRequestParameter(...)
+ when extracting HTTP Request Parameters.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:restriction base="xs:string"></xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="onPostback"
+ type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>
+ Optional boolean (default true), if set
+ to false this query parameter will not be
+ injected on form postbacks.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="onError" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>
+ The pretty:mappingId or #{bean.method} to
+ evaluate, should validation fail.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="validatorIds"
+ type="xs:string">
+ <xs:annotation>
+ <xs:documentation>
+ The IDs of the JSF Validator objects to
+ attach and process before bean value
+ injection.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="validator" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>
+ The validation method used to check the
+ value before bean value injection.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="view-id" type="xs:string" minOccurs="1"
+ maxOccurs="1">
+ <xs:annotation>
+ <xs:documentation>
+ Specify the URI displayed by this mapping, by either
+ calling an el Method (must return an object for which
+ the toString() method will return the view Id) or by
+ returning a literal String value. The ViewId may be
+ any resource located within the current Servlet
+ Context: E.g. PrettyFaces can also forward to a
+ non-Faces servlet.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="action" minOccurs="0"
+ maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>
+ Specify an action method to be called after URL
+ parameters have been parsed and assigned into beans.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:annotation>
+ <xs:documentation>
+ an action method to be called after URL parameters
+ have been parsed and assigned into beans.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="phaseId">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="RESTORE_VIEW" />
+ <xs:enumeration
+ value="APPLY_REQUEST_VALUES" />
+ <xs:enumeration
+ value="PROCESS_VALIDATIONS" />
+ <xs:enumeration
+ value="UPDATE_MODEL_VALUES" />
+ <xs:enumeration
+ value="INVOKE_APPLICATION" />
+ <xs:enumeration value="RENDER_RESPONSE" />
+ <xs:enumeration value="ANY_PHASE" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="onPostback"
+ type="xs:boolean">
+ </xs:attribute>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>
+ The unique identifier by which this url-mapping will be
+ referenced in the application (e.g.: link components,
+ navigation outcomes, etc...)
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="outbound" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>
+ Enable or disable outbound URL rewriting for this
+ mapping (default: 'true' / enabled.) If enabled, any
+ links matching the viewId specified will be rewritten
+ (if possible) using parameters mapping to named path
+ parameters specified in the pattern.
+
+ Eg, given the following mapping: <url-mapping
+ id="singleItem" outbound="true"> <pattern
+
value="/store/#{cat:catBean.category}/#{pid:productBean.productId}"
+ />
+ <viewId>/faces/store/viewProduct.jsf</viewId>
+ </url-mapping>
+
+ The following outbound rewrite will occur:
+ /faces/product/viewProduct.jsf?cat=foods&pid=1234 =>
+ /store/foods/1234
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="onPostback" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>
+ Optional boolean (default true), if set to false path
+ parameters will not be injected on form postbacks.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="parentId" type="xs:string"></xs:attribute>
</xs:complexType>
=======================================
---
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/beans/ActionExecutorTest.java
Thu May 13 09:52:33 2010
+++
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/beans/ActionExecutorTest.java
Thu Nov 4 13:06:12 2010
@@ -22,11 +22,9 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import javax.faces.event.PhaseId;
-
import org.junit.Test;
-import com.ocpsoft.pretty.faces.beans.ActionExecutor;
+import com.ocpsoft.pretty.faces.annotation.URLAction.PhaseId;
import com.ocpsoft.pretty.faces.config.mapping.UrlAction;
/**
@@ -34,70 +32,70 @@
*/
public class ActionExecutorTest
{
- ActionExecutor executor = new ActionExecutor();
-
- @Test
- public void testShouldExecuteOnPostback()
- {
- UrlAction action = new UrlAction("action", PhaseId.ANY_PHASE);
- action.setOnPostback(true);
- assertTrue(executor.shouldExecute(action, PhaseId.RESTORE_VIEW,
true));
- }
-
- @Test
- public void testShouldExecuteOnNonPostback()
- {
- UrlAction action = new UrlAction("action", PhaseId.ANY_PHASE);
- action.setOnPostback(true);
- assertTrue(executor.shouldExecute(action, PhaseId.RESTORE_VIEW,
false));
- }
-
- @Test
- public void testShouldExecuteOnPhaseNonPostback()
- {
- UrlAction action = new UrlAction("action", PhaseId.RESTORE_VIEW);
- action.setOnPostback(true);
- assertTrue(executor.shouldExecute(action, PhaseId.RESTORE_VIEW,
false));
- }
-
- @Test
- public void testShouldNotExecuteOnWrongPhaseNonPostback()
- {
- UrlAction action = new UrlAction("action", PhaseId.RESTORE_VIEW);
- action.setOnPostback(true);
- assertFalse(executor.shouldExecute(action,
PhaseId.APPLY_REQUEST_VALUES, false));
- }
-
- @Test
- public void testShouldExecuteOnPhasePostback()
- {
- UrlAction action = new UrlAction("action", PhaseId.RESTORE_VIEW);
- action.setOnPostback(true);
- assertTrue(executor.shouldExecute(action, PhaseId.RESTORE_VIEW,
true));
- }
-
- @Test
- public void testShouldNotExecuteOnWrongPhasePostback()
- {
- UrlAction action = new UrlAction("action", PhaseId.RESTORE_VIEW);
- action.setOnPostback(true);
- assertFalse(executor.shouldExecute(action,
PhaseId.APPLY_REQUEST_VALUES, true));
- }
-
- @Test
- public void testShouldNotExecuteOnPostbackFalse()
- {
- UrlAction action = new UrlAction("action", PhaseId.ANY_PHASE);
- action.setOnPostback(false);
- assertFalse(executor.shouldExecute(action, PhaseId.RESTORE_VIEW,
true));
- }
-
- @Test
- public void testShouldExecuteOnPostbackFalseWhenNotPostback()
- {
- UrlAction action = new UrlAction("action", PhaseId.ANY_PHASE);
- action.setOnPostback(false);
- assertTrue(executor.shouldExecute(action, PhaseId.RESTORE_VIEW,
false));
- }
+ ActionExecutor executor = new ActionExecutor();
+
+ @Test
+ public void testShouldExecuteOnPostback()
+ {
+ UrlAction action = new UrlAction("action", PhaseId.ANY_PHASE);
+ action.setOnPostback(true);
+ assertTrue(executor.shouldExecute(action,
javax.faces.event.PhaseId.RESTORE_VIEW, true));
+ }
+
+ @Test
+ public void testShouldExecuteOnNonPostback()
+ {
+ UrlAction action = new UrlAction("action", PhaseId.ANY_PHASE);
+ action.setOnPostback(true);
+ assertTrue(executor.shouldExecute(action,
javax.faces.event.PhaseId.RESTORE_VIEW, false));
+ }
+
+ @Test
+ public void testShouldExecuteOnPhaseNonPostback()
+ {
+ UrlAction action = new UrlAction("action", PhaseId.RESTORE_VIEW);
+ action.setOnPostback(true);
+ assertTrue(executor.shouldExecute(action,
javax.faces.event.PhaseId.RESTORE_VIEW, false));
+ }
+
+ @Test
+ public void testShouldNotExecuteOnWrongPhaseNonPostback()
+ {
+ UrlAction action = new UrlAction("action", PhaseId.RESTORE_VIEW);
+ action.setOnPostback(true);
+ assertFalse(executor.shouldExecute(action,
javax.faces.event.PhaseId.APPLY_REQUEST_VALUES, false));
+ }
+
+ @Test
+ public void testShouldExecuteOnPhasePostback()
+ {
+ UrlAction action = new UrlAction("action", PhaseId.RESTORE_VIEW);
+ action.setOnPostback(true);
+ assertTrue(executor.shouldExecute(action,
javax.faces.event.PhaseId.RESTORE_VIEW, true));
+ }
+
+ @Test
+ public void testShouldNotExecuteOnWrongPhasePostback()
+ {
+ UrlAction action = new UrlAction("action", PhaseId.RESTORE_VIEW);
+ action.setOnPostback(true);
+ assertFalse(executor.shouldExecute(action,
javax.faces.event.PhaseId.APPLY_REQUEST_VALUES, true));
+ }
+
+ @Test
+ public void testShouldNotExecuteOnPostbackFalse()
+ {
+ UrlAction action = new UrlAction("action", PhaseId.ANY_PHASE);
+ action.setOnPostback(false);
+ assertFalse(executor.shouldExecute(action,
javax.faces.event.PhaseId.RESTORE_VIEW, true));
+ }
+
+ @Test
+ public void testShouldExecuteOnPostbackFalseWhenNotPostback()
+ {
+ UrlAction action = new UrlAction("action", PhaseId.ANY_PHASE);
+ action.setOnPostback(false);
+ assertTrue(executor.shouldExecute(action,
javax.faces.event.PhaseId.RESTORE_VIEW, false));
+ }
}
=======================================
---
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/MappingDigesterPrettyConfigParserTest.java
Sat Oct 2 01:13:11 2010
+++
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/MappingDigesterPrettyConfigParserTest.java
Thu Nov 4 13:06:12 2010
@@ -21,15 +21,11 @@
import java.io.IOException;
import java.util.List;
-import javax.faces.event.PhaseId;
-
import org.junit.Before;
import org.junit.Test;
import org.xml.sax.SAXException;
-import com.ocpsoft.pretty.faces.config.DigesterPrettyConfigParser;
-import com.ocpsoft.pretty.faces.config.PrettyConfig;
-import com.ocpsoft.pretty.faces.config.PrettyConfigBuilder;
+import com.ocpsoft.pretty.faces.annotation.URLAction.PhaseId;
import com.ocpsoft.pretty.faces.config.mapping.QueryParameter;
import com.ocpsoft.pretty.faces.config.mapping.RequestParameter;
import com.ocpsoft.pretty.faces.config.mapping.UrlAction;
@@ -38,155 +34,157 @@
public class MappingDigesterPrettyConfigParserTest
{
- private static final String CONFIG_PATH = "mock-pretty-config.xml";
- private PrettyConfig config;
-
- @Before
- public void configure() throws IOException, SAXException
- {
- final PrettyConfigBuilder builder = new PrettyConfigBuilder();
- new DigesterPrettyConfigParser().parse(builder,
getClass().getClassLoader().getResourceAsStream(CONFIG_PATH));
- config = builder.build();
- }
-
- @Test
- public void testParse()
- {
- UrlMapping mapping = config.getMappingById("0");
-
- assertEquals("0", mapping.getId());
- assertEquals("/project/#{viewProjectBean.projectId}/",
mapping.getPattern());
- assertEquals("#{viewProjectBean.getPrettyTarget}",
mapping.getViewId());
-
- List<UrlAction> actions = mapping.getActions();
- assertTrue(actions.contains(new
UrlAction("#{viewProjectBean.load}")));
- assertTrue(actions.contains(new
UrlAction("#{viewProjectBean.authorize}")));
- }
-
- @Test
- public void testOnPostbackDefaultsToTrue() {
- UrlMapping mapping = config.getMappingById("0");
- assertEquals(true, mapping.isOnPostback());
- }
-
- @Test
- public void testOnPostbackSetToFalse() {
- UrlMapping mapping = config.getMappingById("1");
- assertEquals(false, mapping.isOnPostback());
- }
-
- @Test
- public void testParseWithPostbackAction() throws Exception
- {
- UrlMapping mapping = config.getMappingById("1");
- assertFalse(mapping.getActions().get(0).onPostback());
- assertTrue(mapping.getActions().get(1).onPostback());
- }
-
- @Test
- public void testParseActionDefaultsToPostbackTrue() throws Exception
- {
- UrlMapping mapping = config.getMappingById("2");
- assertTrue(mapping.getActions().get(0).onPostback());
- assertTrue(mapping.getActions().get(1).onPostback());
- }
-
- @Test
- public void testParseWithAnyPhaseAction() throws Exception
- {
- UrlMapping mapping = config.getMappingById("2");
- assertEquals(PhaseId.ANY_PHASE,
mapping.getActions().get(1).getPhaseId());
- }
-
- @Test
- public void testParseWithPreRenderAction() throws Exception
- {
- UrlMapping mapping = config.getMappingById("3");
- assertEquals(PhaseId.RENDER_RESPONSE,
mapping.getActions().get(1).getPhaseId());
- }
-
- @Test
- public void testParseWithMappedQueryParam() throws Exception
- {
- UrlMapping mapping = config.getMappingById("4");
- List<QueryParameter> params = mapping.getQueryParams();
-
- assertEquals(1, params.size());
- RequestParameter param = params.get(0);
- RequestParameter expected = new QueryParameter("user", null, new
ConstantExpression("#{deleteUserBean.userName}"));
- assertEquals(expected, param);
- }
-
- @Test
- public void testParseWithMappedMultipleQueryParams() throws Exception
- {
- UrlMapping mapping = config.getMappingById("6");
- List<QueryParameter> params = mapping.getQueryParams();
-
- assertEquals(2, params.size());
- RequestParameter name = new QueryParameter("name", null, new
ConstantExpression("#{searchUserBean.userName}"));
- RequestParameter gender = new QueryParameter("gender", null, new
ConstantExpression("#{searchUserBean.userGender}"));
- assertArrayEquals(new Object[] { name, gender }, params.toArray());
- }
-
- @Test
- public void testParseWithNoQueryParams() throws Exception
- {
- UrlMapping mapping = config.getMappingById("7");
- List<QueryParameter> params = mapping.getQueryParams();
- assertEquals(0, params.size());
- }
-
- @Test
- public void testParseWithPathValidators() throws Exception
- {
- UrlMapping mapping = config.getMappingById("validate");
- assertEquals("/validate/#{validationBean.pathInput}",
mapping.getPattern());
- assertEquals(2, mapping.getPathValidators().size());
- assertEquals(0, mapping.getPathValidators().get(0).getIndex());
- assertEquals("validator1",
mapping.getPathValidators().get(0).getValidatorIds());
- assertEquals("#{validationBean.handle}",
mapping.getPathValidators().get(0).getOnError());
- assertEquals(null,
mapping.getPathValidators().get(0).getValidatorExpression());
-
- assertEquals(1, mapping.getPathValidators().get(1).getIndex());
- assertEquals("validator2",
mapping.getPathValidators().get(1).getValidatorIds());
- assertEquals("#{validationBean.handle2}",
mapping.getPathValidators().get(1).getOnError());
- assertEquals("#{validationBean.validateMethod}",
mapping.getPathValidators().get(1).getValidatorExpression().getELExpression());
- List<QueryParameter> params = mapping.getQueryParams();
- assertEquals(1, params.size());
- }
-
- @Test
- public void testParseWithQueryValidators() throws Exception
- {
- UrlMapping mapping = config.getMappingById("validate");
- List<QueryParameter> params = mapping.getQueryParams();
- assertEquals(1, params.size());
-
- QueryParameter p = params.get(0);
- assertEquals("validator1 validator2", p.getValidatorIds());
- assertEquals("pretty:demo", p.getOnError());
- assertEquals("p", p.getName());
- assertEquals("#{validationBean.validateMethod}",
p.getValidatorExpression().getELExpression());
-
- }
-
- @Test
- public void testQueryParameterOnPostbackAttribute() throws Exception
- {
- UrlMapping mapping = config.getMappingById("8");
- List<QueryParameter> params = mapping.getQueryParams();
- assertEquals(3, params.size());
-
- assertEquals("withoutAttribute", params.get(0).getName());
- assertEquals(true, params.get(0).isOnPostback());
-
- assertEquals("attributeSetToFalse", params.get(1).getName());
- assertEquals(false, params.get(1).isOnPostback());
-
- assertEquals("attributeSetToTrue", params.get(2).getName());
- assertEquals(true, params.get(2).isOnPostback());
-
- }
-
-}
+ private static final String CONFIG_PATH = "mock-pretty-config.xml";
+ private PrettyConfig config;
+
+ @Before
+ public void configure() throws IOException, SAXException
+ {
+ final PrettyConfigBuilder builder = new PrettyConfigBuilder();
+ new DigesterPrettyConfigParser().parse(builder,
getClass().getClassLoader().getResourceAsStream(CONFIG_PATH));
+ config = builder.build();
+ }
+
+ @Test
+ public void testParse()
+ {
+ UrlMapping mapping = config.getMappingById("0");
+
+ assertEquals("0", mapping.getId());
+ assertEquals("/project/#{viewProjectBean.projectId}/",
mapping.getPattern());
+ assertEquals("#{viewProjectBean.getPrettyTarget}",
mapping.getViewId());
+
+ List<UrlAction> actions = mapping.getActions();
+ assertTrue(actions.contains(new
UrlAction("#{viewProjectBean.load}")));
+ assertTrue(actions.contains(new
UrlAction("#{viewProjectBean.authorize}")));
+ }
+
+ @Test
+ public void testOnPostbackDefaultsToTrue()
+ {
+ UrlMapping mapping = config.getMappingById("0");
+ assertEquals(true, mapping.isOnPostback());
+ }
+
+ @Test
+ public void testOnPostbackSetToFalse()
+ {
+ UrlMapping mapping = config.getMappingById("1");
+ assertEquals(false, mapping.isOnPostback());
+ }
+
+ @Test
+ public void testParseWithPostbackAction() throws Exception
+ {
+ UrlMapping mapping = config.getMappingById("1");
+ assertFalse(mapping.getActions().get(0).onPostback());
+ assertTrue(mapping.getActions().get(1).onPostback());
+ }
+
+ @Test
+ public void testParseActionDefaultsToPostbackTrue() throws Exception
+ {
+ UrlMapping mapping = config.getMappingById("2");
+ assertTrue(mapping.getActions().get(0).onPostback());
+ assertTrue(mapping.getActions().get(1).onPostback());
+ }
+
+ @Test
+ public void testParseWithAnyPhaseAction() throws Exception
+ {
+ UrlMapping mapping = config.getMappingById("2");
+ assertEquals(PhaseId.ANY_PHASE,
mapping.getActions().get(1).getPhaseId());
+ }
+
+ @Test
+ public void testParseWithPreRenderAction() throws Exception
+ {
+ UrlMapping mapping = config.getMappingById("3");
+ assertEquals(PhaseId.RENDER_RESPONSE,
mapping.getActions().get(1).getPhaseId());
+ }
+
+ @Test
+ public void testParseWithMappedQueryParam() throws Exception
+ {
+ UrlMapping mapping = config.getMappingById("4");
+ List<QueryParameter> params = mapping.getQueryParams();
+
+ assertEquals(1, params.size());
+ RequestParameter param = params.get(0);
+ RequestParameter expected = new QueryParameter("user", null, new
ConstantExpression("#{deleteUserBean.userName}"));
+ assertEquals(expected, param);
+ }
+
+ @Test
+ public void testParseWithMappedMultipleQueryParams() throws Exception
+ {
+ UrlMapping mapping = config.getMappingById("6");
+ List<QueryParameter> params = mapping.getQueryParams();
+
+ assertEquals(2, params.size());
+ RequestParameter name = new QueryParameter("name", null, new
ConstantExpression("#{searchUserBean.userName}"));
+ RequestParameter gender = new QueryParameter("gender", null, new
ConstantExpression("#{searchUserBean.userGender}"));
+ assertArrayEquals(new Object[] { name, gender }, params.toArray());
+ }
+
+ @Test
+ public void testParseWithNoQueryParams() throws Exception
+ {
+ UrlMapping mapping = config.getMappingById("7");
+ List<QueryParameter> params = mapping.getQueryParams();
+ assertEquals(0, params.size());
+ }
+
+ @Test
+ public void testParseWithPathValidators() throws Exception
+ {
+ UrlMapping mapping = config.getMappingById("validate");
+ assertEquals("/validate/#{validationBean.pathInput}",
mapping.getPattern());
+ assertEquals(2, mapping.getPathValidators().size());
+ assertEquals(0, mapping.getPathValidators().get(0).getIndex());
+ assertEquals("validator1",
mapping.getPathValidators().get(0).getValidatorIds());
+ assertEquals("#{validationBean.handle}",
mapping.getPathValidators().get(0).getOnError());
+ assertEquals(null,
mapping.getPathValidators().get(0).getValidatorExpression());
+
+ assertEquals(1, mapping.getPathValidators().get(1).getIndex());
+ assertEquals("validator2",
mapping.getPathValidators().get(1).getValidatorIds());
+ assertEquals("#{validationBean.handle2}",
mapping.getPathValidators().get(1).getOnError());
+ assertEquals("#{validationBean.validateMethod}",
mapping.getPathValidators().get(1).getValidatorExpression().getELExpression());
+ List<QueryParameter> params = mapping.getQueryParams();
+ assertEquals(1, params.size());
+ }
+
+ @Test
+ public void testParseWithQueryValidators() throws Exception
+ {
+ UrlMapping mapping = config.getMappingById("validate");
+ List<QueryParameter> params = mapping.getQueryParams();
+ assertEquals(1, params.size());
+
+ QueryParameter p = params.get(0);
+ assertEquals("validator1 validator2", p.getValidatorIds());
+ assertEquals("pretty:demo", p.getOnError());
+ assertEquals("p", p.getName());
+ assertEquals("#{validationBean.validateMethod}",
p.getValidatorExpression().getELExpression());
+
+ }
+
+ @Test
+ public void testQueryParameterOnPostbackAttribute() throws Exception
+ {
+ UrlMapping mapping = config.getMappingById("8");
+ List<QueryParameter> params = mapping.getQueryParams();
+ assertEquals(3, params.size());
+
+ assertEquals("withoutAttribute", params.get(0).getName());
+ assertEquals(true, params.get(0).isOnPostback());
+
+ assertEquals("attributeSetToFalse", params.get(1).getName());
+ assertEquals(false, params.get(1).isOnPostback());
+
+ assertEquals("attributeSetToTrue", params.get(2).getName());
+ assertEquals(true, params.get(2).isOnPostback());
+
+ }
+
+}
=======================================
---
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/MockFacesServletRegistration.java
Fri Oct 1 07:41:50 2010
+++
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/MockFacesServletRegistration.java
Thu Nov 4 13:06:12 2010
@@ -1,23 +1,15 @@
/*
- * JBoss, Home of Professional Open Source
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ * PrettyFaces is an OpenSource JSF library to create bookmarkable URLs.
+ * Copyright (C) 2009 - Lincoln Baxter, III <
lin...@ocpsoft.com> This
program
+ * is free software: you can redistribute it and/or modify it under the
terms of
+ * the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any
later
+ * version. This program is distributed in the hope that it will be
useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License
+ * for more details. You should have received a copy of the GNU Lesser
General
+ * Public License along with this program. If not, see the file
COPYING.LESSER3
+ * or visit the GNU website at <
http://www.gnu.org/licenses/>.
*/
package com.ocpsoft.pretty.faces.config;
=======================================
---
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/PrettyConfiguratorTest.java
Mon Oct 18 09:56:19 2010
+++
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/PrettyConfiguratorTest.java
Thu Nov 4 13:06:12 2010
@@ -16,11 +16,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
-import java.util.NoSuchElementException;
import javax.servlet.ServletContext;
@@ -31,6 +28,8 @@
import org.xml.sax.SAXException;
import com.ocpsoft.pretty.PrettyContext;
+import
com.ocpsoft.pretty.faces.config.spi.ClassLoaderConfigurationProvider;
+import com.ocpsoft.pretty.faces.config.spi.DefaultXMLConfigurationProvider;
/**
* @author Aleksei Valikov
@@ -39,6 +38,9 @@
{
private final static Map servlets = new HashMap<String,
MockFacesServletRegistration>();
+ final ClassLoader mockResourceLoader = new
MockClassLoader(mockPrettyConfigURL());
+ final ClassLoader mockEmptyResourceLoader = new MockClassLoader();
+
@BeforeClass
@SuppressWarnings("unchecked")
public static void beforeClass()
@@ -47,39 +49,17 @@
}
@Test
- public void configureDefault() throws SAXException, IOException
+ public void testMETAINFConfiguration() throws SAXException, IOException
{
final ServletContext servletContext =
EasyMock.createNiceMock(ServletContext.class);
EasyMock.expect(servletContext.getMajorVersion()).andReturn(3).anyTimes();
EasyMock.expect(servletContext.getServletRegistrations()).andReturn(servlets).anyTimes();
EasyMock.expect(servletContext.getInitParameter(PrettyContext.CONFIG_KEY)).andReturn(null).anyTimes();
-
EasyMock.expect(servletContext.getResourceAsStream(PrettyConfigurator.DEFAULT_PRETTY_FACES_CONFIG)).andReturn(null).anyTimes();
-
- final ClassLoader resourceLoader = new URLClassLoader(new URL[0],
Thread.currentThread().getContextClassLoader())
- {
- @Override
- public Enumeration<URL> getResources(final String name) throws
IOException
- {
- if (PrettyConfigurator.PRETTY_CONFIG_RESOURCE.equals(name))
- {
- return enumeration(mockPrettyConfigURL());
- }
- else
- {
- return super.getResources(name);
- }
- }
- };
-
- final PrettyConfigurator configurator = new
PrettyConfigurator(servletContext)
- {
- @Override
- protected ClassLoader getResourceLoader()
- {
- return resourceLoader;
- }
- };
+
EasyMock.expect(servletContext.getClassLoader()).andReturn(mockResourceLoader).anyTimes();
+
EasyMock.expect(servletContext.getResourceAsStream(DefaultXMLConfigurationProvider.DEFAULT_PRETTY_FACES_CONFIG)).andReturn(null).anyTimes();
+
+ final PrettyConfigurator configurator = new
PrettyConfigurator(servletContext);
EasyMock.replay(servletContext);
configurator.configure();
@@ -89,16 +69,18 @@
@Test
@SuppressWarnings("unchecked")
- public void configureSpecial() throws SAXException, IOException
+ public void testInitParameterLocationConfiguration() throws
SAXException, IOException
{
final ServletContext servletContext =
EasyMock.createNiceMock(ServletContext.class);
EasyMock.expect(servletContext.getMajorVersion()).andReturn(3).anyTimes();
EasyMock.expect(servletContext.getServletRegistrations()).andReturn(servlets).anyTimes();
+
EasyMock.expect(servletContext.getClassLoader()).andReturn(mockEmptyResourceLoader).anyTimes();
EasyMock.expect(servletContext.getInitParameter(PrettyContext.CONFIG_KEY)).andReturn("car.xml,
cdr.xml").anyTimes();
+
EasyMock.expect(servletContext.getInitParameter(ClassLoaderConfigurationProvider.CLASSPATH_CONFIG_ENABLED)).andReturn("false").anyTimes();
EasyMock.expect(servletContext.getResourceAsStream("car.xml")).andReturn(mockPrettyConfigInputStream()).anyTimes();
EasyMock.expect(servletContext.getResourceAsStream("cdr.xml")).andReturn(mockPrettyConfigInputStream()).anyTimes();
-
EasyMock.expect(servletContext.getResourceAsStream(PrettyConfigurator.DEFAULT_PRETTY_FACES_CONFIG)).andReturn(mockPrettyConfigInputStream()).anyTimes();
+
EasyMock.expect(servletContext.getResourceAsStream(DefaultXMLConfigurationProvider.DEFAULT_PRETTY_FACES_CONFIG)).andReturn(mockPrettyConfigInputStream()).anyTimes();
final PrettyConfigurator configurator = new
PrettyConfigurator(servletContext);
EasyMock.replay(servletContext);
@@ -117,27 +99,5 @@
{
return
getClass().getClassLoader().getResource("mock-pretty-config.xml");
}
-
- private <T> Enumeration<T> enumeration(final T... elements)
- {
- return new Enumeration<T>()
- {
- private int index = 0;
-
- public boolean hasMoreElements()
- {
- return index < elements.length;
- }
-
- public T nextElement()
- {
- if (!hasMoreElements())
- {
- throw new NoSuchElementException("No more elements exist.");
- }
- return elements[index++];
- }
- };
- }
}
=======================================
---
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/annotation/PrettyAnnotationHandlerTest.java
Sat Oct 2 01:13:11 2010
+++
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/annotation/PrettyAnnotationHandlerTest.java
Thu Nov 4 13:06:12 2010
@@ -3,11 +3,10 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import javax.faces.event.PhaseId;
-
import org.junit.Test;
import com.ocpsoft.pretty.faces.annotation.URLAction;
+import com.ocpsoft.pretty.faces.annotation.URLAction.PhaseId;
import com.ocpsoft.pretty.faces.annotation.URLActions;
import com.ocpsoft.pretty.faces.annotation.URLBeanName;
import com.ocpsoft.pretty.faces.annotation.URLMapping;
@@ -67,7 +66,7 @@
assertEquals("/some/url", mapping.getPattern());
assertEquals("/view.jsf", mapping.getViewId());
assertEquals(false, mapping.isOutbound());
- assertEquals(false, mapping.isOnPostback());
+ assertEquals(false, mapping.isOnPostback());
assertEquals(0, mapping.getActions().size());
assertEquals(0, mapping.getQueryParams().size());
assertEquals(0, mapping.getPathValidators().size());
@@ -97,11 +96,11 @@
assertEquals("/some/url", mapping.getPattern());
assertEquals("/view.jsf", mapping.getViewId());
assertEquals(true, mapping.isOutbound());
- assertEquals(true, mapping.isOnPostback());
+ assertEquals(true, mapping.isOnPostback());
assertEquals(0, mapping.getActions().size());
assertEquals(0, mapping.getQueryParams().size());
assertEquals(1, mapping.getPathValidators().size());
-
+
// check path validation
PathValidator validator = mapping.getPathValidators().get(0);
assertEquals(0, validator.getIndex());
@@ -109,7 +108,7 @@
assertEquals("myValidator myOtherValidator",
validator.getValidatorIds());
}
-
+
@Test
public void testMappingWithOneLazyExpressionAction()
{
@@ -133,7 +132,7 @@
assertEquals("/some/url", mapping.getPattern());
assertEquals("/view.jsf", mapping.getViewId());
assertEquals(true, mapping.isOutbound());
- assertEquals(true, mapping.isOnPostback());
+ assertEquals(true, mapping.isOnPostback());
assertEquals(0, mapping.getQueryParams().size());
assertEquals(1, mapping.getActions().size());
assertEquals(0, mapping.getPathValidators().size());
@@ -174,7 +173,7 @@
assertEquals("/some/url", mapping.getPattern());
assertEquals("/view.jsf", mapping.getViewId());
assertEquals(true, mapping.isOutbound());
- assertEquals(true, mapping.isOnPostback());
+ assertEquals(true, mapping.isOnPostback());
assertEquals(0, mapping.getQueryParams().size());
assertEquals(1, mapping.getActions().size());
assertEquals(0, mapping.getPathValidators().size());
@@ -213,7 +212,7 @@
assertEquals("/some/url", mapping.getPattern());
assertEquals("/view.jsf", mapping.getViewId());
assertEquals(true, mapping.isOutbound());
- assertEquals(true, mapping.isOnPostback());
+ assertEquals(true, mapping.isOnPostback());
assertEquals(0, mapping.getQueryParams().size());
assertEquals(2, mapping.getActions().size());
assertEquals(0, mapping.getPathValidators().size());
@@ -261,7 +260,7 @@
assertEquals("/some/url", mapping.getPattern());
assertEquals("/view.jsf", mapping.getViewId());
assertEquals(true, mapping.isOutbound());
- assertEquals(true, mapping.isOnPostback());
+ assertEquals(true, mapping.isOnPostback());
assertEquals(0, mapping.getActions().size());
assertEquals(1, mapping.getQueryParams().size());
assertEquals(0, mapping.getPathValidators().size());
@@ -301,7 +300,7 @@
assertEquals("/some/url", mapping.getPattern());
assertEquals("/view.jsf", mapping.getViewId());
assertEquals(true, mapping.isOutbound());
- assertEquals(true, mapping.isOnPostback());
+ assertEquals(true, mapping.isOnPostback());
assertEquals(0, mapping.getActions().size());
assertEquals(1, mapping.getQueryParams().size());
assertEquals(0, mapping.getPathValidators().size());
@@ -313,7 +312,7 @@
assertEquals("#{bean.action}", queryParameter.getOnError());
assertEquals(2, queryParameter.getValidatorIdList().size());
assertEquals("myValidator myOtherValidator",
queryParameter.getValidatorIds());
-
+
// validate PrettyExpression
assertNotNull(queryParameter.getExpression());
assertEquals(ConstantExpression.class,
queryParameter.getExpression().getClass());
@@ -321,7 +320,6 @@
}
-
/**
* Simple class without any PrettyFaces annotations
*/
@@ -334,24 +332,24 @@
* Simple class with a single {@link URLMapping} annotation
*/
@URLMapping(id = "simple", pattern = "/some/url", viewId = "/view.jsf",
- outbound=false, onPostback=false)
+ outbound = false, onPostback = false)
public class ClassWithSimpleMapping
{
// nothing
}
/**
- * Simple class with a single {@link URLMapping} annotation and
- * a validation rule
+ * Simple class with a single {@link URLMapping} annotation and a
validation
+ * rule
*/
@URLMapping(id = "simple", pattern = "/some/url", viewId = "/view.jsf",
- validation=@URLValidator(index=0, onError="#{bean.action}",
+ validation = @URLValidator(index = 0, onError = "#{bean.action}",
validatorIds = { "myValidator", "myOtherValidator" }))
public class ClassWithMappingAndPathValidation
{
// nothing
}
-
+
/**
* Simple class with a mapping and one annotated action method (lazy
* expression)
@@ -363,7 +361,7 @@
@URLAction
public void actionMethod()
{
- // nothing
+ // nothing
}
}
@@ -380,7 +378,7 @@
@URLAction
public void actionMethod()
{
- // nothing
+ // nothing
}
}
@@ -393,13 +391,13 @@
public class ClassWithMultipleActions
{
- @URLActions(actions = {
+ @URLActions(actions = {
@URLAction(phaseId = URLAction.PhaseId.RENDER_RESPONSE),
- @URLAction(phaseId = URLAction.PhaseId.INVOKE_APPLICATION)
+ @URLAction(phaseId = URLAction.PhaseId.INVOKE_APPLICATION)
})
public void actionMethod()
{
- // nothing
+ // nothing
}
}
@@ -426,8 +424,8 @@
public class ClassWithSingleQueryParameterAndValidation
{
- @URLQueryParameter(value="myQueryParam", onPostback=false)
- @URLValidator(index=0, onError="#{bean.action}",
+ @URLQueryParameter(value = "myQueryParam", onPostback = false)
+ @URLValidator(index = 0, onError = "#{bean.action}",
validatorIds = { "myValidator", "myOtherValidator" })
@SuppressWarnings("unused")
private String someParameter;
=======================================
---
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/mapping/UrlActionTest.java
Wed Jun 30 11:26:10 2010
+++
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/mapping/UrlActionTest.java
Thu Nov 4 13:06:12 2010
@@ -16,39 +16,39 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
-import javax.faces.event.PhaseId;
-
import org.junit.Test;
+import com.ocpsoft.pretty.faces.annotation.URLAction.PhaseId;
+
/**
* @author lb3
*/
public class UrlActionTest
{
- @Test
- public void testUrlActionSetsDefaultPhaseIdAndEmptyAction()
- {
- UrlAction urlAction = new UrlAction();
- assertNull(urlAction.getAction());
- assertEquals(PhaseId.RESTORE_VIEW, urlAction.getPhaseId());
- }
-
- @Test
- public void testUrlActionStringSetsActionMethod()
- {
- String action = "#{this.is.my.action}";
- UrlAction urlAction = new UrlAction(action);
- assertEquals(action, urlAction.getAction().getELExpression());
- }
-
- @Test
- public void testUrlActionStringPhaseId()
- {
- String action = "#{this.is.my.action}";
- UrlAction urlAction = new UrlAction(action,
PhaseId.APPLY_REQUEST_VALUES);
- assertEquals(action, urlAction.getAction().getELExpression());
- assertEquals(PhaseId.APPLY_REQUEST_VALUES, urlAction.getPhaseId());
- }
+ @Test
+ public void testUrlActionSetsDefaultPhaseIdAndEmptyAction()
+ {
+ UrlAction urlAction = new UrlAction();
+ assertNull(urlAction.getAction());
+ assertEquals(PhaseId.RESTORE_VIEW, urlAction.getPhaseId());
+ }
+
+ @Test
+ public void testUrlActionStringSetsActionMethod()
+ {
+ String action = "#{this.is.my.action}";
+ UrlAction urlAction = new UrlAction(action);
+ assertEquals(action, urlAction.getAction().getELExpression());
+ }
+
+ @Test
+ public void testUrlActionStringPhaseId()
+ {
+ String action = "#{this.is.my.action}";
+ UrlAction urlAction = new UrlAction(action,
PhaseId.APPLY_REQUEST_VALUES);
+ assertEquals(action, urlAction.getAction().getELExpression());
+ assertEquals(PhaseId.APPLY_REQUEST_VALUES, urlAction.getPhaseId());
+ }
}
=======================================
---
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/mapping/UrlMappingTest.java
Thu May 13 09:52:33 2010
+++
/prettyfaces/trunk/core/src/test/java/com/ocpsoft/pretty/faces/config/mapping/UrlMappingTest.java
Thu Nov 4 13:06:12 2010
@@ -1,7 +1,7 @@
package com.ocpsoft.pretty.faces.config.mapping;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import org.junit.Test;
@@ -12,10 +12,11 @@
public void testSetPatternSetsPatternParser()
{
UrlMapping mapping = new UrlMapping();
- assertNull(mapping.getPatternParser());
+ assertEquals("", mapping.getPatternParser().getPattern());
mapping.setPattern("/foo/bar");
assertNotNull(mapping.getPatternParser());
+ assertEquals("/foo/bar", mapping.getPatternParser().getPattern());
}
}
=======================================
--- /prettyfaces/trunk/impl-jsf11/src/test/resources/log4j.properties Thu
May 13 09:52:33 2010
+++ /prettyfaces/trunk/impl-jsf11/src/test/resources/log4j.properties Thu
Nov 4 13:06:12 2010
@@ -8,4 +8,4 @@
log4j.rootLogger=warn, stdout
-log4j.logger.com.ocpsoft=info
+log4j.logger.com.ocpsoft=DEBUG