001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 2007.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.http.server;
007:
008: import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
009: import static javax.servlet.http.HttpServletResponse.SC_NOT_ACCEPTABLE;
010:
011: import java.util.ArrayList;
012: import java.util.Collection;
013: import java.util.Enumeration;
014:
015: import javax.servlet.http.HttpServletRequest;
016: import javax.servlet.http.HttpServletResponse;
017:
018: import org.slf4j.Logger;
019: import org.slf4j.LoggerFactory;
020:
021: import info.aduna.lang.FileFormat;
022: import info.aduna.lang.service.FileFormatServiceRegistry;
023: import info.aduna.webapp.util.HttpServerUtil;
024:
025: import org.openrdf.http.protocol.Protocol;
026: import org.openrdf.http.protocol.error.ErrorInfo;
027: import org.openrdf.http.protocol.error.ErrorType;
028: import org.openrdf.model.Resource;
029: import org.openrdf.model.URI;
030: import org.openrdf.model.Value;
031: import org.openrdf.model.ValueFactory;
032:
033: /**
034: * Utilities to help with the transition between HTTP requests/responses and
035: * values expected by the protocol.
036: *
037: * @author Herko ter Horst
038: * @author Arjohn Kampman
039: */
040: public class ProtocolUtil {
041:
042: public static Value parseValueParam(HttpServletRequest request,
043: String paramName, ValueFactory vf)
044: throws ClientHTTPException {
045: String paramValue = request.getParameter(paramName);
046: try {
047: return Protocol.decodeValue(paramValue, vf);
048: } catch (IllegalArgumentException e) {
049: throw new ClientHTTPException(SC_BAD_REQUEST,
050: "Invalid value for parameter '" + paramName + "': "
051: + paramValue);
052: }
053: }
054:
055: public static Resource parseResourceParam(
056: HttpServletRequest request, String paramName,
057: ValueFactory vf) throws ClientHTTPException {
058: String paramValue = request.getParameter(paramName);
059: try {
060: return Protocol.decodeResource(paramValue, vf);
061: } catch (IllegalArgumentException e) {
062: throw new ClientHTTPException(SC_BAD_REQUEST,
063: "Invalid value for parameter '" + paramName + "': "
064: + paramValue);
065: }
066: }
067:
068: public static URI parseURIParam(HttpServletRequest request,
069: String paramName, ValueFactory vf)
070: throws ClientHTTPException {
071: String paramValue = request.getParameter(paramName);
072: try {
073: return Protocol.decodeURI(paramValue, vf);
074: } catch (IllegalArgumentException e) {
075: throw new ClientHTTPException(SC_BAD_REQUEST,
076: "Invalid value for parameter '" + paramName + "': "
077: + paramValue);
078: }
079: }
080:
081: public static Resource[] parseContextParam(
082: HttpServletRequest request, String paramName,
083: ValueFactory vf) throws ClientHTTPException {
084: String[] paramValues = request.getParameterValues(paramName);
085: try {
086: return Protocol.decodeContexts(paramValues, vf);
087: } catch (IllegalArgumentException e) {
088: throw new ClientHTTPException(SC_BAD_REQUEST,
089: "Invalid value for parameter '" + paramName + "': "
090: + e.getMessage());
091: }
092: }
093:
094: public static boolean parseBooleanParam(HttpServletRequest request,
095: String paramName, boolean defaultValue) {
096: String paramValue = request.getParameter(paramName);
097: if (paramValue == null) {
098: return defaultValue;
099: } else {
100: return Boolean.parseBoolean(paramValue);
101: }
102: }
103:
104: /**
105: * Logs all request parameters of the supplied request.
106: */
107: public static void logRequestParameters(HttpServletRequest request) {
108: Logger logger = LoggerFactory.getLogger(ProtocolUtil.class);
109: if (logger.isDebugEnabled()) {
110: @SuppressWarnings("unchecked")
111: Enumeration<String> paramNames = request
112: .getParameterNames();
113: while (paramNames.hasMoreElements()) {
114: String name = paramNames.nextElement();
115: for (String value : request.getParameterValues(name)) {
116: logger.debug("{}=\"{}\"", name, value);
117: }
118: }
119: }
120: }
121:
122: public static <FF extends FileFormat, S> S getAcceptableService(
123: HttpServletRequest request, HttpServletResponse response,
124: FileFormatServiceRegistry<FF, S> serviceRegistry)
125: throws ClientHTTPException {
126: // Accept-parameter takes precedence over request headers
127: String mimeType = request
128: .getParameter(Protocol.ACCEPT_PARAM_NAME);
129: boolean hasAcceptParam = mimeType != null;
130:
131: if (mimeType == null) {
132: // Find an acceptable MIME type based on the request headers
133: logAcceptableFormats(request);
134:
135: Collection<String> mimeTypes = new ArrayList<String>(16);
136: for (FileFormat format : serviceRegistry.getKeys()) {
137: mimeTypes.addAll(format.getMIMETypes());
138: }
139:
140: mimeType = HttpServerUtil.selectPreferredMIMEType(mimeTypes
141: .iterator(), request);
142:
143: response.setHeader("Vary",
144: HttpServerUtil.ACCEPT_HEADER_NAME);
145: }
146:
147: if (mimeType != null) {
148: FF format = serviceRegistry
149: .getFileFormatForMIMEType(mimeType);
150:
151: if (format != null) {
152: return serviceRegistry.get(format);
153: }
154: }
155:
156: if (hasAcceptParam) {
157: ErrorInfo errInfo = new ErrorInfo(
158: ErrorType.UNSUPPORTED_FILE_FORMAT, mimeType);
159: throw new ClientHTTPException(SC_BAD_REQUEST, errInfo
160: .toString());
161: } else {
162: // No acceptable format was found, send 406 as required by RFC 2616
163: throw new ClientHTTPException(SC_NOT_ACCEPTABLE,
164: "No acceptable file format found.");
165: }
166: }
167:
168: public static void logAcceptableFormats(HttpServletRequest request) {
169: Logger logger = LoggerFactory.getLogger(ProtocolUtil.class);
170: if (logger.isDebugEnabled()) {
171: StringBuilder acceptable = new StringBuilder(64);
172:
173: @SuppressWarnings("unchecked")
174: Enumeration<String> acceptHeaders = request
175: .getHeaders(HttpServerUtil.ACCEPT_HEADER_NAME);
176:
177: while (acceptHeaders.hasMoreElements()) {
178: acceptable.append(acceptHeaders.nextElement());
179:
180: if (acceptHeaders.hasMoreElements()) {
181: acceptable.append(',');
182: }
183: }
184:
185: logger.debug("Acceptable formats: " + acceptable);
186: }
187: }
188: }
|