Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/opencms/launcher/A_CmsLauncher.java


1   /*
2   * File   : $Source: /usr/local/cvs/opencms/src/com/opencms/launcher/Attic/A_CmsLauncher.java,v $
3   * Date   : $Date: 2003/02/26 10:30:36 $
4   * Version: $Revision: 1.41 $
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  
30  package com.opencms.launcher;
31  
32  import com.opencms.boot.I_CmsLogChannels;
33  import com.opencms.core.A_OpenCms;
34  import com.opencms.core.CmsException;
35  import com.opencms.core.I_CmsConstants;
36  import com.opencms.core.I_CmsResponse;
37  import com.opencms.file.CmsFile;
38  import com.opencms.file.CmsObject;
39  import com.opencms.file.CmsRequestContext;
40  import com.opencms.template.A_CmsXmlContent;
41  import com.opencms.template.CmsRootTemplate;
42  import com.opencms.template.CmsTemplateClassManager;
43  import com.opencms.template.I_CmsTemplate;
44  
45  import java.io.IOException;
46  import java.io.OutputStream;
47  import java.util.Hashtable;
48  
49  /**
50   * Abstract OpenCms launcher class.
51   * <P>
52   * This class implements basic functionality for all OpenCms launchers.
53   * For each relevant file type (e.g. XML control files, plain text files,
54   * JavaScript files,...) a customized launcher has to be implemented.
55   * <P>
56   * Every extending class has to implement the abstract methods
57   * <UL>
58   * <LI>getLauncherId() to indicate the type of the launcher</LI>
59   * <LI>launch() to be called by initlaunch</LI>
60   * </UL>
61   * <P>
62   * The functionality of this class is
63   * <UL>
64   * <LI>provide a global cache for template class results</LI>
65   * <LI>receive the system's launcher call, do some relevant initial
66   * things and call the launch() method</LI>
67   * <LI>provide some utility methods</LI>
68   * </UL>
69   *
70   * @author Alexander Lucas
71   * @version $Revision: 1.41 $ $Date: 2003/02/26 10:30:36 $
72   */
73  abstract class A_CmsLauncher implements I_CmsLauncher,I_CmsLogChannels,I_CmsConstants {
74  
75      /** Boolean for additional debug output control */
76      private static final boolean C_DEBUG = false;
77  
78      /** Value of the filesystem counter, when the last template clear cache was done. */
79      private static long m_lastFsCounterTemplate = 0;
80  
81      /** Value of the filesystem counter, when the last XML file clear cache was done. */
82      private static long m_lastFsCounterFile = 0;
83  
84      /** The template cache that holds all cached templates */
85      protected static I_CmsTemplateCache m_templateCache = new CmsTemplateCache();
86  
87      /**
88       * Utility method used by the launcher implementation to give control
89       * to the CanonicalRoot.
90       * The CanonicalRoot will call the master template and return a byte array of the
91       * generated output.
92       *
93       * @param cms CmsObject Object for accessing system resources.
94       * @param templateClass Class that should generate the output of the master template.
95       * @param masterTemplate CmsFile Object with masterTemplate for the output.
96       * @param parameters Hashtable with all parameters for the template class.
97       * @return byte array with the generated output or null if there were errors.
98       * @throws CmsException
99       *
100      */
101     protected byte[] callCanonicalRoot(CmsObject cms, I_CmsTemplate templateClass, CmsFile masterTemplate, Hashtable parameters) throws CmsException {
102         try {
103             com.opencms.template.CmsRootTemplate root = (CmsRootTemplate)CmsTemplateClassManager.getClassInstance(cms, "com.opencms.template.CmsRootTemplate");
104             return root.getMasterTemplate(cms, templateClass, masterTemplate, m_templateCache, parameters);
105         }
106         catch(Exception e) {
107 
108             // There is no document we could show.
109             handleException(cms, e, "Received error while calling canonical root for requested file " + masterTemplate.getName() + ". ");
110         }
111         return null;
112     }
113 
114     /**
115      * Method for clearing this launchers template cache.
116      */
117     public void clearCache() {
118         m_templateCache.clearCache();
119         System.gc();
120     }
121 
122     /**
123      * Gets the name of the class in the form "[ClassName] "
124      * This can be used for error logging purposes.
125      * @return name of this class
126      */
127     protected String getClassName() {
128         String name = getClass().getName();
129         return "[" + name.substring(name.lastIndexOf(".") + 1) + "] ";
130     }
131 
132     /** Default constructor to create a new launcher */
133 
134     /*public A_CmsLauncher() {
135     if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && A_OpenCms.isLogging() ) {
136         A_OpenCms.log(C_OPENCMS_DEBUG, getClassName() + "Initialized successfully.");
137     }
138     }*/
139 
140     /**
141      * Gets the ID that indicates the type of the launcher.
142      * @return launcher ID
143      */
144     public abstract int getLauncherId();
145 
146     /**
147      * Gets a reference to the global template cache
148      * @return Template cache
149      */
150     public static I_CmsTemplateCache getTemplateCache() {
151         return m_templateCache;
152     }
153 
154     /**
155      * Calls the CmsClassManager to get an instance of the given template class.
156      * The returned object is checked to be an implementing class of the interface
157      * I_CmsTemplate.
158      * If the template cache of the template class is not yet setted, this will
159      * be done, too.
160      * @param cms CmsObject object for accessing system resources.
161      * @param classname Name of the requested template class.
162      * @return Instance of the template class.
163      * @throws CmsException.
164      */
165     protected I_CmsTemplate getTemplateClass(CmsObject cms, String classname) throws CmsException {
166         if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && A_OpenCms.isLogging() && C_DEBUG) {
167             A_OpenCms.log(C_OPENCMS_DEBUG, getClassName() + "Getting start template class " + classname + ". ");
168         }
169         Object o = CmsTemplateClassManager.getClassInstance(cms, classname);
170 
171         // Check, if the loaded class really is a OpenCms template class.
172 
173         // This is done be checking the implemented interface.
174         if(!(o instanceof I_CmsTemplate)) {
175             String errorMessage = "Class " + classname + " is no OpenCms template class.";
176             if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && A_OpenCms.isLogging() ) {
177                 A_OpenCms.log(C_OPENCMS_CRITICAL, "[CmsTemplateClassManager] " + errorMessage);
178             }
179             throw new CmsException(errorMessage, CmsException.C_XML_NO_TEMPLATE_CLASS);
180         }
181         I_CmsTemplate cmsTemplate = (I_CmsTemplate)o;
182         if(!cmsTemplate.isTemplateCacheSet()) {
183             cmsTemplate.setTemplateCache(m_templateCache);
184         }
185         return cmsTemplate;
186     }
187 
188     /**
189      * Utility method to handle any occurence of an execption.
190      * <P>
191      * If the Exception is NO CmsException (i.e. it was not detected previously)
192      * it will be written to the logfile.
193      * <P>
194      * If the current user is the anonymous user, no further execption will
195      * be thrown, but a server error will be sent
196      * (we want to prevent the user from seeing any exeptions).
197      * Otherwise a new Exception will be thrown.
198      *
199      * @param cms CmsObject Object for accessing system resources.
200      * @param e Exception that should be handled.
201      * @param errorText Error message that should be shown.
202      * @throws CmsException
203      */
204     public void handleException(CmsObject cms, Exception e, String errorText) throws CmsException {
205 
206         // Print out some error messages
207         if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && A_OpenCms.isLogging() ) {
208             A_OpenCms.log(C_OPENCMS_CRITICAL, getClassName() + errorText);
209             A_OpenCms.log(C_OPENCMS_CRITICAL, getClassName() + "--> Exception: " + com.opencms.util.Utils.getStackTrace(e));
210             A_OpenCms.log(C_OPENCMS_CRITICAL, getClassName() + "--> Cannot create output for this file. Must send error. Sorry.");
211         }
212 
213         // If the user is "Guest", we send an servlet error.
214 
215         // Otherwise we try to throw an exception.
216         CmsRequestContext reqContext = cms.getRequestContext();
217         if((!C_DEBUG) && cms.anonymousUser().equals(reqContext.currentUser())) {
218             throw new CmsException(errorText, CmsException.C_SERVICE_UNAVAILABLE, e);
219         }
220         else {
221             if(e instanceof CmsException) {
222                 throw (CmsException)e;
223             }
224             else {
225                 throw new CmsException(errorText, CmsException.C_LAUNCH_ERROR, e);
226             }
227         }
228     }
229 
230     /**
231      * Start method called by the OpenCms system to show a resource.
232      * <P>
233      * In this method initial values valid for all launchers can be set
234      * and the _clearcache parameter is checked.
235      * After this the abstract method launch(...) is called to
236      * invoke the customized part of the launcher.
237      *
238      * @param cms CmsObject Object for accessing system resources.
239      * @param file CmsFile Object with the selected resource to be shown.
240      * @param startTemplateClass Name of the template class to start with.
241      * @param openCms a instance of A_OpenCms for redirect-needs
242      * @throws CmsException
243      */
244     public void initlaunch(CmsObject cms, CmsFile file, String startTemplateClass, A_OpenCms openCms) throws CmsException {
245 
246         // First some debugging output.
247         if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && A_OpenCms.isLogging() && C_DEBUG ) {
248             A_OpenCms.log(C_OPENCMS_CRITICAL, getClassName() + "Launcher started for " + file.getName());
249         }
250 
251         // Check all values to be valid
252         String errorMessage = null;
253         if(file == null) {
254             errorMessage = "Got \"null\" CmsFile object. :-(";
255         }
256         if(cms == null) {
257             errorMessage = "Actual cms object missing";
258         }
259         if(errorMessage != null) {
260             if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && A_OpenCms.isLogging() ) {
261                 A_OpenCms.log(C_OPENCMS_CRITICAL, getClassName() + errorMessage);
262             }
263             throw new CmsException(errorMessage, CmsException.C_LAUNCH_ERROR);
264         }
265 
266         // Check the clearcache parameter
267         String clearcache = cms.getRequestContext().getRequest().getParameter("_clearcache");
268         
269         // Clear launcher caches if this is required
270         clearLauncherCache(cms, 
271             ((clearcache != null) && ("all".equals(clearcache) || "file".equals(clearcache))),
272             ((clearcache != null) && ("all".equals(clearcache) || "template".equals(clearcache))));
273         
274         launch(cms, file, startTemplateClass, openCms);
275     }
276     
277     /**
278      * Compatibility method to ensure the legacy cache command line parameters
279      * are still supported.<p>
280      * 
281      * @param cms an initialized CmsObject
282      * @param clearClasses if true, CmsTemplateClassManager is cleared
283      * @param clearFiles if true, A_CmsXmlContent cache is cleared
284      * @param clearTemplates if true, internal template cache is cleared.
285      */
286     private static void clearLauncherCache(CmsObject cms, boolean clearFiles, boolean clearTemplates) {
287         long currentFsCounter = cms.getFileSystemChanges();
288         if(clearFiles || (currentFsCounter > m_lastFsCounterFile)) {
289             A_CmsXmlContent.clearFileCache();
290             m_lastFsCounterFile = currentFsCounter;
291         }
292         if(clearTemplates || (currentFsCounter > m_lastFsCounterTemplate)) {
293             m_templateCache.clearCache();
294             m_lastFsCounterTemplate = currentFsCounter;
295         }        
296     }
297 
298     /**
299      * Clear the XML template cache that is maintained in the launcher.
300      * To use this method, call it on one of the classes that extend 
301      * A_CmsLauncher (e.g. com.opencms.launcher.CmsXmlLauncher.clearLauncherCache()).
302      * @param cms an initialized CmsObject
303      */  
304     public static void clearLauncherCache(CmsObject cms) {
305         clearLauncherCache(cms, true, true);
306     }
307     
308 
309     /**
310      * Unitary method to start generating the output.
311      * Every launcher has to implement this method.
312      * In it possibly the selected file will be analyzed, and the
313      * Canonical Root will be called with the appropriate
314      * template class, template file and parameters. At least the
315      * canonical root's output must be written to the HttpServletResponse.
316      *
317      * @param cms CmsObject Object for accessing system resources
318      * @param file CmsFile Object with the selected resource to be shown
319      * @param startTemplateClass Name of the template class to start with.
320      * @param openCms a instance of A_OpenCms for redirect-needs
321      * @throws CmsException
322      */
323     protected abstract void launch(CmsObject cms, CmsFile file, String startTemplateClass, A_OpenCms openCms) throws CmsException;
324 
325     /**
326      * Writes a given byte array to the HttpServletRespose output stream.
327      * @param result byte array that should be written.
328      * @param mimeType MIME type that should be set for the output.
329      * @throws CmsException
330      */
331     protected void writeBytesToResponse(CmsObject cms, byte[] result) throws CmsException {
332         try {
333             I_CmsResponse resp = cms.getRequestContext().getResponse();
334             if((!cms.getRequestContext().isStreaming()) && result != null && !resp.isRedirected()) {
335                 // Only write any output to the response output stream if
336                 // the current request is neither redirected nor streamed.
337                 OutputStream out = resp.getOutputStream();
338 
339                 resp.setContentLength(result.length);
340                 resp.setHeader("Connection", "keep-alive");
341                 out.write(result);
342                 out.close();
343             }
344         }
345         catch(IOException ioe) {
346             if(C_LOGGING && A_OpenCms.isLogging(C_OPENCMS_DEBUG) ) {
347                 A_OpenCms.log(C_OPENCMS_DEBUG, getClassName() + "IO error while writing to response stream for " + cms.getRequestContext().getFileUri());
348                 A_OpenCms.log(C_OPENCMS_DEBUG, getClassName() + ioe);
349             }
350         }
351         catch(Exception e) {
352             String errorMessage = "Cannot write output to HTTP response stream";
353             handleException(cms, e, errorMessage);
354         }
355     }
356 
357     /**
358      * Sets the currently running OpenCms instance.
359      */
360     public void setOpenCms(A_OpenCms openCms) {
361         // normally we don't need the instance - ignoring
362         // if a launcher uses this, it should overload this method
363     }
364 }