aboutsummaryrefslogtreecommitdiffstats
path: root/org.openembedded.bc.ui/src
diff options
context:
space:
mode:
Diffstat (limited to 'org.openembedded.bc.ui/src')
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBCommonVars.java24
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBLanguageHelper.java61
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBRecipe.java45
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBSession.java513
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ICommandResponseHandler.java15
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ProjectInfoHelper.java102
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ShellSession.java233
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ShellTest2.java111
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/Activator.java209
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/AbstractBitbakeCommandAction.java199
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeBuildRecipeAction.java24
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeCleanRecipeAction.java26
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeImportAction.java106
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeRebuildRecipeAction.java29
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/LaunchNewBitBakeProjectWizardAction.java48
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/LaunchNewRecipeWizardAction.java48
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/LaunchVariableWizardAction.java78
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/builder/BitbakeBuilder.java178
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/builder/BitbakeCommanderNature.java89
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/builder/ToggleNatureAction.java107
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/decorators/ProjectDecorator.java48
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BBVariableTextHover.java119
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BitBakeDocumentProvider.java61
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BitBakeFileEditor.java86
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BitBakeSourceViewerConfiguration.java193
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/CustomFunctionRule.java94
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeCompletionProcessor.java125
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeEditorActionContributor.java47
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeEditorMessages.java21
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeEditorMessages.properties14
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/VariableRule.java69
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/Messages.java48
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEFile.java465
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEFileSystem.java81
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEFileSystemContributor.java30
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEIgnoreFile.java133
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/Policy.java108
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/model/IModelElement.java15
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/model/ProjectInfo.java48
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/perspectives/BitbakeCommanderPerspective.java87
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/popup/actions/NewAction.java43
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/views/RecipeContentProvider.java65
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/views/RecipeView.java165
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/FiniteStateWizard.java56
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/FiniteStateWizardPage.java148
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/NewBitBakeFileRecipeWizard.java185
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/NewBitBakeFileRecipeWizardPage.java221
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/importProject/BBCProjectPage.java234
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/importProject/ConsolePage.java121
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/importProject/ImportOEProjectWizard.java63
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/BBCProjectPage.java244
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/BitbakePage.java154
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/Flavor.java50
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/FlavorPage.java182
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallJob.java170
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallParameter.java99
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallScriptHelper.java52
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallWizard.java105
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/OptionsPage.java313
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/ProgressPage.java191
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/WelcomePage.java96
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/newproject/BBConfigurationInitializeOperation.java59
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/newproject/CreateBBCProjectOperation.java107
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/variable/VariablePage.java262
-rw-r--r--org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/variable/VariableWizard.java43
65 files changed, 7565 insertions, 0 deletions
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBCommonVars.java b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBCommonVars.java
new file mode 100644
index 0000000..0bd1a44
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBCommonVars.java
@@ -0,0 +1,24 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.bitbake;
+
+/**
+ * Constants for commonly used bitbake variables.
+ * @author kgilmer
+ *
+ */
+public class BBCommonVars {
+ public final static String WORKDIR = "WORKDIR";
+ public static final String PN = "PN";
+ public static final String S = "S";
+ public static final String PV = "PV";
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBLanguageHelper.java b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBLanguageHelper.java
new file mode 100644
index 0000000..249bdee
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBLanguageHelper.java
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.bitbake;
+
+import java.util.Comparator;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Here is where all BitBake-related information is centralized.
+ * @author kgilmer
+ *
+ */
+public class BBLanguageHelper {
+
+ public static final String[] BITBAKE_KEYWORDS = new String[] { "inherit", "require", "export", "addtask", "python", "include"};
+ 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"};
+ public static final String[] BITBAKE_STANDARD_FUNCTIONS = new String[] { "stage", "configure", "compile", "install" };
+ public static final String BITBAKE_RECIPE_FILE_EXTENSION = "bb";
+
+ /**
+ * @return A map of names and descriptions of commonly used BitBake variables.
+ */
+ public static Map getCommonBitbakeVariables() {
+ Map m = new TreeMap(new Comparator() {
+
+ public int compare(Object o1, Object o2) {
+
+ return ((String) o1).compareTo(((String) o2));
+ }
+
+ });
+
+ m.put("SECTION", "Category of package");
+ m.put("PR", "Package Release Number");
+ m.put("SRC_URI", "Location of package sources");
+ m.put("DESCRIPTION", "Description of package");
+ m.put("EXTRA_OEMAKE", "Extra flags to pass to the package makefile");
+ m.put("EXTRA_OECONF", "Extra configuration flags for the package makefile");
+ m.put("DEPENDS", "The set of build-time dependent packages");
+ m.put("RDEPENDS", "The set of run-time dependent packages");
+ m.put("HOMEPAGE", "Homepage of the package");
+ m.put("LICENSE", "License of the package");
+ m.put("FILES_${PN}", "Full file path of files on target.");
+ m.put("S", "Package source directory");
+ m.put("PV", "Package version");
+ m.put("AUTHOR", "Author or maintainer of package");
+ m.put("PRIORITY", "Priority of package");
+
+ return m;
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBRecipe.java b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBRecipe.java
new file mode 100644
index 0000000..3321abd
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBRecipe.java
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.bitbake;
+
+import java.io.IOException;
+
+/**
+ * Represents the bitbake environment of a recipe package.
+ * @author kgilmer
+ *
+ */
+public class BBRecipe extends BBSession {
+ private final BBSession session;
+ private final String filePath;
+
+ public BBRecipe(BBSession session, String filePath) throws IOException {
+ super(session.shell, session.pinfo.getRootPath());
+ this.session = session;
+ this.filePath = filePath;
+ }
+
+ @Override
+ public void initialize() throws Exception {
+ if (initialized) {
+ return;
+ }
+
+ String ret = shell.execute("bitbake -e -b " + filePath);
+ properties = parseBBEnvironment(ret);
+
+ if (ret == null || properties.size() == 0) {
+ throw new IOException("Failed to parse " + filePath);
+ }
+
+ initialized = true;
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBSession.java b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBSession.java
new file mode 100644
index 0000000..87b3f53
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/BBSession.java
@@ -0,0 +1,513 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.bitbake;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.ui.console.ConsolePlugin;
+import org.eclipse.ui.console.IConsole;
+import org.eclipse.ui.console.MessageConsole;
+import org.openembedded.bc.ui.model.IModelElement;
+import org.openembedded.bc.ui.model.ProjectInfo;
+
+
+/**
+ * BBSession encapsulates a global bitbake configuration and is the primary interface
+ * for actions against a BitBake installation.
+ *
+ * @author kgilmer
+ *
+ */
+public class BBSession implements IModelElement, Map {
+ public static final int TYPE_VARIABLE_ASSIGNMENT = 1;
+ public static final int TYPE_UNKNOWN = 2;
+ public static final int TYPE_STATEMENT = 3;
+ public static final int TYPE_FLAG = 4;
+
+ protected final ProjectInfo pinfo;
+ protected final ShellSession shell;
+ protected Map properties = null;
+ protected boolean initialized = false;
+ private MessageConsole sessionConsole;
+
+ public BBSession(ShellSession ssession, String projectRoot) throws IOException {
+ shell = ssession;
+ this.pinfo = new ProjectInfo();
+ pinfo.setLocation(projectRoot);
+ pinfo.setInitScriptPath(ProjectInfoHelper.getInitScriptPath(projectRoot));
+ }
+
+ private Collection adapttoIPath(List<File> asList, IProject project) {
+
+ List pathList = new ArrayList();
+
+ for (Iterator i = asList.iterator(); i.hasNext();) {
+ File f = (File) i.next();
+ IFile ff = project.getFile(stripLeading(f.toString(), project.getLocationURI().getPath()));
+ if (ff.exists()) {
+ pathList.add(ff);
+ }
+ }
+
+ return pathList;
+ }
+
+ private String appendAll(String[] elems, int st) {
+ StringBuffer sb = new StringBuffer();
+
+ for (int i = st; i < elems.length; ++i) {
+ sb.append(elems[i]);
+ }
+
+ return sb.toString();
+ }
+
+ private int charCount(String trimmed, char c) {
+ int i = 0;
+ int p = 0;
+
+ while ((p = trimmed.indexOf(c, p)) > -1) {
+ i++;
+ p++;
+ }
+
+ return i;
+ }
+
+ public void clear() {
+ throw new RuntimeException("BB configuration is read-only.");
+ }
+
+ public boolean containsKey(Object arg0) {
+ return properties.containsKey(arg0);
+ }
+
+ public boolean containsValue(Object arg0) {
+ return properties.containsValue(arg0);
+ }
+
+ public Set entrySet() {
+ return properties.entrySet();
+ }
+
+ @Override
+ public boolean equals(Object arg0) {
+ return properties.equals(arg0);
+ }
+
+ public ShellSession getShell() {
+ return shell;
+ }
+
+ /**
+ * Recursively generate list of Recipe files from a root directory.
+ *
+ * @param rootDir
+ * @param recipes
+ * @param fileExtension
+ * @param project
+ */
+ private void findRecipes(File rootDir, List recipes, final String fileExtension, IProject project) {
+ File[] children = rootDir.listFiles(new FileFilter() {
+
+ public boolean accept(File pathname) {
+ return pathname.isFile() && pathname.getName().endsWith(fileExtension);
+ }
+
+ });
+
+ if (children != null && children.length > 0) {
+ recipes.addAll(adapttoIPath(Arrays.asList(children), project));
+ }
+
+ File[] childDirs = rootDir.listFiles(new FileFilter() {
+
+ public boolean accept(File pathname) {
+ return pathname.isDirectory();
+ }
+
+ });
+
+ if (childDirs != null && childDirs.length > 0) {
+ for (int i = 0; i < childDirs.length; ++i) {
+ findRecipes(childDirs[i], recipes, fileExtension, project);
+ }
+ }
+ }
+
+ private Collection findRecipes(List paths, IProject project) {
+ List recipes = new ArrayList();
+
+ for (Iterator i = paths.iterator(); i.hasNext();) {
+ String rawPath = (String) i.next();
+ String[] elems = rawPath.split("\\*/\\*");
+
+ if (elems.length == 2) {
+
+ File rootDir = new File(elems[0]);
+
+ findRecipes(rootDir, recipes, elems[1], project);
+ }
+ }
+
+ return recipes;
+ }
+
+ public Object get(Object arg0) {
+ return properties.get(arg0);
+ }
+
+ private List getBitBakeKeywords() {
+ return Arrays.asList(BBLanguageHelper.BITBAKE_KEYWORDS);
+ }
+
+ /**
+ * @return A MessageConsole for this BB session.
+ */
+ public MessageConsole getConsole() {
+ if (sessionConsole == null) {
+ String cName = ProjectInfoHelper.getProjectName(pinfo.getRootPath()) + " Console";
+ sessionConsole = new MessageConsole(cName, null);
+ ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { sessionConsole });
+ }
+
+ ConsolePlugin.getDefault().getConsoleManager().showConsoleView(sessionConsole);
+
+ return sessionConsole;
+ }
+
+ private int getLineType(String line) {
+
+ if (line.contains("=")) {
+ return TYPE_VARIABLE_ASSIGNMENT;
+ }
+
+ for (Iterator i = getBitBakeKeywords().iterator(); i.hasNext();) {
+ if (line.startsWith((String) i.next())) {
+ return TYPE_STATEMENT;
+ }
+ }
+
+ if (line.contains(":")) {
+ return TYPE_FLAG;
+ }
+
+ return TYPE_UNKNOWN;
+ }
+
+ public Collection getRecipeFiles(IProject project) {
+ if (!initialized) {
+ throw new RuntimeException(this.getClass().getName() + " is not initialized.");
+ }
+ String bbfiles = (String) this.properties.get("BBFILES");
+
+ List paths = parseBBFiles(bbfiles);
+
+ return findRecipes(paths, project);
+ }
+
+ @Override
+ public int hashCode() {
+ return properties.hashCode();
+ }
+
+ public void initialize() throws Exception {
+ if (initialized) {
+ return;
+ }
+
+ properties = parseBBEnvironment(shell.execute("bitbake -e"));
+ initialized = true;
+ }
+
+ private boolean isBlockEnd(String trimmed) {
+ return charCount(trimmed, '}') > charCount(trimmed, '{');
+ // return trimmed.indexOf('}') > -1 && trimmed.indexOf('{') == -1;
+ }
+
+ private boolean isBlockStart(String trimmed) {
+ return charCount(trimmed, '{') > charCount(trimmed, '}');
+ // return trimmed.indexOf('{') > -1 && trimmed.indexOf('}') == -1;
+ }
+
+ public boolean isEmpty() {
+ return properties.isEmpty();
+ }
+
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ public Set keySet() {
+ return properties.keySet();
+ }
+
+ protected void parse(String content, Map outMap) throws Exception {
+ BufferedReader reader = new BufferedReader(new StringReader(content));
+ String line;
+ boolean inLine = false;
+ StringBuffer sb = null;
+ Stack blockStack = new Stack();
+
+ while ((line = reader.readLine()) != null) {
+ String trimmed = line.trim();
+ if (trimmed.length() == 0 || line.startsWith("#")) {
+ // weed out the blank and comment lines
+ continue;
+ }
+ // Now we look for block start ends, and ignore all code within
+ // blocks.
+ if (isBlockStart(trimmed)) {
+ blockStack.push(trimmed);
+ } else if (isBlockEnd(trimmed)) {
+ blockStack.pop();
+
+ }
+
+ if (!blockStack.isEmpty()) {
+ // we are in a code block, continue until we break into global
+ // scope.
+ continue;
+ }
+ if (trimmed.endsWith("\\")) {
+ if (!inLine) {
+ inLine = true;
+ sb = new StringBuffer(trimmed.substring(0, trimmed.length() - 1));
+ } else {
+ sb.append(trimmed.substring(0, trimmed.length() - 1));
+ }
+ // Only parse the line when we have the complete contents.
+ continue;
+ } else if (inLine) {
+ inLine = false;
+ line = sb.toString();
+ }
+
+ parseLine(line, outMap);
+ }
+ }
+
+ private void parseAdditiveAssignment(String line, String operator, Map mo) throws Exception {
+ String[] elems = splitAssignment(line, "\\+=");
+
+ if (elems.length != 2) {
+ throw new Exception("Unable to parse additive variable assignment in line: " + line);
+ }
+
+ if (!mo.containsKey(elems[0])) {
+ mo.put(elems[0].trim(), elems[1]);
+ } else {
+ String existing = (String) mo.get(elems[0]);
+ if (operator.equals("+=")) {
+ mo.put(elems[0], existing + elems[1]);
+ } else {
+ mo.put(elems[0], elems[1] + existing);
+ }
+ }
+ }
+
+ protected Map parseBBEnvironment(String bbOut) throws Exception {
+ Map env = new Hashtable();
+
+ parse(bbOut, env);
+
+ return env;
+ }
+
+
+ private List parseBBFiles(String bbfiles) {
+ return Arrays.asList(bbfiles.split(" "));
+ }
+
+ //Map delegate methods
+
+ private void parseConditionalAssignment(String line, Map mo) throws Exception {
+ String[] elems = splitAssignment(line, "\\?=");
+
+ if (elems.length != 2) {
+ throw new Exception("Unable to parse conditional variable assignment in line: " + line);
+ }
+
+ if (!mo.containsKey(elems[0].trim())) {
+ mo.put(elems[0].trim(), elems[1].trim());
+ }
+ }
+
+ private void parseImmediateAssignment(String line, String delimiter, Map mo) throws Exception {
+ String[] elems = splitAssignment(line, delimiter);
+
+ mo.put(elems[0], substitute(elems[1], mo));
+ }
+
+ private void parseKeyValue(String line, String delimiter, Map mo) throws Exception {
+ String[] elems = splitAssignment(line, delimiter);
+
+ mo.put(elems[0], elems[1]);
+ }
+
+ private void parseLine(String line, Map mo) throws Exception {
+
+ switch (getLineType(line)) {
+ case TYPE_VARIABLE_ASSIGNMENT:
+ parseVariableAssignment(line, mo);
+ break;
+ case TYPE_STATEMENT:
+ case TYPE_FLAG:
+ // for now ignore statements
+ break;
+ case TYPE_UNKNOWN:
+ // we'll gloss over unknown lines as well;
+ break;
+ default:
+ throw new Exception("Unable to parse line: " + line);
+ }
+ }
+
+ private void parseVariableAssignment(String line, Map mo) throws Exception {
+ if (line.contains("?=")) {
+ parseConditionalAssignment(line, mo);
+ } else if (line.contains("+=")) {
+ parseAdditiveAssignment(line, "+=", mo);
+ } else if (line.contains("=+")) {
+ parseAdditiveAssignment(line, "=+", mo);
+ } else if (line.contains(":=")) {
+ parseImmediateAssignment(line, ":=", mo);
+ } else {
+ parseKeyValue(line, "=", mo);
+ }
+
+ }
+
+ private List parseVars(String line) {
+ List l = new ArrayList();
+
+ int i = 0;
+
+ while ((i = line.indexOf("${", i)) > -1) {
+ int i2 = line.indexOf("}", i);
+
+ l.add(line.subSequence(i + 2, i2));
+ i++;
+ }
+
+ return l;
+ }
+
+ public Object put(Object arg0, Object arg1) {
+ throw new RuntimeException("BB configuration is read-only.");
+ }
+
+ public void putAll(Map arg0) {
+ throw new RuntimeException("BB configuration is read-only.");
+ }
+
+ public Object remove(Object arg0) {
+ throw new RuntimeException("BB configuration is read-only.");
+ }
+
+ private String removeQuotes(String line) {
+ line = line.trim();
+
+ if (line.startsWith("\"")) {
+ line = line.substring(1);
+ }
+
+ if (line.endsWith("\"")) {
+ line = line.substring(0, line.length() - 1);
+ }
+
+ return line;
+ }
+
+ public int size() {
+ return properties.size();
+ }
+
+ private String[] splitAssignment(String line, String seperator) throws Exception {
+ String[] elems = line.split(seperator);
+
+ if (elems.length < 2) {
+ throw new Exception("Unable to parse assignment in line: " + line);
+ } else if (elems.length == 2) {
+
+ elems[0] = elems[0].trim(); // Clean up trailing or leading spaces.
+ if (elems[0].startsWith("export ")) {
+ elems[0] = elems[0].substring("export ".length()).trim();
+ }
+ elems[1] = removeQuotes(elems[1]); // Evaluate variables
+
+ return elems;
+ } else {
+ String[] retVal = new String[2];
+
+ retVal[0] = elems[0];
+ if (retVal[0].startsWith("export ")) {
+ retVal[0] = retVal[0].substring("export ".length()).trim();
+ }
+ retVal[1] = appendAll(elems, 1);
+
+ return retVal;
+ }
+ }
+
+ private String stripLeading(String target, String leading) {
+ if (target.startsWith(leading)) {
+ target = target.substring(leading.length());
+ }
+
+ return target;
+ }
+
+ /**
+ * Return a string with variable substitutions in place.
+ *
+ * @param expression
+ * @return Input string with any substitutions from this file.
+ */
+ public String substitute(String expression, Map mo) {
+
+ List vars = parseVars(expression);
+
+ for (Iterator i = vars.iterator(); i.hasNext();) {
+ String varName = (String) i.next();
+ String varToken = "${" + varName + "}";
+
+ if (mo.containsKey(varName)) {
+ expression = expression.replace(varToken, (String) mo.get(varName));
+ } else if (System.getProperty(varName) != null) {
+ expression = expression.replace(varToken, System.getProperty(varName));
+ } else if (varName.toUpperCase().equals("HOME")) {
+ expression = expression.replace(varToken, System.getProperty("user.home"));
+ }
+ }
+
+ return expression;
+ }
+
+ public Collection values() {
+ return properties.values();
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ICommandResponseHandler.java b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ICommandResponseHandler.java
new file mode 100644
index 0000000..bc32895
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ICommandResponseHandler.java
@@ -0,0 +1,15 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.bitbake;
+
+public interface ICommandResponseHandler {
+ public void response(String line, boolean isError);
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ProjectInfoHelper.java b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ProjectInfoHelper.java
new file mode 100644
index 0000000..37cc28b
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ProjectInfoHelper.java
@@ -0,0 +1,102 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.bitbake;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.openembedded.bc.ui.model.ProjectInfo;
+
+
+/**
+ * A helper class for ProjectInfo related tasks.
+ *
+ * @author kgilmer
+ *
+ */
+public class ProjectInfoHelper {
+
+ /**
+ * @param path
+ * @return The path to bitbake init script
+ * @throws IOException
+ */
+ public static String getInitScriptPath(String path) throws IOException {
+ File inFile = new File(path, ".eclipse-data");
+ BufferedReader br = new BufferedReader(new FileReader(inFile));
+
+ String val = br.readLine();
+
+ br.close();
+
+ return val;
+ }
+
+ public static String getInitScript(String path) throws IOException {
+ File inFile = new File(path);
+ BufferedReader br = new BufferedReader(new FileReader(inFile));
+ StringBuffer sb = new StringBuffer();
+ String line = null;
+
+ while ((line = br.readLine()) != null) {
+ sb.append(line);
+ }
+
+ br.close();
+
+ return sb.toString();
+ }
+
+ public static String getProjectName(String projectRoot) {
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ for (int i = 0; i < projects.length; ++i) {
+ try {
+ if (projects[i].getLocationURI().getPath().equals(projectRoot)) {
+ return projects[i].getName();
+ }
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * This method will store the path to the bitbake init script for future
+ * reference.
+ *
+ * @param path
+ * @param projInfo
+ * @throws IOException
+ */
+ public static void store(String path, ProjectInfo projInfo) throws IOException {
+ writeToFile(path, projInfo.getInitScriptPath());
+ }
+
+ private static void writeToFile(String path, String init) throws IOException {
+ File outFile = new File(path, ".eclipse-data");
+ FileOutputStream fos = new FileOutputStream(outFile);
+
+ fos.write(init.getBytes());
+
+ fos.flush();
+ fos.close();
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ShellSession.java b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ShellSession.java
new file mode 100644
index 0000000..37f478f
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ShellSession.java
@@ -0,0 +1,233 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.bitbake;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Writer;
+
+/**
+ * A class for Linux shell sessions.
+ * @author kgilmer
+ *
+ */
+public class ShellSession {
+ /**
+ * Bash shell
+ */
+ public static final int SHELL_TYPE_BASH = 1;
+ /**
+ * sh shell
+ */
+ public static final int SHELL_TYPE_SH = 2;
+ private volatile boolean interrupt = false;
+ /**
+ * String used to isolate command execution
+ */
+ public static final String TERMINATOR = "234o987dsfkcqiuwey18837032843259d";
+ public static final String LT = System.getProperty("line.separator");
+
+ public static String getFilePath(String file) throws IOException {
+ File f = new File(file);
+
+ if (!f.exists() || f.isDirectory()) {
+ throw new IOException("Path passed is not a file: " + file);
+ }
+
+ StringBuffer sb = new StringBuffer();
+
+ String elems[] = file.split(File.separator);
+
+ for (int i = 0; i < elems.length - 1; ++i) {
+ sb.append(elems[i]);
+ sb.append(File.separator);
+ }
+
+ return sb.toString();
+ }
+ private Process process;
+
+ private OutputStream pos = null;
+ //private File initFile = null;
+ private String shellPath = null;
+ private final String initCmd;
+ private final File root;
+ private final Writer out;
+
+
+ public ShellSession(int shellType, File root, String initCmd, Writer out) throws IOException {
+ this.root = root;
+ this.initCmd = initCmd;
+ if (out == null) {
+ this.out = new NullWriter();
+ } else {
+ this.out = out;
+ }
+ if (shellType == SHELL_TYPE_SH) {
+ shellPath = "/bin/sh";
+ }
+ shellPath = "/bin/bash";
+
+ initializeShell();
+ }
+
+ private void initializeShell() throws IOException {
+ process = Runtime.getRuntime().exec(shellPath);
+ pos = process.getOutputStream();
+
+ if (root != null) {
+ out.write(execute("cd " + root.getAbsolutePath()));
+ }
+
+ if (initCmd != null) {
+ out.write(execute("source " + initCmd));
+ }
+ }
+
+ synchronized public String execute(String command) throws IOException {
+ String errorMessage = null;
+ interrupt = false;
+ out.write(command);
+ out.write(LT);
+
+ sendToProcessAndTerminate(command);
+
+ if (process.getErrorStream().available() > 0) {
+ byte[] msg = new byte[process.getErrorStream().available()];
+
+ process.getErrorStream().read(msg, 0, msg.length);
+ out.write(new String(msg));
+ out.write(LT);
+ errorMessage = "Error while executing: " + command + LT + new String(msg);
+ }
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(process
+ .getInputStream()));
+
+ StringBuffer sb = new StringBuffer();
+ String line = null;
+
+ while (((line = br.readLine()) != null) && !line.equals(TERMINATOR) && !interrupt) {
+ sb.append(line);
+ sb.append(LT);
+ out.write(line);
+ out.write(LT);
+ }
+
+ if (interrupt) {
+ process.destroy();
+ initializeShell();
+ interrupt = false;
+ }
+
+ if (errorMessage != null) {
+ throw new IOException(errorMessage);
+ }
+
+ return sb.toString();
+ }
+
+ synchronized public void execute(String command, ICommandResponseHandler handler) throws IOException {
+ execute(command, TERMINATOR, handler);
+ }
+
+ synchronized public void execute(String command, String terminator, ICommandResponseHandler handler) throws IOException {
+ interrupt = false;
+ InputStream errIs = process.getErrorStream();
+ if (errIs.available() > 0) {
+ clearErrorStream(errIs);
+ }
+ sendToProcessAndTerminate(command);
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ String std = null;
+
+ do {
+ if (errIs.available() > 0) {
+ byte[] msg = new byte[errIs.available()];
+
+ errIs.read(msg, 0, msg.length);
+ out.write(new String(msg));
+ handler.response(new String(msg), true);
+ }
+
+ std = br.readLine();
+
+ if (std != null && !std.equals(terminator)) {
+ out.write(std);
+ handler.response(std, false);
+ }
+
+ } while (std != null && !std.equals(terminator) && !interrupt);
+
+ if (interrupt) {
+ process.destroy();
+ initializeShell();
+ interrupt = false;
+ }
+ }
+
+ private void clearErrorStream(InputStream is) {
+
+ try {
+ byte b[] = new byte[is.available()];
+ is.read(b);
+ //System.out.println("clearing: " + new String(b));
+ } catch (IOException e) {
+ e.printStackTrace();
+ //Ignore any error
+ }
+ }
+
+ /**
+ * Send command string to shell process and add special terminator string so
+ * reader knows when output is complete.
+ *
+ * @param command
+ * @throws IOException
+ */
+ private void sendToProcessAndTerminate(String command) throws IOException {
+ pos.write(command.getBytes());
+ pos.write(LT.getBytes());
+ pos.flush();
+ pos.write("echo ".getBytes());
+ pos.write(TERMINATOR.getBytes());
+ pos.write(LT.getBytes());
+ pos.flush();
+ }
+
+ /**
+ * Interrupt any running processes.
+ */
+ public void interrupt() {
+ interrupt = true;
+ }
+
+ private class NullWriter extends Writer {
+
+ @Override
+ public void close() throws IOException {
+ }
+
+ @Override
+ public void flush() throws IOException {
+ }
+
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ }
+
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ShellTest2.java b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ShellTest2.java
new file mode 100644
index 0000000..8ef5ef5
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/bitbake/ShellTest2.java
@@ -0,0 +1,111 @@
+package org.openembedded.bc.bitbake;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * Tests for ShellSession.
+ *
+ * @author kgilmer
+ *
+ */
+public class ShellTest2 {
+ public static void main(String[] args) {
+ ShellTest2 st = new ShellTest2();
+
+ //testSimpleCommands();
+
+ testStreamResponse();
+ }
+
+ private static void streamOut(InputStream executeIS) throws IOException {
+ BufferedReader br = new BufferedReader(new InputStreamReader(executeIS));
+
+ String line = null;
+ while ((line = br.readLine()) != null) {
+ System.out.println(line);
+ }
+ }
+
+ private static void testSimpleCommands() {
+ try {
+ ShellSession ss = new ShellSession(ShellSession.SHELL_TYPE_BASH, null, null, null);
+ System.out.println(ss.execute("echo \"bo is $boo\""));
+
+ System.out.println(ss.execute("export boo=asdf"));
+
+ System.out.println(ss.execute("echo \"bo is $boo\""));
+
+ System.out.println(ss.execute("cd /home/kgilmer/dev/workspaces/com.buglabs.build.oe"));
+ System.out.println(ss.execute("source reinstate-build-env"));
+ System.out.println(ss.execute("echo $BBPATH"));
+ System.out.println(ss.execute("bitbake -e"));
+
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private static void testStreamResponse() {
+ try {
+ final ShellSession ss = new ShellSession(ShellSession.SHELL_TYPE_BASH, null, null, null);
+
+ ss.execute("./loop.sh", ShellSession.TERMINATOR, new ICommandResponseHandler() {
+
+ public void response(String line, boolean isError) {
+ if (isError) {
+ System.out.println("ERROR: " + line);
+ } else {
+ System.out.println(line);
+ ss.interrupt();
+ }
+
+ }
+ });
+
+ ss.execute("ls /home", ShellSession.TERMINATOR, new ICommandResponseHandler() {
+
+ public void response(String line, boolean isError) {
+ if (isError) {
+ System.err.println("ERROR: " + line);
+ } else {
+ System.out.println(line);
+ }
+ }
+ });
+
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+/* *//**
+ * A reader that will terminate upon reading a specific line. Prevents reader from blocking.
+ *
+ * @author kgilmer
+ *//*
+ private class LineTerminatingReader extends BufferedReader {
+
+ private final String terminator;
+
+ public LineTerminatingReader(Reader in, String terminator) {
+ super(in);
+ this.terminator = terminator;
+ }
+
+ public String readLine() throws IOException {
+ String line = null;
+
+ while (((line = this.readLine()) != null) && !line.equals(terminator)) {
+ return line;
+ }
+
+ return null;
+ }
+
+ }*/
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/Activator.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/Activator.java
new file mode 100644
index 0000000..0d1ad26
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/Activator.java
@@ -0,0 +1,209 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.openembedded.bc.bitbake.BBSession;
+import org.openembedded.bc.bitbake.ProjectInfoHelper;
+import org.openembedded.bc.bitbake.ShellSession;
+import org.openembedded.bc.ui.model.ProjectInfo;
+import org.osgi.framework.BundleContext;
+
+
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.openembedded.bc.ui";
+ public static final String IMAGE_VARIABLE = "IMAGE_VARIABLE";
+ public static final String IMAGE_FUNCTION = "IMAGE_FUNCTION";
+
+ // The shared instance
+ private static Activator plugin;
+ private static Map shellMap;
+ private static Map projInfoMap;
+ private static Hashtable bbSessionMap;
+
+ /**
+ * Get or create a BitBake session passing in ProjectInfo
+ *
+ * @param pinfo
+ * @return
+ * @throws IOException
+ */
+ public static BBSession getBBSession(String projectRoot, Writer out) throws IOException {
+ if (bbSessionMap == null) {
+ bbSessionMap = new Hashtable();
+ }
+
+ BBSession bbs = (BBSession) bbSessionMap.get(projectRoot);
+
+ if (bbs == null) {
+ bbs = new BBSession(getShellSession(projectRoot, out), projectRoot);
+ bbSessionMap.put(projectRoot, bbs);
+ }
+
+ return bbs;
+ }
+
+ public static void clearBBSession(String projectRoot) {
+ bbSessionMap.remove(projectRoot);
+ }
+
+ /**
+ * Get or create a BitBake session passing in ProjectInfo
+ *
+ * @param pinfo
+ * @return
+ * @throws IOException
+ */
+ public static BBSession getBBSession(String projectRoot) throws IOException {
+ if (bbSessionMap == null) {
+ bbSessionMap = new Hashtable();
+ }
+
+ BBSession bbs = (BBSession) bbSessionMap.get(projectRoot);
+
+ if (bbs == null) {
+ bbs = new BBSession(getShellSession(projectRoot, null), projectRoot);
+ bbSessionMap.put(projectRoot, bbs);
+ }
+
+ return bbs;
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns an image descriptor for the image file at the given plug-in
+ * relative path
+ *
+ * @param path
+ * the path
+ * @return the image descriptor
+ */
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return imageDescriptorFromPlugin(PLUGIN_ID, path);
+ }
+
+ public static ProjectInfo getProjInfo(String location) throws CoreException, InvocationTargetException, InterruptedException {
+ if (projInfoMap == null) {
+ projInfoMap = new Hashtable();
+ }
+
+ ProjectInfo pi = (ProjectInfo) projInfoMap.get(location);
+
+ if (pi == null) {
+ pi = new ProjectInfo();
+ pi.setLocation(location);
+ try {
+ pi.setInitScriptPath(ProjectInfoHelper.getInitScriptPath(location));
+ } catch (IOException e) {
+ throw new InvocationTargetException(e);
+ }
+ }
+
+ return pi;
+ }
+
+ /**
+ * @param absolutePath
+ * @return a cached shell session for a given project root.
+ * @throws IOException
+ */
+ private static ShellSession getShellSession(String absolutePath, Writer out) throws IOException {
+ if (shellMap == null) {
+ shellMap = new Hashtable();
+ }
+
+ try {
+ ShellSession ss = (ShellSession) shellMap.get(absolutePath);
+
+ if (ss == null) {
+ ss = new ShellSession(ShellSession.SHELL_TYPE_BASH, new File(absolutePath), ProjectInfoHelper.getInitScriptPath(absolutePath), out);
+ }
+
+ return ss;
+ } catch (IOException e) {
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Invalid bitbake commander project at " + absolutePath));
+ return null;
+ }
+ }
+
+ public static void putProjInfo(String location, ProjectInfo pinfo) {
+ if (projInfoMap == null) {
+ projInfoMap = new Hashtable();
+ }
+
+ projInfoMap.put(location, pinfo);
+ }
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ this.getImageRegistry().put(IMAGE_VARIABLE, Activator.getImageDescriptor("icons/variable.gif"));
+ this.getImageRegistry().put(IMAGE_FUNCTION, Activator.getImageDescriptor("icons/function.gif"));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
+ * )
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
+ * )
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Reset a configuration
+ *
+ * @param path
+ */
+ public static void resetBBSession(String path) {
+ shellMap.remove(path);
+ bbSessionMap.remove(path);
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/AbstractBitbakeCommandAction.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/AbstractBitbakeCommandAction.java
new file mode 100644
index 0000000..4e93eee
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/AbstractBitbakeCommandAction.java
@@ -0,0 +1,199 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.actions;
+
+import java.io.IOException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.preference.JFacePreferences;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.eclipse.ui.console.MessageConsole;
+import org.eclipse.ui.console.MessageConsoleStream;
+import org.openembedded.bc.bitbake.BBLanguageHelper;
+import org.openembedded.bc.bitbake.BBSession;
+import org.openembedded.bc.bitbake.ICommandResponseHandler;
+import org.openembedded.bc.ui.Activator;
+import org.openembedded.bc.ui.builder.BitbakeCommanderNature;
+
+
+public abstract class AbstractBitbakeCommandAction implements IWorkbenchWindowActionDelegate {
+
+ private class CommandJob extends Job {
+
+ public CommandJob() {
+ super(getJobTitle());
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ String cmds[] = getCommands();
+ return execCommands(cmds, monitor);
+ }
+
+ }
+ protected IAction action;
+ protected IFile recipe;
+ protected BBSession bbs;
+
+ private Color commandColor, responseColor, errorColor;
+ private boolean errorOccurred = false;
+
+ public AbstractBitbakeCommandAction() {
+ commandColor = JFaceResources.getColorRegistry().get(JFacePreferences.ACTIVE_HYPERLINK_COLOR);
+ responseColor = JFaceResources.getColorRegistry().get(JFacePreferences.HYPERLINK_COLOR);
+ errorColor = JFaceResources.getColorRegistry().get(JFacePreferences.ERROR_COLOR);
+ }
+
+ private void checkEnabled(IFile file) {
+ try {
+ if (file.getFileExtension() == null || !file.getFileExtension().equals(BBLanguageHelper.BITBAKE_RECIPE_FILE_EXTENSION)) {
+ action.setEnabled(false);
+ return;
+ }
+
+ IProject project = file.getProject();
+ if (!(project.hasNature(BitbakeCommanderNature.NATURE_ID))) {
+ action.setEnabled(false);
+ return;
+ }
+
+ bbs = Activator.getBBSession(project.getLocationURI().getPath());
+
+ if (bbs != null) {
+ recipe = file;
+ action.setEnabled(true);
+ }
+
+ } catch (CoreException e) {
+ action.setEnabled(false);
+ e.printStackTrace();
+ } catch (Exception e) {
+ action.setEnabled(false);
+ e.printStackTrace();
+ }
+ }
+
+ public void dispose() {
+ }
+
+ /**
+ * Execute array of commands with bitbake and put output in console.
+ *
+ * @param cmds
+ * @param monitor
+ * @return
+ */
+ protected IStatus execCommands(String[] cmds, final IProgressMonitor monitor) {
+ MessageConsole mc = bbs.getConsole();
+ final MessageConsoleStream cmd = mc.newMessageStream();
+ cmd.setColor(commandColor);
+ final MessageConsoleStream out = mc.newMessageStream();
+ final MessageConsoleStream err = mc.newMessageStream();
+ err.setColor(errorColor);
+
+ try {
+ for (int i = 0; i < cmds.length; ++i) {
+ cmd.println(cmds[i]);
+ monitor.subTask(cmds[i]);
+ bbs.getShell().execute(cmds[i], new ICommandResponseHandler() {
+
+ public void response(String line, boolean isError) {
+ if (monitor.isCanceled()) {
+ cmd.println("Interrupting process by user request.");
+ bbs.getShell().interrupt();
+ }
+
+ if (isError) {
+ err.println(line);
+ errorOccurred();
+ } else if (line.startsWith("ERROR:")) {
+ err.println(line);
+ } else {
+ out.println(line);
+ }
+ }
+ });
+ }
+ } catch (IOException e) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);
+ } finally {
+ try {
+ if (errorOccurred) {
+ cmd.println("At least one error occured while executing this command. Check output for more details.");
+ }
+ cmd.close();
+ out.close();
+ err.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ protected void errorOccurred() {
+ errorOccurred = true;
+ }
+
+ /**
+ * Return the command to be executed.
+ *
+ * @return
+ */
+ public abstract String[] getCommands();
+
+ public Job getJob() {
+ return new CommandJob();
+ }
+
+ /**
+ * Return the title of the job.
+ *
+ * @return
+ */
+ public abstract String getJobTitle();
+
+ public void init(IWorkbenchWindow window) {
+ }
+
+ public void run(IAction action) {
+ Job job = getJob();
+ job.schedule();
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ this.action = action;
+ if (selection instanceof IStructuredSelection) {
+ Object sel = ((IStructuredSelection) selection).getFirstElement();
+
+ if (sel instanceof IFile) {
+ checkEnabled((IFile) sel);
+ return;
+ }
+ }
+
+ action.setEnabled(false);
+ }
+
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeBuildRecipeAction.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeBuildRecipeAction.java
new file mode 100644
index 0000000..e8f6708
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeBuildRecipeAction.java
@@ -0,0 +1,24 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.actions;
+
+public class BitbakeBuildRecipeAction extends AbstractBitbakeCommandAction {
+
+ @Override
+ public String [] getCommands() {
+ return new String[] {"bitbake -b " + recipe.getLocationURI().getPath()};
+ }
+
+ @Override
+ public String getJobTitle() {
+ return "Building " + recipe.getName();
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeCleanRecipeAction.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeCleanRecipeAction.java
new file mode 100644
index 0000000..a0f41c8
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeCleanRecipeAction.java
@@ -0,0 +1,26 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.actions;
+
+public class BitbakeCleanRecipeAction extends AbstractBitbakeCommandAction {
+
+ @Override
+ public String [] getCommands() {
+ return new String[] {"bitbake -c clean -b " + recipe.getLocationURI().getPath()};
+ }
+
+ @Override
+ public String getJobTitle() {
+ return "Cleaning " + recipe.getName();
+ }
+
+
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeImportAction.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeImportAction.java
new file mode 100644
index 0000000..e8e093f
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeImportAction.java
@@ -0,0 +1,106 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.actions;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.openembedded.bc.bitbake.BBCommonVars;
+import org.openembedded.bc.bitbake.BBRecipe;
+import org.openembedded.bc.ui.Activator;
+
+
+public class BitbakeImportAction extends AbstractBitbakeCommandAction {
+
+ private class ImportJob extends Job {
+
+ public ImportJob() {
+ super(getJobTitle());
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+
+ try {
+ BBRecipe br = new BBRecipe(bbs, recipe.getLocationURI().getPath());
+ br.initialize();
+ String filePath = (String) br.get(BBCommonVars.S);
+
+ //"${WORKDIR}/${PN}-${PV}"
+ if (filePath == null) {
+ filePath = ((String) br.get(BBCommonVars.WORKDIR)) + File.separator + ((String) br.get(BBCommonVars.PN)) + "-" + ((String) br.get(BBCommonVars.PV));
+ }
+
+ String projectName = (String) br.get(BBCommonVars.PN);
+
+ if (filePath == null || projectName == null) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Unable to parse recipe file.");
+ }
+
+ File workdir = new File(filePath);
+
+ if (workdir.exists() && workdir.isFile()) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, workdir.getPath() + " is an invalid workdir.");
+ }
+
+ if (!workdir.exists()) {
+ execCommands(new String[] {"bitbake -c patch -b " + recipe.getLocationURI().getPath()}, monitor);
+ }
+
+ if (!workdir.exists()) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Unable to retrieve sources from BitBake. Consult console.");
+ }
+
+ IProjectDescription desc = ResourcesPlugin.getWorkspace().newProjectDescription(projectName);
+ IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace().getRoot();
+ IProject proj = wsroot.getProject(projectName);
+ proj.create(desc, monitor);
+ proj.open(monitor);
+
+ String copyCmd = "cp -r " + workdir.getAbsolutePath() + File.separator + "* \"" + proj.getLocationURI().getPath() + "\"";
+ execCommands(new String[] {copyCmd} , monitor);
+
+ proj.refreshLocal(IResource.DEPTH_INFINITE, monitor);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Unable to create project.", e);
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ }
+
+ @Override
+ public String [] getCommands() {
+ return null;
+ }
+
+
+ @Override
+ public Job getJob() {
+ return new ImportJob();
+ }
+
+ @Override
+ public String getJobTitle() {
+ return "Importing " + recipe.getName();
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeRebuildRecipeAction.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeRebuildRecipeAction.java
new file mode 100644
index 0000000..f968b12
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/BitbakeRebuildRecipeAction.java
@@ -0,0 +1,29 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.actions;
+
+/**
+ * Rebuild a recipe.
+ * @author kgilmer
+ *
+ */
+public class BitbakeRebuildRecipeAction extends AbstractBitbakeCommandAction {
+
+ @Override
+ public String [] getCommands() {
+ return new String[] {"bitbake -c rebuild -b " + recipe.getLocationURI().getPath()};
+ }
+
+ @Override
+ public String getJobTitle() {
+ return "Rebuilding " + recipe.getName();
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/LaunchNewBitBakeProjectWizardAction.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/LaunchNewBitBakeProjectWizardAction.java
new file mode 100644
index 0000000..7f71d32
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/LaunchNewBitBakeProjectWizardAction.java
@@ -0,0 +1,48 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.openembedded.bc.ui.wizards.importProject.ImportOEProjectWizard;
+
+
+public class LaunchNewBitBakeProjectWizardAction implements IWorkbenchWindowActionDelegate {
+
+ private IWorkbenchWindow window;
+ private IStructuredSelection selection;
+
+ public void dispose() {
+ }
+
+ public void init(IWorkbenchWindow window) {
+ this.window = window;
+ }
+
+ public void run(IAction action) {
+ ImportOEProjectWizard wizard = new ImportOEProjectWizard();
+
+ wizard.init(window.getWorkbench(), selection);
+ WizardDialog wd = new WizardDialog(window.getShell(), wizard);
+ wd.create();
+ wd.open();
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ if (selection instanceof IStructuredSelection) {
+ this.selection = (IStructuredSelection) selection;
+ }
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/LaunchNewRecipeWizardAction.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/LaunchNewRecipeWizardAction.java
new file mode 100644
index 0000000..f1f09f8
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/LaunchNewRecipeWizardAction.java
@@ -0,0 +1,48 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.openembedded.bc.ui.wizards.NewBitBakeFileRecipeWizard;
+
+
+public class LaunchNewRecipeWizardAction implements IWorkbenchWindowActionDelegate {
+
+ private IWorkbenchWindow window;
+ private IStructuredSelection selection;
+
+ public void dispose() {
+ }
+
+ public void init(IWorkbenchWindow window) {
+ this.window = window;
+ }
+
+ public void run(IAction action) {
+ NewBitBakeFileRecipeWizard wizard = new NewBitBakeFileRecipeWizard();
+
+ wizard.init(window.getWorkbench(), selection);
+ WizardDialog wd = new WizardDialog(window.getShell(), wizard);
+ wd.create();
+ wd.open();
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ if (selection instanceof IStructuredSelection) {
+ this.selection = (IStructuredSelection) selection;
+ }
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/LaunchVariableWizardAction.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/LaunchVariableWizardAction.java
new file mode 100644
index 0000000..b70b05b
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/actions/LaunchVariableWizardAction.java
@@ -0,0 +1,78 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.actions;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.openembedded.bc.ui.Activator;
+import org.openembedded.bc.ui.builder.BitbakeCommanderNature;
+import org.openembedded.bc.ui.wizards.variable.VariableWizard;
+
+
+/**
+ * Action to launch the Variable Wizard.
+ * @author kgilmer
+ *
+ */
+public class LaunchVariableWizardAction implements IWorkbenchWindowActionDelegate {
+
+ private IWorkbenchWindow window;
+ private Map session;
+
+ public void dispose() {
+ }
+
+ public void init(IWorkbenchWindow window) {
+ this.window = window;
+ }
+
+ public void run(IAction action) {
+ VariableWizard wizard = new VariableWizard(session);
+
+ WizardDialog wd = new WizardDialog(window.getShell(), wizard);
+ wd.create();
+ wd.open();
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ session = null;
+
+ if (selection instanceof IStructuredSelection) {
+ Object element = ((IStructuredSelection)selection).getFirstElement();
+
+ if (element instanceof IResource) {
+ IProject p = ((IResource)element).getProject();
+
+ try {
+ if (p.isOpen() && p.hasNature(BitbakeCommanderNature.NATURE_ID)) {
+ session = Activator.getBBSession(((IResource)element).getProject().getLocationURI().getPath());
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ action.setEnabled(session != null);
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/builder/BitbakeBuilder.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/builder/BitbakeBuilder.java
new file mode 100644
index 0000000..40ece69
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/builder/BitbakeBuilder.java
@@ -0,0 +1,178 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.builder;
+
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.xml.sax.SAXException;
+
+public class BitbakeBuilder extends IncrementalProjectBuilder {
+
+ class SampleDeltaVisitor implements IResourceDeltaVisitor {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
+ */
+ public boolean visit(IResourceDelta delta) throws CoreException {
+ IResource resource = delta.getResource();
+ switch (delta.getKind()) {
+ case IResourceDelta.ADDED:
+ // handle added resource
+ //checkXML(resource);
+ break;
+ case IResourceDelta.REMOVED:
+ // handle removed resource
+ break;
+ case IResourceDelta.CHANGED:
+ // handle changed resource
+ //checkXML(resource);
+ break;
+ }
+ //return true to continue visiting children.
+ return true;
+ }
+ }
+/*
+ class SampleResourceVisitor implements IResourceVisitor {
+ public boolean visit(IResource resource) {
+
+ return true;
+ }
+ }
+*/
+/* class XMLErrorHandler extends DefaultHandler {
+
+ private IFile file;
+
+ public XMLErrorHandler(IFile file) {
+ this.file = file;
+ }
+
+ private void addMarker(SAXParseException e, int severity) {
+ BitbakeBuilder.this.addMarker(file, e.getMessage(), e
+ .getLineNumber(), severity);
+ }
+
+ @Override
+ public void error(SAXParseException exception) throws SAXException {
+ addMarker(exception, IMarker.SEVERITY_ERROR);
+ }
+
+ @Override
+ public void fatalError(SAXParseException exception) throws SAXException {
+ addMarker(exception, IMarker.SEVERITY_ERROR);
+ }
+
+ @Override
+ public void warning(SAXParseException exception) throws SAXException {
+ addMarker(exception, IMarker.SEVERITY_WARNING);
+ }
+ }
+*/
+ public static final String BUILDER_ID = "org.openembedded.bc.ui.builder.BitbakeBuilder";
+
+ private static final String MARKER_TYPE = "org.openembedded.bc.ui.xmlProblem";
+
+ private SAXParserFactory parserFactory;
+
+ private void addMarker(IFile file, String message, int lineNumber,
+ int severity) {
+ try {
+ IMarker marker = file.createMarker(MARKER_TYPE);
+ marker.setAttribute(IMarker.MESSAGE, message);
+ marker.setAttribute(IMarker.SEVERITY, severity);
+ if (lineNumber == -1) {
+ lineNumber = 1;
+ }
+ marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.internal.events.InternalBuilder#build(int,
+ * java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
+ throws CoreException {
+ if (kind == FULL_BUILD) {
+ fullBuild(monitor);
+ } else {
+ IResourceDelta delta = getDelta(getProject());
+ if (delta == null) {
+ fullBuild(monitor);
+ } else {
+ incrementalBuild(delta, monitor);
+ }
+ }
+ return null;
+ }
+
+ /*void checkXML(IResource resource) {
+ if (resource instanceof IFile && resource.getName().endsWith(".xml")) {
+ IFile file = (IFile) resource;
+ deleteMarkers(file);
+ XMLErrorHandler reporter = new XMLErrorHandler(file);
+ try {
+ getParser().parse(file.getContents(), reporter);
+ } catch (Exception e1) {
+ }
+ }
+ }*/
+
+ private void deleteMarkers(IFile file) {
+ try {
+ file.deleteMarkers(MARKER_TYPE, false, IResource.DEPTH_ZERO);
+ } catch (CoreException ce) {
+ ce.printStackTrace();
+ }
+ }
+
+ protected void fullBuild(final IProgressMonitor monitor)
+ throws CoreException {
+ /*try {
+ getProject().accept(new SampleResourceVisitor());
+ } catch (CoreException e) {
+ }*/
+ }
+
+ private SAXParser getParser() throws ParserConfigurationException,
+ SAXException {
+ if (parserFactory == null) {
+ parserFactory = SAXParserFactory.newInstance();
+ }
+ return parserFactory.newSAXParser();
+ }
+
+ protected void incrementalBuild(IResourceDelta delta,
+ IProgressMonitor monitor) throws CoreException {
+ // the visitor does the work.
+ delta.accept(new SampleDeltaVisitor());
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/builder/BitbakeCommanderNature.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/builder/BitbakeCommanderNature.java
new file mode 100644
index 0000000..ccaba8d
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/builder/BitbakeCommanderNature.java
@@ -0,0 +1,89 @@
+ /*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.builder;
+
+import org.eclipse.core.resources.ICommand;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IProjectNature;
+import org.eclipse.core.runtime.CoreException;
+
+public class BitbakeCommanderNature implements IProjectNature {
+
+ /**
+ * ID of this project nature
+ */
+ public static final String NATURE_ID = "org.openembedded.bc.ui.builder.BitbakeCommanderNature";
+
+ private IProject project;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IProjectNature#configure()
+ */
+ public void configure() throws CoreException {
+ IProjectDescription desc = project.getDescription();
+ ICommand[] commands = desc.getBuildSpec();
+
+ for (int i = 0; i < commands.length; ++i) {
+ if (commands[i].getBuilderName().equals(BitbakeBuilder.BUILDER_ID)) {
+ return;
+ }
+ }
+
+ ICommand[] newCommands = new ICommand[commands.length + 1];
+ System.arraycopy(commands, 0, newCommands, 0, commands.length);
+ ICommand command = desc.newCommand();
+ command.setBuilderName(BitbakeBuilder.BUILDER_ID);
+ newCommands[newCommands.length - 1] = command;
+ desc.setBuildSpec(newCommands);
+ project.setDescription(desc, null);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IProjectNature#deconfigure()
+ */
+ public void deconfigure() throws CoreException {
+ IProjectDescription description = getProject().getDescription();
+ ICommand[] commands = description.getBuildSpec();
+ for (int i = 0; i < commands.length; ++i) {
+ if (commands[i].getBuilderName().equals(BitbakeBuilder.BUILDER_ID)) {
+ ICommand[] newCommands = new ICommand[commands.length - 1];
+ System.arraycopy(commands, 0, newCommands, 0, i);
+ System.arraycopy(commands, i + 1, newCommands, i,
+ commands.length - i - 1);
+ description.setBuildSpec(newCommands);
+ return;
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IProjectNature#getProject()
+ */
+ public IProject getProject() {
+ return project;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core.resources.IProject)
+ */
+ public void setProject(IProject project) {
+ this.project = project;
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/builder/ToggleNatureAction.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/builder/ToggleNatureAction.java
new file mode 100644
index 0000000..38f8409
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/builder/ToggleNatureAction.java
@@ -0,0 +1,107 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.builder;
+
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+
+public class ToggleNatureAction implements IObjectActionDelegate {
+
+ private ISelection selection;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ if (selection instanceof IStructuredSelection) {
+ for (Iterator it = ((IStructuredSelection) selection).iterator(); it
+ .hasNext();) {
+ Object element = it.next();
+ IProject project = null;
+ if (element instanceof IProject) {
+ project = (IProject) element;
+ } else if (element instanceof IAdaptable) {
+ project = (IProject) ((IAdaptable) element)
+ .getAdapter(IProject.class);
+ }
+ if (project != null) {
+ toggleNature(project);
+ }
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ this.selection = selection;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction,
+ * org.eclipse.ui.IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ }
+
+ /**
+ * Toggles sample nature on a project
+ *
+ * @param project
+ * to have sample nature added or removed
+ */
+ private void toggleNature(IProject project) {
+ try {
+ IProjectDescription description = project.getDescription();
+ String[] natures = description.getNatureIds();
+
+ for (int i = 0; i < natures.length; ++i) {
+ if (BitbakeCommanderNature.NATURE_ID.equals(natures[i])) {
+ // Remove the nature
+ String[] newNatures = new String[natures.length - 1];
+ System.arraycopy(natures, 0, newNatures, 0, i);
+ System.arraycopy(natures, i + 1, newNatures, i,
+ natures.length - i - 1);
+ description.setNatureIds(newNatures);
+ project.setDescription(description, null);
+ return;
+ }
+ }
+
+ // Add the nature
+ String[] newNatures = new String[natures.length + 1];
+ System.arraycopy(natures, 0, newNatures, 0, natures.length);
+ newNatures[natures.length] = BitbakeCommanderNature.NATURE_ID;
+ description.setNatureIds(newNatures);
+ project.setDescription(description, null);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/decorators/ProjectDecorator.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/decorators/ProjectDecorator.java
new file mode 100644
index 0000000..6580f10
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/decorators/ProjectDecorator.java
@@ -0,0 +1,48 @@
+package org.openembedded.bc.ui.decorators;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IDecoration;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ILightweightLabelDecorator;
+import org.openembedded.bc.ui.Activator;
+import org.openembedded.bc.ui.builder.BitbakeCommanderNature;
+
+
+public class ProjectDecorator implements ILightweightLabelDecorator {
+
+ private ImageDescriptor image;
+
+ public ProjectDecorator() {
+ image = Activator.getImageDescriptor("icons/oe_decorator.gif");
+ }
+
+
+ public void decorate(Object element, IDecoration decoration) {
+ IProject p = (IProject) element;
+
+ try {
+ if (p.isOpen() && p.hasNature(BitbakeCommanderNature.NATURE_ID)) {
+ decoration.addOverlay(image, IDecoration.TOP_RIGHT);
+ }
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void addListener(ILabelProviderListener arg0) {
+ }
+
+ public void dispose() {
+ }
+
+ public boolean isLabelProperty(Object arg0, String arg1) {
+ return false;
+ }
+
+
+ public void removeListener(ILabelProviderListener arg0) {
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BBVariableTextHover.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BBVariableTextHover.java
new file mode 100644
index 0000000..d98c305
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BBVariableTextHover.java
@@ -0,0 +1,119 @@
+/**
+ *
+ */
+package org.openembedded.bc.ui.editors.bitbake;
+
+import java.io.File;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.openembedded.bc.bitbake.BBRecipe;
+import org.openembedded.bc.bitbake.BBSession;
+import org.openembedded.bc.ui.Activator;
+
+
+/**
+ * Maps BB Variables in the editor to BBSession
+ * @author kgilmer
+ *
+ */
+class BBVariableTextHover implements ITextHover {
+ private final BBSession session;
+ private volatile Map envMap;
+
+ public BBVariableTextHover(BBSession session, String file) {
+ this.session = session;
+ envMap = session;
+ LoadRecipeJob loadRecipeJob = new LoadRecipeJob(getFilename(file), file);
+ loadRecipeJob.schedule();
+ }
+
+ private String getFilename(String file) {
+
+ String [] elems = file.split(File.separator);
+
+ return elems[elems.length - 1];
+ }
+
+ public IRegion getHoverRegion(ITextViewer tv, int off) {
+ return new Region(off, 0);
+ }
+
+ public String getHoverInfo(ITextViewer tv, IRegion r) {
+ try {
+ IRegion lineRegion = tv.getDocument().getLineInformationOfOffset(r.getOffset());
+
+ return getBBVariable(tv.getDocument().get(lineRegion.getOffset(), lineRegion.getLength()).toCharArray(), r.getOffset() - lineRegion.getOffset());
+ } catch (Exception e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ private String getBBVariable(char[] line, int offset) {
+ // Find start of word.
+ int i = offset;
+
+ while (line[i] != ' ' && line[i] != '$' && i > 0) {
+ i--;
+ }
+
+ if (i < 0 || line[i] != '$') {
+ return ""; //this is not a BB variable.
+ }
+
+ // find end of word
+ int start = i;
+ i = offset;
+
+ while (line[i] != ' ' && line[i] != '}' && i <= line.length) {
+ i++;
+ }
+
+ if (line[i] != '}') {
+ return ""; //this bb variable didn't terminate as expected
+ }
+
+ String key = new String(line, start + 2, i - start - 2);
+ String val = (String) envMap.get(key);
+
+ if (val == null) {
+ val = "";
+ }
+
+ if (val.length() > 64) {
+ val = val.substring(0, 64) + '\n' + val.substring(65);
+ }
+
+ return val;
+ }
+
+ private class LoadRecipeJob extends Job {
+ private final String filePath;
+
+ public LoadRecipeJob(String name, String filePath) {
+ super("Extracting BitBake environment for " + name);
+ this.filePath = filePath;
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor mon) {
+ try {
+ BBRecipe recipe = new BBRecipe(session, filePath);
+ recipe.initialize();
+ envMap = recipe;
+ } catch (Exception e) {
+ return new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Unable to load session for " + filePath, e);
+ }
+
+ return Status.OK_STATUS;
+ }
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BitBakeDocumentProvider.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BitBakeDocumentProvider.java
new file mode 100644
index 0000000..dba29c2
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BitBakeDocumentProvider.java
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/package org.openembedded.bc.ui.editors.bitbake;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.rules.FastPartitioner;
+import org.eclipse.jface.text.rules.IPredicateRule;
+import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.ui.editors.text.FileDocumentProvider;
+
+/**
+ * Document provider for BB recipe.
+ * @author kgilmer
+ *
+ */
+public class BitBakeDocumentProvider extends FileDocumentProvider {
+ /**
+ * The recipe partitioning. It contains two partition types: {@link #RECIPE_CODE} and
+ * {@link #RECIPE_COMMENT}.
+ */
+ public static final String RECIPE_PARTITIONING= "org.recipeeditor.recipepartitioning"; //$NON-NLS-1$
+
+ public static final String RECIPE_CODE= IDocument.DEFAULT_CONTENT_TYPE;
+ public static final String RECIPE_COMMENT= "RECIPE_COMMENT"; //$NON-NLS-1$
+
+ private static final String[] CONTENT_TYPES= {
+ RECIPE_CODE,
+ RECIPE_COMMENT
+ };
+
+ private IDocumentPartitioner createRecipePartitioner() {
+ IPredicateRule[] rules= { new SingleLineRule("#", null, new Token(RECIPE_COMMENT), (char) 0, true, false) }; //$NON-NLS-1$
+
+ RuleBasedPartitionScanner scanner= new RuleBasedPartitionScanner();
+ scanner.setPredicateRules(rules);
+
+ return new FastPartitioner(scanner, CONTENT_TYPES);
+ }
+
+ @Override
+ protected void setupDocument(Object element,IDocument document) {
+ if (document instanceof IDocumentExtension3) {
+ IDocumentExtension3 ext= (IDocumentExtension3) document;
+ IDocumentPartitioner partitioner= createRecipePartitioner();
+ ext.setDocumentPartitioner(RECIPE_PARTITIONING, partitioner);
+ partitioner.connect(document);
+ }
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BitBakeFileEditor.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BitBakeFileEditor.java
new file mode 100644
index 0000000..2e48c97
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BitBakeFileEditor.java
@@ -0,0 +1,86 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.editors.bitbake;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.ide.FileStoreEditorInput;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
+import org.eclipse.ui.texteditor.ContentAssistAction;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.openembedded.bc.ui.Activator;
+import org.openembedded.bc.ui.builder.BitbakeCommanderNature;
+
+
+/**
+ * Editor for BB Recipe
+ *
+ * @author kgilmer
+ *
+ */
+public class BitBakeFileEditor extends AbstractDecoratedTextEditor {
+
+ public static final String EDITOR_ID = "org.openembedded.bc.ui.editors.BitBakeFileEditor";
+ static final String CONTENT_ASSIST = "ContentAssist";
+ private BitBakeSourceViewerConfiguration viewerConfiguration;
+ private String targetFilePath;
+
+ public BitBakeFileEditor() {
+ super();
+ viewerConfiguration = new BitBakeSourceViewerConfiguration(getSharedColors(), getPreferenceStore());
+ setSourceViewerConfiguration(viewerConfiguration);
+ setDocumentProvider(new BitBakeDocumentProvider());
+ }
+
+ @Override
+ protected void createActions() {
+ super.createActions();
+
+ ResourceBundle bundle = RecipeEditorMessages.getBundle();
+ ContentAssistAction action = new ContentAssistAction(bundle, "contentAssist.", this); //$NON-NLS-1$
+ action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+ setAction(CONTENT_ASSIST, action);
+ }
+
+ @Override
+ public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+
+ if (input instanceof FileEditorInput) {
+ IProject p = ((FileEditorInput) input).getFile().getProject();
+ try {
+ if (p != null && p.isOpen() && p.hasNature(BitbakeCommanderNature.NATURE_ID)) {
+ targetFilePath = ((FileEditorInput) input).getFile().getLocationURI().getPath();
+ viewerConfiguration.setTargetFilePath(targetFilePath);
+ viewerConfiguration.setBBSession(Activator.getBBSession(p.getLocationURI().getPath()));
+ }
+ } catch (Exception e) {
+ throw new PartInitException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "On " + input.getClass().getName() + " input, nable to load editor.", e));
+ }
+ } else if (input instanceof FileStoreEditorInput) {
+ targetFilePath = ((FileStoreEditorInput)input).getURI().getPath();
+ System.out.println("Target path:" + targetFilePath);
+ } else {
+ if (input == null) {
+ System.out.println("The input is null!");
+ }
+ System.out.println("The input is not a FileEditorInput: " + input.getClass().getName());
+ }
+
+ super.init(site, input);
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BitBakeSourceViewerConfiguration.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BitBakeSourceViewerConfiguration.java
new file mode 100644
index 0000000..e3cbeb4
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/BitBakeSourceViewerConfiguration.java
@@ -0,0 +1,193 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.editors.bitbake;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WordRule;
+import org.eclipse.jface.text.source.ISharedTextColors;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
+import org.openembedded.bc.bitbake.BBLanguageHelper;
+import org.openembedded.bc.bitbake.BBSession;
+
+
+public class BitBakeSourceViewerConfiguration extends TextSourceViewerConfiguration {
+
+ private static final class WordDetector implements IWordDetector {
+ public boolean isWordPart(char c) {
+ return !Character.isWhitespace(c);
+ }
+
+ public boolean isWordStart(char c) {
+ return !Character.isWhitespace(c);
+ }
+ }
+
+ private final ISharedTextColors fSharedColors;
+ private BBSession session;
+ private String targetFilePath;
+ private BBVariableTextHover textHover;
+
+ public BitBakeSourceViewerConfiguration(ISharedTextColors sharedColors, IPreferenceStore store) {
+ super(store);
+ fSharedColors = sharedColors;
+ }
+
+ protected void setTargetFilePath(String targetFilePath) {
+ this.targetFilePath = targetFilePath;
+ }
+
+ public ITextHover getTextHover(ISourceViewer sv, String contentType) {
+ if (textHover == null && session != null && targetFilePath != null) {
+ textHover = new BBVariableTextHover(session, targetFilePath);
+ }
+
+ return textHover;
+ }
+
+ private void addDamagerRepairer(PresentationReconciler reconciler, RuleBasedScanner commentScanner, String contentType) {
+ DefaultDamagerRepairer commentDamagerRepairer = new DefaultDamagerRepairer(commentScanner);
+ reconciler.setDamager(commentDamagerRepairer, contentType);
+ reconciler.setRepairer(commentDamagerRepairer, contentType);
+ }
+
+ private RuleBasedScanner createCommentScanner() {
+ Color green = fSharedColors.getColor(new RGB(16, 96, 16));
+ RuleBasedScanner commentScanner = new RuleBasedScanner();
+ commentScanner.setDefaultReturnToken(new Token(new TextAttribute(green, null, SWT.ITALIC)));
+ return commentScanner;
+ }
+
+ private IRule createCustomFunctionRule() {
+ Color blue = fSharedColors.getColor(new RGB(130, 0, 0));
+ IRule rule = new CustomFunctionRule(new Token(new TextAttribute(blue, null, SWT.BOLD)));
+
+ return rule;
+ }
+
+ private SingleLineRule createFunctionNameRule() {
+ Color red = fSharedColors.getColor(new RGB(150, 0, 96));
+ SingleLineRule stepRule = new SingleLineRule("do_", ")", new Token(new TextAttribute(red, null, SWT.BOLD))); //$NON-NLS-1$ //$NON-NLS-2$
+ stepRule.setColumnConstraint(0);
+ return stepRule;
+ }
+
+ private SingleLineRule createInlineVariableRule() {
+ Color blue = fSharedColors.getColor(new RGB(50, 50, 100));
+ SingleLineRule stepRule = new SingleLineRule("${", "}", new Token(new TextAttribute(blue, null, SWT.BOLD))); //$NON-NLS-1$ //$NON-NLS-2$
+ return stepRule;
+ }
+
+ private WordRule createKeywordRule() {
+ WordRule keywordRule = new WordRule(new WordDetector());
+ IToken token = new Token(new TextAttribute(fSharedColors.getColor(new RGB(96, 96, 0)), null, SWT.NONE));
+
+ for (int i = 0; i < BBLanguageHelper.BITBAKE_KEYWORDS.length; ++i) {
+
+ keywordRule.addWord(BBLanguageHelper.BITBAKE_KEYWORDS[i], token);
+ keywordRule.setColumnConstraint(0);
+ }
+
+ return keywordRule;
+ }
+
+ private RuleBasedScanner createRecipeScanner() {
+ RuleBasedScanner recipeScanner = new RuleBasedScanner();
+
+ IRule[] rules = { createKeywordRule(), createShellKeywordRule(), createStringLiteralRule(), createVariableRule(), createFunctionNameRule(), createCustomFunctionRule(),
+ createInlineVariableRule() };
+ recipeScanner.setRules(rules);
+ return recipeScanner;
+ }
+
+ private WordRule createShellKeywordRule() {
+ WordRule keywordRule = new WordRule(new WordDetector());
+ IToken token = new Token(new TextAttribute(fSharedColors.getColor(new RGB(0, 64, 92)), null, SWT.NONE));
+
+ for (int i = 0; i < BBLanguageHelper.SHELL_KEYWORDS.length; ++i) {
+ keywordRule.addWord(BBLanguageHelper.SHELL_KEYWORDS[i], token);
+ }
+
+ return keywordRule;
+ }
+
+ private SingleLineRule createStringLiteralRule() {
+ Color red = fSharedColors.getColor(new RGB(50, 50, 100));
+ SingleLineRule rule = new SingleLineRule("\"", "\"", new Token(new TextAttribute(red, null, SWT.NONE)), '\\');
+
+ return rule;
+ }
+
+ private IRule createVariableRule() {
+ Color blue = fSharedColors.getColor(new RGB(0, 0, 200));
+ IRule rule = new VariableRule(new Token(new TextAttribute(blue, null, SWT.NONE)));
+
+ return rule;
+ }
+
+ @Override
+ public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+ return new String[] { BitBakeDocumentProvider.RECIPE_CODE, BitBakeDocumentProvider.RECIPE_COMMENT };
+ }
+
+ @Override
+ public String getConfiguredDocumentPartitioning(ISourceViewer sourceViewer) {
+ return BitBakeDocumentProvider.RECIPE_PARTITIONING;
+ }
+
+ @Override
+ public IContentAssistant getContentAssistant(final ISourceViewer sourceViewer) {
+ ContentAssistant assistant = new ContentAssistant();
+ assistant.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+
+ // assistant.setContentAssistProcessor(new HippieProposalProcessor(),
+ // BitBakeDocumentProvider.RECIPE_COMMENT);
+ assistant.setContentAssistProcessor(new RecipeCompletionProcessor(), BitBakeDocumentProvider.RECIPE_CODE);
+
+ return assistant;
+ }
+
+ public IReconciler getReconciler(ISourceViewer sourceViewer) {
+ return null;
+ }
+
+ @Override
+ public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
+ PresentationReconciler reconciler = new PresentationReconciler();
+ reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+
+ addDamagerRepairer(reconciler, createCommentScanner(), BitBakeDocumentProvider.RECIPE_COMMENT);
+ addDamagerRepairer(reconciler, createRecipeScanner(), BitBakeDocumentProvider.RECIPE_CODE);
+
+ return reconciler;
+ }
+
+ public void setBBSession(BBSession session) {
+ this.session = session;
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/CustomFunctionRule.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/CustomFunctionRule.java
new file mode 100644
index 0000000..68bf076
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/CustomFunctionRule.java
@@ -0,0 +1,94 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.editors.bitbake;
+
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+
+/**
+ * Rule for def_ BB Recipe functions
+ * @author kgilmer
+ *
+ */
+final class CustomFunctionRule implements IRule {
+
+ /** Token to return for this rule */
+ private final IToken fToken;
+
+ /**
+ * Creates a new operator rule.
+ *
+ * @param token
+ * Token to use for this rule
+ */
+ public CustomFunctionRule(IToken token) {
+ fToken = token;
+ }
+
+ public IToken evaluate(ICharacterScanner scanner) {
+ if (scanner.getColumn() > 0) {
+ return Token.UNDEFINED;
+ }
+
+ int i = scanner.read();
+ int c = 1;
+
+ if (!Character.isLetter(i) && i != 10) {
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+
+ if (i == 'd' && scanAhead(scanner, "o_".toCharArray())) {
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+
+ while (i != ICharacterScanner.EOF && i != 10) {
+ i = scanner.read();
+ c++;
+
+ if (i == '(') {
+ readUntil(scanner, ')');
+
+ return fToken;
+ }
+ }
+
+ for (int t = 0; t < c; t++) {
+ scanner.unread();
+ }
+
+ return Token.UNDEFINED;
+ }
+
+ private void readUntil(ICharacterScanner scanner, int c) {
+ int i;
+ do {
+ i = scanner.read();
+ } while (! (i == ICharacterScanner.EOF) && ! (i == c));
+ }
+
+ private boolean scanAhead(ICharacterScanner scanner, char [] chars) {
+ boolean v = true;
+ for (int i = 0; i < chars.length; ++i) {
+ if (! (scanner.read() == chars[i])) {
+ v = false;
+ for (int j = 0; j < i; ++j) {
+ scanner.unread();
+ }
+ break;
+ }
+ }
+ return v;
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeCompletionProcessor.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeCompletionProcessor.java
new file mode 100644
index 0000000..c410124
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeCompletionProcessor.java
@@ -0,0 +1,125 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.editors.bitbake;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.jface.text.templates.DocumentTemplateContext;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateProposal;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.openembedded.bc.bitbake.BBLanguageHelper;
+import org.openembedded.bc.ui.Activator;
+
+
+class RecipeCompletionProcessor implements IContentAssistProcessor {
+
+ private static final String CONTEXT_ID= "bitbake_variables"; //$NON-NLS-1$
+ private final TemplateContextType fContextType= new TemplateContextType(CONTEXT_ID, "Common BitBake Variables"); //$NON-NLS-1$
+ //private final TemplateContextType fKeywordContextType= new TemplateContextType("bitbake_keywords", "BitBake Keywords"); //$NON-NLS-1$
+ private final TemplateContextType fFunctionContextType = new TemplateContextType("bitbake_functions", "BitBake Functions");
+
+ RecipeCompletionProcessor() {
+ }
+
+ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
+ IDocument document= viewer.getDocument();
+ Region region= new Region(offset, 0);
+
+ TemplateContext templateContext= new DocumentTemplateContext(fContextType, document, offset, 0);
+ //TemplateContext keywordContext = new DocumentTemplateContext(fKeywordContextType, document, offset, 0);
+ TemplateContext functionContext = new DocumentTemplateContext(fFunctionContextType, document, offset, 0);
+
+ List proposals = new ArrayList();
+
+ getVariableTemplateProposals(templateContext, region, proposals);
+ // getKeywordTemplateProposals(keywordContext, region, proposals);
+ getAddTaskTemplateProposals(templateContext, region, proposals);
+ getFunctionTemplateProposals(functionContext, region, proposals);
+
+ return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]);
+ }
+
+ public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
+ return null;
+ }
+
+ private Template generateVariableTemplate(String name, String description) {
+
+ return new Template(name, description, CONTEXT_ID, name + " = \"${" + name.toLowerCase() + "}\"", false);
+ }
+
+ private void getAddTaskTemplateProposals(TemplateContext templateContext, Region region, List p) {
+ p.add(new TemplateProposal(new Template("addtask", "addtask statement", CONTEXT_ID, "addtask ${task_name} after ${do_previous_task} before ${do_next_task}", false),templateContext, region, PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_BKMRK_TSK)));
+ }
+
+
+ public char[] getCompletionProposalAutoActivationCharacters() {
+ return null;
+ }
+
+ public char[] getContextInformationAutoActivationCharacters() {
+ return null;
+ }
+
+ public IContextInformationValidator getContextInformationValidator() {
+ return null;
+ }
+
+ public String getErrorMessage() {
+ return null;
+ }
+
+ private void getFunctionTemplateProposals(TemplateContext templateContext, Region region, List p) {
+ String [] keywords = BBLanguageHelper.BITBAKE_STANDARD_FUNCTIONS;
+ Image img = Activator.getDefault().getImageRegistry().get(Activator.IMAGE_FUNCTION);
+ Arrays.sort(keywords);
+
+ for (int i = 0; i < keywords.length; ++i) {
+ p.add(new TemplateProposal(new Template(keywords[i], keywords[i] + " function", CONTEXT_ID, "do_" + keywords[i] + "() {\n\n}", false), templateContext, region, img));
+ }
+ }
+
+ private void getKeywordTemplateProposals(TemplateContext templateContext, Region region, List p) {
+ String [] keywords = BBLanguageHelper.BITBAKE_KEYWORDS;
+
+ Arrays.sort(keywords);
+
+ for (int i = 0; i < keywords.length; ++i) {
+ p.add(new TemplateProposal(new Template(keywords[i], keywords[i] + " keyword", CONTEXT_ID, keywords[i] + " ", false),templateContext, region, null));
+ }
+ }
+
+ private void getVariableTemplateProposals(TemplateContext templateContext, Region region, List p) {
+ Map n = BBLanguageHelper.getCommonBitbakeVariables();
+ Image img = Activator.getDefault().getImageRegistry().get(Activator.IMAGE_VARIABLE);
+ for (Iterator i = n.keySet().iterator(); i.hasNext();) {
+ String name = (String) i.next();
+ String description = (String) n.get(name);
+ p.add(new TemplateProposal(generateVariableTemplate(name, description), templateContext, region, img));
+ }
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeEditorActionContributor.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeEditorActionContributor.java
new file mode 100644
index 0000000..b4ae491
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeEditorActionContributor.java
@@ -0,0 +1,47 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.editors.bitbake;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.editors.text.TextEditorActionContributor;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.texteditor.RetargetTextEditorAction;
+
+public class RecipeEditorActionContributor extends TextEditorActionContributor {
+
+ private RetargetTextEditorAction fContentAssist;
+
+ public RecipeEditorActionContributor() {
+ fContentAssist= new RetargetTextEditorAction(RecipeEditorMessages.getBundle(), "contentAssist."); //$NON-NLS-1$
+ fContentAssist.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+ }
+
+ @Override
+ public void contributeToMenu(IMenuManager menu) {
+ super.contributeToMenu(menu);
+
+ IMenuManager editMenu= menu.findMenuUsingPath(IWorkbenchActionConstants.M_EDIT);
+ if (editMenu != null) {
+ editMenu.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, fContentAssist);
+ }
+ }
+
+ @Override
+ public void setActiveEditor(IEditorPart part) {
+ super.setActiveEditor(part);
+ if (part instanceof ITextEditor) {
+ fContentAssist.setAction(getAction((ITextEditor) part, BitBakeFileEditor.CONTENT_ASSIST));
+ }
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeEditorMessages.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeEditorMessages.java
new file mode 100644
index 0000000..c1f80ba
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeEditorMessages.java
@@ -0,0 +1,21 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.editors.bitbake;
+
+import java.util.ResourceBundle;
+
+public class RecipeEditorMessages {
+
+ public static ResourceBundle getBundle() {
+ return ResourceBundle.getBundle(RecipeEditorMessages.class.getName());
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeEditorMessages.properties b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeEditorMessages.properties
new file mode 100644
index 0000000..76c670b
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/RecipeEditorMessages.properties
@@ -0,0 +1,14 @@
+#########################################################
+# Copyright (c) 2006 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+##########################################################
+contentAssist.label=Content Assist
+contentAssist.tooltip=Content Assist
+contentAssist.image=
+contentAssist.description= Invokes content assist \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/VariableRule.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/VariableRule.java
new file mode 100644
index 0000000..c615a9f
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/editors/bitbake/VariableRule.java
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.editors.bitbake;
+
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+
+final class VariableRule implements IRule {
+
+ /** Token to return for this rule */
+ private final IToken fToken;
+
+ /**
+ * Creates a new operator rule.
+ *
+ * @param token
+ * Token to use for this rule
+ */
+ public VariableRule(IToken token) {
+ fToken = token;
+ }
+
+ public IToken evaluate(ICharacterScanner scanner) {
+ if (scanner.getColumn() > 0) {
+ return Token.UNDEFINED;
+ }
+
+ int i = scanner.read();
+ int c = 1;
+
+ if (!Character.isLetter(i) && i != 10) {
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+
+ int p = i;
+
+ while (i != ICharacterScanner.EOF && i != 10) {
+ p = i;
+ i = scanner.read();
+ c++;
+
+ if (i == '=') {
+ scanner.unread();
+
+ if (p == '?' || p == '+') {
+ scanner.unread();
+ }
+ return fToken;
+ }
+ }
+
+ for (int t = 0; t < c; t++) {
+ scanner.unread();
+ }
+
+ return Token.UNDEFINED;
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/Messages.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/Messages.java
new file mode 100644
index 0000000..596f565
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/Messages.java
@@ -0,0 +1,48 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.filesystem;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Provides translatable messages for the file system bundle
+ */
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.core.internal.filesystem.messages"; //$NON-NLS-1$
+
+ public static String copying;
+ public static String couldnotDelete;
+ public static String couldnotDeleteReadOnly;
+ public static String couldNotLoadLibrary;
+ public static String couldNotMove;
+ public static String couldNotRead;
+ public static String couldNotWrite;
+ public static String deleteProblem;
+ public static String deleting;
+ public static String failedCreateWrongType;
+ public static String failedMove;
+ public static String failedReadDuringWrite;
+ public static String fileExists;
+ public static String fileNotFound;
+ public static String moving;
+ public static String noFileSystem;
+ public static String noImplDelete;
+ public static String noImplWrite;
+ public static String noScheme;
+ public static String notAFile;
+ public static String readOnlyParent;
+
+ static {
+ // initialize resource bundles
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEFile.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEFile.java
new file mode 100644
index 0000000..673bb56
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEFile.java
@@ -0,0 +1,465 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Ken Gilmer - adaptation from internal class.
+ *******************************************************************************/
+package org.openembedded.bc.ui.filesystem;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.util.List;
+
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileInfo;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.filesystem.IFileSystem;
+import org.eclipse.core.filesystem.URIUtil;
+import org.eclipse.core.filesystem.provider.FileInfo;
+import org.eclipse.core.filesystem.provider.FileStore;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * File system implementation based on storage of files in the local
+ * operating system's file system.
+ */
+public class OEFile extends FileStore {
+ private static int attributes(File aFile) {
+ if (!aFile.exists() || aFile.canWrite())
+ return EFS.NONE;
+ return EFS.ATTRIBUTE_READ_ONLY;
+ }
+
+ /**
+ * The java.io.File that this store represents.
+ */
+ protected final File file;
+ private List ignorePaths;
+
+ /**
+ * The absolute file system path of the file represented by this store.
+ */
+ protected final String filePath;
+
+ private final String root;
+
+ /**
+ * Creates a new local file.
+ *
+ * @param file The file this local file represents
+ * @param root
+ */
+ public OEFile(File file, List ignorePaths, String root) {
+ this.file = file;
+ this.ignorePaths = ignorePaths;
+ this.root = root;
+ this.filePath = file.getAbsolutePath();
+ }
+
+ /**
+ * This method is called after a failure to modify a file or directory.
+ * Check to see if the parent is read-only and if so then
+ * throw an exception with a more specific message and error code.
+ *
+ * @param target The file that we failed to modify
+ * @param exception The low level exception that occurred, or <code>null</code>
+ * @throws CoreException A more specific exception if the parent is read-only
+ */
+ private void checkReadOnlyParent(File target, Throwable exception) throws CoreException {
+ File parent = target.getParentFile();
+ if (parent != null && (attributes(parent) & EFS.ATTRIBUTE_READ_ONLY) != 0) {
+ String message = NLS.bind(Messages.readOnlyParent, target.getAbsolutePath());
+ Policy.error(EFS.ERROR_PARENT_READ_ONLY, message, exception);
+ }
+ }
+
+ @Override
+ public String[] childNames(int options, IProgressMonitor monitor) {
+ String[] names = file.list();
+ return (names == null ? EMPTY_STRING_ARRAY : names);
+ }
+
+ @Override
+ public IFileStore[] childStores(int options, IProgressMonitor monitor) throws CoreException {
+ String[] children = childNames(options, monitor);
+ IFileStore[] wrapped = new IFileStore[children.length];
+
+ for (int i = 0; i < wrapped.length; i++) {
+ String fullPath = file.toString() +File.separatorChar + children[i];
+
+ if (ignorePaths.contains(fullPath)) {
+ wrapped[i] = getDeadChild(children[i]);
+ } else {
+ wrapped[i] = getChild(children[i]);
+ }
+ }
+
+ return wrapped;
+ }
+
+ @Override
+ public void copy(IFileStore destFile, int options, IProgressMonitor monitor) throws CoreException {
+ if (destFile instanceof OEFile) {
+ File source = file;
+ File destination = ((OEFile) destFile).file;
+ //handle case variants on a case-insensitive OS, or copying between
+ //two equivalent files in an environment that supports symbolic links.
+ //in these nothing needs to be copied (and doing so would likely lose data)
+ try {
+ if (source.getCanonicalFile().equals(destination.getCanonicalFile())) {
+ //nothing to do
+ return;
+ }
+ } catch (IOException e) {
+ String message = NLS.bind(Messages.couldNotRead, source.getAbsolutePath());
+ Policy.error(EFS.ERROR_READ, message, e);
+ }
+ }
+ //fall through to super implementation
+ super.copy(destFile, options, monitor);
+ }
+
+ @Override
+ public void delete(int options, IProgressMonitor monitor) throws CoreException {
+ if (monitor == null)
+ monitor = new NullProgressMonitor();
+ else
+ monitor = new NullProgressMonitor();
+ try {
+ monitor.beginTask(NLS.bind(Messages.deleting, this), 200);
+ String message = Messages.deleteProblem;
+ MultiStatus result = new MultiStatus(Policy.PI_FILE_SYSTEM, EFS.ERROR_DELETE, message, null);
+
+ //don't allow Eclipse to delete entire OE directory
+
+ if (!isProject()) {
+ internalDelete(file, filePath, result, monitor);
+ }
+
+ if (!result.isOK())
+ throw new CoreException(result);
+ } finally {
+ monitor.done();
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof OEFile))
+ return false;
+
+ OEFile otherFile = (OEFile) obj;
+
+ return file.equals(otherFile.file);
+ }
+
+ @Override
+ public IFileInfo fetchInfo(int options, IProgressMonitor monitor) {
+ //in-lined non-native implementation
+ FileInfo info = new FileInfo(file.getName());
+ final long lastModified = file.lastModified();
+ if (lastModified <= 0) {
+ //if the file doesn't exist, all other attributes should be default values
+ info.setExists(false);
+ return info;
+ }
+ info.setLastModified(lastModified);
+ info.setExists(true);
+ info.setLength(file.length());
+ info.setDirectory(file.isDirectory());
+ info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, file.exists() && !file.canWrite());
+ info.setAttribute(EFS.ATTRIBUTE_HIDDEN, file.isHidden());
+ return info;
+ }
+
+ @Override
+ public IFileStore getChild(IPath path) {
+ return new OEFile(new File(file, path.toOSString()), ignorePaths, root);
+ }
+
+ @Override
+ public IFileStore getChild(String name) {
+ return new OEFile(new File(file, name), ignorePaths, root);
+ }
+
+ private IFileStore getDeadChild(String name) {
+ return new OEIgnoreFile(new File(file, name));
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.core.filesystem.IFileStore#getFileSystem()
+ */
+ @Override
+ public IFileSystem getFileSystem() {
+ return OEFileSystem.getInstance();
+ }
+
+ @Override
+ public String getName() {
+ return file.getName();
+ }
+
+ @Override
+ public IFileStore getParent() {
+ File parent = file.getParentFile();
+ return parent == null ? null : new OEFile(parent, ignorePaths, root);
+ }
+
+ @Override
+ public int hashCode() {
+ return file.hashCode();
+ }
+
+ /**
+ * Deletes the given file recursively, adding failure info to
+ * the provided status object. The filePath is passed as a parameter
+ * to optimize java.io.File object creation.
+ */
+ private boolean internalDelete(File target, String pathToDelete, MultiStatus status, IProgressMonitor monitor) {
+ //first try to delete - this should succeed for files and symbolic links to directories
+ if (target.delete() || !target.exists())
+ return true;
+ if (target.isDirectory()) {
+ monitor.subTask(NLS.bind(Messages.deleting, target));
+ String[] list = target.list();
+ if (list == null)
+ list = EMPTY_STRING_ARRAY;
+ int parentLength = pathToDelete.length();
+ boolean failedRecursive = false;
+ for (int i = 0, imax = list.length; i < imax; i++) {
+ //optimized creation of child path object
+ StringBuffer childBuffer = new StringBuffer(parentLength + list[i].length() + 1);
+ childBuffer.append(pathToDelete);
+ childBuffer.append(File.separatorChar);
+ childBuffer.append(list[i]);
+ String childName = childBuffer.toString();
+ // try best effort on all children so put logical OR at end
+ failedRecursive = !internalDelete(new java.io.File(childName), childName, status, monitor) || failedRecursive;
+ monitor.worked(1);
+ }
+ try {
+ // don't try to delete the root if one of the children failed
+ if (!failedRecursive && target.delete())
+ return true;
+ } catch (Exception e) {
+ // we caught a runtime exception so log it
+ String message = NLS.bind(Messages.couldnotDelete, target.getAbsolutePath());
+ status.add(new Status(IStatus.ERROR, Policy.PI_FILE_SYSTEM, EFS.ERROR_DELETE, message, e));
+ return false;
+ }
+ }
+ //if we got this far, we failed
+ String message = null;
+ if (fetchInfo().getAttribute(EFS.ATTRIBUTE_READ_ONLY))
+ message = NLS.bind(Messages.couldnotDeleteReadOnly, target.getAbsolutePath());
+ else
+ message = NLS.bind(Messages.couldnotDelete, target.getAbsolutePath());
+ status.add(new Status(IStatus.ERROR, Policy.PI_FILE_SYSTEM, EFS.ERROR_DELETE, message, null));
+ return false;
+ }
+
+ @Override
+ public boolean isParentOf(IFileStore other) {
+ if (!(other instanceof OEFile))
+ return false;
+ String thisPath = filePath;
+ String thatPath = ((OEFile) other).filePath;
+ int thisLength = thisPath.length();
+ int thatLength = thatPath.length();
+ //if equal then not a parent
+ if (thisLength >= thatLength)
+ return false;
+ if (getFileSystem().isCaseSensitive()) {
+ if (thatPath.indexOf(thisPath) != 0)
+ return false;
+ } else {
+ if (thatPath.toLowerCase().indexOf(thisPath.toLowerCase()) != 0)
+ return false;
+ }
+ //The common portion must end with a separator character for this to be a parent of that
+ return thisPath.charAt(thisLength - 1) == File.separatorChar || thatPath.charAt(thisLength) == File.separatorChar;
+ }
+
+ /**
+ * @return
+ */
+ private boolean isProject() {
+ return this.file.toString().equals(root);
+ }
+
+ @Override
+ public IFileStore mkdir(int options, IProgressMonitor monitor) throws CoreException {
+ boolean shallow = (options & EFS.SHALLOW) != 0;
+ //must be a directory
+ if (shallow)
+ file.mkdir();
+ else
+ file.mkdirs();
+ if (!file.isDirectory()) {
+ checkReadOnlyParent(file, null);
+ String message = NLS.bind(Messages.failedCreateWrongType, filePath);
+ Policy.error(EFS.ERROR_WRONG_TYPE, message);
+ }
+ return this;
+ }
+
+ @Override
+ public void move(IFileStore destFile, int options, IProgressMonitor monitor) throws CoreException {
+ if (!(destFile instanceof OEFile)) {
+ super.move(destFile, options, monitor);
+ return;
+ }
+ File source = file;
+ File destination = ((OEFile) destFile).file;
+ boolean overwrite = (options & EFS.OVERWRITE) != 0;
+ monitor = Policy.monitorFor(monitor);
+ try {
+ monitor.beginTask(NLS.bind(Messages.moving, source.getAbsolutePath()), 10);
+ //this flag captures case renaming on a case-insensitive OS, or moving
+ //two equivalent files in an environment that supports symbolic links.
+ //in these cases we NEVER want to delete anything
+ boolean sourceEqualsDest = false;
+ try {
+ sourceEqualsDest = source.getCanonicalFile().equals(destination.getCanonicalFile());
+ } catch (IOException e) {
+ String message = NLS.bind(Messages.couldNotMove, source.getAbsolutePath());
+ Policy.error(EFS.ERROR_WRITE, message, e);
+ }
+ if (!sourceEqualsDest && !overwrite && destination.exists()) {
+ String message = NLS.bind(Messages.fileExists, destination.getAbsolutePath());
+ Policy.error(EFS.ERROR_EXISTS, message);
+ }
+ if (source.renameTo(destination)) {
+ // double-check to ensure we really did move
+ // since java.io.File#renameTo sometimes lies
+ if (!sourceEqualsDest && source.exists()) {
+ // XXX: document when this occurs
+ if (destination.exists()) {
+ // couldn't delete the source so remove the destination and throw an error
+ // XXX: if we fail deleting the destination, the destination (root) may still exist
+ new OEFile(destination, ignorePaths, root).delete(EFS.NONE, null);
+ String message = NLS.bind(Messages.couldnotDelete, source.getAbsolutePath());
+ Policy.error(EFS.ERROR_DELETE, message);
+ }
+ // source exists but destination doesn't so try to copy below
+ } else {
+ if (!destination.exists()) {
+ // neither the source nor the destination exist. this is REALLY bad
+ String message = NLS.bind(Messages.failedMove, source.getAbsolutePath(), destination.getAbsolutePath());
+ Policy.error(EFS.ERROR_WRITE, message);
+ }
+ //the move was successful
+ monitor.worked(10);
+ return;
+ }
+ }
+ // for some reason renameTo didn't work
+ if (sourceEqualsDest) {
+ String message = NLS.bind(Messages.couldNotMove, source.getAbsolutePath());
+ Policy.error(EFS.ERROR_WRITE, message, null);
+ }
+ // fall back to default implementation
+ super.move(destFile, options, Policy.subMonitorFor(monitor, 10));
+ } finally {
+ monitor.done();
+ }
+ }
+
+ @Override
+ public InputStream openInputStream(int options, IProgressMonitor monitor) throws CoreException {
+ monitor = Policy.monitorFor(monitor);
+ try {
+ monitor.beginTask("", 1); //$NON-NLS-1$
+ return new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ String message;
+ if (!file.exists())
+ message = NLS.bind(Messages.fileNotFound, filePath);
+ else if (file.isDirectory())
+ message = NLS.bind(Messages.notAFile, filePath);
+ else
+ message = NLS.bind(Messages.couldNotRead, filePath);
+ Policy.error(EFS.ERROR_READ, message, e);
+ return null;
+ } finally {
+ monitor.done();
+ }
+ }
+
+ @Override
+ public OutputStream openOutputStream(int options, IProgressMonitor monitor) throws CoreException {
+ monitor = Policy.monitorFor(monitor);
+ try {
+ monitor.beginTask("", 1); //$NON-NLS-1$
+ return new FileOutputStream(file, (options & EFS.APPEND) != 0);
+ } catch (FileNotFoundException e) {
+ checkReadOnlyParent(file, e);
+ String message;
+ String path = filePath;
+ if (file.isDirectory())
+ message = NLS.bind(Messages.notAFile, path);
+ else
+ message = NLS.bind(Messages.couldNotWrite, path);
+ Policy.error(EFS.ERROR_WRITE, message, e);
+ return null;
+ } finally {
+ monitor.done();
+ }
+ }
+
+ @Override
+ public void putInfo(IFileInfo info, int options, IProgressMonitor monitor) throws CoreException {
+ boolean success = true;
+
+ //native does not currently set last modified
+ if ((options & EFS.SET_LAST_MODIFIED) != 0)
+ success &= file.setLastModified(info.getLastModified());
+ if (!success && !file.exists())
+ Policy.error(EFS.ERROR_NOT_EXISTS, NLS.bind(Messages.fileNotFound, filePath));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.filesystem.provider.FileStore#toLocalFile(int, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public File toLocalFile(int options, IProgressMonitor monitor) throws CoreException {
+ if (options == EFS.CACHE)
+ return super.toLocalFile(options, monitor);
+ return file;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.filesystem.IFileStore#toString()
+ */
+ @Override
+ public String toString() {
+ return file.toString();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.filesystem.IFileStore#toURI()
+ */
+ @Override
+ public URI toURI() {
+ return URIUtil.toURI(filePath);
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEFileSystem.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEFileSystem.java
new file mode 100644
index 0000000..1c138b9
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEFileSystem.java
@@ -0,0 +1,81 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.filesystem;
+
+import java.io.File;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.filesystem.IFileSystem;
+import org.eclipse.core.filesystem.provider.FileSystem;
+import org.eclipse.core.internal.filesystem.NullFileStore;
+import org.eclipse.core.runtime.Path;
+import org.openembedded.bc.bitbake.BBSession;
+import org.openembedded.bc.ui.Activator;
+
+
+/**
+ * A filesystem that ignores specific OE directories that contain derived information.
+ * @author kgilmer
+ *
+ */
+public class OEFileSystem extends FileSystem {
+
+ private static IFileSystem ref;
+ public static IFileSystem getInstance() {
+ return ref;
+ }
+
+ private Map fileStoreCache;
+
+ public OEFileSystem() {
+ ref = this;
+ fileStoreCache = new Hashtable();
+ }
+
+ @Override
+ public IFileStore getStore(URI uri) {
+
+ OEFile uf = (OEFile) fileStoreCache.get(uri);
+
+ if (uf == null) {
+ BBSession config = null;
+ try {
+ config = Activator.getBBSession(uri.getPath());
+ if (!config.isInitialized()) {
+ config.initialize();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return new NullFileStore(new Path(uri.getPath()));
+ }
+
+ if (config.get("TMPDIR") == null || config.get("DL_DIR") == null) {
+ throw new RuntimeException("Invalid local.conf: TMPDIR or DL_DIR undefined.");
+ }
+
+ List ignoreList = new ArrayList();
+
+ //These directories are ignored because they contain too many files for Eclipse to handle efficiently.
+ ignoreList.add(config.get("TMPDIR"));
+ ignoreList.add(config.get("DL_DIR"));
+
+ uf = new OEFile(new File(uri.getPath()), ignoreList, uri.getPath());
+ fileStoreCache.put(uri, uf);
+ }
+
+ return uf;
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEFileSystemContributor.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEFileSystemContributor.java
new file mode 100644
index 0000000..58554a1
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEFileSystemContributor.java
@@ -0,0 +1,30 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.filesystem;
+
+import java.net.URI;
+
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.ide.fileSystem.FileSystemContributor;
+
+public class OEFileSystemContributor extends FileSystemContributor {
+
+ @Override
+ public URI browseFileSystem(String initialPath, Shell shell) {
+ return null;
+ }
+
+ @Override
+ public URI getURI(String string) {
+ return super.getURI(string);
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEIgnoreFile.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEIgnoreFile.java
new file mode 100644
index 0000000..63d51b8
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/OEIgnoreFile.java
@@ -0,0 +1,133 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.filesystem;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+
+import org.eclipse.core.filesystem.IFileInfo;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.filesystem.IFileSystem;
+import org.eclipse.core.filesystem.provider.FileInfo;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+public class OEIgnoreFile implements IFileStore {
+
+ private final File file;
+
+ public OEIgnoreFile(File file) {
+ this.file = file;
+ }
+
+ public IFileInfo[] childInfos(int options, IProgressMonitor monitor) throws CoreException {
+
+ return new IFileInfo[0];
+ }
+
+ public String[] childNames(int options, IProgressMonitor monitor) throws CoreException {
+ return new String[0];
+ }
+
+ public IFileStore[] childStores(int options, IProgressMonitor monitor) throws CoreException {
+
+ return new IFileStore[0];
+ }
+
+ public void copy(IFileStore destination, int options, IProgressMonitor monitor) throws CoreException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void delete(int options, IProgressMonitor monitor) throws CoreException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public IFileInfo fetchInfo() {
+ // TODO Auto-generated method stub
+ return new FileInfo(file.getName());
+ }
+
+ public IFileInfo fetchInfo(int options, IProgressMonitor monitor) throws CoreException {
+ return new FileInfo(file.getName());
+ }
+
+ public Object getAdapter(Class adapter) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public IFileStore getChild(IPath path) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+
+ public IFileStore getChild(String name) {
+ return null;
+ }
+
+ public IFileSystem getFileSystem() {
+ // TODO Auto-generated method stub
+ return OEFileSystem.getInstance();
+ }
+
+ public String getName() {
+ return file.getName();
+ }
+
+ public IFileStore getParent() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean isParentOf(IFileStore other) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public IFileStore mkdir(int options, IProgressMonitor monitor) throws CoreException {
+ return null;
+ }
+
+ public void move(IFileStore destination, int options, IProgressMonitor monitor) throws CoreException {
+ }
+
+ public InputStream openInputStream(int options, IProgressMonitor monitor) throws CoreException {
+ return null;
+ }
+
+ public OutputStream openOutputStream(int options, IProgressMonitor monitor) throws CoreException {
+ return null;
+ }
+
+ public void putInfo(IFileInfo info, int options, IProgressMonitor monitor) throws CoreException {
+ }
+
+ public File toLocalFile(int options, IProgressMonitor monitor) throws CoreException {
+ return file;
+ }
+
+ public URI toURI() {
+ return file.toURI();
+ }
+
+ public IFileStore getFileStore(IPath path) {
+ return null;
+ }
+
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/Policy.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/Policy.java
new file mode 100644
index 0000000..f19ecbd
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/filesystem/Policy.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.filesystem;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Date;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.openembedded.bc.ui.Activator;
+
+
+/**
+ * Grab bag of utility methods for the file system plugin
+ */
+public class Policy {
+
+ /**
+ * General debug flag for the plugin
+ */
+ public static boolean DEBUG = false;
+
+ public static final String PI_FILE_SYSTEM = "org.eclipse.core.filesystem"; //$NON-NLS-1$
+
+ public static void checkCanceled(IProgressMonitor monitor) {
+ if (monitor.isCanceled())
+ throw new OperationCanceledException();
+ }
+
+ /**
+ * Print a debug message to the console.
+ * Pre-pend the message with the current date and the name of the current thread.
+ */
+ public static void debug(String message) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(new Date(System.currentTimeMillis()));
+ buffer.append(" - ["); //$NON-NLS-1$
+ buffer.append(Thread.currentThread().getName());
+ buffer.append("] "); //$NON-NLS-1$
+ buffer.append(message);
+ System.out.println(buffer.toString());
+ }
+
+ public static void error(int code, String message) throws CoreException {
+ error(code, message, null);
+ }
+
+ public static void error(int code, String message, Throwable exception) throws CoreException {
+ int severity = code == 0 ? 0 : 1 << (code % 100 / 33);
+ throw new CoreException(new Status(severity, PI_FILE_SYSTEM, code, message, exception));
+ }
+
+ public static void log(int severity, String message, Throwable t) {
+ if (message == null)
+ message = ""; //$NON-NLS-1$
+ Activator.getDefault().getLog().log(new Status(severity, PI_FILE_SYSTEM, 1, message, t));
+ }
+
+ public static IProgressMonitor monitorFor(IProgressMonitor monitor) {
+ return monitor == null ? new NullProgressMonitor() : monitor;
+ }
+
+ /**
+ * Closes a stream and ignores any resulting exception.
+ */
+ public static void safeClose(InputStream in) {
+ try {
+ if (in != null)
+ in.close();
+ } catch (IOException e) {
+ //ignore
+ }
+ }
+
+ /**
+ * Closes a stream and ignores any resulting exception.
+ */
+ public static void safeClose(OutputStream out) {
+ try {
+ if (out != null)
+ out.close();
+ } catch (IOException e) {
+ //ignore
+ }
+ }
+
+ public static IProgressMonitor subMonitorFor(IProgressMonitor monitor, int ticks) {
+ if (monitor == null)
+ return new NullProgressMonitor();
+ if (monitor instanceof NullProgressMonitor)
+ return monitor;
+ return new SubProgressMonitor(monitor, ticks);
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/model/IModelElement.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/model/IModelElement.java
new file mode 100644
index 0000000..6a352c5
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/model/IModelElement.java
@@ -0,0 +1,15 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.model;
+
+public interface IModelElement {
+ public void initialize() throws Exception;
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/model/ProjectInfo.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/model/ProjectInfo.java
new file mode 100644
index 0000000..026e15b
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/model/ProjectInfo.java
@@ -0,0 +1,48 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.model;
+
+
+public class ProjectInfo implements IModelElement {
+ private String name;
+ private String location;
+ private String init;
+
+ public ProjectInfo() {
+ }
+
+ public String getInitScriptPath() {
+ return init;
+ }
+ public String getProjectName() {
+ return name;
+ }
+ public String getRootPath() {
+ return location;
+ }
+ public void initialize() throws Exception {
+ name = new String();
+ location = new String();
+ init = new String();
+ }
+
+ public void setInitScriptPath(String init) {
+ this.init = init;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/perspectives/BitbakeCommanderPerspective.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/perspectives/BitbakeCommanderPerspective.java
new file mode 100644
index 0000000..ecd5ce9
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/perspectives/BitbakeCommanderPerspective.java
@@ -0,0 +1,87 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.perspectives;
+
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+import org.eclipse.ui.console.IConsoleConstants;
+import org.openembedded.bc.ui.views.RecipeView;
+
+
+public class BitbakeCommanderPerspective implements IPerspectiveFactory {
+
+ private IPageLayout factory;
+
+ public BitbakeCommanderPerspective() {
+ super();
+ }
+
+ private void addActionSets() {
+ factory.addActionSet("org.openembedded.bc.ui.actionSet");
+ factory.addActionSet(IPageLayout.ID_NAVIGATE_ACTION_SET); // NON-NLS-1
+ }
+
+ private void addNewWizardShortcuts() {
+ factory.addNewWizardShortcut("org.openembedded.bc.ui.wizards.NewRecipeWizard");// NON-NLS-1
+ factory.addNewWizardShortcut("org.openembedded.bc.ui.wizards.newproject.NewBBCProjectWizard");// NON-NLS-1
+ factory.addNewWizardShortcut("org.eclipse.ui.wizards.new.file");// NON-NLS-1
+ }
+
+ private void addPerspectiveShortcuts() {
+ // factory.addPerspectiveShortcut("org.eclipse.team.ui.TeamSynchronizingPerspective");
+ // //NON-NLS-1
+ // factory.addPerspectiveShortcut("org.eclipse.team.cvs.ui.cvsPerspective");
+ // //NON-NLS-1
+ factory.addPerspectiveShortcut("org.eclipse.ui.resourcePerspective"); // NON-NLS-1
+ }
+
+ private void addViews() {
+ IFolderLayout bottom = factory.createFolder("bottomRight", // NON-NLS-1
+ IPageLayout.BOTTOM, 0.75f, factory.getEditorArea());
+
+ bottom.addView(IPageLayout.ID_PROBLEM_VIEW);
+ bottom.addView("org.eclipse.team.ui.GenericHistoryView"); // NON-NLS-1
+ bottom.addPlaceholder(IConsoleConstants.ID_CONSOLE_VIEW);
+
+ IFolderLayout topLeft = factory.createFolder("topLeft", // NON-NLS-1
+ IPageLayout.LEFT, 0.25f, factory.getEditorArea());
+ topLeft.addView(IPageLayout.ID_RES_NAV);
+ topLeft.addView(RecipeView.ID_VIEW); // NON-NLS-1
+ }
+
+ private void addViewShortcuts() {
+ // factory.addShowViewShortcut("org.eclipse.ant.ui.views.AntView");
+ // //NON-NLS-1
+ // factory.addShowViewShortcut("org.eclipse.team.ccvs.ui.AnnotateView");
+ // //NON-NLS-1
+ // factory.addShowViewShortcut("org.eclipse.pde.ui.DependenciesView");
+ // //NON-NLS-1
+ // factory.addShowViewShortcut("org.eclipse.jdt.junit.ResultView");
+ // //NON-NLS-1
+ factory.addShowViewShortcut("org.eclipse.team.ui.GenericHistoryView"); // NON-NLS-1
+ factory.addShowViewShortcut(IConsoleConstants.ID_CONSOLE_VIEW);
+ // factory.addShowViewShortcut(JavaUI.ID_PACKAGES);
+ factory.addShowViewShortcut(IPageLayout.ID_RES_NAV);
+ // factory.addShowViewShortcut(IPageLayout.ID_PROBLEM_VIEW);
+ // factory.addShowViewShortcut(IPageLayout.ID_OUTLINE);
+ }
+
+ public void createInitialLayout(IPageLayout factory) {
+ this.factory = factory;
+ addViews();
+ addActionSets();
+ addNewWizardShortcuts();
+ addPerspectiveShortcuts();
+ addViewShortcuts();
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/popup/actions/NewAction.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/popup/actions/NewAction.java
new file mode 100644
index 0000000..30eb3e8
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/popup/actions/NewAction.java
@@ -0,0 +1,43 @@
+package org.openembedded.bc.ui.popup.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IActionDelegate;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+
+public class NewAction implements IObjectActionDelegate {
+
+ /**
+ * Constructor for Action1.
+ */
+ public NewAction() {
+ super();
+ }
+
+ /**
+ * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ }
+
+ /**
+ * @see IActionDelegate#run(IAction)
+ */
+ public void run(IAction action) {
+ Shell shell = new Shell();
+ MessageDialog.openInformation(
+ shell,
+ "BitBake Commander UI Plug-in",
+ "New Action was executed.");
+ }
+
+ /**
+ * @see IActionDelegate#selectionChanged(IAction, ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/views/RecipeContentProvider.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/views/RecipeContentProvider.java
new file mode 100644
index 0000000..3482b9b
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/views/RecipeContentProvider.java
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.views;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectNature;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.openembedded.bc.bitbake.BBSession;
+import org.openembedded.bc.ui.Activator;
+import org.openembedded.bc.ui.builder.BitbakeCommanderNature;
+
+
+class RecipeContentProvider implements IStructuredContentProvider {
+ public void dispose() {
+ }
+
+ public Object[] getElements(Object parent) {
+ List recipes = new ArrayList();
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ IProjectNature nature = null;
+ for (int i = 0; i < projects.length; ++i) {
+ try {
+ if (projects[i].isOpen() && projects[i].hasNature(BitbakeCommanderNature.NATURE_ID)) {
+ recipes.addAll(getRecipesFromProject(projects[i]));
+ }
+ } catch (CoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ return recipes.toArray();
+ }
+
+ private Collection getRecipesFromProject(IProject project) throws Exception {
+ BBSession session = Activator.getBBSession(project.getLocationURI().getPath(), null);
+
+ if (!session.isInitialized()) {
+ session.initialize();
+ }
+
+ return session.getRecipeFiles(project);
+ }
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput) {
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/views/RecipeView.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/views/RecipeView.java
new file mode 100644
index 0000000..844a75e
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/views/RecipeView.java
@@ -0,0 +1,165 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.views;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.part.ViewPart;
+import org.openembedded.bc.ui.editors.bitbake.BitBakeFileEditor;
+
+
+public class RecipeView extends ViewPart {
+ class ViewLabelProvider extends LabelProvider implements ITableLabelProvider {
+ public Image getColumnImage(Object obj, int index) {
+ return getImage(obj);
+ }
+
+ public String getColumnText(Object obj, int index) {
+
+ if (obj instanceof IFile) {
+ return ((IFile) obj).getName();
+ }
+
+ return getText(obj);
+ }
+
+ @Override
+ public Image getImage(Object obj) {
+ return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE);
+ }
+ }
+ public static final String ID_VIEW = "org.openembedded.bc.ui.views.RecipeView";
+private TableViewer viewer;
+
+ /* private Action action1;
+ private Action action2;
+ */ private Action doubleClickAction;
+
+ private void contributeToActionBars() {
+ IActionBars bars = getViewSite().getActionBars();
+ fillLocalPullDown(bars.getMenuManager());
+ fillLocalToolBar(bars.getToolBarManager());
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+ viewer.setContentProvider(new RecipeContentProvider());
+ viewer.setLabelProvider(new ViewLabelProvider());
+ viewer.setSorter(new ViewerSorter());
+ viewer.setInput(getViewSite());
+ makeActions();
+ hookContextMenu();
+ hookDoubleClickAction();
+ contributeToActionBars();
+ }
+
+ private void fillContextMenu(IMenuManager manager) {
+/* manager.add(action1);
+ manager.add(action2);
+*/ // Other plug-ins can contribute there actions here
+ manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+ }
+
+ private void fillLocalPullDown(IMenuManager manager) {
+/* manager.add(action1);
+ manager.add(new Separator());
+ manager.add(action2);
+*/ }
+
+ private void fillLocalToolBar(IToolBarManager manager) {
+/* manager.add(action1);
+ manager.add(action2);
+*/ }
+
+ private void hookContextMenu() {
+ MenuManager menuMgr = new MenuManager("#PopupMenu");
+ menuMgr.setRemoveAllWhenShown(true);
+ menuMgr.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ RecipeView.this.fillContextMenu(manager);
+ }
+ });
+ Menu menu = menuMgr.createContextMenu(viewer.getControl());
+ viewer.getControl().setMenu(menu);
+ getSite().registerContextMenu(menuMgr, viewer);
+ }
+
+ private void hookDoubleClickAction() {
+ viewer.addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+ doubleClickAction.run();
+ }
+ });
+ }
+
+ private void makeActions() {
+/* action1 = new Action() {
+ public void run() {
+ }
+ };
+ action1.setText("Action 1");
+ action1.setToolTipText("Action 1 tooltip");
+ action1.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
+
+ action2 = new Action() {
+ public void run() {
+ }
+ };
+ action2.setText("Action 2");
+ action2.setToolTipText("Action 2 tooltip");
+ action2.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
+*/ doubleClickAction = new Action() {
+ @Override
+ public void run() {
+ ISelection selection = viewer.getSelection();
+ Object obj = ((IStructuredSelection) selection).getFirstElement();
+
+ if (obj instanceof IFile) {
+ try {
+ RecipeView.this.getViewSite().getPage().openEditor(new FileEditorInput((IFile) obj), BitBakeFileEditor.EDITOR_ID);
+ } catch (PartInitException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ };
+ }
+
+ @Override
+ public void setFocus() {
+ viewer.getControl().setFocus();
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/FiniteStateWizard.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/FiniteStateWizard.java
new file mode 100644
index 0000000..575b3ec
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/FiniteStateWizard.java
@@ -0,0 +1,56 @@
+package org.openembedded.bc.ui.wizards;
+import java.util.Map;
+
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.swt.widgets.Composite;
+
+
+
+public abstract class FiniteStateWizard extends Wizard {
+ private boolean finishable = false;
+ private boolean canFinish;
+
+ public FiniteStateWizard() {
+ }
+
+ public abstract boolean performFinish();
+
+ /**
+ * @return Returns if the wizard is finishable in its current state.
+ */
+ public boolean isFinishable() {
+ return finishable;
+ }
+ /**
+ * @param finishable Change the finish state of the wizard.
+ */
+ public void setFinishable(boolean finishable) {
+ this.finishable = finishable;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.wizard.IWizard#createPageControls(org.eclipse.swt.widgets.Composite)
+ */
+ public void createPageControls(Composite pageContainer) {
+ super.createPageControls(pageContainer);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWizard.
+ */
+ public boolean canFinish() {
+ if (canFinish)
+ return true;
+ return super.canFinish();
+ }
+
+ public void setCanFinish(boolean canFinish) {
+ this.canFinish = canFinish;
+ }
+
+ /**
+ * Retrive the model object from the wizard.
+ * @return
+ */
+ public abstract Map getModel();
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/FiniteStateWizardPage.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/FiniteStateWizardPage.java
new file mode 100644
index 0000000..4a26d13
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/FiniteStateWizardPage.java
@@ -0,0 +1,148 @@
+package org.openembedded.bc.ui.wizards;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+public abstract class FiniteStateWizardPage extends WizardPage {
+ protected Map model = null;
+ protected FiniteStateWizard wizard = null;
+ private static boolean previousState = false;
+ /**
+ * @param pageName
+ */
+ protected FiniteStateWizardPage(String name, Map model) {
+ super(name);
+ this.model = model;
+ this.setPageComplete(false);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public abstract void createControl(Composite parent);
+
+ protected void setModelWizard() {
+ if (wizard == null) {
+ wizard = (FiniteStateWizard)FiniteStateWizardPage.this.getWizard();
+ }
+ }
+
+ /**
+ * Add page validation logic here. Returning <code>true</code> means that
+ * the page is complete and the user can go to the next page.
+ *
+ * @return
+ */
+ protected abstract boolean validatePage();
+
+ /**
+ * This method should be implemented by ModelWizardPage classes. This method
+ * is called after the <code>validatePage()</code> returns successfully.
+ * Update the model with the contents of the controls on the page.
+ */
+ protected abstract void updateModel();
+
+ /**
+ * Helper method to see if a field has some sort of text in it.
+ * @param value
+ * @return
+ */
+ protected boolean hasContents(String value) {
+ if (value == null || value.length() == 0) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * This method is called right before a page is displayed.
+ * This occurs on user action (Next/Back buttons).
+ */
+ public abstract void pageDisplay();
+
+ /**
+ * This method is called on the concrete WizardPage after the user has
+ * gone to the page after.
+ */
+ public abstract void pageCleanup();
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
+ */
+ public void setVisible(boolean arg0) {
+
+ if (!arg0 && previousState) {
+ pageCleanup();
+ } else if (arg0 && !previousState) {
+ pageDisplay();
+ } else if (arg0 && previousState) {
+ pageDisplay();
+ }
+
+ previousState = arg0;
+
+ super.setVisible(arg0);
+ }
+
+ public class ValidationListener implements SelectionListener, ModifyListener, Listener, ISelectionChangedListener {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ public void widgetSelected(SelectionEvent e) {
+ validate();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
+ */
+ public void modifyText(ModifyEvent e) {
+ validate();
+ }
+
+ public void validate() {
+ if (validatePage()) {
+ updateModel();
+ setPageComplete(true);
+ return;
+ }
+
+ setPageComplete(false);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
+ */
+ public void handleEvent(Event event) {
+ validate();
+ }
+
+ public void selectionChanged(SelectionChangedEvent event) {
+ validate();
+ }
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/NewBitBakeFileRecipeWizard.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/NewBitBakeFileRecipeWizard.java
new file mode 100644
index 0000000..c02719f
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/NewBitBakeFileRecipeWizard.java
@@ -0,0 +1,185 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.wizards;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWizard;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.openembedded.bc.bitbake.BBLanguageHelper;
+
+
+public class NewBitBakeFileRecipeWizard extends Wizard implements INewWizard {
+ private NewBitBakeFileRecipeWizardPage page;
+ private ISelection selection;
+
+ public NewBitBakeFileRecipeWizard() {
+ super();
+ setNeedsProgressMonitor(true);
+ }
+
+ @Override
+ public void addPages() {
+ page = new NewBitBakeFileRecipeWizardPage(selection);
+ addPage(page);
+ }
+
+ private void doFinish(String containerName, String fileName, String description, String license, String homepage, String author, String srcuri, IProgressMonitor monitor) throws CoreException {
+
+ monitor.beginTask("Creating " + fileName, 2);
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IResource resource = root.findMember(new Path(containerName));
+ if (!resource.exists() || !(resource instanceof IContainer)) {
+ throwCoreException("Container \"" + containerName + "\" does not exist.");
+ }
+ IContainer container = (IContainer) resource;
+
+ // If the extension wasn't specified, assume .bb
+ if (!fileName.endsWith(BBLanguageHelper.BITBAKE_RECIPE_FILE_EXTENSION) || !fileName.endsWith(".inc") || !fileName.endsWith(".conf")) {
+ fileName = fileName + ".bb";
+ }
+
+ final IFile file = container.getFile(new Path(fileName));
+ try {
+ InputStream stream = openContentStream(fileName, description, license, homepage, author, srcuri);
+ if (file.exists()) {
+ file.setContents(stream, true, true, monitor);
+ } else {
+ file.create(stream, true, monitor);
+ }
+ stream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ monitor.worked(1);
+ monitor.setTaskName("Opening file for editing...");
+ getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ try {
+ IDE.openEditor(page, file, true);
+ } catch (PartInitException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ monitor.worked(1);
+ }
+
+ /**
+ * We will accept the selection in the workbench to see if we can initialize
+ * from it.
+ *
+ * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
+ */
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ this.selection = selection;
+ }
+
+ /**
+ * We will initialize file contents with a sample text.
+ * @param srcuri
+ * @param author
+ * @param homepage
+ * @param license
+ * @param description
+ * @param fileName
+ * @param newPage
+ */
+
+ private InputStream openContentStream(String fileName, String description, String license, String homepage, String author, String srcuri) {
+
+ StringBuffer sb = new StringBuffer();
+
+ sb.append("DESCRIPTION = \"" + description + "\"\n");
+
+ if (author.length() > 0) {
+ sb.append("AUTHOR = \"" + author + "\"\n");
+ }
+
+ if (homepage.length() > 0) {
+ sb.append("HOMEPAGE = \"" + homepage + "\"\n");
+ }
+
+ if (license.length() > 0) {
+ sb.append("LICENSE = \"" + license + "\"\n");
+ }
+
+ if (srcuri.length() > 0) {
+ sb.append("SRC_URI = \"" + srcuri + "\"\n");
+ }
+
+ sb.append("\n");
+
+ return new ByteArrayInputStream(sb.toString().getBytes());
+ }
+
+ @Override
+ public boolean performFinish() {
+ final String containerName = page.getContainerName();
+ final String fileName = page.getFileName();
+ final String description = page.getDescriptionText();
+ final String license = page.getLicenseText();
+ final String homepage = page.getHomepageText();
+ final String author = page.getAuthorText();
+ final String srcuri = page.getSrcuriText();
+
+ IRunnableWithProgress op = new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InvocationTargetException {
+ try {
+ doFinish(containerName, fileName, description, license, homepage, author, srcuri, monitor);
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+ try {
+ getContainer().run(true, false, op);
+ } catch (InterruptedException e) {
+ return false;
+ } catch (InvocationTargetException e) {
+ Throwable realException = e.getTargetException();
+ MessageDialog.openError(getShell(), "Error", realException.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ private void throwCoreException(String message) throws CoreException {
+ IStatus status = new Status(IStatus.ERROR, "org.openembedded.bc.ui", IStatus.OK, message, null);
+ throw new CoreException(status);
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/NewBitBakeFileRecipeWizardPage.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/NewBitBakeFileRecipeWizardPage.java
new file mode 100644
index 0000000..0f725a3
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/NewBitBakeFileRecipeWizardPage.java
@@ -0,0 +1,221 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.wizards;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.ContainerSelectionDialog;
+
+public class NewBitBakeFileRecipeWizardPage extends WizardPage {
+ private Text containerText;
+
+ private Text fileText;
+
+ private ISelection selection;
+
+ private Text descriptionText;
+
+ private Text licenseText;
+
+ private Text homepageText;
+
+ private Text authorText;
+
+ private Text srcuriText;
+ public NewBitBakeFileRecipeWizardPage(ISelection selection) {
+ super("wizardPage");
+ setTitle("BitBake Recipe");
+ setDescription("Create a new BitBake recipe.");
+ this.selection = selection;
+ }
+
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ container.setLayout(layout);
+ layout.numColumns = 3;
+ layout.verticalSpacing = 9;
+
+ createField(container, "&Recipe Name:", (fileText = new Text(container, SWT.BORDER | SWT.SINGLE)));
+
+ Label label = new Label(container, SWT.NULL);
+ GridData gd = new GridData();
+ gd.horizontalSpan = 3;
+ label.setLayoutData(gd);
+
+ label = new Label(container, SWT.NULL);
+ label.setText("&Directory:");
+
+ containerText = new Text(container, SWT.BORDER | SWT.SINGLE);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ containerText.setLayoutData(gd);
+ containerText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ dialogChanged();
+ }
+ });
+
+ Button button = new Button(container, SWT.PUSH);
+ button.setText("Browse...");
+ button.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowse();
+ }
+ });
+
+ label = new Label(container, SWT.NULL);
+ gd = new GridData();
+ gd.horizontalSpan = 3;
+ label.setLayoutData(gd);
+
+ // label = new Label(container, SWT.SEPARATOR | SWT.HORIZONTAL);
+ createField(container, "&Package Description:", (descriptionText = new Text(container, SWT.BORDER | SWT.SINGLE)));
+ createField(container, "&License:", (licenseText = new Text(container, SWT.BORDER | SWT.SINGLE)));
+ createField(container, "&Homepage:", (homepageText = new Text(container, SWT.BORDER | SWT.SINGLE)));
+ createField(container, "Package &Author:", (authorText = new Text(container, SWT.BORDER | SWT.SINGLE)));
+
+ // label = new Label(container, SWT.SEPARATOR | SWT.HORIZONTAL);
+
+ createField(container, "SRC_URI:", (srcuriText = new Text(container, SWT.BORDER | SWT.SINGLE)));
+
+ initialize();
+ dialogChanged();
+ setControl(container);
+ }
+
+ private void createField(Composite container, String title, Text control) {
+ Label label = new Label(container, SWT.NONE);
+ label.setText(title);
+ label.moveAbove(control);
+
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ control.setLayoutData(gd);
+ control.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent e) {
+ dialogChanged();
+ }
+
+ });
+ }
+
+ private void dialogChanged() {
+ IResource container = ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(getContainerName()));
+ String fileName = getFileName();
+
+ if (getContainerName().length() == 0) {
+ updateStatus("Directory must be specified");
+ return;
+ }
+ if (container == null || (container.getType() & (IResource.PROJECT | IResource.FOLDER)) == 0) {
+ updateStatus("File container must exist");
+ return;
+ }
+ if (!container.isAccessible()) {
+ updateStatus("Project must be writable");
+ return;
+ }
+ if (fileName.length() == 0) {
+ updateStatus("File name must be specified");
+ return;
+ }
+ if (fileName.replace('\\', '/').indexOf('/', 1) > 0) {
+ updateStatus("File name must be valid");
+ return;
+ }
+
+ if (getDescriptionText().length() == 0) {
+ updateStatus("Recipe must have a description");
+ return;
+ }
+
+ updateStatus(null);
+ }
+
+ public String getAuthorText() {
+ return authorText.getText();
+ }
+
+ public String getContainerName() {
+ return containerText.getText();
+ }
+
+ public String getDescriptionText() {
+ return descriptionText.getText();
+ }
+
+ public String getFileName() {
+ return fileText.getText();
+ }
+
+ public String getHomepageText() {
+ return homepageText.getText();
+ }
+
+ public String getLicenseText() {
+ return licenseText.getText();
+ }
+
+ public String getSrcuriText() {
+ return srcuriText.getText();
+ }
+
+ private void handleBrowse() {
+ ContainerSelectionDialog dialog = new ContainerSelectionDialog(getShell(), ResourcesPlugin.getWorkspace().getRoot(), false, "Select project directory");
+ if (dialog.open() == Window.OK) {
+ Object[] result = dialog.getResult();
+ if (result.length == 1) {
+ containerText.setText(((Path) result[0]).toString());
+ }
+ }
+ }
+
+ private void initialize() {
+ if (selection != null && selection.isEmpty() == false && selection instanceof IStructuredSelection) {
+ IStructuredSelection ssel = (IStructuredSelection) selection;
+ if (ssel.size() > 1)
+ return;
+ Object obj = ssel.getFirstElement();
+ if (obj instanceof IResource) {
+ IContainer container;
+ if (obj instanceof IContainer)
+ container = (IContainer) obj;
+ else
+ container = ((IResource) obj).getParent();
+ containerText.setText(container.getFullPath().toString());
+ }
+ }
+ }
+
+ private void updateStatus(String message) {
+ setErrorMessage(message);
+ setPageComplete(message == null);
+ }
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/importProject/BBCProjectPage.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/importProject/BBCProjectPage.java
new file mode 100644
index 0000000..44198aa
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/importProject/BBCProjectPage.java
@@ -0,0 +1,234 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.wizards.importProject;
+
+import java.io.File;
+import java.util.Map;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.openembedded.bc.ui.wizards.FiniteStateWizardPage;
+
+
+/**
+ * Main property page for new project wizard.
+ * @author kgilmer
+ *
+ */
+public class BBCProjectPage extends FiniteStateWizardPage {
+
+ private class FileOpenSelectionAdapter extends SelectionAdapter {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ FileDialog fd = new FileDialog(PlatformUI.getWorkbench()
+ .getDisplay().getActiveShell(), SWT.OPEN);
+
+ fd.setText("Open Configuration Script");
+ fd.setFilterPath(txtProjectLocation.getText());
+
+ String selected = fd.open();
+
+ if (selected != null) {
+ txtInit.setText(selected);
+ updateModel();
+ }
+ }
+ }
+ public static final String PAGE_TITLE = "BitBake Commander Project";
+ private Text txtProjectLocation;
+
+ private Text txtInit;
+ private ValidationListener validationListener;
+ private Text txtProjectName;
+
+ public BBCProjectPage(Map model) {
+ super(PAGE_TITLE, model);
+ setMessage("Enter information to create a BitBake Commander project.");
+ }
+
+ public void createControl(Composite parent) {
+ GridData gdFillH = new GridData(GridData.FILL_HORIZONTAL);
+ GridData gdVU = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
+
+ Composite top = new Composite(parent, SWT.NONE);
+ top.setLayoutData(new GridData(GridData.FILL_BOTH));
+ top.setLayout(new GridLayout());
+
+ Composite projectNameComp = new Composite(top, SWT.NONE);
+ GridData gdProjName = new GridData(GridData.FILL_HORIZONTAL);
+ projectNameComp.setLayoutData(gdProjName);
+ projectNameComp.setLayout(new GridLayout(2, false));
+ Label lblProjectName = new Label(projectNameComp, SWT.NONE);
+ lblProjectName.setText("N&ame:");
+
+ txtProjectName = new Text(projectNameComp, SWT.BORDER);
+ txtProjectName.setLayoutData(gdFillH);
+ txtProjectName.setFocus();
+ validationListener = new ValidationListener();
+
+ txtProjectName.addModifyListener(validationListener);
+
+ Label lblProjectLocation = new Label(projectNameComp, SWT.None);
+ lblProjectLocation.setText("&Location:");
+
+ Composite locComposite = new Composite(projectNameComp, SWT.NONE);
+ GridData gd = new GridData(GridData.VERTICAL_ALIGN_END
+ | GridData.FILL_HORIZONTAL);
+ gd.horizontalIndent = 0;
+ locComposite.setLayoutData(gd);
+ GridLayout gl = new GridLayout(2, false);
+ gl.marginWidth = 0;
+ locComposite.setLayout(gl);
+
+ txtProjectLocation = new Text(locComposite, SWT.BORDER);
+ txtProjectLocation.setLayoutData(gdFillH);
+ txtProjectLocation.addModifyListener(validationListener);
+
+ Button button = new Button(locComposite, SWT.PUSH);
+ button.setText("Browse...");
+ button.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowse();
+ }
+ });
+
+ Label lblInit = new Label(projectNameComp, SWT.NONE);
+ lblInit.setText("Init Script:");
+
+ Composite initComposite = new Composite(projectNameComp, SWT.NONE);
+ gd = new GridData(GridData.VERTICAL_ALIGN_END
+ | GridData.FILL_HORIZONTAL);
+ gd.horizontalIndent = 0;
+ initComposite.setLayoutData(gd);
+ gl = new GridLayout(2, false);
+ gl.marginWidth = 0;
+ initComposite.setLayout(gl);
+
+ txtInit = new Text(initComposite, SWT.BORDER);
+ GridData gdi = new GridData(GridData.FILL_HORIZONTAL);
+ txtInit.setLayoutData(gdi);
+ txtInit.addModifyListener(validationListener);
+
+ Button btnLoadInit = new Button(initComposite, SWT.PUSH);
+ btnLoadInit.setLayoutData(gdVU);
+ btnLoadInit.setText("Choose...");
+ btnLoadInit.addSelectionListener(new FileOpenSelectionAdapter());
+
+ if (System.getenv("OEROOT") != null) {
+ txtProjectLocation.setText(System.getenv("OEROOT"));
+ }
+
+ setControl(top);
+ }
+
+ private void handleBrowse() {
+ DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.None);
+ String dir = dialog.open();
+ if (dir != null) {
+ txtProjectLocation.setText(dir);
+ }
+ }
+
+ private String getFileSegment(String initScriptPath) {
+ //return the first segment of " " seperated array, or full string if no " " exists
+ return initScriptPath.split(" ")[0];
+ }
+
+ private boolean isValidProjectName(String projectName) {
+ if (projectName.indexOf('$') > -1) {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ @Override
+ public void pageCleanup() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void pageDisplay() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void updateModel() {
+ model.put(ImportOEProjectWizard.KEY_NAME, txtProjectName.getText());
+ model.put(ImportOEProjectWizard.KEY_LOCATION, txtProjectLocation.getText());
+ model.put(ImportOEProjectWizard.KEY_INITPATH, txtInit.getText());
+ }
+
+
+ @Override
+ protected boolean validatePage() {
+ IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace().getRoot();
+
+ IStatus validate = ResourcesPlugin.getWorkspace().validateName(txtProjectName.getText(), IResource.PROJECT);
+
+ if (!validate.isOK() || !isValidProjectName(txtProjectName.getText())) {
+ setErrorMessage("Invalid project name: " + txtProjectName.getText());
+ return false;
+ }
+
+ IProject proj = wsroot.getProject(txtProjectName.getText());
+ if (proj.exists()) {
+ setErrorMessage("A project with the name " + txtProjectName.getText()
+ + " already exists");
+ return false;
+ }
+
+ if (txtProjectLocation.getText().trim().length() == 0) {
+ setErrorMessage("Set directory to an OpenEmbedded or Poky project root (OEROOT)");
+ return false;
+ }
+
+ File f = new File(txtProjectLocation.getText());
+ if (!f.exists() || !f.isDirectory()) {
+ setErrorMessage("Invalid Directory");
+ return false;
+ }
+
+ if (txtInit.getText().length() == 0) {
+ setErrorMessage("Set configuration file before bitbake is launched.");
+ return false;
+ }
+
+ File f2 = new File(getFileSegment(txtInit.getText()));
+ if (!f2.exists() || f2.isDirectory()) {
+ setErrorMessage("The configuration file is invalid.");
+ return false;
+ }
+
+ setErrorMessage(null);
+
+ return true;
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/importProject/ConsolePage.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/importProject/ConsolePage.java
new file mode 100644
index 0000000..86d5803
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/importProject/ConsolePage.java
@@ -0,0 +1,121 @@
+package org.openembedded.bc.ui.wizards.importProject;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+import org.openembedded.bc.ui.Activator;
+import org.openembedded.bc.ui.model.ProjectInfo;
+import org.openembedded.bc.ui.wizards.FiniteStateWizardPage;
+import org.openembedded.bc.ui.wizards.newproject.BBConfigurationInitializeOperation;
+
+
+/**
+ * Bitbake console view.
+ * @author kgilmer
+ *
+ */
+public class ConsolePage extends FiniteStateWizardPage {
+
+ private boolean valid = false;
+
+ public ConsolePage(Map model) {
+ super("Bitbake Console Page", model);
+ setTitle("Extracting BitBake Environment");
+ setMessage("Output of 'bitbake -e' command, for verification purposes.");
+ }
+
+ private Text txtConsole;
+
+ @Override
+ public void createControl(Composite parent) {
+ Composite top = new Composite(parent, SWT.NONE);
+ top.setLayoutData(new GridData(GridData.FILL_BOTH));
+ top.setLayout(new GridLayout());
+
+ txtConsole = new Text(top, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
+ txtConsole.setLayoutData(new GridData(GridData.FILL_BOTH));
+ txtConsole.setEditable(false);
+ txtConsole.setFont(JFaceResources.getFont(JFaceResources.TEXT_FONT));
+
+ setControl(top);
+ }
+
+ @Override
+ public void pageCleanup() {
+ Activator.resetBBSession((String) model.get(ImportOEProjectWizard.KEY_LOCATION));
+ }
+
+ @Override
+ public void pageDisplay() {
+ ProjectInfo pinfo = new ProjectInfo();
+ pinfo.setInitScriptPath((String) model.get(ImportOEProjectWizard.KEY_INITPATH));
+ pinfo.setLocation((String) model.get(ImportOEProjectWizard.KEY_LOCATION));
+ pinfo.setName((String) model.get(ImportOEProjectWizard.KEY_NAME));
+
+ try {
+ ConsoleWriter cw = new ConsoleWriter();
+ this.getContainer().run(false, false, new BBConfigurationInitializeOperation(pinfo, cw));
+ txtConsole.setText(cw.getContents());
+ } catch (Exception e) {
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
+ this.getContainer().getCurrentPage().setDescription("Failed to create project: " + e.getMessage());
+ valid = false;
+ setPageComplete(valid);
+ return;
+ }
+ valid = true;
+ model.put(ImportOEProjectWizard.KEY_PINFO, pinfo);
+ setPageComplete(valid);
+ }
+
+ @Override
+ protected void updateModel() {
+
+ }
+
+ @Override
+ protected boolean validatePage() {
+ return valid;
+ }
+
+ private class ConsoleWriter extends Writer {
+
+ private StringBuffer sb;
+
+ public ConsoleWriter() {
+ sb = new StringBuffer();
+ }
+ @Override
+ public void close() throws IOException {
+ }
+
+ public String getContents() {
+ return sb.toString();
+ }
+
+ @Override
+ public void flush() throws IOException {
+ }
+
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ txtConsole.getText().concat(new String(cbuf));
+ }
+
+ @Override
+ public void write(String str) throws IOException {
+ sb.append(str);
+ }
+
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/importProject/ImportOEProjectWizard.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/importProject/ImportOEProjectWizard.java
new file mode 100644
index 0000000..b810fe7
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/importProject/ImportOEProjectWizard.java
@@ -0,0 +1,63 @@
+package org.openembedded.bc.ui.wizards.importProject;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.IWorkbench;
+import org.openembedded.bc.ui.Activator;
+import org.openembedded.bc.ui.model.ProjectInfo;
+import org.openembedded.bc.ui.wizards.FiniteStateWizard;
+import org.openembedded.bc.ui.wizards.newproject.CreateBBCProjectOperation;
+
+
+public class ImportOEProjectWizard extends FiniteStateWizard implements IImportWizard {
+ protected final static String KEY_OEROOT = "OEROOT";
+ public static final String KEY_NAME = "NAME";
+ public static final String KEY_LOCATION = "LOCATION";
+ public static final String KEY_INITPATH = "INITPATH";
+ protected static final String KEY_PINFO = "PINFO";
+
+ private Map projectModel;
+ private IWorkbench workbench;
+ private IStructuredSelection selection;
+
+ public ImportOEProjectWizard() {
+ projectModel = new Hashtable();
+ }
+
+ public Map getModel() {
+ return projectModel;
+ }
+
+ @Override
+ public void addPages() {
+ addPage(new BBCProjectPage(projectModel));
+ addPage(new ConsolePage(projectModel));
+ }
+
+
+ public boolean performFinish() {
+ ProjectInfo pinfo = (ProjectInfo) projectModel.get(KEY_PINFO);
+ Activator.putProjInfo(pinfo.getRootPath(), pinfo);
+ try {
+ getContainer().run(false, false, new CreateBBCProjectOperation(pinfo));
+ } catch (Exception e) {
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
+ this.getContainer().getCurrentPage().setDescription("Failed to create project: " + e.getMessage());
+ return false;
+ }
+
+ return true;
+ }
+
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ this.workbench = workbench;
+ this.selection = selection;
+ this.setNeedsProgressMonitor(true);
+ setWindowTitle("BitBake Commander Project");
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/BBCProjectPage.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/BBCProjectPage.java
new file mode 100644
index 0000000..a234bca
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/BBCProjectPage.java
@@ -0,0 +1,244 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.wizards.install;
+
+import java.io.File;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.openembedded.bc.ui.wizards.FiniteStateWizardPage;
+
+
+/**
+ * Main property page for new project wizard.
+ * @author kgilmer
+ *
+ */
+public class BBCProjectPage extends FiniteStateWizardPage {
+
+ private class FileOpenSelectionAdapter extends SelectionAdapter {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ FileDialog fd = new FileDialog(PlatformUI.getWorkbench()
+ .getDisplay().getActiveShell(), SWT.OPEN);
+
+ fd.setText("Open Configuration Script");
+ fd.setFilterPath(txtProjectLocation.getText());
+
+ String selected = fd.open();
+
+ if (selected != null) {
+ txtInit.setText(selected);
+ updateModel();
+ }
+ }
+ }
+ public static final String PAGE_TITLE = "BitBake Commander Project";
+ public static final String INIT_SCRIPT_KEY = "Init Script";
+ public static final String INSTALL_DIRECTORY_KEY = "Install Directory";
+ public static final String PROJECT_NAME_KEY = "Project Name";
+
+ private Text txtProjectLocation;
+
+ private Text txtInit;
+ private ValidationListener validationListener;
+ private Text txtProjectName;
+
+ public BBCProjectPage(Map model) {
+ super(PAGE_TITLE, model);
+ setMessage("Enter information to create a BitBake Commander project.");
+ }
+
+ public void createControl(Composite parent) {
+ GridData gdFillH = new GridData(GridData.FILL_HORIZONTAL);
+ GridData gdVU = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
+
+ Composite top = new Composite(parent, SWT.NONE);
+ top.setLayoutData(new GridData(GridData.FILL_BOTH));
+ top.setLayout(new GridLayout());
+
+ Composite projectNameComp = new Composite(top, SWT.NONE);
+ GridData gdProjName = new GridData(GridData.FILL_HORIZONTAL);
+ projectNameComp.setLayoutData(gdProjName);
+ projectNameComp.setLayout(new GridLayout(2, false));
+ Label lblProjectName = new Label(projectNameComp, SWT.NONE);
+ lblProjectName.setText("N&ame:");
+
+ txtProjectName = new Text(projectNameComp, SWT.BORDER);
+ txtProjectName.setLayoutData(gdFillH);
+ txtProjectName.setFocus();
+ validationListener = new ValidationListener();
+
+ txtProjectName.addModifyListener(validationListener);
+
+ Label lblProjectLocation = new Label(projectNameComp, SWT.None);
+ lblProjectLocation.setText("&Location:");
+
+ Composite locComposite = new Composite(projectNameComp, SWT.NONE);
+ GridData gd = new GridData(GridData.VERTICAL_ALIGN_END
+ | GridData.FILL_HORIZONTAL);
+ gd.horizontalIndent = 0;
+ locComposite.setLayoutData(gd);
+ GridLayout gl = new GridLayout(2, false);
+ gl.marginWidth = 0;
+ locComposite.setLayout(gl);
+
+ txtProjectLocation = new Text(locComposite, SWT.BORDER);
+ txtProjectLocation.setLayoutData(gdFillH);
+ txtProjectLocation.addModifyListener(validationListener);
+
+ Button button = new Button(locComposite, SWT.PUSH);
+ button.setText("Browse...");
+ button.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowse();
+ }
+ });
+
+ Label lblInit = new Label(projectNameComp, SWT.NONE);
+ lblInit.setText("Init Script:");
+
+ Composite initComposite = new Composite(projectNameComp, SWT.NONE);
+ gd = new GridData(GridData.VERTICAL_ALIGN_END
+ | GridData.FILL_HORIZONTAL);
+ gd.horizontalIndent = 0;
+ initComposite.setLayoutData(gd);
+ gl = new GridLayout(2, false);
+ gl.marginWidth = 0;
+ initComposite.setLayout(gl);
+
+ txtInit = new Text(initComposite, SWT.BORDER);
+ GridData gdi = new GridData(GridData.FILL_HORIZONTAL);
+ txtInit.setLayoutData(gdi);
+ txtInit.addModifyListener(validationListener);
+
+ Button btnLoadInit = new Button(initComposite, SWT.PUSH);
+ btnLoadInit.setLayoutData(gdVU);
+ btnLoadInit.setText("Choose...");
+ btnLoadInit.addSelectionListener(new FileOpenSelectionAdapter());
+
+ if (System.getenv("OEROOT") != null) {
+ txtProjectLocation.setText(System.getenv("OEROOT"));
+ }
+
+ setControl(top);
+ }
+
+ private void handleBrowse() {
+ DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.None);
+ String dir = dialog.open();
+ if (dir != null) {
+ txtProjectLocation.setText(dir);
+ }
+ }
+
+ private String getFileSegment(String initScriptPath) {
+ //return the first segment of " " seperated array, or full string if no " " exists
+ return initScriptPath.split(" ")[0];
+ }
+
+ private boolean isValidProjectName(String projectName) {
+ if (projectName.indexOf('$') > -1) {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ @Override
+ public void pageCleanup() {
+
+ }
+
+ @Override
+ public void pageDisplay() {
+
+ }
+
+ @Override
+ protected void updateModel() {
+ Map props = (Map) model.get(OptionsPage.OPTION_MAP);
+
+ if (props == null) {
+ props = new Hashtable();
+ model.put(OptionsPage.OPTION_MAP, props);
+ }
+
+ props.put(INIT_SCRIPT_KEY, txtInit.getText());
+ props.put(INSTALL_DIRECTORY_KEY, txtProjectLocation.getText());
+ props.put(PROJECT_NAME_KEY, txtProjectName.getText());
+ }
+
+
+ @Override
+ protected boolean validatePage() {
+ IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace().getRoot();
+
+ IStatus validate = ResourcesPlugin.getWorkspace().validateName(txtProjectName.getText(), IResource.PROJECT);
+
+ if (!validate.isOK() || !isValidProjectName(txtProjectName.getText())) {
+ setErrorMessage("Invalid project name: " + txtProjectName.getText());
+ return false;
+ }
+
+ IProject proj = wsroot.getProject(txtProjectName.getText());
+ if (proj.exists()) {
+ setErrorMessage("A project with the name " + txtProjectName.getText()
+ + " already exists");
+ return false;
+ }
+
+ if (txtProjectLocation.getText().trim().length() == 0) {
+ setErrorMessage("Set directory to an OpenEmbedded or Poky project root (OEROOT)");
+ return false;
+ }
+
+ File f = new File(txtProjectLocation.getText());
+ if (!f.exists() || !f.isDirectory()) {
+ setErrorMessage("Invalid Directory");
+ return false;
+ }
+
+ if (txtInit.getText().length() == 0) {
+ setErrorMessage("Set configuration file before bitbake is launched.");
+ return false;
+ }
+
+ File f2 = new File(getFileSegment(txtInit.getText()));
+ if (!f2.exists() || f2.isDirectory()) {
+ setErrorMessage("The configuration file is invalid.");
+ return false;
+ }
+
+ setErrorMessage(null);
+
+ return true;
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/BitbakePage.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/BitbakePage.java
new file mode 100644
index 0000000..09e58b9
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/BitbakePage.java
@@ -0,0 +1,154 @@
+package org.openembedded.bc.ui.wizards.install;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+
+import org.eclipse.core.commands.ParameterValueConversionException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+import org.openembedded.bc.ui.Activator;
+import org.openembedded.bc.ui.model.ProjectInfo;
+import org.openembedded.bc.ui.wizards.FiniteStateWizard;
+import org.openembedded.bc.ui.wizards.FiniteStateWizardPage;
+import org.openembedded.bc.ui.wizards.importProject.ImportOEProjectWizard;
+import org.openembedded.bc.ui.wizards.newproject.BBConfigurationInitializeOperation;
+
+
+/**
+ * Bitbake console view.
+ *
+ * @author kgilmer
+ *
+ */
+public class BitbakePage extends FiniteStateWizardPage {
+
+ private boolean valid = false;
+
+ public BitbakePage(Map model) {
+ super("Bitbake Console Page", model);
+ setTitle("Extracting BitBake Environment");
+ setMessage("Output of 'bitbake -e' command");
+ }
+
+ private Text txtConsole;
+
+ @Override
+ public void createControl(Composite parent) {
+ Composite top = new Composite(parent, SWT.NONE);
+ top.setLayoutData(new GridData(GridData.FILL_BOTH));
+ top.setLayout(new GridLayout());
+
+ txtConsole = new Text(top, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
+ txtConsole.setLayoutData(new GridData(GridData.FILL_BOTH));
+ txtConsole.setEditable(false);
+ txtConsole.setFont(JFaceResources.getFont(JFaceResources.TEXT_FONT));
+
+ setControl(top);
+ }
+
+ @Override
+ public void pageCleanup() {
+ Activator.resetBBSession((String) model.get(ImportOEProjectWizard.KEY_LOCATION));
+ }
+
+ @Override
+ public void pageDisplay() {
+ Map props = (Map) model.get(OptionsPage.OPTION_MAP);
+
+ try {
+ String initPath = InstallJob.substitute((String) props.get(BBCProjectPage.INIT_SCRIPT_KEY), model);
+ String location = InstallJob.substitute((String) props.get(BBCProjectPage.INSTALL_DIRECTORY_KEY), model);
+ String name = null;
+ if (props.containsKey(BBCProjectPage.PROJECT_NAME_KEY)) {
+ name = InstallJob.substitute((String) props.get(BBCProjectPage.PROJECT_NAME_KEY), model);
+ } else {
+ name = parseName((String) props.get("Install Directory"));
+ }
+
+ ProjectInfo pinfo = new ProjectInfo();
+ pinfo.setInitScriptPath(initPath);
+ pinfo.setLocation(location);
+ pinfo.setName(name);
+
+ ConsoleWriter cw = new ConsoleWriter();
+ this.getContainer().run(false, false, new BBConfigurationInitializeOperation(pinfo, cw));
+ txtConsole.setText(cw.getContents());
+ valid = true;
+ model.put(InstallWizard.KEY_PINFO, pinfo);
+ } catch (InvocationTargetException e) {
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, e.getTargetException().getMessage(), e));
+ setErrorMessage("Failed to create project.");
+ txtConsole.setText(e.getTargetException().getMessage());
+ valid = false;
+ setPageComplete(valid);
+ return;
+ } catch (InterruptedException e) {
+ } catch (ParameterValueConversionException e) {
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
+ setErrorMessage("Failed to create project: " + e.getMessage());
+ valid = false;
+ setPageComplete(valid);
+ return;
+ }
+
+ setPageComplete(valid);
+ ((FiniteStateWizard) this.getWizard()).setCanFinish(true);
+ }
+
+ private String parseName(String name) {
+ String[] e = name.split(File.separator);
+ return e[e.length - 1];
+ }
+
+ @Override
+ protected void updateModel() {
+
+ }
+
+ @Override
+ protected boolean validatePage() {
+ return valid;
+ }
+
+ private class ConsoleWriter extends Writer {
+
+ private StringBuffer sb;
+
+ public ConsoleWriter() {
+ sb = new StringBuffer();
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+
+ public String getContents() {
+ return sb.toString();
+ }
+
+ @Override
+ public void flush() throws IOException {
+ }
+
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ txtConsole.getText().concat(new String(cbuf));
+ }
+
+ @Override
+ public void write(String str) throws IOException {
+ sb.append(str);
+ }
+
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/Flavor.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/Flavor.java
new file mode 100644
index 0000000..7462047
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/Flavor.java
@@ -0,0 +1,50 @@
+/**
+ *
+ */
+package org.openembedded.bc.ui.wizards.install;
+
+import java.io.IOException;
+
+// # Flavor Label (shows in UI)| description text| image URL| script URL
+
+/**
+ * Data class for flavor definition.
+ * @author kgilmer
+ *
+ */
+public class Flavor {
+ private final String label;
+ private final String description;
+ private final String imageURL;
+ private final String scriptURL;
+
+ public Flavor(String line) throws IOException {
+ String [] e = line.split("\\|");
+
+ if (e.length != 4) {
+ throw new IOException("Invalid flavor line: " + line);
+ }
+
+ label = e[0];
+ description = e[1];
+ imageURL = e[2];
+ scriptURL = e[3];
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getImageURL() {
+ return imageURL;
+ }
+
+ public String getScriptURL() {
+ return scriptURL;
+ }
+
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/FlavorPage.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/FlavorPage.java
new file mode 100644
index 0000000..db75c98
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/FlavorPage.java
@@ -0,0 +1,182 @@
+package org.openembedded.bc.ui.wizards.install;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TableColumn;
+import org.openembedded.bc.ui.Activator;
+import org.openembedded.bc.ui.wizards.FiniteStateWizardPage;
+
+
+/**
+ * Select which flavor of OE is to be installed.
+ *
+ * @author kgilmer
+ *
+ */
+public class FlavorPage extends FiniteStateWizardPage {
+ protected static final String OE_FLAVOR = "FLAVOR";
+ protected static final String OE_FLAVOR_TITLE = "OE_FLAVOR_TITLE";
+ protected static final String INSTALL_SCRIPT = "INSTALL_SCRIPT";
+
+ private boolean controlsCreated;
+ private TableViewer flavorList;
+
+ protected FlavorPage(Map model) {
+ super("Flavor", model);
+ setTitle("Select OpenEmbedded Flavor");
+ setMessage("Select the flavor of OpenEmbedded you wish to install...");
+ }
+
+
+ public void createControl(Composite parent) {
+ Composite top = new Composite(parent, SWT.None);
+ top.setLayout(new GridLayout());
+ top.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ flavorList = new TableViewer(top, SWT.BORDER);
+ flavorList.setContentProvider(new FlavorContentProvider());
+ flavorList.setLabelProvider(new FlavorLabelProvider());
+ flavorList.getTable().setLayoutData(new GridData(GridData.FILL_BOTH));
+ flavorList.addSelectionChangedListener(new ValidationListener());
+
+ TableColumn tc = new TableColumn(flavorList.getTable(), SWT.LEFT);
+ tc.setText("Image");
+ tc.setWidth(128);
+
+ tc = new TableColumn(flavorList.getTable(), SWT.LEFT);
+ tc.setText("Title");
+ tc.setWidth(300);
+ /*
+ tc = new TableColumn(flavorList.getTable(), SWT.LEFT);
+ tc.setText("Description");
+ tc.setWidth(300);*/
+
+
+ setControl(top);
+ }
+
+
+ public void pageCleanup() {
+
+ }
+
+
+ public void pageDisplay() {
+ getContainer().getShell().setSize(getContainer().getShell().getSize().x, 600);
+ if (!controlsCreated) {
+ try {
+ flavorList.setInput(InstallScriptHelper.getFlavors("scripts/install_flavors.txt"));
+ controlsCreated = true;
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+
+ protected void updateModel() {
+ Flavor f = (Flavor) ((IStructuredSelection) flavorList.getSelection()).getFirstElement();
+ model.put(OE_FLAVOR, f);
+ model.put(OE_FLAVOR_TITLE, f.getLabel());
+ try {
+ model.put(INSTALL_SCRIPT, InstallScriptHelper.loadFile(f.getScriptURL()));
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+
+ protected boolean validatePage() {
+ return flavorList.getSelection() != null;
+ }
+
+ private class FlavorContentProvider implements IStructuredContentProvider {
+
+
+ public Object[] getElements(Object arg0) {
+ return ((List) arg0).toArray();
+ }
+
+
+ public void dispose() {
+ }
+
+
+ public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
+ }
+
+ }
+
+ private class FlavorLabelProvider implements ITableLabelProvider {
+ private Map imageMap = new Hashtable();
+
+
+ public Image getColumnImage(Object arg0, int arg1) {
+ Flavor f = (Flavor) arg0;
+ Image i = null;
+
+ if (arg1 == 0) {
+ i = (Image) imageMap.get(f);
+ if (i == null) {
+ i = Activator.getImageDescriptor(f.getImageURL()).createImage();
+ imageMap.put(f, i);
+ }
+ }
+
+ return i;
+ }
+
+
+ public String getColumnText(Object arg0, int arg1) {
+ Flavor f = (Flavor) arg0;
+ if (arg1 == 1) {
+ return f.getLabel();
+ } else if (arg1 == 2) {
+ return f.getDescription();
+ }
+
+ return null;
+ }
+
+
+ public void addListener(ILabelProviderListener arg0) {
+
+ }
+
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+
+ }
+
+
+ public boolean isLabelProperty(Object arg0, String arg1) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+
+ public void removeListener(ILabelProviderListener arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallJob.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallJob.java
new file mode 100644
index 0000000..5b2b0a7
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallJob.java
@@ -0,0 +1,170 @@
+/**
+ *
+ */
+package org.openembedded.bc.ui.wizards.install;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.commands.ParameterValueConversionException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.openembedded.bc.bitbake.ICommandResponseHandler;
+import org.openembedded.bc.bitbake.ShellSession;
+import org.openembedded.bc.ui.Activator;
+
+
+class InstallJob extends Job {
+
+ private final Map mod;
+ private UICommandResponseHandler cmdOut;
+ private boolean errorOccurred = false;
+ private String errorMessage = "";
+
+ public InstallJob(Map model, ProgressPage progressPage) {
+ super("Install OpenEmbedded");
+ mod = model;
+ cmdOut = new UICommandResponseHandler(progressPage);
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ BufferedReader reader = new BufferedReader(new StringReader(
+ (String) mod.get(FlavorPage.INSTALL_SCRIPT)));
+ String line = null;
+ Map vars = loadVariables();
+
+ try {
+ ShellSession shell = new ShellSession(ShellSession.SHELL_TYPE_BASH,
+ null, null, null);
+ while ((line = reader.readLine()) != null && !errorOccurred) {
+ line = line.trim();
+ if (line.length() > 0 && !line.startsWith("#")) {
+ line = substitute(line, vars);
+ cmdOut.printCmd(line);
+ System.out.println("Running: " + line);
+ shell.execute(line, cmdOut);
+ } else if (line.startsWith("#")) {
+ cmdOut.printDialog(line.substring(1).trim());
+ }
+ }
+
+ if (errorOccurred) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ "Failed to install OpenEmbedded: " + errorMessage);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ "Failed to install OpenEmbedded", e);
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ private Map loadVariables() {
+ return (Map) mod.get(OptionsPage.OPTION_MAP);
+ }
+
+ /**
+ * Return a string with variable substitutions in place.
+ *
+ * @param expression
+ * @return Input string with any substitutions from this file.
+ * @throws ParameterValueConversionException
+ */
+ public static String substitute(String expression, Map mo)
+ throws ParameterValueConversionException {
+
+ List vars;
+ int literals = 0;
+
+ while ((vars = parseVars(expression)).size() > literals) {
+ for (Iterator i = vars.iterator(); i.hasNext();) {
+ String varName = (String) i.next();
+ String varToken = "${" + varName + "}";
+
+ if (mo.containsKey(varName)) {
+ expression = expression.replace(varToken, (String) mo
+ .get(varName));
+ } else if (System.getProperty(varName) != null) {
+ expression = expression.replace(varToken, System
+ .getProperty(varName));
+ } else if (varName.toUpperCase().equals("HOME")) {
+ expression = expression.replace(varToken, System
+ .getProperty("user.home"));
+ } else {
+ //throw new ParameterValueConversionException(
+ // "Unable to match parameter: " + expression);
+ // Leave the value, treat as a literal.
+ literals++;
+ }
+ }
+ }
+
+ return expression;
+ }
+
+ /**
+ *
+ * @param line
+ * @return A list of variables in $[variable name] format.
+ */
+ public static List parseVars(String line) {
+ List l = new ArrayList();
+
+ int i = 0;
+
+ while ((i = line.indexOf("${", i)) > -1) {
+ int i2 = line.indexOf("}", i);
+
+ String var = line.subSequence(i + 2, i2).toString().trim();
+
+ if (var.length() > 0 && !l.contains(var)) {
+ l.add(var);
+ }
+ i++;
+ }
+
+ return l;
+ }
+
+ private class UICommandResponseHandler implements ICommandResponseHandler {
+
+ private final ProgressPage progressPage;
+
+ public UICommandResponseHandler(ProgressPage progressPage) {
+ this.progressPage = progressPage;
+ }
+
+ public void printDialog(String msg) {
+ progressPage.printDialog(msg);
+ }
+
+ public void response(String line, boolean isError) {
+ if (isError) {
+ progressPage.printLine(line, ProgressPage.PRINT_ERR);
+ //errorOccurred = true;
+ //errorMessage = line;
+ } else {
+ progressPage.printLine(line, ProgressPage.PRINT_OUT);
+ if (line.endsWith("!!OTEWIZARDSTOP")) {
+ errorOccurred = true;
+ errorMessage = line;
+ }
+ }
+ }
+
+ public void printCmd(String cmd) {
+ progressPage.printLine(cmd, ProgressPage.PRINT_CMD);
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallParameter.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallParameter.java
new file mode 100644
index 0000000..517a0fe
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallParameter.java
@@ -0,0 +1,99 @@
+/**
+ *
+ */
+package org.openembedded.bc.ui.wizards.install;
+
+class InstallParameter {
+ public static final int DT_TEXT = 1;
+ public static final int DT_COMBO = 2;
+ public static final int DT_LIST = 3;
+ public static final int DT_NUMBER = 4;
+ public static final int DT_DIRECTORY = 5;
+ public static final int DT_FILE = 6;
+ public static final int DT_CHECKBOX = 7;
+
+ private boolean valid = false;
+ private int type;
+ private String label;
+ private boolean required;
+ private String data;
+ private String helpURL;
+ private String helpText;
+
+ public int getType() {
+ return type;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public boolean isRequired() {
+ return required;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public String getHelpURL() {
+ return helpURL;
+ }
+
+ public String getHelpText() {
+ return helpText;
+ }
+
+ public InstallParameter(String var) {
+ // {|Datatype|Label|UnRequired|Data|Help|}
+ // {|T|Distribution|R|angstrom-2008.1|http://wiki.openembedded.net/index.php/Getting_started#Create_local_configuration|}
+
+ String[] elems = var.split("\\|");
+
+ if (elems.length == 5 || elems.length == 6) {
+ if (elems[0].equals("T")) {
+ type = DT_TEXT;
+ } else if (elems[0].equals("D")) {
+ type = DT_DIRECTORY;
+ } else if (elems[0].equals("F")) {
+ type = DT_FILE;
+ } else if (elems[0].equals("C")) {
+ type = DT_COMBO;
+ } else if (elems[0].equals("B")) {
+ type = DT_CHECKBOX;
+ } else {
+ throw new RuntimeException("Invalid field format: " + var);
+ }
+
+ label = elems[1];
+
+ if (elems[2].equals("R")) {
+ required = true;
+ } else if (elems[2].equals("U")) {
+ required = false;
+ } else {
+ throw new RuntimeException("Invalid field format: " + var);
+ }
+
+ data = elems[3].trim();
+
+ if (elems[4].trim().length() > 0) {
+ helpURL = elems[4].trim();
+ }
+
+ if (elems.length == 6) {
+ helpText = elems[5];
+ }
+
+ valid = true;
+ } else {
+ throw new RuntimeException("Invalid field format: " + var);
+ }
+ }
+
+ public boolean isValid() {
+
+ return valid;
+ }
+
+} \ No newline at end of file
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallScriptHelper.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallScriptHelper.java
new file mode 100644
index 0000000..5225929
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallScriptHelper.java
@@ -0,0 +1,52 @@
+package org.openembedded.bc.ui.wizards.install;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openembedded.bc.ui.Activator;
+
+
+/**
+ * Helper for loading install scripts.
+ * @author kgilmer
+ *
+ */
+public class InstallScriptHelper {
+
+ public static List getFlavors(String filePath) throws IOException {
+ InputStream is = Activator.getDefault().getBundle().getResource(filePath).openStream();
+ List list = new ArrayList();
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
+ String line = null;
+
+ while ((line = br.readLine()) != null) {
+ line = line.trim();
+
+ if (line.length() > 0 && !line.startsWith("#")) {
+ list.add(new Flavor(line));
+ }
+ }
+
+ return list;
+ }
+
+ public static String loadFile(String fileName) throws IOException {
+ InputStream is = Activator.getDefault().getBundle().getResource(fileName).openStream();
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
+ String line = null;
+ StringBuffer sb = new StringBuffer();
+
+ while ((line = br.readLine()) != null) {
+ sb.append(line);
+ sb.append('\n');
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallWizard.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallWizard.java
new file mode 100644
index 0000000..2297939
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/InstallWizard.java
@@ -0,0 +1,105 @@
+package org.openembedded.bc.ui.wizards.install;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWizard;
+import org.openembedded.bc.ui.Activator;
+import org.openembedded.bc.ui.model.ProjectInfo;
+import org.openembedded.bc.ui.wizards.FiniteStateWizard;
+import org.openembedded.bc.ui.wizards.newproject.CreateBBCProjectOperation;
+
+
+/**
+ * A wizard for installing a fresh copy of an OE system.
+ *
+ * @author kgilmer
+ *
+ */
+public class InstallWizard extends FiniteStateWizard implements IWorkbenchWizard {
+
+ static final String KEY_PINFO = "KEY_PINFO";
+ private Map model;
+
+ public InstallWizard() {
+ this.model = new Hashtable();
+ setWindowTitle("BitBake Commander");
+ setNeedsProgressMonitor(false);
+ setDefaultPageImageDescriptor(Activator.getImageDescriptor("icons/OE_logo_96.png"));
+ }
+
+ public InstallWizard(IStructuredSelection selection) {
+ model = new Hashtable();
+ }
+
+ /*@Override
+ public IWizardPage getNextPage(IWizardPage page) {
+ if (page instanceof WelcomePage) {
+ if (model.containsKey(WelcomePage.ACTION_USE)) {
+ return bbcProjectPage;
+ }
+ } else if (page instanceof ProgressPage) {
+ return bitbakePage;
+ }
+
+ if (super.getNextPage(page) != null) {
+ System.out.println("next page: " + super.getNextPage(page).getClass().getName());
+ } else {
+ System.out.println("end page");
+ }
+
+ return super.getNextPage(page);
+ }
+
+ @Override
+ public boolean canFinish() {
+ System.out.println("can finish: " + super.canFinish());
+ return super.canFinish();
+ }
+*/
+ @Override
+ public void addPages() {
+ // flavorPage = new FlavorPage(model);
+ // bitbakePage = new BitbakePage(model);
+ // bbcProjectPage = new BBCProjectPage(model);
+ //addPage(new WelcomePage(model));
+ addPage(new FlavorPage(model));
+ addPage(new OptionsPage(model));
+ addPage(new ProgressPage(model));
+ //addPage(bbcProjectPage);
+ addPage(new BitbakePage(model));
+ }
+
+ @Override
+ public Map getModel() {
+ return model;
+ }
+
+ @Override
+ public boolean performFinish() {
+ ProjectInfo pinfo = (ProjectInfo) model.get(KEY_PINFO);
+ Activator.putProjInfo(pinfo.getRootPath(), pinfo);
+ try {
+ getContainer().run(false, false, new CreateBBCProjectOperation(pinfo));
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
+ this.getContainer().getCurrentPage().setTitle("Failed to create project: " + e.getTargetException().getMessage());
+ return false;
+ } catch (Exception e) {
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
+ this.getContainer().getCurrentPage().setTitle("Failed to create project: " + e.getMessage());
+ return false;
+ }
+
+ return true;
+ }
+
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/OptionsPage.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/OptionsPage.java
new file mode 100644
index 0000000..97115f1
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/OptionsPage.java
@@ -0,0 +1,313 @@
+package org.openembedded.bc.ui.wizards.install;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.openembedded.bc.ui.wizards.FiniteStateWizardPage;
+
+
+/**
+ * Select which flavor of OE is to be installed.
+ *
+ * @author kgilmer
+ *
+ */
+public class OptionsPage extends FiniteStateWizardPage {
+
+ private Map vars;
+ private Composite c1;
+ private Composite top;
+ protected static final String OPTION_MAP = "OPTION_MAP";
+ private static final String DEFAULT_MESSAGE = "Enter these parameters to install.";
+ private List controlList;
+ private boolean controlsCreated = false;
+
+ protected OptionsPage(Map model) {
+ super("Options", model);
+ setTitle("Installing...");
+ setMessage(DEFAULT_MESSAGE);
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ top = new Composite(parent, SWT.None);
+ top.setLayout(new GridLayout());
+ top.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ c1 = new Composite(top, SWT.None);
+ c1.setLayout(new GridLayout(3, false));
+ c1.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ setControl(top);
+ }
+
+ private void createControls(Composite comp, Map v, List cl) {
+ ValidationListener listener = new ValidationListener();
+
+ for (Iterator i = v.keySet().iterator(); i.hasNext();) {
+
+ String label = (String) i.next();
+ final InstallParameter ip = (InstallParameter) v.get(label);
+
+ if (ip.getType() != InstallParameter.DT_CHECKBOX) {
+ Label title = new Label(comp, SWT.None);
+ title.setText(ip.getLabel() + ": ");
+ if (ip.getHelpText() != null) {
+ title.setToolTipText(ip.getHelpText());
+ }
+ } else {
+ //If we are creating checkbox, layout differently.
+ new Label(comp, SWT.None);
+ }
+
+ Control toolTipControl = null;
+ switch (ip.getType()) {
+ case InstallParameter.DT_TEXT:
+ Text field = new Text(comp, SWT.BORDER);
+ field.setData(ip);
+ field.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ field.addModifyListener(listener);
+ field.setText(ip.getData());
+ cl.add(field);
+ toolTipControl = field;
+ break;
+ case InstallParameter.DT_DIRECTORY:
+ Composite locComposite = new Composite(comp, SWT.NONE);
+ GridData gd = new GridData(GridData.VERTICAL_ALIGN_END | GridData.FILL_HORIZONTAL);
+ gd.horizontalIndent = 0;
+ locComposite.setLayoutData(gd);
+ GridLayout gl = new GridLayout(2, false);
+ gl.marginWidth = 0;
+ locComposite.setLayout(gl);
+
+ final Text location = new Text(locComposite, SWT.BORDER);
+ location.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ location.setText(ip.getData());
+ location.addModifyListener(listener);
+ location.setData(ip);
+ toolTipControl = location;
+ cl.add(location);
+
+ Button button = new Button(locComposite, SWT.PUSH);
+ button.setText("...");
+ button.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ DirectoryDialog fd = new DirectoryDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), SWT.OPEN);
+
+ fd.setText(ip.getLabel());
+
+ String selected = fd.open();
+
+ if (selected != null) {
+ location.setText(selected);
+ // updateModel();
+ }
+ }
+ });
+ break;
+ case InstallParameter.DT_FILE:
+ Composite fileComposite = new Composite(comp, SWT.NONE);
+ gd = new GridData(GridData.VERTICAL_ALIGN_END | GridData.FILL_HORIZONTAL);
+ gd.horizontalIndent = 0;
+ fileComposite.setLayoutData(gd);
+ gl = new GridLayout(2, false);
+ gl.marginWidth = 0;
+ fileComposite.setLayout(gl);
+
+ final Text fileLocation = new Text(fileComposite, SWT.BORDER);
+ fileLocation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ fileLocation.setText(ip.getData());
+ fileLocation.addModifyListener(listener);
+ fileLocation.setData(ip);
+ toolTipControl = fileLocation;
+ cl.add(fileLocation);
+
+ button = new Button(fileComposite, SWT.PUSH);
+ button.setText("...");
+ button.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ FileDialog fd = new FileDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), SWT.OPEN);
+
+ fd.setText(ip.getLabel());
+
+ String selected = fd.open();
+
+ if (selected != null) {
+ fileLocation.setText(selected);
+ // updateModel();
+ }
+ }
+ });
+ break;
+ case InstallParameter.DT_COMBO:
+ Combo cfield = new Combo(comp, SWT.READ_ONLY);
+ cfield.setData(ip);
+ // cfield.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ cfield.addModifyListener(listener);
+ cfield.setItems(ip.getData().split(","));
+ cfield.setText(ip.getData().split(",")[0]);
+ toolTipControl = cfield;
+ cl.add(cfield);
+ break;
+ case InstallParameter.DT_CHECKBOX:
+ Button bfield = new Button(comp, SWT.CHECK);
+ bfield.setData(ip);
+ bfield.setText(ip.getLabel());
+ // bfield.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ bfield.addSelectionListener(listener);
+ if (ip.getData().trim().toUpperCase().equals("TRUE")) {
+ bfield.setSelection(true);
+ }
+ toolTipControl = bfield;
+ cl.add(bfield);
+ break;
+ default:
+ throw new RuntimeException("Unknown or unimplemented field: " + ip.getType());
+ }
+
+ // Setup tool tips and wizard help.
+ if (toolTipControl != null) {
+ if (ip.getHelpText() != null) {
+ toolTipControl.setToolTipText(ip.getHelpText());
+ toolTipControl.addFocusListener(new FocusListener() {
+
+ public void focusLost(FocusEvent e) {
+ }
+
+ public void focusGained(FocusEvent e) {
+ setMessage(ip.getHelpText());
+ }
+ });
+ } else {
+ toolTipControl.addFocusListener(new FocusListener() {
+
+ public void focusLost(FocusEvent e) {
+ }
+
+ public void focusGained(FocusEvent e) {
+ setMessage(DEFAULT_MESSAGE);
+ ;
+ }
+ });
+ }
+ }
+
+ // Create a hyperlink to help content if exists, or invisible label if not.
+ if (ip.getHelpURL() != null) {
+ Link l = new Link(comp, SWT.None);
+ l.setText("<a>Help...</a>");
+ l.addSelectionListener(new SelectionListener() {
+
+ public void widgetSelected(SelectionEvent e) {
+ org.eclipse.swt.program.Program.launch(ip.getHelpURL());
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // TODO Auto-generated method stub
+
+ }
+ });
+ } else {
+ new Label(comp, SWT.None);
+ }
+ }
+ }
+
+ @Override
+ public void pageCleanup() {
+
+ }
+
+ @Override
+ public void pageDisplay() {
+ if (!controlsCreated) {
+ controlList = new ArrayList();
+
+ vars = parseVars((String) model.get(FlavorPage.INSTALL_SCRIPT));
+
+ createControls(c1, vars, controlList);
+ c1.layout();
+
+ controlsCreated = true;
+ setTitle(((String) model.get(FlavorPage.OE_FLAVOR_TITLE)).trim() + " Options");
+ }
+ updateModel();
+ }
+
+ public static Map parseVars(String line) {
+ Map l = new LinkedHashMap();
+
+ int i = 0;
+
+ while ((i = line.indexOf("{|", i)) > -1) {
+ int i2 = line.indexOf("|}", i);
+
+ String var = line.subSequence(i + 2, i2).toString().trim();
+
+ if (var.length() > 0) {
+ InstallParameter ip = new InstallParameter(var + " ");
+
+ if (ip.isValid() && !l.containsKey(ip.getLabel())) {
+ l.put(ip.getLabel(), ip);
+ }
+ }
+ i++;
+ }
+
+ return l;
+ }
+
+ @Override
+ protected void updateModel() {
+ Map m = new Hashtable();
+
+ for (Iterator i = controlList.iterator(); i.hasNext();) {
+ Control t = (Control) i.next();
+ String val = null;
+ InstallParameter ip = (InstallParameter) t.getData();
+
+ if (t instanceof Text) {
+ val = ((Text) t).getText();
+ } else if (t instanceof Combo) {
+ val = ((Combo) t).getText();
+ } else if (t instanceof Button) {
+ val = Boolean.toString(((Button) t).getSelection());
+ } else {
+ throw new RuntimeException("Unknown control type: " + t.getClass().getName());
+ }
+
+ m.put(ip.getLabel(), val);
+ }
+ model.put(OPTION_MAP, m);
+ }
+
+ @Override
+ protected boolean validatePage() {
+ return true;
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/ProgressPage.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/ProgressPage.java
new file mode 100644
index 0000000..6a54a6b
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/ProgressPage.java
@@ -0,0 +1,191 @@
+package org.openembedded.bc.ui.wizards.install;
+
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Map;
+
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.IJobChangeListener;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ProgressBar;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.openembedded.bc.ui.wizards.FiniteStateWizardPage;
+
+
+/**
+ * Select which flavor of OE is to be installed.
+ * @author kgilmer
+ *
+ */
+public class ProgressPage extends FiniteStateWizardPage {
+
+ private static final String STARTED_INSTALL = "STARTED_INSTALL";
+ private Text txtConsole;
+ private StringBuffer consoleBuffer;
+ private ProgressBar pbProgress;
+ private String lastError;
+
+ protected static final int PRINT_CMD = 1;
+ protected static final int PRINT_OUT = 2;
+ protected static final int PRINT_ERR = 3;
+
+ protected ProgressPage(Map model) {
+ super("Progress", model);
+ setTitle("Installing OpenEmbedded");
+ setMessage("");
+ }
+
+ public void createControl(Composite parent) {
+ Composite top = new Composite(parent, SWT.None);
+ top.setLayout(new GridLayout());
+ top.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ txtConsole = new Text(top, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+ txtConsole.setLayoutData(new GridData(GridData.FILL_BOTH));
+ txtConsole.setFont(JFaceResources.getFont(JFaceResources.TEXT_FONT));
+ txtConsole.setEditable(false);
+
+ Label s = new Label(top, SWT.SEPARATOR | SWT.HORIZONTAL);
+ s.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ pbProgress = new ProgressBar(top, SWT.HORIZONTAL | SWT.BORDER);
+
+ setControl(top);
+ }
+
+ protected void printLine(String line, final int type) {
+ if (consoleBuffer == null) {
+ consoleBuffer = new StringBuffer();
+ }
+
+ if (type == PRINT_CMD) {
+ consoleBuffer.append("$ ");
+ } else if (type == PRINT_ERR) {
+ consoleBuffer.append("ERROR: ");
+ lastError = line;
+ }
+
+ consoleBuffer.append(line);
+ consoleBuffer.append('\n');
+
+ PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
+
+
+ public void run() {
+ txtConsole.setText(consoleBuffer.toString());
+ txtConsole.setSelection(txtConsole.getText().length() - 1);
+
+ if (type == PRINT_CMD) {
+ pbProgress.setSelection(pbProgress.getSelection() + 1);
+ }
+ }
+
+ });
+ }
+
+ public void pageCleanup() {
+
+ }
+
+ public void pageDisplay() {
+ if (!model.containsKey(STARTED_INSTALL)) {
+ model.put(STARTED_INSTALL, new Boolean(true));
+
+ try {
+ pbProgress.setMaximum(getLineCount((String) model.get(FlavorPage.INSTALL_SCRIPT)));
+ } catch (IOException e) {
+ //TODO add logging here.
+ e.printStackTrace();
+ return;
+ }
+
+ executeInstall();
+ }
+ }
+
+ private int getLineCount(String str) throws IOException {
+ int count = 0;
+
+ BufferedReader br = new BufferedReader(new StringReader(str));
+
+ while (br.readLine() != null) {
+ count++;
+ }
+
+ return count;
+ }
+
+ private void executeInstall() {
+ InstallJob j = new InstallJob(model, this);
+ j.addJobChangeListener(new IJobChangeListener() {
+
+ public void aboutToRun(IJobChangeEvent event) {
+ }
+
+
+ public void awake(IJobChangeEvent event) {
+ }
+
+
+ public void done(final IJobChangeEvent event) {
+ PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
+
+
+ public void run() {
+ if (event.getResult().isOK()) {
+ setMessage("Installation complete, next is to load into workspace.");
+ pbProgress.setVisible(false);
+ setPageComplete(true);
+ } else {
+ setErrorMessage("An error occurred while installing OpenEmbedded:\n" + lastError);
+ }
+ }
+
+ });
+ }
+
+ public void running(IJobChangeEvent event) {
+ }
+
+
+ public void scheduled(IJobChangeEvent event) {
+ }
+
+
+ public void sleeping(IJobChangeEvent event) {
+ }
+
+ });
+ setMessage("Installing OpenEmbedded...");
+ j.schedule();
+ }
+
+
+ protected void updateModel() {
+ }
+
+
+ protected boolean validatePage() {
+
+ return true;
+ }
+
+ public void printDialog(final String msg) {
+ PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
+
+
+ public void run() {
+ setMessage(msg);
+ }
+ });
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/WelcomePage.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/WelcomePage.java
new file mode 100644
index 0000000..cbb4317
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/install/WelcomePage.java
@@ -0,0 +1,96 @@
+package org.openembedded.bc.ui.wizards.install;
+
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.openembedded.bc.ui.wizards.FiniteStateWizardPage;
+
+
+public class WelcomePage extends FiniteStateWizardPage {
+
+ public static final String ACTION_INSTALL = "ACTION_INSTALL";
+ public static final String ACTION_USE = "ACTION_USE";
+ private Button installButton;
+ private Button useButton;
+
+ protected WelcomePage(Map model) {
+ super("Introduction", model);
+ setTitle("Select Project Type");
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ Composite top = new Composite(parent, SWT.None);
+ top.setLayout(new GridLayout());
+ top.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ ValidationListener listener = new ValidationListener();
+
+ installButton = new Button(top, SWT.RADIO | SWT.WRAP);
+ installButton.setText("Install a flavor of OpenEmbedded on your computer.");
+ Composite lc = new Composite(top, SWT.None);
+ lc.setLayout(new GridLayout(2, false));
+ lc.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ Label spacer = new Label(lc, SWT.None);
+ spacer.setText(" ");
+ Label installLabel = new Label(lc, SWT.WRAP);
+ installLabel.setText(
+ "This will install a flavor of OpenEmbedded in your Eclipse workspace. It is the " +
+ "recommended option for new projects in Eclipse."
+ );
+ installLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ installButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ installButton.addSelectionListener(listener);
+
+ useButton = new Button(top, SWT.RADIO | SWT.WRAP);
+ useButton.setText("Use an existing local copy of OpenEmbedded.");
+ lc = new Composite(top, SWT.None);
+ lc.setLayout(new GridLayout(2, false));
+ lc.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ spacer = new Label(lc, SWT.None);
+ spacer.setText(" ");
+ installLabel = new Label(lc, SWT.WRAP);
+ installLabel.setText(
+ "A working install " +
+ "of a flavor of OpenEmbedded is required. An init script will need to be selected to initialize " +
+ "the environment.");
+ installLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ useButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ useButton.addSelectionListener(listener);
+
+ setControl(top);
+ }
+
+ @Override
+ public void pageCleanup() {
+ }
+
+ @Override
+ public void pageDisplay() {
+ setMessage("Choose to install a new instance or an existing one.");
+ }
+
+ @Override
+ protected void updateModel() {
+ model.remove(ACTION_INSTALL);
+ model.remove(ACTION_USE);
+
+ if (installButton.getSelection()) {
+ model.put(ACTION_INSTALL, ACTION_INSTALL);
+ } else if (useButton.getSelection()) {
+ model.put(ACTION_USE, ACTION_USE);
+ }
+ }
+
+ @Override
+ protected boolean validatePage() {
+ return useButton.getSelection() || installButton.getSelection();
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/newproject/BBConfigurationInitializeOperation.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/newproject/BBConfigurationInitializeOperation.java
new file mode 100644
index 0000000..ae3f90c
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/newproject/BBConfigurationInitializeOperation.java
@@ -0,0 +1,59 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.wizards.newproject;
+
+import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.openembedded.bc.bitbake.BBSession;
+import org.openembedded.bc.bitbake.ProjectInfoHelper;
+import org.openembedded.bc.ui.Activator;
+import org.openembedded.bc.ui.model.ProjectInfo;
+
+
+public class BBConfigurationInitializeOperation implements IRunnableWithProgress {
+
+ private final ProjectInfo pinfo;
+ private final Writer writer;
+
+ public BBConfigurationInitializeOperation(ProjectInfo pinfo) {
+ this.pinfo = pinfo;
+ writer = null;
+ }
+
+ public BBConfigurationInitializeOperation(ProjectInfo pinfo, Writer writer) {
+ this.pinfo = pinfo;
+ this.writer = writer;
+ }
+
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ BBSession session;
+ try {
+ ProjectInfoHelper.store(pinfo.getRootPath(), pinfo);
+ session = Activator.getBBSession(pinfo.getRootPath(), writer);
+
+ if (!session.isInitialized()) {
+ session.initialize();
+ }
+
+ if (session.isEmpty()) {
+ Activator.clearBBSession(pinfo.getRootPath());
+ throw new RuntimeException("Bitbake failed silently. No configuration is availalbe.");
+ }
+
+ } catch (Exception e) {
+ Activator.clearBBSession(pinfo.getRootPath());
+ throw new InvocationTargetException(e);
+ }
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/newproject/CreateBBCProjectOperation.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/newproject/CreateBBCProjectOperation.java
new file mode 100644
index 0000000..9e67e5b
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/newproject/CreateBBCProjectOperation.java
@@ -0,0 +1,107 @@
+/*****************************************************************************
+ * Copyright (c) 2009 Ken Gilmer
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ken Gilmer - initial API and implementation
+ *******************************************************************************/
+package org.openembedded.bc.ui.wizards.newproject;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Vector;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+import org.openembedded.bc.bitbake.ProjectInfoHelper;
+import org.openembedded.bc.ui.Activator;
+import org.openembedded.bc.ui.builder.BitbakeCommanderNature;
+import org.openembedded.bc.ui.model.ProjectInfo;
+
+
+
+/**
+ * Creates a bbc project
+ * @author kgilmer
+ *
+ */
+public class CreateBBCProjectOperation extends WorkspaceModifyOperation {
+
+ public static final String OEFS_SCHEME = "OEFS://";
+ public static final QualifiedName BBC_PROJECT_INIT = new QualifiedName(null, "BBC_PROJECT_INIT");
+ public static void addNatureToProject(IProject proj, String nature_id, IProgressMonitor monitor) throws CoreException {
+ IProjectDescription desc = proj.getDescription();
+ Vector natureIds = new Vector();
+
+ natureIds.add(nature_id);
+ natureIds.addAll(Arrays.asList(desc.getNatureIds()));
+ desc.setNatureIds((String[]) natureIds.toArray(new String[natureIds.size()]));
+
+ proj.setDescription(desc, monitor);
+ }
+
+ private ProjectInfo projInfo;
+
+ public CreateBBCProjectOperation(ProjectInfo projInfo) {
+ this.projInfo = projInfo;
+ }
+
+ protected void addNatures(IProject proj, IProgressMonitor monitor) throws CoreException {
+ addNatureToProject(proj, BitbakeCommanderNature.NATURE_ID, monitor);
+ }
+
+ private IProjectDescription createProjectDescription(IWorkspace workspace, ProjectInfo projInfo2) throws CoreException {
+ IProjectDescription desc = workspace.newProjectDescription(projInfo2.getProjectName());
+
+ try {
+ System.out.println("Calling creageProjeDesc");
+ desc.setLocationURI(new URI(OEFS_SCHEME + projInfo2.getRootPath()));
+ } catch (URISyntaxException e) {
+ throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Unable to load filesystem.", e));
+ }
+
+ return desc;
+ }
+
+ @Override
+ protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException {
+ System.out.println("Init: " + projInfo.getInitScriptPath());
+ System.out.println("Proj: " + projInfo.getProjectName());
+ System.out.println("Root: " + projInfo.getRootPath());
+
+ IProjectDescription desc = createProjectDescription(ResourcesPlugin.getWorkspace(), projInfo);
+
+ IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace().getRoot();
+
+ IProject proj = wsroot.getProject(projInfo.getProjectName());
+ proj.create(desc, monitor);
+ try {
+ ProjectInfoHelper.store(proj.getLocationURI().getPath(), projInfo);
+ } catch (IOException e) {
+ throw new InvocationTargetException(e);
+ }
+
+ proj.open(monitor);
+
+ addNatures(proj, monitor);
+ }
+
+ public ProjectInfo getProjectInfo() {
+ return projInfo;
+ }
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/variable/VariablePage.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/variable/VariablePage.java
new file mode 100644
index 0000000..5919581
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/variable/VariablePage.java
@@ -0,0 +1,262 @@
+package org.openembedded.bc.ui.wizards.variable;
+
+import java.util.Comparator;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+import org.openembedded.bc.ui.wizards.FiniteStateWizardPage;
+
+
+/**
+ * The wizard page for the Variable Wizard.
+ * @author kgilmer
+ *
+ */
+public class VariablePage extends FiniteStateWizardPage {
+
+ private Text txtName;
+ private Text txtValue;
+ private TableViewer viewer;
+ private TableColumn c1;
+ private TableColumn c2;
+
+ protected VariablePage(Map model) {
+ super("BitBake Commander", model);
+ setTitle("BitBake Variable Viewer");
+ setDescription("Sort and fitler global BitBake variables by name or value.");
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ Composite top = new Composite(parent, SWT.None);
+ top.setLayout(new GridLayout(2, true));
+ top.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ ValidationListener listener = new ValidationListener();
+
+ txtName = new Text(top, SWT.BORDER);
+ txtName.addModifyListener(listener);
+ txtName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ txtValue = new Text(top, SWT.BORDER);
+ txtValue.addModifyListener(listener);
+ txtValue.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ viewer = new TableViewer(top);
+
+ Table table = viewer.getTable();
+ table.setLinesVisible(true);
+ table.setHeaderVisible(true);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ data.heightHint = 200;
+ data.horizontalSpan = 2;
+ table.setLayoutData(data);
+ c1 = new TableColumn(table, SWT.NONE);
+ c1.setText("Name");
+ c1.setWidth(200);
+ c1.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ ((VariableViewerSorter) viewer.getSorter()).doSort(0);
+ viewer.refresh();
+ }
+ });
+
+ c2 = new TableColumn(table, SWT.NONE);
+ c2.setText("Value");
+ c2.setWidth(200);
+ c2.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ ((VariableViewerSorter) viewer.getSorter()).doSort(1);
+ viewer.refresh();
+ }
+ });
+
+ viewer.setContentProvider(new VariableContentProvider());
+ viewer.setLabelProvider(new VariableLabelProvider());
+ viewer.setSorter(new VariableViewerSorter());
+
+ viewer.setFilters(new ViewerFilter[] {new MapViewerFilter()});
+ setControl(top);
+ }
+
+ @Override
+ public void pageCleanup() {
+
+ }
+
+ @Override
+ public void pageDisplay() {
+ viewer.setInput(model);
+ }
+
+ @Override
+ protected void updateModel() {
+ viewer.refresh();
+ }
+
+ @Override
+ protected boolean validatePage() {
+ return true;
+ }
+
+ /**
+ * A content provider for the variable wizard dialog.
+ * @author kgilmer
+ *
+ */
+ private class VariableContentProvider implements IStructuredContentProvider {
+
+ public Object[] getElements(Object inputElement) {
+ return model.keySet().toArray();
+ }
+
+ public void dispose() {
+
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+
+ }
+ }
+
+ /**
+ * A label provider for variable wizard dialog.
+ * @author kgilmer
+ *
+ */
+ private class VariableLabelProvider implements ITableLabelProvider {
+
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+
+ public String getColumnText(Object element, int columnIndex) {
+ String val;
+
+ switch (columnIndex) {
+ case 0:
+ val = element.toString();
+ break;
+ case 1:
+ val = (String) model.get(element);
+ break;
+ default:
+ val = "";
+ break;
+ }
+
+ return val;
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+
+ }
+
+ public void dispose() {
+
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+
+ }
+
+ }
+
+ /**
+ *
+ * A tableviewer sorter found on the internet.
+ *
+ */
+ class VariableViewerSorter extends ViewerSorter {
+ private static final int ASCENDING = 0;
+
+ private static final int DESCENDING = 1;
+
+ private int column;
+
+ private int direction;
+
+ public void doSort(int column) {
+ if (column == this.column) {
+ // Same column as last sort; toggle the direction
+ direction = 1 - direction;
+ } else {
+ // New column; do an ascending sort
+ this.column = column;
+ direction = ASCENDING;
+ }
+ }
+
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ int rc = 0;
+ Comparator c = this.getComparator();
+ // Determine which column and do the appropriate sort
+ switch (column) {
+ case 0:
+ rc = c.compare(e1, e2);
+ break;
+ case 1:
+ rc = c.compare(model.get(e1), model.get(e2));
+ break;
+ }
+
+ // If descending order, flip the direction
+ if (direction == DESCENDING)
+ rc = -rc;
+
+ return rc;
+ }
+ }
+
+ /**
+ * A filter for the name/value model.
+ * @author kgilmer
+ *
+ */
+ private class MapViewerFilter extends ViewerFilter {
+
+ public MapViewerFilter() {
+ }
+
+ @Override
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ String keyFilter = txtName.getText();
+ String valFilter = txtValue.getText();
+
+ String elem = (String) element;
+ String val = (String) model.get(element);
+
+ if (keyFilter.length() > 0 && elem.indexOf(keyFilter) == -1 ) {
+ return false;
+ }
+
+ if (valFilter.length() > 0 && val.indexOf(valFilter) == -1 ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ }
+
+}
diff --git a/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/variable/VariableWizard.java b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/variable/VariableWizard.java
new file mode 100644
index 0000000..d93a440
--- /dev/null
+++ b/org.openembedded.bc.ui/src/org/openembedded/bc/ui/wizards/variable/VariableWizard.java
@@ -0,0 +1,43 @@
+package org.openembedded.bc.ui.wizards.variable;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.openembedded.bc.ui.wizards.FiniteStateWizard;
+
+
+/**
+ * This wizard is used to view, filter, and search for BitBake variables and variable contents.
+ * @author kgilmer
+ *
+ */
+public class VariableWizard extends FiniteStateWizard {
+
+ private Map model;
+
+ public VariableWizard(Map model) {
+ this.model = model;
+ setWindowTitle("BitBake Commander");
+ }
+
+ public VariableWizard(IStructuredSelection selection) {
+ model = new Hashtable();
+ }
+
+ @Override
+ public void addPages() {
+ addPage(new VariablePage(model));
+ }
+
+ @Override
+ public Map getModel() {
+ return model;
+ }
+
+ @Override
+ public boolean performFinish() {
+ return true;
+ }
+
+}