Source code: com/opencms/launcher/CmsXmlLauncher.java
1 /*
2 * File : $Source: /usr/local/cvs/opencms/src/com/opencms/launcher/Attic/CmsXmlLauncher.java,v $
3 * Date : $Date: 2003/02/26 10:30:36 $
4 * Version: $Revision: 1.44 $
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.launcher;
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.I_CmsConstants;
35 import com.opencms.core.I_CmsRequest;
36 import com.opencms.file.CmsFile;
37 import com.opencms.file.CmsObject;
38 import com.opencms.template.CmsXmlControlFile;
39 import com.opencms.template.I_CmsTemplate;
40 import com.opencms.template.I_CmsXmlTemplate;
41 import com.opencms.template.cache.CmsElementCache;
42 import com.opencms.template.cache.CmsElementDefinition;
43 import com.opencms.template.cache.CmsElementDefinitionCollection;
44 import com.opencms.template.cache.CmsElementDescriptor;
45 import com.opencms.template.cache.CmsUri;
46 import com.opencms.template.cache.CmsUriDescriptor;
47 import com.opencms.template.cache.CmsUriLocator;
48 import com.opencms.util.Utils;
49
50 import java.util.Enumeration;
51 import java.util.Hashtable;
52
53 import javax.servlet.http.HttpServletRequest;
54
55 /**
56 * OpenCms launcher class for XML templates.<p>
57 *
58 * This can be used generating output for XML body files using XML template and
59 * subtemplate technology.<p>
60 *
61 * The selected body should define a start template class using <BR> <CODE>
62 * <PAGE><BR>
63 * <CLASS>...</CLASS><BR>
64 * </PAGE></CODE><p>
65 *
66 * If no start template is defined, the class given by the parameters
67 * will be used.
68 * If even this is not defined, CmsXmlTemplate will
69 * be used to create output.<p>
70 *
71 * @author Alexander Lucas
72 * @version $Revision: 1.44 $ $Date: 2003/02/26 10:30:36 $
73 */
74 public class CmsXmlLauncher extends A_CmsLauncher implements I_CmsLogChannels, I_CmsConstants {
75
76 /** Magic elemet replace name */
77 public static final String C_ELEMENT_REPLACE = "_CMS_ELEMENTREPLACE";
78
79 /**
80 * Starts generating the output.
81 * Calls the canonical root with the appropriate template class.
82 *
83 * @param cms CmsObject Object for accessing system resources
84 * @param file CmsFile Object with the selected resource to be shown
85 * @param startTemplateClass Name of the template class to start with.
86 * @throws CmsException
87 */
88 protected byte[] generateOutput(CmsObject cms, CmsFile file, String startTemplateClass, I_CmsRequest req) throws CmsException {
89 byte[] output = null;
90
91 // Hashtable for collecting all parameters.
92 Hashtable newParameters = new Hashtable();
93
94 // Parameters used for element cache
95 boolean elementCacheEnabled = cms.getRequestContext().isElementCacheEnabled();
96 CmsElementCache elementCache = null;
97 String uri = cms.getRequestContext().getUri();
98 CmsUriDescriptor uriDesc = null;
99 CmsUriLocator uriLoc = null;
100 CmsUri cmsUri = null;
101
102 String templateClass = null;
103 String templateName = null;
104 CmsXmlControlFile doc = null;
105
106 if(elementCacheEnabled) {
107 // Get the global element cache object
108 elementCache = cms.getRequestContext().getElementCache();
109
110 // Prepare URI Locator
111 uriDesc = new CmsUriDescriptor(uri);
112 uriLoc = elementCache.getUriLocator();
113 cmsUri = uriLoc.get(uriDesc);
114 }
115
116 // check if printversion is requested
117 String replace = req.getParameter(C_ELEMENT_REPLACE);
118 boolean elementreplace = false;
119 CmsElementDefinition replaceDef = null;
120 if(replace != null){
121 int index = replace.indexOf(":");
122 if(index != -1){
123 elementreplace = true;
124 cmsUri = null;
125 replaceDef = new CmsElementDefinition(replace.substring(0,index),
126 "com.opencms.template.CmsXmlTemplate",
127 replace.substring(index+1), null, new Hashtable());
128 }
129 }
130
131 if(cmsUri == null || !elementCacheEnabled) {
132 // Entry point to page file analysis.
133 // For performance reasons this should only be done if the element
134 // cache is not activated or if it's activated but no URI object could be found.
135
136 // Parse the page file
137 try {
138 doc = new CmsXmlControlFile(cms, file);
139 }
140 catch(Exception e) {
141 // there was an error while parsing the document.
142 // No chance to go on here.
143 handleException(cms, e, "There was an error while parsing XML page file " + file.getAbsolutePath());
144 return "".getBytes();
145 }
146
147 if (! elementCacheEnabled && (replaceDef != null)) {
148 // Required to enable element replacement if element cache is disabled
149 doc.setElementClass(replaceDef.getName(), replaceDef.getClassName());
150 doc.setElementTemplate(replaceDef.getName(), replaceDef.getTemplateName());
151 }
152
153 // Get the names of the master template and the template class from
154 // the parsed page file. Fall back to default value, if template class
155 // is not defined
156 templateClass = doc.getTemplateClass();
157 if(templateClass == null || "".equals(templateClass)) {
158 templateClass = startTemplateClass;
159 }
160 if(templateClass == null || "".equals(templateClass)) {
161 templateClass = "com.opencms.template.CmsXmlTemplate";
162 }
163 templateName = doc.getMasterTemplate();
164 if(templateName != null && !"".equals(templateName)){
165 templateName = Utils.mergeAbsolutePath(file.getAbsolutePath(), templateName);
166 }
167
168 // Previously, the template class was loaded here.
169 // We avoid doing this so early, since in element cache mode the template
170 // class is not needed here.
171
172 // Now look for parameters in the page file...
173 // ... first the params of the master template...
174 Enumeration masterTemplateParams = doc.getParameterNames();
175 while(masterTemplateParams.hasMoreElements()) {
176 String paramName = (String)masterTemplateParams.nextElement();
177 String paramValue = doc.getParameter(paramName);
178 newParameters.put(C_ROOT_TEMPLATE_NAME + "." + paramName, paramValue);
179 }
180
181 // ... and now the params of all subtemplates
182 Enumeration elementDefinitions = doc.getElementDefinitions();
183 while(elementDefinitions.hasMoreElements()) {
184 String elementName = (String)elementDefinitions.nextElement();
185 if(doc.isElementClassDefined(elementName)) {
186 newParameters.put(elementName + "._CLASS_", doc.getElementClass(elementName));
187 }
188 if(doc.isElementTemplateDefined(elementName)) {
189 // need to check for the body template here so that non-XMLTemplate templates
190 // like JSPs know where to find the body defined in the XMLTemplate
191 String template = doc.getElementTemplate(elementName);
192 if (I_CmsConstants.C_XML_BODY_ELEMENT.equalsIgnoreCase(elementName)) {
193 // found body element
194 if (template != null) {
195 cms.getRequestContext().setAttribute(I_CmsConstants.C_XML_BODY_ELEMENT, template);
196 }
197 }
198 newParameters.put(elementName + "._TEMPLATE_", template);
199 }
200 if(doc.isElementTemplSelectorDefined(elementName)) {
201 newParameters.put(elementName + "._TEMPLATESELECTOR_", doc.getElementTemplSelector(elementName));
202 }
203 Enumeration parameters = doc.getElementParameterNames(elementName);
204 while(parameters.hasMoreElements()) {
205 String paramName = (String)parameters.nextElement();
206 String paramValue = doc.getElementParameter(elementName, paramName);
207 if(paramValue != null) {
208 newParameters.put(elementName + "." + paramName, paramValue);
209 }
210 else {
211 if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && A_OpenCms.isLogging() ) {
212 A_OpenCms.log(C_OPENCMS_INFO, getClassName() + "Empty parameter \"" + paramName + "\" found.");
213 }
214 }
215 }
216 }
217 }
218
219 // URL parameters ary really dynamic.
220 // We cannot store them in an element cache.
221 // Therefore these parameters must be collected in ANY case!
222
223 String datafor = req.getParameter("datafor");
224 if(datafor == null) {
225 datafor = "";
226 } else {
227 if(!"".equals(datafor)) {
228 datafor = datafor + ".";
229 }
230 }
231 Enumeration urlParameterNames = req.getParameterNames();
232 while(urlParameterNames.hasMoreElements()) {
233 String pname = (String)urlParameterNames.nextElement();
234 String paramValue = req.getParameter(pname);
235 if(paramValue != null) {
236 if((!"datafor".equals(pname)) && (!"_clearcache".equals(pname))) {
237 newParameters.put(datafor + pname, paramValue);
238 }
239 }else {
240 if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && A_OpenCms.isLogging() ) {
241 A_OpenCms.log(C_OPENCMS_INFO, getClassName() + "Empty URL parameter \"" + pname + "\" found.");
242 }
243 }
244 }
245
246 if(elementCacheEnabled && cmsUri == null) {
247 // ---- element cache stuff --------
248 // No URI could be found in cache.
249 // So create a new URI object with a start element and store it using the UriLocator
250 CmsElementDescriptor elemDesc = new CmsElementDescriptor(templateClass, templateName);
251 CmsElementDefinitionCollection eldefs = doc.getElementDefinitionCollection();
252 if(elementreplace){
253 // we cant cach this
254 eldefs.add(replaceDef);
255 cmsUri = new CmsUri(elemDesc, cms.getReadingpermittedGroup(
256 cms.getRequestContext().currentProject().getId(),
257 templateName), eldefs, Utils.isHttpsResource(cms, file));
258 }else{
259 cmsUri = new CmsUri(elemDesc, cms.getReadingpermittedGroup(
260 cms.getRequestContext().currentProject().getId(),
261 templateName), eldefs, Utils.isHttpsResource(cms, file));
262 elementCache.getUriLocator().put(uriDesc, cmsUri);
263 }
264 }
265
266 if(elementCacheEnabled) {
267 // lets check if ssl is active
268 if(cms.getMode() == C_MODUS_ONLINE){
269 String scheme = ((HttpServletRequest)cms.getRequestContext().getRequest().getOriginalRequest()).getScheme();
270 boolean httpsReq = "https".equalsIgnoreCase(scheme);
271 if(cmsUri.isHttpsResource() != httpsReq){
272 if(httpsReq){
273 //throw new CmsException(" "+file.getAbsolutePath()+" needs a http request", CmsException.C_HTTPS_PAGE_ERROR);
274 }else if(CmsObject.getStaticExportProperties().isStaticExportEnabled()
275 || "false_ssl".equals(CmsObject.getStaticExportProperties().getStaticExportEnabledValue())){
276 // check if static export is enabled and value is not false_ssl
277 throw new CmsException(" "+file.getAbsolutePath()+" needs a https request", CmsException.C_HTTPS_REQUEST_ERROR);
278 }
279 }
280 }
281 // now lets get the output
282 if(elementreplace){
283 output = cmsUri.callCanonicalRoot(elementCache, cms, newParameters);
284 }else{
285 output = elementCache.callCanonicalRoot(cms, newParameters);
286 }
287 } else {
288 // ----- traditional stuff ------
289 // Element cache is deactivated. So let's go on as usual.
290 try {
291 CmsFile masterTemplate = loadMasterTemplateFile(cms, templateName, doc);
292 I_CmsTemplate tmpl = getTemplateClass(cms, templateClass);
293 if(!(tmpl instanceof I_CmsXmlTemplate)) {
294 String errorMessage = "Error in " + file.getAbsolutePath() + ": " + templateClass + " is not a XML template class.";
295 if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && A_OpenCms.isLogging() ) {
296 A_OpenCms.log(C_OPENCMS_CRITICAL, getClassName() + errorMessage);
297 }
298 throw new CmsException(errorMessage, CmsException.C_XML_WRONG_TEMPLATE_CLASS);
299 }
300 output = callCanonicalRoot(cms, (I_CmsTemplate)tmpl, masterTemplate, newParameters);
301 }
302 catch(CmsException e) {
303 if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && A_OpenCms.isLogging() ) {
304 A_OpenCms.log(C_OPENCMS_INFO, "[CmsXmlLauncher] There were exceptions while generating output for " + file.getAbsolutePath());
305 A_OpenCms.log(C_OPENCMS_INFO, "[CmsXmlLauncher] Clearing template file cache for this file.");
306 }
307 doc.removeFromFileCache();
308 throw e;
309 }
310 }
311 return output;
312 }
313
314 /**
315 * Gets the ID that indicates the type of the launcher.
316 * @return launcher ID
317 */
318 public int getLauncherId() {
319 return C_TYPE_XML;
320 }
321
322 /**
323 * Unitary method to start generating the output.
324 * Every launcher has to implement this method.
325 * In it possibly the selected file will be analyzed, and the
326 * Canonical Root will be called with the appropriate
327 * template class, template file and parameters. At least the
328 * canonical root's output must be written to the HttpServletResponse.
329 *
330 * @param cms CmsObject Object for accessing system resources
331 * @param file CmsFile Object with the selected resource to be shown
332 * @param startTemplateClass Name of the template class to start with.
333 * @param openCms a instance of A_OpenCms for redirect-needs
334 * @throws CmsException
335 */
336 protected void launch(CmsObject cms, CmsFile file, String startTemplateClass, A_OpenCms openCms) throws CmsException {
337
338 // get the CmsRequest
339 I_CmsRequest req = cms.getRequestContext().getRequest();
340 byte[] result = null;
341 result = generateOutput(cms, file, startTemplateClass, req);
342 if(result != null) {
343 writeBytesToResponse(cms, result);
344 }
345 }
346
347 /**
348 * Internal utility method for checking and loading a given template file.
349 * @param cms CmsObject for accessing system resources.
350 * @param templateName Name of the requestet template file.
351 * @param doc CmsXmlControlFile object containig the parsed body file.
352 * @return CmsFile object of the requested template file.
353 * @throws CmsException
354 */
355 private CmsFile loadMasterTemplateFile(CmsObject cms, String templateName, com.opencms.template.CmsXmlControlFile doc) throws CmsException {
356 CmsFile masterTemplate = null;
357 try {
358 masterTemplate = cms.readFile(templateName);
359 }
360 catch(Exception e) {
361 handleException(cms, e, "Cannot load master template " + templateName + ". ");
362 doc.removeFromFileCache();
363 }
364 return masterTemplate;
365 }
366 }