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