Project

General

Profile

1 2096 jones
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2004 Regents of the University of California and the
4
 *             National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author$'
7
 *     '$Date$'
8
 * '$Revision$'
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, write to the Free Software
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 */
24
package edu.ucsb.nceas.metacat;
25
26 2104 jones
import java.sql.PreparedStatement;
27 2111 jones
import java.sql.ResultSet;
28 2096 jones
import java.sql.SQLException;
29 2104 jones
import java.sql.Timestamp;
30 6595 leinfelder
import java.util.ArrayList;
31 2096 jones
import java.util.Date;
32 8464 leinfelder
import java.util.HashMap;
33 6595 leinfelder
import java.util.List;
34 8464 leinfelder
import java.util.Map;
35 7285 leinfelder
import java.util.Vector;
36 2096 jones
37 2663 sgarg
import org.apache.log4j.Logger;
38 8810 leinfelder
import org.dataone.service.types.v1.Identifier;
39
import org.dataone.service.types.v2.Log;
40
import org.dataone.service.types.v2.LogEntry;
41 7285 leinfelder
import org.dataone.service.types.v1.Event;
42
import org.dataone.service.types.v1.NodeReference;
43
import org.dataone.service.types.v1.Subject;
44 6944 leinfelder
import org.dataone.service.util.DateTimeMarshaller;
45 2663 sgarg
46 5015 daigle
import edu.ucsb.nceas.metacat.database.DBConnection;
47
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
48 7437 leinfelder
import edu.ucsb.nceas.metacat.database.DatabaseService;
49 8464 leinfelder
import edu.ucsb.nceas.metacat.index.MetacatSolrIndex;
50 7285 leinfelder
import edu.ucsb.nceas.metacat.properties.PropertyService;
51 7409 leinfelder
import edu.ucsb.nceas.metacat.util.DocumentUtil;
52 7285 leinfelder
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
53 5015 daigle
54 2096 jones
/**
55
 * EventLog is used to intialize and store a log of events that occur in an
56
 * application. The events are registered with the logger as they occur, but
57
 * EventLog writes them to permenant storage when it is most convenient or
58
 * efficient. EventLog is a Singleton as there should always be only one object
59
 * for these logging events.
60
 *
61
 * TODO: Logging to the database needn't be synchronous with the event.
62
 * Instead, a separate thread can be launched that periodically sleeps and only
63
 * wakes periodically to see if metacat is idle.  The log event can be cached
64
 * and inserted later when the thread wakes and finds metacat idle.
65
 *
66
 * TODO: Write a function that archives a part of the log table to an
67
 * external text file so that the log table doesn't get to big.  This
68
 * function should be able to be called manually or on a schedule.
69
 *
70
 * TODO: Write an access function that returns an XML report for a
71
 * specific subset of events.  Users should be able to query on
72
 * principal, docid/rev, date, event, and possibly other fields.
73
 *
74
 * @author jones
75
 */
