001/*
002    Licensed to the Apache Software Foundation (ASF) under one
003    or more contributor license agreements.  See the NOTICE file
004    distributed with this work for additional information
005    regarding copyright ownership.  The ASF licenses this file
006    to you under the Apache License, Version 2.0 (the
007    "License"); you may not use this file except in compliance
008    with the License.  You may obtain a copy of the License at
009
010       http://www.apache.org/licenses/LICENSE-2.0
011
012    Unless required by applicable law or agreed to in writing,
013    software distributed under the License is distributed on an
014    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015    KIND, either express or implied.  See the License for the
016    specific language governing permissions and limitations
017    under the License.
018 */
019package org.apache.wiki.api.core;
020
021import javax.servlet.http.HttpServletRequest;
022import javax.servlet.jsp.PageContext;
023import java.security.Principal;
024
025
026/**
027 *  <p>Provides state information throughout the processing of a page.  A Context is born when the JSP pages that are the main entry
028 *  points, are invoked.  The JSPWiki engine creates the new Context, which basically holds information about the page, the
029 *  handling engine, and in which context (view, edit, etc) the call was done.</p>
030 *  <p>A Context also provides request-specific variables, which can be used to communicate between plugins on the same page, or
031 *  between different instances of the same plugin. A Context variable is valid until the processing of the WikiPage has ended. For
032 *  an example, please see the Counter plugin.</p>
033 *  <p>When a Context is created, it automatically associates a {@link Session} object with the user's
034 *  HttpSession. The Session contains information about the user's authentication status, and is consulted by {@link #getCurrentUser()}
035 *  object.</p>
036 *  <p>Do not cache the WikiPage object that you get from the WikiContext; always use getPage()!</p>
037 *
038 *  @see {@code org.apache.wiki.plugin.Counter}
039 */
040public interface Context extends Cloneable, Command {
041
042    String ATTR_CONTEXT = "jspwiki.context";
043
044    /**
045     *  Variable name which tells whether plugins should be executed or not. Value can be either {@code Boolean.TRUE} or
046     *  {@code Boolean.FALSE}. While not set its value is {@code null}.
047     */
048    String VAR_EXECUTE_PLUGINS = "_PluginContent.execute";
049
050    /** Name of the variable which is set to Boolean.TRUE or Boolean.FALSE depending on whether WYSIWYG is currently in effect. */
051    String VAR_WYSIWYG_EDITOR_MODE = "WYSIWYG_EDITOR_MODE";
052
053    /**
054     *  Returns the WikiPage that is being handled.
055     *
056     *  @return the WikiPage which was fetched.
057     */
058    Page getPage();
059
060    /**
061     *  Sets the WikiPage that is being handled.
062     *
063     *  @param wikiPage The wikipage
064     *  @since 2.1.37.
065     */
066    void setPage( Page wikiPage );
067
068    /**
069     *  Gets a reference to the real WikiPage whose content is currently being rendered. If your plugin e.g. does some variable setting, be
070     *  aware that if it is embedded in the LeftMenu or some other WikiPage added with InsertPageTag, you should consider what you want to
071     *  do - do you wish to really reference the "master" WikiPage or the included page.
072     *  <p>
073     *  For example, in the default template, there is a WikiPage called "LeftMenu". Whenever you access a page, e.g. "Main", the master
074     *  WikiPage will be Main, and that's what the getPage() will return - regardless of whether your plugin resides on the LeftMenu or on
075     *  the Main page.  However, getRealPage() will return "LeftMenu".
076     *
077     *  @return A reference to the real page.
078     *  @see {@code org.apache.wiki.tags.InsertPageTag}
079     *  @see {@code org.apache.wiki.parser.JSPWikiMarkupParser}
080     */
081    Page getRealPage();
082
083    /**
084     *  Sets a reference to the real WikiPage whose content is currently being rendered.
085     *  <p>
086     *  Sometimes you may want to render the WikiPage using some other page's context. In those cases, it is highly recommended that you set
087     *  the setRealPage() to point at the real WikiPage you are rendering.  Please see InsertPageTag for an example.
088     *  <p>
089     *  Also, if your plugin e.g. does some variable setting, be aware that if it is embedded in the LeftMenu or some other WikiPage added
090     *  with InsertPageTag, you should consider what you want to do - do you wish to really reference the "master" WikiPage or the included
091     *  page.
092     *
093     *  @param wikiPage  The real WikiPage which is being rendered.
094     *  @return The previous real page
095     *  @since 2.3.14
096     *  @see {@code org.apache.wiki.tags.InsertPageTag}
097     */
098    Page setRealPage( Page wikiPage );
099
100    /**
101     *  Returns the handling engine.
102     *
103     *  @return The wikiengine owning this context.
104     */
105    Engine getEngine();
106
107    /**
108     *  Sets the request context.  See above for the different request contexts (VIEW, EDIT, etc.)
109     *
110     *  @param context The request context (one of the predefined contexts.)
111     */
112    void setRequestContext( String context );
113
114    /**
115     *  Gets a previously set variable.
116     *
117     *  @param key The variable name.
118     *  @return The variable contents.
119     */
120    < T > T getVariable( String key );
121
122    /**
123     *  Sets a variable.  The variable is valid while the WikiContext is valid, i.e. while WikiPage processing continues.  The variable data
124     *  is discarded once the WikiPage processing is finished.
125     *
126     *  @param key The variable name.
127     *  @param data The variable value.
128     */
129    void setVariable( String key, Object data );
130
131    /**
132     * This is just a simple helper method which will first check the context if there is already an override in place, and if there is not,
133     * it will then check the given properties.
134     *
135     * @param key What key are we searching for?
136     * @param defValue Default value for the boolean
137     * @return {@code true} or {@code false}.
138     */
139    boolean getBooleanWikiProperty( String key, boolean defValue );
140
141    /**
142     *  This method will safely return any HTTP parameters that might have been defined.  You should use this method instead
143     *  of peeking directly into the result of getHttpRequest(), since this method is smart enough to do all the right things,
144     *  figure out UTF-8 encoded parameters, etc.
145     *
146     *  @since 2.0.13.
147     *  @param paramName Parameter name to look for.
148     *  @return HTTP parameter, or null, if no such parameter existed.
149     */
150    String getHttpParameter( String paramName );
151
152    /**
153     *  If the request did originate from an HTTP request, then the HTTP request can be fetched here.  However, if the request
154     *  did NOT originate from an HTTP request, then this method will return null, and YOU SHOULD CHECK FOR IT!
155     *
156     *  @return Null, if no HTTP request was done.
157     *  @since 2.0.13.
158     */
159    HttpServletRequest getHttpRequest();
160
161    /**
162     *  Sets the template to be used for this request.
163     *
164     *  @param dir The template name
165     *  @since 2.1.15.
166     */
167    void setTemplate( String dir );
168
169    /**
170     *  Gets the template that is to be used throughout this request.
171     *
172     *  @since 2.1.15.
173     *  @return template name
174     */
175    String getTemplate();
176
177    /**
178     *  Returns the Session associated with the context. This method is guaranteed to always return a valid Session.
179     *  If this context was constructed without an associated HttpServletRequest, it will return a guest session.
180     *
181     *  @return The Session associate with this context.
182     */
183    Session getWikiSession();
184
185    /**
186     *  Convenience method that gets the current user. Delegates the lookup to the Session associated with this Context.
187     *  May return null, in case the current user has not yet been determined; or this is an internal system. If the Session has not
188     *  been set, <em>always</em> returns null.
189     *
190     *  @return The current user; or maybe null in case of internal calls.
191     */
192    Principal getCurrentUser();
193
194    /**
195     *  Returns true, if the current user has administrative permissions (i.e. the omnipotent AllPermission).
196     *
197     *  @since 2.4.46
198     *  @return true, if the user has all permissions.
199     */
200    boolean hasAdminPermissions();
201
202    /**
203     *  A shortcut to generate a VIEW url.
204     *
205     *  @param WikiPage The WikiPage to which to link.
206     *  @return A URL to the page.  This honours the current absolute/relative setting.
207     */
208    String getViewURL( String WikiPage );
209
210    /**
211     *  Figure out to which WikiPage we are really going to.  Considers special WikiPage names from the jspwiki.properties, and possible aliases.
212     *
213     *  @return A complete URL to the new WikiPage to redirect to
214     *  @since 2.2
215     */
216    String getRedirectURL();
217
218    /**
219     * Returns the Command associated with this Context.
220     *
221     * @return the command
222     */
223    Command getCommand();
224
225    /**
226     *  Creates a URL for the given request context.
227     *
228     *  @param context e.g. WikiContext.EDIT
229     *  @param page The WikiPage to which to link
230     *  @return A URL to the page.
231     */
232    default String getURL( final String context, final String page ) {
233        return getURL( context, page, null );
234    }
235
236    /**
237     *  Returns a URL from a page. It this Context instance was constructed with an actual HttpServletRequest, we will attempt to
238     *  construct the URL using HttpUtil, which preserves the HTTPS portion if it was used.
239     *
240     *  @param context The request context (e.g. WikiContext.UPLOAD)
241     *  @param page The WikiPage to which to link
242     *  @param params A list of parameters, separated with "&amp;"
243     *
244     *  @return A URL to the given context and page.
245     */
246    default String getURL( final String context, final String page, final String params ) {
247        // FIXME: is rather slow
248        return getEngine().getURL( context, page, params );
249    }
250
251    /** {@inheritDoc} */
252    Context clone();
253
254    /**
255     *  Creates a deep clone of the Context. This is useful when you want to be sure that you don't accidentally mess with page
256     *  attributes, etc.
257     *
258     *  @since  2.8.0
259     *  @return A deep clone of the Context.
260     */
261    Context deepClone();
262
263    /**
264     *  This method can be used to find the WikiContext programmatically from a JSP PageContext. We check the request context.
265     *  The wiki context, if it exists, is looked up using the key {@link #ATTR_CONTEXT}.
266     *
267     *  @since 2.4
268     *  @param pageContext the JSP page context
269     *  @return Current WikiContext, or null, of no context exists.
270     */
271    static Context findContext( final PageContext pageContext ) {
272        final HttpServletRequest request = ( HttpServletRequest )pageContext.getRequest();
273        return ( Context )request.getAttribute( ATTR_CONTEXT );
274    }
275
276}