/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.cocoon.selection; import java.util.HashMap; import java.util.Map; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.regexp.RE; import org.apache.regexp.RECompiler; import org.apache.regexp.REProgram; import org.apache.regexp.RESyntaxException; /** * <p>The {@link AbstractRegexpSelector} abstract class defines a simple selector * operating over configured regular-expression patterns.</p> * * <p>Configuration of an {@link AbstractRegexpSelector} is quite simple: first of * all the patterns used for selections must be configured:</p> * * <pre> * <map:components> * ... * <map:selectors default="..."> * <map:selector name="..." src="org.apache.cocoon.selection...."> * <pattern name="empty">^$</pattern> * <pattern name="number">^[0-9]+$</pattern> * <pattern name="string">^.+$</pattern> * </map:selector> * </map:selectors> * </map:components> * </pre> * * <p>Then, each configured pattern can be referenced in the pipelines section of * the sitemap:</p> * * <pre> * <map:pipelines> * ... * <map:match ...> * ... * <map:select type="browser"> * <map:when test="empty">...</map:when> * <map:when test="number">...</map:when> * <map:when test="string">...</map:when> * <map:otherwise>...</map:otherwise> * </map:select> * ... * </map:match> * ... * </map:pipelines> * </pre> * * @author <a href="mailto:pier@apache.org">Pier Fumagalli</a> * @version CVS $Id: AbstractRegexpSelector.java 30941 2004-07-29 19:56:58Z vgritsenko $ */ public abstract class AbstractRegexpSelector extends AbstractSwitchSelector implements Configurable { /** <p>A {@link Map} of regular expression programs by name.</p> */ protected Map patterns = new HashMap(); /** * <p>Create a new {@link AbstractRegexpSelector} instance.</p> */ protected AbstractRegexpSelector() { super(); } /** * <p>Select a pipeline fragment based on a previously configured pattern.</p> * * @param patternName the name of the configured pattern. * @param selectorContext the string to be matched by the named pattern. * @return <b>true</b> if the contexts is matched by the configured pattern. */ public boolean select(String patternName, Object selectorContext) { /* Check that the context selection returned something */ if (selectorContext == null) return(false); /* Check that we actually have a configured pattern */ REProgram pattern = (REProgram) this.patterns.get(patternName); if (pattern == null) { if (this.getLogger().isWarnEnabled()) { this.getLogger().warn("The specified pattern name \"" + patternName + "\" was not configured in this instance"); } return(false); } /* Pattern matching */ return(new RE(pattern).match(selectorContext.toString())); } /** * <p>Configure this instance parsing all regular expression patterns.</p> * * @param configuration the {@link Configuration} instance where configured * patterns are defined. * @throws ConfigurationException if one of the regular-expression to configure * could not be compiled. */ public void configure(Configuration configuration) throws ConfigurationException { Configuration patterns[] = configuration.getChildren("pattern"); for (int x = 0; x < patterns.length; x++) { String name = patterns[x].getAttribute("name"); String pattern = patterns[x].getValue(); this.patterns.put(name, this.compile(pattern)); } } /** * <p>Compile the pattern in a {@link REProgram}.</p> * * @param pattern the regular expression pattern in a textual format. * @return a compiled regular expression pattern. * @throws ConfigurationException in the pattern could not be compiled. */ protected REProgram compile(String pattern) throws ConfigurationException { if (pattern == null) { throw new ConfigurationException("Null pattern"); } if (pattern.length() == 0) { pattern = "^$"; if (this.getLogger().isWarnEnabled()) { this.getLogger().warn("The empty pattern string was rewritten to " + "'^$' to match for empty strings. If you " + "intended to match all strings, please " + "change your pattern to '.*'"); } } try { RECompiler compiler = new RECompiler(); REProgram program = compiler.compile(pattern); return program; } catch (RESyntaxException rse) { getLogger().debug("Failed to compile the pattern '" + pattern + "'", rse); throw new ConfigurationException(rse.getMessage(), rse); } } }