package com.dotj.web.struts; import java.util.Properties; import java.util.ArrayList; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.sql.ResultSet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import com.dotj.io.DataSet; import com.dotj.grid.interfaces.IGridCommandEventArgs; import com.dotj.form.interfaces.IFormValidator; import com.dotj.form.FormValidatorTag; import com.dotj.test.MyGridSublistListener; import com.dotj.test.Message; public final class ProcessSublistAction extends Action { public static final String REQ_MESSAGE_LIST = "msgList"; /** * The Log instance for this application. */ protected static Log log = LogFactory.getLog(ProcessSublistAction.class); // --------------------------------------------------------- Public Methods /** * Process the specified HTTP request, and create the corresponding HTTP * response (or forward to another web component that will create it). * Return an ActionForward instance describing where and how * control should be forwarded, or null if the response has * already been completed. * * @param mapping The ActionMapping used to select this instance * @param form The optional ActionForm bean for this request (if any) * @param request The HTTP request we are processing * @param response The HTTP response we are creating * @throws Exception if the application business logic throws * an exception */ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // Set a transactional control token to prevent double posting saveToken(request); Long start2 = new Long(System.currentTimeMillis()); request.setAttribute("startTimer", start2); // Array constants to match column fields and sort order. String[] dataFields = {"", "-RowNumber-", "-Icon-", "MessageId", "Forum", "ThreadID", "Name", "Subject", "Email"}; String[] sortTypes = {"", "ASC", "DESC"}; // Default sorted column is the 4th column (Forum). int sortColumn = 4; String sortField = dataFields[sortColumn]; // Default sort order is Ascending. int sortType = DataSet.SORT_ASCENDING; String sortOrder = sortTypes[sortType]; // Default initialization. These wil be overloaded by what the user performed as an action. int rowCount = 0; int pageCount = 1; int displayPage = 1; int pageSize = 0; // Get a handle to the dotJ form validator object. IFormValidator formValidator = FormValidatorTag.getDotJFormValidator(request); // Only process POST events. if (formValidator.IsPost()) { // Check for a Grid command event. if (formValidator.getCommandEvent() instanceof IGridCommandEventArgs) { IGridCommandEventArgs cmdEvt = (IGridCommandEventArgs) formValidator.getCommandEvent(); // Store some important paging and sorting information. displayPage = cmdEvt.getDisplayPage(); pageSize = cmdEvt.getPageSize(); sortColumn = cmdEvt.getSortColumnNumber(); if (sortColumn > 0) { sortField = dataFields[sortColumn]; } sortType = cmdEvt.getSortType(); sortOrder = sortTypes[sortType]; } } // Build the SQL. Get all the messages from the database. String sql = "SELECT A.MessageID, B.Name, A.Subject, A.ThreadID, B.Email, D.Name AS Forum" + " FROM jiveMessage A, jiveUser B," + " jiveThread C, jiveForum D" + " WHERE A.userID = B.userID" + " AND A.threadID = C.threadID" + " AND C.forumID = D.forumID" + " ORDER BY " + sortField + " " + sortOrder; Connection conn = null; Statement stmt = null; ResultSet rs = null; Message message = null; ArrayList messageList = new ArrayList(); // Cache the message list in the request. We'll bind the to this in the JSP. request.setAttribute(REQ_MESSAGE_LIST, messageList); // Create the sublist grid listener. This is required because we are doing grid sublist processing. MyGridSublistListener listener = new MyGridSublistListener(); try { // Issue the SQL call. Use a scrollable Resultset in order to skip rows. conn = getConnection(servlet.getServletContext()); stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); rs = stmt.executeQuery(sql); if (rs != null) { int startRow, endRow; // Calculate the starting row. startRow = (displayPage - 1) * pageSize + 1; if (rs.last()) rowCount = rs.getRow(); // Calculate the end row. if (pageSize <= 0) endRow = rowCount; else endRow = startRow + pageSize - 1; if (endRow > rowCount) endRow = rowCount; // Using a scrollable ResultSet, go to the starting row. Then iterate over the Resultset until // reaching the end row. This avoids processing every single row in the ResultSet. for (int i = startRow; i <= endRow; i++) { if (rs.absolute(i)) { message = new Message(); message.setId(rs.getLong("MessageID")); message.setForumName(rs.getString("Forum")); message.setUserName(rs.getString("Name")); message.setSubject(rs.getString("Subject")); message.setEmail(rs.getString("Email")); message.setThreadId(rs.getLong("ThreadID")); messageList.add(message); } } // Calculate the page count. pageCount = rowCount / MyGridSublistListener.PAGE_SIZE; } // Now get the thread total using SQL. This is necessary since we're not processing all rows and the only // way to sum the column is via SQL. Normally, dotJ handles this automatically, but it can't since we're // doing sublist processing and dotJ won't see every row. String sql2 = "SELECT SUM(ThreadID)" + " FROM jiveMessage"; stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); rs = stmt.executeQuery(sql2); if (rs != null && rs.next()) { int threadTotal = rs.getInt(1); listener.setThreadTotal(threadTotal); } } finally { try { if (rs != null) rs.close(); if (stmt != null) stmt.close(); if (conn != null) conn.close(); } catch (SQLException sqle) { ; // Ok to eat since we're cleaning up. } } // Transfer this sort state to the grid listener so the grid in the JSP will know about everything. // Also, cache the listener in the request, so the JSP can use it. listener.setPost(formValidator.IsPost()); listener.setSortColumn(sortColumn); listener.setSortType(sortType); listener.setRowCount(rowCount); listener.setPageCount(pageCount); request.setAttribute("listener", listener); // Forward control to the edit user registration page return (mapping.findForward("success")); } private static Connection getConnection(ServletContext application) throws SQLException { Connection conn = null; Properties prop = new java.util.Properties(); try { prop.load(new java.io.FileInputStream(application.getRealPath("/WEB-INF/database.properties"))); String driver = prop.getProperty("databaseDriver"); String uri = prop.getProperty("databaseURI"); String userid = prop.getProperty("databaseUserid"); String password = prop.getProperty("databasePassword"); Class.forName(driver); conn = java.sql.DriverManager.getConnection(uri, userid, password); } catch (Exception e) { throw new SQLException(e.getMessage()); } return conn; } }