001: /* *****************************************************************************
002: * CanvasCompiler.java
003: * ****************************************************************************/
004:
005: /* J_LZ_COPYRIGHT_BEGIN *******************************************************
006: * Copyright 2001-2007 Laszlo Systems, Inc. All Rights Reserved. *
007: * Use is subject to license terms. *
008: * J_LZ_COPYRIGHT_END *********************************************************/
009:
010: package org.openlaszlo.compiler;
011:
012: import java.io.*;
013: import java.util.*;
014:
015: import org.openlaszlo.compiler.ViewCompiler.*;
016: import org.openlaszlo.compiler.ViewSchema.ColorFormatException;
017: import org.openlaszlo.sc.*;
018: import org.openlaszlo.server.*;
019: import org.openlaszlo.utils.*;
020: import org.jdom.*;
021: import org.apache.log4j.*;
022: import org.openlaszlo.css.CSSParser;
023:
024: /** Compiler for the <code>canvas</code> element. */
025: class CanvasCompiler extends ToplevelCompiler {
026: /** Logger */
027: private static Logger mLogger = Logger
028: .getLogger(CanvasCompiler.class);
029:
030: CanvasCompiler(CompilationEnvironment env) {
031: super (env);
032: }
033:
034: static boolean isElement(Element element) {
035: return element.getName().equals("canvas");
036: }
037:
038: // Apps are proxied by default.
039: public static boolean APP_PROXIED_DEFAULT = true;
040:
041: public void compile(Element element) throws CompilationError {
042: Canvas canvas = new Canvas();
043: // query arg
044: String lzproxied = mEnv.getProperty(mEnv.PROXIED_PROPERTY);
045: // canvas attribute
046: String cproxied = element.getAttributeValue("proxied");
047:
048: canvas
049: .setDebug(mEnv
050: .getBooleanProperty(CompilationEnvironment.DEBUG_PROPERTY));
051: canvas
052: .setProfile(mEnv
053: .getBooleanProperty(CompilationEnvironment.PROFILE_PROPERTY));
054: canvas
055: .setBacktrace(mEnv
056: .getBooleanProperty(CompilationEnvironment.BACKTRACE_PROPERTY));
057:
058: // Set the "proxied" flag for this app.
059: // canvas attribute overrides passed in arg, warn for conflict
060: if (cproxied != null && !cproxied.equals("inherit")) {
061: if (lzproxied != null && !lzproxied.equals(cproxied)) {
062: mEnv.warn(
063: /* (non-Javadoc)
064: * @i18n.test
065: * @org-mes="The canvas attribute 'proxied=" + p[0] + "' conflicts with the 'lzproxied=" + p[1] + "' query arg"
066: */
067: org.openlaszlo.i18n.LaszloMessages.getMessage(
068: CanvasCompiler.class.getName(), "051018-56",
069: new Object[] { cproxied, lzproxied }), element);
070: }
071: canvas.setProxied(cproxied.equals("true"));
072: } else {
073: // inherit from lzproxied arg, or default to APP_PROXIED_PROPERTY
074: if (lzproxied != null) {
075: canvas.setProxied(lzproxied.equals("true"));
076: } else {
077: canvas.setProxied(APP_PROXIED_DEFAULT);
078: }
079: }
080:
081: String versionNumber = element.getAttributeValue("version");
082: if (versionNumber != null) {
083: String msg =
084: /* (non-Javadoc)
085: * @i18n.test
086: * @org-mes="The canvas is declared with version=\"" + p[0] + "\". This version of the LPS compiles version 1.1 files. This applicaton may not behave as intended when compiled with this version of the product."
087: */
088: org.openlaszlo.i18n.LaszloMessages.getMessage(
089: CanvasCompiler.class.getName(), "051018-77",
090: new Object[] { versionNumber });
091: if (versionNumber.equals("1.1"))
092: ;
093: else if (versionNumber.equals("1.0"))
094: mEnv.warn(
095: /* (non-Javadoc)
096: * @i18n.test
097: * @org-mes=p[0] + " It is recommended that you run it in debug mode and fix all compiler and debugger warnings, and that you read the migration guide in the developer documentation."
098: */
099: org.openlaszlo.i18n.LaszloMessages.getMessage(
100: CanvasCompiler.class.getName(), "051018-88",
101: new Object[] { msg }), element);
102: else
103: mEnv.warn(msg, element);
104: }
105:
106: String scriptLimits = element.getAttributeValue("scriptlimits");
107: if (scriptLimits != null) {
108: try {
109: Map properties = new CSSParser(new AttributeStream(
110: element, "scriptlimits")).Parse();
111: int recursion = properties.containsKey("recursion") ? ((Integer) properties
112: .get("recursion")).intValue()
113: : 0;
114: int timeout = properties.containsKey("timeout") ? ((Integer) properties
115: .get("timeout")).intValue()
116: : 0;
117: mEnv.setScriptLimits(recursion, timeout);
118: } catch (org.openlaszlo.css.ParseException e) {
119: throw new CompilationError(e);
120: } catch (org.openlaszlo.css.TokenMgrError e) {
121: throw new CompilationError(e);
122: }
123: }
124:
125: if (mEnv.isSWF()) {
126: String baseLibraryName = getBaseLibraryName(mEnv);
127: String baseLibraryBecause = "Required for all applications";
128:
129: // TODO [2004-06-02]: explanation for debug attribute and
130: // request parameter
131:
132: mEnv.getGenerator()
133: .importBaseLibrary(baseLibraryName, mEnv);
134: }
135:
136: canvas.setRuntime(mEnv.getRuntime());
137: initializeFromElement(canvas, element);
138:
139: // Default to true, embed fonts in swf file
140: boolean embedFonts = true;
141: String embed = element
142: .getAttributeValue(CompilationEnvironment.EMBEDFONTS_PROPERTY);
143: if ("false".equals(embed)) {
144: embedFonts = false;
145: }
146: mEnv.setEmbedFonts(embedFonts);
147:
148: Map map = createCanvasObject(element, canvas);
149: String script;
150: try {
151: java.io.Writer writer = new java.io.StringWriter();
152: writer.write("canvas = new LzCanvas(");
153: ScriptCompiler.writeObject(map, writer);
154: writer.write(");");
155: script = writer.toString();
156: } catch (java.io.IOException e) {
157: throw new ChainedException(e);
158: }
159: if (mEnv.isCanvas()) {
160: throw new CompilationError(
161: /* (non-Javadoc)
162: * @i18n.test
163: * @org-mes="An application may only have one canvas tag. Check included files for a duplicate canvas tag"
164: */
165: org.openlaszlo.i18n.LaszloMessages.getMessage(
166: CanvasCompiler.class.getName(), "051018-131"),
167: element);
168: }
169:
170: mEnv.setCanvas(canvas, script);
171:
172: // Compile (import) canvas's fonts first
173: for (Iterator iter = element.getChildren("font",
174: element.getNamespace()).iterator(); iter.hasNext();) {
175: Compiler.compileElement((Element) iter.next(), mEnv);
176: }
177:
178: handleAutoincludes(mEnv, element);
179:
180: // Compile child elements
181: for (Iterator iter = element.getChildren().iterator(); iter
182: .hasNext();) {
183: Element child = (Element) iter.next();
184: // fonts were compiled above
185: // createCanvasObject, so ignore them here
186: if (!NodeModel.isPropertyElement(child)
187: && !FontCompiler.isElement(child)) {
188: Compiler.compileElement(child, mEnv);
189: }
190: }
191:
192: }
193:
194: private Map createCanvasObject(Element element, Canvas canvas) {
195: NodeModel model = NodeModel.elementOnlyAsModel(element, mEnv
196: .getSchema(), mEnv);
197: Set visited = new HashSet();
198: for (Iterator iter = getLibraries(element).iterator(); iter
199: .hasNext();) {
200: File file = (File) iter.next();
201: Element library = LibraryCompiler.resolveLibraryElement(
202: file, mEnv, visited);
203: if (library != null) {
204: collectObjectProperties(library, model, visited);
205: }
206: }
207: collectObjectProperties(element, model, visited);
208: model.updateAttrs();
209: Map attrs = model.attrs;
210:
211: // default width is 100% by 100%
212: if (attrs.get("width") == null)
213: attrs.put("width", "100%");
214: if (attrs.get("height") == null)
215: attrs.put("height", "100%");
216:
217: setDimension(attrs, "width", canvas.getWidth());
218: setDimension(attrs, "height", canvas.getHeight());
219:
220: attrs.put("lpsbuild", ScriptCompiler.quote(LPS.getBuild()));
221: attrs.put("lpsbuilddate", ScriptCompiler.quote(LPS
222: .getBuildDate()));
223: attrs.put("lpsversion", ScriptCompiler.quote(LPS.getVersion()));
224: attrs.put("lpsrelease", ScriptCompiler.quote(LPS.getRelease()));
225: attrs.put("runtime", ScriptCompiler.quote(canvas.getRuntime()));
226: attrs.put("__LZproxied", ScriptCompiler.quote(mEnv.getProperty(
227: mEnv.PROXIED_PROPERTY, APP_PROXIED_DEFAULT ? "true"
228: : "false")));
229:
230: attrs.put("embedfonts", Boolean.toString(mEnv.getEmbedFonts()));
231: attrs.put("bgcolor", new Integer(canvas.getBGColor()));
232: FontInfo fontInfo = canvas.getFontInfo();
233: attrs.put("fontname", ScriptCompiler.quote(fontInfo.getName()));
234: attrs.put("fontsize", new Integer(fontInfo.getSize()));
235: attrs.put("fontstyle", ScriptCompiler
236: .quote(fontInfo.getStyle()));
237: if (element.getAttribute("id") != null)
238: attrs.put("id", ScriptCompiler.quote(element
239: .getAttributeValue("id")));
240: // Remove this so that Debug.write works in canvas methods.
241: attrs.remove("debug");
242: // Remove this since it isn't a JavaScript expression.
243: attrs.remove("libraries");
244: return attrs;
245: }
246:
247: protected void setDimension(Map attrs, String name, int value) {
248: String strval = (String) attrs.get(name);
249: if (strval != null && isPercentageDimension(strval))
250: attrs.put(name, ScriptCompiler.quote(strval));
251: else
252: attrs.put(name, new Integer(value));
253: }
254:
255: protected boolean isPercentageDimension(String str) {
256: return str.matches("\\s*(?:\\d+[.\\d*]|.\\d+)%\\s*");
257: }
258:
259: /**
260: * Initializes the canvas from the Element and
261: * removes any "special" children elements that
262: * should not be compiled.
263: *
264: * @param elt element that contains the canvas
265: */
266: public void initializeFromElement(Canvas canvas, Element elt) {
267: final String BGCOLOR_ATTR_NAME = "bgcolor";
268: boolean resizable = false;
269:
270: String width = elt.getAttributeValue("width");
271: String height = elt.getAttributeValue("height");
272: String bgcolor = elt.getAttributeValue(BGCOLOR_ATTR_NAME);
273: String title = elt.getAttributeValue("title");
274: String id = elt.getAttributeValue("id");
275: String accessible = elt.getAttributeValue("accessible");
276:
277: if (width != null) {
278: if (isPercentageDimension(width)) {
279: resizable = true;
280: canvas.setWidthString(width);
281: } else {
282: try {
283: canvas.setWidth(Integer.parseInt(width));
284: } catch (NumberFormatException e) {
285: throw new CompilationError(elt, "width", e);
286: }
287: }
288: }
289: if (height != null) {
290: if (isPercentageDimension(height)) {
291: resizable = true;
292: canvas.setHeightString(height);
293: } else {
294: try {
295: canvas.setHeight(Integer.parseInt(height));
296: } catch (NumberFormatException e) {
297: throw new CompilationError(elt, "height", e);
298: }
299: }
300: }
301:
302: if (bgcolor != null) {
303: try {
304: canvas.setBGColor(ViewSchema.parseColor(bgcolor));
305: } catch (ColorFormatException e) {
306: throw new CompilationError(elt, BGCOLOR_ATTR_NAME, e);
307: }
308: }
309: if (title != null) {
310: canvas.setTitle(title);
311: }
312: if (id != null) {
313: canvas.setID(id);
314: }
315: if (accessible != null) {
316: canvas.setAccessible(accessible.equals("true"));
317: }
318:
319: // Persistent connection parameters
320: canvas.initializeConnection(elt);
321:
322: String version = elt.getAttributeValue("version");
323: if (version != null && !version.equals(canvas.DEFAULT_VERSION)) {
324: if (version.equals("1.0")) {
325: // TODO: [2003-10-25 bloch] these should come from a
326: // properties file
327: canvas.defaultFont = "lztahoe8";
328: canvas.defaultFontFilename = "lztahoe8.ttf";
329: canvas.defaultBoldFontFilename = "lztahoe8b.ttf";
330: canvas.defaultItalicFontFilename = "lztahoe8i.ttf";
331: // NOTE: [2003-10-30 bloch] we don't have lztahoe8bi yet
332: // But 1.0 didn't either so this is prolly ok.
333: canvas.defaultBoldItalicFontFilename = "lztahoe8bi.ttf";
334: }
335: }
336:
337: String font = elt.getAttributeValue("font");
338: String fontstyle = elt.getAttributeValue("fontstyle");
339: String fontsize = elt.getAttributeValue("fontsize");
340: if (font == null || font.equals("")) {
341: font = canvas.defaultFont();
342: }
343: if (fontstyle == null || fontstyle.equals("")) {
344: fontstyle = canvas.DEFAULT_FONTSTYLE;
345: }
346: if (fontsize == null || fontsize.equals("")) {
347: fontsize = canvas.defaultFontsize();
348: }
349:
350: canvas.setFontInfo(new FontInfo(font, fontsize, fontstyle));
351:
352: }
353:
354: private void collectObjectProperties(Element element,
355: NodeModel model, Set visited) {
356: for (Iterator iter = element.getChildren().iterator(); iter
357: .hasNext();) {
358: Element child = (Element) iter.next();
359: if (NodeModel.isPropertyElement(child)) {
360: model.addPropertyElement(child);
361: } else if (LibraryCompiler.isElement(child)) {
362: Element libraryElement = LibraryCompiler
363: .resolveLibraryElement(child, mEnv, visited);
364: if (libraryElement != null) {
365: collectObjectProperties(libraryElement, model,
366: visited);
367: }
368: }
369: }
370: }
371: }
|