Java tutorial
/* Copyright (c) <2009> <Leonardo Rodriguez-Velez draco_rosa@hotmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package com.lrodriguez; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.jxpath.JXPathContext; import org.tigris.subversion.javahl.ClientException; import org.tigris.subversion.javahl.DirEntry; import org.tigris.subversion.javahl.Revision; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNLogEntry; import org.tmatesoft.svn.core.SVNLogEntryPath; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory; import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.io.SVNRepositoryFactory; import org.tmatesoft.svn.core.wc.SVNWCUtil; import com.lrodriguez.model.SVNHttpSession; public class SVNBrowser extends HttpServlet { private static final long serialVersionUID = 3L; private static final String INDEX_JSP = "index.jsp";//most GET requests are forwarded to this JSP after processing public static final int _2359HOURS = 86399999;//this is added to endDate in short Date style private static String webappRoot = null; //initialization parameters (in web.xml) public static final String REPOSITORY_DIR = "repositoryDir"; public static final String USER_NAME = "userName"; public static final String REPOSITORY_URL = "repositoryURL"; public static final String WEBAPP_ROOT = "webappRoot"; //session only attributes public static final String SVNSESSION = "svnsession";//holds the SVNHttpSession object public static final String UNIQUE_ENTRIES = "uniqueEntries";//holds a List of entries for this session public static final String BRANCHES = "branches";//holds a List<String> of all branches //session and/or request attributes/parameters (for session persistence) public static final String SORT_BY = "sortBy";//query parameter public static final String START_DATE = "startDate";//query parameter public static final String END_DATE = "endDate";//query parameter public static final String P_FILE_TYPE = "pFileType";//query parameter public static final String CURRENT_BRANCH = "currentBranch";//query parameter (the branch we are working with in the UI) public static final String IS_SHORT_END_DATE = "isShortEndDate";//interpreted from END_DATE parameter, indicates the user wants dates in "yyyy-MM-dd" format instead of "yyyy-MM-dd-HH:mm:ss" public static final String IS_SHORT_START_DATE = "isShortStartDate";//interpreted from START_DATE parameter, indicates the user wants dates in "yyyy-MM-dd" format instead of "yyyy-MM-dd-HH:mm:ss" //request only parameters/attributes public static final String SVN_QUERY = "svnQuery";//indicates a new query (returns plain list of files) public static final String QUERY = "query";//query parameter - indicates a new query (UI interface) public static final String XPATH_QUERY = "xpathQuery";//indicates a new xpath query public static final String FILE_QUERY = "fileQuery"; public static final String CHANGE_URL = "changeUrl"; public static final String ERROR = "error";//indicates an error public static final String FILE_TYPE = "fileType";//query parameter public static final String FILE_PATH = "filePath";//query parameter public static final String END_REVISION = "endRevision"; public static final String START_REVISION = "startRevision"; public static final String GET_FILE = "getFile"; public static final String REVISION = "revision"; //Utility properties private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//short Date style private static final String sdfRegex = "[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}";//short Date style private static final SimpleDateFormat sdfFull = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");//Full Date style private static final String sdfFullRegex = "[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}-[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}";//Full Date style private void initSession(HttpServletRequest request, HttpServletResponse response) { HttpSession session = request.getSession(); if (session.getAttribute(SVNSESSION) == null) { try { SVNHttpSession svnsession = new SVNHttpSession(getInitParameter(REPOSITORY_URL), getInitParameter(USER_NAME), getInitParameter("password"), webappRoot, getInitParameter(REPOSITORY_DIR)); logDebug("initializing SVNRepository.\nrepositoryURL=" + svnsession.getRepositoryURL() + "\nuser=" + svnsession.getUserName()); svnsession.init(); session.setAttribute(SVNSESSION, svnsession); } catch (SVNException e) { e.printStackTrace(); request.setAttribute(ERROR, e.getErrorMessage()); } } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setAttribute(ERROR, "this functionality is disabled"); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; //request.getRequestDispatcher("SVNClient").forward(request, response); } /** * this method acts as the controller/dispatcher */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { logDebug("SVNBrowser: doGet() invoked"); initSession(request, response); initBranches(request); HttpSession session = request.getSession(); Date startDate = persistStartDate(request); Date endDate = persistEndDate(request); String pFileType = persistFileType(request); String currentBranch = persistCurrentBranch(request); Comparator comparator = persistSortBy(request); //get file for listings if (request.getParameter("serveFile") != null) { doGetGetFile2(request, response); return; } //get file if (request.getParameter(GET_FILE) != null) { doGetFile(request, response); return; } //Change URL if (request.getParameter(CHANGE_URL) != null) { doChangeUrl(request, response); return; } //SVN Date query if (request.getParameter(SVN_QUERY) != null && request.getParameter(START_DATE) != null && request.getParameter(END_DATE) != null) {//new query doSvnDateQuery(request, response, startDate, endDate); return; } //SVN Revision query if (request.getParameter(SVN_QUERY) != null && request.getParameter(START_REVISION) != null && request.getParameter(END_REVISION) != null) { doSvnRevisionQuery(request, response); return; } //Xpath query if (request.getParameter(XPATH_QUERY) != null) { doXpathQuery(request, response, session); return; } //Browser Date query if (request.getParameter(QUERY) != null && request.getParameter(START_DATE) != null && request.getParameter(END_DATE) != null) {//new query doBrowserDateQuery(request, response, session, startDate, endDate, pFileType, currentBranch, comparator); return; } //Browser Revision query if (request.getParameter(QUERY) != null && request.getParameter(START_REVISION) != null && request.getParameter(END_REVISION) != null) {//new query doBrowserRevisionQuery(request, response, session, pFileType, currentBranch, comparator); return; } //Browser file query if (request.getParameter(FILE_QUERY) != null) { doBrowserFileQuery(request, response, session, comparator); return; } //Sort query if (request.getParameter(SORT_BY) != null && request.getParameter(QUERY) == null && session.getAttribute(UNIQUE_ENTRIES) != null) {//request to sort doSort(request, response, session, comparator); return; } //Sort query null entries if (request.getParameter(SORT_BY) != null && request.getParameter(QUERY) == null && session.getAttribute(UNIQUE_ENTRIES) == null) {//request to sort, no entries doSortNoEntries(request, response, session, startDate, endDate, comparator); return; } //Ant build if (request.getParameter("doAntBuild") != null) { request.setAttribute(ERROR, "this functionality is disabled"); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; //logDebug("dispatching doAntBuild request"); //AntRunner antRunner = new AntRunner(); //antRunner.run(request, response); } //switch branch if (request.getParameter(QUERY) != null && request.getParameter(CURRENT_BRANCH) != null) { doSwitchBranch(request, response, session); return; } //DEFAULT request if (request.getParameter(SORT_BY) == null && request.getParameter(QUERY) == null && request.getParameter("doUpdate") == null && request.getParameter("doUpdate") == null && request.getParameter("doCleanup") == null && request.getParameter("doCheckout") == null && request.getParameter("doAntBuild") == null) {//on initial page doDefaultRequest(request, response, session, startDate, endDate, comparator); return; } //request.getRequestDispatcher("index.jsp").forward(request, response); } /////////////////////////////////////Dispatch methods private void doDefaultRequest(HttpServletRequest request, HttpServletResponse response, HttpSession session, Date startDate, Date endDate, Comparator comparator) throws ServletException, IOException { logDebug("dispatching default request"); List branches = getAllBranches(request); if (request.getAttribute(ERROR) != null) { return; } session.setAttribute(BRANCHES, branches); List uniqueEntries = getUniqueEntries(request, startDate, endDate); if (request.getAttribute(ERROR) != null) { request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } //uniqueEntries = filterListByCurrentBranch(uniqueEntries, currentBranch); Collections.sort(uniqueEntries, comparator); session.setAttribute(UNIQUE_ENTRIES, uniqueEntries); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } private void doGetGetFile2(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { logDebug("dispatching serveFile request"); if (request.getParameter("serveFile") != null) { if (request.getParameter("serveFile").indexOf("..") >= 0) { response.sendError(404); System.err.println("******** Invalid serveFile attempt from " + request.getRemoteAddr()); return; } String workingCopyDir = webappRoot + getInitParameter(REPOSITORY_DIR).replaceAll("[/\\\\]+", "\\" + File.separator); String fileName = workingCopyDir + request.getParameter("serveFile").replaceAll("[/\\\\]+", "\\" + File.separator); File f = new File(fileName); try { if (f.getCanonicalPath().indexOf(workingCopyDir) != 0 || !f.exists() || !f.isFile() || f.isHidden()) { response.sendError(404); System.err.println( "******** Invalid serveFile attempt " + fileName + " from " + request.getRemoteAddr()); return; } } catch (IOException e) { e.printStackTrace(); response.sendError(404); System.err.println( "******** Invalid serveFile attempt " + fileName + " from " + request.getRemoteAddr()); return; } int length = 0; byte[] bbuf = new byte[1024]; DataInputStream in = new DataInputStream(new FileInputStream(f)); response.setHeader("Content-disposition", "attachment; filename=\"" + request.getParameter("serveFile") .substring(request.getParameter("serveFile").lastIndexOf("/") + 1)); while ((in != null) && ((length = in.read(bbuf)) != -1)) { response.getOutputStream().write(bbuf, 0, length); } in.close(); response.getOutputStream().flush(); response.getOutputStream().close(); return; } } private void doGetFile(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { logDebug("dispatching getFile"); HttpSession session = request.getSession(); if (session != null && (request.getParameter(GET_FILE) == null || "".equals(request.getParameter(GET_FILE))) && request.getParameter(REVISION) != null) { response.getWriter().println("an error ocurred, check the query parameters"); } if (session.getAttribute(SVNBrowser.SVNSESSION) != null) { SVNHttpSession svnsession = (SVNHttpSession) session.getAttribute(SVNBrowser.SVNSESSION); if (svnsession != null) { SVNRepository repo = svnsession.getRepository(); logDebug("im here!"); response.setHeader("Content-disposition", "attachment; filename=\"" + request.getParameter(GET_FILE) .substring(request.getParameter(GET_FILE).lastIndexOf("/") + 1)); try { repo.getFile(request.getParameter(GET_FILE), Long.parseLong(request.getParameter("revision")), null, response.getOutputStream()); } catch (NumberFormatException e) { request.setAttribute(ERROR, e.getMessage()); request.getRequestDispatcher(INDEX_JSP).forward(request, response); } catch (SVNException e) { request.setAttribute(ERROR, e.getMessage()); request.getRequestDispatcher(INDEX_JSP).forward(request, response); } } else { request.setAttribute(ERROR, "svnsession is null, try refreshing the session by setting the Repository URL"); request.getRequestDispatcher(INDEX_JSP).forward(request, response); } } } private void doSwitchBranch(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws ServletException, IOException { logDebug("dispatching Browser switch branch query"); //List uniqueEntries = getUniqueEntries(request, startDate, endDate); //if(request.getAttribute(ERROR)!= null){ // request.getRequestDispatcher("index.jsp").forward(request, response); // return; //} //uniqueEntries = filterListByCurrentBranch(uniqueEntries, currentBranch); //Collections.sort(uniqueEntries, comparator); session.setAttribute(UNIQUE_ENTRIES, null); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } private void doSvnRevisionQuery(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { logDebug("dispatching Revision SVN query request"); List entriesList = getUniqueEntries(request, Long.parseLong(request.getParameter(START_REVISION)), Long.parseLong(request.getParameter(END_REVISION)));//get all files in date range if (request.getAttribute(ERROR) != null) { request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } sortAndFilterSvnQuery(request, response, entriesList); return; } private void doSvnDateQuery(HttpServletRequest request, HttpServletResponse response, Date startDate, Date endDate) throws ServletException, IOException { logDebug("dispatching Date SVN query request"); List entriesList = getUniqueEntries(request, startDate, endDate);//get all files in date range if (request.getAttribute(ERROR) != null) { request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } sortAndFilterSvnQuery(request, response, entriesList); return; } private void doSort(HttpServletRequest request, HttpServletResponse response, HttpSession session, Comparator comparator) throws ServletException, IOException { logDebug("dispatching Sort request"); Collections.sort(((List) session.getAttribute(UNIQUE_ENTRIES)), comparator); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } private void doSortNoEntries(HttpServletRequest request, HttpServletResponse response, HttpSession session, Date startDate, Date endDate, Comparator comparator) throws ServletException, IOException { logDebug("dispatching Default request"); List uniqueEntries = getUniqueEntries(request, startDate, endDate); if (request.getAttribute(ERROR) != null) { request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } Collections.sort(uniqueEntries, comparator); session.setAttribute(UNIQUE_ENTRIES, uniqueEntries); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } private void doXpathQuery(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws ServletException, IOException { //example //?xpathQuery=.[revision < 9315 and revision>9000 and author='echow' or author ='lrodrigu' and type='A'] logDebug("dispatching xpath query: " + request.getParameter(XPATH_QUERY)); SVNRepository repository = ((SVNHttpSession) request.getSession().getAttribute(SVNSESSION)).getRepository(); Collection svnLogEntries = null; try { svnLogEntries = getSVNLogEntries(request, 0, repository.getDatedRevision(new Date())); } catch (SVNException e) { e.printStackTrace(); request.setAttribute(ERROR, e.getErrorMessage()); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } List entriesList = new ArrayList(); if (svnLogEntries != null && svnLogEntries.size() > 0) { List entryFacadeList = getAllEntries(svnLogEntries); JXPathContext context = JXPathContext.newContext(entryFacadeList); context.setLenient(true); for (Iterator iter = context.iterate(request.getParameter(XPATH_QUERY)); iter.hasNext();) { Object currEntryFacade = iter.next(); entriesList.add(currEntryFacade); } } session.setAttribute(UNIQUE_ENTRIES, entriesList); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } private void doBrowserDateQuery(HttpServletRequest request, HttpServletResponse response, HttpSession session, Date startDate, Date endDate, String pFileType, String currentBranch, Comparator comparator) throws ServletException, IOException { logDebug("dispatching Browser Date query"); List uniqueEntries = getUniqueEntries(request, startDate, endDate); if (request.getAttribute(ERROR) != null) { request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } uniqueEntries = filterListByDateRange(uniqueEntries, startDate, endDate); uniqueEntries = filterListByFileType(uniqueEntries, pFileType); uniqueEntries = filterListByCurrentBranch(uniqueEntries, currentBranch); Collections.sort(uniqueEntries, comparator); session.setAttribute(UNIQUE_ENTRIES, uniqueEntries); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } private void doBrowserFileQuery(HttpServletRequest request, HttpServletResponse response, HttpSession session, Comparator comparator) throws ServletException, IOException { logDebug("Dispatching Browser File query"); SVNRepository repository = ((SVNHttpSession) request.getSession().getAttribute(SVNSESSION)).getRepository(); try { long endRevision = repository.getDatedRevision(new Date()); Collection logEntries = repository.log(new String[] { request.getParameter(FILE_QUERY) }, null, 1, endRevision, true, true); List outputList = getAllEntries(logEntries); outputList = filterListByFilePath(outputList, request.getParameter(FILE_QUERY)); Collections.sort(outputList, comparator); session.setAttribute(UNIQUE_ENTRIES, outputList); } catch (SVNException e) { e.printStackTrace(); request.setAttribute(ERROR, e.getErrorMessage()); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } private void doBrowserRevisionQuery(HttpServletRequest request, HttpServletResponse response, HttpSession session, String pFileType, String currentBranch, Comparator comparator) throws ServletException, IOException { logDebug("Dispatching Browser Revision query"); logDebug("dispatching Revision query request"); List uniqueEntries = getUniqueEntries(request, Long.parseLong(request.getParameter(START_REVISION)), Long.parseLong(request.getParameter(END_REVISION))); if (request.getAttribute(ERROR) != null) { request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } uniqueEntries = filterListByFileType(uniqueEntries, pFileType); uniqueEntries = filterListByCurrentBranch(uniqueEntries, currentBranch); Collections.sort(uniqueEntries, comparator); session.setAttribute(UNIQUE_ENTRIES, uniqueEntries); request.getRequestDispatcher(INDEX_JSP).forward(request, response); } private void doChangeUrl(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); logDebug("dispatching changeUrl"); SVNHttpSession svnsession = (SVNHttpSession) session.getAttribute(SVNSESSION); if (svnsession == null) { request.setAttribute(ERROR, "svnsession is null, try deleting your cookies and accessing SVNBrowser with no parameters"); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } String webappRoot = this.getServletContext().getRealPath("/") == null ? getInitParameter(WEBAPP_ROOT) : this.getServletContext().getRealPath("/"); SVNHttpSession newSvnsession = new SVNHttpSession(request.getParameter(CHANGE_URL), getInitParameter(USER_NAME), getInitParameter("password"), webappRoot, getInitParameter(REPOSITORY_DIR)); logDebug("initializing SVNRepository.\nrepositoryURL=" + newSvnsession.getRepositoryURL() + "\nuser=" + newSvnsession.getUserName()); try { newSvnsession.init(); } catch (SVNException e) { e.printStackTrace(); request.setAttribute(ERROR, e.getErrorMessage()); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } session.setAttribute(SVNSESSION, newSvnsession); List branches = getAllBranches(request); if (request.getAttribute(ERROR) != null) { session.setAttribute(SVNSESSION, newSvnsession);//revert to original session request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } session.setAttribute(BRANCHES, branches); logDebug("closing existing svnsession "); svnsession.getRepository().closeSession(); session.setAttribute(REPOSITORY_URL, request.getParameter(CHANGE_URL));//set the new URL in the session (used by JSP) session.removeAttribute(CURRENT_BRANCH); //currentBranch = persistCurrentBranch(request);//set the current branch //List uniqueEntries = getUniqueEntries(request, startDate, endDate); //if(request.getAttribute(ERROR)!= null){ // request.getRequestDispatcher("index.jsp").forward(request, response); // return; //} //uniqueEntries = filterListByCurrentBranch(uniqueEntries, currentBranch); //Collections.sort(uniqueEntries, comparator); session.setAttribute(UNIQUE_ENTRIES, null); request.getRequestDispatcher(INDEX_JSP).forward(request, response); return; } /////////////////////////////////////Utility methods private List getAllBranches(HttpServletRequest request) {//TODO this logic needs to be fixed, too many assumptions HttpSession session = request.getSession(); SVNHttpSession svnsession = (SVNHttpSession) session.getAttribute(SVNSESSION); org.tigris.subversion.javahl.SVNClient client = new org.tigris.subversion.javahl.SVNClient(); client.username(svnsession.getUserName()); client.password(svnsession.getPassword()); List branchesList = new ArrayList(); try { DirEntry[] branches = client.list(svnsession.getRepositoryURL(), Revision.HEAD, false); for (int i = 0; i < branches.length; i++) { if (branches[i].getPath().equals("trunk")) {//in VitaminShoppe's case, the trunk has no sub-branch branchesList.add(branches[i].getPath()); continue; } DirEntry[] subBranches = client.list(svnsession.getRepositoryURL() + "/" + branches[i].getPath(), Revision.HEAD, false); for (int j = 0; j < subBranches.length; j++) { branchesList.add(branches[i].getPath() + "/" + subBranches[j].getPath()); } } //branchesList.add("trunk"); } catch (ClientException e) { request.setAttribute(ERROR, e.getMessage()); e.printStackTrace(); } return branchesList; } private void sortAndFilterSvnQuery(HttpServletRequest request, HttpServletResponse response, List entriesList) throws IOException { Collections.sort(entriesList, Sorter.PATH_INSENSITIVE_COMPARATOR); if (request.getParameter(FILE_TYPE) != null && request.getParameter(FILE_PATH) == null) {//filter by fileType String fileType = request.getParameter(FILE_TYPE); entriesList = filterListByFileType(entriesList, fileType); } else if (request.getParameter(FILE_TYPE) == null && request.getParameter(FILE_PATH) != null) {//filter by filePath String filePath = request.getParameter(FILE_PATH); entriesList = filterListByFilePath(entriesList, filePath); } else if (request.getParameter(FILE_TYPE) != null && request.getParameter(FILE_PATH) != null) {//filter by both String fileType = request.getParameter(FILE_TYPE); String filePath = request.getParameter(FILE_PATH); entriesList = filterListByFilePath(entriesList, filePath);//the path is a larger restriction, do first entriesList = filterListByFileType(entriesList, fileType); } for (Iterator iter = entriesList.iterator(); iter.hasNext();) { response.getWriter().println(((SVNEntryFacade) iter.next()).getPath()); } logDebug("svnQuery: returning " + entriesList.size() + " entries"); } private List filterListByDateRange(List input, Date startDate, Date endDate) { List filteredList = new ArrayList(); for (int i = 0; i < input.size(); i++) { SVNEntryFacade entry = (SVNEntryFacade) input.get(i); if ((entry.getTimestamp().after(startDate) || entry.getTimestamp().equals(startDate)) && entry.getTimestamp().before(endDate) || entry.getTimestamp().equals(endDate)) { filteredList.add(entry); } } return filteredList; } private List filterListByCurrentBranch(List input, String currentBranch) { List filteredList = new ArrayList(); for (int i = 0; i < input.size(); i++) { SVNEntryFacade entry = (SVNEntryFacade) input.get(i); if (entry.getPath().indexOf("/" + currentBranch + "/") >= 0) {//TODO this is causing issues with repositories whose Bran filteredList.add(entry); } } return filteredList; } private List filterListByFilePath(List input, String filePath) { List filteredList = new ArrayList(); if (filePath == null || filePath.length() == 0) { return input; } else { for (int i = 0; i < input.size(); i++) { SVNEntryFacade entry = (SVNEntryFacade) input.get(i); if (entry.getPath().startsWith(filePath)) { filteredList.add(entry); //logDebug(i+" "+entry.getPath()); } } } return filteredList; } private List filterListByFileType(List input, String fileType) { List filteredList = new ArrayList(); if (fileType == null || fileType.length() == 0) { return input; } else if (("jsp".equals(fileType) || ".jsp".equals(fileType) || "*.jsp".equals(fileType))) { //logDebug("uniqueEntries.size()="+input.size()); for (int i = 0; i < input.size(); i++) { SVNEntryFacade entry = (SVNEntryFacade) input.get(i); if (entry.getPath().matches(".*\\.jsp") || entry.getPath().matches(".*\\.jspf")) { filteredList.add(entry); //logDebug(i+" "+entry.getPath()); } } } else { logDebug("uniqueEntries.size()=" + input.size()); for (int i = 0; i < input.size(); i++) { SVNEntryFacade entry = (SVNEntryFacade) input.get(i); //String ft = fileType.matches("\\..*") ? fileType.substring(1) : fileType; if (fileType.startsWith("*") || fileType.startsWith(".")) { String ft = fileType.replaceAll("\\*", ""); //logDebug("ft="+ft); if (entry.getPath().matches(".*" + ft) || entry.getPath().matches(".*\\." + ft)) { filteredList.add(entry); //logDebug(i+" "+entry.getPath()); } } else if (fileType.indexOf("/") > -1) {//searching for a path+filename if (entry.getPath().indexOf(fileType) > -1) { filteredList.add(entry); } } else {//searching for just the filename String comparePath = entry.getPath().substring(entry.getPath().lastIndexOf("/") + 1); if (comparePath.equals(fileType)) { filteredList.add(entry); } } } } return filteredList; } public List getUniqueEntries(HttpServletRequest request, Date startDate, Date endDate) { List outputList = new ArrayList(); try { Collection latestEntries = getSVNLogEntries(request, startDate, endDate); if (latestEntries == null || latestEntries.size() == 0) { if (request.getAttribute(ERROR) != null) { return null; } } else { HashMap uniqueEntries = getLatestEntries(latestEntries); Iterator iter = uniqueEntries.keySet().iterator(); while (iter.hasNext()) { SVNEntryFacade entry = (SVNEntryFacade) uniqueEntries.get(iter.next()); outputList.add(entry); } } } catch (SVNException e) { request.setAttribute(ERROR, e.getErrorMessage()); e.printStackTrace(); } return outputList; } public List getUniqueEntries(HttpServletRequest request, long startRevision, long endRevision) { List outputList = new ArrayList(); try { Collection latestEntries = getSVNLogEntries(request, startRevision, endRevision); if (latestEntries.size() == 0) { if (request.getAttribute(ERROR) != null) { return null; } } else { HashMap uniqueEntries = getLatestEntries(latestEntries); Iterator iter = uniqueEntries.keySet().iterator(); while (iter.hasNext()) { SVNEntryFacade entry = (SVNEntryFacade) uniqueEntries.get(iter.next()); outputList.add(entry); } } } catch (SVNException e) { request.setAttribute(ERROR, e.getErrorMessage()); e.printStackTrace(); } return outputList; } private HashMap getLatestEntries(Collection logEntries) { HashMap uniqueEntries = new HashMap(); for (Iterator entries = logEntries.iterator(); entries.hasNext();) { SVNLogEntry logEntry = (SVNLogEntry) entries.next(); if (logEntry.getChangedPaths().size() > 0) { Set changedPathsSet = logEntry.getChangedPaths().keySet(); for (Iterator changedPaths = changedPathsSet.iterator(); changedPaths.hasNext();) { SVNLogEntryPath entryPath = (SVNLogEntryPath) logEntry.getChangedPaths() .get(changedPaths.next()); SVNEntryFacade fileEntry = new SVNEntryFacade(new File(entryPath.getPath()), entryPath, logEntry, true); if (uniqueEntries.containsKey(fileEntry.file.getAbsolutePath())) { SVNEntryFacade existingEntry = (SVNEntryFacade) uniqueEntries .get(fileEntry.file.getAbsolutePath()); if (existingEntry.getRevision() <= logEntry.getRevision()) { uniqueEntries.put(fileEntry.file.getAbsolutePath(), fileEntry); } } else { uniqueEntries.put(fileEntry.file.getAbsolutePath(), fileEntry); } } } } return uniqueEntries; } private List getAllEntries(Collection logEntries) { List uniqueEntries = new ArrayList(); for (Iterator entries = logEntries.iterator(); entries.hasNext();) { SVNLogEntry logEntry = (SVNLogEntry) entries.next(); if (logEntry.getChangedPaths().size() > 0) { Set changedPathsSet = logEntry.getChangedPaths().keySet(); for (Iterator changedPaths = changedPathsSet.iterator(); changedPaths.hasNext();) { SVNLogEntryPath entryPath = (SVNLogEntryPath) logEntry.getChangedPaths() .get(changedPaths.next()); SVNEntryFacade fileEntry = new SVNEntryFacade(new File(entryPath.getPath()), entryPath, logEntry, true); uniqueEntries.add(fileEntry); } } } return uniqueEntries; } public Collection getSVNLogEntries(HttpServletRequest request, Date startDate, Date endDate) throws SVNException { SVNRepository repository = ((SVNHttpSession) request.getSession().getAttribute(SVNSESSION)).getRepository(); long startRevision = repository.getDatedRevision(startDate); //long endRevision = repository.getDatedRevision(new Date(endDate.getTime()+_2359HOURS)); long endRevision = repository.getDatedRevision(endDate); logDebug("startDate=" + startDate); Collection logEntries = null; if (request.getSession().getAttribute(CURRENT_BRANCH) != null) { logEntries = repository.log(new String[] { (String) request.getSession().getAttribute(CURRENT_BRANCH) }, null, startRevision, endRevision, true, true); } else { repository.log(new String[] { "" }, null, startRevision, endRevision, true, true); } return logEntries; } public Collection getSVNLogEntries(HttpServletRequest request, long startRevision, long endRevision) throws SVNException { SVNRepository repository = ((SVNHttpSession) request.getSession().getAttribute(SVNSESSION)).getRepository(); Collection logEntries = repository.log(new String[] { "" }, null, startRevision, endRevision, true, true); return logEntries; } /////////////////////////////////////Session Persistence methods //these are called at the beginning of every request private void initBranches(HttpServletRequest request) { if (request.getSession().getAttribute(BRANCHES) == null) { List branches = getAllBranches(request); //branches.add("trunk"); request.getSession().setAttribute(BRANCHES, branches); } } private String persistCurrentBranch(HttpServletRequest request) { HttpSession session = request.getSession(); String currentBranch = ""; if (request.getParameter(CURRENT_BRANCH) == null) { if (session.getAttribute(CURRENT_BRANCH) != null) { currentBranch = (String) session.getAttribute(CURRENT_BRANCH); } else { List branches = getAllBranches(request); for (int i = 0; i < branches.size(); i++) { if ("trunk".equals((String) branches.get(i))) { currentBranch = (String) branches.get(i);//if we find "trunk" in List, use that as default break; } } if ("".equals(currentBranch) && branches.size() > 0) { currentBranch = (String) branches.get(0);//we didn't find "trunk", so use whatever } session.setAttribute(CURRENT_BRANCH, currentBranch); } } else { currentBranch = request.getParameter(CURRENT_BRANCH); session.setAttribute(CURRENT_BRANCH, currentBranch); } return currentBranch; } private String persistFileType(HttpServletRequest request) { HttpSession session = request.getSession(); String fileType = ""; if (request.getParameter(P_FILE_TYPE) == null) { if (session.getAttribute(FILE_TYPE) != null) { fileType = (String) session.getAttribute(FILE_TYPE); } else { fileType = "*"; session.setAttribute(FILE_TYPE, "*"); } } else { fileType = request.getParameter(P_FILE_TYPE); session.setAttribute(FILE_TYPE, fileType); } return fileType; } private Date persistEndDate(HttpServletRequest request) { HttpSession session = request.getSession(); Date endDate = null; if (request.getParameter(END_DATE) == null) { if (session.getAttribute(END_DATE) == null) {//the first request(default) endDate = new Date((new Date()).getTime()); session.setAttribute(END_DATE, endDate); session.setAttribute(IS_SHORT_END_DATE, Boolean.TRUE);//default to short style } else { endDate = (Date) session.getAttribute(END_DATE); } } else { try { if (request.getParameter(END_DATE).matches(sdfRegex)) { endDate = new Date(sdf.parse(request.getParameter(END_DATE)).getTime() + _2359HOURS);//add 23:59 session.setAttribute(IS_SHORT_END_DATE, Boolean.TRUE); } else if (request.getParameter(END_DATE).matches(sdfFullRegex)) { endDate = new Date(sdfFull.parse(request.getParameter(END_DATE)).getTime());//add one second session.setAttribute(IS_SHORT_END_DATE, Boolean.FALSE); } session.setAttribute(END_DATE, endDate); } catch (ParseException e) { e.printStackTrace(); } } return endDate; } private Date persistStartDate(HttpServletRequest request) { HttpSession session = request.getSession(); Date startDate = null; if (request.getParameter(START_DATE) == null) { if (session.getAttribute(START_DATE) == null) {//the first request(default) startDate = new Date(837039900000L); session.setAttribute(IS_SHORT_START_DATE, Boolean.TRUE);//default to short style session.setAttribute(START_DATE, startDate); } else { startDate = (Date) session.getAttribute(START_DATE); } } else { try { if (request.getParameter(START_DATE).matches(sdfRegex)) { startDate = sdf.parse(request.getParameter(START_DATE)); session.setAttribute(IS_SHORT_START_DATE, Boolean.TRUE); } else if (request.getParameter(START_DATE).matches(sdfFullRegex)) { startDate = sdfFull.parse(request.getParameter(START_DATE)); session.setAttribute(IS_SHORT_START_DATE, Boolean.FALSE); } session.setAttribute(START_DATE, startDate); } catch (ParseException e) { e.printStackTrace(); } } return startDate; } private Comparator persistSortBy(HttpServletRequest request) { HttpSession session = request.getSession(); Comparator comparator = (Comparator) session.getAttribute(SORT_BY); if (request.getParameter(SORT_BY) == null) { if (session.getAttribute(SORT_BY) == null) { comparator = Sorter.DATE_REVERSE_COMPARATOR;//default } } else { if (session.getAttribute(SORT_BY) == null) { if ("togglePath".equals(request.getParameter(SORT_BY))) { comparator = Sorter.PATH_INSENSITIVE_REVERSE_COMPARATOR; } else if ("toggleAuthor".equals(request.getParameter(SORT_BY))) { comparator = String.CASE_INSENSITIVE_ORDER; } else { comparator = Sorter.DATE_REVERSE_COMPARATOR;//default } } else { if ("togglePath".equals(request.getParameter(SORT_BY))) { if (Sorter.PATH_INSENSITIVE_COMPARATOR.equals(comparator)) { comparator = Sorter.PATH_INSENSITIVE_REVERSE_COMPARATOR; } else { comparator = Sorter.PATH_INSENSITIVE_COMPARATOR; } } else if ("toggleAuthor".equals(request.getParameter(SORT_BY))) { if (Sorter.AUTHOR_COMPARATOR.equals(comparator)) { comparator = Sorter.AUTHOR_REVERSE_COMPARATOR; } else { comparator = Sorter.AUTHOR_COMPARATOR; } } else if ("toggleDate".equals(request.getParameter(SORT_BY))) { if (Sorter.DATE_COMPARATOR.equals(comparator)) { comparator = Sorter.DATE_REVERSE_COMPARATOR; } else { comparator = Sorter.DATE_COMPARATOR; } } else if ("toggleRevision".equals(request.getParameter(SORT_BY))) { if (Sorter.REV_COMPARATOR.equals(comparator)) { comparator = Sorter.REV__REVERSE_COMPARATOR; } else { comparator = Sorter.REV_COMPARATOR; } } } } session.setAttribute(SORT_BY, comparator); return comparator; } //////////////////////////////////////initialization Methods private static void initSVNRepositoryFactories() { DAVRepositoryFactory.setup(); SVNRepositoryFactoryImpl.setup(); FSRepositoryFactory.setup(); } public void init() throws ServletException { try { super.init(); } catch (ServletException e) { e.printStackTrace(); } webappRoot = (this.getServletContext().getRealPath("/") == null ? getInitParameter(WEBAPP_ROOT) : this.getServletContext().getRealPath("/")).replaceAll("[/\\\\]+", "\\" + File.separator); ; System.out.println("init() setting webappRoot to " + webappRoot); if (getServletContext().getAttribute("com.lrodriguez.model.SVNLogEntryDB") == null) { try { initSVNRepositoryFactories(); //SVNLogEntryDB db = SVNLogEntryDB.getInstance(); SVNRepository repository = SVNRepositoryFactory .create(SVNURL.parseURIEncoded(getInitParameter(REPOSITORY_URL))); ISVNAuthenticationManager manager = SVNWCUtil.createDefaultAuthenticationManager( getInitParameter(USER_NAME), getInitParameter("password")); repository.setAuthenticationManager(manager); } catch (SVNException e) { e.printStackTrace(); } } } public void logDebug(String arg) { System.out.println(arg); } }