Source code: com/opencms/file/CmsRequestContext.java
1 /*
2 * File : $Source: /usr/local/cvs/opencms/src/com/opencms/file/CmsRequestContext.java,v $
3 * Date : $Date: 2003/03/07 16:15:49 $
4 * Version: $Revision: 1.67 $
5 *
6 * This library is part of OpenCms -
7 * the Open Source Content Mananagement System
8 *
9 * Copyright (C) 2001 The OpenCms Group
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * For further information about OpenCms, please see the
22 * OpenCms Website: http://www.opencms.org
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 */
28
29 package com.opencms.file;
30
31 import com.opencms.boot.I_CmsLogChannels;
32 import com.opencms.core.A_OpenCms;
33 import com.opencms.core.CmsException;
34 import com.opencms.core.CmsExportRequest;
35 import com.opencms.core.CmsSession;
36 import com.opencms.core.I_CmsConstants;
37 import com.opencms.core.I_CmsRequest;
38 import com.opencms.core.I_CmsResponse;
39 import com.opencms.core.I_CmsSession;
40 import com.opencms.flex.util.CmsResourceTranslator;
41 import com.opencms.template.cache.CmsElementCache;
42 import com.opencms.workplace.I_CmsWpConstants;
43
44 import java.util.HashMap;
45 import java.util.StringTokenizer;
46 import java.util.Vector;
47
48 import javax.servlet.http.HttpServletRequest;
49 import javax.servlet.http.HttpSession;
50
51 /**
52 * This class provides access to the CmsRequestContext.
53 * <br>
54 * In the CmsRequestContext class are all methods bundled, which can inform about the
55 * current request properties, like the url or uri of the request.
56 * <p>
57 *
58 * @author Andreas Schouten
59 * @author Michael Emmerich
60 * @author Anders Fugmann
61 * @author Alexander Lucas
62 *
63 * @version $Revision: 1.67 $ $Date: 2003/03/07 16:15:49 $
64 *
65 */
66 public class CmsRequestContext implements I_CmsConstants {
67
68 /** The rb to get access to the OpenCms */
69 private I_CmsResourceBroker m_rb;
70
71 /** The current CmsRequest */
72 private I_CmsRequest m_req;
73
74 /** The current CmsResponse */
75 private I_CmsResponse m_resp;
76
77 /** The current user */
78 private CmsUser m_user;
79
80 /** The current group of the user */
81 private CmsGroup m_currentGroup;
82
83 /** The current project */
84 private CmsProject m_currentProject;
85
86 /** Flag to indicate if this response is streaming or not (legacy, not used by Element or Flex cache) */
87 private boolean m_streaming = true;
88
89 /**
90 * In export mode the links in pages will be stored in this vector
91 * for further processing.
92 */
93 private Vector m_links;
94
95 /** Flag to indicate that this request is event controlled */
96 private boolean m_eventControlled = false;
97
98 /** Flag to indicate that this context should not update the user session */
99 private boolean m_updateSession = true;
100
101 /**
102 * In export mode this vector is used to store all dependencies this request
103 * may have. It is saved to the database and if one of the dependencies changes
104 * the request will be exported again.
105 */
106 private Vector m_dependencies;
107
108 /** Starting point for element cache */
109 private CmsElementCache m_elementCache = null;
110
111 /** Current languages */
112 private Vector m_language = new Vector();
113
114 /** The name of the root, e.g. /site_a/vfs */
115 private String m_siteRoot = C_DEFAULT_SITE + C_ROOTNAME_VFS;
116
117 /** Current encoding */
118 private String m_encoding = null;
119
120 /** The URI for getUri() in case it is "overwritten" */
121 private String m_uri = null;
122
123 /** Directroy name translator */
124 private CmsResourceTranslator m_directoryTranslator = null;
125
126 /** File name translator */
127 private CmsResourceTranslator m_fileTranslator = null;
128
129 /** A map for storing (optional) request context attributes */
130 private HashMap m_attributeMap = null;
131
132 /**
133 * The default constructor.
134 */
135 public CmsRequestContext() {
136 super();
137 }
138
139 /**
140 * Initializes this RequestContext.
141 *
142 * @param req the CmsRequest.
143 * @param resp the CmsResponse.
144 * @param user the current user for this request.
145 * @param currentGroup the current group for this request.
146 * @param currentProjectId the id of the current project for this request.
147 * @param streaming <code>true</code> if streaming should be enabled for this response, <code>false</code> otherwise.
148 * @param elementCache Starting point for the element cache or <code>null</code> if the element cache should be disabled.
149 * @param directoryTranslator Translator for directories (file with full path)
150 * @param fileTranslator Translator for new file names (without path)
151 * @throws CmsException if operation was not successful.
152 */
153 void init(
154 I_CmsResourceBroker rb,
155 I_CmsRequest req,
156 I_CmsResponse resp,
157 String user,
158 String currentGroup,
159 int currentProjectId,
160 boolean streaming,
161 CmsElementCache elementCache,
162 CmsResourceTranslator directoryTranslator,
163 CmsResourceTranslator fileTranslator)
164 throws CmsException {
165 m_rb = rb;
166 m_req = req;
167 m_resp = resp;
168 m_links = new Vector();
169 m_dependencies = new Vector();
170
171 try {
172 m_user = m_rb.readUser(null, null, user);
173 } catch (CmsException ex) {
174 }
175 // if no user found try to read webUser
176 if (m_user == null) {
177 m_user = m_rb.readWebUser(null, null, user);
178 }
179
180 // check, if the user is disabled
181 if (m_user.getDisabled() == true) {
182 m_user = null;
183 }
184
185 // set current project, group and streaming proerties for this request
186 try {
187 setCurrentProject(currentProjectId);
188 } catch (CmsException exc) {
189 // there was a problem to set the needed project - using the online one
190 setCurrentProject(I_CmsConstants.C_PROJECT_ONLINE_ID);
191 }
192 m_currentGroup = m_rb.readGroup(m_user, m_currentProject, currentGroup);
193 m_streaming = streaming;
194 m_elementCache = elementCache;
195 m_directoryTranslator = directoryTranslator;
196 m_fileTranslator = fileTranslator;
197
198 // Analyze the user's preferred languages coming with the request
199 if (req != null) {
200 try {
201 HttpServletRequest httpReq =
202 (HttpServletRequest) req.getOriginalRequest();
203 String accLangs = null;
204 if (httpReq != null) {
205 accLangs = httpReq.getHeader("Accept-Language");
206 }
207 if (accLangs != null) {
208 StringTokenizer toks = new StringTokenizer(accLangs, ",");
209 while (toks.hasMoreTokens()) {
210 // Loop through all languages and cut off trailing extensions
211 String current = toks.nextToken().trim();
212 if (current.indexOf("-") > -1) {
213 current =
214 current.substring(0, current.indexOf("-"));
215 }
216 if (current.indexOf(";") > -1) {
217 current =
218 current.substring(0, current.indexOf(";"));
219 }
220 m_language.addElement(current);
221
222 }
223 }
224 } catch (UnsupportedOperationException e) {
225 }
226
227 // Initialize encoding
228 initEncoding();
229 }
230 }
231
232 /**
233 * Adds a link for the static export.
234 */
235 public void addLink(String link) {
236 m_links.add(link);
237 }
238
239 /**
240 * Returns all links that the template mechanism has registered.
241 */
242 public Vector getLinkVector() {
243 return m_links;
244 }
245
246 /**
247 * Adds a dependency.
248 *
249 * @param dependency. The rootpath of the resource.
250 */
251 public void addDependency(String rootName) {
252 m_dependencies.add(rootName);
253 }
254
255 /**
256 * Returns all dependencies the templatemechanism has registered.
257 */
258 public Vector getDependencies() {
259 return m_dependencies;
260 }
261
262 /**
263 * Returns the current folder object.
264 *
265 * @return the current folder object.
266 * @throws CmsException if operation was not successful.
267 */
268 public CmsFolder currentFolder() throws CmsException {
269 return (
270 m_rb.readFolder(
271 currentUser(),
272 currentProject(),
273 getSiteRoot(getFolderUri())
274 ));
275 }
276
277 /**
278 * Returns the current group of the current user.
279 *
280 * @return the current group of the current user.
281 */
282 public CmsGroup currentGroup() {
283 return (m_currentGroup);
284 }
285
286 /**
287 * Returns the current project of the current user.
288 *
289 * @return the current project of the current user.
290 */
291 public CmsProject currentProject() {
292 return m_currentProject;
293 }
294
295 /**
296 * Returns the current user object.
297 *
298 * @return the current user object.
299 */
300 public CmsUser currentUser() {
301 return (m_user);
302 }
303
304 /**
305 * Gets the name of the requested file without any path-information.
306 *
307 * @return the requested filename.
308 */
309 public String getFileUri() {
310 String uri = m_req.getRequestedResource();
311 uri = uri.substring(uri.lastIndexOf("/") + 1);
312 return uri;
313 }
314
315 /**
316 * Gets the name of the parent folder of the requested file
317 *
318 * @return the requested filename.
319 */
320 public String getFolderUri() {
321 return getUri().substring(0, getUri().lastIndexOf("/") + 1);
322 }
323
324 /**
325 * Gets the current request, if availaible.
326 *
327 * @return the current request, if availaible.
328 */
329 public I_CmsRequest getRequest() {
330 return (m_req);
331 }
332
333 /**
334 * Gets the current response, if availaible.
335 *
336 * @return the current response, if availaible.
337 */
338 public I_CmsResponse getResponse() {
339 return (m_resp);
340 }
341
342 /**
343 * Gets the Session for this request.<p>
344 *
345 * This method should be used instead of the originalRequest.getSession() method.
346 *
347 * @param value indicates, if a session should be created when a session for the particular client does not already exist.
348 * @return the CmsSession, or <code>null</code> if no session already exists and value was set to <code>false</code>
349 *
350 */
351 public I_CmsSession getSession(boolean value) {
352 HttpSession session =
353 ((HttpServletRequest) m_req.getOriginalRequest()).getSession(value);
354 if (session != null) {
355 return (I_CmsSession) new CmsSession(session);
356 } else {
357 return null;
358 }
359 }
360
361 /**
362 * Gets the uri for the requested resource.<p>
363 *
364 * For a http request, the name of the resource is extracted as follows:<br>
365 * <CODE>http://{servername}/{servletpath}/{path to the cms resource}</CODE><br>
366 * In the following example:<br>
367 * <CODE>http://my.work.server/servlet/opencms/system/def/explorer</CODE><br>
368 * the requested resource is <CODE>/system/def/explorer</CODE>.
369 *
370 * @return the path to the requested resource.
371 */
372 public String getUri() {
373 if (m_uri != null) return m_uri;
374 if( m_req != null ) {
375 return( m_req.getRequestedResource() );
376 } else {
377 return (C_ROOT);
378 }
379 }
380
381 /**
382 * Set the value that is returned by getUri()
383 * to the provided String.<p>
384 *
385 * This is required in a context where
386 * a cascade of included XMLTemplates are combined with JSP or other
387 * Templates that use the ResourceLoader interface.
388 * You need to fake the URI because the ElementCache always
389 * uses cms.getRequestContext().getUri() even if you called
390 * CmsXmlLauncher.generateOutput() with a differnt file name.
391 *
392 * @param value The value to set the Uri to, must be a complete OpenCms path name like /system/workplace/stlye.css
393 * @since 5.0 beta 1
394 */
395 public void setUri(String value) {
396 m_uri = value;
397 }
398
399 /**
400 * Determines if the users is in the admin-group.
401 *
402 * @return <code>true</code> if the users current group is the admin-group; <code>false</code> otherwise.
403 * @throws CmsException if operation was not successful.
404 */
405 public boolean isAdmin() throws CmsException {
406 return (m_rb.isAdmin(m_user, m_currentProject));
407 }
408
409 /**
410 * Determines if the users current group is the projectmanager-group.<p>
411 *
412 * All projectmanagers can create new projects, or close their own projects.
413 *
414 * @return <code>true</code> if the users current group is the projectleader-group; <code>false</code> otherwise.
415 * @throws CmsException if operation was not successful.
416 */
417 public boolean isProjectManager() throws CmsException {
418 return (m_rb.isProjectManager(m_user, m_currentProject));
419 }
420
421 /**
422 * Sets the current group of the current user.
423 *
424 * @param groupname the name of the group to be set as current group.
425 * @throws CmsException if operation was not successful.
426 */
427 public void setCurrentGroup(String groupname) throws CmsException {
428
429 // is the user in that group?
430 if (m_rb
431 .userInGroup(
432 m_user,
433 m_currentProject,
434 m_user.getName(),
435 groupname)) {
436 // Yes - set it to the current Group.
437 m_currentGroup =
438 m_rb.readGroup(m_user, m_currentProject, groupname);
439 } else {
440 // No - throw exception.
441 throw new CmsException(
442 "[" + this.getClass().getName() + "] " + groupname,
443 CmsException.C_NO_ACCESS);
444 }
445 }
446
447 /**
448 * Sets the current project for the user.
449 *
450 * @param projectId the id of the project to be set as current project.
451 * @throws CmsException if operation was not successful.
452 */
453 public CmsProject setCurrentProject(int projectId) throws CmsException {
454 CmsProject newProject =
455 m_rb.readProject(m_user, m_currentProject, projectId);
456 if (newProject != null) {
457 m_currentProject = newProject;
458 }
459 return (m_currentProject);
460 }
461
462 /**
463 * Get the current mode for HTTP streaming.
464 *
465 * @return <code>true</code> if template classes are allowed to stream the
466 * results to the response output stream theirselves, <code>false</code> otherwise.
467 */
468 public boolean isStreaming() {
469 return m_streaming;
470 }
471
472 /**
473 * Set the current mode for HTTP streaming.<p>
474 *
475 * Calling this method is only allowed, if the response output stream was
476 * not used before. Otherwise the streaming mode must not be changed.
477 *
478 * @param b <code>true</code> if template classes are allowed to stream the
479 * results to the response's output stream theirselves, <code>false</code> otherwise.
480 * @throws CmsException if the output stream was already used previously.
481 */
482 public void setStreaming(boolean b) throws CmsException {
483 if ((m_streaming != b) && getResponse().isOutputWritten()) {
484 throw new CmsException(
485 "[CmsRequestContext] Cannot switch streaming mode, if output stream is used previously.",
486 CmsException.C_STREAMING_ERROR);
487 }
488 m_streaming = b;
489 }
490
491 /**
492 * Get the current mode for element cache.
493 *
494 * @return <code>true</code> if element cache is active, <code>false</code> otherwise.
495 */
496 public boolean isElementCacheEnabled() {
497 return (m_elementCache != null);
498 }
499
500 /**
501 * Get the CmsElementCache object. This is the starting point for the element cache area.
502 * @return CmsElementCachee
503 */
504 public CmsElementCache getElementCache() {
505 return m_elementCache;
506 }
507
508 /**
509 * Get a Vector of all accepted languages for this request.
510 * Languages are coded in international shortcuts like "en" or "de".
511 * If the browser has sent special versions of languages (e.g. "de-ch" for Swiss-German)
512 * these extensions will be cut off.
513 * @return Vector of Strings with language codes or <code>null</code> if no request object is available.
514 */
515 public Vector getAcceptedLanguages() {
516 return m_language;
517 }
518
519 /**
520 * Returns the name of the current site root, e.g. /default/vfs
521 *
522 * @param resourcename
523 * @return String The resourcename with its site root
524 */
525 public String getSiteRoot(String resourcename) {
526 if (resourcename == null) return null;
527 if (resourcename.startsWith("///")) {
528 return m_directoryTranslator.translateResource(resourcename.substring(2));
529 } else if (resourcename.startsWith("//")) {
530 return m_directoryTranslator.translateResource(C_DEFAULT_SITE + resourcename.substring(1));
531 } else {
532 return m_directoryTranslator.translateResource(m_siteRoot + resourcename);
533 }
534 }
535
536 /**
537 * @return The directory name translator this context was initialized with
538 */
539 public CmsResourceTranslator getDirectoryTranslator() {
540 return m_directoryTranslator;
541 }
542
543 /**
544 * @return The file name translator this context was initialized with
545 */
546 public CmsResourceTranslator getFileTranslator() {
547 return m_fileTranslator;
548 }
549
550 /**
551 * Returns the site name, e.g. <code>/default</code>
552 *
553 * @return the site name, e.g. <code>/default</code>
554 */
555 public String getSiteName() {
556 return C_DEFAULT_SITE;
557 }
558
559 /**
560 * Returns the site root, e.g. <code>/default/vfs</code>
561 *
562 * @return the site root, e.g. <code>/default/vfs</code>
563 */
564 public String getSiteRoot() {
565 return m_siteRoot;
566 }
567
568 /**
569 * Sets the name of the current site root
570 * of the virtual file system
571 */
572 public void setContextTo(String name) {
573 m_siteRoot = C_DEFAULT_SITE + name;
574 }
575
576 /**
577 * Detects current content encoding to be used in HTTP response
578 * based on requested resource or session state.
579 */
580 public void initEncoding() {
581 try {
582 m_encoding = m_rb.readProperty(m_user, m_currentProject, getSiteRoot(m_req.getRequestedResource()), m_siteRoot, C_PROPERTY_CONTENT_ENCODING, true);
583 } catch (CmsException e) {
584 m_encoding = null;
585 }
586 if ((m_encoding != null) && ! "".equals(m_encoding)) {
587 // encoding was read from resource property
588 return;
589 } else if ((getUri().startsWith(I_CmsWpConstants.C_VFS_PATH_SYSTEM)) && (! (m_req instanceof CmsExportRequest))) {
590 // try to get encoding from session for special system folder only
591 if (A_OpenCms.C_LOGGING && A_OpenCms.isLogging(A_OpenCms.C_OPENCMS_DEBUG)) {
592 A_OpenCms.log(I_CmsLogChannels.C_OPENCMS_DEBUG,
593 "[" + getClass().getName() + "] can't get encoding property for resource "
594 + m_req.getRequestedResource() + ", trying to get it from session.");
595 }
596 I_CmsSession session = getSession(false);
597 if (session != null) {
598 m_encoding = (String)session.getValue(I_CmsConstants.C_SESSION_CONTENT_ENCODING);
599 }
600 }
601 if (m_encoding == null || "".equals(m_encoding)) {
602 // no encoding found - use default one
603 if (A_OpenCms.C_LOGGING && A_OpenCms.isLogging(A_OpenCms.C_OPENCMS_DEBUG)) {
604 A_OpenCms.log(I_CmsLogChannels.C_OPENCMS_DEBUG,
605 "[" + getClass().getName() + "] no encoding found - using default: " + A_OpenCms.getDefaultEncoding());
606 }
607 m_encoding = A_OpenCms.getDefaultEncoding();
608 }
609 }
610
611 /**
612 * Returns the current content encoding to be used in HTTP response
613 */
614 public String getEncoding() {
615 return m_encoding;
616 }
617
618 /**
619 * Sets the current content encoding to be used in HTTP response
620 */
621 public void setEncoding(String encoding) {
622 setEncoding(encoding, false);
623 }
624
625 /**
626 * Sets the current content encoding to be used in HTTP response
627 * and store it in session if it is available
628 */
629 public void setEncoding(String encoding, boolean storeInSession) {
630 m_encoding = encoding;
631 if (!storeInSession) {
632 return;
633 }
634 I_CmsSession session = getSession(false);
635 if (session != null) {
636 session.putValue(
637 I_CmsConstants.C_SESSION_CONTENT_ENCODING,
638 m_encoding);
639 }
640 }
641
642 /**
643 * Mark this request context as event controlled.<p>
644 *
645 * @param true if the request is event controlled, false otherwise
646 */
647 public void setEventControlled(boolean value) {
648 m_eventControlled = value;
649 }
650
651 /**
652 * Check if this request context is event controlled.<p>
653 *
654 * @return true if the request context is event controlled, false otherwise
655 */
656 public boolean isEventControlled() {
657 return m_eventControlled;
658 }
659
660 /**
661 * Mark this request context to update the session or not.<p>
662 *
663 * @param true if this request context will update the session, false otherwise
664 */
665 public void setUpdateSessionEnabled(boolean value) {
666 m_updateSession = value;
667 }
668
669 /**
670 * Check if this request context will update the session.<p>
671 *
672 * @return true if this request context will update the session, false otherwise
673 */
674 public boolean isUpdateSessionEnabled() {
675 return m_updateSession;
676 }
677
678 /**
679 * Gets the value of an attribute from the OpenCms request context attribute list.<p>
680 *
681 * @param attributeName the attribute name
682 * @return Object the attribute value, or <code>null</code> if the attribute was not found
683 */
684 public Object getAttribute(String attributeName) {
685 if (m_attributeMap == null) return null;
686 return m_attributeMap.get(attributeName);
687 }
688
689 /**
690 * Sets an attribute in the request context.<p>
691 *
692 * @param key the attribute name
693 * @param value the attribute value
694 */
695 public void setAttribute(String key, Object value) {
696 if (m_attributeMap == null) m_attributeMap = new HashMap();
697 m_attributeMap.put(key, value);
698 }
699 }