001: /**
002: *
003: */package org.enhydra.dm;
004:
005: import java.io.IOException;
006: import java.lang.reflect.Array;
007: import java.util.Enumeration;
008: import java.util.HashMap;
009: import java.util.Iterator;
010: import java.util.Map;
011: import java.util.Properties;
012:
013: import javax.naming.Context;
014: import javax.naming.InitialContext;
015: import javax.servlet.ServletConfig;
016: import javax.servlet.ServletException;
017: import javax.servlet.http.HttpServlet;
018: import javax.servlet.http.HttpServletRequest;
019: import javax.servlet.http.HttpServletResponse;
020: import javax.transaction.UserTransaction;
021:
022: import org.enhydra.dm.api.DocumentManager;
023: import org.enhydra.dm.api.DocumentStore;
024: import org.enhydra.dm.api.handler.MethodHandler;
025: import org.enhydra.dm.api.loggers.Log;
026: import org.enhydra.dm.api.util.DesEncription;
027: import org.enhydra.dm.handler.DefaultCheckinHandler;
028: import org.enhydra.dm.handler.DefaultCheckoutHandler;
029: import org.enhydra.dm.handler.DefaultCopyHandler;
030: import org.enhydra.dm.handler.DefaultDeleteHandler;
031: import org.enhydra.dm.handler.DefaultGetHandler;
032: import org.enhydra.dm.handler.DefaultHeadHandler;
033: import org.enhydra.dm.handler.DefaultLockHandler;
034: import org.enhydra.dm.handler.DefaultMkcolHandler;
035: import org.enhydra.dm.handler.DefaultMoveHandler;
036: import org.enhydra.dm.handler.DefaultOptionsHandler;
037: import org.enhydra.dm.handler.DefaultPostHandler;
038: import org.enhydra.dm.handler.DefaultPropfindHandler;
039: import org.enhydra.dm.handler.DefaultProppatchHandler;
040: import org.enhydra.dm.handler.DefaultPutHandler;
041: import org.enhydra.dm.handler.DefaultReportHandler;
042: import org.enhydra.dm.handler.DefaultUncheckoutHandler;
043: import org.enhydra.dm.handler.DefaultUnlockHandler;
044: import org.enhydra.dm.handler.DefaultVersionHandler;
045:
046: import com.lutris.appserver.server.Enhydra;
047: import com.lutris.appserver.server.httpPresentation.servlet.HttpPresentationServlet;
048: import com.lutris.util.ConfigException;
049:
050: /**
051: * @author Slobodan Vujasinovic
052: */
053: public class WebDavServlet extends HttpServlet {
054:
055: private final Map handlers = new HashMap();
056:
057: /**
058: * Transaction object reference
059: */
060: protected UserTransaction transaction = null;
061:
062: public static String transactionJNDIPath;
063:
064: public static final String defaultLogImpl = "org.enhydra.dm.api.loggers.DefaultLog";
065:
066: public static final String defaultDocumentManagerImpl = "org.enhydra.dm.business.DocumentManagerImpl";
067:
068: public static final String defaultDocumentStoreImpl = "org.enhydra.dm.business.DocumentStoreImpl";
069:
070: public static final String defaultUserManagerImpl = "org.enhydra.dm.business.UserManagerImpl";
071:
072: public static final String defaultDesEncriptionImpl = null;
073:
074: private Log logger = null;
075:
076: /**
077: * DesEncription
078: */
079: private DesEncription desenc = null;
080:
081: /**
082: * Document Manager
083: */
084: private DocumentManager documentManager = null;
085:
086: /**
087: * Document Store
088: */
089: private DocumentStore documentStore = null;
090:
091: /**
092: * Enhydra Super Servlet
093: */
094: private HttpPresentationServlet hps;
095:
096: /**
097: * Method for initialization ; Reads parameters from config and initialize application
098: * parts
099: */
100: public void init() throws ServletException {
101: ServletConfig config = getServletConfig();
102: Properties props = null;
103: try {
104: props = readConfigIntoProp(config);
105: transactionJNDIPath = config
106: .getInitParameter("transactionJNDIPath");
107:
108: } catch (Exception ex) {
109: throw new ServletException(ex.getMessage());
110: }
111: initLogger(props);
112: if (null != logger) {
113: logger
114: .log(Log.INFORMATION,
115: "Logger for WebDavServlet is successfully initialized!");
116: }
117: initDocumentManager(props);
118: initDocumentStore(props);
119: initHandlers(config);
120: initDesEncriptor(props);
121:
122: /*
123: * Enhydra Super Servlet Initialization
124: */
125: hps = new HttpPresentationServlet();
126: hps.init(config);
127: }
128:
129: /**
130: * Logger initialization. Try to find logProvider parameter(full class name for Log
131: * class implementation) in config. If parameter does not exist application uses
132: * default implementation: DefaultLog.
133: *
134: * @param config
135: * @throws ServletException
136: */
137: private void initLogger(Properties props) throws ServletException {
138: try {
139: String logProviderName = Log.class.getName();
140: String logProvider = props.getProperty(logProviderName,
141: defaultLogImpl);
142:
143: try {
144:
145: logger = (Log) Class.forName(logProvider).newInstance();
146: Log.setLogger(logger);
147: } catch (Exception ex) {
148:
149: logger = Log.getInstance();
150: }
151: } catch (Exception e) {
152: throw new ServletException(e);
153: }
154:
155: }
156:
157: /**
158: * Manager initialization. Try to find full class name for Manager interface
159: * implementation in config. If parameter does not exist application uses default
160: * implementation: DocumentManagerImpl
161: *
162: * @param config
163: * @throws ServletException
164: */
165: private void initDocumentManager(Properties props)
166: throws ServletException {
167:
168: try {
169:
170: String documentManagerImplClassName = props.getProperty(
171: DocumentManager.class.getName(),
172: defaultDocumentManagerImpl);
173:
174: documentManager = (DocumentManager) Class.forName(
175: documentManagerImplClassName).newInstance();
176:
177: documentManager.setLogger(logger);
178: documentManager.configure(props);
179:
180: } catch (Exception e) {
181: throw new ServletException(e);
182: }
183: }
184:
185: /**
186: * DocumentStore initialization. Try to find full class name for DocumentStore
187: * interface implementation in config. If parameter does not exist application uses
188: * default implementation: DocumentStoreImpl
189: *
190: * @param config
191: * @throws ServletException
192: */
193: private void initDocumentStore(Properties props)
194: throws ServletException {
195:
196: try {
197:
198: String documentStoreImplClassName = props.getProperty(
199: DocumentStore.class.getName(),
200: defaultDocumentStoreImpl);
201:
202: documentStore = (DocumentStore) Class.forName(
203: documentStoreImplClassName).newInstance();
204:
205: documentStore.setLogger(logger);
206: documentStore.configure(props);
207:
208: } catch (Exception e) {
209: throw new ServletException(e);
210: }
211: }
212:
213: /**
214: * DesEncriptor initialization. Try to find full class name for DesEncriptor interface
215: * implementation in config. If parameter does not exist application uses default
216: * implementation: DesEncriptorImpl
217: *
218: * @param config
219: * @throws ServletException
220: */
221: private void initDesEncriptor(Properties props)
222: throws ServletException {
223: try {
224:
225: String desEncriptionImplClass = props.getProperty(
226: DesEncription.class.getName(),
227: defaultDesEncriptionImpl);
228: if (null != desEncriptionImplClass) {
229: desenc = (DesEncription) Class.forName(
230: desEncriptionImplClass).newInstance();
231: if (null != desenc) {
232: desenc.setLogger(logger);
233: desenc.configure(props);
234: } else {
235: if (null != logger) {
236: logger
237: .log(Log.WARNING,
238: "Can't find DesEncriptor implementation class!");
239: }
240: }
241: }
242:
243: } catch (Exception ex) {
244: throw new ServletException(ex);
245: }
246: }
247:
248: /**
249: * Destroy method for all handler implementations
250: */
251: public void destroy() {
252: Iterator iterator = handlers.entrySet().iterator();
253: while (iterator.hasNext()) {
254: ((MethodHandler) ((Map.Entry) iterator.next()).getValue())
255: .destroy();
256: iterator.remove();
257: }
258: hps.destroy();
259: }
260:
261: /**
262: * Service method for WebDavServlet
263: *
264: * @param request The request being handled.
265: * @param response The response supplied by the servlet.
266: * @throws IOException If an IO error occurs while handling the request.
267: * @throws ServletException If an application error occurs.
268: */
269: protected void service(HttpServletRequest request,
270: HttpServletResponse response) throws IOException,
271: ServletException {
272:
273: // Registering Thread to enhydra (getting correct DatabaseManager instance) - DODS usage obligation
274: Enhydra.register(hps.getApplication());
275: try {
276: serviceRequest(request, response);
277: } finally {
278: // Be sure the thread is unregistered no matter what.
279: Enhydra.unRegister();
280: }
281: }
282:
283: /**
284: * ServiceRequest method for WebDavServlet (Calls proper Handler for every request)
285: *
286: * @param request The request being handled.
287: * @param response The response supplied by the servlet.
288: * @throws IOException If an IO error occurs while handling the request.
289: * @throws ServletException If an application error occurs.
290: */
291: protected void serviceRequest(HttpServletRequest request,
292: HttpServletResponse response) throws IOException,
293: ServletException {
294: boolean doCommit = true;
295: try {
296: initTransaction();
297: MethodHandler handler = getHandler(request.getMethod());
298: if (handler != null) {
299: try {
300: handler.service(request, response);
301: } catch (Throwable throwable) {
302: if (null != logger) {
303: logger.log(Log.ERROR, request.getMethod()
304: + " request failure! Reason: "
305: + throwable.getMessage());
306: }
307: fail(request, response);
308: }
309: } else {
310: if (null != logger) {
311: logger.log(Log.ERROR, "Method "
312: + request.getMethod() + " not allowed");
313: }
314: response
315: .sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
316: }
317: } catch (Exception ex) {
318: doCommit = false;
319: throw new ServletException(ex);
320: } finally {
321: if (doCommit) {
322: try {
323: commitTransaction();
324: } catch (Exception e) {
325: e.printStackTrace();
326: }
327: } else {
328: try {
329: rollbackTransaction();
330: } catch (Exception e) {
331: e.printStackTrace();
332: }
333: }
334: }
335: }
336:
337: /**
338: * Returns the <code>MethodHandler</code> for the specified method.
339: *
340: * @param method The HTTP method (GET, POST, PUT, etc.) being handled.
341: * @return A <code>MethodHandler</code> capable of servicing the request using the
342: * given method.
343: */
344: protected MethodHandler getHandler(String method) {
345: if (method == null)
346: return null;
347: return (MethodHandler) handlers.get(method.toUpperCase());
348: }
349:
350: /**
351: * Method for handler initialization. First initialize default implementations then
352: * read config and initialize other implementations; Fill handlers map.
353: *
354: * @param config
355: * @throws ServletException
356: */
357: private void initHandlers(ServletConfig config)
358: throws ServletException {
359: handlers.clear();
360: // WebDav
361: handlers.put("OPTIONS", new DefaultOptionsHandler());
362: handlers.put("HEAD", new DefaultHeadHandler());
363: handlers.put("GET", new DefaultGetHandler());
364: handlers.put("POST", new DefaultPostHandler());
365: handlers.put("DELETE", new DefaultDeleteHandler());
366: handlers.put("PROPFIND", new DefaultPropfindHandler());
367: handlers.put("PROPPATCH", new DefaultProppatchHandler());
368: handlers.put("COPY", new DefaultCopyHandler());
369: handlers.put("MOVE", new DefaultMoveHandler());
370: handlers.put("PUT", new DefaultPutHandler());
371: handlers.put("MKCOL", new DefaultMkcolHandler());
372:
373: handlers.put("LOCK", new DefaultLockHandler());
374: handlers.put("UNLOCK", new DefaultUnlockHandler());
375:
376: // DeltaV
377: handlers.put("VERSION-CONTROL", new DefaultVersionHandler());
378: handlers.put("CHECKOUT", new DefaultCheckoutHandler());
379: handlers.put("UNCHECKOUT", new DefaultUncheckoutHandler());
380: handlers.put("CHECKIN", new DefaultCheckinHandler());
381: handlers.put("REPORT", new DefaultReportHandler());
382:
383: Enumeration parameters = config.getInitParameterNames();
384: while (parameters.hasMoreElements()) {
385: String name = (String) parameters.nextElement();
386: if (!name.startsWith("handler."))
387: continue;
388: String method = name.substring(8);
389: try {
390: handlers.put(method.toUpperCase(), Class.forName(
391: config.getInitParameter(name)).newInstance());
392: } catch (Exception e) {
393: throw new ServletException(e);
394: }
395: }
396: Iterator iterator = handlers.values().iterator();
397: while (iterator.hasNext()) {
398: ((MethodHandler) iterator.next()).init(config,
399: documentManager, documentStore, desenc, logger);
400: }
401: }
402:
403: /**
404: * Method that handle exceptions from all handler implementations
405: *
406: * @param request
407: * @param response
408: * @throws ServletException
409: * @throws IOException
410: */
411: private void fail(HttpServletRequest request,
412: HttpServletResponse response) throws ServletException,
413: IOException {
414:
415: response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
416: response.flushBuffer();
417: }
418:
419: /**
420: * Method initializes DB transation instance
421: */
422: protected void initTransaction() throws Exception {
423: Context ctx = new InitialContext();
424: transaction = (UserTransaction) ctx.lookup(transactionJNDIPath);
425: if (transaction != null) {
426: transaction.begin();
427: }
428: }
429:
430: /**
431: * Method commits DB transation instance
432: */
433: protected void commitTransaction() throws Exception {
434: if (transaction != null) {
435: transaction.commit();
436: }
437:
438: }
439:
440: private void rollbackTransaction() throws Exception {
441: if (transaction != null) {
442: transaction.rollback();
443: }
444: }
445:
446: /**
447: * Methos that generate correspondent Properties object for given ServletConfig object
448: *
449: * @param config
450: * @return
451: * @throws ConfigException
452: */
453: private Properties readConfigIntoProp(ServletConfig config)
454: throws ConfigException {
455: Properties props = new Properties();
456: try {
457: Enumeration leafKeys = config.getInitParameterNames();
458:
459: while (leafKeys.hasMoreElements()) {
460: String leafKey = (String) leafKeys.nextElement();
461: Object value = config.getInitParameter(leafKey);
462: if (value.getClass().isArray()) {
463: int len = Array.getLength(value);
464: String valueArray = Array.get(value, 0).toString();
465: for (int j = 1; j < len; j++) {
466: valueArray = valueArray + ","
467: + Array.get(value, j).toString();
468: }
469: props.put(leafKey + "[]", valueArray);
470: } else {
471: if (value instanceof javax.sql.DataSource) {
472: props.put(leafKey, value.toString());
473: } else {
474: props.put(leafKey, value);
475: }
476: }
477:
478: }
479:
480: } catch (Exception ex) {
481: throw new ConfigException(ex);
482: }
483: return props;
484: }
485: }
|