Upgrade to ExtJS 4.0.1 - Released 05/18/2011
[extjs.git] / jsbuilder / src / Target.js
1 Target = Ext.extend(Object, {
2     constructor: function(config, project) {
3         this.config = config || {};
4         this.project = project;
5     },
6
7     create: function() {
8         this.parseTarget();
9
10         var project = this.project,
11             builder = project.builder,
12             verbose = builder.get('verbose'),
13             file;
14
15         if (verbose) {
16             Logger.log('\nCreating the "' + this.get('name') + '" target as "' + this.get('target') + '"');
17         }
18
19         // Open the file stream
20         file = new Stream(this.get('targetPath'), 'w');
21
22         this.onCreate(file);
23         this.writeIncludes(file);
24         this.onAfterWriteIncludes(file);
25
26         // Close the target file
27         file.close();
28
29         this.afterCreate();
30     },
31
32     afterCreate: function() {
33         this.project.compressTarget(this);
34
35         var filePath = this.get('targetPath');
36         var license = (this.project.get('license')) ? "/*\n" + this.project.get('license') + "\n*/\n" : '';
37
38         if (license) {
39             var content = Fs.readFile(filePath);
40
41             if (content.substring(0, license.length) !== license) {
42                 Fs.writeFile(filePath, license + content);
43             }
44         }
45     },
46
47     onAfterWriteIncludes: function(file) {
48         var namespaceRewrites = this.get('namespaceRewrites'),
49             settings = this.get('settings'),
50             suffix = '})(',
51             names = [];
52
53         if (namespaceRewrites) {
54             namespaceRewrites.forEach(function(rewrite) {
55                 names.push('this.' + rewrite.to + ' || (this.' + rewrite.to + ' = {})');
56             });
57
58             suffix += names.join(', ');
59             suffix += ');';
60
61             file.writeln(suffix);
62         }
63     },
64
65     onCreate: function(file) {
66         var namespaceRewrites = this.get('namespaceRewrites'),
67             prefix = '(function(',
68             settings = this.get('settings'),
69             names = [];
70
71         if (namespaceRewrites) {
72             namespaceRewrites.forEach(function(rewrite) {
73                 names.push(rewrite.from);
74             });
75
76             prefix += names.join(', ');
77             prefix += '){';
78
79             if (settings) {
80                 prefix += "\n";
81                 prefix +=  ["if (typeof Ext === 'undefined') {",
82                                 "this.Ext = {};",
83                             "}",
84                             "",
85                             "Ext.buildSettings = " + JSON.stringify(settings) + ";"
86                            ].join("\n");
87             }
88
89
90             file.writeln(prefix);
91         }
92     },
93
94     parseTarget: function() {
95         if (this.parsed) {
96             return;
97         }
98
99         // Backwards compatibility with JSB2
100         var target = this.get('target') || this.get('file') || this.getDefaultTarget(),
101             basePath = this.project.get('deployDir') + Fs.sep,
102             dir;
103
104         target = target.replace(/\//g, Fs.sep);
105
106         if (target.indexOf('.js') !== -1) {
107             target = target.replace('.js', '');
108 //            if (this.get('debug')) {
109 //                target += this.project.builder.get('debugSuffix');
110 //            }
111             target += '.js';
112         }
113
114         this.set('target', target);
115
116         // If the target is a path, then create the needed folders
117         if (target.indexOf(Fs.sep) !== -1) {
118             dir = target.substr(0, target.lastIndexOf(Fs.sep));
119             target = target.replace(dir, '').substr(1);
120             target = Fs.mkdir(basePath + dir) + Fs.sep + target;
121         }
122         else {
123             target = basePath + target;
124         }
125
126         this.set('targetPath', target);
127         this.parsed = true;
128     },
129
130     writeIncludes: function(file) {
131         var project = this.project,
132             verbose = project.builder.get('verbose'),
133             includes = this.get('files') || this.get('fileIncludes') || [],
134             jsbDir = project.get('jsbDir') + Fs.sep;
135
136         if (verbose && includes.length) {
137             Logger.log('  - ' + includes.length + ' file(s) included in this target.');
138         }
139
140         // Loop over all file includes, read the contents, and write
141         // it to our target file
142         includes.forEach(function(include) {
143             var path = this.getIncludePath(include),
144                 content = '',
145                                 gotFile = false,
146                 filesStream, files;
147
148             if (verbose) {
149                 Logger.log('    + ' + path);
150             }
151
152
153             if (!Fs.exists(jsbDir + path)) {
154                 if (Platform.isUnix) {
155                     filesStream = new Stream('exec://ls -a ' + jsbDir + path);
156                     files = filesStream.readFile().split('\n');
157                     filesStream.close();
158
159                     files.forEach(function(filePath) {
160                         if (!Ext.isEmpty(filePath)) {
161                             include = new Stream(filePath);
162                             content += include.readFile() + '\n';
163                             include.close();
164                                                         gotFile = true;
165                         }
166                     });
167
168                                         if (!gotFile) {
169                                                 Logger.log("[ERROR] File '" + jsbDir + path + "' is either not existent or unreadble");
170                                         }
171                 }
172             }
173             else {
174                 content = this.getContent(jsbDir + path);
175             }
176
177
178
179             file.writeln(content);
180         }, this);
181     },
182
183
184     getContent: function(file, callNum) {
185         /**
186          * This function should pretty much never fail since we already know the file exists.
187          * However in Windows it seems to randomly omit files when building because it can't
188          * open the stream, which causes the build to break. Since we know the file is there,
189          * we'll just re-request it until we get it. While stupid, this makes it reliable.
190          */
191
192         var content = '';
193
194         callNum = callNum || 0;
195         try {
196             content = Fs.readFile(file);
197         } catch (e) {
198             if (Platform.isWindows && callNum < 5) {
199                 return this.getContent(file, callNum + 1);
200             }
201         }
202         return content;
203     },
204
205     getIncludePath : function(include) {
206         return include.path.replace(/\//g, Fs.sep) + (include.name || include.text || '');
207     },
208
209
210     get: function(key) {
211         return this.config[key] || false;
212     },
213
214     set: function(key, value, ifNotExists) {
215         if (ifNotExists && this.get(key) !== false) {
216             return;
217         }
218         this.config[key] = value;
219     }
220 });