001: package org.gomba;
002:
003: import java.sql.ResultSet;
004: import java.util.List;
005:
006: import javax.servlet.http.HttpServletRequest;
007:
008: import org.apache.commons.beanutils.ConversionException;
009: import org.gomba.utils.convert.ConvertUtilsWrapper;
010: import org.gomba.utils.servlet.ServletParameterUtils;
011:
012: /**
013: * This class holds context information used to resolve ${} parameters.
014: *
015: * @author Flavio Tordini
016: * @version $Id: ParameterResolver.java,v 1.2 2004/07/16 15:41:20 flaviotordini
017: * Exp $
018: */
019: public class ParameterResolver {
020:
021: /**
022: * Used to resolve "param", "paramValues", "header" and "requestScope"
023: * domain parameters.
024: */
025: private final HttpServletRequest request;
026:
027: /**
028: * The resultSet used to resolve "column" domain parameters.
029: */
030: private ResultSet resultSet;
031:
032: /**
033: * Parsed servlet extra path. List of <code>String</code>. This is lazily
034: * set when needed. Used to resolve "path" domain parameters.
035: */
036: private List pathElements;
037:
038: /**
039: * Constructor.
040: */
041: public ParameterResolver(HttpServletRequest request) {
042: this .request = request;
043: }
044:
045: /**
046: * Get a parameter value converted to the required Java type.
047: *
048: * @return The parameter value. May return <code>null</code>, if the
049: * parameter is nullable.
050: * @exception MissingParameterException
051: * if no matching parameter is found and the parameter is not
052: * nullable.
053: */
054: public Object getParameterValue(ParameterDefinition parameter)
055: throws Exception {
056:
057: // TODO we may implement a little cache for parameters used multiple
058: // times. The ParameterDefinition will need an hashcode() method.
059: // we could map parameter definitions to parameters values converted to
060: // the required type. Mapping will be <code>ParameterDefinition</code>
061: // to <code>Object</code>.
062:
063: // get parameter value
064: Object parameterValue = parameter.getDomain()
065: .getParameterValue(this , parameter);
066:
067: if (parameterValue != null) {
068:
069: final Class parameterType = parameter.getType();
070: if (parameterType != null
071: && parameterType != java.lang.String.class
072: && parameterValue instanceof java.lang.String) {
073: // convert string to the required type
074: try {
075: return ConvertUtilsWrapper.convert(
076: (String) parameterValue, parameterType);
077: } catch (ConversionException ce) {
078: // Don't throw the original ConversionException as it
079: // contains the input string in its message. This can be a
080: // security issue.
081: throw new Exception(
082: "Error converting parameter to the specified type: "
083: + parameter, ce);
084: }
085: }
086:
087: } else {
088: // the default value (which can in turn be null)
089: parameterValue = parameter.getDefaultValue();
090: }
091:
092: if (parameterValue == null && !parameter.isNullable()) {
093: throw new MissingParameterException("Missing parameter: "
094: + parameter);
095: }
096:
097: return parameterValue;
098:
099: }
100:
101: /**
102: * Once we have a reference to the resultset we can resolve parameters that
103: * use the 'column' domain.
104: *
105: * @param resultSet
106: * The resultSet to set.
107: */
108: public void setResultSet(ResultSet resultSet) throws Exception {
109: this .resultSet = resultSet;
110: }
111:
112: /**
113: * @return Returns the servlet extra path elements.
114: */
115: public List getPathElements() {
116: if (this .pathElements == null) {
117: // parse the servlet path info
118: this .pathElements = ServletParameterUtils
119: .getPathElements(this .request);
120: }
121: return this .pathElements;
122: }
123:
124: /**
125: * @return Returns the request.
126: */
127: public HttpServletRequest getRequest() {
128: return this .request;
129: }
130:
131: /**
132: * @return Returns the resultSet, never returns null.
133: * @throws UnavailableResultSetException
134: * when a resultset is not available.
135: */
136: public ResultSet getResultSet()
137: throws UnavailableResultSetException {
138: if (this .resultSet == null) {
139: throw new UnavailableResultSetException(
140: "Cannot use the 'column' domain at this stage. A resultset is not available.");
141: }
142: return this .resultSet;
143: }
144:
145: /**
146: * Thrown when a resultset is not available.
147: */
148: public static class UnavailableResultSetException extends Exception {
149:
150: /**
151: * Constructor
152: */
153: public UnavailableResultSetException(String message) {
154: super(message);
155: }
156:
157: }
158: }
|