Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements a metacat web front end as a java Servlet
4
 *  Copyright: 2009 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Michael Daigle
7
 *
8
 *   '$Author: daigle $'
9
 *     '$Date: 2009-08-07 10:35:18 -0700 (Fri, 07 Aug 2009) $'
10
 * '$Revision: 5018 $'
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 */
26

    
27
package edu.ucsb.nceas.metacat.web;
28

    
29
import java.io.IOException;
30
import java.io.PrintWriter;
31
import java.util.Enumeration;
32
import java.util.Hashtable;
33

    
34
import javax.servlet.ServletConfig;
35
import javax.servlet.ServletException;
36
import javax.servlet.http.HttpServlet;
37
import javax.servlet.http.HttpServletRequest;
38
import javax.servlet.http.HttpServletResponse;
39
import javax.servlet.http.HttpSession;
40

    
41
import org.apache.log4j.Logger;
42

    
43
import edu.ucsb.nceas.metacat.AuthSession;
44
import edu.ucsb.nceas.metacat.DBTransform;
45
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
46
import edu.ucsb.nceas.metacat.service.SessionService;
47
import edu.ucsb.nceas.metacat.shared.BaseException;
48
import edu.ucsb.nceas.metacat.shared.ServiceException;
49
import edu.ucsb.nceas.metacat.util.ErrorSendingErrorException;
50
import edu.ucsb.nceas.metacat.util.RequestUtil;
51
import edu.ucsb.nceas.metacat.util.ResponseUtil;
52
import edu.ucsb.nceas.metacat.util.SessionData;
53
import edu.ucsb.nceas.metacat.workflow.WorkflowSchedulerClient;
54

    
55
/**
56
 * A workflow scheduling server implemented as a Java Servlet
57
 *
58
 * Valid actions are:
59
 * 
60
 * action=scheduleWorkflow -- Schedule a workflow to be run.  Scheduling a workflow 
61
 *                            registers it with the scheduling engine and creates a row
62
 *                            in the scheduled_job table.  Note that this may be 
63
 *                            extracted into a separate servlet.
64
 *     delay -- The amount of time from now before the workflow should be run.  The 
65
 *              delay can be expressed in number of seconds, minutes, hours and days, 
66
 *              for instance 30s, 2h, etc.
67
 *     starttime -- The time that the workflow should first run.  If both are provided
68
 *                  this takes precedence over delay.  The time should be expressed as: 
69
 *                  MM/dd/yyyy HH:mm:ss with the timezone assumed to be that of the OS.
70
 *     endtime -- The time when the workflow should end. The time should be expressed as: 
71
 *                  MM/dd/yyyy HH:mm:ss with the timezone assumed to be that of the OS.
72
 *     intervalvalue -- The numeric value of the interval between runs
73
 *     intervalunit -- The unit of the interval between runs.  Can be s, m, h, d for 
74
 *                     seconds, minutes, hours and days respectively
75
 *     workflowid -- The lsid of the workflow that we want to schedule.  This workflow
76
 *                   must already exist in the database.
77
 *     karid -- The karid for the workflow that we want to schedule.
78
 *     workflowname -- The name of the workflow.
79
 *     forwardto -- If provided, forward to this page when processing is done.
80
 *     qformat -- If provided, render results using the stylesheets associated with
81
 *                this skin.  Default is xml.
82
 * action=unscheduleWorkflow -- Unschedule a workflow.  Unscheduling a workflow 
83
 *                            removes it from the scheduling engine and changes the 
84
 *                            status in the scheduled_job table to " unscheduled.  Note 
85
 *                            that this may be extracted into a separate servlet.
86
 *     workflowjobid -- The job ID for the workflow run that we want to unschedule.  This
87
 *                      is held in the database as scheduled_job.name
88
 *     forwardto -- If provided, forward to this page when processing is done.
89
 *     qformat -- If provided, render results using the stylesheets associated with
90
 *                this skin.  Default is xml.
91
 * action=rescheduleWorkflow -- Unschedule a workflow.  Rescheduling a workflow 
92
 *                            registers it with the scheduling engine and changes the 
93
 *                            status in the scheduled_job table to " scheduled.  Note 
94
 *                            that this may be extracted into a separate servlet.
95
 *     workflowjobid -- The job ID for the workflow run that we want to reschedule.  This
96
 *                      is held in the database as scheduled_job.name
97
 *     forwardto -- If provided, forward to this page when processing is done.
98
 *     qformat -- If provided, render results using the stylesheets associated with
99
 *                this skin.  Default is xml.
100
 * action=deleteScheduledWorkflow -- Delete a workflow.  Deleting a workflow 
101
 *                            removes it from the scheduling engine and changes the 
102
 *                            status in the scheduled_job table to " deleted.  Note 
103
 *                            that this may be extracted into a separate servlet.
104
 *     workflowjobid -- The job ID for the workflow run that we want to delete.  This
105
 *                      is held in the database as scheduled_job.name
106
 *     forwardto -- If provided, forward to this page when processing is done.
107
 *     qformat -- If provided, render results using the stylesheets associated with
108
 *                this skin.  Default is xml.
109
 *     
110
 */
