001: /* *****************************************************************************
002: * ImportCompiler.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: import org.jdom.Document;
015: import org.jdom.Element;
016: import org.openlaszlo.xml.internal.XMLUtils;
017: import org.openlaszlo.utils.FileUtils;
018: import org.openlaszlo.sc.ScriptCompiler;
019: import org.openlaszlo.utils.ChainedException;
020: import org.apache.log4j.*;
021:
022: /** Compiler for <code>import</code> elements.
023: *
024: * @author Henry Minsky
025: */
026: class ImportCompiler extends ToplevelCompiler {
027: final static String HREF_ANAME = "href";
028: final static String NAME_ANAME = "name";
029:
030: private static Logger mLogger = Logger
031: .getLogger(ImportCompiler.class);
032:
033: ImportCompiler(CompilationEnvironment env) {
034: super (env);
035: }
036:
037: static boolean isElement(Element element) {
038: return element.getName().equals("import");
039: }
040:
041: /** Return the difference of two strings.
042: * stringDiff("foo/bar/baz.lzx", "foo/bar") ==> /baz.lzx
043: */
044: static String stringDiff(String s1, String s2) {
045: int sl1 = s1.length();
046: int sl2 = s2.length();
047: return s1.substring(sl2 + 1, sl1);
048: }
049:
050: public void compile(Element element) throws CompilationError {
051: String href = XMLUtils.requireAttributeValue(element,
052: HREF_ANAME);
053: String libname = XMLUtils.requireAttributeValue(element,
054: NAME_ANAME);
055: String stage = XMLUtils.requireAttributeValue(element, "stage");
056:
057: Element module = LibraryCompiler.resolveLibraryElement(element,
058: mEnv, mEnv.getImportedLibraryFiles());
059: if (module != null) {
060: // check for conflict in the value of the "proxied"
061: // attribute declared on the <import> tag vs the
062: // <library> tag.
063:
064: String libproxied = module.getAttributeValue("proxied",
065: "inherit");
066: String importproxied = element.getAttributeValue("proxied",
067: "inherit");
068:
069: if ((importproxied.equals("true") && libproxied
070: .equals("false"))
071: || (importproxied.equals("false") && libproxied
072: .equals("true"))) {
073: mEnv.warn(
074: /* (non-Javadoc)
075: * @i18n.test
076: * @org-mes="The value of the 'proxied' attribute on this library, '" + p[0] + "', conflicts with the import element value of '" + p[1] + "'"
077: */
078: org.openlaszlo.i18n.LaszloMessages.getMessage(
079: ImportCompiler.class.getName(), "051018-71",
080: new Object[] { libproxied, importproxied }),
081: element);
082: }
083:
084: // We're not compiling this into the current app, we're
085: // building a separate binary library object file for it.
086: File appdir = mEnv.getApplicationFile().getParentFile();
087: File libsrcfile = mEnv.resolveReference(element,
088: HREF_ANAME, true);
089: String adjustedhref = libsrcfile.getPath();
090:
091: if (appdir != null) {
092: adjustedhref = FileUtils.relativePath(libsrcfile
093: .getPath(), appdir.getPath());
094: }
095:
096: // If we added a "library.lzx" to the path, set it properly in the XML
097: element.setAttribute(HREF_ANAME, adjustedhref);
098:
099: // I'm scared of the CompilationManager, just generate the output file
100: // directly for now.
101: String libfile = libsrcfile.getName();
102: String libprefix = mEnv.getLibPrefix();
103: String runtime = mEnv.getProperty(mEnv.RUNTIME_PROPERTY);
104: String extension = Compiler.SCRIPT_RUNTIMES
105: .contains(runtime) ? ".js" : ".swf";
106: String objfilename = libprefix + "/" + libfile + extension;
107: String objpath = mEnv.getLibPrefixRelative() + "/"
108: + libfile + extension;
109:
110: mLogger.info(
111: /* (non-Javadoc)
112: * @i18n.test
113: * @org-mes="calling compilerLibrary libsrcfile=" + p[0] + " objfile=" + p[1]
114: */
115: org.openlaszlo.i18n.LaszloMessages.getMessage(
116: ImportCompiler.class.getName(), "051018-103",
117: new Object[] { libsrcfile, objfilename }));
118:
119: try {
120: FileUtils.makeFileAndParentDirs(new File(objfilename));
121: } catch (java.io.IOException e) {
122: throw new CompilationError(element, e);
123: }
124:
125: compileLibrary(libsrcfile, objfilename, objpath, module);
126:
127: // Emit code into main app to instantiate a LzLibrary
128: // object, which implements the load() method.
129: ViewCompiler vc = new ViewCompiler(mEnv);
130:
131: // Override the href with a pointer to the library object-file build directory
132: element.setAttribute("href", objpath);
133: vc.compile(element);
134: }
135: }
136:
137: void updateSchema(Element element, ViewSchema schema, Set visited) {
138: element = LibraryCompiler.resolveLibraryElement(element, mEnv,
139: visited);
140: if (element != null) {
141: super .updateSchema(element, schema, visited);
142: }
143: }
144:
145: /**
146: * Compile a standalone binary library file with no canvas.
147: */
148: void compileLibrary(File infile, String outfile, String liburl,
149: Element element) throws CompilationError {
150: // copy fields from mEnv to new Environment
151: CompilationEnvironment env = new CompilationEnvironment(mEnv);
152: CompilationErrorHandler errors = env.getErrorHandler();
153: env.setApplicationFile(infile);
154: Properties props = (Properties) env.getProperties().clone();
155: byte[] action;
156:
157: try {
158:
159: OutputStream ostream = new FileOutputStream(outfile);
160: try {
161: ObjectWriter writer;
162:
163: String runtime = env.getProperty(env.RUNTIME_PROPERTY);
164: if (Compiler.SCRIPT_RUNTIMES.contains(runtime)) {
165: writer = new DHTMLWriter(env.getProperties(),
166: ostream, env.getMediaCache(), false, env);
167: } else if (Compiler.SWF_RUNTIMES.contains(runtime)) {
168: writer = new SWFWriter(env.getProperties(),
169: ostream, env.getMediaCache(), false, env);
170: } else {
171: throw new CompilationError(
172: "runtime "
173: + runtime
174: + " not supported for generating an import library",
175: element);
176: }
177:
178: env.setObjectWriter(writer);
179: // Set the main SWFWriter so we can output resources
180: // to the main app
181: env.setMainObjectWriter(mEnv.getGenerator());
182:
183: // Mark it as an runtime-importable library.
184: env.setImportLib(true);
185:
186: // We can embed swf fonts in libraries now
187: env.setEmbedFonts(true);
188:
189: // copy the fontmanager from old env to new one.
190: writer.setFontManager(mEnv.getGenerator()
191: .getFontManager());
192: writer.setCanvasDefaults(mEnv.getCanvas(), mEnv
193: .getMediaCache());
194:
195: writer.openSnippet(liburl);
196:
197: // allows snippet code to call out to LzInstantiateView in the main app:
198: // var LzInstantiateView = _level0.LzInstantiateView;
199: if (Compiler.SWF_RUNTIMES.contains(runtime)) {
200: env.compileScript("var " + VIEW_INSTANTIATION_FNAME
201: + " = _level0." + VIEW_INSTANTIATION_FNAME,
202: element);
203: }
204:
205: // Note: canvas.initDone() resets the _lzinitialsubviews list, so
206: // that has to be called when the library finishes loading. This is currently
207: // done by LzLibraryLoader.snippetLoaded(), which is the callback
208: // that we emit at the end of our snippet file.
209:
210: for (Iterator iter = element.getChildren().iterator(); iter
211: .hasNext();) {
212: Element child = (Element) iter.next();
213: if (!NodeModel.isPropertyElement(child)) {
214: Compiler.compileElement(child, env);
215: }
216: }
217:
218: ViewCompiler.checkUnresolvedResourceReferences(env);
219: writer.closeSnippet();
220: } finally {
221: ostream.close();
222: }
223:
224: /** Copy any compilation errors/warnings over to canvas's CompilationErrorHandler
225: */
226: mEnv.getErrorHandler().appendErrors(env.getErrorHandler());
227:
228: } catch (CompilationError e) {
229: // TBD: e.initPathname(file.getPath());
230: e.attachErrors(errors.getErrors());
231: throw e;
232: //errors.addError(new CompilationError(e.getMessage() + "; compilation aborted"));
233: //throw errors.toCompilationError();
234: } catch (org.openlaszlo.xml.internal.MissingAttributeException e) {
235: /* The validator will have caught this, but if we simply
236: * pass the error through, the vaildation warnings will
237: * never be printed. Create a new message that includes
238: * them so that we get the source information. */
239: errors.addError(new CompilationError(
240: /* (non-Javadoc)
241: * @i18n.test
242: * @org-mes=p[0] + "; compilation aborted"
243: */
244: org.openlaszlo.i18n.LaszloMessages.getMessage(
245: ImportCompiler.class.getName(), "051018-210",
246: new Object[] { e.getMessage() })));
247: throw errors.toCompilationError();
248: } catch (IOException e) {
249: throw new CompilationError(element, e);
250: }
251:
252: }
253: }
|