001package org.apache.commons.jcs.admin.servlet;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.commons.jcs.admin.JCSAdminBean;
023import org.apache.velocity.Template;
024import org.apache.velocity.context.Context;
025import org.apache.velocity.tools.view.VelocityViewServlet;
026
027import javax.servlet.http.HttpServletRequest;
028import javax.servlet.http.HttpServletResponse;
029import java.io.IOException;
030
031/**
032 * A servlet which provides HTTP access to JCS. Allows a summary of regions to
033 * be viewed, and removeAll to be run on individual regions or all regions. Also
034 * provides the ability to remove items (any number of key arguments can be
035 * provided with action 'remove'). Should be initialized with a properties file
036 * that provides at least a classpath resource loader. Since this extends
037 * VelocityServlet, which uses the singleton model for velocity, it will share
038 * configuration with any other Velocity in the same JVM.
039 * <p>
040 * Initialization in a webapp will look something like this:
041 * <p>
042 *
043 * <pre>
044 *
045 *    [servlet]
046 *        [servlet-name]JCSAdminServlet[/servlet-name]
047 *        [servlet-class]org.apache.commons.jcs.admin.servlet.JCSAdminServlet[/servlet-class]
048 *        [init-param]
049 *            [param-name]properties[/param-name]
050 *            [param-value]WEB-INF/conf/JCSAdminServlet.velocity.properties[/param-value]
051 *        [/init-param]
052 *    [/servlet]
053 *
054 * </pre>
055 *
056 * <p>
057 * FIXME: It would be nice to use the VelocityEngine model so this can be truly
058 * standalone. Right now if you run it in the same container as, say, turbine,
059 * turbine must be run first to ensure it's config takes precedence.
060 * <p>
061 */
062public class JCSAdminServlet
063    extends VelocityViewServlet
064{
065    private static final long serialVersionUID = -5519844149238645275L;
066
067    private static final String DEFAULT_TEMPLATE_NAME = "/org/apache/jcs/admin/servlet/JCSAdminServletDefault.vm";
068
069    private static final String REGION_DETAIL_TEMPLATE_NAME = "/org/apache/jcs/admin/servlet/JCSAdminServletRegionDetail.vm";
070
071    // Keys for parameters
072
073    private static final String CACHE_NAME_PARAM = "cacheName";
074
075    private static final String ACTION_PARAM = "action";
076
077    private static final String KEY_PARAM = "key";
078
079    private static final String SILENT_PARAM = "silent";
080
081    // Possible values for 'action' parameter
082
083    private static final String CLEAR_ALL_REGIONS_ACTION = "clearAllRegions";
084
085    private static final String CLEAR_REGION_ACTION = "clearRegion";
086
087    private static final String REMOVE_ACTION = "remove";
088
089    private static final String DETAIL_ACTION = "detail";
090
091    /**
092     * Velocity based admin servlet.
093     * <p>
094     * @param request
095     * @param response
096     * @param context
097     * @return Template
098     *
099     */
100    @Override
101    protected Template handleRequest( HttpServletRequest request, HttpServletResponse response, Context context )
102    {
103        JCSAdminBean admin = new JCSAdminBean();
104
105        String templateName = DEFAULT_TEMPLATE_NAME;
106
107        // Get cacheName for actions from request (might be null)
108
109        String cacheName = request.getParameter( CACHE_NAME_PARAM );
110
111        // If an action was provided, handle it
112
113        String action = request.getParameter( ACTION_PARAM );
114
115        try
116        {
117                        if ( action != null )
118                        {
119                            if ( action.equals( CLEAR_ALL_REGIONS_ACTION ) )
120                            {
121                                admin.clearAllRegions();
122                            }
123                            else if ( action.equals( CLEAR_REGION_ACTION ) )
124                            {
125                                if ( cacheName != null )
126                                {
127                                    admin.clearRegion( cacheName );
128                                }
129                            }
130                            else if ( action.equals( REMOVE_ACTION ) )
131                            {
132                                String[] keys = request.getParameterValues( KEY_PARAM );
133
134                                for ( int i = 0; i < keys.length; i++ )
135                                {
136                                    admin.removeItem( cacheName, keys[i] );
137                                }
138
139                                templateName = REGION_DETAIL_TEMPLATE_NAME;
140                            }
141                            else if ( action.equals( DETAIL_ACTION ) )
142                            {
143                                templateName = REGION_DETAIL_TEMPLATE_NAME;
144                            }
145                        }
146                }
147        catch (IOException e)
148        {
149                getLog().error("Could not execute action.", e);
150                return null;
151                }
152
153        if ( request.getParameter( SILENT_PARAM ) != null )
154        {
155            // If silent parameter was passed, no output should be produced.
156
157            return null;
158        }
159        // Populate the context based on the template
160
161        try
162        {
163                        if ( templateName == REGION_DETAIL_TEMPLATE_NAME )
164                        {
165                            context.put( "cacheName", cacheName );
166                            context.put( "elementInfoRecords", admin.buildElementInfo( cacheName ) );
167                        }
168                        else if ( templateName == DEFAULT_TEMPLATE_NAME )
169                        {
170                            context.put( "cacheInfoRecords", admin.buildCacheInfo() );
171                        }
172                }
173        catch (Exception e)
174        {
175                getLog().error("Could not populate context.", e);
176                }
177
178        return getTemplate( templateName );
179    }
180}