KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > dev > cfg > ModuleDefSchema


1 /*
2  * Copyright 2006 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.dev.cfg;
17
18 import com.google.gwt.core.ext.Generator;
19 import com.google.gwt.core.ext.TreeLogger;
20 import com.google.gwt.core.ext.UnableToCompleteException;
21 import com.google.gwt.dev.js.JsParser;
22 import com.google.gwt.dev.js.JsParserException;
23 import com.google.gwt.dev.js.JsParserException.SourceDetail;
24 import com.google.gwt.dev.js.ast.JsExprStmt;
25 import com.google.gwt.dev.js.ast.JsFunction;
26 import com.google.gwt.dev.js.ast.JsProgram;
27 import com.google.gwt.dev.js.ast.JsStatements;
28 import com.google.gwt.dev.util.Empty;
29 import com.google.gwt.dev.util.Util;
30 import com.google.gwt.dev.util.xml.AttributeConverter;
31 import com.google.gwt.dev.util.xml.Schema;
32
33 import java.io.IOException JavaDoc;
34 import java.io.StringReader JavaDoc;
35 import java.net.URL JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.HashSet JavaDoc;
38 import java.util.Map JavaDoc;
39 import java.util.Set JavaDoc;
40
41 // CHECKSTYLE_NAMING_OFF
42
/**
43  * Configures a module definition object using XML.
44  */

