blob: 1089900c1efe03e52a4df7fe1b6e1fa57dc173a1 [file] [log] [blame]
/*
JSPWiki - a JSP-based WikiWiki clone.
Copyright (C) 2001 Janne Jalkanen (Janne.Jalkanen@iki.fi)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.ecyrd.jspwiki;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.PageContext;
import org.apache.log4j.Logger;
import com.ecyrd.jspwiki.auth.WikiPrincipal;
import com.ecyrd.jspwiki.tags.WikiTagBase;
import com.ecyrd.jspwiki.util.HttpUtil;
/**
* <p>Provides state information throughout the processing of a page. A
* WikiContext is born when the JSP pages that are the main entry
* points, are invoked. The JSPWiki engine creates the new
* WikiContext, which basically holds information about the page, the
* handling engine, and in which context (view, edit, etc) the
* call was done.</p>
* <p>A WikiContext also provides request-specific variables, which can
* be used to communicate between plugins on the same page, or
* between different instances of the same plugin. A WikiContext
* variable is valid until the processing of the page has ended. For
* an example, please see the Counter plugin.</p>
* <p>When a WikiContext is created, it automatically associates a
* {@link WikiSession} object with the user's HttpSession. The
* WikiSession contains information about the user's authentication
* status, and is consulted by {@link #getCurrentUser()}.
* object</p>
*
* @see com.ecyrd.jspwiki.plugin.Counter
*
* @author Janne Jalkanen
* @author Andrew R. Jaquith
*/
public class WikiContext
implements Cloneable
{
WikiPage m_page;
WikiPage m_realPage;
WikiEngine m_engine;
String m_requestContext = VIEW;
String m_template = "default";
Map m_variableMap = new HashMap();
HttpServletRequest m_request = null;
WikiSession m_session = null;
/** The VIEW context - the user just wants to view the page
contents. */
public static final String VIEW = "view";
/** The EDIT context - the user is editing the page. */
public static final String EDIT = "edit";
/** User is preparing for a login/authentication. */
public static final String LOGIN = "login";
/** User is preparing to log out. */
public static final String LOGOUT = "logout";
/** User is viewing a DIFF between the two versions of the page. */
public static final String DIFF = "diff";
/** User is viewing page history. */
public static final String INFO = "info";
/** User is previewing the changes he just made. */
public static final String PREVIEW = "preview";
/** User has an internal conflict, and does quite not know what to
do. Please provide some counseling. */
public static final String CONFLICT = "conflict";
/** An error has been encountered and the user needs to be informed. */
public static final String ERROR = "error";
public static final String UPLOAD = "upload";
public static final String COMMENT = "comment";
public static final String FIND = "find";
public static final String CREATE_GROUP = "createGroup";
public static final String PREFS = "prefs";
/** Deprecated. @deprecated */
public static final String REGISTER = "register";
public static final String RENAME = "rename";
public static final String DELETE = "del";
public static final String ATTACH = "att";
public static final String RSS = "rss";
public static final String NONE = ""; // This is not a JSPWiki context, use it to access static files
public static final String OTHER = NONE; // This is just a clarification.
protected static Logger log = Logger.getLogger( WikiContext.class );
/**
* Create a new WikiContext for the given WikiPage. Delegates to
* {@link #WikiContext(WikiEngine, HttpServletRequest, WikiPage)}.
* @param engine The WikiEngine that is handling the request.
* @param page The WikiPage. If you want to create a
* WikiContext for an older version of a page, you must use this
* constructor.
*/
public WikiContext( WikiEngine engine, WikiPage page )
{
this(engine, null, page);
}
/**
* <p>
* Creates a new WikiContext for the given WikiEngine, WikiPage and
* HttpServletRequest. This constructor will also look up the HttpSession
* associated with the request, and determine if a WikiSession object is
* present. If not, a new one is created.
* </p>
* <p>
* After the WikiSession object is obtained, the current authentication
* status is checked. If not authenticated, or if the login status reported
* by the container has changed, the constructor attempts to log in the user
* with
* {@link com.ecyrd.jspwiki.auth.AuthenticationManager#login(HttpServletRequest)}.
* </p>
* @param engine The WikiEngine that is handling the request
* @param request The HttpServletRequest that should be associated with this
* context. This parameter may be <code>null</code>.
* @param page The WikiPage. If you want to create a WikiContext for an
* older version of a page, you must supply this parameter
*/
public WikiContext(WikiEngine engine, HttpServletRequest request, WikiPage page)
{
super();
m_engine = engine;
m_request = request;
m_session = WikiSession.getWikiSession( request );
m_page = page;
m_realPage = page;
// Log in the user if new session or the container status changed
boolean doLogin = ( (request != null) && m_session.getLastContext() == null );
// Debugging...
if ( log.isDebugEnabled() )
{
HttpSession session = ( request == null ) ? null : request.getSession( false );
String sid = ( session == null ) ? "(null)" : session.getId();
log.debug( "Creating WikiContext for session ID=" + sid + "; page=" + page.getName() );
log.debug( "Do we need to log the user in? " + doLogin );
}
if ( doLogin || m_session.isContainerStatusChanged( request ) )
{
engine.getAuthenticationManager().login( request );
}
// Stash the wiki context in the session as the "last context"
m_session.setLastContext( this );
}
/**
* Sometimes you may want to render the page using some other page's context.
* In those cases, it is highly recommended that you set the setRealPage()
* to point at the real page you are rendering.
*
* @param page The real page which is being rendered.
* @since 2.3.14
* @return The previous real page
*/
public WikiPage setRealPage( WikiPage page )
{
WikiPage old = m_realPage;
m_realPage = page;
return old;
}
public WikiPage getRealPage()
{
return m_realPage;
}
/**
* Returns the handling engine.
*/
public WikiEngine getEngine()
{
return m_engine;
}
/**
* Returns the page that is being handled.
*/
public WikiPage getPage()
{
return m_page;
}
/**
* Sets the page that is being handled.
*
* @since 2.1.37.
*/
public void setPage( WikiPage page )
{
m_page = page;
}
/**
* Returns the request context.
*/
public String getRequestContext()
{
return m_requestContext;
}
/**
* Sets the request context. See above for the different
* request contexts (VIEW, EDIT, etc.)
*
* @param arg The request context (one of the predefined contexts.)
*/
public void setRequestContext( String arg )
{
m_requestContext = arg;
}
/**
* Gets a previously set variable.
*
* @param key The variable name.
* @return The variable contents.
*/
public Object getVariable( String key )
{
return m_variableMap.get( key );
}
/**
* Sets a variable. The variable is valid while the WikiContext is valid,
* i.e. while page processing continues. The variable data is discarded
* once the page processing is finished.
*
* @param key The variable name.
* @param data The variable value.
*/
public void setVariable( String key, Object data )
{
m_variableMap.put( key, data );
}
/**
* This method will safely return any HTTP parameters that
* might have been defined. You should use this method instead
* of peeking directly into the result of getHttpRequest(), since
* this method is smart enough to do all of the right things,
* figure out UTF-8 encoded parameters, etc.
*
* @since 2.0.13.
* @param paramName Parameter name to look for.
* @return HTTP parameter, or null, if no such parameter existed.
*/
public String getHttpParameter( String paramName )
{
String result = null;
if( m_request != null )
{
result = m_request.getParameter( paramName );
}
return result;
}
/**
* If the request did originate from a HTTP request,
* then the HTTP request can be fetched here. However, it the request
* did NOT originate from a HTTP request, then this method will
* return null, and YOU SHOULD CHECK FOR IT!
*
* @return Null, if no HTTP request was done.
* @since 2.0.13.
*/
public HttpServletRequest getHttpRequest()
{
return m_request;
}
/**
* Sets the template to be used for this request.
* @since 2.1.15.
*/
public void setTemplate( String dir )
{
m_template = dir;
}
/**
* Gets the template that is to be used throughout this request.
* @since 2.1.15.
*/
public String getTemplate()
{
return m_template;
}
/**
* Convenience method that gets the current user. Delegates the
* lookup to the WikiSession associated with this WikiContect.
* May return null, in case the current
* user has not yet been determined; or this is an internal system.
* If the WikiSession has not been set, <em>always</em> returns null.
*/
public Principal getCurrentUser()
{
if (m_session == null)
{
// This shouldn't happen, really...
return WikiPrincipal.GUEST;
}
return m_session.getUserPrincipal();
}
public String getViewURL( String page )
{
return getURL( VIEW, page, null );
}
public String getURL( String context,
String page )
{
return getURL( context, page, null );
}
/**
* Returns an URL from a page. It this WikiContext instance was constructed
* with an actual HttpServletRequest, we will attempt to construct the
* URL using HttpUtil, which preserves the HTTPS portion if it was used.
*/
public String getURL( String context,
String page,
String params )
{
boolean absolute = "absolute".equals(m_engine.getVariable( this, WikiEngine.PROP_REFSTYLE ));
if ( m_request == null || !absolute )
{
// FIXME: is rather slow
return m_engine.getURL( context,
page,
params,
absolute );
}
else
{
String url = HttpUtil.makeBaseURLNoContext( m_request )
+ m_engine.getURL( context, page, params, false );
return url;
}
}
/**
* Returns a shallow clone of the WikiContext.
*
* @since 2.1.37.
*/
public Object clone()
{
WikiContext copy = new WikiContext( m_engine, m_page );
copy.m_requestContext = m_requestContext;
copy.m_template = m_template;
copy.m_variableMap = m_variableMap;
copy.m_request = m_request;
copy.m_session = m_session;
return copy;
}
/**
* Returns the WikiSession associated with the context.
* This method is guaranteed to always return a valid WikiSession.
* If this context was constructed without an associated
* HttpServletRequest, it will return {@link WikiSession#guestSession()}.
*/
public WikiSession getWikiSession()
{
return m_session;
}
/**
* This method can be used to find the WikiContext programmatically
* from a JSP PageContext.
*
* @since 2.4
* @param pc
* @return Current WikiContext, or null, of no context exists.
*/
public static WikiContext findContext( PageContext pageContext )
{
return (WikiContext)pageContext.getAttribute( WikiTagBase.ATTR_CONTEXT, PageContext.REQUEST_SCOPE );
}
}