1 4 5 9 10 package org.openlaszlo.compiler; 11 import java.lang.Integer ; 12 import java.io.*; 13 import java.text.ChoiceFormat ; 14 import java.text.MessageFormat ; 15 import java.util.*; 16 import org.jdom.*; 17 import org.jdom.input.SAXBuilder; 18 import org.openlaszlo.sc.ScriptCompiler; 19 import org.openlaszlo.utils.ChainedException; 20 import org.openlaszlo.utils.FileUtils; 21 import org.openlaszlo.utils.ListFormat; 22 import org.openlaszlo.xml.internal.*; 23 import org.openlaszlo.server.LPS; 24 import org.apache.log4j.*; 25 26 import org.openlaszlo.iv.flash.util.*; 27 import org.openlaszlo.iv.flash.api.*; 28 29 30 31 38 public class Compiler { 39 40 public static Logger SchemaLogger = Logger.getLogger("schema"); 41 42 protected static List KNOWN_RUNTIMES = 43 Arrays.asList(new String [] {"swf5", "swf6", "swf7"}); 44 45 48 protected FileResolver mFileResolver = FileResolver.DEFAULT_FILE_RESOLVER; 49 50 53 protected CompilerMediaCache mMediaCache = null; 54 55 57 protected final Properties mProperties = new Properties(); 58 59 61 private static Logger mLogger = Logger.getLogger(Compiler .class); 62 63 64 87 public String getProperty(String key) { 88 return mProperties.getProperty(key); 89 } 90 91 public void setProperty(String key, String value) { 92 mProperties.setProperty(key, value); 93 } 94 95 public FileResolver getFileResolver() { 96 return mFileResolver; 97 } 98 99 104 public void setFileResolver(FileResolver resolver) { 105 this.mFileResolver = resolver; 106 } 107 108 111 public void setMediaCache(CompilerMediaCache cache) { 112 this.mMediaCache = cache; 113 } 114 115 118 public CompilationEnvironment makeCompilationEnvironment() { 119 CompilationEnvironment env = 120 new CompilationEnvironment(mProperties, mFileResolver, mMediaCache); 121 return env; 122 } 123 124 133 public Canvas compile(File sourceFile, File objectFile, String url) 134 throws CompilationError, IOException 135 { 136 Properties props = new Properties(); 137 return compile(sourceFile, objectFile, props); 138 } 139 140 141 157 public Canvas compile(File sourceFile, File objectFile, Properties props) 158 throws CompilationError, IOException 159 { 160 FileUtils.makeFileAndParentDirs(objectFile); 161 162 ByteArrayOutputStream bstream = new ByteArrayOutputStream(); 165 OutputStream ostream = new FileOutputStream(objectFile); 166 167 boolean success = false; 168 try { 169 Canvas canvas = compile(sourceFile, bstream, props); 170 bstream.writeTo(ostream); 171 ostream.close(); 172 173 if (!canvas.isProxied()) { 175 OutputStream fostream = null; 176 try { 177 File deploymentFile = new File(sourceFile+".swf"); 179 fostream = new FileOutputStream(deploymentFile); 180 bstream.writeTo(fostream); 181 } finally { 182 if (fostream != null) { 183 fostream.close(); 184 } 185 } 186 } 187 success = true; 188 return canvas; 189 } catch (java.lang.OutOfMemoryError e) { 190 System.gc(); 193 Runtime.getRuntime().gc(); 194 throw new CompilationError("out of memory"); 195 } finally { 196 if (!success) { 197 ostream.close(); 198 objectFile.delete(); 199 } 200 } 201 } 202 203 216 public Canvas compile(File file, OutputStream ostr, Properties props) 217 throws CompilationError, IOException 218 { 219 mLogger.info("compiling " + file + "..."); 220 CompilationEnvironment env = makeCompilationEnvironment(); 221 CompilationErrorHandler errors = env.getErrorHandler(); 222 env.setApplicationFile(file); 223 224 String swfversion = props.getProperty(env.SWFVERSION_PROPERTY); 227 228 if (swfversion != null) { 229 mLogger.info("canvas compiler compiling runtime = " + swfversion); 230 env.setProperty(env.SWFVERSION_PROPERTY, swfversion); 231 if (! KNOWN_RUNTIMES.contains(swfversion)) { 232 List runtimes = new Vector(); 233 for (Iterator iter = KNOWN_RUNTIMES.iterator(); 234 iter.hasNext(); ) { 235 runtimes.add("\"" + iter.next() + "\""); 236 } 237 238 throw new CompilationError( 239 MessageFormat.format( 240 "Request for unknown runtime: The \"lzr\" query parameter has the value \"{0}\". It must be {1}{2}.", 241 new String [] { 242 swfversion, 243 new ChoiceFormat ( 244 "1#| 2#either | 2<one of "). 245 format(runtimes.size()), 246 new ListFormat("or").format(runtimes) 247 })); 248 } 249 } 250 251 String proxied = props.getProperty(env.PROXIED_PROPERTY); 252 mLogger.debug("looking for lzproxied, props= " + props.toString()); 253 if (proxied != null) { 254 mLogger.debug("setting lzproxied to " + proxied); 255 env.setProperty(env.PROXIED_PROPERTY, proxied); 256 } 257 258 259 String debug = props.getProperty(env.DEBUG_PROPERTY); 260 if (debug != null) { 261 env.setProperty(env.DEBUG_PROPERTY, debug); 262 } 263 264 String profile = props.getProperty(env.PROFILE_PROPERTY); 265 if (profile != null) { 266 env.setProperty(env.PROFILE_PROPERTY, profile); 267 } 268 269 String krank = props.getProperty(env.KRANK_PROPERTY); 270 if (krank != null) { 271 env.setProperty(env.KRANK_PROPERTY, krank); 272 } 273 274 String logdebug = props.getProperty(env.LOGDEBUG_PROPERTY); 275 if (logdebug != null) { 276 env.setProperty(env.LOGDEBUG_PROPERTY, logdebug); 277 } 278 279 String remotedebug = props.getProperty(env.REMOTEDEBUG_PROPERTY); 280 if (remotedebug != null) { 281 env.setProperty(env.REMOTEDEBUG_PROPERTY, remotedebug); 282 } 283 284 String sourcelocators = props.getProperty(env.SOURCELOCATOR_PROPERTY); 285 if (sourcelocators != null) { 286 env.setProperty(env.SOURCELOCATOR_PROPERTY, sourcelocators); 287 } 288 289 try { 290 mLogger.debug("Parsing " + file.getAbsolutePath()); 291 292 Document doc = env.getParser().parse(file); 293 Element root = doc.getRootElement(); 294 295 if ("true".equals(root.getAttributeValue("debug"))) { 298 env.setProperty(env.DEBUG_PROPERTY, true); 299 } 300 301 if ("true".equals(root.getAttributeValue("profile"))) { 302 env.setProperty(env.PROFILE_PROPERTY, true); 303 } 304 if ("false".equals(root.getAttributeValue("validate"))) { 305 env.setProperty(env.VALIDATE_PROPERTY, false); 306 } 307 309 mLogger.debug("Making a writer..."); 310 311 try { 313 env.getSchema().loadSchema(); 314 } catch (org.jdom.JDOMException e) { 315 throw new ChainedException(e); 316 } 317 Compiler.updateSchema(doc.getRootElement(), env, 318 env.getSchema(), new HashSet()); 319 if (SchemaLogger.isDebugEnabled()) { 320 org.jdom.output.XMLOutputter xmloutputter = 321 new org.jdom.output.XMLOutputter(); 322 try { 323 SchemaLogger.debug(xmloutputter.outputString(env.getSchema().getSchemaDOM())); 324 } catch (org.jdom.JDOMException e) { 325 throw new ChainedException(e); 326 } 327 } 328 329 if (env.getBooleanProperty(env.VALIDATE_PROPERTY)) 330 Parser.validate(doc, file.getPath(), env); 331 332 SWFWriter writer = new SWFWriter(env.getProperties(), ostr, 333 mMediaCache, true, env); 334 env.setSWFWriter(writer); 335 mLogger.debug("new env..." + env.getProperties().toString()); 336 if (root.getName().intern() != "canvas") { 337 throw new CompilationError("invalid root element type: " + 338 root.getName(), root); 339 } 340 341 processCompilerInstructions(root, env); 342 compileElement(root, env); 343 ViewCompiler.checkUnresolvedResourceReferences (env); 344 mLogger.debug("done..."); 345 writer.close(); 348 349 Canvas canvas = env.getCanvas(); 350 if (!errors.isEmpty()) { 351 if (canvas != null) { 352 canvas.setCompilationWarningText( 353 errors.toCompilationError().getMessage()); 354 canvas.setCompilationWarningXML( 355 errors.toXML()); 356 } 357 System.err.println(errors.toCompilationError().getMessage()); 358 } 359 canvas.setFilePath(FileUtils.relativePath(file, LPS.HOME())); 361 mLogger.info("done"); 362 return canvas; 363 } catch (CompilationError e) { 364 e.attachErrors(errors.getErrors()); 366 throw e; 367 } catch (org.openlaszlo.xml.internal.MissingAttributeException e) { 370 374 errors.addError(new CompilationError(e.getMessage() + "; compilation aborted")); 375 throw errors.toCompilationError(); 376 } 377 } 378 379 public void compileAndWriteToSWF (String script, String seqnum, OutputStream out, String swfversion) { 380 try { 381 CompilationEnvironment env = makeCompilationEnvironment(); 382 env.setProperty(env.DEBUG_PROPERTY, true); 383 Properties props = (Properties) env.getProperties().clone(); 384 env.setProperty(env.SWFVERSION_PROPERTY, swfversion); 385 byte[] action; 386 387 try { 391 String prog; 392 if (seqnum == null) { 393 prog = "Debug.displayResult(" + script + ");\n"; 394 } else { 395 prog = "Debug.displayResult(_level0.__LzDebug.sockWriteAsXML("+script+","+seqnum+"));\n"; 397 } 398 prog += "this._parent.loader.returnData( this._parent );"; 399 action = ScriptCompiler.compileToByteArray(prog, props); 400 } catch (org.openlaszlo.sc.parser.ParseException e) { 401 try { 402 action = ScriptCompiler.compileToByteArray( 403 "function $evalee() {\n" + 404 "#pragma 'scriptElement'\n" + 405 CompilerUtils.sourceLocationDirective(null, new Integer (0), new Integer (0)) + 406 script+"\n"+ 407 "if (Debug.remoteDebug) { _level0.__LzDebug.sockWriteAsXML(true,"+seqnum+");};\n" + 408 "};\n" + 409 "$evalee();\n" + 410 "this._parent.loader.returnData( this._parent )", props); 411 } catch (org.openlaszlo.sc.parser.ParseException e2) { 412 action = ScriptCompiler.compileToByteArray( 414 "Debug.__write(" + 415 ScriptCompiler.quote("Parse error: "+ e2.getMessage()) + ")\n" 416 + "this._parent.loader.returnData( this._parent )", props); 417 } 418 } 419 420 ScriptCompiler.writeScriptToStream(action, out, LPS.getSWFVersionNum(swfversion)); 421 out.flush(); 422 out.close(); 423 } catch (IOException e) { 424 mLogger.info("error compiling/writing script: "+script+" :" +e); 425 } 426 } 427 428 429 430 static ElementCompiler getElementCompiler(Element element, 431 CompilationEnvironment env) { 432 if (CanvasCompiler.isElement(element)) { 433 return new CanvasCompiler(env); 434 } else if (ImportCompiler.isElement(element)) { 435 return new ImportCompiler(env); 436 } else if (LibraryCompiler.isElement(element)) { 437 return new LibraryCompiler(env); 438 } else if (ScriptElementCompiler.isElement(element)) { 439 return new ScriptElementCompiler(env); 440 } else if (SecurityCompiler.isElement(element)) { 441 return new SecurityCompiler(env); 442 } else if (SplashCompiler.isElement(element)) { 443 return new SplashCompiler(env); 444 } else if (FontCompiler.isElement(element)) { 445 return new FontCompiler(env); 446 } else if (ResourceCompiler.isElement(element)) { 447 return new ResourceCompiler(env); 448 } else if (ClassCompiler.isElement(element)) { 449 return new ClassCompiler(env); 450 } else if (DataCompiler.isElement(element)) { 451 return new DataCompiler(env); 452 } else if (DebugCompiler.isElement(element)) { 453 return new DebugCompiler(env); 454 } else if (SwitchCompiler.isElement(element)) { 455 return new SwitchCompiler(env); 456 } else if (ViewCompiler.isElement(element)) { 459 return new ViewCompiler(env); 460 } else { 461 throw new CompilationError("unknown tag: " + element.getName(), 462 element); 463 } 464 } 465 466 475 protected static void compileElement(Element element, 476 CompilationEnvironment env) 477 throws CompilationError 478 { 479 if (element.getAttributeValue("disabled") != null && 480 element.getAttributeValue("disabled").intern() == "true") { 481 return; 482 } 483 try { 484 ElementCompiler compiler = getElementCompiler(element, env); 485 mLogger.debug("compiling element with " + compiler.getClass().toString()); 486 compiler.compile(element); 487 } catch (CompilationError e) { 488 if (e.getElement() == null && e.getPathname() == null) { 490 e.initElement(element); 491 } 492 throw e; 493 } 494 } 495 496 static void updateSchema(Element element, CompilationEnvironment env, 497 ViewSchema schema, Set visited) 498 { 499 getElementCompiler(element, env).updateSchema(element, schema, visited); 500 } 501 502 static void importLibrary(File file, CompilationEnvironment env) { 503 Element root = LibraryCompiler.resolveLibraryElement( 504 file, env, env.getImportedLibraryFiles(), true); 505 if (root != null) { 506 compileElement(root, env); 507 } 508 } 509 510 static void updateSchemaFromLibrary(File file, CompilationEnvironment env, 511 ViewSchema schema, Set visited) 512 { 513 Element root = LibraryCompiler.resolveLibraryElement( 514 file, env, visited, false); 515 if (root != null) { 516 Compiler.updateSchema(root, env, schema, visited); 517 } 518 } 519 520 protected void processCompilerInstructions(Element element, 521 CompilationEnvironment env) { 522 for (Iterator iter = element.getContent().iterator(); 523 iter.hasNext(); ) { 524 ProcessingInstruction pi; 525 try { 526 pi = (ProcessingInstruction) iter.next(); 527 } catch (ClassCastException e) { 528 continue; 529 } 530 if (pi.getTarget().equals("lzc")) 531 processCompilerInstruction(env, pi); 532 } 533 } 534 535 protected void processCompilerInstruction(CompilationEnvironment env, 536 ProcessingInstruction pi) { 537 if (pi.getValue("class") != null) 538 processClassInstruction(env, pi.getValue("class"), pi); 539 if (pi.getValue("classes") != null) { 540 for (Iterator iter = Arrays.asList(pi.getValue("classes").split("\\s+")).iterator(); iter.hasNext(); ) { 541 processClassInstruction(env, (String ) iter.next(), pi); 542 } 543 } 544 } 545 546 protected void processClassInstruction(CompilationEnvironment env, 547 String className, 548 ProcessingInstruction pi) { 549 String inlineString = pi.getValue("inline-only"); 550 if (inlineString != null) { 551 boolean inline = Boolean.valueOf(inlineString).booleanValue(); 552 ClassModel classModel = env.getSchema().getClassModel(className); 553 if (classModel == null) { 554 env.warn("A processor instruction refers to a class named \""+ 555 className + "\". No class with this name exists."); 556 return; 557 } 558 classModel.setInline(inline); 559 } 560 } 561 } 562 | Popular Tags |