001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.chain.web.javax.servlet;
018
019import javax.servlet.http.HttpServletRequest;
020
021import org.apache.commons.chain.Catalog;
022import org.apache.commons.chain.Command;
023import org.apache.commons.chain.Context;
024import org.apache.commons.chain.generic.LookupCommand;
025
026/**
027 * {@link Command} that uses the "servlet path" component of the request URI
028 * to select a {@link Command} from the appropriate {@link Catalog}, and
029 * execute it. To use this command, you would typically map an instance
030 * of {@link ChainProcessor} to an extension pattern like "*.execute" and
031 * then arrange that this is the default command to be executed. In such
032 * an environment, a request for a context relative URI of "/foo.execute"
033 * would cause the "/foo.execute" command to be loaded and executed.
034 *
035 * @author Craig R. McClanahan
036 */
037public class ServletPathMapper extends LookupCommand<ServletWebContext> {
038
039    // ------------------------------------------------------ Instance Variables
040
041    private String catalogKey = ChainProcessor.CATALOG_DEFAULT;
042
043    // ------------------------------------------------------------ Constructors
044
045    /**
046     * The Default-Constructor for this class.
047     */
048    public ServletPathMapper() {
049    }
050
051    // -------------------------------------------------------------- Properties
052
053    /**
054     * Return the context key under which our {@link Catalog} has been
055     * stored.
056     *
057     * @return The context key for the Catalog.
058     *
059     * @deprecated Use catalogName to specify the name of the catalog in the
060     *  catalog factory
061     */
062    @Deprecated
063    public String getCatalogKey() {
064        return this.catalogKey;
065    }
066
067    /**
068     * Set the context key under which our {@link Catalog} has been
069     * stored.
070     *
071     * @param catalogKey The new catalog key
072     *
073     * @deprecated Use catalogName to specify the name of the catalog in the
074     *  catalog factory
075     */
076    @Deprecated
077    public void setCatalogKey(String catalogKey) {
078        this.catalogKey = catalogKey;
079    }
080
081    // --------------------------------------------------------- Command Methods
082
083    /**
084     * Look up the servlet path information for this request, and use it to
085     * select an appropriate {@link Command} to be executed.
086     *
087     * @param context Context for the current request
088     *
089     * @return The name of the {@link Command} instance
090     *
091     * @since Chain 1.2
092     */
093    @Override
094    protected String getCommandName(ServletWebContext context) {
095        // Look up the servlet path for this request
096        final HttpServletRequest request = context.getRequest();
097        final Object attrServletPath = request.getAttribute("javax.servlet.include.servlet_path");
098        final String servletPath = attrServletPath == null
099                ? request.getServletPath()
100                : attrServletPath.toString();
101
102        return servletPath;
103    }
104
105    /**
106     * Return the {@link Catalog} to look up the {@link Command} in.
107     *
108     * @param context {@link Context} for this request
109     *
110     * @return The catalog.
111     *
112     * @throws IllegalArgumentException if no {@link Catalog}
113     *         can be found
114     *
115     * @since Chain 1.2
116     */
117    @Override
118    protected Catalog<ServletWebContext> getCatalog(ServletWebContext context) {
119        /* If the object returned from the passed context is not a valid catalog
120         * then we use the super class's catalog extraction logic to pull it
121         * or to error gracefully.
122         */
123        Object testCatalog = context.get(getCatalogKey());
124
125        /* Assume that the underlying implementation is following convention and
126         * returning a catalog with the current context.
127         */
128        @SuppressWarnings("unchecked")
129        Catalog<ServletWebContext> catalog = testCatalog instanceof Catalog
130                    ? (Catalog<ServletWebContext>) testCatalog
131                    : super.getCatalog(context);
132
133        return catalog;
134    }
135}