Upgrade to ExtJS 4.0.2 - Released 06/09/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                             "Ext.isSandboxed = true;"
87                            ].join("\n");
88             }
89
90
91             file.writeln(prefix);
92         }
93     },
94
95     parseTarget: function() {
96         if (this.parsed) {
97             return;
98         }
99
100         // Backwards compatibility with JSB2
101         var target = this.get('target') || this.get('file') || this.getDefaultTarget(),
102             basePath = this.project.get('deployDir') + Fs.sep,
103             dir;
104
105         target = target.replace(/\//g, Fs.sep);
106
107         if (target.indexOf('.js') !== -1) {
108             target = target.replace('.js', '');
109 //            if (this.get('debug')) {
110 //                target += this.project.builder.get('debugSuffix');
111 //            }
112             target += '.js';
113         }
114
115         this.set('target', target);
116
117         // If the target is a path, then create the needed folders
118         if (target.indexOf(Fs.sep) !== -1) {
119             dir = target.substr(0, target.lastIndexOf(Fs.sep));
120             target = target.replace(dir, '').substr(1);
121             target = Fs.mkdir(basePath + dir) + Fs.sep + target;
122         }
123         else {
124             target = basePath + target;
125         }
126
127         this.set('targetPath', target);
128         this.parsed = true;
129     },
130
131     writeIncludes: function(file) {
132         var project = this.project,
133             verbose = project.builder.get('verbose'),
134             includes = this.get('files') || this.get('fileIncludes') || [],
135             jsbDir = project.get('jsbDir') + Fs.sep;
136
137         if (verbose && includes.length) {
138             Logger.log('  - ' + includes.length + ' file(s) included in this target.');
139         }
140
141         // Loop over all file includes, read the contents, and write
142         // it to our target file
143         includes.forEach(function(include) {
144             var path = this.getIncludePath(include),
145                 content = '',
146                                 gotFile = false,
147                 filesStream, files;
148
149             if (verbose) {
150                 Logger.log('    + ' + path);
151             }
152
153
154             if (!Fs.exists(jsbDir + path)) {
155                 if (Platform.isUnix) {
156                     filesStream = new Stream('exec://ls -a ' + jsbDir + path);
157                     files = filesStream.readFile().split('\n');
158                     filesStream.close();
159
160                     files.forEach(function(filePath) {
161                         if (!Ext.isEmpty(filePath)) {
162                             include = new Stream(filePath);
163                             content += include.readFile() + '\n';
164                             include.close();
165                                                         gotFile = true;
166                         }
167                     });
168
169                                         if (!gotFile) {
170                                                 Logger.log("[ERROR] File '" + jsbDir + path + "' is either not existent or unreadble");
171                                         }
172                 }
173             }
174             else {
175                 content = this.getContent(jsbDir + path);
176             }
177
178
179
180             file.writeln(content);
181         }, this);
182     },
183
184
185     getContent: function(file, callNum) {
186         /**
187          * This function should pretty much never fail since we already know the file exists.
188          * However in Windows it seems to randomly omit files when building because it can't
189          * open the stream, which causes the build to break. Since we know the file is there,
190          * we'll just re-request it until we get it. While stupid, this makes it reliable.
191          */
192
193         var content = '';
194
195         callNum = callNum || 0;
196         try {
197             content = Fs.readFile(file);
198         } catch (e) {
199             if (Platform.isWindows && callNum < 5) {
200                 return this.getContent(file, callNum + 1);
201             }
202         }
203         return content;
204     },
205
206     getIncludePath : function(include) {
207         return include.path.replace(/\//g, Fs.sep) + (include.name || include.text || '');
208     },
209
210
211     get: function(key) {
212         return this.config[key] || false;
213     },
214
215     set: function(key, value, ifNotExists) {
216         if (ifNotExists && this.get(key) !== false) {
217             return;
218         }
219         this.config[key] = value;
220     }
221 });