111
public class MetacatWebServlet extends HttpServlet {
112

    
113
	/**
114
	 * 
115
	 */
116
	private static final long serialVersionUID = 1L;
117

    
118
    /**
119
     * Initialize the servlet by creating appropriate database connections
120
     */
121
    public void init(ServletConfig config) throws ServletException {
122
    	
123
    	super.init(config);
124
            
125
    }
126
    
127
    /**
128
	 * Close all db connections from the pool
129
	 */
130
    public void destroy() {
131
    	Logger logMetacat = Logger.getLogger(MetacatWebServlet.class);
132
    	
133
        // Close all db connection
134
        logMetacat.warn("Destroying MetacatWebServlet");
135
    }
136
    
137
    /** Handle "GET" method requests from HTTP clients */
138
    public void doGet(HttpServletRequest request, HttpServletResponse response)
139
    throws ServletException, IOException {
140
        
141
        // Process the data and send back the response
142
        handleGetOrPost(request, response);
143
    }
144
    
145
    /** Handle "POST" method requests from HTTP clients */
146
    public void doPost(HttpServletRequest request, HttpServletResponse response)
147
    throws ServletException, IOException {
148
        
149
        // Process the data and send back the response
150
        handleGetOrPost(request, response);
151
    }
152
    
153
    /**
154
	 * Control servlet response depending on the action parameter specified
155
	 */
156
	private void handleGetOrPost(HttpServletRequest request,
157
			HttpServletResponse response) throws ServletException, IOException {
158
		Logger logMetacat = Logger.getLogger(MetacatWebServlet.class);
159

    
160
		// Update the last update time for this user if they are not new
161
		HttpSession httpSession = request.getSession(false);
162
		if (httpSession != null) {
163
			SessionService.touchSession(httpSession.getId());
164
		}
165

    
166
		try {
167

    
168
				String name = null;
169
				String[] value = null;
170
				Hashtable<String, String[]> params = new Hashtable<String, String[]>();
171

    
172
				Enumeration<String> paramlist =(Enumeration<String>)request.getParameterNames();
173
				while (paramlist.hasMoreElements()) {
174

    
175
					name = paramlist.nextElement();
176
					value = request.getParameterValues(name);
177

    
178
					params.put(name, value);
179
				}
180

    
181
				// handle param is emptpy
182
				if (params.isEmpty() || params == null) {
183
					return;
184
				}
185

    
186
				// if the user clicked on the input images, decode which image
187
				// was clicked then set the action.
188
				if (params.get("action") == null) {
189
					PrintWriter out = response.getWriter();
190
					response.setContentType("text/xml");
191
					out.println("<?xml version=\"1.0\"?>");
192
					out.println("<error>");
193
					out.println("Action not specified");
194
					out.println("</error>");
195
					out.close();
196
					return;
197
				}
198

    
199
				String action = (params.get("action"))[0];
200
				logMetacat.info("Action is: " + action);
201

    
202
				// This block handles session management for the servlet
203
				// by looking up the current session information for all actions
204
				// other than "login" and "logout"
205
				String userName = null;
206
				String[] groupNames = null;
207
				name = null;
208

    
209
				// handle login action
210
				if (action.equals("login")) {
211
					PrintWriter out = response.getWriter();
212
					handleLoginAction(out, params, request, response);
213
					out.close();
214

    
215
					// handle logout action
216
				} else if (action.equals("logout")) {
217
					PrintWriter out = response.getWriter();
218
					handleLogoutAction(out, params, request, response);
219
					out.close();
220

    
221
					// handle shrink DBConnection request
222
				} else if (action.equals("shrink")) {
223
					PrintWriter out = response.getWriter();
224
					boolean success = false;
225
					// If all DBConnection in the pool are free and DBConnection pool
226
					// size is greater than initial value, shrink the connection pool
227
					// size to initial value
228
					success = DBConnectionPool.shrinkConnectionPoolSize();
229
					if (success) {
230
						// if successfully shrink the pool size to initial value
231
						out.println("DBConnection Pool shrunk successfully.");
232
					}// if
233
					else {
234
						out.println("DBConnection pool not shrunk successfully.");
235
					}
236
					// close out put
237
					out.close();
238

    
239
					// aware of session expiration on every request
240
				} else {
241
					SessionData sessionData = RequestUtil.getSessionData(request);
242
					
243
					userName = sessionData.getUserName();
244
//					password = sessionData.getPassword();
245
					groupNames = sessionData.getGroupNames();
246
//					sessionId = sessionData.getId();
247

    
248
					logMetacat.info("The user is : " + userName);
249
				}
250
				
251
				if (action.equals("scheduleWorkflow")) {
252
					try {
253
						WorkflowSchedulerClient.getInstance().scheduleJob(request, response, params, 
254
							userName, groupNames);
255
						return;
256
					} catch (BaseException be) {
257
						ResponseUtil.sendErrorXML(response, ResponseUtil.SCHEDULE_WORKFLOW_ERROR, be);
258
						return;						
259
					}
260
				} else if (action.equals("unscheduleWorkflow")) {
261
					try {
262
						WorkflowSchedulerClient.getInstance().unScheduleJob(request, response, params, 
263
							userName, groupNames);
264
						return;
265
					} catch (BaseException be) {
266
						ResponseUtil.sendErrorXML(response, ResponseUtil.UNSCHEDULE_WORKFLOW_ERROR, be);
267
						return;						
268
					}
269
				} else if (action.equals("rescheduleWorkflow")) {
270
					try {
271
						WorkflowSchedulerClient.getInstance().reScheduleJob(request, response, params, 
272
							userName, groupNames);
273
						return;
274
					} catch (BaseException be) {
275
						ResponseUtil.sendErrorXML(response, ResponseUtil.RESCHEDULE_WORKFLOW_ERROR, be);
276
						return;						
277
					}
278
				} else if (action.equals("getScheduledWorkflow")) {
279
					try {
280
						WorkflowSchedulerClient.getInstance().getJobs(request, response, params, 
281
								userName, groupNames);				
282
						return;
283
					} catch (BaseException be) {
284
						ResponseUtil.sendErrorXML(response, ResponseUtil.GET_SCHEDULED_WORKFLOW_ERROR, be);
285
						return;						
286
					}
287
				} else if (action.equals("deleteScheduledWorkflow")) {
288
					try {
289
						WorkflowSchedulerClient.getInstance().deleteJob(request, response, params, 
290
								userName, groupNames);				
291
						return;
292
					} catch (BaseException be) {
293
						ResponseUtil.sendErrorXML(response, ResponseUtil.DELETE_SCHEDULED_WORKFLOW_ERROR, be);
294
						return;						
295
					}
296
				} else {
297
					PrintWriter out = response.getWriter();
298
					out.println("<?xml version=\"1.0\"?>");
299
					out.println("<error>");
300
					out.println("Error: action not registered.  Please report this error.");
301
					out.println("</error>");
302
					out.close();
303
				}
304
		} catch (ErrorSendingErrorException esee) {
305
			String errorString = "Error sending error message: " + esee.getMessage();
306
			logMetacat.error(errorString);
307
			throw new ServletException(errorString);
308
		} 
309
	}
310
    
311
    // LOGIN & LOGOUT SECTION
312
    /**
313
	 * Handle the login request. Create a new session object. Do user
314
	 * authentication through the session.
315
	 */
316
    private void handleLoginAction(PrintWriter out, Hashtable<String, String[]> params,
317
            HttpServletRequest request, HttpServletResponse response) {
318
        Logger logMetacat = Logger.getLogger(MetacatWebServlet.class);
319
        AuthSession sess = null;
320
        
321
        if(params.get("username") == null){
322
            response.setContentType("text/xml");
323
            out.println("<?xml version=\"1.0\"?>");
324
            out.println("<error>");
325
            out.println("Username not specified");
326
            out.println("</error>");
327
            return;
328
        }
329
        
330
        // }
331
        
332
        if(params.get("password") == null){
333
            response.setContentType("text/xml");
334
            out.println("<?xml version=\"1.0\"?>");
335
            out.println("<error>");
336
            out.println("Password not specified");
337
            out.println("</error>");
338
            return;
339
        }
340
        
341
        String un = (params.get("username"))[0];
342
        logMetacat.info("user " + un + " is trying to login");
343
        String pw = (params.get("password"))[0];
344
        
345
        String qformat = "xml";
346
        if(params.get("qformat") != null){
347
            qformat = (params.get("qformat"))[0];
348
        }
349
        
350
        try {
351
            sess = new AuthSession();
352
        } catch (Exception e) {
353
        	String errorMsg = "Problem in MetacatWebServlet.handleLoginAction() authenicating session: "
354
                + e.getMessage();
355
            logMetacat.error(errorMsg);
356
            out.println(errorMsg);
357
            return;
358
        }
359
        boolean isValid = sess.authenticate(request, un, pw);
360
        
361
        //if it is authernticate is true, store the session
362
        if (isValid) {
363
            HttpSession session = sess.getSessions();
364
            String id = session.getId();
365
            logMetacat.debug("Store session id " + id
366
                    + " which has username" + session.getAttribute("username")
367
                    + " into hash in login method");
368
            try {
369
				SessionService.registerSession(id, (String) session
370
						.getAttribute("username"), (String[]) session
371
						.getAttribute("groupnames"), (String) session
372
						.getAttribute("password"));
373
			} catch (ServiceException se) {
374
				String errorMsg = "Problem in MetacatWebServlet.handleLoginAction() registering session: "
375
						+ se.getMessage();
376
				logMetacat.error(errorMsg);
377
				out.println(errorMsg);
378
				return;
379
			}
380
        }
381
        
382
        // format and transform the output
383
        if (qformat.equals("xml")) {
384
            response.setContentType("text/xml");
385
            out.println(sess.getMessage());
386
        } else {
387
            try {
388
                DBTransform trans = new DBTransform();
389
                response.setContentType("text/html");
390
                trans.transformXMLDocument(sess.getMessage(),
391
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
392
                        out, null, null);
393
            } catch (Exception e) {               
394
                logMetacat.error("Error in MetacatWebServlet.handleLoginAction: "
395
                        + e.getMessage());
396
            }
397
        }
398
    }
399
    
400
    /**
401
     * Handle the logout request. Close the connection.
402
     */
403
    private void handleLogoutAction(PrintWriter out, Hashtable<String, String[]> params,
404
            HttpServletRequest request, HttpServletResponse response) {
405
        Logger logMetacat = Logger.getLogger(MetacatWebServlet.class);
406
        String qformat = "xml";
407
        if(params.get("qformat") != null){
408
            qformat = params.get("qformat")[0];
409
        }
410
        
411
        // close the connection
412
        HttpSession sess = request.getSession(false);
413
        logMetacat.info("After get session in logout request");
414
        if (sess != null) {
415
            logMetacat.info("The session id " + sess.getId()
416
            + " will be invalidate in logout action");
417
            logMetacat.info("The session contains user "
418
                    + sess.getAttribute("username")
419
                    + " will be invalidate in logout action");
420
            sess.invalidate();
421
            SessionService.unRegisterSession(sess.getId());
422
        }
423
        
424
        // produce output
425
        StringBuffer output = new StringBuffer();
426
        output.append("<?xml version=\"1.0\"?>");
427
        output.append("<logout>");
428
        output.append("User logged out");
429
        output.append("</logout>");
430
        
431
        //format and transform the output
432
        if (qformat.equals("xml")) {
433
            response.setContentType("text/xml");
434
            out.println(output.toString());
435
        } else {
436
            try {
437
                DBTransform trans = new DBTransform();
438
                response.setContentType("text/html");
439
                trans.transformXMLDocument(output.toString(),
440
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
441
                        out, null, null);
442
            } catch (Exception e) {
443
                logMetacat.error(
444
                        "Error in MetacatWebServlet.handleLogoutAction"
445
                        + e.getMessage());
446
            }
447
        }
448
    }
449
}
    (1-1/1)