45 public class ModuleDefSchema extends Schema {
46   private final class BodySchema extends Schema {
47
48     protected final String JavaDoc __define_property_1_name = null;
49
50     protected final String JavaDoc __define_property_2_values = null;
51
52     protected final String JavaDoc __entry_point_1_class = null;
53
54     protected final String JavaDoc __extend_property_1_name = null;
55
56     protected final String JavaDoc __extend_property_2_values = null;
57
58     protected final String JavaDoc __generate_with_1_class = null;
59
60     protected final String JavaDoc __inherits_1_name = null;
61
62     protected final String JavaDoc __property_provider_1_name = null;
63
64     protected final String JavaDoc __public_1_path = null;
65
66     protected final String JavaDoc __public_2_includes = "";
67
68     protected final String JavaDoc __public_3_excludes = "";
69
70     protected final String JavaDoc __public_4_defaultexcludes = "yes";
71
72     protected final String JavaDoc __public_5_casesensitive = "true";
73
74     protected final String JavaDoc __replace_with_1_class = null;
75
76     protected final String JavaDoc __script_1_src = null;
77
78     protected final String JavaDoc __servlet_1_path = null;
79
80     protected final String JavaDoc __servlet_2_class = null;
81
82     protected final String JavaDoc __set_property_1_name = null;
83
84     protected final String JavaDoc __set_property_2_value = null;
85
86     protected final String JavaDoc __source_1_path = "";
87
88     protected final String JavaDoc __stylesheet_1_src = null;
89
90     protected final String JavaDoc __super_source_1_path = "";
91
92     private Schema fChild;
93
94     protected Schema __define_property_begin(PropertyName name,
95         PropertyValue[] values) throws UnableToCompleteException {
96       if (moduleDef.getProperties().find(name.token) != null) {
97         // Disallow redefinition.
98
String JavaDoc msg = "Attempt to redefine property '" + name.token + "'";
99         logger.log(TreeLogger.ERROR, msg, null);
100         throw new UnableToCompleteException();
101       }
102
103       Property prop = moduleDef.getProperties().create(name.token);
104       for (int i = 0; i < values.length; i++) {
105         prop.addKnownValue(values[i].token);
106       }
107
108       // No children.
109
return null;
110     }
111
112     protected Schema __entry_point_begin(String JavaDoc className) {
113       moduleDef.addEntryPointTypeName(className);
114       return null;
115     }
116
117     protected Schema __extend_property_begin(Property property,
118         PropertyValue[] values) {
119       for (int i = 0; i < values.length; i++) {
120         property.addKnownValue(values[i].token);
121       }
122
123       // No children.
124
return null;
125     }
126
127     protected Schema __fail_begin() {
128       RuleFail rule = new RuleFail();
129       moduleDef.getRules().prepend(rule);
130       return new ConditionSchema(rule.getRootCondition());
131     }
132
133     protected Schema __generate_with_begin(Generator gen) {
134       RuleGenerateWith rule = new RuleGenerateWith(gen);
135       moduleDef.getRules().prepend(rule);
136       return new ConditionSchema(rule.getRootCondition());
137     }
138
139     protected Schema __inherits_begin(String JavaDoc name)
140         throws UnableToCompleteException {
141       TreeLogger branch = logger.branch(TreeLogger.TRACE,
142           "Loading inherited module '" + name + "'", null);
143       loader.nestedLoad(branch, name, moduleDef);
144       return null;
145     }
146
147     protected Schema __property_provider_begin(Property property) {
148       property.setProvider(new PropertyProvider(moduleDef, property));
149       return fChild = new PropertyProviderBodySchema();
150     }
151
152     protected void __property_provider_end(Property property)
153         throws UnableToCompleteException {
154       PropertyProviderBodySchema childSchema = ((PropertyProviderBodySchema) fChild);
155       String JavaDoc script = childSchema.getScript();
156       if (script == null) {
157         // This is a problem.
158
//
159
logger.log(TreeLogger.ERROR,
160             "Property providers must specify a JavaScript body", null);
161         throw new UnableToCompleteException();
162       }
163
164       int lineNumber = childSchema.getStartLineNumber();
165       JsFunction fn = parseJsBlock(lineNumber, script);
166
167       property.getProvider().setBody(fn.getBody());
168     }
169
170     protected Schema __public_begin(String JavaDoc path, String JavaDoc includes,
171         String JavaDoc excludes, String JavaDoc defaultExcludes, String JavaDoc caseSensitive) {
172       return fChild = new IncludeExcludeSchema();
173     }
174
175     protected void __public_end(String JavaDoc path, String JavaDoc includes, String JavaDoc excludes,
176         String JavaDoc defaultExcludes, String JavaDoc caseSensitive) {
177       IncludeExcludeSchema childSchema = ((IncludeExcludeSchema) fChild);
178       foundAnyPublic = true;
179
180       Set JavaDoc includeSet = childSchema.getIncludes();
181       addDelimitedStringToSet(includes, "[ ,]", includeSet);
182       String JavaDoc[] includeList = (String JavaDoc[]) includeSet.toArray(new String JavaDoc[includeSet.size()]);
183
184       Set JavaDoc excludeSet = childSchema.getExcludes();
185       addDelimitedStringToSet(excludes, "[ ,]", excludeSet);
186       String JavaDoc[] excludeList = (String JavaDoc[]) excludeSet.toArray(new String JavaDoc[excludeSet.size()]);
187
188       boolean doDefaultExcludes = "yes".equalsIgnoreCase(defaultExcludes)
189           || "true".equalsIgnoreCase(defaultExcludes);
190       boolean doCaseSensitive = "yes".equalsIgnoreCase(caseSensitive)
191           || "true".equalsIgnoreCase(caseSensitive);
192
193       addPublicPackage(modulePackageAsPath, path, includeList, excludeList,
194           doDefaultExcludes, doCaseSensitive);
195     }
196
197     protected Schema __replace_with_begin(String JavaDoc className) {
198       RuleReplaceWith rule = new RuleReplaceWith(className);
199       moduleDef.getRules().prepend(rule);
200       return new ConditionSchema(rule.getRootCondition());
201     }
202
203     /**
204      * @param src a partial or full url to a script file to inject
205      * @return <code>null</code> since there can be no children
206      */

207     protected Schema __script_begin(String JavaDoc src) {
208       return fChild = new ScriptReadyBodySchema();
209     }
210
211     protected void __script_end(String JavaDoc src) throws UnableToCompleteException {
212       ScriptReadyBodySchema childSchema = (ScriptReadyBodySchema) fChild;
213       String JavaDoc js = childSchema.getScriptReadyBlock();
214       if (js != null) {
215         logger.log(
216             TreeLogger.WARN,
217             "Injected scripts no longer require an associated JavaScript block.",
218             null);
219       }
220
221       // For consistency, we allow the ready functions to use $wnd even though
222
// they'll be running in the context of the host html window anyway.
223
// We make up the difference by injecting a local variable into the
224
// function we wrap around their code.
225
js = "var $wnd = window; " + js;
226
227       int lineNumber = childSchema.getStartLineNumber();
228       JsFunction fn = parseJsBlock(lineNumber, js);
229       Script script = new Script(src, fn);
230       moduleDef.getScripts().append(script);
231     }
232
233     protected Schema __servlet_begin(String JavaDoc path, String JavaDoc servletClass)
234         throws UnableToCompleteException {
235
236       // Only absolute paths, although it is okay to have multiple slashes.
237
if (!path.startsWith("/")) {
238         logger.log(TreeLogger.ERROR, "Servlet path '" + path
239             + "' must begin with forward slash (e.g. '/foo')", null);
240         throw new UnableToCompleteException();
241       }
242
243       // Map the path within this module.
244
moduleDef.mapServlet(path, servletClass);
245
246       return null;
247     }
248
249     protected Schema __set_property_begin(Property prop, PropertyValue value) {
250       prop.setActiveValue(value.token);
251
252       // No children.
253
return null;
254     }
255
256     /**
257      * Indicates which subdirectories contain translatable source without
258      * necessarily adding a sourcepath entry.
259      */

260     protected Schema __source_begin(String JavaDoc path) {
261       foundExplicitSourceOrSuperSource = true;
262
263       // Build a new path entry rooted at the classpath base.
264
//
265
addSourcePackage(modulePackageAsPath, path, false);
266       return null;
267     }
268
269     /**
270      * @param src a partial or full url to a stylesheet file to inject
271      * @return <code>null</code> since there can be no children
272      */

273     protected Schema __stylesheet_begin(String JavaDoc src) {
274       moduleDef.getStyles().append(src);
275       return null;
276     }
277
278     /**
279      * Like adding a translatable source package, but such that it uses the
280      * module's package itself as its sourcepath root entry.
281      */

282     protected Schema __super_source_begin(String JavaDoc path) {
283       foundExplicitSourceOrSuperSource = true;
284
285       // Build a new path entry rooted at this module's dir.
286
//
287
addSourcePackage(modulePackageAsPath, path, true);
288       return null;
289     }
290
291     private void addDelimitedStringToSet(String JavaDoc delimited, String JavaDoc delimiter,
292         Set JavaDoc toSet) {
293       if (delimited.length() > 0) {
294         String JavaDoc[] split = delimited.split(delimiter);
295         for (int i = 0; i < split.length; ++i) {
296           if (split[i].length() > 0) {
297             toSet.add(split[i]);
298           }
299         }
300       }
301     }
302
303     private void addPublicPackage(String JavaDoc parentDir, String JavaDoc relDir,
304         String JavaDoc[] includeList, String JavaDoc[] excludeList, boolean defaultExcludes,
305         boolean caseSensitive) {
306       String JavaDoc normChildDir = normalizePathEntry(relDir);
307       if (normChildDir.startsWith("/")) {
308         logger.log(TreeLogger.WARN, "Non-relative public package: "
309             + normChildDir, null);
310         return;
311       }
312       if (normChildDir.startsWith("./") || normChildDir.indexOf("/./") >= 0) {
313         logger.log(TreeLogger.WARN, "Non-canonical public package: "
314             + normChildDir, null);
315         return;
316       }
317       if (normChildDir.startsWith("../") || normChildDir.indexOf("/../") >= 0) {
318         logger.log(TreeLogger.WARN, "Non-canonical public package: "
319             + normChildDir, null);
320         return;
321       }
322       String JavaDoc fullDir = parentDir + normChildDir;
323       moduleDef.addPublicPackage(fullDir, includeList, excludeList,
324           defaultExcludes, caseSensitive);
325     }
326
327     private void addSourcePackage(String JavaDoc parentDir, String JavaDoc relDir,
328         boolean isSuperSource) {
329       String JavaDoc normChildDir = normalizePathEntry(relDir);
330       if (normChildDir.startsWith("/")) {
331         logger.log(TreeLogger.WARN, "Non-relative source package: "
332             + normChildDir, null);
333         return;
334       }
335       if (normChildDir.startsWith("./") || normChildDir.indexOf("/./") >= 0) {
336         logger.log(TreeLogger.WARN, "Non-canonical source package: "
337             + normChildDir, null);
338         return;
339       }
340       if (normChildDir.startsWith("../") || normChildDir.indexOf("/../") >= 0) {
341         logger.log(TreeLogger.WARN, "Non-canonical source package: "
342             + normChildDir, null);
343         return;
344       }
345
346       String JavaDoc fullDir = parentDir + normChildDir;
347       if (isSuperSource) {
348         moduleDef.addSuperSourcePackage(fullDir);
349       } else {
350         moduleDef.addSourcePackage(fullDir);
351       }
352     }
353
354     /**
355      * Normalizes a path entry such that it does not start with but does end
356      * with '/'.
357      */

358     private String JavaDoc normalizePathEntry(String JavaDoc path) {
359       path = path.trim();
360
361       if (path.length() == 0) {
362         return "";
363       }
364
365       path = path.replace('\\', '/');
366
367       if (!path.endsWith("/")) {
368         path += "/";
369       }
370
371       return path;
372     }
373   }
374
375   private final class ConditionSchema extends Schema {
376
377     protected final String JavaDoc __when_property_is_1_name = null;
378
379     protected final String JavaDoc __when_property_is_2_value = null;
380
381     protected final String JavaDoc __when_type_assignable_1_class = null;
382
383     protected final String JavaDoc __when_type_is_1_class = null;
384
385     private final CompoundCondition parentCondition;
386
387     public ConditionSchema(CompoundCondition parentCondition) {
388       this.parentCondition = parentCondition;
389     }
390
391     protected Schema __all_begin() {
392       CompoundCondition cond = new ConditionAll();
393       parentCondition.getConditions().add(cond);
394       return new ConditionSchema(cond);
395     }
396
397     protected Schema __any_begin() {
398       CompoundCondition cond = new ConditionAny();
399       parentCondition.getConditions().add(cond);
400       return new ConditionSchema(cond);
401     }
402
403     protected Schema __none_begin() {
404       CompoundCondition cond = new ConditionNone();
405       parentCondition.getConditions().add(cond);
406       return new ConditionSchema(cond);
407     }
408
409     // We intentionally use the Property type here for tough-love on module
410
// writers. It prevents them from trying to create property providers for
411
// unknown properties.
412
//
413
protected Schema __when_property_is_begin(Property prop, PropertyValue value) {
414       Condition cond = new ConditionWhenPropertyIs(prop.getName(), value.token);
415       parentCondition.getConditions().add(cond);
416
417       // No children allowed.
418
return null;
419     }
420
421     protected Schema __when_type_assignable_begin(String JavaDoc className) {
422       Condition cond = new ConditionWhenTypeAssignableTo(className);
423       parentCondition.getConditions().add(cond);
424
425       // No children allowed.
426
return null;
427     }
428
429     protected Schema __when_type_is_begin(String JavaDoc className) {
430       Condition cond = new ConditionWhenTypeIs(className);
431       parentCondition.getConditions().add(cond);
432
433       // No children allowed.
434
return null;
435     }
436   }
437
438   private final class IncludeExcludeSchema extends Schema {
439
440     protected final String JavaDoc __exclude_1_name = null;
441
442     protected final String JavaDoc __include_1_name = null;
443
444     private final Set JavaDoc excludes = new HashSet JavaDoc();
445
446     private final Set JavaDoc includes = new HashSet JavaDoc();
447
448     public Set JavaDoc getExcludes() {
449       return excludes;
450     }
451
452     public Set JavaDoc getIncludes() {
453       return includes;
454     }
455
456     protected Schema __exclude_begin(String JavaDoc name) {
457       excludes.add(name);
458       return null;
459     }
460
461     protected Schema __include_begin(String JavaDoc name) {
462       includes.add(name);
463       return null;
464     }
465   }
466
467   /**
468    * Creates singleton instances of objects based on an attribute containing a
469    * class name.
470    */

471   private final class ObjAttrCvt extends AttributeConverter {
472
473     private final Class JavaDoc fReqdSuperclass;
474
475     public ObjAttrCvt(Class JavaDoc reqdSuperclass) {
476       fReqdSuperclass = reqdSuperclass;
477     }
478
479     public Object JavaDoc convertToArg(Schema schema, int lineNumber, String JavaDoc elemName,
480         String JavaDoc attrName, String JavaDoc attrValue) throws UnableToCompleteException {
481
482       Object JavaDoc found = singletonsByName.get(attrValue);
483       if (found != null) {
484         // Found in the cache.
485
//
486
return found;
487       }
488
489       try {
490         // Load the class.
491
//
492
ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
493         Class JavaDoc clazz = cl.loadClass(attrValue);
494
495         // Make sure it's compatible.
496
//
497
if (!fReqdSuperclass.isAssignableFrom(clazz)) {
498           Messages.INVALID_CLASS_DERIVATION.log(logger, clazz, fReqdSuperclass,
499               null);
500           throw new UnableToCompleteException();
501         }
502
503         Object JavaDoc object = clazz.newInstance();
504         singletonsByName.put(attrValue, object);
505         return object;
506       } catch (ClassNotFoundException JavaDoc e) {
507         Messages.UNABLE_TO_LOAD_CLASS.log(logger, attrValue, e);
508         throw new UnableToCompleteException();
509       } catch (InstantiationException JavaDoc e) {
510         Messages.UNABLE_TO_CREATE_OBJECT.log(logger, attrValue, e);
511         throw new UnableToCompleteException();
512       } catch (IllegalAccessException JavaDoc e) {
513         Messages.UNABLE_TO_CREATE_OBJECT.log(logger, attrValue, e);
514         throw new UnableToCompleteException();
515       }
516     }
517   }
518
519   /**
520    * Converts property names into their corresponding property objects.
521    */

522   private final class PropertyAttrCvt extends AttributeConverter {
523     public Object JavaDoc convertToArg(Schema schema, int line, String JavaDoc elem,
524         String JavaDoc attr, String JavaDoc value) throws UnableToCompleteException {
525       // Find the named property.
526
//
527
Property prop = moduleDef.getProperties().find(value);
528
529       if (prop != null) {
530         // Found it.
531
//
532
return prop;
533       } else {
534         // Property not defined. This is a problem.
535
//
536
Messages.PROPERTY_NOT_FOUND.log(logger, value, null);
537         throw new UnableToCompleteException();
538       }
539     }
540   }
541
542   private static class PropertyName {
543     public final String JavaDoc token;
544
545     public PropertyName(String JavaDoc token) {
546       this.token = token;
547     }
548   }
549
550   /**
551    * Converts a string into a property name, validating it in the process.
552    */

553   private final class PropertyNameAttrCvt extends AttributeConverter {
554
555     public Object JavaDoc convertToArg(Schema schema, int line, String JavaDoc elem,
556         String JavaDoc attr, String JavaDoc value) throws UnableToCompleteException {
557       // Ensure each part of the name is valid.
558
//
559
String JavaDoc[] tokens = (value + ". ").split("\\.");
560       for (int i = 0; i < tokens.length - 1; i++) {
561         String JavaDoc token = tokens[i];
562         if (!Util.isValidJavaIdent(token)) {
563           Messages.PROPERTY_NAME_INVALID.log(logger, value, null);
564           throw new UnableToCompleteException();
565         }
566       }
567
568       // It is a valid name.
569
//
570
return new PropertyName(value);
571     }
572   }
573
574   private class PropertyProviderBodySchema extends Schema {
575
576     private StringBuffer JavaDoc script;
577
578     private int startLineNumber = -1;
579
580     public PropertyProviderBodySchema() {
581     }
582
583     public void __text(String JavaDoc text) {
584       if (script == null) {
585         script = new StringBuffer JavaDoc();
586         startLineNumber = getLineNumber();
587       }
588       script.append(text);
589     }
590
591     public String JavaDoc getScript() {
592       return script != null ? script.toString() : null;
593     }
594
595     public int getStartLineNumber() {
596       return startLineNumber;
597     }
598   }
599
600   private static class PropertyValue {
601     public final String JavaDoc token;
602
603     public PropertyValue(String JavaDoc token) {
604       this.token = token;
605     }
606   }
607
608   /**
609    * Converts a comma-separated string into an array of property value tokens.
610    */

611   private final class PropertyValueArrayAttrCvt extends AttributeConverter {
612     public Object JavaDoc convertToArg(Schema schema, int line, String JavaDoc elem,
613         String JavaDoc attr, String JavaDoc value) throws UnableToCompleteException {
614       String JavaDoc[] tokens = value.split(",");
615       PropertyValue[] values = new PropertyValue[tokens.length];
616
617       // Validate each token as we copy it over.
618
//
619
for (int i = 0; i < tokens.length; i++) {
620         values[i] = (PropertyValue) propValueAttrCvt.convertToArg(schema, line,
621             elem, attr, tokens[i]);
622       }
623
624       return values;
625     }
626   }
627
628   /**
629    * Converts a string into a property value, validating it in the process.
630    */

631   private final class PropertyValueAttrCvt extends AttributeConverter {
632     public Object JavaDoc convertToArg(Schema schema, int line, String JavaDoc elem,
633         String JavaDoc attr, String JavaDoc value) throws UnableToCompleteException {
634
635       String JavaDoc token = value.trim();
636       if (Util.isValidJavaIdent(token)) {
637         return new PropertyValue(token);
638       } else {
639         Messages.PROPERTY_VALUE_INVALID.log(logger, token, null);
640         throw new UnableToCompleteException();
641       }
642     }
643   }
644
645   private class ScriptReadyBodySchema extends Schema {
646
647     private StringBuffer JavaDoc script;
648
649     private int startLineNumber = -1;
650
651     public ScriptReadyBodySchema() {
652     }
653
654     public void __text(String JavaDoc text) {
655       if (script == null) {
656         script = new StringBuffer JavaDoc();
657         startLineNumber = getLineNumber();
658       }
659       script.append(text);
660     }
661
662     public String JavaDoc getScriptReadyBlock() {
663       return script != null ? script.toString() : null;
664     }
665
666     public int getStartLineNumber() {
667       return startLineNumber;
668     }
669   }
670
671   private static final Map JavaDoc singletonsByName = new HashMap JavaDoc();
672
673   private final BodySchema bodySchema;
674
675   private boolean foundAnyPublic;
676
677   private boolean foundExplicitSourceOrSuperSource;
678
679   private final ObjAttrCvt genAttrCvt = new ObjAttrCvt(Generator.class);
680
681   private final JsParser jsParser = new JsParser();
682   private final JsProgram jsPgm = new JsProgram();
683   private final ModuleDefLoader loader;
684   private final TreeLogger logger;
685   private final ModuleDef moduleDef;
686   private final String JavaDoc modulePackageAsPath;
687   private final URL JavaDoc moduleURL;
688   private final PropertyAttrCvt propAttrCvt = new PropertyAttrCvt();
689   private final PropertyNameAttrCvt propNameAttrCvt = new PropertyNameAttrCvt();
690   private final PropertyValueArrayAttrCvt propValueArrayAttrCvt = new PropertyValueArrayAttrCvt();
691   private final PropertyValueAttrCvt propValueAttrCvt = new PropertyValueAttrCvt();
692
693   public ModuleDefSchema(TreeLogger logger, ModuleDefLoader loader,
694       URL JavaDoc moduleURL, String JavaDoc modulePackageAsPath, ModuleDef toConfigure) {
695     this.logger = logger;
696     this.loader = loader;
697     this.moduleURL = moduleURL;
698     this.modulePackageAsPath = modulePackageAsPath;
699     assert (modulePackageAsPath.endsWith("/") || modulePackageAsPath.equals(""));
700     this.moduleDef = toConfigure;
701     this.bodySchema = new BodySchema();
702
703     registerAttributeConverter(PropertyName.class, propNameAttrCvt);
704     registerAttributeConverter(Property.class, propAttrCvt);
705     registerAttributeConverter(PropertyValue.class, propValueAttrCvt);
706     registerAttributeConverter(PropertyValue[].class, propValueArrayAttrCvt);
707     registerAttributeConverter(Generator.class, genAttrCvt);
708   }
709
710   protected Schema __module_begin() {
711     return bodySchema;
712   }
713
714   protected void __module_end() {
715     // Maybe infer source and public.
716
//
717
if (!foundExplicitSourceOrSuperSource) {
718       bodySchema.addSourcePackage(modulePackageAsPath, "client", false);
719     }
720
721     if (!foundAnyPublic) {
722       bodySchema.addPublicPackage(modulePackageAsPath, "public", Empty.STRINGS,
723           Empty.STRINGS, true, true);
724     }
725   }
726
727   /**
728    * Parses handwritten JavaScript found in the module xml, logging an error
729    * message and throwing an exception if there's a problem.
730    *
731    * @param startLineNumber the start line number where the script was found;
732    * used to report errors
733    * @param script the JavaScript to wrap in "function() { script }" to parse
734    * @return the parsed function
735    * @throws UnableToCompleteException
736    */

737   private JsFunction parseJsBlock(int startLineNumber, String JavaDoc script)
738       throws UnableToCompleteException {
739     script = "function() { " + script + "}";
740     StringReader JavaDoc r = new StringReader JavaDoc(script);
741     JsStatements stmts;
742     try {
743       stmts = jsParser.parse(jsPgm.getScope(), r, startLineNumber);
744     } catch (IOException JavaDoc e) {
745       logger.log(TreeLogger.ERROR, "Error reading script source", e);
746       throw new UnableToCompleteException();
747     } catch (JsParserException e) {
748       SourceDetail dtl = e.getSourceDetail();
749       if (dtl != null) {
750         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
751         sb.append(moduleURL.toExternalForm());
752         sb.append("(");
753         sb.append(dtl.getLine());
754         sb.append(", ");
755         sb.append(dtl.getLineOffset());
756         sb.append("): ");
757         sb.append(e.getMessage());
758         logger.log(TreeLogger.ERROR, sb.toString(), e);
759       } else {
760         logger.log(TreeLogger.ERROR, "Error parsing JavaScript source", e);
761       }
762       throw new UnableToCompleteException();
763     }
764
765     // Rip the body out of the parsed function and attach the JavaScript
766
// AST to the method.
767
//
768
JsFunction fn = (JsFunction) ((JsExprStmt) stmts.get(0)).getExpression();
769     return fn;
770   }
771
772 }
773 // CHECKSTYLE_NAMING_ON
774
Popular Tags