/********************************************************************************
* CruiseControl, a Continuous Integration Toolkit
* Copyright (c) 2003, ThoughtWorks, Inc.
* 200 E. Randolph, 25th Floor
* Chicago, IL 60601 USA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* + Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* + Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
********************************************************************************/
package net.sourceforge.cruisecontrol.taglib;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Locale;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagSupport;
import net.sourceforge.cruisecontrol.LogFile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A helper class to consolidate tags that deal with log files.
* @author <a href="mailto:robertdw@sourceforge.net">Robert Watkins</a>
* @author <a href="mailto:jeffjensen@upstairstechnology.com">Jeff Jensen </a>
*/
public class CruiseControlTagSupport extends TagSupport {
private static final long serialVersionUID = 8248280337148037681L;
protected static final String LOG_PARAMETER = "log";
public static Log getLog(final Class clazz) {
return (LogFactory.getLog(clazz));
}
private static final FilenameFilter DIR_FILTER = new FilenameFilter() {
public boolean accept(File dir, String name) {
return (new File(dir, name).isDirectory());
}
};
private String projectName = null;
protected void debug(final String message) {
getLog(this.getClass()).debug(message);
}
protected void debug(final String message, final Throwable throwable) {
getLog(this.getClass()).debug(message, throwable);
}
protected void info(final String message) {
getLog(this.getClass()).info(message);
}
protected void err(final String message) {
getLog(this.getClass()).error(message);
}
protected void err(final Throwable exception) {
getLog(this.getClass()).error(exception);
}
protected void err(final String message, Throwable cause) {
getLog(this.getClass()).error(message, cause);
}
protected String getBaseLogDir() throws JspException {
final String logDirName = getContextParam("logDir");
if (logDirName == null) {
throw new JspException("You need to specify a log directory as a context param");
}
return logDirName;
}
protected File findLogDir() throws JspException {
final String logDirName = getBaseLogDir() + getProject();
final File logDir = new File(logDirName);
if (!logDir.isDirectory()) {
throw new JspException(logDirName + " either does not exist, or is not a directory");
}
return logDir;
}
/**
* Gets the correct log file, based on the project and log file requested
* in the query string.
*
* @return The specified log file or the latest log, if no log file is
* specified in the request.
* @throws JspException if logDir either does not exist, or is not a directory
*/
protected LogFile findLogFile() throws JspException {
final String logFile = getPageContext().getRequest().getParameter(LOG_PARAMETER);
return getXMLFile(findLogDir(), logFile);
}
LogFile getXMLFile(final File logDir, final String logName) {
final LogFile logFile;
if (logName == null || logName.trim().equals("")) {
logFile = LogFile.getLatestLogFile(logDir);
info("Using latest log file: " + logFile.getFile().getAbsolutePath());
} else {
logFile = new LogFile(logDir, logName);
info("Using specified log file: " + logFile.getFile().getAbsolutePath());
}
return logFile;
}
protected String[] findProjects() throws JspException {
final String logDirName = getBaseLogDir();
final File logDir = new File(logDirName);
if (!logDir.isDirectory()) {
throw new JspException(logDirName + " either does not exist, or is not a directory");
}
final String[] projects = logDir.list(DIR_FILTER);
Arrays.sort(projects);
return projects;
}
protected String getContextParam(final String name) {
String value = pageContext.getServletConfig().getInitParameter(name);
if (value == null) {
value = pageContext.getServletContext().getInitParameter(name);
}
return value;
}
public void setProject(final String projectName) {
this.projectName = projectName;
}
protected String getProject() {
if (projectName != null) {
return "/" + projectName;
}
if (isSingleProject()) {
info("in singleProjectMode");
return "";
}
final String pathInfo = getRequest().getPathInfo();
if (pathInfo == null) {
info("pathInfo is null");
return "";
}
return pathInfo;
}
/**
* Determine if this is a single project config or not.
*
* @return true if this is a single project config.
*/
protected boolean isSingleProject() {
final String singleProjectMode = getContextParam("singleProject");
return Boolean.valueOf(singleProjectMode);
}
public void setPageContext(final PageContext pageContext) {
this.pageContext = pageContext;
}
protected PageContext getPageContext() {
return pageContext;
}
protected String getServletPath() {
final HttpServletRequest request = getRequest();
return request.getContextPath() + request.getServletPath();
}
protected HttpServletRequest getRequest() {
return (HttpServletRequest) getPageContext().getRequest();
}
/**
* Create a link to the app, including the supplied parameter, but preserving all other parameters.
* @param paramName the name of the parameter.
* @param paramValue the value of the parameter
* @return a link to the app, including the supplied parameter, but preserving all other parameters.
*/
@SuppressWarnings("unchecked") // we know ServletRequest.getParameterNames() returns Enumeration<String>
protected String createUrl(final String paramName, final String paramValue) {
final StringBuffer url = new StringBuffer(getServletPath());
url.append(getProject());
final StringBuffer queryString = new StringBuffer("?");
final ServletRequest request = getPageContext().getRequest();
final Enumeration<String> requestParams = request.getParameterNames();
while (requestParams.hasMoreElements()) {
final String requestParamNameRaw = requestParams.nextElement();
if (!requestParamNameRaw.equals(paramName)) {
final String requestParamName = removeCrossSiteChars(requestParamNameRaw);
final String[] requestParamValues = request.getParameterValues(requestParamName);
for (final String requestParamValueRaw : requestParamValues) {
final String requestParamValue = removeCrossSiteChars(requestParamValueRaw);
appendParam(queryString, requestParamName, requestParamValue);
}
}
}
url.append(queryString.toString());
if (paramName != null && paramValue != null) {
appendParam(url, paramName, paramValue);
}
url.setLength(url.length() - 1);
return url.toString();
}
public String removeCrossSiteChars(final String fromValue) {
final StringBuffer buf = new StringBuffer(fromValue.length());
for (int i = 0; i < fromValue.length(); i++) {
final char c = fromValue.charAt(i);
switch(c) {
case '<':
case '>':
case '&':
case '/':
case '"':
buf.append(' ');
break;
default:
buf.append(c);
break;
}
}
return buf.toString();
}
private void appendParam(final StringBuffer queryString, final String name, final String value) {
queryString.append(name);
queryString.append("=");
queryString.append(value);
queryString.append("&");
}
protected String createUrl(final String paramToExclude) {
return createUrl(paramToExclude, null);
}
protected Locale getLocale() {
return pageContext.getRequest().getLocale();
}
}