| /* |
| * 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.jsecurity.web.attr; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.jsecurity.JSecurityException; |
| import org.jsecurity.util.ClassUtils; |
| |
| import javax.servlet.ServletRequest; |
| import javax.servlet.ServletResponse; |
| import java.beans.PropertyEditor; |
| |
| /** |
| * Convenient superclass for implementations of the {@link WebAttribute} interface. This class encapsulates |
| * converting values from a String form to Object form and vice versa through the use of a <tt>PropertyEditor</tt> |
| * configured using {@link #setEditorClass(Class)}. Subclasses are expected to implement the |
| * {@link #onStoreValue(Object, javax.servlet.ServletRequest, javax.servlet.ServletResponse)} and |
| * {@link #onRetrieveValue(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} |
| * methods that perform the actual storing and retrieving of a String value. This class also contains convenience |
| * methods for retrieving the value of a request parameter to be stored. |
| * |
| * @author Les Hazlewood |
| * @since 0.2 |
| */ |
| public abstract class AbstractWebAttribute<T> implements WebAttribute<T> { |
| |
| public static final String DEFAULT_NAME = "name"; |
| |
| private static final Log log = LogFactory.getLog(AbstractWebAttribute.class); |
| |
| protected String name = DEFAULT_NAME; |
| |
| protected boolean checkRequestParams = true; |
| protected boolean checkRequestParamsFirst = true; |
| |
| protected boolean mutable = true; |
| |
| /** |
| * Property editor class to use to convert attributes to and from strings. |
| */ |
| private Class<? extends PropertyEditor> editorClass = null; |
| |
| public AbstractWebAttribute() { |
| this(DEFAULT_NAME, true); |
| } |
| |
| public AbstractWebAttribute(String name) { |
| this(name, true); |
| } |
| |
| public AbstractWebAttribute(String name, boolean checkRequestParams) { |
| setName(name); |
| setCheckRequestParams(checkRequestParams); |
| } |
| |
| public AbstractWebAttribute(String name, Class<? extends PropertyEditor> editorClass) { |
| this(name, true, editorClass); |
| } |
| |
| public AbstractWebAttribute(String name, boolean checkRequestParams, Class<? extends PropertyEditor> editorClass) { |
| setName(name); |
| setCheckRequestParams(checkRequestParams); |
| setEditorClass(editorClass); |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| public boolean isCheckRequestParams() { |
| return checkRequestParams; |
| } |
| |
| public void setCheckRequestParams(boolean checkRequestParams) { |
| this.checkRequestParams = checkRequestParams; |
| } |
| |
| public boolean isCheckRequestParamsFirst() { |
| return checkRequestParamsFirst; |
| } |
| |
| public void setCheckRequestParamsFirst(boolean checkRequestParamsFirst) { |
| this.checkRequestParamsFirst = checkRequestParamsFirst; |
| } |
| |
| public Class<? extends PropertyEditor> getEditorClass() { |
| return editorClass; |
| } |
| |
| /** |
| * If set, an instance of this class will be used to convert a the object value to a string value (and vice versa) |
| * when reading and populating values in |
| * {@link javax.servlet.http.HttpServletRequest HttpServletRequest}s, {@link javax.servlet.http.Cookie Cookie}s or |
| * {@link javax.servlet.http.HttpSession HttpSession}s. |
| * |
| * <p>If not set, the string itself will be used. |
| * |
| * @param editorClass {@link PropertyEditor PropertyEditor} implementation used to |
| * convert between string values and sessionId objects. |
| */ |
| public void setEditorClass(Class<? extends PropertyEditor> editorClass) { |
| this.editorClass = editorClass; |
| } |
| |
| /** |
| * Returns <tt>true</tt> if the value stored can be changed once it has been set, <tt>false</tt> if it cannot. |
| * <p>Default is <tt>true</tt>. |
| * |
| * @return <tt>true</tt> if the value stored can be changed once it has been set, <tt>false</tt> if it cannot. |
| */ |
| public boolean isMutable() { |
| return mutable; |
| } |
| |
| public void setMutable(boolean mutable) { |
| this.mutable = mutable; |
| } |
| |
| @SuppressWarnings({"unchecked"}) |
| protected T fromStringValue(String stringValue) { |
| Class clazz = getEditorClass(); |
| if (clazz == null) { |
| try { |
| return (T) stringValue; |
| } catch (Exception e) { |
| String msg = "If the type is not String, you must specify the 'editorClass' property."; |
| throw new JSecurityException(msg, e); |
| } |
| } else { |
| PropertyEditor editor = (PropertyEditor) ClassUtils.newInstance(getEditorClass()); |
| editor.setAsText(stringValue); |
| Object value = editor.getValue(); |
| try { |
| return (T) value; |
| } catch (ClassCastException e) { |
| String msg = "Returned value from PropertyEditor does not match the specified type."; |
| throw new JSecurityException(msg, e); |
| } |
| } |
| } |
| |
| protected String toStringValue(T value) { |
| Class clazz = getEditorClass(); |
| if (clazz == null) { |
| |
| if (log.isDebugEnabled()) { |
| log.debug("No 'editorClass' property set - returning value.toString() as the string value for " + |
| "method argument."); |
| } |
| return value.toString(); |
| } else { |
| PropertyEditor editor = (PropertyEditor) ClassUtils.newInstance(getEditorClass()); |
| editor.setValue(value); |
| return editor.getAsText(); |
| } |
| } |
| |
| protected T getFromRequestParam(ServletRequest request) { |
| T value = null; |
| |
| String paramName = getName(); |
| String paramValue = request.getParameter(paramName); |
| if (paramValue != null) { |
| if (log.isTraceEnabled()) { |
| log.trace("Found string value [" + paramValue + "] from HttpServletRequest parameter [" + paramName + "]"); |
| } |
| value = fromStringValue(paramValue); |
| } else { |
| if (log.isTraceEnabled()) { |
| log.trace("No string value found in the HttpServletRequest under parameter named [" + paramName + "]"); |
| } |
| } |
| |
| return value; |
| } |
| |
| public final T retrieveValue(ServletRequest request, ServletResponse response) { |
| T value = null; |
| if (isCheckRequestParams() && isCheckRequestParamsFirst()) { |
| value = getFromRequestParam(request); |
| } |
| |
| if (value == null) { |
| value = onRetrieveValue(request, response); |
| } |
| |
| if (value == null) { |
| if (isCheckRequestParams() && !isCheckRequestParamsFirst()) { |
| value = getFromRequestParam(request); |
| } |
| } |
| |
| return value; |
| } |
| |
| protected abstract T onRetrieveValue(ServletRequest request, ServletResponse response); |
| |
| public void storeValue(T value, ServletRequest request, ServletResponse response) { |
| if (value == null && isMutable()) { |
| removeValue(request, response); |
| return; |
| } |
| |
| if (!isMutable()) { |
| Object existing = onRetrieveValue(request, response); |
| if (existing != null) { |
| if (log.isDebugEnabled()) { |
| log.debug("Found existing value stored under name [" + getName() + "]. Ignoring new " + |
| "storage request - this store is immutable after the value has initially been set."); |
| } |
| } |
| return; |
| } |
| |
| onStoreValue(value, request, response); |
| } |
| |
| protected abstract void onStoreValue(T value, ServletRequest request, ServletResponse response); |
| } |