76
public class EventLog
77
{
78 8896 tao
    public static final String DELETE = "delete";
79 2096 jones
    /**
80
     * The single instance of the event log that is always returned.
81
     */
82
    private static EventLog self = null;
83 2663 sgarg
    private Logger logMetacat = Logger.getLogger(EventLog.class);
84 9107 tao
    private static final int USERAGENTLENGTH = 512;
85 2096 jones
86 9489 tao
87 2096 jones
    /**
88
     * A private constructor that initializes the class when getInstance() is
89
     * called.
90
     */
91
    private EventLog()
92
    {
93
    }
94
95
    /**
96
     * Return the single instance of the event log after initializing it if it
97
     * wasn't previously initialized.
98
     *
99
     * @return the single EventLog instance
100
     */
101
    public static EventLog getInstance()
102
    {
103
        if (self == null) {
104
            self = new EventLog();
105
        }
106
        return self;
107
    }
108
109
    /**
110
     * Log an event of interest to the application. The information logged can
111
     * include basic identification information about the principal or computer
112
     * that initiated the event.
113
     *
114 2099 jones
     * @param ipAddress the internet protocol address for the event
115 6542 leinfelder
     * @param userAgent the agent making the request
116 2099 jones
	 * @param principal the principal for the event (a username, etc)
117
	 * @param docid the identifier of the document to which the event applies
118
	 * @param event the string code for the event
119 2096 jones
     */
120 6542 leinfelder
    public void log(String ipAddress, String userAgent, String principal, String docid, String event) {
121 9098 tao
        EventLogData logData = new EventLogData(ipAddress, userAgent, principal, docid, event);
122 2096 jones
        insertLogEntry(logData);
123 8464 leinfelder
124
        // update the event information in the index
125
        try {
126
	        String localId = DocumentUtil.getSmartDocId(docid);
127
			int rev = DocumentUtil.getRevisionFromAccessionNumber(docid);
128
129
	        String guid = IdentifierManager.getInstance().getGUID(localId, rev);
130
	        Identifier pid = new Identifier();
131
	        pid.setValue(guid);
132
133
	        // submit for indexing
134 8647 leinfelder
	        MetacatSolrIndex.getInstance().submit(pid, null, this.getIndexFields(pid, event), false);
135 8464 leinfelder
136
        } catch (Exception e) {
137
        	logMetacat.error("Could not update event index information", e);
138
        }
139 2096 jones
    }
140 2099 jones
141 8464 leinfelder
    public Map<String, List<Object>> getIndexFields(Identifier pid, String event) {
142
    	// update the search index for the event
143
        try {
144
145 8810 leinfelder
        	if (event != null) {
146 8596 leinfelder
147 8810 leinfelder
	        	String fieldName = event + "_count_i";
148 8596 leinfelder
	        	int eventCount = 0;
149
150
	        	String docid = IdentifierManager.getInstance().getLocalId(pid.getValue());
151 8810 leinfelder
	        	Log eventLog = this.getD1Report(null, null, new String[] {docid}, event, null, null, false, 0, 0);
152 8596 leinfelder
	        	eventCount = eventLog.getTotal();
153
154
		        List<Object> values = new ArrayList<Object>();
155
				values.add(eventCount);
156
		        Map<String, List<Object>> fields = new HashMap<String, List<Object>>();
157
		        fields.put(fieldName, values);
158
159
		        return fields;
160
        	}
161 8464 leinfelder
162
        } catch (Exception e) {
163 8596 leinfelder
        	logMetacat.error("Could not update event index information on pid: " + pid.getValue() + " for event: " + event, e);
164 8464 leinfelder
        }
165 8596 leinfelder
        // default if we can't find the event information
166
    	return null;
167
168 8464 leinfelder
    }
169
170 2096 jones
    /**
171
     * Insert a single log event record to the database.
172
     *
173
     * @param logData the data to be logged when an event occurs
174
     */
175
    private void insertLogEntry(EventLogData logData)
176
    {
177
        String insertString = "insert into access_log"
178 6542 leinfelder
                + "(ip_address, user_agent, principal, docid, "
179 2096 jones
                + "event, date_logged) "
180 6595 leinfelder
                + "values ( ?, ?, ?, ?, ?, ? )";
181
182 2096 jones
        DBConnection dbConn = null;
183
        int serialNumber = -1;
184
        try {
185
            // Get a database connection from the pool
186 2111 jones
            dbConn = DBConnectionPool.getDBConnection("EventLog.insertLogEntry");
187 2096 jones
            serialNumber = dbConn.getCheckOutSerialNumber();
188 9107 tao
            String userAgent = logData.getUserAgent();
189
            if(userAgent != null && userAgent.length() > USERAGENTLENGTH) {
190
                userAgent = userAgent.substring(0, USERAGENTLENGTH);
191
            }
192 2096 jones
193
            // Execute the insert statement
194 2104 jones
            PreparedStatement stmt = dbConn.prepareStatement(insertString);
195 6595 leinfelder
196
            stmt.setString(1, logData.getIpAddress());
197 9107 tao
            stmt.setString(2, userAgent);
198 6595 leinfelder
            stmt.setString(3, logData.getPrincipal());
199
            stmt.setString(4, logData.getDocid());
200
            stmt.setString(5, logData.getEvent());
201
            stmt.setTimestamp(6, new Timestamp(new Date().getTime()));
202 2104 jones
            stmt.executeUpdate();
203 2096 jones
            stmt.close();
204
        } catch (SQLException e) {
205 2663 sgarg
        	logMetacat.error("Error while logging event to database: "
206
                    + e.getMessage());
207 2096 jones
        } finally {
208
            // Return database connection to the pool
209
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
210
        }
211
    }
212 2110 jones
213
    /**
214
     * Get a report of the log events that match a set of filters.  The
215 2111 jones
     * filter parameters can be null; log records are subset based on
216 2110 jones
     * non-null filter parameters.
217
     *
218
     * @param ipAddress the internet protocol address for the event
219
	 * @param principal the principal for the event (a username, etc)
220
	 * @param docid the identifier of the document to which the event applies
221
	 * @param event the string code for the event
222 2111 jones
	 * @param startDate beginning of date range for query
223
	 * @param endDate end of date range for query
224
	 * @return an XML-formatted report of the access log entries
225 2110 jones
     */
226 2111 jones
    public String getReport(String[] ipAddress, String[] principal, String[] docid,
227 5693 leinfelder
            String[] event, Timestamp startDate, Timestamp endDate, boolean anonymous)
228 2110 jones
    {
229 2111 jones
        StringBuffer resultDoc = new StringBuffer();
230
        StringBuffer query = new StringBuffer();
231 6542 leinfelder
        query.append("select entryid, ip_address, user_agent, principal, docid, "
232 2111 jones
            + "event, date_logged from access_log");
233
//                        + ""
234
//                        + "event, date_logged) " + "values (" + "'"
235
//                        + logData.getIpAddress() + "', " + "'"
236
//                        + logData.getPrincipal() + "', " + "'"
237
//                        + logData.getDocid() + "', " + "'" + logData.getEvent()
238
//                        + "', " + " ? " + ")";
239
        if (ipAddress != null || principal != null || docid != null
240
                        || event != null || startDate != null || endDate != null) {
241
            query.append(" where ");
242
        }
243
        boolean clauseAdded = false;
244
        int startIndex = 0;
245
        int endIndex = 0;
246
247 6595 leinfelder
        List<String> paramValues = new ArrayList<String>();
248 2111 jones
        if (ipAddress != null) {
249 6595 leinfelder
        	query.append("ip_address in (");
250
        	for (int i = 0; i < ipAddress.length; i++) {
251
        		if (i > 0) {
252
            		query.append(", ");
253
        		}
254
        		query.append("?");
255
        		paramValues.add(ipAddress[i]);
256
        	}
257
        	query.append(") ");
258 2111 jones
            clauseAdded = true;
259
        }
260
        if (principal != null) {
261 7309 leinfelder
        	if (clauseAdded) {
262
                query.append(" and ");
263
            }
264 6595 leinfelder
        	query.append("principal in (");
265
        	for (int i = 0; i < principal.length; i++) {
266
        		if (i > 0) {
267
            		query.append(", ");
268
        		}
269
        		query.append("?");
270
        		paramValues.add(principal[i]);
271
        	}
272
        	query.append(") ");
273 2111 jones
            clauseAdded = true;
274
        }
275
        if (docid != null) {
276 7309 leinfelder
        	if (clauseAdded) {
277
                query.append(" and ");
278
            }
279 6595 leinfelder
        	query.append("docid in (");
280
        	for (int i = 0; i < docid.length; i++) {
281
        		if (i > 0) {
282
            		query.append(", ");
283
        		}
284
        		query.append("?");
285 7409 leinfelder
        		String fullDocid = docid[i];
286
        		// allow docid without revision - look up latest version
287
        		try {
288
        			fullDocid = DocumentUtil.appendRev(fullDocid);
289
        		} catch (Exception e) {
290
					// just warn about this
291
        			logMetacat.warn("Could not check docid for revision: " + fullDocid, e);
292
				}
293
        		paramValues.add(fullDocid);
294 6595 leinfelder
        	}
295
        	query.append(") ");
296 2111 jones
            clauseAdded = true;
297
        }
298
        if (event != null) {
299 7309 leinfelder
        	if (clauseAdded) {
300
                query.append(" and ");
301
            }
302 6595 leinfelder
        	query.append("event in (");
303
        	for (int i = 0; i < event.length; i++) {
304
        		if (i > 0) {
305
            		query.append(", ");
306
        		}
307
        		query.append("?");
308
        		paramValues.add(event[i]);
309
        	}
310
        	query.append(") ");
311 2111 jones
            clauseAdded = true;
312
        }
313
        if (startDate != null) {
314
            if (clauseAdded) {
315
                query.append(" and ");
316
            }
317 7057 leinfelder
            query.append("date_logged >= ?");
318 2111 jones
            clauseAdded = true;
319
            startIndex++;
320
        }
321
        if (endDate != null) {
322
            if (clauseAdded) {
323
                query.append(" and ");
324
            }
325
            query.append("date_logged < ?");
326
            clauseAdded = true;
327
            endIndex = startIndex + 1;
328
        }
329
        DBConnection dbConn = null;
330
        int serialNumber = -1;
331
        try {
332
            // Get a database connection from the pool
333
            dbConn = DBConnectionPool.getDBConnection("EventLog.getReport");
334
            serialNumber = dbConn.getCheckOutSerialNumber();
335
336 2113 jones
            // Execute the query statement
337 2111 jones
            PreparedStatement stmt = dbConn.prepareStatement(query.toString());
338 6595 leinfelder
            //set the param values
339
            int parameterIndex = 1;
340
            for (String val: paramValues) {
341 7309 leinfelder
            	stmt.setString(parameterIndex++, val);
342 6595 leinfelder
            }
343 6598 leinfelder
            if (startDate != null) {
344
                stmt.setTimestamp(parameterIndex++, startDate);
345 2111 jones
            }
346 6598 leinfelder
            if (endDate != null) {
347
            	stmt.setTimestamp(parameterIndex++, endDate);
348 2111 jones
            }
349
            stmt.execute();
350
            ResultSet rs = stmt.getResultSet();
351 2113 jones
            //process the result and return it as an XML document
352 2111 jones
            resultDoc.append("<?xml version=\"1.0\"?>\n");
353
            resultDoc.append("<log>\n");
354
            while (rs.next()) {
355 5693 leinfelder
                resultDoc.append(
356
                		generateXmlRecord(
357
                				rs.getString(1), //id
358
                				anonymous ? "" : rs.getString(2), //ip
359 6542 leinfelder
                				rs.getString(3), //userAgent
360
                				anonymous ? "" : rs.getString(4), //principal
361 5693 leinfelder
                                rs.getString(5),
362 6542 leinfelder
                                rs.getString(6),
363
                                rs.getTimestamp(7)));
364 2111 jones
            }
365
            resultDoc.append("</log>");
366
            stmt.close();
367
        } catch (SQLException e) {
368 2663 sgarg
        	logMetacat.info("Error while logging event to database: "
369
                            + e.getMessage());
370 2111 jones
        } finally {
371
            // Return database connection to the pool
372
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
373
        }
374
        return resultDoc.toString();
375 2110 jones
    }
376 2111 jones
377 8896 tao
    /**
378
     * A utility method to determine if the given docid was deleted.
379
     * @param docid the specified docid
380
     * @return true if there is a delete event for the id; false otherwise.
381
     */
382
    public boolean isDeleted(String docid) {
383
        boolean deleted =false;
384
        if(docid != null || !docid.trim().equals("")) {
385
            String[] docids = new String[1];
386
            docids[0] = docid;
387
            String[] events = new String[1];
388
            events[0]= DELETE;
389
            String[] ipAddress = null;
390
            String[] principal = null;
391
            Timestamp startDate = null;
392
            Timestamp endDate = null;
393
            boolean anonymous = false;
394
395
            String report =getReport(ipAddress, principal, docids,
396
                     events, startDate, endDate, anonymous);
397
            //System.out.println("the report is "+report);
398
            if(report != null && report.contains("<event>"+DELETE+"</event>") ){
399
                deleted = true;
400
            }
401
        }
402
        return deleted;
403
    }
404 7285 leinfelder
405
    public Log getD1Report(String[] ipAddress, String[] principal, String[] docid,
406 8810 leinfelder
            String event, Timestamp startDate, Timestamp endDate, boolean anonymous, Integer start, Integer count)
407 7285 leinfelder
    {
408 9489 tao
        boolean isCreateEvent = false;
409 7285 leinfelder
        Log log = new Log();
410
411
    	NodeReference memberNode = new NodeReference();
412
        String nodeId = "localhost";
413
        try {
414
            nodeId = PropertyService.getProperty("dataone.nodeId");
415
        } catch (PropertyNotFoundException e1) {
416
            // TODO Auto-generated catch block
417
            e1.printStackTrace();
418
        }
419
        memberNode.setValue(nodeId);
420
421 9410 leinfelder
        // subquery does the heavy lifting
422
        StringBuffer subQueryFrom = new StringBuffer();
423
        subQueryFrom.append("from access_log ");
424 7451 leinfelder
425 9410 leinfelder
        boolean clauseAdded = false;
426 7285 leinfelder
427
        List<String> paramValues = new ArrayList<String>();
428
        if (ipAddress != null) {
429 7309 leinfelder
        	if (clauseAdded) {
430 9410 leinfelder
        		subQueryFrom.append(" and ");
431
            } else {
432
            	subQueryFrom.append(" where ");
433 7309 leinfelder
            }
434 9410 leinfelder
        	subQueryFrom.append("ip_address in (");
435 7285 leinfelder
        	for (int i = 0; i < ipAddress.length; i++) {
436
        		if (i > 0) {
437 9410 leinfelder
        			subQueryFrom.append(", ");
438 7285 leinfelder
        		}
439 9410 leinfelder
        		subQueryFrom.append("?");
440 7285 leinfelder
        		paramValues.add(ipAddress[i]);
441
        	}
442 9410 leinfelder
        	subQueryFrom.append(") ");
443 7285 leinfelder
            clauseAdded = true;
444
        }
445
        if (principal != null) {
446 7309 leinfelder
        	if (clauseAdded) {
447 9410 leinfelder
        		subQueryFrom.append(" and ");
448
            } else {
449
            	subQueryFrom.append(" where ");
450 7309 leinfelder
            }
451 9410 leinfelder
        	subQueryFrom.append("principal in (");
452 7285 leinfelder
        	for (int i = 0; i < principal.length; i++) {
453
        		if (i > 0) {
454 9410 leinfelder
        			subQueryFrom.append(", ");
455 7285 leinfelder
        		}
456 9410 leinfelder
        		subQueryFrom.append("?");
457 7285 leinfelder
        		paramValues.add(principal[i]);
458
        	}
459 9410 leinfelder
        	subQueryFrom.append(") ");
460 7285 leinfelder
            clauseAdded = true;
461
        }
462
        if (docid != null) {
463 7309 leinfelder
        	if (clauseAdded) {
464 9410 leinfelder
        		subQueryFrom.append(" and ");
465
            } else {
466
            	subQueryFrom.append(" where ");
467 7309 leinfelder
            }
468 9422 leinfelder
        	subQueryFrom.append("docid in (");
469 7285 leinfelder
        	for (int i = 0; i < docid.length; i++) {
470
        		if (i > 0) {
471 9410 leinfelder
        			subQueryFrom.append(", ");
472 7285 leinfelder
        		}
473 9410 leinfelder
        		subQueryFrom.append("?");
474 7285 leinfelder
        		paramValues.add(docid[i]);
475
        	}
476 9410 leinfelder
        	subQueryFrom.append(") ");
477 7285 leinfelder
            clauseAdded = true;
478
        }
479 9489 tao
480
       //please make sure the handling of event is just before the the startDate clause!!!
481 7285 leinfelder
        if (event != null) {
482 9489 tao
            if (clauseAdded) {
483
                subQueryFrom.append(" and ");
484 9410 leinfelder
            } else {
485 9489 tao
                subQueryFrom.append(" where ");
486 7309 leinfelder
            }
487 9489 tao
            subQueryFrom.append("event in (");
488
            subQueryFrom.append("?");
489
            String eventString = event;
490
            if (eventString.equals(Event.CREATE.xmlValue())) {
491
                isCreateEvent = true; //since the create event maps create, insert and et al, we handle it in different way
492
                subQueryFrom.append(",?");// for INSERT, the insert is handled by line 508
493
                subQueryFrom.append(",?");// for upload
494
                subQueryFrom.append(",?");// for UPLOAD
495
                subQueryFrom.append(",?");// for create
496
                //eventString = "insert,INSERT,upload,UPLOAD,create";
497
            } else {
498
                paramValues.add(eventString);
499
            }
500
            subQueryFrom.append(") ");
501 7285 leinfelder
            clauseAdded = true;
502
        }
503 9489 tao
504 7285 leinfelder
        if (startDate != null) {
505
            if (clauseAdded) {
506 9410 leinfelder
            	subQueryFrom.append(" and ");
507
            } else {
508
            	subQueryFrom.append(" where ");
509 7285 leinfelder
            }
510 9410 leinfelder
            subQueryFrom.append("date_logged >= ?");
511 7285 leinfelder
            clauseAdded = true;
512
        }
513
        if (endDate != null) {
514
            if (clauseAdded) {
515 9410 leinfelder
            	subQueryFrom.append(" and ");
516
            } else {
517
            	subQueryFrom.append(" where ");
518 7285 leinfelder
            }
519 9410 leinfelder
            subQueryFrom.append("date_logged < ?");
520 7285 leinfelder
            clauseAdded = true;
521
        }
522 9489 tao
523
524 7437 leinfelder
525 9410 leinfelder
        // count query
526
        String countSelect = "select count(*) ";
527
528
        // subquery select
529
        String subquerySelect = "select entryid ";
530
531
        // for selecting fields we want in the join
532
        String fieldSelect =
533
        		"select " +
534
        		"entryid, " +
535
        		"id.guid as identifier, " +
536
        		"ip_address, " +
537
        		"user_agent, " +
538
        		"principal, " +
539
        		"case " +
540
        		"	when event = 'insert' then 'create' " +
541 9488 tao
        		" when event = 'INSERT' then 'create' " +
542
        		" when event = 'upload' then 'create' " +
543
        		" when event = 'UPLOAD' then 'create' " +
544 9410 leinfelder
        		"	else event " +
545
        		"end as event, " +
546
        		"date_logged " +
547
        		"from access_log al, identifier id " +
548
        		"where al.docid = id.docid||'.'||id.rev " +
549
        		"and al.entryid in ";
550
551 7437 leinfelder
        // order by
552 7451 leinfelder
        String orderByClause = " order by entryid ";
553 9410 leinfelder
554 7451 leinfelder
        // select the count
555 9410 leinfelder
        String countQuery = countSelect + subQueryFrom.toString();
556
        logMetacat.debug("The count query is " + countQuery);
557
		// select the fields using paged subquery and fields join query
558
        String pagedSubquery = DatabaseService.getInstance().getDBAdapter().getPagedQuery(subquerySelect + subQueryFrom.toString() + orderByClause, start, count);
559
        String pagedQuery = fieldSelect + " ( " + pagedSubquery + " ) " + orderByClause;
560
        logMetacat.debug("The selection query is " + pagedQuery);
561
        logMetacat.debug("The startDate in the query is " + startDate);
562
        logMetacat.debug("The endDate in the query is " + startDate);
563 7437 leinfelder
564 7285 leinfelder
        DBConnection dbConn = null;
565
        int serialNumber = -1;
566
        try {
567
            // Get a database connection from the pool
568
            dbConn = DBConnectionPool.getDBConnection("EventLog.getD1Report");
569
            serialNumber = dbConn.getCheckOutSerialNumber();
570
571
            // Execute the query statement
572 7451 leinfelder
            PreparedStatement fieldsStmt = dbConn.prepareStatement(pagedQuery);
573
            PreparedStatement countStmt = dbConn.prepareStatement(countQuery);
574
575 7285 leinfelder
            //set the param values
576
            int parameterIndex = 1;
577
            for (String val: paramValues) {
578 7451 leinfelder
            	countStmt.setString(parameterIndex, val);
579
            	fieldsStmt.setString(parameterIndex, val);
580
            	parameterIndex++;
581 7285 leinfelder
            }
582 9489 tao
583
            if(isCreateEvent) {
584
                //handle the event mapping. If we add another event mapping, we need add a "?" in line 496
585
                //those values are not in the paramValues.
586
                countStmt.setString(parameterIndex, "insert");
587
                fieldsStmt.setString(parameterIndex, "insert");
588
                parameterIndex++;
589
                countStmt.setString(parameterIndex, "INSERT");
590
                fieldsStmt.setString(parameterIndex, "INSERT");
591
                parameterIndex++;
592
                countStmt.setString(parameterIndex, "upload");
593
                fieldsStmt.setString(parameterIndex, "upload");
594
                parameterIndex++;
595
                countStmt.setString(parameterIndex, "UPLOAD");
596
                fieldsStmt.setString(parameterIndex, "UPLOAD");
597
                parameterIndex++;
598
                countStmt.setString(parameterIndex, "create");
599
                fieldsStmt.setString(parameterIndex, "create");
600
                parameterIndex++;
601
            }
602
603 7285 leinfelder
            if (startDate != null) {
604 7451 leinfelder
            	countStmt.setTimestamp(parameterIndex, startDate);
605
                fieldsStmt.setTimestamp(parameterIndex, startDate);
606
            	parameterIndex++;
607 7285 leinfelder
            }
608
            if (endDate != null) {
609 7451 leinfelder
            	countStmt.setTimestamp(parameterIndex, endDate);
610
            	fieldsStmt.setTimestamp(parameterIndex, endDate);
611
            	parameterIndex++;
612 7285 leinfelder
            }
613 9489 tao
614 7451 leinfelder
615
            // for the return Log list
616 7285 leinfelder
            List<LogEntry> logs = new Vector<LogEntry>();
617
618 7451 leinfelder
            // get the fields form the query
619
            if (count != 0) {
620 9408 tao
                long startTime = System.currentTimeMillis();
621
                logMetacat.debug("Time to start to execute the selection query "+startTime);
622 7451 leinfelder
	            fieldsStmt.execute();
623 9408 tao
	            long endTime = System.currentTimeMillis();
624
	            logMetacat.debug("Time to run the selection query is "+(endTime-startTime)/1000+" seconds.");
625 7451 leinfelder
	            ResultSet rs = fieldsStmt.getResultSet();
626
	            //process the result and return it
627
	            while (rs.next()) {
628
	            	LogEntry logEntry = new LogEntry();
629
	            	logEntry.setEntryId(rs.getString(1));
630
631
	            	Identifier identifier = new Identifier();
632
	            	identifier.setValue(rs.getString(2));
633
					logEntry.setIdentifier(identifier);
634
635
	            	logEntry.setIpAddress(anonymous ? "N/A" : rs.getString(3));
636
	            	String userAgent = "N/A";
637
	            	if (rs.getString(4) != null) {
638
	            		userAgent = rs.getString(4);
639
	            	}
640
	            	logEntry.setUserAgent(userAgent);
641
642
	            	Subject subject = new Subject();
643
	            	subject.setValue(anonymous ? "N/A" : rs.getString(5));
644
					logEntry.setSubject(subject);
645
646
					String logEventString = rs.getString(6);
647 9323 tao
					if(logEventString == null) {
648 9324 tao
					    logEventString = "unknown";
649 9323 tao
					}
650 8810 leinfelder
					logEntry.setEvent(logEventString);
651 7451 leinfelder
					logEntry.setDateLogged(rs.getTimestamp(7));
652
653
					logEntry.setNodeIdentifier(memberNode);
654
					logs.add(logEntry);
655
	            }
656
	            fieldsStmt.close();
657 9408 tao
	            long endTime2 = System.currentTimeMillis();
658
	            logMetacat.debug("Time to put the query result to the log is "+(endTime2-endTime)/1000+" seconds.");
659 7285 leinfelder
            }
660
661 7451 leinfelder
            // set what we have
662
            log.setLogEntryList(logs);
663 7285 leinfelder
		    log.setStart(start);
664
		    log.setCount(logs.size());
665 7451 leinfelder
666
			// get total for out query
667
		    int total = 0;
668 9408 tao
		    long startTime = System.currentTimeMillis();
669
            logMetacat.debug("Time to start to execute the counting query "+startTime);
670 7451 leinfelder
            countStmt.execute();
671 9408 tao
            long endTime = System.currentTimeMillis();
672
            logMetacat.debug("Time to run the counting query is "+(endTime-startTime)/1000+" seconds.");
673 7451 leinfelder
            ResultSet countRs = countStmt.getResultSet();
674
            if (countRs.next()) {
675
            	total = countRs.getInt(1);
676
            }
677
            countStmt.close();
678 7285 leinfelder
		    log.setTotal(total);
679
680
        } catch (SQLException e) {
681 7287 leinfelder
        	logMetacat.error("Error while getting log events: " + e.getMessage(), e);
682 7285 leinfelder
        } finally {
683
            // Return database connection to the pool
684
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
685
        }
686
        return log;
687
    }
688
689 2111 jones
    /**
690
     * Format each returned log record as an XML structure.
691
     *
692
     * @param entryId the identifier of the log entry
693
     * @param ipAddress the internet protocol address for the event
694 6542 leinfelder
     * @param the agent making the request
695 2111 jones
	 * @param principal the principal for the event (a username, etc)
696
	 * @param docid the identifier of the document to which the event applies
697
	 * @param event the string code for the event
698
     * @param dateLogged the date on which the event occurred
699
     * @return String containing the formatted XML
700
     */
701 6542 leinfelder
    private String generateXmlRecord(String entryId, String ipAddress, String userAgent,
702 2113 jones
            String principal, String docid, String event, Timestamp dateLogged)
703 2111 jones
    {
704
        StringBuffer rec = new StringBuffer();
705
        rec.append("<logEntry>");
706 2113 jones
        rec.append(generateXmlElement("entryid", entryId));
707
        rec.append(generateXmlElement("ipAddress", ipAddress));
708 6542 leinfelder
        rec.append(generateXmlElement("userAgent", userAgent));
709 2113 jones
        rec.append(generateXmlElement("principal", principal));
710
        rec.append(generateXmlElement("docid", docid));
711
        rec.append(generateXmlElement("event", event));
712 6944 leinfelder
        rec.append(generateXmlElement("dateLogged", DateTimeMarshaller.serializeDateToUTC(dateLogged)));
713 2111 jones
        rec.append("</logEntry>\n");
714
715
        return rec.toString();
716
    }
717
718
    /**
719
     * Return an XML formatted element for a given name/value pair.
720
     *
721
     * @param name the name of the xml element
722
     * @param value the content of the xml element
723
     * @return the formatted XML element as a String
724
     */
725 2113 jones
    private String generateXmlElement(String name, String value)
726 2111 jones
    {
727
        return "<" + name + ">" + value + "</" + name + ">";
728
    }
729 2096 jones
}