View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.jetspeed.statistics.impl;
19  
20  import java.security.Principal;
21  import java.sql.Connection;
22  import java.sql.PreparedStatement;
23  import java.sql.ResultSet;
24  import java.sql.SQLException;
25  import java.sql.Timestamp;
26  import java.text.MessageFormat;
27  import java.text.SimpleDateFormat;
28  import java.util.ArrayList;
29  import java.util.Calendar;
30  import java.util.Collections;
31  import java.util.Date;
32  import java.util.GregorianCalendar;
33  import java.util.HashMap;
34  import java.util.List;
35  import java.util.Map;
36  import java.util.TreeMap;
37  
38  import javax.naming.NamingException;
39  import javax.servlet.http.HttpServletRequest;
40  import javax.sql.DataSource;
41  
42  import org.apache.commons.logging.Log;
43  import org.apache.commons.logging.LogFactory;
44  import org.apache.jetspeed.om.page.ContentPage;
45  import org.apache.jetspeed.request.RequestContext;
46  import org.apache.jetspeed.statistics.AggregateStatistics;
47  import org.apache.jetspeed.statistics.InvalidCriteriaException;
48  import org.apache.jetspeed.statistics.PortalStatistics;
49  import org.apache.jetspeed.statistics.StatisticsQueryCriteria;
50  import org.apache.jetspeed.statistics.UserStats;
51  import org.springframework.orm.ojb.support.PersistenceBrokerDaoSupport;
52  
53  /***
54   * <p>
55   * PortalStatisticsImpl
56   * </p>
57   * 
58   * @author <a href="mailto:chris@bluesunrise.com">Chris Schaefer </a>
59   * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
60   * @version $Id: TestPortletEntityDAO.java,v 1.3 2005/05/24 14:43:19 ate Exp $
61   */
62  public class PortalStatisticsImpl extends PersistenceBrokerDaoSupport implements
63          PortalStatistics
64  {
65      /* CLF logger */
66      protected final static Log logger = LogFactory
67              .getLog(PortalStatisticsImpl.class);
68  
69      /* batch of portlet statistics */
70      protected BatchedStatistics portletBatch;
71  
72      /* batch if page statistics */
73      protected BatchedStatistics pageBatch;
74  
75      /* batch of user statistics */
76      protected BatchedStatistics userBatch;
77  
78      /* format string for a portlet access log entry */
79      protected static final String portletLogFormat = "{0} {1} {2} [{3}] \"{4} {5} {6}\" {7} {8}";
80  
81      /* format string for a page access log entry */
82      protected static final String pageLogFormat = "{0} {1} {2} [{3}] \"{4} {5}\" {6} {7}";
83  
84      /* Format string for a User Logout log entry */
85      protected static final String logoutLogFormat = "{0} {1} {2} [{3}] \"{4}\" {5} {6}";
86  
87      protected static final int STATUS_LOGGED_IN = 1;
88  
89      protected static final int STATUS_LOGGED_OUT = 2;
90  
91      /* the following fields should be settable with Spring injection */
92      protected boolean logToCLF = true;
93  
94      protected boolean logToDatabase = true;
95  
96      protected int maxRecordToFlush_Portlet = 30;
97  
98      protected int maxRecordToFlush_User = 30;
99  
100     protected int maxRecordToFlush_Page = 30;
101 
102     protected long maxTimeMsToFlush_Portlet = 10 * 1000;
103 
104     protected long maxTimeMsToFlush_User = 10 * 1000;
105 
106     protected long maxTimeMsToFlush_Page = 10 * 1000;
107 
108     //protected ConnectionRepositoryEntry jetspeedDSEntry;
109     
110     /* after this is NOT for injection */
111 
112     protected DataSource ds;
113 
114     protected int currentUserCount = 0;
115 
116     protected Map currentUsers;
117 
118     /* date formatter */
119     protected SimpleDateFormat formatter = null;
120 
121     /***
122      * <p>
123      * Default constructor.
124      * </p>
125      */
126     
127     public PortalStatisticsImpl(boolean logToCLF, boolean logToDatabase,
128             int maxRecordToFlush_Portal, int maxRecordToFlush_User,
129             int maxRecordToFlush_Page, long maxTimeMsToFlush_Portal,
130             long maxTimeMsToFlush_User, long maxTimeMsToFlush_Page,
131             DataSource dataSource)
132             //ConnectionRepositoryEntry jetspeedDSEntry)
133     {
134 
135         this.logToCLF = logToCLF;
136         this.logToDatabase = logToDatabase;
137         this.maxRecordToFlush_Portlet = maxRecordToFlush_Portal;
138         this.maxRecordToFlush_User = maxRecordToFlush_User;
139         this.maxRecordToFlush_Page = maxRecordToFlush_Page;
140         this.maxTimeMsToFlush_Portlet = maxTimeMsToFlush_Portal;
141         this.maxTimeMsToFlush_User = maxTimeMsToFlush_User;
142         this.maxTimeMsToFlush_Page = maxTimeMsToFlush_Page;
143         //this.jetspeedDSEntry = jetspeedDSEntry;
144         this.ds = dataSource;        
145         currentUsers = Collections.synchronizedMap(new TreeMap());
146     }
147 
148     public void springInit() throws NamingException
149     {
150         formatter = new SimpleDateFormat("dd/MM/yyyy:hh:mm:ss z");
151         currentUserCount = 0;
152     }
153 
154     public DataSource getDataSource()
155     {
156         return ds;
157     }
158 
159     public void logPortletAccess(RequestContext request, String portletName,
160             String statusCode, long msElapsedTime)
161     {
162 
163         try
164         {
165             HttpServletRequest req = request.getRequest();
166             Principal principal = req.getUserPrincipal();
167             String userName = (principal != null) ? principal.getName()
168                     : "guest";
169             Timestamp timestamp = new Timestamp(System.currentTimeMillis());
170             PortletLogRecord record = new PortletLogRecord();
171 
172             record.setPortletName(portletName);
173             record.setUserName(userName);
174             if (req.getRemoteAddr() != null)
175             {
176                 record.setIpAddress(req.getRemoteAddr());
177             }
178             ContentPage cp = request.getPage();
179             if (cp != null)
180             {
181                 if (cp.getPath() != null)
182                 {
183                     record.setPagePath(cp.getPath());
184                 }
185             }
186             record.setStatus(Integer.parseInt(statusCode));
187             record.setTimeStamp(timestamp);
188             record.setMsElapsedTime(msElapsedTime);
189 
190             if (logToCLF)
191             {
192                 saveAccessToCLF(record);
193             }
194             if (logToDatabase)
195             {
196                 storeAccessToStats(record);
197             }
198         } catch (Exception e)
199         {
200             logger.error("Exception", e);
201         }
202     }
203 
204     protected void storeAccessToStats(LogRecord record)
205     {
206 
207         if (record instanceof PortletLogRecord)
208         {
209             if (portletBatch == null)
210             {
211                 synchronized (this)
212                 {
213                     if (portletBatch == null)
214                     {
215                         portletBatch = new BatchedPortletStatistics(ds,
216                                 this.maxRecordToFlush_Portlet,
217                                 this.maxTimeMsToFlush_Portlet, "portletLogBatcher");
218                         portletBatch.startThread();
219                     }
220                 }
221             }
222             portletBatch.addStatistic(record);
223 
224         }
225         if (record instanceof PageLogRecord)
226         {
227             if (pageBatch == null)
228             {
229                 synchronized (this)
230                 {
231                     if (pageBatch == null)
232                     {
233                         pageBatch = new BatchedPageStatistics(ds,
234                                 this.maxRecordToFlush_Page, this.maxTimeMsToFlush_Page,
235                                 "pageLogBatcher");
236                         pageBatch.startThread();
237                     }
238                 }
239             }
240             pageBatch.addStatistic(record);
241 
242         }
243         if (record instanceof UserLogRecord)
244         {
245             if (userBatch == null)
246             {
247                 synchronized (this)
248                 {
249                     if (userBatch == null)
250                     {
251                         userBatch = new BatchedUserStatistics(ds,
252                                 this.maxRecordToFlush_User, this.maxTimeMsToFlush_User,
253                                 "userLogBatcher");
254                         userBatch.startThread();
255                     }
256                 }
257             }
258             userBatch.addStatistic(record);
259 
260         }
261     }
262 
263     protected void saveAccessToCLF(LogRecord record)
264     {
265         Object[] args =  {""};
266         String logMessage = "";
267         if (record instanceof PortletLogRecord)
268         {
269             PortletLogRecord rec = (PortletLogRecord) record;
270             Object[] args1 =
271             { rec.getIpAddress(), "-", rec.getUserName(), rec.getTimeStamp(),
272                     rec.getLogType(), formatter.format(rec.getTimeStamp()),
273                     rec.getPortletName(),
274                     new Integer(rec.getStatus()).toString(),
275                     new Long(rec.getMsElapsedTime())};
276             args = args1;
277             logMessage = MessageFormat.format(portletLogFormat, args)
278                     .toString();
279         }
280         if (record instanceof PageLogRecord)
281         {
282             PageLogRecord rec = (PageLogRecord) record;
283             Object[] args1 =
284             { rec.getIpAddress(), "-", rec.getUserName(), rec.getTimeStamp(),
285                     rec.getLogType(), formatter.format(rec.getTimeStamp()),
286                     new Integer(rec.getStatus()).toString(),
287                     new Long(rec.getMsElapsedTime())};
288             args = args1;
289             logMessage = MessageFormat.format(pageLogFormat, args).toString();
290         }
291         if (record instanceof UserLogRecord)
292         {
293             UserLogRecord rec = (UserLogRecord) record;
294             Object[] args1 =
295             { rec.getIpAddress(), "-", rec.getUserName(), rec.getTimeStamp(),
296                     rec.getLogType(), formatter.format(rec.getTimeStamp()),
297                     new Integer(rec.getStatus()).toString(),
298                     new Long(rec.getMsElapsedTime())};
299             args = args1;
300             logMessage = MessageFormat.format(logoutLogFormat, args).toString();
301         }
302         logger.info(logMessage);
303     }
304 
305     public void logPageAccess(RequestContext request, String statusCode,
306             long msElapsedTime)
307     {
308         try
309         {
310             HttpServletRequest req = request.getRequest();
311             Principal principal = req.getUserPrincipal();
312             String userName = (principal != null) ? principal.getName()
313                     : "guest";
314             Timestamp timestamp = new Timestamp(System.currentTimeMillis());
315             PageLogRecord record = new PageLogRecord();
316 
317             record.setUserName(userName);
318             record.setIpAddress(req.getRemoteAddr());
319             ContentPage cp = request.getPage();
320             if (cp != null)
321             {
322                 if (cp.getPath() != null)
323                 {
324                     record.setPagePath(cp.getPath());
325                 }
326             }
327             record.setStatus(Integer.parseInt(statusCode));
328             record.setTimeStamp(timestamp);
329             record.setMsElapsedTime(msElapsedTime);
330 
331             if (logToCLF)
332             {
333                 saveAccessToCLF(record);
334             }
335             if (logToDatabase)
336             {
337                 storeAccessToStats(record);
338             }
339 
340         } catch (Exception e)
341         {
342             logger.error("Exception", e);
343         }
344     }
345 
346     public void logUserLogout(String ipAddress, String userName,
347             long msSessionLength)
348     {
349         try
350         {
351 
352             if (userName == null)
353             {
354                 userName = "guest";
355             }
356 
357             if (!"guest".equals(userName))
358             {
359                 synchronized (currentUsers)
360                 {
361                 	UserStats userStats = null;
362                 	
363                 	Map users = (Map)currentUsers.get(userName);                	
364                 	if(users != null && users.size() > 0)
365                 	{
366                 		userStats = (UserStats) users.get(ipAddress);                		
367                 	}                	
368             	
369                 	if(userStats != null)
370                     {
371                     	// only decrement if user has been logged in
372                     	currentUserCount = currentUserCount - 1;
373                         
374                     	userStats.setNumberOfSession(userStats
375                                 .getNumberOfSessions() - 1);                    
376                         if (userStats.getNumberOfSessions() <= 0)
377                         {
378                         	users.remove(ipAddress);
379                             currentUsers.put(userName, users);
380                         }
381                     }
382                 }
383             }
384 
385             Timestamp timestamp = new Timestamp(System.currentTimeMillis());
386             UserLogRecord record = new UserLogRecord();
387 
388             record.setUserName(userName);
389             record.setIpAddress(ipAddress);
390             record.setStatus(STATUS_LOGGED_OUT);
391             record.setTimeStamp(timestamp);
392             record.setMsElapsedTime(msSessionLength);
393 
394             if (logToCLF)
395             {
396                 saveAccessToCLF(record);
397             }
398             if (logToDatabase)
399             {
400                 storeAccessToStats(record);
401             }
402 
403         } catch (Exception e)
404         {
405             logger.error("Exception", e);
406         }
407     }
408 
409     /*
410      * (non-Javadoc)
411      * 
412      * @see org.apache.jetspeed.statistics.PortalStatistics#logUserLogin(org.apache.jetspeed.request.RequestContext,
413      *      long)
414      */
415     public void logUserLogin(RequestContext request, long msElapsedLoginTime)
416     {
417         try
418         {
419             HttpServletRequest req = request.getRequest();
420             Principal principal = req.getUserPrincipal();
421             String userName = (principal != null) ? principal.getName()
422                     : "guest";
423             String ipAddress = req.getRemoteAddr();
424             Timestamp timestamp = new Timestamp(System.currentTimeMillis());
425             UserLogRecord record = new UserLogRecord();
426 
427             if (!"guest".equals(userName))
428             {
429                 currentUserCount = currentUserCount + 1;
430 
431                 synchronized (currentUsers)
432                 {
433                 	
434                 	UserStats userStats = null;
435                 	
436                 	Map users = (Map)currentUsers.get(userName);                	
437                 	if(users != null && users.size() > 0)
438                 	{
439                 		userStats = (UserStats) users.get(ipAddress);                		
440                 	}
441                 	else
442                 	{
443                 		users = new TreeMap();
444                 	}
445                 	
446                 	if(userStats == null)
447                     {
448                         userStats = new UserStatsImpl();
449                         userStats.setNumberOfSession(0);
450                         userStats.setUsername(userName);
451                         userStats.setInetAddressFromIp(ipAddress);                        
452                     }
453                     
454                     userStats.setNumberOfSession(userStats
455                             .getNumberOfSessions() + 1);
456                     users.put(ipAddress, userStats);
457             		currentUsers.put(userName, users);
458                 }
459             }
460 
461             record.setUserName(userName);
462             record.setIpAddress(ipAddress);
463             record.setStatus(STATUS_LOGGED_IN);
464             record.setTimeStamp(timestamp);
465             record.setMsElapsedTime(msElapsedLoginTime);
466 
467             if (logToCLF)
468             {
469                 saveAccessToCLF(record);
470             }
471             if (logToDatabase)
472             {
473                 storeAccessToStats(record);
474             }
475 
476         } catch (Exception e)
477         {
478             logger.error("Exception", e);
479         }
480 
481     }
482 
483     /***
484      * @see org.springframework.beans.factory.DisposableBean#destroy()
485      */
486     public void springDestroy()
487     {
488         if (portletBatch != null)
489         {
490             portletBatch.tellThreadToStop();
491             synchronized (portletBatch.thread)
492             {
493                 portletBatch.thread.notify();
494             }
495 
496         }
497         if (userBatch != null)
498         {
499             userBatch.tellThreadToStop();
500             synchronized (userBatch.thread)
501             {
502                 userBatch.thread.notify();
503             }
504         }
505         if (pageBatch != null)
506         {
507             pageBatch.tellThreadToStop();
508             synchronized (pageBatch.thread)
509             {
510                 pageBatch.thread.notify();
511             }
512         }
513 
514         if ((this.currentUserCount != 0) && logger.isDebugEnabled())
515         {
516             logger.debug("destroying while users are logged in");
517         }
518         boolean done = false;
519         while (!done)
520         {
521             done = true;
522             if (portletBatch != null)
523             {
524                 if (!portletBatch.isDone())
525                 {
526                     done = false;
527                 }
528             }
529             if (userBatch != null)
530             {
531                 if (!userBatch.isDone())
532                 {
533                     done = false;
534                 }
535             }
536             if (pageBatch != null)
537             {
538                 if (!pageBatch.isDone())
539                 {
540                     done = false;
541                 }
542             }
543 
544             try
545             {
546                 Thread.sleep(2);
547             } catch (InterruptedException ie)
548             {
549             }
550         }
551 
552     }
553 
554     /***
555      * @see org.apache.jetspeed.statistics.PortalStatistics#getNumberOfCurrentUsers()
556      */
557     public int getNumberOfCurrentUsers()
558     {
559         return currentUserCount;
560     }
561 
562     protected Date getStartDateFromPeriod(String period, Date end)
563     {
564         GregorianCalendar gcEnd = new GregorianCalendar();
565         gcEnd.setTime(end);
566         if (period != null)
567         {
568             if (period.endsWith("m"))
569             {
570                 // months
571                 String p = period.substring(0, period.length() - 1);
572                 int ret = Integer.parseInt(p);
573                 gcEnd.add(Calendar.MONTH, (ret * -1));
574             } else if (period.endsWith("d"))
575             {
576                 // days
577                 String p = period.substring(0, period.length() - 1);
578                 int ret = Integer.parseInt(p);
579                 gcEnd.add(Calendar.HOUR, (ret * 24 * -1));
580             } else if (period.endsWith("h"))
581             {
582                 // hours
583                 String p = period.substring(0, period.length() - 1);
584                 int ret = Integer.parseInt(p);
585                 gcEnd.add(Calendar.HOUR, (ret * -1));
586             } else if (period.equals("all"))
587             {
588                 gcEnd = new GregorianCalendar();
589                 gcEnd.set(1968, 07, 15);
590             } else
591             {
592                 // minutes
593                 int ret = Integer.parseInt(period);
594                 gcEnd.add(Calendar.MINUTE, (ret * -1));
595             }
596         } else
597         {
598             gcEnd = new GregorianCalendar();
599             gcEnd.set(1968, 07, 15);
600 
601         }
602         return gcEnd.getTime();
603     }
604 
605     
606     /* (non-Javadoc)
607      * @see org.apache.jetspeed.statistics.PortalStatistics#getDefaultEmptyStatisticsQueryCriteria()
608      */
609     public StatisticsQueryCriteria createStatisticsQueryCriteria()
610     {
611         return new StatisticsQueryCriteriaImpl();
612     }
613 
614     /* (non-Javadoc)
615      * @see org.apache.jetspeed.statistics.PortalStatistics#getDefaultEmptyAggregateStatistics()
616      */
617     public AggregateStatistics getDefaultEmptyAggregateStatistics()
618     {
619         return new AggregateStatisticsImpl();
620     }
621 
622     /***
623      * @see org.apache.jetspeed.statistics.PortalStatistics#queryStatistics(org.apache.jetspeed.statistics.StatisticsQueryCriteria)
624      */
625     public AggregateStatistics queryStatistics(StatisticsQueryCriteria criteria)
626             throws InvalidCriteriaException
627     {
628         AggregateStatistics as = new AggregateStatisticsImpl();
629         String query;
630         String query2;
631 
632         String tableName;
633         String groupColumn;
634 
635         Date end = new Date();
636         Date start = getStartDateFromPeriod(criteria.getTimePeriod(), end);
637 
638         String queryType = criteria.getQueryType();
639         
640 
641         if (PortalStatistics.QUERY_TYPE_USER.equals(queryType))
642         {
643             tableName = "USER_STATISTICS";
644             groupColumn = "USER_NAME";
645         } else if (PortalStatistics.QUERY_TYPE_PORTLET.equals(queryType))
646         {
647             tableName = "PORTLET_STATISTICS";
648             groupColumn = "PORTLET";
649         } else if (PortalStatistics.QUERY_TYPE_PAGE.equals(queryType))
650         {
651             tableName = "PAGE_STATISTICS";
652             groupColumn = "PAGE";
653         } else
654         {
655             throw new InvalidCriteriaException(
656                     " invalid queryType passed to queryStatistics");
657         }
658         String orderColumn = "itemcount";
659 
660         String ascDesc = "DESC";
661 
662         if (!PortalStatistics.QUERY_TYPE_USER.equals(queryType))
663         {
664             query = "select count(*) as itemcount , MIN(ELAPSED_TIME) as amin ,AVG(ELAPSED_TIME) as aavg ,MAX(ELAPSED_TIME) as amax from "
665                     + tableName + " where time_stamp > ? and time_stamp < ?";
666             query2 = "select count(*) as itemcount ,"
667                     + groupColumn
668                     + ", MIN(ELAPSED_TIME) as amin ,AVG(ELAPSED_TIME) as aavg ,MAX(ELAPSED_TIME) as amax "
669                     + "from " + tableName
670                     + " where time_stamp > ? and time_stamp < ? group by "
671                     + groupColumn + "  order by " + orderColumn + " " + ascDesc;
672         } else
673         {
674             query = "select count(*) as itemcount , MIN(ELAPSED_TIME) as amin,AVG(ELAPSED_TIME) as aavg ,MAX(ELAPSED_TIME) as amax from "
675                     + tableName
676                     + " where time_stamp > ? and time_stamp < ? and status = 2";
677             query2 = "select count(*) as itemcount ,"
678                     + groupColumn
679                     + ", MIN(ELAPSED_TIME) as amin ,AVG(ELAPSED_TIME) as aavg ,MAX(ELAPSED_TIME) as amax "
680                     + "from "
681                     + tableName
682                     + " where time_stamp > ? and time_stamp < ? and status = 2 group by "
683                     + groupColumn + "  order by " + orderColumn + " " + ascDesc;
684         }
685         Connection con = null;
686         try
687         {
688             con = ds.getConnection();
689             PreparedStatement pstmt = con.prepareStatement(query);
690             pstmt.setTimestamp(1, new Timestamp(start.getTime()));
691             pstmt.setTimestamp(2, new Timestamp(end.getTime()));
692             ResultSet rs = pstmt.executeQuery();
693             float denominator = 1.0f;
694             if (PortalStatistics.QUERY_TYPE_USER.equals(queryType))
695             {
696                 denominator = 1000f * 60f; // this should convert from mS to
697                                            // minutes
698             }
699             if (rs.next())
700             {
701                 as.setHitCount(rs.getInt("itemcount"));
702 
703                 as.setMinProcessingTime(rs.getFloat("amin") / denominator);
704                 as.setAvgProcessingTime(rs.getFloat("aavg") / denominator);
705                 as.setMaxProcessingTime(rs.getFloat("amax") / denominator);
706 
707             }
708             PreparedStatement pstmt2 = con.prepareStatement(query2);
709             pstmt2.setTimestamp(1, new Timestamp(start.getTime()));
710             pstmt2.setTimestamp(2, new Timestamp(end.getTime()));
711             ResultSet rs2 = pstmt2.executeQuery();
712 
713             int rowCount = 0;
714             int totalRows = 5;
715             String listsizeStr = criteria.getListsize();
716             int temp = -1;
717             try 
718             {
719                 temp = Integer.parseInt(listsizeStr);
720             } 
721             catch (NumberFormatException e) 
722             {
723             }
724             if(temp != -1) {
725                 totalRows = temp;
726             }
727             
728             while ((rs2.next()) && (rowCount < totalRows))
729             {
730                 Map row = new HashMap();
731                 row.put("count", "" + rs2.getInt("itemcount"));
732                 String col = rs2.getString(groupColumn);
733                 int maxColLen = 35;
734                 if (col != null)
735                 {
736 
737                     if (col.length() > maxColLen)
738                     {
739                         col = col.substring(0, maxColLen);
740                     }
741                 }
742 
743                 row.put("groupColumn", col);
744                 row.put("min", ""
745                         + floatFormatter(rs2.getFloat("amin") / denominator));
746                 row.put("avg", ""
747                         + floatFormatter(rs2.getFloat("aavg") / denominator));
748                 row.put("max", ""
749                         + floatFormatter(rs2.getFloat("amax") / denominator));
750                 as.addRow(row);
751                 rowCount++;
752             }
753 
754         } 
755         catch (SQLException e)
756         {
757             throw new InvalidCriteriaException(e.toString());
758         }
759         finally 
760         {
761             try 
762             {
763                 if(con != null) 
764                 {
765                     con.close();
766                 }
767             } 
768             catch (SQLException e) 
769             {
770                 logger.error("error releasing the connection",e);
771             }
772         }
773 
774         return as;
775     }
776 
777     protected String floatFormatter(float f)
778     {
779         // for now we'll just truncate as int
780         int f2 = new Float(f).intValue();
781         return Integer.toString(f2);
782     }
783 
784     /*
785      * (non-Javadoc)
786      * 
787      * @see org.apache.jetspeed.statistics.PortalStatistics#getListOfLoggedInUsers()
788      */
789     public List getListOfLoggedInUsers()
790     {
791         List list = new ArrayList();
792 
793         synchronized (currentUsers)
794         {
795             list.addAll(currentUsers.values());
796         }
797         return list;
798     }
799 
800     /*
801      * (non-Javadoc)
802      * 
803      * @see org.apache.jetspeed.statistics.PortalStatistics#getNumberOfLoggedInUsers()
804      */
805     public int getNumberOfLoggedInUsers()
806     {
807         return this.currentUserCount;
808     }
809     
810 
811     /***
812      * @see org.apache.jetspeed.statistics.PortalStatistics#forceFlush()
813      */
814     public void forceFlush()
815     {
816         if (pageBatch != null)
817         {
818             this.pageBatch.flush();
819         }
820         if (portletBatch != null)
821         {
822             this.portletBatch.flush();
823         }
824         if (userBatch != null)
825         {
826             this.userBatch.flush();
827         }
828     }
829     
830 }