001/*
002 * (C) Copyright 2006-2012 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     bstefanescu
018 *
019 */
020
021package org.nuxeo.ecm.webengine.model;
022
023import java.io.Writer;
024import java.security.Principal;
025import java.text.ParseException;
026import java.util.List;
027import java.util.Locale;
028import java.util.Map;
029
030import javax.servlet.http.HttpServletRequest;
031import javax.ws.rs.core.HttpHeaders;
032import javax.ws.rs.core.UriInfo;
033
034import org.apache.commons.logging.Log;
035import org.nuxeo.ecm.core.api.CoreSession;
036import org.nuxeo.ecm.core.api.DocumentModel;
037import org.nuxeo.ecm.webengine.WebEngine;
038import org.nuxeo.ecm.webengine.WebException;
039import org.nuxeo.ecm.webengine.forms.FormData;
040import org.nuxeo.ecm.webengine.scripting.ScriptFile;
041import org.nuxeo.ecm.webengine.session.UserSession;
042import org.nuxeo.runtime.model.Adaptable;
043
044import com.sun.jersey.api.core.HttpContext;
045import com.sun.jersey.server.impl.inject.ServerInjectableProviderContext;
046
047/**
048 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
049 */
050public interface WebContext extends Adaptable {
051
052    /**
053     * <p>
054     * This variable is used in a proxy setting. The proxy should send a header with this name. Webengine will assume
055     * that the base path of the application is this value.
056     * <p>
057     * If your application is on server localhost:8080/nuxeo/site/myapp and you proxy it via mysite.com/myapp, then the
058     * header should have an empty string value.
059     */
060    String NUXEO_WEBENGINE_BASE_PATH = "nuxeo-webengine-base-path";
061
062    /**
063     * Gets the current web application.
064     *
065     * @return the web root. Cannot return null.
066     */
067    Module getModule();
068
069    /**
070     *
071     * Gets the jersey server injection context
072     *
073     * @since 9.1
074     */
075    ServerInjectableProviderContext getServerInjectableProviderContext();
076
077    /**
078     * Gets the jersey server http context
079     *
080     * @since 9.1
081     */
082    HttpContext getServerHttpContext();
083
084    /**
085     * Gets the root resource if any resource was defined as being the root
086     * <p>
087     * A root resource can be any resource from the resource chain.
088     *
089     * @return the root resource or null if no root was defined
090     */
091    Resource getRoot();
092
093    /**
094     * Set the root resource of this context
095     */
096    void setRoot(Resource root);
097
098    /**
099     * Gets the i18n message for the given key.
100     * <p>
101     * The current module i18n messages are queried first then if no message is found the global message pool is queried
102     * (the one living in WEB-INF/i18n). If no message is found the key surrounded by exclamation marks is returned.
103     *
104     * @param key the message key
105     * @return the message
106     */
107    String getMessage(String key);
108
109    /**
110     * The same as {@link #getMessage(String)} but with parameter support
111     */
112    String getMessage(String key, Object... args);
113
114    /**
115     * The same as {@link #getMessage(String)} but with parameter support
116     */
117    String getMessage(String key, List<Object> args);
118
119    /**
120     * Same as {@link #getMessage(String)} but uses the given locale.
121     *
122     * @param key the message key
123     * @param locale the locale to use
124     * @return the message
125     */
126    String getMessageL(String key, String locale);
127
128    /**
129     * The same as {@link #getMessage(String)} but uses the given locale, with parameter support
130     */
131    String getMessageL(String key, String locale, Object... args);
132
133    /**
134     * The same as {@link #getMessage(String)} but uses the given locale, with parameter support.
135     */
136    String getMessageL(String key, String locale, List<Object> args);
137
138    /**
139     * Gets the context locale.
140     * <p>
141     * If the locale has been set using {@link #setLocale(Locale)}, returns the last locale set. Otherwise, compute it
142     * from the Accept-Language language sent by the client, using {@link HttpServletRequest#getLocale()}.
143     *
144     * @return the context locale
145     */
146    Locale getLocale();
147
148    /**
149     * Sets the current locale, that will be kept in context.
150     */
151    void setLocale(Locale locale);
152
153    /**
154     * Gets the web engine instance.
155     *
156     * @return the web engine instance. Cannot return null
157     */
158    WebEngine getEngine();
159
160    /**
161     * Gets the current user session.
162     * <p>
163     * The user session is a WebEngine abstraction for the current user session and can be used to retrieve current
164     * login, core session, and to set or get user session variables.
165     *
166     * @return the user session. Never returns null.
167     */
168    UserSession getUserSession();
169
170    /**
171     * Gets the Core Session (or Repository Session) corresponding to that request.
172     *
173     * @return the core session. Cannot return null
174     */
175    CoreSession getCoreSession();
176
177    /**
178     * Gets the principal identifying the user that originated the request.
179     *
180     * @return the current principal. Can return null if the user has not been authenticated.
181     */
182    Principal getPrincipal();
183
184    /**
185     * Gets the JAX-RS UriInfo.
186     *
187     * @return the uri info
188     */
189    UriInfo getUriInfo();
190
191    /**
192     * Gets HTTP Headers as defined by JAX-RS.
193     *
194     * @return HTTP headers object
195     */
196    HttpHeaders getHttpHeaders();
197
198    /**
199     * Gets the underlying HTTP servlet request object.
200     *
201     * @return the HTTP Request object. Cannot return null
202     */
203    HttpServletRequest getRequest();
204
205    /**
206     * Get HTTP Method.
207     *
208     * @return the method
209     */
210    String getMethod();
211
212    /**
213     * Gets the representation of the data form submitted by the user.
214     * <p>
215     * This provides access to both POST and GET parameters, or to multipart form data requests.
216     *
217     * @return the request form data. Cannot return null
218     */
219    FormData getForm();
220
221    /**
222     * Gets the URL requested by the client. Same as {@link HttpServletRequest#getRequestURL()}.
223     *
224     * @return the request URL. Cannot return null.
225     */
226    String getURL();
227
228    /**
229     * Returns the part of this request's URL from the protocol name up to the query string in the first line of the
230     * HTTP request. This is the same as {@link HttpServletRequest#getRequestURI()}.
231     *
232     * @return the request URI. Cannot return null.
233     */
234    String getURI();
235
236    /**
237     * Gets the path portion of the request URL.
238     *
239     * @return the path portion of the request URL. Cannot return null.
240     */
241    String getUrlPath();
242
243    /**
244     * Gets the login path for the current context.
245     * <p>
246     * This is the path you can use as a login form action to perform a login or a logout. After the login/logout is
247     * done the current page in that context will be served.
248     */
249    String getLoginPath();
250
251    /**
252     * Get the path prefix that identify the current web application.
253     * <p>
254     * The application path will include the base path (context + servlet path).
255     *
256     * @return the application path. Cannot be null
257     */
258    String getModulePath();
259
260    /**
261     * Gets the path of the servlet. Same as servlet context path + servlet path.
262     *
263     * @return the site path
264     */
265    String getBasePath();
266
267    /**
268     * Gets the URL of the base path. This is the same as {@link #getURL()} after removing the path segments over the
269     * base path.
270     *
271     * @return the base URL
272     */
273    String getBaseURL();
274
275    /**
276     * Gets the server URL without any path or trailing /. The returned string builder can be used to build the wanted
277     * URL. If the server is behind a proxy, return the server url of the proxy so writing the url in a webpage is safe.
278     *
279     * @return a string builder
280     */
281    StringBuilder getServerURL();
282
283    /**
284     * Get a suitable URI path for the given Nuxeo document, that can be used to invoke this document. This method is
285     * working only for root objects that implement {@link ModuleResource}
286     *
287     * @param document the nuxeo document
288     * @return the path if any or null if no suitable path can be found XXX can this method return null?
289     * @throws ClassCastException if the module root does not implementing {@link ModuleResource}
290     */
291    // TODO: should we remove this method from the context and create a
292    // specialized service to resolve document models to paths?
293    String getUrlPath(DocumentModel document);
294
295    /**
296     * Sets a context variable.
297     *
298     * @param key the variable key
299     * @param value the variable value
300     * @see #getProperty(String)
301     */
302    void setProperty(String key, Object value);
303
304    /**
305     * Gets a context variable.
306     * <p>
307     * Context variables can be used to share data between the scripts that are called in that request (and between Java
308     * code too of course).
309     *
310     * @param key the variable key
311     * @return the variable value or null if none
312     */
313    Object getProperty(String key);
314
315    /**
316     * Gets a context variable.
317     * <p>
318     * Context variables can be used to share data between the scripts that are called in that request (and between java
319     * code too of course).
320     *
321     * @param key the variable key
322     * @param defaultValue the default value to use if the property doesn't exists
323     * @return the variable value or the given default value if none
324     */
325    Object getProperty(String key, Object defaultValue);
326
327    /**
328     * Convenience method to get a cookie value.
329     *
330     * @param name the cookie name
331     * @return the cookie value if any null otherwise
332     */
333    String getCookie(String name);
334
335    /**
336     * Convenience method to get a cookie value using a default value.
337     *
338     * @param name the cookie name
339     * @param defaultValue the value to return when cookie is not set
340     * @return the cookie value if any or the default if none
341     */
342    String getCookie(String name, String defaultValue);
343
344    /**
345     * Gets a logger to be used by scripts for logging.
346     *
347     * @return a logger
348     */
349    Log getLog();
350
351    Resource newObject(String typeName, Object... args);
352
353    Resource newObject(ResourceType type, Object... args);
354
355    AdapterResource newAdapter(Resource ctx, String adapterName, Object... args);
356
357    /* object stack API */
358
359    Resource push(Resource obj);
360
361    Resource pop();
362
363    Resource tail();
364
365    Resource head();
366
367    Resource getTargetObject();
368
369    AdapterResource getTargetAdapter();
370
371    /* template and script resolver */
372
373    /**
374     * Resolves the given path into a file.
375     * <p>
376     * The path is resolved as following:
377     * <ol>
378     * <li>if the path begin with a dot '.' then a local path is assumed and the path will be resolved relative to the
379     * current executed script if any. Note that the directory stack will be consulted as well. If there is no current
380     * executed script then the path will be transformed into an absolute path and next step is entered.
381     * <li>the resolving is delegated to the current {@link Module#getFile(String)} that will try to resolve the path
382     * relative to each directory in the directory stack
383     * </ol>
384     *
385     * @param path the path to resolve into a file
386     * @return the file or null if the path couldn't be resolved
387     */
388    ScriptFile getFile(String path);
389
390    /* running scripts and rendering templates */
391
392    /**
393     * Renders the given template using the rendering engine registered in that web engine.
394     * <p>
395     * This is similar to the {@link #render(String, Object, Writer)} method with a null value for the <i>args</i>
396     * argument.
397     *
398     * @param template the template to render. Can be a path absolute to the web directory or relative to the caller
399     *            script if any.
400     * @param writer the writer to use
401     * @see #render(String, Object, Writer)
402     */
403    void render(String template, Writer writer);
404
405    /**
406     * Renders the given template using the rendering engine registered in that web engine. The given arguments are
407     * passed to the rendering process as context variables
408     *
409     * @param template the template to render
410     * @param args the arguments to pass
411     * @param writer the writer to use
412     * @throws WebException
413     */
414    void render(String template, Object args, Writer writer);
415
416    /**
417     * Renders the given template using the rendering engine registered in that web engine.
418     * <p>
419     * The given arguments are passed to the rendering process as context variables.
420     *
421     * @param script the template to render
422     * @param args the arguments to pass
423     * @param writer the writer to use
424     * @throws WebException
425     */
426    void render(ScriptFile script, Object args, Writer writer);
427
428    /**
429     * Runs the given script.
430     *
431     * @param script the script path. Can be a path absolute to the web directory or relative to the caller script if
432     *            any.
433     * @param args the arguments to pass
434     */
435    Object runScript(String script, Map<String, Object> args);
436
437    /**
438     * Runs the given script.
439     * <p>
440     * This is similar to {@link #runScript(String, Map)} with a null value for the <i>args</i> argument
441     *
442     * @param script the script path. Can be a path absolute to the web directory or relative to the caller script if
443     *            any.
444     * @see #runScript(String, Map)
445     */
446    Object runScript(String script);
447
448    /**
449     * Runs the script using given arguments
450     * <p>
451     * This is similar to {@link #runScript(String, Map)} with a null value for the <i>args</i> argument
452     *
453     * @param script the script path. Can be a path absolute to the web directory or relative to the caller script if
454     *            any.
455     * @param args a map of arguments
456     * @see #runScript(String, Map)
457     */
458    Object runScript(ScriptFile script, Map<String, Object> args);
459
460    /**
461     * Check the given expression in this context and return true if the expression is verified or false otherwise. Any
462     * valid guard expression is accepted
463     *
464     * @see org.nuxeo.ecm.webengine.security.Guard
465     * @param guard the guard to check
466     */
467    boolean checkGuard(String guard) throws ParseException;
468
469    /**
470     * Sets the repository name that will be used by {@link #getCoreSession()}.
471     *
472     * @param repoName
473     * @throws IllegalArgumentException if the repository is not found.
474     * @since 5.7.3
475     */
476    void setRepositoryName(String repoName);
477
478}