001: /**
002: *
003: */package org.enhydra.dm.api.handler;
004:
005: import java.io.IOException;
006: import java.net.URLDecoder;
007: import java.util.Enumeration;
008: import java.util.HashMap;
009: import java.util.Map;
010: import java.util.StringTokenizer;
011:
012: import javax.servlet.ServletConfig;
013: import javax.servlet.ServletException;
014: import javax.servlet.http.HttpServletRequest;
015: import javax.servlet.http.HttpServletResponse;
016:
017: import org.enhydra.dm.api.Document;
018: import org.enhydra.dm.api.DocumentManager;
019: import org.enhydra.dm.api.DocumentStore;
020: import org.enhydra.dm.api.exceptions.BaseException;
021: import org.enhydra.dm.api.loggers.Log;
022: import org.enhydra.dm.api.util.DesEncription;
023: import org.enhydra.dm.util.EnhydraDMConstants;
024:
025: /**
026: * An abstract implementation of the <code>MethodHandler</code> interface. This class
027: * serves as a convenient basis for building method handlers. In addition to providing
028: * basic <code>init</code> and <code>destroy</code> methods, several useful utility
029: * methods are supplied.
030: *
031: * @author Slobodan Vujasinovic
032: */
033: public abstract class AbstractHandler implements MethodHandler {
034:
035: private ServletConfig config;
036:
037: private DocumentManager documentManager;
038:
039: private DocumentStore documentStore;
040:
041: private DesEncription desEncription;
042:
043: private Log logger;
044:
045: private String lockRequestTimeout;
046:
047: public static final String REQUEST_URI_CHARSET = "WebDavServlet.RequestUriCharset";
048:
049: public static final String DEFAULT_LOCK_TIMEOUT = "-1";
050:
051: public static final String SESSION_ATT_LOCKED = "locked";
052:
053: /**
054: * Initializes the method handler. This implementation stores the provided
055: * <code>ServletConfig</code> object and makes it available via the
056: * <code>getServletConfig</code> method. Subclasses overriding this method should
057: * start by invoking
058: * <p>
059: * <code>super.init(config);</code>
060: *
061: * @param config a <code>ServletConfig</code> object containing the servlet's
062: * configuration and initialization parameters.
063: * @throws ServletException If an error occurs during initialization.
064: */
065: public void init(ServletConfig config,
066: DocumentManager documentManager,
067: DocumentStore documentStore, DesEncription desEncription,
068: Log logger) throws ServletException {
069: this .config = config;
070: this .documentManager = documentManager;
071: this .documentStore = documentStore;
072: this .desEncription = desEncription;
073: this .logger = logger;
074: this .lockRequestTimeout = config
075: .getInitParameter("lockRequestTimeout");
076: if (null == this .lockRequestTimeout) {
077: this .lockRequestTimeout = DEFAULT_LOCK_TIMEOUT;
078: }
079: }
080:
081: /**
082: * method that reads parameters from request, decode them and returns parameter Map
083: *
084: * @param request
085: * @return
086: * @throws ServletException
087: */
088: public Map readParameters(HttpServletRequest request)
089: throws ServletException {
090: Map parameterMap = new HashMap();
091:
092: try {
093: String parameters = null;
094: if (this .desEncription != null) {
095: parameters = request.getPathInfo();
096: parameters = request
097: .getParameter(EnhydraDMConstants.PARAM);
098:
099: if (parameters == null) {
100: return parameterMap;
101: }
102:
103: parameters = this .desEncription.decrypt(parameters);
104:
105: } else {
106: try {
107: parameters = request.getQueryString();
108:
109: if (parameters == null) {
110: return parameterMap;
111: }
112:
113: parameters = URLDecoder.decode(parameters,
114: EnhydraDMConstants.ENCODING);
115: } catch (Exception ex) {
116: ex.printStackTrace();
117: }
118: }
119:
120: StringTokenizer st = new StringTokenizer(parameters, "&");
121:
122: String token = null;
123: String parameterName = null;
124: String parameterValue = null;
125: while (st.hasMoreTokens()) {
126: token = st.nextToken();
127: int equalIndex = token.indexOf("=");
128:
129: if (-1 < equalIndex && equalIndex < token.length()) {
130: parameterName = token.substring(0, equalIndex);
131: parameterValue = token.substring(equalIndex + 1);
132: parameterMap.put(parameterName, parameterValue);
133: }
134: }
135: } catch (BaseException e) {
136: if (null != logger) {
137: logger.log(Log.ERROR,
138: "Error during parameters decrypt!");
139: }
140: throw new ServletException(e.getMessage());
141: }
142:
143: return parameterMap;
144: }
145:
146: /**
147: * Destroy method
148: */
149: public void destroy() {
150: config = null;
151: documentManager = null;
152: documentStore = null;
153: logger = null;
154: }
155:
156: /**
157: * Returns the <code>ServletConfig</code> object that was provided to the
158: * <code>init</code> method.
159: *
160: * @return A <code>ServletConfig</code> object containing the servlet's configuration
161: * and initialization parameters.
162: */
163: protected ServletConfig getServletConfig() {
164: return config;
165: }
166:
167: /**
168: * @return documentManager
169: */
170: protected DocumentManager getDocumentManager() {
171: return documentManager;
172: }
173:
174: /**
175: * @return documentStore
176: */
177: protected DocumentStore getDocumentStore() {
178: return documentStore;
179: }
180:
181: /**
182: * @return logger
183: */
184: public Log getLogger() {
185: return logger;
186: }
187:
188: /**
189: * @param logger
190: */
191: public void setLogger(Log logger) {
192: this .logger = logger;
193: }
194:
195: /**
196: * @return user
197: */
198: public String getUser(HttpServletRequest request) {
199: String user = request.getRemoteUser();
200: return user;
201: }
202:
203: /**
204: *
205: */
206: public abstract void service(HttpServletRequest request,
207: HttpServletResponse response) throws IOException,
208: ServletException;
209:
210: protected String getAllowedMethods() {
211: StringBuffer allow = new StringBuffer();
212:
213: allow.append("OPTIONS");
214: allow.append(", HEAD");
215: allow.append(", GET");
216: allow.append(", POST");
217: allow.append(", DELETE");
218: allow.append(", PROPFIND");
219: allow.append(", PROPPATCH");
220: allow.append(", COPY");
221: allow.append(", MOVE");
222: allow.append(", PUT");
223: allow.append(", MKCOL");
224:
225: allow.append(", LOCK");
226: allow.append(", UNLOCK");
227:
228: allow.append(", VERSION-CONTROL");
229: allow.append(", CHECKOUT");
230: allow.append(", UNCHECKOUT");
231: allow.append(", CHECKIN");
232: allow.append(", REPORT");
233:
234: return allow.toString();
235: }
236:
237: public String getLockRequestTimeout() {
238: return lockRequestTimeout;
239: }
240:
241: /**
242: * Checks if a conditional request should apply. If the client specifies one or more
243: * conditional cache headers ("<code>If-Match</code>", "<code>If-None-Match</code>", "<code>If-Modified-Since</code>",
244: * or "<code>If-Unmodified-Since" -- "<code>If-Range</code>" is not
245: * currently supported), this method will indicate whether the
246: * request should be processed.
247: *
248: * @param request The servlet request whose conditional cache headers
249: * will be examined.
250: * @param file The resource that is being examined.
251: * @return An HTTP status code indicating the result. This will be one of:
252: * <ul>
253: * <li><code>200</code> (<code>HttpServletResponse.SC_OK</code>) --
254: * if the request should be serviced normally</li>
255: * <li><code>304</code> (<code>HttpServletResponse.SC_NOT_MODIFIED</code>)
256: * -- if the resource has not been modified</li>
257: * <li><code>400</code>
258: * (<code>HttpServletResponse.SC_BAD_REQUEST</code>) --
259: * if the client has submitted a malformed conditional header</li>
260: * <li><code>412</code>
261: * (<code>HttpServletResponse.SC_PRECONDITION_FAILED</code>) --
262: * if no matching entity was found, or the request should not proceed
263: * based on the current lock status</li>
264: * </ul>
265: * @throws IOException If an error occurs while examining the resource.
266: */
267: protected int checkConditionalRequest(HttpServletRequest request,
268: Document document) throws IOException {
269: Enumeration values = request.getHeaders("If-None-Match");
270: if (values.hasMoreElements()) {
271: String etag = document.getETag();
272: if (etag != null) {
273: boolean match = false;
274: do {
275: String value = (String) values.nextElement();
276:
277: if ("*".equals(value) || etag.equals(value))
278: match = true;
279: } while (!match && values.hasMoreElements());
280: if (match) {
281:
282: long timestamp = request
283: .getDateHeader("If-Modified-Since");
284:
285: if (timestamp == -1
286: || timestamp >= (document
287: .getLastModifiedDate() / 1000 * 1000)) {
288:
289: return HttpServletResponse.SC_NOT_MODIFIED;
290: } else {
291:
292: }
293: } else {
294:
295: }
296: }
297: } else {
298: values = request.getHeaders("If-Match");
299: if (values.hasMoreElements()) {
300: String etag = document.getETag();
301: if (etag == null) {
302:
303: return HttpServletResponse.SC_PRECONDITION_FAILED;
304: }
305: boolean match = false;
306: do {
307: String value = (String) values.nextElement();
308:
309: if ("*".equals(value) || etag.equals(value))
310: match = true;
311: } while (!match && values.hasMoreElements());
312: if (!match) {
313:
314: return HttpServletResponse.SC_PRECONDITION_FAILED;
315: } else {
316:
317: }
318: }
319: long timestamp = request
320: .getDateHeader("If-Unmodified-Since");
321:
322: if (timestamp != -1) {
323: if ((document.getLastModifiedDate() / 1000 * 1000) > timestamp) {
324:
325: return HttpServletResponse.SC_PRECONDITION_FAILED;
326: } else {
327:
328: }
329: } else {
330: timestamp = request.getDateHeader("If-Modified-Since");
331:
332: if (timestamp != -1
333: && timestamp >= (document.getLastModifiedDate() / 1000 * 1000)) {
334:
335: return HttpServletResponse.SC_NOT_MODIFIED;
336: } else {
337:
338: }
339: }
340: }
341: return HttpServletResponse.SC_OK;
342: }
343:
344: }
|