Ticket #2696: build.patch

File build.patch, 76.2 kB (added by guest, 20 months ago)
  • build.xml

     
    3030        <property name="lang" value="en"/> 
    3131        <property name="releaseName" value="${project}"/> 
    3232        <property name="dojoLoader" value="default"/> 
     33        <property name="source_dir" location="${root}"/> 
    3334        <property name="release_dir" location="${root}/release/${releaseName}"/> 
    3435        <property name="docs_dir" value="${root}/documents"/> 
    3536        <property name="articles_dir" value="${docs_dir}/articles"/> 
     
    595596                        <param name="dstFile" value="${release_dir}/dojo.js" /> 
    596597                </antcall> 
    597598 
    598                 <!-- add build notice --> 
    599                 <replaceregexp match="^" byline="false" replace="${build_notice}"> 
    600                         <fileset dir="${release_dir}" includes="dojo.js"/> 
    601                 </replaceregexp> 
    602  
    603                 <!-- add copyright notice --> 
    604                 <replaceregexp match="^" byline="false" replace="${copyright}"> 
    605                         <fileset dir="${release_dir}"> 
    606                                 <include name="**/*.js" /> 
    607                                 <include name="**/*.as" /> 
    608                                 <not> 
    609                                         <contains text="copyright" casesensitive="no"  /> 
    610                                 </not> 
    611                         </fileset> 
    612                 </replaceregexp> 
    613  
    614599                <delete file="${release_dir}/source.__package__.js"/> 
    615600 
    616601                <!-- we copy over iframe_history.html here just in case this is a truly 
    617602                stand-alone build that isn't being kicked off via release --> 
    618603                <copy file="../iframe_history.html" todir="${release_dir}/" /> 
    619604 
    620                 <!-- copy our dojo.storage and dojo.flash SWFs --> 
     605                <!-- copy our dojo.storage and dojo.flash SWFs 
    621606                <copy todir="${release_dir}/" preservelastmodified="true"> 
    622607                        <fileset dir="${root}/"> 
    623608                                <include name="**/*.swf" /> 
    624609                                <include name="*.jar" /> 
    625610                        </fileset> 
    626                 </copy> 
     611                </copy> --> 
    627612 
    628613        </target> 
    629614        <!-- end compress task --> 
     
    691676                        <arg value="${profileFile}" /> 
    692677                        <arg value="${dojoLoader}" /> 
    693678                        <arg value="${release_dir}" /> 
     679                        <arg value="${source_dir}" /> 
    694680                </java> 
    695681        </target> 
    696682        <!-- end intern-strings task --> 
     
    769755                <antcall target="compress" /> 
    770756                <!-- <antcall target="intern-strings" /> --> 
    771757 
     758                <!-- add build notice --> 
     759                <replaceregexp match="^" byline="false" replace="${build_notice}"> 
     760                        <fileset dir="${release_dir}" includes="dojo.js"/> 
     761                </replaceregexp> 
     762 
     763                <!-- add copyright notice --> 
     764                <replaceregexp match="^" byline="false" replace="${copyright}"> 
     765                        <fileset dir="${release_dir}"> 
     766                                <include name="**/*.js" /> 
     767                                <include name="**/*.as" /> 
     768                                <not> 
     769                                        <contains text="copyright" casesensitive="no"  /> 
     770                                </not> 
     771                        </fileset> 
     772                </replaceregexp> 
     773 
    772774                <!-- Run xdgen if it xdomain loading is wanted. --> 
    773775                <condition property="xdgenRun"> 
    774776                        <equals arg1="xdomain" arg2="${dojoLoader}"/> 
     
    782784        </target> 
    783785        <!-- end release task --> 
    784786 
     787        <!-- minimal task --> 
     788        <target name="minimal" depends="-fix-config" 
     789                description="builds a minimal release"> 
     790 
     791                <echo level="info" taskName="minimal" message="Using version number: ${version} for the release."/> 
     792 
     793                <antcall target="clean" /> 
     794 
     795                <antcall target="compress" /> 
     796                 
     797                <antcall target="copyRessources" /> 
     798                 
     799                <!-- TODO, find simple heuristic to determine if intern-strings will help performance - load time vs. widget creation speed      
     800                        And go deeper, split into: internCSS and internHTML and benchmark results--> 
     801                 <antcall target="intern-strings" /> 
     802 
     803                <!-- TODO, improve performance here --> 
     804                <replaceregexp file="${release_dir}/dojo.js" match="(;\n)" replace="\1___GOODNEWLINE___" flags="g"/> 
     805                <replaceregexp file="${release_dir}/dojo.js" match="\n" replace="" flags="g"/> 
     806                <replaceregexp file="${release_dir}/dojo.js" match="(.{300}___GOODNEWLINE___)" replace="\1&#010;" flags="g"/> 
     807                <replaceregexp file="${release_dir}/dojo.js" match="___GOODNEWLINE___" replace="" flags="g"/> 
     808                 
     809                <!-- add copyright notice --> 
     810                <replaceregexp match="^" byline="false" replace="${copyright}"> 
     811                        <fileset dir="${release_dir}" includes="dojo.js" /> 
     812                </replaceregexp> 
     813                 
     814                <!-- add build notice --> 
     815                <replaceregexp match="^" byline="false" replace="${build_notice}"> 
     816                        <fileset dir="${release_dir}" includes="dojo.js"/> 
     817                </replaceregexp> 
     818                 
     819                <!-- Run xdgen if it xdomain loading is wanted. --> 
     820                <condition property="xdgenRun"> 
     821                        <equals arg1="xdomain" arg2="${dojoLoader}"/> 
     822                </condition> 
     823                <antcall target="xdgenRelease"/> 
     824 
     825                <!-- Remove uncompressed version --> 
     826                <delete file="${release_dir}/dojo.js.uncompressed.js"/> 
     827 
     828                <copy file="${root}/LICENSE" todir="${release_dir}/"  preservelastmodified="true" /> 
     829        </target> 
     830        <!-- end minimal task --> 
     831 
     832        <target name="copyRessources" depends="-fix-config, -set-profileFile" description="Copies appropriate HTML, CSS and images ressources"> 
     833                 
     834                <java jar="./lib/custom_rhino.jar" failonerror="true" fork="true" 
     835                        logError="true"> 
     836                        <arg value="copyRessources.js" /> 
     837                        <arg value="${release_dir}/dojo.js" /> 
     838                        <arg value="${source_dir}" /> 
     839                        <sysproperty key="DOJO_LOADER" value="${dojoLoader}" /> 
     840                </java> 
     841                 
     842        </target> 
     843 
    785844        <target name="api-prep" 
    786845                description="Constructs API outlines"> 
    787846                <copy todir="${release_dir}/apis" includeEmptyDirs="false" preservelastmodified="true"> 
  • buildUtil.js

     
    1 var buildUtil = {}; 
    2  
    3 buildUtil.getLineSeparator = function(){ 
    4         //summary: Gives the line separator for the platform. 
    5         //For web builds override this function. 
    6         return java.lang.System.getProperty("line.separator"); 
    7 } 
    8  
    9 buildUtil.getDojoLoader = function(/*Object?*/dependencies){ 
    10         //summary: gets the type of Dojo loader for the build. For example default or 
    11         //xdomain loading. Override for web builds. 
    12         return (dependencies && dependencies["loader"] ? dependencies["loader"] : java.lang.System.getProperty("DOJO_LOADER")); 
    13 } 
    14  
    15 buildUtil.getDependencyList = function(/*Object*/dependencies, /*String or Array*/hostenvType, /*boolean?*/isWebBuild){ 
    16         if(!isWebBuild){ 
    17                 djConfig = { 
    18                         baseRelativePath: "../" 
    19                         // isDebug: true 
    20                 }; 
    21         } 
    22  
    23         if(!dependencies){ 
    24                 dependencies = [  
    25                         "dojo.event.*", 
    26                         "dojo.io.*", 
    27                         "dojo.string", 
    28                         "dojo.xml.*", 
    29                         "dojo.xml.Parse", 
    30                         "dojo.widget.Parse", 
    31                         "dojo.widget.Button" 
    32                 ]; 
    33         } 
    34          
    35         var dojoLoader = buildUtil.getDojoLoader(dependencies); 
    36         if(!dojoLoader || dojoLoader=="null" || dojoLoader==""){ 
    37                 dojoLoader = "default"; 
    38         } 
    39  
    40         if(!isWebBuild){ 
    41                 dj_global = {}; 
    42                  
    43                 load("../src/bootstrap1.js"); 
    44                 load("../src/loader.js"); 
    45                 load("../src/hostenv_rhino.js"); 
    46          
    47                 // FIXME: is this really what we want to say? 
    48                 dojo.render.html.capable = true; 
    49         } 
    50  
    51         dojo.hostenv.loadedUris.push("dojoGuardStart.js"); 
    52         dojo.hostenv.loadedUris.push("../src/bootstrap1.js"); 
    53          
    54         if(dojoLoader == "default"){ 
    55                 dojo.hostenv.loadedUris.push("../src/loader.js"); 
    56         }else if(dojoLoader=="xdomain"){ 
    57                 dojo.hostenv.loadedUris.push("../src/loader.js"); 
    58                 dojo.hostenv.loadedUris.push("../src/loader_xd.js"); 
    59         } 
    60         dojo.hostenv.loadedUris.push("dojoGuardEnd.js"); 
    61          
    62         if(!hostenvType){ 
    63                 hostenvType = "browser"; 
    64         } 
    65          
    66         if(hostenvType.constructor == Array){ 
    67                 for(var x=0; x<hostenvType.length; x++){ 
    68                         dojo.hostenv.loadedUris.push("../src/hostenv_"+hostenvType[x]+".js"); 
    69                 } 
    70                 hostenvType = hostenvType.pop(); 
    71         }else{ 
    72                 dojo.hostenv.loadedUris.push("../src/hostenv_"+hostenvType+".js"); 
    73         } 
    74          
    75         if(dependencies["prefixes"]){ 
    76                 var tmp = dependencies.prefixes; 
    77                 for(var x=0; x<tmp.length; x++){ 
    78                         dojo.registerModulePath(tmp[x][0], tmp[x][1]); 
    79                 } 
    80         } 
    81          
    82         dojo.hostenv.name_ = hostenvType; 
    83          
    84         //Override dojo.provide to get a list of resource providers. 
    85         var provideList = []; 
    86         dojo._provide = dojo.provide; 
    87         dojo.provide = function(resourceName){ 
    88                 provideList.push(resourceName); 
    89                 dojo._provide(resourceName); 
    90         } 
    91          
    92         function removeComments(contents){ 
    93                 // if we get the contents of the file from Rhino, it might not be a JS 
    94                 // string, but rather a Java string, which will cause the replace() method 
    95                 // to bomb. 
    96                 contents = new String((!contents) ? "" : contents); 
    97                 // clobber all comments 
    98                 contents = contents.replace( /^(.*?)\/\/(.*)$/mg , "$1"); 
    99                 contents = contents.replace( /(\n)/mg , "__DOJONEWLINE"); 
    100                 contents = contents.replace( /\/\*(.*?)\*\//g , ""); 
    101                 return contents.replace( /__DOJONEWLINE/mg , "\n"); 
    102         } 
    103          
    104         // over-write dj_eval to prevent actual loading of subsequent files 
    105         var old_eval = dj_eval; 
    106         dj_eval = function(){ return true; } 
    107         var old_load = load; 
    108         load = function(uri){ 
    109                 try{ 
    110                         var text = removeComments((isWebBuild ? dojo.hostenv.getText(uri) : readText(uri))); 
    111                         var requires = dojo.hostenv.getRequiresAndProvides(text); 
    112                         eval(requires.join(";")); 
    113                         dojo.hostenv.loadedUris.push(uri); 
    114                         dojo.hostenv.loadedUris[uri] = true; 
    115                         var delayRequires = dojo.hostenv.getDelayRequiresAndProvides(text); 
    116                         eval(delayRequires.join(";")); 
    117                 }catch(e){ 
    118                         if(isWebBuild){ 
    119                                 dojo.debug("error loading uri: " + uri + ", exception: " + e); 
    120                         }else{ 
    121                                 java.lang.System.err.println("error loading uri: " + uri + ", exception: " + e); 
    122                                 quit(-1); 
    123                         } 
    124                 } 
    125                 return true; 
    126         } 
    127          
    128         if(isWebBuild){ 
    129                 dojo.hostenv.oldLoadUri = dojo.hostenv.loadUri; 
    130                 dojo.hostenv.loadUri = load; 
    131         } 
    132          
    133         dojo.hostenv.getRequiresAndProvides = function(contents){ 
    134                 // FIXME: should probably memoize this! 
    135                 if(!contents){ return []; } 
    136          
    137                 // check to see if we need to load anything else first. Ugg. 
    138                 var deps = []; 
    139                 var tmp; 
    140                 RegExp.lastIndex = 0; 
    141                 var testExp = /dojo.(hostenv.loadModule|hostenv.require|require|kwCompoundRequire|hostenv.conditionalLoadModule|hostenv.startPackage|provide)\([\w\W]*?\)/mg; 
    142                 while((tmp = testExp.exec(contents)) != null){ 
    143                         deps.push(tmp[0]); 
    144                 } 
    145                 return deps; 
    146         } 
    147          
    148         dojo.hostenv.getDelayRequiresAndProvides = function(contents){ 
    149                 // FIXME: should probably memoize this! 
    150                 if(!contents){ return []; } 
    151          
    152                 // check to see if we need to load anything else first. Ugg. 
    153                 var deps = []; 
    154                 var tmp; 
    155                 RegExp.lastIndex = 0; 
    156                 var testExp = /dojo.(requireAfterIf|requireIf)\([\w\W]*?\)/mg; 
    157                 while((tmp = testExp.exec(contents)) != null){ 
    158                         deps.push(tmp[0]); 
    159                 } 
    160                 return deps; 
    161         } 
    162  
    163         if(dependencies["dojoLoaded"]){ 
    164                 dependencies["dojoLoaded"](); 
    165         } 
    166          
    167         for(var x=0; x<dependencies.length; x++){ 
    168                 try{ 
    169                         var dep = dependencies[x]; 
    170                         if(dep.indexOf("(") != -1){ 
    171                                 dep = dojo.hostenv.getDepsForEval(dep)[0]; 
    172                         } 
    173                         //Don't process loader_xd.js since it has some regexps  
    174                         //and mentions of dojo.require/provide, which will cause  
    175                         //havoc in the dojo.hostenv.loadModule() method. 
    176                         if(dep.indexOf("loader_xd.js") == -1){ 
    177                                 dojo.hostenv.loadModule(dep, null, true); 
    178                         } 
    179                 }catch(e){ 
    180                         java.lang.System.err.println("Error loading module!" + e); 
    181                         quit(-1); 
    182                 } 
    183         } 
    184          
    185         // FIXME: we should also provide some way of figuring out what files are the 
    186         // test files for the namespaces which are included and provide them in the 
    187         // final package. 
    188          
    189         // FIXME: should we turn __package__.js file clobbering on? It will break things if there's a subdir rolled up into a __package__ 
    190         /* 
    191         for(var x=0; x<dojo.hostenv.loadedUris.length; x++){ 
    192                 print(dojo.hostenv.loadedUris[x].substr(-14)); 
    193                 if(dojo.hostenv.loadedUris[x].substr(-14) == "__package__.js"){ 
    194                         dojo.hostenv.loadedUris.splice(x, 1); 
    195                         x--; 
    196                 } 
    197         } 
    198         */ 
    199          
    200         // print("URIs, in order: "); 
    201         // for(var x=0; x<dojo.hostenv.loadedUris.length; x++){ 
    202         //      print(dojo.hostenv.loadedUris[x]); 
    203         // } 
    204          
    205         var depList = []; 
    206         var seen = {}; 
    207         uris: for(var x=0; x<dojo.hostenv.loadedUris.length; x++){ 
    208                 var curi = dojo.hostenv.loadedUris[x]; 
    209                 if(!seen[curi]){ 
    210                         seen[curi] = true; 
    211                         if(dependencies["filters"]){ 
    212                                 for(var i in dependencies.filters){ 
    213                                         if(curi.match(dependencies.filters[i])){ 
    214                                                 continue uris; 
    215                                         }}} 
    216                         depList.push(curi); 
    217                 } 
    218         } 
    219          
    220         if(isWebBuild){ 
    221                 dojo.hostenv.loadUri = dojo.hostenv.oldLoadUri; 
    222         }else{ 
    223                 load = old_load; // restore the original load function 
    224                 dj_eval = old_eval; // restore the original dj_eval function 
    225  
    226                 dj_global['dojo'] = undefined; 
    227                 dj_global['djConfig'] = undefined; 
    228                 delete dj_global; 
    229         } 
    230  
    231         return { 
    232                 depList: depList, 
    233                 provideList: provideList 
    234         }; 
    235 } 
    236  
    237 buildUtil.loadDependencyList = function(/*String*/profileFile){ 
    238         var dependencies = null; 
    239         var hostenvType = null; 
    240         var profileText = new String(buildUtil.readFile(profileFile)); 
    241          
    242         //Remove the call to getDependencyList.js because we want to call it manually. 
    243         profileText = profileText.replace(/load\(("|')getDependencyList.js("|')\)/, ""); 
    244         eval(profileText); 
    245         if(hostenvType){ 
    246                 hostenvType.join(",\n"); 
    247         } 
    248         var depResult = buildUtil.getDependencyList(dependencies, hostenvType); 
    249         depResult.dependencies = dependencies; 
    250          
    251         return depResult; 
    252 } 
    253  
    254 buildUtil.makeDojoJs = function(/*Object*/dependencyResult, /*String*/version){ 
    255         //summary: Makes the uncompressed contents for dojo.js using the object 
    256         //returned from buildUtil.getDependencyList() 
    257  
    258         var lineSeparator = buildUtil.getLineSeparator(); 
    259         var depList = dependencyResult.depList; 
    260  
    261         //Concat the files together, and mark where we should insert all the 
    262         //provide statements. 
    263         var dojoContents = ""; 
    264         for(var i = 0; i < depList.length; i++){ 
    265                 //Make sure we have a JS string and not a Java string by using new String(). 
    266                 dojoContents += new String(buildUtil.readFile(depList[i])) + "\r\n"; 
    267         } 
    268          
    269         // dojo.requireLocalization is a special case as it pulls in dojo.i18n.loader at runtime 
    270         if(dojoContents.match(buildUtil.globalRequireLocalizationRegExp)){ 
    271                 depList.push("../src/i18n/loader.js"); 
    272                 dojoContents += new String(readFile(depList[depList.length-1])); 
    273         } 
    274  
    275         //Construct a string of all the dojo.provide statements. 
    276         //This string will be used to construct the regexp that will be 
    277         //used to remove matching dojo.require statements. 
    278         //Sort the provide list alphabetically to make it easy to read. 
    279         //Order of provide statements do not matter. 
    280         var provideList = dependencyResult.provideList.sort();  
    281         var depRegExpString = ""; 
    282         for(var i = 0; i < provideList.length; i++){ 
    283                 if(i != 0){ 
    284                         depRegExpString += "|"; 
    285                 } 
    286                 depRegExpString += '("' + provideList[i] + '")'; 
    287         } 
    288                  
    289         //If we have a string for a regexp, do the dojo.require() removal now. 
    290         if(depRegExpString){ 
    291                 var depRegExp = new RegExp("dojo\\.(require)\\((" + depRegExpString + ")\\)(;?)", "g"); 
    292                 dojoContents = dojoContents.replace(depRegExp, ""); 
    293         } 
    294  
    295         //Set version number. 
    296         //First, break apart the version string. 
    297         var verSegments = version.split("."); 
    298         var majorValue = 0; 
    299         var minorValue = 0; 
    300         var patchValue = 0; 
    301         var flagValue = ""; 
    302          
    303         if(verSegments.length > 0 && verSegments[0]){ 
    304                 majorValue = verSegments[0]; 
    305         } 
    306         if(verSegments.length > 1 && verSegments[1]){ 
    307                 minorValue = verSegments[1]; 
    308         } 
    309         if(verSegments.length > 2 && verSegments[2]){ 
    310                 //If the patchValue has a string in it, split 
    311                 //it off and store it in the flagValue. 
    312                 var patchSegments = verSegments[2].split(/\D/); 
    313                 patchValue = patchSegments[0]; 
    314                 if(patchSegments.length > 1){ 
    315                         flagValue = verSegments[2].substring(patchValue.length, verSegments[2].length); 
    316                 } 
    317         } 
    318         if(verSegments.length > 3 && verSegments[3]){ 
    319                 flagValue = verSegments[3]; 
    320         } 
    321          
    322         //Do the final version replacement. 
    323         dojoContents = dojoContents.replace( 
    324                 /major:\s*\d*,\s*minor:\s*\d*,\s*patch:\s*\d*,\s*flag:\s*".*?"\s*,/g, 
    325                 "major: " + majorValue + ", minor: " + minorValue + ", patch: " + patchValue + ", flag: \"" + flagValue + "\"," 
    326         ); 
    327          
    328         //Return the dependency list, since it is used for other things in the ant file. 
    329         return { 
    330                 resourceDependencies: depList, 
    331                 dojoContents: dojoContents 
    332         }; 
    333  
    334         //Things to consider for later: 
    335  
    336         //preload resources? 
    337         //Remove requireLocalization calls? 
    338          
    339         //compress (or minify?) 
    340         //Name changes to dojo.js here 
    341          
    342         //no compress if nostrip = true 
    343         //Name changes to dojo.js here 
    344          
    345         //Add build notice 
    346          
    347         //Add copyright notice 
    348          
    349         //Remove ${release_dir}/source.__package__.js 
    350 } 
    351  
    352  
    353 buildUtil.getDependencyPropertyFromProfile = function(/*String*/profileFile, /*String*/propName){ 
    354         //summary: Gets a dependencies property from the profile file. The value 
    355         //of the property is assumed to be an array. An array will always be returned, 
    356         //but it may be an empty array. 
    357  
    358         //Use new String to make sure we have a JS string (not a Java string) 
    359         //readText is from hostenv_rhino.js, so be sure to load Dojo before calling this function. 
    360         var profileText = new String(readText(profileFile)); 
    361         //Get rid of CR and LFs since they seem to mess with the regexp match. 
    362         //Using the "m" option on the regexp was not enough. 
    363         profileText = profileText.replace(/\r/g, ""); 
    364         profileText = profileText.replace(/\n/g, ""); 
    365  
    366  
    367         var result = []; 
    368         var matchRegExp = new RegExp("(dependencies\\." + propName + "\\s*=\\s*\\[[^;]*\\s*\\])", "m"); 
    369  
    370         var matches = profileText.match(matchRegExp); 
    371         //Create a shell object to hold the evaled properties. 
    372         var dependencies = {}; 
    373          
    374         if(matches && matches.length > 0){ 
    375                 eval(matches[0]); 
    376                 if(dependencies && dependencies[propName] && dependencies[propName].length > 0){ 
    377                         result = dependencies[propName]; 
    378                 } 
    379         } 
    380  
    381         return result; //Array 
    382 } 
    383  
    384 buildUtil.configPrefixes = function(profileFile){ 
    385         //summary: Get the resource prefixes from the profile and registers the prefixes with Dojo. 
    386         var prefixes = this.getDependencyPropertyFromProfile(profileFile, "prefixes"); 
    387         if(prefixes && prefixes.length > 0){ 
    388                 for(i = 0; i < prefixes.length; i++){ 
    389                         dojo.registerModulePath(prefixes[i][0], prefixes[i][1]); 
    390                 } 
    391         } 
    392         return prefixes; //Array of arrays 
    393 } 
    394  
    395 //The regular expressions that will help find dependencies in the file contents. 
    396 buildUtil.masterDependencyRegExpString = "dojo.(requireLocalization|require|requireIf|requireAll|provide|requireAfterIf|requireAfter|kwCompoundRequire|conditionalRequire|hostenv\\.conditionalLoadModule|.hostenv\\.loadModule|hostenv\\.moduleLoaded)\\(([\\w\\W]*?)\\)"; 
    397 buildUtil.globalDependencyRegExp = new RegExp(buildUtil.masterDependencyRegExpString, "mg"); 
    398 buildUtil.dependencyPartsRegExp = new RegExp(buildUtil.masterDependencyRegExpString); 
    399  
    400 buildUtil.masterRequireLocalizationRegExpString = "dojo.(requireLocalization)\\(([\\w\\W]*?)\\)"; 
    401 buildUtil.globalRequireLocalizationRegExp = new RegExp(buildUtil.masterRequireLocalizationRegExpString, "mg"); 
    402 buildUtil.requireLocalizationRegExp = new RegExp(buildUtil.masterRequireLocalizationRegExpString); 
    403  
    404 buildUtil.modifyRequireLocalization = function(fileContents, baseRelativePath, prefixes){ 
    405         //summary: Modifies any dojo.requireLocalization calls in the fileContents to have the 
    406         //list of supported locales as part of the call. This allows the i18n loading functions 
    407         //to only make request(s) for locales that actually exist on disk. 
    408         var dependencies = []; 
    409          
    410         //Make sure we have a JS string, and not a Java string. 
    411         fileContents = String(fileContents); 
    412          
    413         var modifiedContents = fileContents; 
    414          
    415         if(fileContents.match(buildUtil.globalRequireLocalizationRegExp)){ 
    416                 modifiedContents = fileContents.replace(buildUtil.globalRequireLocalizationRegExp, function(matchString){ 
    417                         var replacement = matchString; 
    418                         var partMatches = matchString.match(buildUtil.requireLocalizationRegExp); 
    419                         var depCall = partMatches[1]; 
    420                         var depArgs = partMatches[2]; 
    421          
    422                         if(depCall == "requireLocalization"){ 
    423                                 //Need to find out what locales are available so the dojo loader 
    424                                 //only has to do one script request for the closest matching locale. 
    425                                 var reqArgs = buildUtil.getRequireLocalizationArgsFromString(depArgs); 
    426                                 if(reqArgs.moduleName){ 
    427                                         //Find the list of locales supported by looking at the path names. 
    428                                         var locales = buildUtil.getLocalesForBundle(reqArgs.moduleName, reqArgs.bundleName, baseRelativePath, prefixes); 
    429          
    430                                         //Add the supported locales to the requireLocalization arguments. 
    431                                         if(!reqArgs.localeName){ 
    432                                                 depArgs += ", null"; 
    433                                         } 
    434          
    435                                         depArgs += ', "' + locales.join(",") + '"'; 
    436                                          
    437                                         replacement = "dojo." + depCall + "(" + depArgs + ")"; 
    438                                 } 
    439                         } 
    440                         return replacement;              
    441                 }); 
    442         }        
    443         return modifiedContents; 
    444 } 
    445  
    446 buildUtil.makeFlatBundleContents = function(prefix, prefixPath, srcFileName){ 
    447         //summary: Given a nls file name, flatten the bundles from parent locales into the nls bundle. 
    448         var bundleParts = buildUtil.getBundlePartsFromFileName(prefix, prefixPath, srcFileName); 
    449         if(!bundleParts){ 
    450                 return null; 
    451         } 
    452         var moduleName = bundleParts.moduleName; 
    453         var bundleName = bundleParts.bundleName; 
    454         var localeName = bundleParts.localeName; 
    455  
    456         //print("## moduleName: " + moduleName + ", bundleName: " + bundleName + ", localeName: " + localeName); 
    457         dojo.requireLocalization(moduleName, bundleName, localeName); 
    458          
    459         //Get the generated, flattened bundle. 
    460         var module = dojo.getObject(moduleName); 
    461         var bundleLocale = localeName ? localeName.replace(/-/g, "_") : "ROOT"; 
    462         var flattenedBundle = module.nls[bundleName][bundleLocale]; 
    463         //print("## flattenedBundle: " + flattenedBundle); 
    464         if(!flattenedBundle){ 
    465                 throw "Cannot create flattened bundle for src file: " + srcFileName; 
    466         } 
    467  
    468         return dojo.json.serialize(flattenedBundle); 
    469 } 
    470  
    471 //Given a module and bundle name, find all the supported locales. 
    472 buildUtil.getLocalesForBundle = function(moduleName, bundleName, baseRelativePath, prefixes){ 
    473         //Build a path to the bundle directory and ask for all files that match 
    474         //the bundle name. 
    475         var filePath = this.mapResourceToPath(moduleName, baseRelativePath, prefixes); 
    476          
    477         var bundleRegExp = new RegExp("nls[/]?([\\w\\-]*)/" + bundleName + ".js$"); 
    478         var bundleFiles = buildUtil.getFilteredFileList(filePath + "nls/", bundleRegExp, true); 
    479          
    480         //Find the list of locales supported by looking at the path names. 
    481         var locales = []; 
    482         for(var j = 0; j < bundleFiles.length; j++){ 
    483                 var bundleParts = bundleFiles[j].match(bundleRegExp); 
    484                 if(bundleParts && bundleParts[1]){ 
    485                         locales.push(bundleParts[1]); 
    486                 }else{ 
    487                         locales.push("ROOT"); 
    488                 } 
    489         } 
    490  
    491         return locales; 
    492 } 
    493  
    494 buildUtil.getRequireLocalizationArgsFromString = function(argString){ 
    495         //summary: Given a string of the arguments to a dojo.requireLocalization 
    496         //call, separate the string into individual arguments. 
    497         var argResult = { 
    498                 moduleName: null, 
    499                 bundleName: null, 
    500                 localeName: null 
    501         }; 
    502          
    503         var l10nMatches = argString.split(/\,\s*/); 
    504         if(l10nMatches && l10nMatches.length > 1){ 
    505                 argResult.moduleName = l10nMatches[0] ? l10nMatches[0].replace(/\"/g, "") : null; 
    506                 argResult.bundleName = l10nMatches[1] ? l10nMatches[1].replace(/\"/g, "") : null; 
    507                 argResult.localeName = l10nMatches[2]; 
    508         } 
    509         return argResult; 
    510 } 
    511  
    512 buildUtil.getBundlePartsFromFileName = function(prefix, prefixPath, srcFileName){ 
    513         //Pull off any ../ values from prefix path to make matching easier. 
    514         var prefixPath = prefixPath.replace(/\.\.\//g, ""); 
    515  
    516         //Strip off the prefix path so we can find the real resource and bundle names. 
    517         var prefixStartIndex = srcFileName.lastIndexOf(prefixPath);