summaryrefslogtreecommitdiffstats
path: root/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake')
-rw-r--r--plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBCommonVars.java24
-rw-r--r--plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBLanguageHelper.java62
-rw-r--r--plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBRecipe.java50
-rw-r--r--plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBSession.java739
-rw-r--r--plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/IBBSessionListener.java18
-rw-r--r--plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ICommandResponseHandler.java15
-rw-r--r--plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ProjectInfoHelper.java105
-rw-r--r--plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ShellSession.java248
8 files changed, 1261 insertions, 0 deletions
diff --git a/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBCommonVars.java b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBCommonVars.java
new file mode 100644
index 0000000..d905e50
--- /dev/null
+++ b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBCommonVars.java
@@ -0,0 +1,24 @@
1/*****************************************************************************
2 * Copyright (c) 2009 Ken Gilmer
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 *******************************************************************************/
11package org.yocto.bc.bitbake;
12
13/**
14 * Constants for commonly used bitbake variables.
15 * @author kgilmer
16 *
17 */
18public class BBCommonVars {
19 public final static String WORKDIR = "WORKDIR";
20 public static final String PN = "PN";
21 public static final String S = "S";
22 public static final String PV = "PV";
23
24}
diff --git a/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBLanguageHelper.java b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBLanguageHelper.java
new file mode 100644
index 0000000..8ebe134
--- /dev/null
+++ b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBLanguageHelper.java
@@ -0,0 +1,62 @@
1/*****************************************************************************
2 * Copyright (c) 2009 Ken Gilmer
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 * Lianhao Lu (Intel) - add more bitbake keywords and functions
11 *******************************************************************************/
12package org.yocto.bc.bitbake;
13
14import java.util.Comparator;
15import java.util.Map;
16import java.util.TreeMap;
17
18/**
19 * Here is where all BitBake-related information is centralized.
20 * @author kgilmer
21 *
22 */
23public class BBLanguageHelper {
24
25 public static final String[] BITBAKE_KEYWORDS = new String[] { "inherit", "require", "export", "addtask", "python", "include", "fakeroot", "addhandler", "def"};
26 public static final String[] SHELL_KEYWORDS = new String[] { "while", "do", "if", "fi", "ln", "export", "install", "oe_libinstall", "for", "in", "done", "echo", "then", "cat", "rm", "rmdir", "mkdir", "printf", "exit", "test", "cd", "cp"};
27 public static final String[] BITBAKE_STANDARD_FUNCTIONS = new String[] { "fetch", "unpack", "patch", "configure", "compile", "install", "populate_sysroot", "package"};
28 public static final String BITBAKE_RECIPE_FILE_EXTENSION = "bb";
29
30 /**
31 * @return A map of names and descriptions of commonly used BitBake variables.
32 */
33 public static Map<String, String> getCommonBitbakeVariables() {
34 Map<String, String> m = new TreeMap<String, String>(new Comparator<Object>() {
35
36 public int compare(Object o1, Object o2) {
37
38 return ((String) o1).compareTo(((String) o2));
39 }
40
41 });
42
43 m.put("SECTION", "Category of package");
44 m.put("PR", "Package Release Number");
45 m.put("SRC_URI", "Location of package sources");
46 m.put("DESCRIPTION", "Description of package");
47 m.put("EXTRA_OEMAKE", "Extra flags to pass to the package makefile");
48 m.put("EXTRA_OECONF", "Extra configuration flags for the package makefile");
49 m.put("DEPENDS", "The set of build-time dependent packages");
50 m.put("RDEPENDS", "The set of run-time dependent packages");
51 m.put("HOMEPAGE", "Homepage of the package");
52 m.put("LICENSE", "License of the package");
53 m.put("FILES_${PN}", "Full file path of files on target.");
54 m.put("S", "Package source directory");
55 m.put("PV", "Package version");
56 m.put("AUTHOR", "Author or maintainer of package");
57 m.put("PRIORITY", "Priority of package");
58
59 return m;
60 }
61
62}
diff --git a/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBRecipe.java b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBRecipe.java
new file mode 100644
index 0000000..2b355ba
--- /dev/null
+++ b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBRecipe.java
@@ -0,0 +1,50 @@
1/*****************************************************************************
2 * Copyright (c) 2009 Ken Gilmer
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 *******************************************************************************/
11package org.yocto.bc.bitbake;
12
13import java.io.IOException;
14
15import org.eclipse.jface.preference.JFacePreferences;
16import org.eclipse.jface.resource.JFaceResources;
17import org.eclipse.swt.widgets.Display;
18import org.eclipse.ui.console.ConsolePlugin;
19import org.eclipse.ui.console.IConsole;
20import org.eclipse.ui.console.MessageConsole;
21import org.eclipse.ui.console.MessageConsoleStream;
22
23/**
24 * Represents the bitbake environment of a recipe package.
25 * @author kgilmer
26 *
27 */
28public class BBRecipe extends BBSession {
29 private final BBSession session;
30 private final String filePath;
31
32 public BBRecipe(BBSession session, String filePath) throws IOException {
33 super(session.shell, session.pinfo.getRootPath());
34 this.session = session;
35 this.filePath = filePath;
36 this.parsingCmd = "DISABLE_SANITY_CHECKS=1 bitbake -e -b " + filePath;
37 }
38
39 @Override
40 public void initialize() throws Exception {
41 if (this.size() == 0) {
42 //System.out.println("Failed to parse " + filePath);
43 //throw new IOException("Failed to parse " + filePath);
44 }
45 }
46
47 protected String getDefaultDepends() {
48 return this.filePath;
49 }
50}
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..e998bcd
--- /dev/null
+++ b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBSession.java
@@ -0,0 +1,739 @@
1/*****************************************************************************
2 * Copyright (c) 2009 Ken Gilmer
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 *******************************************************************************/
11package org.yocto.bc.bitbake;
12
13import java.io.BufferedReader;
14import java.io.File;
15import java.io.FileFilter;
16import java.io.IOException;
17import java.io.StringReader;
18import java.util.ArrayList;
19import java.util.Arrays;
20import java.util.Collection;
21import java.util.Hashtable;
22import java.util.Iterator;
23import java.util.List;
24import java.util.Map;
25import java.util.Set;
26import java.util.Stack;
27import java.util.concurrent.locks.ReentrantReadWriteLock;
28import java.util.concurrent.locks.Lock;
29
30import org.eclipse.core.resources.IFile;
31import org.eclipse.core.resources.IProject;
32import org.eclipse.core.resources.IResource;
33import org.eclipse.core.runtime.IProgressMonitor;
34import org.eclipse.core.runtime.IStatus;
35import org.eclipse.core.runtime.Status;
36import org.eclipse.jface.preference.JFacePreferences;
37import org.eclipse.jface.resource.JFaceResources;
38import org.eclipse.ui.console.ConsolePlugin;
39import org.eclipse.ui.console.IConsole;
40import org.eclipse.ui.console.IConsoleManager;
41import org.eclipse.ui.console.MessageConsole;
42import org.eclipse.ui.console.MessageConsoleStream;
43import org.eclipse.ui.progress.WorkbenchJob;
44
45import org.yocto.bc.ui.model.IModelElement;
46import org.yocto.bc.ui.model.ProjectInfo;
47
48/**
49 * BBSession encapsulates a global bitbake configuration and is the primary interface
50 * for actions against a BitBake installation.
51 *
52 * @author kgilmer
53 *
54 */
55public class BBSession implements IBBSessionListener, IModelElement, Map {
56 public static final int TYPE_VARIABLE_ASSIGNMENT = 1;
57 public static final int TYPE_UNKNOWN = 2;
58 public static final int TYPE_STATEMENT = 3;
59 public static final int TYPE_FLAG = 4;
60
61 public static final String BUILDDIR_INDICATORS [] = {
62 File.separatorChar + "conf" + File.separatorChar + "local.conf",
63 File.separatorChar + "conf" + File.separatorChar + "bblayers.conf",
64 };
65
66 protected final ProjectInfo pinfo;
67 protected final ShellSession shell;
68 protected Map properties = null;
69 protected List <String> depends = null;
70 protected boolean initialized = false;
71 protected MessageConsole sessionConsole;
72 private final ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock();
73 private final Lock rlock = rwlock.readLock();
74 private final Lock wlock = rwlock.writeLock();
75 protected String parsingCmd;
76 private boolean silent = false;
77
78 public BBSession(ShellSession ssession, String projectRoot) throws IOException {
79 shell = ssession;
80 this.pinfo = new ProjectInfo();
81 pinfo.setLocation(projectRoot);
82 pinfo.setInitScriptPath(ProjectInfoHelper.getInitScriptPath(projectRoot));
83 this.parsingCmd = "DISABLE_SANITY_CHECKS=1 bitbake -e";
84 }
85
86 public BBSession(ShellSession ssession, String projectRoot, boolean silent) throws IOException {
87 this(ssession, projectRoot);
88 this.silent = silent;
89 }
90
91 private Collection adapttoIPath(List<File> asList, IProject project) {
92
93 List pathList = new ArrayList();
94
95 for (Iterator i = asList.iterator(); i.hasNext();) {
96 File f = (File) i.next();
97 IFile ff = project.getFile(stripLeading(f.toString(), project.getLocationURI().getPath()));
98 if (ff.exists()) {
99 pathList.add(ff);
100 }
101 }
102
103 return pathList;
104 }
105
106 private String appendAll(String[] elems, int st) {
107 StringBuffer sb = new StringBuffer();
108
109 for (int i = st; i < elems.length; ++i) {
110 sb.append(elems[i]);
111 }
112
113 return sb.toString();
114 }
115
116 private int charCount(String trimmed, char c) {
117 int i = 0;
118 int p = 0;
119
120 while ((p = trimmed.indexOf(c, p)) > -1) {
121 i++;
122 p++;
123 }
124
125 return i;
126 }
127
128 public void clear() {
129 throw new RuntimeException("BB configuration is read-only.");
130 }
131
132 public boolean containsKey(Object arg0) {
133 try {
134 checkValidAndLock(true);
135 return properties.containsKey(arg0);
136 } catch (Exception e) {
137 e.printStackTrace();
138 return false;
139 }finally {
140 rlock.unlock();
141 }
142 }
143
144 public boolean containsValue(Object arg0) {
145 try {
146 checkValidAndLock(true);
147 return properties.containsValue(arg0);
148 } catch (Exception e) {
149 e.printStackTrace();
150 return false;
151 }finally {
152 rlock.unlock();
153 }
154 }
155
156 public Set entrySet() {
157 try {
158 checkValidAndLock(true);
159 return properties.entrySet();
160 } catch (Exception e) {
161 e.printStackTrace();
162 return null;
163 }finally {
164 rlock.unlock();
165 }
166 }
167
168 @Override
169 public boolean equals(Object arg0) {
170 try {
171 checkValidAndLock(true);
172 return properties.equals(arg0);
173 } catch (Exception e) {
174 e.printStackTrace();
175 return false;
176 }finally {
177 rlock.unlock();
178 }
179 }
180
181 public ShellSession getShell() {
182 return shell;
183 }
184
185 public String getProjInfoRoot() {
186 return pinfo.getRootPath();
187 }
188
189 /**
190 * Recursively generate list of Recipe files from a root directory.
191 *
192 * @param rootDir
193 * @param recipes
194 * @param fileExtension
195 * @param project
196 */
197 private void findRecipes(File rootDir, List recipes, final String fileExtension, IProject project) {
198 File[] children = rootDir.listFiles(new FileFilter() {
199
200 public boolean accept(File pathname) {
201 return pathname.isFile() && pathname.getName().endsWith(fileExtension);
202 }
203
204 });
205
206 if (children != null && children.length > 0) {
207 recipes.addAll(adapttoIPath(Arrays.asList(children), project));
208 }
209
210 File[] childDirs = rootDir.listFiles(new FileFilter() {
211
212 public boolean accept(File pathname) {
213 return pathname.isDirectory();
214 }
215
216 });
217
218 if (childDirs != null && childDirs.length > 0) {
219 for (int i = 0; i < childDirs.length; ++i) {
220 findRecipes(childDirs[i], recipes, fileExtension, project);
221 }
222 }
223 }
224
225 private Collection findRecipes(List paths, IProject project) {
226 List recipes = new ArrayList();
227
228 for (Iterator i = paths.iterator(); i.hasNext();) {
229 String rawPath = (String) i.next();
230 String[] elems = rawPath.split("\\*/\\*");
231
232 if (elems.length == 2) {
233
234 File rootDir = new File(elems[0]);
235
236 findRecipes(rootDir, recipes, elems[1], project);
237 }
238 }
239
240 return recipes;
241 }
242
243 public Object get(Object arg0) {
244 try {
245 checkValidAndLock(true);
246 return properties.get(arg0);
247 } catch (Exception e) {
248 e.printStackTrace();
249 return null;
250 }finally {
251 rlock.unlock();
252 }
253 }
254
255 private List getBitBakeKeywords() {
256 return Arrays.asList(BBLanguageHelper.BITBAKE_KEYWORDS);
257 }
258
259 /**
260 * @return A MessageConsole for this BB session.
261 */
262 public MessageConsole getConsole() {
263 if (sessionConsole == null) {
264 String cName = ProjectInfoHelper.getProjectName(pinfo.getRootPath()) + " Console";
265 IConsoleManager conMan = ConsolePlugin.getDefault().getConsoleManager();
266 IConsole[] existing = conMan.getConsoles();
267 for (int i = 0; i < existing.length; i++)
268 if (cName.equals(existing[i].getName())) {
269 sessionConsole = (MessageConsole) existing[i];
270 break;
271 }
272 if (sessionConsole == null) {
273 sessionConsole = new MessageConsole(cName, null);
274 conMan.addConsoles(new IConsole[] { sessionConsole });
275 }
276 }
277
278 ConsolePlugin.getDefault().getConsoleManager().showConsoleView(sessionConsole);
279
280 return sessionConsole;
281 }
282
283 private int getLineType(String line) {
284
285 if (line.contains("=")) {
286 return TYPE_VARIABLE_ASSIGNMENT;
287 }
288
289 for (Iterator i = getBitBakeKeywords().iterator(); i.hasNext();) {
290 if (line.startsWith((String) i.next())) {
291 return TYPE_STATEMENT;
292 }
293 }
294
295 if (line.contains(":")) {
296 return TYPE_FLAG;
297 }
298
299 return TYPE_UNKNOWN;
300 }
301
302 public Collection getRecipeFiles(IProject project) {
303 try {
304 checkValidAndLock(true);
305 if (!initialized) {
306 throw new RuntimeException(this.getClass().getName() + " is not initialized.");
307 }
308 String bbfiles = (String) this.properties.get("BBFILES");
309 List paths = parseBBFiles(bbfiles);
310 return findRecipes(paths, project);
311 } catch (Exception e) {
312 return null;
313 }
314 finally {
315 rlock.unlock();
316 }
317 }
318
319 @Override
320 public int hashCode() {
321 try {
322 checkValidAndLock(true);
323 return properties.hashCode();
324 } catch (Exception e) {
325 e.printStackTrace();
326 return 0;
327 }finally {
328 rlock.unlock();
329 }
330 }
331
332 protected int checkExecuteError(String result, int code) {
333 String recipe = getDefaultDepends();
334 String text = "Parsing " + ((recipe != null) ? ("recipe " + recipe) : "base configurations");
335 if (code != 0) {
336 text = text + " ERROR!\n" + result;
337 }else {
338 text = text + " SUCCESS.\n";
339 }
340 if(!silent) {
341 displayInConsole(text, code, false);
342 }
343 return code;
344 }
345
346 protected void displayInConsole(final String result, final int code, boolean clear) {
347 MessageConsole console = getConsole();
348 final MessageConsoleStream info = console.newMessageStream();
349 if(clear)
350 console.clearConsole();
351 new WorkbenchJob("Display parsing result") {
352 public IStatus runInUIThread(IProgressMonitor monitor) {
353 if(code != 0) {
354 info.setColor(JFaceResources.getColorRegistry().get(JFacePreferences.ERROR_COLOR));
355 }
356 try {
357 info.println(result);
358 info.close();
359 }catch (Exception e) {
360 e.printStackTrace();
361 }
362 return Status.OK_STATUS;
363 }
364 }.schedule();
365 }
366
367 private void checkValidAndLock(boolean rdlck) throws Exception {
368 if(rdlck)
369 rlock.lock();
370 else
371 wlock.lock();
372 if(!initialized) {
373 //upgrade lock manually
374 if(rdlck) {
375 rlock.unlock();
376 wlock.lock();
377 }
378 try {
379 if(!initialized) { //recheck
380 int [] codes = {-1};
381 String result = shell.execute(parsingCmd, codes);
382 if(checkExecuteError(result, codes[0]) == 0) {
383 properties = parseBBEnvironment(result);
384 } else {
385 properties = parseBBEnvironment("");
386 }
387 initialized = true;
388 }
389 } finally {
390 //downgrade lock
391 if(rdlck) {
392 rlock.lock();
393 wlock.unlock();
394 }
395 }
396 }
397 //not release lock
398 }
399
400 public void initialize() throws Exception {
401 try {
402 checkValidAndLock(false);
403 }finally {
404 wlock.unlock();
405 }
406 }
407
408 private boolean isBlockEnd(String trimmed) {
409 return charCount(trimmed, '}') > charCount(trimmed, '{');
410 // return trimmed.indexOf('}') > -1 && trimmed.indexOf('{') == -1;
411 }
412
413 private boolean isBlockStart(String trimmed) {
414 return charCount(trimmed, '{') > charCount(trimmed, '}');
415 // return trimmed.indexOf('{') > -1 && trimmed.indexOf('}') == -1;
416 }
417
418 public boolean isEmpty() {
419 try {
420 checkValidAndLock(true);
421 return properties.isEmpty();
422 } catch (Exception e) {
423 e.printStackTrace();
424 return true;
425 }finally {
426 rlock.unlock();
427 }
428 }
429
430 public Set keySet() {
431 try {
432 checkValidAndLock(true);
433 return properties.keySet();
434 } catch (Exception e) {
435 e.printStackTrace();
436 return null;
437 }finally {
438 rlock.unlock();
439 }
440 }
441
442 protected void parse(String content, Map outMap) throws Exception {
443 BufferedReader reader = new BufferedReader(new StringReader(content));
444 String line;
445 boolean inLine = false;
446 StringBuffer sb = null;
447 Stack blockStack = new Stack();
448
449 while ((line = reader.readLine()) != null) {
450 String trimmed = line.trim();
451 if (trimmed.length() == 0 || line.startsWith("#")) {
452 // weed out the blank and comment lines
453 continue;
454 }
455 // Now we look for block start ends, and ignore all code within
456 // blocks.
457 if (isBlockStart(trimmed)) {
458 blockStack.push(trimmed);
459 } else if (isBlockEnd(trimmed)) {
460 blockStack.pop();
461
462 }
463
464 if (!blockStack.isEmpty()) {
465 // we are in a code block, continue until we break into global
466 // scope.
467 continue;
468 }
469 if (trimmed.endsWith("\\")) {
470 if (!inLine) {
471 inLine = true;
472 sb = new StringBuffer(trimmed.substring(0, trimmed.length() - 1));
473 } else {
474 sb.append(trimmed.substring(0, trimmed.length() - 1));
475 }
476 // Only parse the line when we have the complete contents.
477 continue;
478 } else if (inLine) {
479 inLine = false;
480 line = sb.toString();
481 }
482
483 parseLine(line, outMap);
484 }
485 }
486
487 private void parseAdditiveAssignment(String line, String operator, Map mo) throws Exception {
488 String[] elems = splitAssignment(line, "\\+=");
489
490 if (elems.length != 2) {
491 throw new Exception("Unable to parse additive variable assignment in line: " + line);
492 }
493
494 if (!mo.containsKey(elems[0])) {
495 mo.put(elems[0].trim(), elems[1]);
496 } else {
497 String existing = (String) mo.get(elems[0]);
498 if (operator.equals("+=")) {
499 mo.put(elems[0], existing + elems[1]);
500 } else {
501 mo.put(elems[0], elems[1] + existing);
502 }
503 }
504 }
505
506 protected String getDefaultDepends() {
507 return null;
508 }
509
510 protected Map parseBBEnvironment(String bbOut) throws Exception {
511 Map env = new Hashtable();
512 this.depends = new ArrayList<String>();
513
514 parse(bbOut, env);
515
516 String included = (String) env.get("BBINCLUDED");
517 if(getDefaultDepends() != null) {
518 this.depends.add(getDefaultDepends());
519 }
520 if(included != null) {
521 this.depends.addAll(Arrays.asList(included.split(" ")));
522 }
523
524 return env;
525 }
526
527
528 private List parseBBFiles(String bbfiles) {
529 return Arrays.asList(bbfiles.split(" "));
530 }
531
532 //Map delegate methods
533
534 private void parseConditionalAssignment(String line, Map mo) throws Exception {
535 String[] elems = splitAssignment(line, "\\?=");
536
537 if (elems.length != 2) {
538 throw new Exception("Unable to parse conditional variable assignment in line: " + line);
539 }
540
541 if (!mo.containsKey(elems[0].trim())) {
542 mo.put(elems[0].trim(), elems[1].trim());
543 }
544 }
545
546 private void parseImmediateAssignment(String line, String delimiter, Map mo) throws Exception {
547 String[] elems = splitAssignment(line, delimiter);
548
549 mo.put(elems[0], substitute(elems[1], mo));
550 }
551
552 private void parseKeyValue(String line, String delimiter, Map mo) throws Exception {
553 String[] elems = splitAssignment(line, delimiter);
554
555 mo.put(elems[0], elems[1]);
556 }
557
558 private void parseLine(String line, Map mo) throws Exception {
559
560 switch (getLineType(line)) {
561 case TYPE_VARIABLE_ASSIGNMENT:
562 parseVariableAssignment(line, mo);
563 break;
564 case TYPE_STATEMENT:
565 case TYPE_FLAG:
566 // for now ignore statements
567 break;
568 case TYPE_UNKNOWN:
569 // we'll gloss over unknown lines as well;
570 break;
571 default:
572 throw new Exception("Unable to parse line: " + line);
573 }
574 }
575
576 private void parseVariableAssignment(String line, Map mo) throws Exception {
577 if (line.contains("?=")) {
578 parseConditionalAssignment(line, mo);
579 } else if (line.contains("+=")) {
580 parseAdditiveAssignment(line, "+=", mo);
581 } else if (line.contains("=+")) {
582 parseAdditiveAssignment(line, "=+", mo);
583 } else if (line.contains(":=")) {
584 parseImmediateAssignment(line, ":=", mo);
585 } else {
586 parseKeyValue(line, "=", mo);
587 }
588
589 }
590
591 private List parseVars(String line) {
592 List l = new ArrayList();
593
594 int i = 0;
595
596 while ((i = line.indexOf("${", i)) > -1) {
597 int i2 = line.indexOf("}", i);
598
599 l.add(line.subSequence(i + 2, i2));
600 i++;
601 }
602
603 return l;
604 }
605
606 public Object put(Object arg0, Object arg1) {
607 throw new RuntimeException("BB configuration is read-only.");
608 }
609
610 public void putAll(Map arg0) {
611 throw new RuntimeException("BB configuration is read-only.");
612 }
613
614 public Object remove(Object arg0) {
615 throw new RuntimeException("BB configuration is read-only.");
616 }
617
618 private String removeQuotes(String line) {
619 line = line.trim();
620
621 if (line.startsWith("\"")) {
622 line = line.substring(1);
623 }
624
625 if (line.endsWith("\"")) {
626 line = line.substring(0, line.length() - 1);
627 }
628
629 return line;
630 }
631
632 public int size() {
633 try {
634 checkValidAndLock(true);
635 return properties.size();
636 }catch (Exception e) {
637 e.printStackTrace();
638 return 0;
639 }finally {
640 rlock.unlock();
641 }
642 }
643
644 private String[] splitAssignment(String line, String seperator) throws Exception {
645 String[] elems = line.split(seperator);
646
647 if (elems.length < 2) {
648 throw new Exception("Unable to parse assignment in line: " + line);
649 } else if (elems.length == 2) {
650
651 elems[0] = elems[0].trim(); // Clean up trailing or leading spaces.
652 if (elems[0].startsWith("export ")) {
653 elems[0] = elems[0].substring("export ".length()).trim();
654 }
655 elems[1] = removeQuotes(elems[1]); // Evaluate variables
656
657 return elems;
658 } else {
659 String[] retVal = new String[2];
660
661 retVal[0] = elems[0];
662 if (retVal[0].startsWith("export ")) {
663 retVal[0] = retVal[0].substring("export ".length()).trim();
664 }
665 retVal[1] = appendAll(elems, 1);
666
667 return retVal;
668 }
669 }
670
671 private String stripLeading(String target, String leading) {
672 if (target.startsWith(leading)) {
673 target = target.substring(leading.length());
674 }
675
676 return target;
677 }
678
679 /**
680 * Return a string with variable substitutions in place.
681 *
682 * @param expression
683 * @return Input string with any substitutions from this file.
684 */
685 public String substitute(String expression, Map mo) {
686
687 List vars = parseVars(expression);
688
689 for (Iterator i = vars.iterator(); i.hasNext();) {
690 String varName = (String) i.next();
691 String varToken = "${" + varName + "}";
692
693 if (mo.containsKey(varName)) {
694 expression = expression.replace(varToken, (String) mo.get(varName));
695 } else if (System.getProperty(varName) != null) {
696 expression = expression.replace(varToken, System.getProperty(varName));
697 } else if (varName.toUpperCase().equals("HOME")) {
698 expression = expression.replace(varToken, System.getProperty("user.home"));
699 }
700 }
701
702 return expression;
703 }
704
705 public Collection values() {
706 try {
707 checkValidAndLock(true);
708 return properties.values();
709 } catch (Exception e) {
710 e.printStackTrace();
711 return null;
712 }finally {
713 rlock.unlock();
714 }
715 }
716
717 public void changeNotified(IResource[] added, IResource[] removed, IResource[] changed) {
718 wlock.lock();
719 try {
720 if (initialized && (removed != null || changed != null)) {
721 for(int i=0;removed != null && i<removed.length;i++) {
722 if (this.depends.contains(removed[i].getLocation().toString())) {
723 initialized = false;
724 return;
725 }
726 }
727 for(int i=0;changed != null && i<changed.length;i++) {
728 if (this.depends.contains(changed[i].getLocation().toString())) {
729 initialized = false;
730 return;
731 }
732 }
733 }
734 }
735 finally {
736 wlock.unlock();
737 }
738 }
739}
diff --git a/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/IBBSessionListener.java b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/IBBSessionListener.java
new file mode 100644
index 0000000..4d0054f
--- /dev/null
+++ b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/IBBSessionListener.java
@@ -0,0 +1,18 @@
1/*******************************************************************************
2 * Copyright (c) 2012 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 * Intel - initial API and implementation
10 *******************************************************************************/
11
12package org.yocto.bc.bitbake;
13
14import org.eclipse.core.resources.IResource;
15
16public interface IBBSessionListener {
17 public void changeNotified(IResource[] added, IResource[] removed, IResource[] changed);
18}
diff --git a/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ICommandResponseHandler.java b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ICommandResponseHandler.java
new file mode 100644
index 0000000..4c44352
--- /dev/null
+++ b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ICommandResponseHandler.java
@@ -0,0 +1,15 @@
1/*****************************************************************************
2 * Copyright (c) 2009 Ken Gilmer
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 *******************************************************************************/
11package org.yocto.bc.bitbake;
12
13public interface ICommandResponseHandler {
14 public void response(String line, boolean isError);
15}
diff --git a/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ProjectInfoHelper.java b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ProjectInfoHelper.java
new file mode 100644
index 0000000..25dac97
--- /dev/null
+++ b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ProjectInfoHelper.java
@@ -0,0 +1,105 @@
1/*****************************************************************************
2 * Copyright (c) 2009 Ken Gilmer
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 *******************************************************************************/
11package org.yocto.bc.bitbake;
12
13import java.io.BufferedReader;
14import java.io.File;
15import java.io.FileOutputStream;
16import java.io.FileReader;
17import java.io.IOException;
18
19import org.eclipse.core.resources.IProject;
20import org.eclipse.core.resources.ResourcesPlugin;
21
22import org.yocto.bc.ui.model.ProjectInfo;
23
24/**
25 * A helper class for ProjectInfo related tasks.
26 *
27 * @author kgilmer
28 *
29 */
30public class ProjectInfoHelper {
31
32 protected static final String DEFAULT_INIT_SCRIPT = "oe-init-build-env";
33 /**
34 * @param path
35 * @return The path to bitbake init script
36 * @throws IOException
37 */
38 public static String getInitScriptPath(String path) throws IOException {
39 String val = path + File.separator + DEFAULT_INIT_SCRIPT;
40
41 File inFile = new File(path, ".eclipse-data");
42 if(inFile.exists()) {
43 BufferedReader br = new BufferedReader(new FileReader(inFile));
44 val = br.readLine();
45 br.close();
46 }
47
48 return val;
49 }
50
51 public static String getInitScript(String path) throws IOException {
52 File inFile = new File(path);
53 BufferedReader br = new BufferedReader(new FileReader(inFile));
54 StringBuffer sb = new StringBuffer();
55 String line = null;
56
57 while ((line = br.readLine()) != null) {
58 sb.append(line);
59 }
60
61 br.close();
62
63 return sb.toString();
64 }
65
66 public static String getProjectName(String projectRoot) {
67 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
68 for (int i = 0; i < projects.length; ++i) {
69 try {
70 if (projects[i].getLocationURI().getPath().equals(projectRoot)) {
71 return projects[i].getName();
72 }
73
74 } catch (Exception e) {
75 // TODO Auto-generated catch block
76 e.printStackTrace();
77 }
78 }
79
80 return null;
81 }
82
83 /**
84 * This method will store the path to the bitbake init script for future
85 * reference.
86 *
87 * @param path
88 * @param projInfo
89 * @throws IOException
90 */
91 public static void store(String path, ProjectInfo projInfo) throws IOException {
92 writeToFile(path, projInfo.getInitScriptPath());
93 }
94
95 private static void writeToFile(String path, String init) throws IOException {
96 File outFile = new File(path, ".eclipse-data");
97 FileOutputStream fos = new FileOutputStream(outFile);
98
99 fos.write(init.getBytes());
100
101 fos.flush();
102 fos.close();
103 }
104
105}
diff --git a/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ShellSession.java b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ShellSession.java
new file mode 100644
index 0000000..4719865
--- /dev/null
+++ b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ShellSession.java
@@ -0,0 +1,248 @@
1/*****************************************************************************
2 * Copyright (c) 2009 Ken Gilmer
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 *******************************************************************************/
11package org.yocto.bc.bitbake;
12
13import java.io.BufferedReader;
14import java.io.File;
15import java.io.IOException;
16import java.io.InputStream;
17import java.io.InputStreamReader;
18import java.io.OutputStream;
19import java.io.Writer;
20
21/**
22 * A class for Linux shell sessions.
23 * @author kgilmer
24 *
25 */
26public class ShellSession {
27 /**
28 * Bash shell
29 */
30 public static final int SHELL_TYPE_BASH = 1;
31 /**
32 * sh shell
33 */
34 public static final int SHELL_TYPE_SH = 2;
35 private volatile boolean interrupt = false;
36 /**
37 * String used to isolate command execution
38 */
39 public static final String TERMINATOR = "#234o987dsfkcqiuwey18837032843259d";
40 public static final String LT = System.getProperty("line.separator");
41
42 public static String getFilePath(String file) throws IOException {
43 File f = new File(file);
44
45 if (!f.exists() || f.isDirectory()) {
46 throw new IOException("Path passed is not a file: " + file);
47 }
48
49 StringBuffer sb = new StringBuffer();
50
51 String elems[] = file.split(File.separator);
52
53 for (int i = 0; i < elems.length - 1; ++i) {
54 sb.append(elems[i]);
55 sb.append(File.separator);
56 }
57
58 return sb.toString();
59 }
60 private Process process;
61
62 private OutputStream pos = null;
63 //private File initFile = null;
64 private String shellPath = null;
65 private final String initCmd;
66 private final File root;
67 private final Writer out;
68
69
70 public ShellSession(int shellType, File root, String initCmd, Writer out) throws IOException {
71 this.root = root;
72 this.initCmd = initCmd;
73 if (out == null) {
74 this.out = new NullWriter();
75 } else {
76 this.out = out;
77 }
78 if (shellType == SHELL_TYPE_SH) {
79 shellPath = "/bin/sh";
80 }
81 shellPath = "/bin/bash";
82
83 initializeShell();
84 }
85
86 private void initializeShell() throws IOException {
87 process = Runtime.getRuntime().exec(shellPath);
88 pos = process.getOutputStream();
89
90 if (root != null) {
91 out.write(execute("cd " + root.getAbsolutePath()));
92 }
93
94 if (initCmd != null) {
95 out.write(execute("source " + initCmd));
96 }
97 }
98
99 synchronized
100 public String execute(String command) throws IOException {
101 return execute(command, (int [])null);
102 }
103
104 synchronized
105 public String execute(String command, int[] retCode) throws IOException {
106 String errorMessage = null;
107 interrupt = false;
108 out.write(command);
109 out.write(LT);
110
111 sendToProcessAndTerminate(command);
112
113 if (process.getErrorStream().available() > 0) {
114 byte[] msg = new byte[process.getErrorStream().available()];
115
116 process.getErrorStream().read(msg, 0, msg.length);
117 out.write(new String(msg));
118 out.write(LT);
119 errorMessage = "Error while executing: " + command + LT + new String(msg);
120 }
121
122 BufferedReader br = new BufferedReader(new InputStreamReader(process
123 .getInputStream()));
124
125 StringBuffer sb = new StringBuffer();
126 String line = null;
127
128 while (((line = br.readLine()) != null) && !line.endsWith(TERMINATOR) && !interrupt) {
129 sb.append(line);
130 sb.append(LT);
131 out.write(line);
132 out.write(LT);
133 }
134
135 if (interrupt) {
136 process.destroy();
137 initializeShell();
138 interrupt = false;
139 }else if (line != null && retCode != null) {
140 try {
141 retCode[0]=Integer.parseInt(line.substring(0,line.lastIndexOf(TERMINATOR)));
142 }catch (NumberFormatException e) {
143 throw new IOException("Can NOT get return code" + command + LT + line);
144 }
145 }
146
147 if (errorMessage != null) {
148 throw new IOException(errorMessage);
149 }
150
151 return sb.toString();
152 }
153
154synchronized
155 public void execute(String command, ICommandResponseHandler handler) throws IOException {
156 System.out.println(command);
157 execute(command, TERMINATOR, handler);
158 }
159
160 synchronized
161 public void execute(String command, String terminator, ICommandResponseHandler handler) throws IOException {
162 interrupt = false;
163 InputStream errIs = process.getErrorStream();
164 if (errIs.available() > 0) {
165 clearErrorStream(errIs);
166 }
167 sendToProcessAndTerminate(command);
168
169 BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
170 String std = null;
171
172 do {
173 if (errIs.available() > 0) {
174 byte[] msg = new byte[errIs.available()];
175
176 errIs.read(msg, 0, msg.length);
177 out.write(new String(msg));
178 handler.response(new String(msg), true);
179 }
180
181 std = br.readLine();
182
183 if (std != null && !std.endsWith(terminator)) {
184 out.write(std);
185 handler.response(std, false);
186 }
187
188 } while (std != null && !std.endsWith(terminator) && !interrupt);
189
190 if (interrupt) {
191 process.destroy();
192 initializeShell();
193 interrupt = false;
194 }
195 }
196
197 private void clearErrorStream(InputStream is) {
198
199 try {
200 byte b[] = new byte[is.available()];
201 is.read(b);
202 System.out.println("clearing: " + new String(b));
203 } catch (IOException e) {
204 e.printStackTrace();
205 //Ignore any error
206 }
207 }
208
209 /**
210 * Send command string to shell process and add special terminator string so
211 * reader knows when output is complete.
212 *
213 * @param command
214 * @throws IOException
215 */
216 private void sendToProcessAndTerminate(String command) throws IOException {
217 pos.write(command.getBytes());
218 pos.write(LT.getBytes());
219 pos.flush();
220 pos.write("echo $?".getBytes());
221 pos.write(TERMINATOR.getBytes());
222 pos.write(LT.getBytes());
223 pos.flush();
224 }
225
226 /**
227 * Interrupt any running processes.
228 */
229 public void interrupt() {
230 interrupt = true;
231 }
232
233 private class NullWriter extends Writer {
234
235 @Override
236 public void close() throws IOException {
237 }
238
239 @Override
240 public void flush() throws IOException {
241 }
242
243 @Override
244 public void write(char[] cbuf, int off, int len) throws IOException {
245 }
246
247 }
248}