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.java45
-rw-r--r--plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBSession.java785
-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/ProjectInfoHelper.java64
-rw-r--r--plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ShellSession.java209
7 files changed, 1207 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..9092759
--- /dev/null
+++ b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/BBRecipe.java
@@ -0,0 +1,45 @@
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 *******************************************************************************/
12package org.yocto.bc.bitbake;
13
14import java.io.IOException;
15import java.net.URI;
16
17/**
18 * Represents the bitbake environment of a recipe package.
19 * @author kgilmer
20 *
21 */
22public class BBRecipe extends BBSession {
23 private final BBSession session;
24 private final URI fileURI;
25
26 public BBRecipe(BBSession session, URI filePath) throws IOException {
27 super(session.shell, session.pinfo.getOriginalURI());
28 this.session = session;
29 this.fileURI = filePath;
30 this.parsingCmd = "DISABLE_SANITY_CHECKS=\"1\" bitbake -e -b " + filePath.getPath() + " >& " + BB_ENV_FILE;
31 }
32
33 @Override
34 public void initialize() throws Exception {
35 if (this.size() == 0) {
36 //System.out.println("Failed to parse " + fileURI);
37 //throw new IOException("Failed to parse " + filePath);
38 }
39 }
40
41 @Override
42 protected URI getDefaultDepends() {
43 return this.fileURI;
44 }
45}
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 *******************************************************************************/
12package org.yocto.bc.bitbake;
13
14import java.io.BufferedReader;
15import java.io.File;
16import java.io.FileFilter;
17import java.io.IOException;
18import java.io.StringReader;
19import java.io.InputStream;
20import java.io.InputStreamReader;
21import java.net.URI;
22import java.util.ArrayList;
23import java.util.Arrays;
24import java.util.Collection;
25import java.util.Hashtable;
26import java.util.Iterator;
27import java.util.List;
28import java.util.Map;
29import java.util.Set;
30import java.util.Stack;
31import java.util.concurrent.locks.ReentrantReadWriteLock;
32import java.util.concurrent.locks.Lock;
33
34import org.eclipse.core.resources.IFile;
35import org.eclipse.core.resources.IProject;
36import org.eclipse.core.resources.IResource;
37import org.eclipse.core.runtime.IProgressMonitor;
38import org.eclipse.core.runtime.IStatus;
39import org.eclipse.core.runtime.NullProgressMonitor;
40import org.eclipse.core.runtime.Status;
41import org.eclipse.jface.preference.JFacePreferences;
42import org.eclipse.jface.resource.JFaceResources;
43import org.eclipse.rse.core.model.IHost;
44import org.eclipse.ui.console.ConsolePlugin;
45import org.eclipse.ui.console.IConsole;
46import org.eclipse.ui.console.IConsoleManager;
47import org.eclipse.ui.console.MessageConsole;
48import org.eclipse.ui.console.MessageConsoleStream;
49import org.eclipse.ui.progress.WorkbenchJob;
50
51import org.yocto.bc.ui.model.IModelElement;
52import org.yocto.bc.ui.model.ProjectInfo;
53import org.yocto.remote.utils.RemoteHelper;
54import 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 */
63public 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}
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/ProjectInfoHelper.java b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ProjectInfoHelper.java
new file mode 100644
index 0000000..800fe2b
--- /dev/null
+++ b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ProjectInfoHelper.java
@@ -0,0 +1,64 @@
1/*****************************************************************************
2 * Copyright (c) 2013 Ken Gilmer, 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 *******************************************************************************/
12package org.yocto.bc.bitbake;
13
14import java.io.BufferedReader;
15import java.io.File;
16import java.io.FileOutputStream;
17import java.io.FileReader;
18import java.io.IOException;
19import java.net.URI;
20
21import org.eclipse.core.resources.IProject;
22import org.eclipse.core.resources.ResourcesPlugin;
23
24import org.yocto.bc.ui.model.ProjectInfo;
25
26/**
27 * A helper class for ProjectInfo related tasks.
28 *
29 * @author kgilmer
30 *
31 */
32public class ProjectInfoHelper {
33 public static final String OEFS_SCHEME = "OEFS://";
34 public static final String FILE_SCHEME = "file";
35 public static final String RSE_SCHEME = "rse";
36
37 protected static final String DEFAULT_INIT_SCRIPT = "oe-init-build-env";
38 /**
39 * @param path
40 * @return The path to bitbake init script
41 * @throws IOException
42 */
43 public static String getInitScriptPath(URI uri) throws IOException {
44 String val = uri.getPath() + "/" + DEFAULT_INIT_SCRIPT;
45 return val;
46 }
47
48 public static String getProjectName(URI projectRoot) {
49 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
50 for (int i = 0; i < projects.length; ++i) {
51 try {
52 if (projects[i].getLocationURI().equals(projectRoot)) {
53 return projects[i].getName();
54 }
55
56 } catch (Exception e) {
57 // TODO Auto-generated catch block
58 e.printStackTrace();
59 }
60 }
61
62 return null;
63 }
64}
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..0e262b1
--- /dev/null
+++ b/plugins/org.yocto.bc.ui/src/org/yocto/bc/bitbake/ShellSession.java
@@ -0,0 +1,209 @@
1/*****************************************************************************
2 * Copyright (c) 2013 Ken Gilmer, 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 *******************************************************************************/
12package org.yocto.bc.bitbake;
13
14import java.io.BufferedReader;
15import java.io.File;
16import java.io.IOException;
17import java.io.InputStream;
18import java.io.InputStreamReader;
19import java.io.OutputStream;
20import java.io.Writer;
21
22import org.eclipse.core.runtime.IProgressMonitor;
23import org.eclipse.core.runtime.NullProgressMonitor;
24import org.eclipse.rse.core.model.IHost;
25import org.eclipse.rse.services.files.IHostFile;
26import org.yocto.bc.ui.model.ProjectInfo;
27import org.yocto.remote.utils.ICommandResponseHandler;
28import org.yocto.remote.utils.RemoteHelper;
29import org.yocto.remote.utils.YoctoCommand;
30
31/**
32 * A class for Linux shell sessions.
33 * @author kgilmer
34 *
35 */
36public class ShellSession {
37 private volatile boolean interrupt = false;
38 /**
39 * String used to isolate command execution
40 */
41 public static final String TERMINATOR = "#234o987dsfkcqiuwey18837032843259d";
42 public static final String LT = System.getProperty("line.separator");
43 public static final String exportCmd = "export BB_ENV_EXTRAWHITE=\\\"DISABLE_SANITY_CHECKS $BB_ENV_EXTRAWHITE\\\"";
44 public static final String exportColumnsCmd = "export COLUMNS=1000";
45 private static final String BUILD_DIR = "/build/";
46
47
48 public static String getFilePath(String file) throws IOException {
49 File f = new File(file);
50
51 if (!f.exists() || f.isDirectory()) {
52 throw new IOException("Path passed is not a file: " + file);
53 }
54
55 StringBuffer sb = new StringBuffer();
56
57 String elems[] = file.split("//");
58
59 for (int i = 0; i < elems.length - 1; ++i) {
60 sb.append(elems[i]);
61 sb.append("//");
62 }
63
64 return sb.toString();
65 }
66 private Process process;
67
68 private OutputStream pos = null;
69 private String shellPath = null;
70 private final String initCmd;
71 private final IHostFile root;
72 private ProjectInfo projectInfo;
73
74 public ProjectInfo getProjectInfo() {
75 return projectInfo;
76 }
77
78 public void setProjectInfo(ProjectInfo projectInfo) {
79 this.projectInfo = projectInfo;
80 }
81
82 public ShellSession(ProjectInfo pInfo, IHostFile root, String initCmd) throws IOException {
83 this.projectInfo = pInfo;
84 this.root = root;
85 this.initCmd = initCmd;
86
87 initializeShell(new NullProgressMonitor());
88 }
89
90 private void initializeShell(IProgressMonitor monitor) throws IOException {
91 try {
92 if (root != null) {
93 IHost connection = projectInfo.getConnection();
94 RemoteHelper.handleRunCommandRemote(connection, new YoctoCommand("source " + initCmd, root.getAbsolutePath(), ""), monitor);
95 RemoteHelper.handleRunCommandRemote(connection, new YoctoCommand(exportCmd, root.getAbsolutePath(), ""), monitor);
96 } else {
97 throw new Exception("Root file not found!");
98 }
99 } catch (Exception e) {
100 e.printStackTrace();
101 }
102 }
103
104 synchronized
105 public String execute(String command) throws IOException {
106 return execute(command, false);
107 }
108
109 synchronized
110 public String execute(String command, boolean hasErrors) throws IOException {
111 try {
112 if (projectInfo.getConnection() != null) {
113 command = getInitCmd() + command;
114 RemoteHelper.handleRunCommandRemote(projectInfo.getConnection(), new YoctoCommand(command, getBuildDirAbsolutePath(), ""), new NullProgressMonitor());
115 return getBuildDirAbsolutePath();
116 }
117 return null;
118 } catch (Exception e) {
119 e.printStackTrace();
120 }
121 return null;
122 }
123
124 private String getBuildDirAbsolutePath() {
125 return root.getAbsolutePath() + BUILD_DIR;
126 }
127
128 private String getInitCmd() {
129 return "source " + initCmd + " " + getBuildDirAbsolutePath()
130 + " > tempsf; rm -rf tempsf;" + exportCmd + ";"
131 + exportColumnsCmd + ";" + "cd " + getBuildDirAbsolutePath()
132 + ";";
133 }
134
135 synchronized
136 public void execute(String command, String terminator, ICommandResponseHandler handler) throws IOException {
137 interrupt = false;
138 InputStream errIs = process.getErrorStream();
139 if (errIs.available() > 0) {
140 clearErrorStream(errIs);
141 }
142 sendToProcessAndTerminate(command);
143
144 BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
145 String std = null;
146
147 do {
148 if (errIs.available() > 0) {
149 byte[] msg = new byte[errIs.available()];
150
151 errIs.read(msg, 0, msg.length);
152 handler.response(new String(msg), true);
153 }
154
155 std = br.readLine();
156
157 if (std != null && !std.endsWith(terminator)) {
158 handler.response(std, false);
159 }
160
161 } while (std != null && !std.endsWith(terminator) && !interrupt);
162
163 if (interrupt) {
164 process.destroy();
165 initializeShell(null);
166 interrupt = false;
167 }
168 }
169
170 private void clearErrorStream(InputStream is) {
171
172 try {
173 byte b[] = new byte[is.available()];
174 is.read(b);
175 System.out.println("clearing: " + new String(b));
176 } catch (IOException e) {
177 e.printStackTrace();
178 //Ignore any error
179 }
180 }
181
182 /**
183 * Send command string to shell process and add special terminator string so
184 * reader knows when output is complete.
185 *
186 * @param command
187 * @throws IOException
188 */
189 private void sendToProcessAndTerminate(String command) throws IOException {
190 pos.write(command.getBytes());
191 pos.write(LT.getBytes());
192 pos.flush();
193 pos.write("echo $?".getBytes());
194 pos.write(TERMINATOR.getBytes());
195 pos.write(LT.getBytes());
196 pos.flush();
197 }
198
199 /**
200 * Interrupt any running processes.
201 */
202 public void interrupt() {
203 interrupt = true;
204 }
205
206 public void printError(String errorLines) {
207 RemoteHelper.getCommandHandler(projectInfo.getConnection()).response(errorLines, true);
208 }
209}