diff options
author | Adrian Dudau <adrian.dudau@enea.com> | 2014-06-26 13:23:09 +0200 |
---|---|---|
committer | Adrian Dudau <adrian.dudau@enea.com> | 2014-06-26 13:24:09 +0200 |
commit | c7da892cb23d50d4d85746c9a0b6b14bf570989d (patch) | |
tree | e7136073f386d6156f51766c498c52c30c8df85f /plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBSession.java | |
download | eclipse-poky-kepler-c7da892cb23d50d4d85746c9a0b6b14bf570989d.tar.gz |
initial commit for Enea Linux 4.0daisy
Migrated from the internal git server on the daisy-enea branch
Signed-off-by: Adrian Dudau <adrian.dudau@enea.com>
Diffstat (limited to 'plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBSession.java')
-rw-r--r-- | plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBSession.java | 785 |
1 files changed, 785 insertions, 0 deletions
diff --git a/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBSession.java b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBSession.java new file mode 100644 index 0000000..4434df8 --- /dev/null +++ b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBSession.java | |||
@@ -0,0 +1,785 @@ | |||
1 | /***************************************************************************** | ||
2 | * Copyright (c) 2009 Ken Gilmer, 2013 Intel Corporation | ||
3 | * All rights reserved. This program and the accompanying materials | ||
4 | * are made available under the terms of the Eclipse Public License v1.0 | ||
5 | * which accompanies this distribution, and is available at | ||
6 | * http://www.eclipse.org/legal/epl-v10.html | ||
7 | * | ||
8 | * Contributors: | ||
9 | * Ken Gilmer - initial API and implementation | ||
10 | * Ioana Grigoropol (Intel) - adapt class for remote support | ||
11 | *******************************************************************************/ | ||
12 | package org.yocto.bc.bitbake; | ||
13 | |||
14 | import java.io.BufferedReader; | ||
15 | import java.io.File; | ||
16 | import java.io.FileFilter; | ||
17 | import java.io.IOException; | ||
18 | import java.io.StringReader; | ||
19 | import java.io.InputStream; | ||
20 | import java.io.InputStreamReader; | ||
21 | import java.net.URI; | ||
22 | import java.util.ArrayList; | ||
23 | import java.util.Arrays; | ||
24 | import java.util.Collection; | ||
25 | import java.util.Hashtable; | ||
26 | import java.util.Iterator; | ||
27 | import java.util.List; | ||
28 | import java.util.Map; | ||
29 | import java.util.Set; | ||
30 | import java.util.Stack; | ||
31 | import java.util.concurrent.locks.ReentrantReadWriteLock; | ||
32 | import java.util.concurrent.locks.Lock; | ||
33 | |||
34 | import org.eclipse.core.resources.IFile; | ||
35 | import org.eclipse.core.resources.IProject; | ||
36 | import org.eclipse.core.resources.IResource; | ||
37 | import org.eclipse.core.runtime.IProgressMonitor; | ||
38 | import org.eclipse.core.runtime.IStatus; | ||
39 | import org.eclipse.core.runtime.NullProgressMonitor; | ||
40 | import org.eclipse.core.runtime.Status; | ||
41 | import org.eclipse.jface.preference.JFacePreferences; | ||
42 | import org.eclipse.jface.resource.JFaceResources; | ||
43 | import org.eclipse.rse.core.model.IHost; | ||
44 | import org.eclipse.ui.console.ConsolePlugin; | ||
45 | import org.eclipse.ui.console.IConsole; | ||
46 | import org.eclipse.ui.console.IConsoleManager; | ||
47 | import org.eclipse.ui.console.MessageConsole; | ||
48 | import org.eclipse.ui.console.MessageConsoleStream; | ||
49 | import org.eclipse.ui.progress.WorkbenchJob; | ||
50 | |||
51 | import org.yocto.bc.ui.model.IModelElement; | ||
52 | import org.yocto.bc.ui.model.ProjectInfo; | ||
53 | import org.yocto.remote.utils.RemoteHelper; | ||
54 | import org.yocto.remote.utils.YoctoCommand; | ||
55 | |||
56 | /** | ||
57 | * BBSession encapsulates a global bitbake configuration and is the primary interface | ||
58 | * for actions against a BitBake installation. | ||
59 | * | ||
60 | * @author kgilmer | ||
61 | * | ||
62 | */ | ||
63 | public class BBSession implements IBBSessionListener, IModelElement, Map { | ||
64 | public static final int TYPE_VARIABLE_ASSIGNMENT = 1; | ||
65 | public static final int TYPE_UNKNOWN = 2; | ||
66 | public static final int TYPE_STATEMENT = 3; | ||
67 | public static final int TYPE_FLAG = 4; | ||
68 | |||
69 | public static final String BB_ENV_FILE = "bitbake.env"; | ||
70 | |||
71 | public static final String CONF_DIR = "conf"; | ||
72 | public static final String BUILDDIR_INDICATORS [] = { | ||
73 | "local.conf", | ||
74 | "bblayers.conf", | ||
75 | }; | ||
76 | |||
77 | protected final ProjectInfo pinfo; | ||
78 | protected final ShellSession shell; | ||
79 | protected Map<?,?> properties = null; | ||
80 | protected List <URI> depends = null; | ||
81 | protected boolean initialized = false; | ||
82 | protected boolean errorOccured = false; | ||
83 | protected MessageConsole sessionConsole; | ||
84 | private final ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock(); | ||
85 | private final Lock rlock = rwlock.readLock(); | ||
86 | private final Lock wlock = rwlock.writeLock(); | ||
87 | protected String parsingCmd; | ||
88 | private boolean silent = false; | ||
89 | private String errorLines = ""; | ||
90 | |||
91 | public BBSession(ShellSession ssession, URI projectRoot) throws IOException { | ||
92 | shell = ssession; | ||
93 | this.pinfo = new ProjectInfo(); | ||
94 | pinfo.setLocationURI(projectRoot); | ||
95 | pinfo.setInitScriptPath(ProjectInfoHelper.getInitScriptPath(projectRoot)); | ||
96 | this.parsingCmd = "DISABLE_SANITY_CHECKS=\"1\" bitbake -e >& " + BB_ENV_FILE; | ||
97 | } | ||
98 | |||
99 | public BBSession(ShellSession ssession, URI projectRoot, boolean silent) throws IOException { | ||
100 | this(ssession, projectRoot); | ||
101 | this.silent = silent; | ||
102 | } | ||
103 | |||
104 | private Collection adapttoIPath(List<File> asList, IProject project) { | ||
105 | |||
106 | List pathList = new ArrayList(); | ||
107 | |||
108 | for (Iterator i = asList.iterator(); i.hasNext();) { | ||
109 | File f = (File) i.next(); | ||
110 | IFile ff = project.getFile(stripLeading(f.toString(), project.getLocationURI().getPath())); | ||
111 | if (ff.exists()) { | ||
112 | pathList.add(ff); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | return pathList; | ||
117 | } | ||
118 | |||
119 | private String appendAll(String[] elems, int st) { | ||
120 | StringBuffer sb = new StringBuffer(); | ||
121 | |||
122 | for (int i = st; i < elems.length; ++i) { | ||
123 | sb.append(elems[i]); | ||
124 | } | ||
125 | |||
126 | return sb.toString(); | ||
127 | } | ||
128 | |||
129 | private int charCount(String trimmed, char c) { | ||
130 | int i = 0; | ||
131 | int p = 0; | ||
132 | |||
133 | while ((p = trimmed.indexOf(c, p)) > -1) { | ||
134 | i++; | ||
135 | p++; | ||
136 | } | ||
137 | |||
138 | return i; | ||
139 | } | ||
140 | |||
141 | public void clear() { | ||
142 | throw new RuntimeException("BB configuration is read-only."); | ||
143 | } | ||
144 | |||
145 | public boolean containsKey(Object arg0) { | ||
146 | try { | ||
147 | checkValidAndLock(true); | ||
148 | return properties.containsKey(arg0); | ||
149 | } catch (Exception e) { | ||
150 | e.printStackTrace(); | ||
151 | return false; | ||
152 | }finally { | ||
153 | rlock.unlock(); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | public boolean containsValue(Object arg0) { | ||
158 | try { | ||
159 | checkValidAndLock(true); | ||
160 | return properties.containsValue(arg0); | ||
161 | } catch (Exception e) { | ||
162 | e.printStackTrace(); | ||
163 | return false; | ||
164 | }finally { | ||
165 | rlock.unlock(); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | public Set entrySet() { | ||
170 | try { | ||
171 | checkValidAndLock(true); | ||
172 | return properties.entrySet(); | ||
173 | } catch (Exception e) { | ||
174 | e.printStackTrace(); | ||
175 | return null; | ||
176 | }finally { | ||
177 | rlock.unlock(); | ||
178 | } | ||
179 | } | ||
180 | |||
181 | @Override | ||
182 | public boolean equals(Object arg0) { | ||
183 | try { | ||
184 | checkValidAndLock(true); | ||
185 | return properties.equals(arg0); | ||
186 | } catch (Exception e) { | ||
187 | e.printStackTrace(); | ||
188 | return false; | ||
189 | }finally { | ||
190 | rlock.unlock(); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | public ShellSession getShell() { | ||
195 | return shell; | ||
196 | } | ||
197 | |||
198 | public URI getProjInfoRoot() { | ||
199 | return pinfo.getOriginalURI(); | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * Recursively generate list of Recipe files from a root directory. | ||
204 | * | ||
205 | * @param rootDir | ||
206 | * @param recipes | ||
207 | * @param fileExtension | ||
208 | * @param project | ||
209 | */ | ||
210 | private void findRecipes(File rootDir, List recipes, final String fileExtension, IProject project) { | ||
211 | File[] children = rootDir.listFiles(new FileFilter() { | ||
212 | |||
213 | public boolean accept(File pathname) { | ||
214 | return pathname.isFile() && pathname.getName().endsWith(fileExtension); | ||
215 | } | ||
216 | |||
217 | }); | ||
218 | |||
219 | if (children != null && children.length > 0) { | ||
220 | recipes.addAll(adapttoIPath(Arrays.asList(children), project)); | ||
221 | } | ||
222 | |||
223 | File[] childDirs = rootDir.listFiles(new FileFilter() { | ||
224 | |||
225 | public boolean accept(File pathname) { | ||
226 | return pathname.isDirectory(); | ||
227 | } | ||
228 | |||
229 | }); | ||
230 | |||
231 | if (childDirs != null && childDirs.length > 0) { | ||
232 | for (int i = 0; i < childDirs.length; ++i) { | ||
233 | findRecipes(childDirs[i], recipes, fileExtension, project); | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | |||
238 | private Collection findRecipes(List paths, IProject project) { | ||
239 | List recipes = new ArrayList(); | ||
240 | |||
241 | for (Iterator i = paths.iterator(); i.hasNext();) { | ||
242 | String rawPath = (String) i.next(); | ||
243 | String[] elems = rawPath.split("\\*/\\*"); | ||
244 | |||
245 | if (elems.length == 2) { | ||
246 | |||
247 | File rootDir = new File(elems[0]); | ||
248 | |||
249 | findRecipes(rootDir, recipes, elems[1], project); | ||
250 | } | ||
251 | } | ||
252 | |||
253 | return recipes; | ||
254 | } | ||
255 | |||
256 | public Object get(Object arg0) { | ||
257 | try { | ||
258 | checkValidAndLock(true); | ||
259 | return properties.get(arg0); | ||
260 | } catch (Exception e) { | ||
261 | e.printStackTrace(); | ||
262 | return null; | ||
263 | }finally { | ||
264 | rlock.unlock(); | ||
265 | } | ||
266 | } | ||
267 | |||
268 | private List getBitBakeKeywords() { | ||
269 | return Arrays.asList(BBLanguageHelper.BITBAKE_KEYWORDS); | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * @return A MessageConsole for this BB session. | ||
274 | */ | ||
275 | public MessageConsole getConsole() { | ||
276 | if (sessionConsole == null) { | ||
277 | String cName = ProjectInfoHelper.getProjectName(pinfo.getOriginalURI()) + " Console"; | ||
278 | IConsoleManager conMan = ConsolePlugin.getDefault().getConsoleManager(); | ||
279 | IConsole[] existing = conMan.getConsoles(); | ||
280 | for (int i = 0; i < existing.length; i++) | ||
281 | if (cName.equals(existing[i].getName())) { | ||
282 | sessionConsole = (MessageConsole) existing[i]; | ||
283 | break; | ||
284 | } | ||
285 | if (sessionConsole == null) { | ||
286 | sessionConsole = new MessageConsole(cName, null); | ||
287 | conMan.addConsoles(new IConsole[] { sessionConsole }); | ||
288 | } | ||
289 | } | ||
290 | |||
291 | ConsolePlugin.getDefault().getConsoleManager().showConsoleView(sessionConsole); | ||
292 | |||
293 | return sessionConsole; | ||
294 | } | ||
295 | |||
296 | private int getLineType(String line) { | ||
297 | |||
298 | if (line.contains("=")) { | ||
299 | return TYPE_VARIABLE_ASSIGNMENT; | ||
300 | } | ||
301 | |||
302 | for (Iterator i = getBitBakeKeywords().iterator(); i.hasNext();) { | ||
303 | if (line.startsWith((String) i.next())) { | ||
304 | return TYPE_STATEMENT; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | if (line.contains(":")) { | ||
309 | return TYPE_FLAG; | ||
310 | } | ||
311 | |||
312 | return TYPE_UNKNOWN; | ||
313 | } | ||
314 | |||
315 | public Collection getRecipeFiles(IProject project) { | ||
316 | try { | ||
317 | checkValidAndLock(true); | ||
318 | if (!initialized) { | ||
319 | throw new RuntimeException(this.getClass().getName() + " is not initialized."); | ||
320 | } | ||
321 | String bbfiles = (String) this.properties.get("BBFILES"); | ||
322 | List paths = parseBBFiles(bbfiles); | ||
323 | return findRecipes(paths, project); | ||
324 | } catch (Exception e) { | ||
325 | return null; | ||
326 | } | ||
327 | finally { | ||
328 | rlock.unlock(); | ||
329 | } | ||
330 | } | ||
331 | |||
332 | @Override | ||
333 | public int hashCode() { | ||
334 | try { | ||
335 | checkValidAndLock(true); | ||
336 | return properties.hashCode(); | ||
337 | } catch (Exception e) { | ||
338 | e.printStackTrace(); | ||
339 | return 0; | ||
340 | }finally { | ||
341 | rlock.unlock(); | ||
342 | } | ||
343 | } | ||
344 | |||
345 | protected void checkExecuteError(String result, boolean hasErrors) { | ||
346 | URI recipeURI = getDefaultDepends(); | ||
347 | String text = "Parsing " + ((recipeURI != null) ? ("recipe " + recipeURI) : "base configurations"); | ||
348 | if (hasErrors) { | ||
349 | text = text + " ERROR!\n" + result; | ||
350 | }else { | ||
351 | text = text + " SUCCESS.\n"; | ||
352 | } | ||
353 | if(!silent) { | ||
354 | displayInConsole(text, -1, false); | ||
355 | } | ||
356 | } | ||
357 | |||
358 | protected void displayInConsole(final String result, final int code, boolean clear) { | ||
359 | MessageConsole console = getConsole(); | ||
360 | final MessageConsoleStream info = console.newMessageStream(); | ||
361 | if(clear) | ||
362 | console.clearConsole(); | ||
363 | new WorkbenchJob("Display parsing result") { | ||
364 | public IStatus runInUIThread(IProgressMonitor monitor) { | ||
365 | if(code != 0) { | ||
366 | info.setColor(JFaceResources.getColorRegistry().get(JFacePreferences.ERROR_COLOR)); | ||
367 | } | ||
368 | try { | ||
369 | info.println(result); | ||
370 | info.close(); | ||
371 | }catch (Exception e) { | ||
372 | e.printStackTrace(); | ||
373 | } | ||
374 | return Status.OK_STATUS; | ||
375 | } | ||
376 | }.schedule(); | ||
377 | } | ||
378 | |||
379 | private void checkValidAndLock(boolean rdlck) throws Exception { | ||
380 | if(rdlck) | ||
381 | rlock.lock(); | ||
382 | else | ||
383 | wlock.lock(); | ||
384 | if(!initialized) { | ||
385 | //upgrade lock manually | ||
386 | if(rdlck) { | ||
387 | rlock.unlock(); | ||
388 | wlock.lock(); | ||
389 | } | ||
390 | try { | ||
391 | if(!initialized) { //recheck | ||
392 | boolean hasErrors = false; | ||
393 | String result = shell.execute(parsingCmd, hasErrors); | ||
394 | |||
395 | properties = parseBBEnvironment(result); | ||
396 | |||
397 | if (properties.size() == 0) { // there was an error in sourcing bitbake environment | ||
398 | shell.printError(errorLines); | ||
399 | errorOccured = true; | ||
400 | } else { | ||
401 | errorLines = ""; | ||
402 | errorOccured = false; | ||
403 | initialized = true; | ||
404 | } | ||
405 | RemoteHelper.handleRunCommandRemote(this.pinfo.getConnection(), new YoctoCommand("rm -rf " + result + BB_ENV_FILE, result, ""), new NullProgressMonitor()); | ||
406 | } | ||
407 | } finally { | ||
408 | //downgrade lock | ||
409 | if(rdlck) { | ||
410 | rlock.lock(); | ||
411 | wlock.unlock(); | ||
412 | } | ||
413 | } | ||
414 | } | ||
415 | //not release lock | ||
416 | } | ||
417 | |||
418 | public void initialize() throws Exception { | ||
419 | try { | ||
420 | checkValidAndLock(false); | ||
421 | }finally { | ||
422 | wlock.unlock(); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | private boolean isBlockEnd(String trimmed) { | ||
427 | return charCount(trimmed, '}') > charCount(trimmed, '{'); | ||
428 | // return trimmed.indexOf('}') > -1 && trimmed.indexOf('{') == -1; | ||
429 | } | ||
430 | |||
431 | private boolean isBlockStart(String trimmed) { | ||
432 | return charCount(trimmed, '{') > charCount(trimmed, '}'); | ||
433 | // return trimmed.indexOf('{') > -1 && trimmed.indexOf('}') == -1; | ||
434 | } | ||
435 | |||
436 | public boolean isEmpty() { | ||
437 | try { | ||
438 | checkValidAndLock(true); | ||
439 | return properties.isEmpty(); | ||
440 | } catch (Exception e) { | ||
441 | e.printStackTrace(); | ||
442 | return true; | ||
443 | }finally { | ||
444 | rlock.unlock(); | ||
445 | } | ||
446 | } | ||
447 | |||
448 | public Set keySet() { | ||
449 | try { | ||
450 | checkValidAndLock(true); | ||
451 | return properties.keySet(); | ||
452 | } catch (Exception e) { | ||
453 | e.printStackTrace(); | ||
454 | return null; | ||
455 | }finally { | ||
456 | rlock.unlock(); | ||
457 | } | ||
458 | } | ||
459 | |||
460 | protected void parse(String bbOutfilePath, Map outMap) throws Exception { | ||
461 | IHost connection = shell.getProjectInfo().getConnection(); | ||
462 | InputStream is = RemoteHelper.getRemoteInputStream(connection, bbOutfilePath, BB_ENV_FILE, new NullProgressMonitor()); | ||
463 | RemoteHelper.getRemoteHostFile(connection, bbOutfilePath + BB_ENV_FILE, new NullProgressMonitor()); | ||
464 | BufferedReader reader = new BufferedReader(new InputStreamReader(is)); | ||
465 | String line; | ||
466 | boolean inLine = false; | ||
467 | StringBuffer sb = null; | ||
468 | Stack blockStack = new Stack(); | ||
469 | |||
470 | while ((line = reader.readLine()) != null) { | ||
471 | errorLines += line; | ||
472 | String trimmed = line.trim(); | ||
473 | if (trimmed.length() == 0 || line.startsWith("#")) { | ||
474 | // weed out the blank and comment lines | ||
475 | continue; | ||
476 | } | ||
477 | // Now we look for block start ends, and ignore all code within | ||
478 | // blocks. | ||
479 | if (isBlockStart(trimmed)) { | ||
480 | blockStack.push(trimmed); | ||
481 | } else if (isBlockEnd(trimmed)) { | ||
482 | blockStack.pop(); | ||
483 | |||
484 | } | ||
485 | |||
486 | if (!blockStack.isEmpty()) { | ||
487 | // we are in a code block, continue until we break into global | ||
488 | // scope. | ||
489 | continue; | ||
490 | } | ||
491 | if (trimmed.endsWith("\\")) { | ||
492 | if (!inLine) { | ||
493 | inLine = true; | ||
494 | sb = new StringBuffer(trimmed.substring(0, trimmed.length() - 1)); | ||
495 | } else { | ||
496 | sb.append(trimmed.substring(0, trimmed.length() - 1)); | ||
497 | } | ||
498 | // Only parse the line when we have the complete contents. | ||
499 | continue; | ||
500 | } else if (inLine) { | ||
501 | inLine = false; | ||
502 | line = sb.toString(); | ||
503 | } | ||
504 | |||
505 | parseLine(line, outMap); | ||
506 | } | ||
507 | } | ||
508 | |||
509 | private void parseAdditiveAssignment(String line, String operator, Map mo) throws Exception { | ||
510 | String[] elems = splitAssignment(line, "\\+="); | ||
511 | |||
512 | if (elems.length != 2) { | ||
513 | throw new Exception("Unable to parse additive variable assignment in line: " + line); | ||
514 | } | ||
515 | |||
516 | if (!mo.containsKey(elems[0])) { | ||
517 | mo.put(elems[0].trim(), elems[1]); | ||
518 | } else { | ||
519 | String existing = (String) mo.get(elems[0]); | ||
520 | if (operator.equals("+=")) { | ||
521 | mo.put(elems[0], existing + elems[1]); | ||
522 | } else { | ||
523 | mo.put(elems[0], elems[1] + existing); | ||
524 | } | ||
525 | } | ||
526 | } | ||
527 | |||
528 | protected URI getDefaultDepends() { | ||
529 | return null; | ||
530 | } | ||
531 | |||
532 | protected Map parseBBEnvironment(String bbOutFilePath) throws Exception { | ||
533 | Map env = new Hashtable(); | ||
534 | this.depends = new ArrayList<URI>(); | ||
535 | |||
536 | parse(bbOutFilePath, env); | ||
537 | |||
538 | String included = (String) env.get("BBINCLUDED"); | ||
539 | if(getDefaultDepends() != null) { | ||
540 | this.depends.add(getDefaultDepends()); | ||
541 | } | ||
542 | if(included != null) { | ||
543 | String[] includedSplitted = included.split(" "); | ||
544 | for (String incl : includedSplitted){ | ||
545 | if (!incl.contains("${")) { | ||
546 | this.depends.add(new URI(incl)); | ||
547 | } | ||
548 | } | ||
549 | } | ||
550 | |||
551 | return env; | ||
552 | } | ||
553 | |||
554 | |||
555 | private List parseBBFiles(String bbfiles) { | ||
556 | return Arrays.asList(bbfiles.split(" ")); | ||
557 | } | ||
558 | |||
559 | //Map delegate methods | ||
560 | |||
561 | private void parseConditionalAssignment(String line, Map mo) throws Exception { | ||
562 | String[] elems = splitAssignment(line, "\\?="); | ||
563 | |||
564 | if (elems.length != 2) { | ||
565 | throw new Exception("Unable to parse conditional variable assignment in line: " + line); | ||
566 | } | ||
567 | |||
568 | if (!mo.containsKey(elems[0].trim())) { | ||
569 | mo.put(elems[0].trim(), elems[1].trim()); | ||
570 | } | ||
571 | } | ||
572 | |||
573 | private void parseImmediateAssignment(String line, String delimiter, Map mo) throws Exception { | ||
574 | String[] elems = splitAssignment(line, delimiter); | ||
575 | |||
576 | mo.put(elems[0], substitute(elems[1], mo)); | ||
577 | } | ||
578 | |||
579 | private void parseKeyValue(String line, String delimiter, Map mo) throws Exception { | ||
580 | String[] elems = splitAssignment(line, delimiter); | ||
581 | |||
582 | mo.put(elems[0], elems[1]); | ||
583 | } | ||
584 | |||
585 | private void parseLine(String line, Map mo) throws Exception { | ||
586 | |||
587 | switch (getLineType(line)) { | ||
588 | case TYPE_VARIABLE_ASSIGNMENT: | ||
589 | parseVariableAssignment(line, mo); | ||
590 | break; | ||
591 | case TYPE_STATEMENT: | ||
592 | case TYPE_FLAG: | ||
593 | // for now ignore statements | ||
594 | break; | ||
595 | case TYPE_UNKNOWN: | ||
596 | // we'll gloss over unknown lines as well; | ||
597 | break; | ||
598 | default: | ||
599 | throw new Exception("Unable to parse line: " + line); | ||
600 | } | ||
601 | } | ||
602 | |||
603 | private void parseVariableAssignment(String line, Map mo) throws Exception { | ||
604 | if (line.contains("?=")) { | ||
605 | parseConditionalAssignment(line, mo); | ||
606 | } else if (line.contains("+=")) { | ||
607 | parseAdditiveAssignment(line, "+=", mo); | ||
608 | } else if (line.contains("=+")) { | ||
609 | parseAdditiveAssignment(line, "=+", mo); | ||
610 | } else if (line.contains(":=")) { | ||
611 | parseImmediateAssignment(line, ":=", mo); | ||
612 | } else { | ||
613 | parseKeyValue(line, "=", mo); | ||
614 | } | ||
615 | |||
616 | } | ||
617 | |||
618 | private List parseVars(String line) { | ||
619 | List l = new ArrayList(); | ||
620 | |||
621 | int i = 0; | ||
622 | |||
623 | while ((i = line.indexOf("${", i)) > -1) { | ||
624 | int i2 = line.indexOf("}", i); | ||
625 | |||
626 | l.add(line.subSequence(i + 2, i2)); | ||
627 | i++; | ||
628 | } | ||
629 | |||
630 | return l; | ||
631 | } | ||
632 | |||
633 | public Object put(Object arg0, Object arg1) { | ||
634 | throw new RuntimeException("BB configuration is read-only."); | ||
635 | } | ||
636 | |||
637 | public void putAll(Map arg0) { | ||
638 | throw new RuntimeException("BB configuration is read-only."); | ||
639 | } | ||
640 | |||
641 | public Object remove(Object arg0) { | ||
642 | throw new RuntimeException("BB configuration is read-only."); | ||
643 | } | ||
644 | |||
645 | private String removeQuotes(String line) { | ||
646 | line = line.trim(); | ||
647 | |||
648 | if (line.startsWith("\"")) { | ||
649 | line = line.substring(1); | ||
650 | } | ||
651 | |||
652 | if (line.endsWith("\"")) { | ||
653 | line = line.substring(0, line.length() - 1); | ||
654 | } | ||
655 | |||
656 | return line; | ||
657 | } | ||
658 | |||
659 | public int size() { | ||
660 | try { | ||
661 | checkValidAndLock(true); | ||
662 | return properties.size(); | ||
663 | }catch (Exception e) { | ||
664 | e.printStackTrace(); | ||
665 | return 0; | ||
666 | }finally { | ||
667 | rlock.unlock(); | ||
668 | } | ||
669 | } | ||
670 | |||
671 | private String[] splitAssignment(String line, String seperator) throws Exception { | ||
672 | String[] elems = line.split(seperator); | ||
673 | |||
674 | if (elems.length < 2) { | ||
675 | throw new Exception("Unable to parse assignment in line: " + line); | ||
676 | } else if (elems.length == 2) { | ||
677 | |||
678 | elems[0] = elems[0].trim(); // Clean up trailing or leading spaces. | ||
679 | if (elems[0].startsWith("export ")) { | ||
680 | elems[0] = elems[0].substring("export ".length()).trim(); | ||
681 | } | ||
682 | elems[1] = removeQuotes(elems[1]); // Evaluate variables | ||
683 | |||
684 | return elems; | ||
685 | } else { | ||
686 | String[] retVal = new String[2]; | ||
687 | |||
688 | retVal[0] = elems[0]; | ||
689 | if (retVal[0].startsWith("export ")) { | ||
690 | retVal[0] = retVal[0].substring("export ".length()).trim(); | ||
691 | } | ||
692 | retVal[1] = appendAll(elems, 1); | ||
693 | |||
694 | return retVal; | ||
695 | } | ||
696 | } | ||
697 | |||
698 | private String stripLeading(String target, String leading) { | ||
699 | if (target.startsWith(leading)) { | ||
700 | target = target.substring(leading.length()); | ||
701 | } | ||
702 | |||
703 | return target; | ||
704 | } | ||
705 | |||
706 | /** | ||
707 | * Return a string with variable substitutions in place. | ||
708 | * | ||
709 | * @param expression | ||
710 | * @return Input string with any substitutions from this file. | ||
711 | */ | ||
712 | public String substitute(String expression, Map mo) { | ||
713 | |||
714 | List vars = parseVars(expression); | ||
715 | |||
716 | for (Iterator i = vars.iterator(); i.hasNext();) { | ||
717 | String varName = (String) i.next(); | ||
718 | String varToken = "${" + varName + "}"; | ||
719 | |||
720 | if (mo.containsKey(varName)) { | ||
721 | expression = expression.replace(varToken, (String) mo.get(varName)); | ||
722 | } else if (System.getProperty(varName) != null) { | ||
723 | expression = expression.replace(varToken, System.getProperty(varName)); | ||
724 | } else if (varName.toUpperCase().equals("HOME")) { | ||
725 | expression = expression.replace(varToken, System.getProperty("user.home")); | ||
726 | } | ||
727 | } | ||
728 | |||
729 | return expression; | ||
730 | } | ||
731 | |||
732 | public Collection values() { | ||
733 | try { | ||
734 | checkValidAndLock(true); | ||
735 | return properties.values(); | ||
736 | } catch (Exception e) { | ||
737 | e.printStackTrace(); | ||
738 | return null; | ||
739 | }finally { | ||
740 | rlock.unlock(); | ||
741 | } | ||
742 | } | ||
743 | |||
744 | public void changeNotified(IResource[] added, IResource[] removed, IResource[] changed) { | ||
745 | wlock.lock(); | ||
746 | try { | ||
747 | if (initialized && (removed != null || changed != null)) { | ||
748 | for(int i=0;removed != null && i<removed.length;i++) { | ||
749 | if (this.depends.contains(removed[i].getLocationURI())) { | ||
750 | initialized = false; | ||
751 | return; | ||
752 | } | ||
753 | } | ||
754 | if (!depends.isEmpty()) { | ||
755 | for(int i=0;changed != null && i<changed.length;i++) { | ||
756 | if (changed[i].getLocation() != null && this.depends.contains(changed[i].getLocation().toString())) { | ||
757 | initialized = false; | ||
758 | return; | ||
759 | } | ||
760 | } | ||
761 | } | ||
762 | } | ||
763 | } | ||
764 | finally { | ||
765 | wlock.unlock(); | ||
766 | } | ||
767 | } | ||
768 | |||
769 | public Map<String, String> getProperties() { | ||
770 | return (Map<String, String>) properties; | ||
771 | } | ||
772 | |||
773 | public ProjectInfo getProjectInfo() { | ||
774 | return pinfo; | ||
775 | } | ||
776 | |||
777 | public boolean hasErrorOccured() { | ||
778 | return errorOccured; | ||
779 | } | ||
780 | |||
781 | public String getErrorLines() { | ||
782 | return errorLines; | ||
783 | } | ||
784 | |||
785 | } | ||