001: /*
002: * Copyright (c) 2001 - 2005 ivata limited.
003: * All rights reserved.
004: * -----------------------------------------------------------------------------
005: * ivata masks may be redistributed under the GNU General Public
006: * License as published by the Free Software Foundation;
007: * version 2 of the License.
008: *
009: * These programs are free software; you can redistribute them and/or
010: * modify them under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; version 2 of the License.
012: *
013: * These programs are distributed in the hope that they will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: *
017: * See the GNU General Public License in the file LICENSE.txt for more
018: * details.
019: *
020: * If you would like a copy of the GNU General Public License write to
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place - Suite 330
024: * Boston, MA 02111-1307, USA.
025: *
026: *
027: * To arrange commercial support and licensing, contact ivata at
028: * http://www.ivata.com/contact.jsp
029: * -----------------------------------------------------------------------------
030: * $Log: GenerateCSS.java,v $
031: * Revision 1.9 2005/10/12 18:35:57 colinmacleod
032: * Standardized format of Logger declaration - to make it easier to find instances
033: * which are not both static and final.
034: *
035: * Revision 1.8 2005/10/11 18:52:08 colinmacleod
036: * Fixed some checkstyle and javadoc issues.
037: *
038: * Revision 1.7 2005/10/03 10:17:25 colinmacleod
039: * Fixed some style and javadoc issues.
040: *
041: * Revision 1.6 2005/10/02 14:06:34 colinmacleod
042: * Added/improved log4j logging.
043: *
044: * Revision 1.5 2005/09/14 13:24:51 colinmacleod
045: * Added serialVersionUID.
046: * Added handling for /shared path.
047: *
048: * Revision 1.4 2005/04/28 18:23:35 colinmacleod
049: * Added server/contextPath rewriting.
050: *
051: * Revision 1.3 2005/04/09 18:04:21 colinmacleod
052: * Changed copyright text to GPL v2 explicitly.
053: *
054: * Revision 1.2 2005/03/10 11:05:27 colinmacleod
055: * Added checking for empty file array.
056: *
057: * Revision 1.1 2005/01/19 13:00:49 colinmacleod
058: * Moved from ivata groupware.
059: *
060: * Revision 1.2 2004/11/03 16:10:11 colinmacleod
061: * Changed todo comments to TODO: all caps.
062: *
063: * Revision 1.1 2004/09/30 15:16:02 colinmacleod
064: * Split off addressbook elements into security subproject.
065: *
066: * Revision 1.3 2004/03/21 21:16:08 colinmacleod
067: * Shortened name to ivata op.
068: *
069: * Revision 1.2 2004/02/01 22:00:33 colinmacleod
070: * Added full names to author tags
071: *
072: * Revision 1.1.1.1 2004/01/27 20:57:56 colinmacleod
073: * Moved ivata openportal to SourceForge..
074: *
075: * Revision 1.1.1.1 2003/10/13 20:50:09 colin
076: * Restructured portal into subprojects
077: *
078: * Revision 1.2 2003/09/08 06:12:14 peter
079: * added a use of org.apache.commons.beanutils.BeanUtils to include it as a
080: * class - should be removed in the future
081: *
082: * Revision 1.1 2003/02/24 19:33:33 colin
083: * moved to JSP
084: *
085: * Revision 1.5 2003/02/04 17:43:50 colin
086: * copyright notice
087: *
088: * Revision 1.4 2002/07/01 08:08:38 colin
089: * trapped new theme parse exception
090: *
091: * Revision 1.3 2002/06/21 12:38:52 colin
092: * restructured com.ivata.groupware.web
093: *
094: * Revision 1.2 2002/06/13 11:22:04 colin
095: * first version with rose model integration.
096: *
097: * Revision 1.1 2002/04/30 15:21:36 colin
098: * first functional version of the mail subproject in JBuilder
099: * -----------------------------------------------------------------------------
100: */
101: package com.ivata.mask.web.servlet;
102:
103: import java.io.BufferedReader;
104: import java.io.BufferedWriter;
105: import java.io.File;
106: import java.io.FileReader;
107: import java.io.FileWriter;
108: import java.io.IOException;
109:
110: import javax.servlet.http.HttpServlet;
111: import javax.servlet.http.HttpServletRequest;
112: import javax.servlet.http.HttpServletResponse;
113:
114: import org.apache.log4j.Logger;
115:
116: import com.ivata.mask.web.RewriteHandling;
117: import com.ivata.mask.web.theme.Theme;
118: import com.ivata.mask.web.theme.ThemeParseException;
119:
120: /**
121: * <p>This servlet generates the CSS files by evaluating properties. This is
122: * done to evaluate the context path at the moment, and a theme object is used
123: * to do the parsing. This replaces all instances of PROPERTY(pathContext) in
124: * the template files, just as per the theme.</p>
125: *
126: * <p>All of the templates in the /style/template directory are parsed, with the
127: * results being written in the /style directory.</p>
128: *
129: * @since 2002-04-29
130: * @author Colin MacLeod
131: * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
132: * @version $Revision: 1.9 $
133: * @seee Theme
134: */
135: public class GenerateCSS extends HttpServlet {
136: /**
137: * Serialization version (for <code>Serializable</code> interface).
138: */
139: private static final long serialVersionUID = 1L;
140: /**
141: * This is the path where all the style-sheets are stored.
142: */
143: public static final String CSS_PATH = "/style";
144: /**
145: * This array contains all web paths we will search for style sheets. At the
146: * moment, we check both root and shared paths for css styles - if the
147: * pages are imported automatically in projects, you can put them all in a
148: * /shared path to separate them from the sheets for this project - see
149: * ivata cms)
150: */
151: public static final String[] CSS_ROOT_PATHS = new String[] {
152: // note: these are processed in order - you want the most important
153: // last so that it overrides the others.
154: "/shared", "" };
155:
156: /**
157: * This is the path where all the templates style-sheets (the ones to be
158: * parsed and converted) are stored.
159: */
160: public static final String CSS_TEMPLATE_PATH = "/style/template";
161:
162: /**
163: * Logger for this class.
164: */
165: private static final Logger logger = Logger
166: .getLogger(GenerateCSS.class);
167:
168: /**
169: * If components from ivata groupware are being re-used, this is the
170: * directory where they are shared. If you change this, be sure to change
171: * CSS_ROOT_PATHS too.
172: */
173: public static final String SHARED_PATH = "/shared";
174:
175: /**
176: * Clean up resources. Does nothing in this servlet.
177: */
178: public void destroy() {
179: if (logger.isDebugEnabled()) {
180: logger.debug("destroy() - start");
181: }
182:
183: if (logger.isDebugEnabled()) {
184: logger.debug("destroy() - end");
185: }
186: }
187:
188: /**
189: * Process the HTTP Get request.
190: *
191: * @param request servlet request currently being processed.
192: * @param response response we are writing.
193: * @throws IOException if the style sheet files cannot be accessed or
194: * written.
195: *
196: * @throws IOException if the stylesheet files cannot be read or written.
197: */
198: public void doGet(final HttpServletRequest request,
199: final HttpServletResponse response) throws IOException {
200: logger.info("START CSS Generation Sequence.");
201: Theme theme = new Theme("css");
202:
203: String pathContext = RewriteHandling.getContextPath(request);
204: logger.info("pathContext: '" + pathContext + "'");
205: theme.setDefaultProperty("pathContext", pathContext);
206:
207: // See if we are sharing components from ivata groupware in another
208: // project.
209: // For now, it looks to see if there is a directory called 'shared'
210: // if so, it assumes the project is being shared, and sets a theme
211: // property to this directory. This means any instances of
212: // PROPERTY(sharedPath) in the stylesheet are replaced.
213: // You might want to change this to read a setting or an environment
214: // entry, and use that path.
215: File sharedDirectory = new File(getServletContext()
216: .getRealPath(SHARED_PATH));
217: if (sharedDirectory.exists() && sharedDirectory.isDirectory()) {
218: theme.setDefaultProperty("sharedPath", SHARED_PATH);
219: logger.info("Using CSS Generation shared path '"
220: + SHARED_PATH + "'.");
221: } else {
222: theme.setDefaultProperty("sharedPath", "");
223: }
224:
225: parseDirectory(".", theme);
226: logger.info("END CSS Generation Sequence.");
227: }
228:
229: /**
230: * Initialization. This method does nothing, for this servlet.
231: */
232: public void init() {
233: if (logger.isDebugEnabled()) {
234: logger.debug("init() - start");
235: }
236:
237: if (logger.isDebugEnabled()) {
238: logger.debug("init() - end");
239: }
240: }
241:
242: /**
243: * Recursive helper. This method goes thro' all the directories under
244: * /style/template and parses the contents of each.
245: *
246: * @param directoryPathParam directory to recurse through.
247: * @param theme used to parse out all the properties in the style sheet.
248: * @throws IOException if the style sheets cannot be read or written.
249: */
250: private void parseDirectory(final String directoryPathParam,
251: final Theme theme) throws IOException {
252: if (logger.isDebugEnabled()) {
253: logger.debug("parseDirectory(String directoryPathParam = "
254: + directoryPathParam + ", Theme theme = " + theme
255: + ") - start");
256: }
257:
258: // check both root and shared paths for css styles (if the
259: // pages are imported automatically in projects, you can put
260: // them all in a /shared path to separate them from the
261: // sheets for this project - see ivata cms)
262: for (int rootPathIndex = 0; rootPathIndex < GenerateCSS.CSS_ROOT_PATHS.length; ++rootPathIndex) {
263: // if the root path doesn't exist, skip it
264: File rootDirectory = new File(getServletContext()
265: .getRealPath(
266: GenerateCSS.CSS_ROOT_PATHS[rootPathIndex]));
267: if (!rootDirectory.exists()) {
268: logger.debug("Root CSS directory '"
269: + rootDirectory.getAbsolutePath()
270: + "' not found.");
271: continue;
272: }
273: if (!rootDirectory.isDirectory()) {
274: logger.error("Path for Root CSS directory '"
275: + rootDirectory.getAbsolutePath()
276: + "' is NOT A DIRECTORY.");
277: continue;
278: }
279:
280: File cSSTemplateDirectory = new File(getServletContext()
281: .getRealPath(
282: GenerateCSS.CSS_ROOT_PATHS[rootPathIndex]
283: + CSS_TEMPLATE_PATH + "/"
284: + directoryPathParam));
285: File[] cSSFileArray = cSSTemplateDirectory.listFiles();
286: if (cSSFileArray == null) {
287: logger
288: .warn("No CSS files found to process at '"
289: + cSSTemplateDirectory
290: .getAbsolutePath() + "'.");
291: return;
292: }
293:
294: for (int nFile = 0; nFile < cSSFileArray.length; ++nFile) {
295: // if this is a directory, then parse it as well
296: if (cSSFileArray[nFile].isDirectory()) {
297: parseDirectory(
298: GenerateCSS.CSS_ROOT_PATHS[rootPathIndex]
299: + directoryPathParam + "/"
300: + cSSFileArray[nFile].getName(),
301: theme);
302: } else {
303: // create the relative directory if it doesn't exist, and
304: // then convert the input file to this path
305: String inputFile = cSSFileArray[nFile]
306: .getAbsolutePath();
307: File directory = new File(
308: getServletContext()
309: .getRealPath(
310: GenerateCSS.CSS_ROOT_PATHS[rootPathIndex]
311: + CSS_PATH
312: + "/"
313: + directoryPathParam));
314: directory.mkdirs();
315: String outputFile = directory.getAbsolutePath()
316: + "/" + cSSFileArray[nFile].getName();
317:
318: logger.info("Converting " + inputFile + " to "
319: + outputFile);
320: BufferedReader reader = new BufferedReader(
321: new FileReader(inputFile));
322: BufferedWriter writer = new BufferedWriter(
323: new FileWriter(outputFile));
324: String line;
325:
326: // go through the entire input file, a line at a time
327: while ((line = reader.readLine()) != null) {
328: // parse the input against the default properties only
329: // and write them out again
330: //Properties properties = new Properties( );
331: //properties.setProperty( "pathContext",
332: //request.getContextPath( ) );
333: try {
334: writer.write(theme.parse(line, null));
335: } catch (ThemeParseException e) {
336: logger.error(
337: "parseDirectory(String, Theme)", e);
338:
339: e.printStackTrace(System.err);
340: }
341: writer.newLine();
342: }
343: writer.flush();
344: writer.close();
345: }
346: }
347: }
348:
349: if (logger.isDebugEnabled()) {
350: logger.debug("parseDirectory(String, Theme) - end");
351: }
352: }
353: }
|