/*
* Copyright (c) JForum Team
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* 1) Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* 2) 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.
* 3) Neither the name of "Rafael Steil" 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 COPYRIGHT OWNER 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
*
* This file creation date: 29/01/2006 - 12:19:11
* The JForum Project
* http://www.jforum.net
*/
package net.jforum;
import java.io.IOException;
import java.sql.Connection;
import javax.servlet.http.HttpServletResponse;
import net.jforum.context.RequestContext;
import net.jforum.context.ResponseContext;
import net.jforum.context.ForumContext;
import net.jforum.exceptions.ForumException;
import net.jforum.util.preferences.ConfigKeys;
import net.jforum.util.preferences.SystemGlobals;
import org.apache.log4j.Logger;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.SimpleHash;
/**
* Data execution context.
*
* @author Rafael Steil
* @version $Id: JForumExecutionContext.java,v 1.10 2006/10/10 01:59:55 rafaelsteil Exp $
*/
public class JForumExecutionContext
{
private static ThreadLocal userData = new ThreadLocal();
private static Logger logger = Logger.getLogger(JForumExecutionContext.class);
private static Configuration templateConfig;
private Connection conn;
private ForumContext forumContext;
private SimpleHash context = new SimpleHash(ObjectWrapper.BEANS_WRAPPER);
private String redirectTo;
private String contentType;
private boolean isCustomContent;
private boolean enableRollback;
/**
* Gets the execution context.
* @return JForumExecutionContext
*/
public static JForumExecutionContext get()
{
JForumExecutionContext ex = (JForumExecutionContext)userData.get();
if (ex == null) {
ex = new JForumExecutionContext();
userData.set(ex);
}
return ex;
}
/**
* Checks if there is an execution context already set
* @return <code>true</code> if there is an execution context
* @see #get()
*/
public static boolean exists()
{
return (userData.get() != null);
}
/**
* Sets the default template configuration
* @param config The template configuration to set
*/
public static void setTemplateConfig(Configuration config)
{
templateConfig = config;
}
/**
* Gets a reference to the default template configuration settings.
* @return The template configuration instance
*/
public static Configuration templateConfig()
{
return templateConfig;
}
/**
* Sets the execution context
* @param ex JForumExecutionContext
*/
public static void set(JForumExecutionContext ex)
{
userData.set(ex);
}
/**
* Sets a connection
* @param conn The connection to use
*/
public void setConnection(Connection conn)
{
this.conn = conn;
}
/**
* Gets the current thread's connection
* @return Connection
*/
public static Connection getConnection()
{
return getConnection(true);
}
public static Connection getConnection(boolean validate)
{
JForumExecutionContext ex = get();
Connection c = ex.conn;
if (validate && c == null) {
c = DBConnection.getImplementation().getConnection();
try {
c.setAutoCommit(!SystemGlobals.getBoolValue(ConfigKeys.DATABASE_USE_TRANSACTIONS));
}
catch (Exception e) {
//catch error autocommit
}
ex.setConnection(c);
set(ex);
}
return c;
}
public static ForumContext getForumContext()
{
return ((JForumExecutionContext)userData.get()).forumContext;
}
public void setForumContext(ForumContext forumContext)
{
this.forumContext = forumContext;
}
/**
* Gets the current thread's request
* @return WebContextRequest
*/
public static RequestContext getRequest() {
return getForumContext().getRequest();
}
/**
* Gets the current thread's response
* @return HttpServletResponse
*/
public static ResponseContext getResponse() {
return getForumContext().getResponse();
}
/**
* Gets the current thread's template context
* @return SimpleHash
*/
public static SimpleHash getTemplateContext() {
return ((JForumExecutionContext)userData.get()).context;
}
/**
* Gets the current thread's <code>DataHolder</code> instance
* @param redirect String
*/
public static void setRedirect(String redirect) {
((JForumExecutionContext)userData.get()).redirectTo = redirect;
}
/**
* Sets the content type for the current http response.
* @param contentType String
*/
public static void setContentType(String contentType) {
((JForumExecutionContext)userData.get()).contentType = contentType;
}
/**
* Gets the content type for the current request.
* @return String
*/
public static String getContentType()
{
return ((JForumExecutionContext)userData.get()).contentType;
}
/**
* Gets the URL to redirect to, if any.
* @return The URL to redirect, of <code>null</code> if none.
*/
public static String getRedirectTo()
{
JForumExecutionContext ex = (JForumExecutionContext)userData.get();
return (ex != null ? ex.redirectTo : null);
}
/**
* Marks the request to use a binary content-type.
* @param enable boolean
*/
public static void enableCustomContent(boolean enable) {
((JForumExecutionContext)userData.get()).isCustomContent = enable;
}
/**
* Checks if the current request is binary
* @return <code>true</code> if the content tyee for the current request is
* any binary data.
*/
public static boolean isCustomContent()
{
return ((JForumExecutionContext)userData.get()).isCustomContent;
}
/**
* Forces the request to not commit the connection.
*/
public static void enableRollback() {
((JForumExecutionContext)userData.get()).enableRollback = true;
}
/**
* Check if commit is disabled or not for the current request.
* @return <code>true</code> if a commit should NOT be made
*/
public static boolean shouldRollback() {
return ((JForumExecutionContext)userData.get()).enableRollback;
}
/**
* Send UNAUTHORIZED to the browser and ask user to login via basic authentication
*/
public static void requestBasicAuthentication()
{
getResponse().addHeader("WWW-Authenticate", "Basic realm=\"JForum\"");
try {
getResponse().sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
catch (IOException e) {
throw new ForumException(e);
}
enableCustomContent(true);
}
/**
* Finishes the execution context
*/
public static void finish()
{
Connection conn = JForumExecutionContext.getConnection(false);
if (conn != null) {
if (SystemGlobals.getBoolValue(ConfigKeys.DATABASE_USE_TRANSACTIONS)) {
if (JForumExecutionContext.shouldRollback()) {
try {
conn.rollback();
}
catch (Exception e) {
logger.error("Error while rolling back a transaction", e);
}
}
else {
try {
conn.commit();
}
catch (Exception e) {
logger.error("Error while commiting a transaction", e);
}
}
}
try {
DBConnection.getImplementation().releaseConnection(conn);
}
catch (Exception e) {
logger.error("Error while releasing the connection : " + e, e);
}
}
userData.set(null);
}
}