changeset 136:31d0ab4467ad

Add an export wizard to export entire plugin Introduce an export wizard that can export the entire plugin projects into a Thermostat installation. Add 'tags' to projects to keep track of what the root project (to export) is. There's barely any feedback for the export process right now. Errors and issues are effectively ignored.
author Omair Majid <omajid@redhat.com>
date Thu, 05 Jun 2014 11:53:06 -0400
parents eef52fe80553
children 2d1213657085
files com.redhat.thermostat.tools.eclipse.plugin/plugin.xml com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/ProjectFinder.java com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/ProjectPreferences.java com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/SelectionUtils.java com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/Unzipper.java com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/wizards/ExportPluginPage.java com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/wizards/ExportPluginWizard.java com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/wizards/PluginXmlProjectSelectionPage.java com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/wizards/ProjectCreator.java
diffstat 9 files changed, 539 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/com.redhat.thermostat.tools.eclipse.plugin/plugin.xml	Tue Jun 03 17:32:08 2014 -0400
+++ b/com.redhat.thermostat.tools.eclipse.plugin/plugin.xml	Thu Jun 05 11:53:06 2014 -0400
@@ -57,5 +57,17 @@
          </describer>
       </content-type>
    </extension>
+   <extension
+         point="org.eclipse.ui.exportWizards">
+      <wizard
+            class="com.redhat.thermostat.tools.eclipse.plugin.wizards.ExportPluginWizard"
+            icon="icons/thermostat.png"
+            id="com.redhat.thermostat.tools.eclipse.plugin.exportWizard"
+            name="Thermostat Export Plugin">
+         <description>
+            Export a Thermostat plugin into a target Thermostat installation
+         </description>
+      </wizard>
+   </extension>
 
 </plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/ProjectFinder.java	Thu Jun 05 11:53:06 2014 -0400
@@ -0,0 +1,39 @@
+package com.redhat.thermostat.tools.eclipse.plugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+
+public class ProjectFinder {
+
+    // TODO replace with j.u.f.Predicate
+    public static interface Criteria {
+        public boolean matches(IProject project);
+    }
+
+    public List<IProject> find(Criteria criteria) {
+        List<IProject> result = new ArrayList<>();
+
+        IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+        for (IProject project : projects) {
+           if (criteria.matches(project)) {
+               result.add(project);
+           }
+        }
+        return result;
+    }
+
+    public List<String> findProjectNames(Criteria criteria) {
+        List<String> result = new ArrayList<>();
+
+        IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+        for (IProject project : projects) {
+           if (criteria.matches(project)) {
+               result.add(project.getName());
+           }
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/ProjectPreferences.java	Thu Jun 05 11:53:06 2014 -0400
@@ -0,0 +1,42 @@
+package com.redhat.thermostat.tools.eclipse.plugin;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ProjectScope;
+import org.osgi.service.prefs.BackingStoreException;
+import org.osgi.service.prefs.Preferences;
+
+public class ProjectPreferences {
+
+    /** A boolean tag to indicate the root/parent project */
+    public static final String PLUGIN_PROJECT = "pluginProject";
+
+    /** A boolean tag to indicate the project containing the {@code thermostat-plugin.xml} file*/
+    public static final String PLUGIN_DISTRIBUTION_PROJECT = "pluginDistributionProject";
+
+    /** The last thermostat install location that plugin was installed to */
+    public static final String THERMOSTAT_LOCATION = "thermostatLocation";
+
+    private Preferences node;
+
+    public ProjectPreferences(IProject project) {
+        ProjectScope scope = new ProjectScope(project);
+        Preferences node = scope.getNode(Activator.PLUGIN_ID);
+        if (node == null) {
+            throw new AssertionError("Null prefs node not implemented");
+        }
+        this.node = node;
+    }
+
+    public void add(String key, String value) {
+        node.put(key, value);
+    }
+
+    public String get(String key) {
+        return node.get(key, null);
+    }
+
+    public void flush() throws BackingStoreException {
+        node.flush();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/SelectionUtils.java	Thu Jun 05 11:53:06 2014 -0400
@@ -0,0 +1,31 @@
+package com.redhat.thermostat.tools.eclipse.plugin;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+
+public class SelectionUtils {
+
+    /**
+     * Returns an IProject that corresponds to the currently selected project.
+     * Returns {@code null} if no project was selected or multiple projects were
+     * selected
+     */
+    public static IProject getSelectedProject(ISelection selection) {
+        if (selection instanceof IStructuredSelection && selection.isEmpty() == false) {
+            IStructuredSelection ssel = (IStructuredSelection) selection;
+            if (ssel.size() > 1) {
+                return null;
+            }
+
+            Object obj = ssel.getFirstElement();
+            if (obj instanceof IAdaptable) {
+                IProject container = (IProject)((IAdaptable)obj).getAdapter(IProject.class);
+                return container;
+            }
+        }
+
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/Unzipper.java	Thu Jun 05 11:53:06 2014 -0400
@@ -0,0 +1,43 @@
+package com.redhat.thermostat.tools.eclipse.plugin;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+public class Unzipper {
+
+    public void unzip(ZipFile zipFile, File targetDirectory) throws IOException {
+        Enumeration<? extends ZipEntry> entries = zipFile.entries();
+        while (entries.hasMoreElements()) {
+            ZipEntry entry = entries.nextElement();
+
+            if (entry.isDirectory()) {
+                continue;
+            }
+
+            File targetFile = new File(targetDirectory, entry.getName());
+            targetFile.getParentFile().mkdirs();
+
+            copyStream(zipFile.getInputStream(entry), new FileOutputStream(targetFile));
+        }
+    }
+
+    private void copyStream(InputStream input, OutputStream output) throws IOException {
+        byte[] buffer = new byte[1024];
+        try (InputStream in = new BufferedInputStream(input)) {
+            try (OutputStream out = new BufferedOutputStream(output)) {
+                int read = 0;
+                while ((read = in.read(buffer)) != -1) {
+                    out.write(buffer, 0, read);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/wizards/ExportPluginPage.java	Thu Jun 05 11:53:06 2014 -0400
@@ -0,0 +1,211 @@
+package com.redhat.thermostat.tools.eclipse.plugin.wizards;
+
+import java.io.File;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.fieldassist.ContentProposalAdapter;
+import org.eclipse.jface.fieldassist.SimpleContentProposalProvider;
+import org.eclipse.jface.fieldassist.TextContentAdapter;
+import org.eclipse.jface.viewers.ISelection;
+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.DirectoryDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import com.redhat.thermostat.tools.eclipse.plugin.ProjectFinder;
+import com.redhat.thermostat.tools.eclipse.plugin.ProjectFinder.Criteria;
+import com.redhat.thermostat.tools.eclipse.plugin.ProjectPreferences;
+import com.redhat.thermostat.tools.eclipse.plugin.SelectionUtils;
+
+public class ExportPluginPage extends WizardPage {
+
+    static final String PAGE_NAME = "exportPlugin"; //$NON-NLS-1$
+
+    private IProject project;
+
+    private Text projectNameText;
+    private Text installationLocationText;
+
+
+    private ISelection selection;
+
+    public ExportPluginPage(ISelection selection) {
+        super(PAGE_NAME);
+        setTitle("Export Plugin");
+        setDescription("Export a plugin to a Thermostat installation");
+        this.selection = selection;
+    }
+
+    public void createControl(Composite parent) {
+        GridData gd;
+
+        Composite container = new Composite(parent, SWT.NULL);
+        GridLayout layout = new GridLayout(3, false);
+        container.setLayout(layout);
+
+        Label projectName = new Label(container, SWT.NONE);
+        projectName.setText("Project Name");
+
+        projectNameText = new Text(container, SWT.BORDER | SWT.SINGLE);
+        gd = new GridData(GridData.FILL_HORIZONTAL);
+        gd.horizontalSpan = 2;
+        projectNameText.setLayoutData(gd);
+        projectNameText.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                dialogChanged();
+            }
+        });
+
+        Label targetDirectory = new Label(container, SWT.NONE);
+        targetDirectory.setText("Installation Location");
+
+        installationLocationText = new Text(container, SWT.BORDER | SWT.SINGLE);
+        gd = new GridData(GridData.FILL_HORIZONTAL);
+        installationLocationText.setLayoutData(gd);
+        installationLocationText.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                dialogChanged();
+            }
+        });
+
+        Button browse = new Button(container, SWT.PUSH);
+        browse.setText("Browse");
+        browse.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                handleBrowse();
+            }
+        });
+
+        String[] proposals = getProjectNamesForExporting().toArray(new String[0]);
+        SimpleContentProposalProvider projectProposalProvider = new SimpleContentProposalProvider(proposals);
+        TextContentAdapter contentAdapter = new TextContentAdapter();
+        ContentProposalAdapter proposalAdapter = new ContentProposalAdapter(projectNameText, contentAdapter, projectProposalProvider, null, null);
+        proposalAdapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);
+
+        initialize();
+        dialogChanged();
+
+        setControl(container);
+    }
+
+    private void initialize() {
+        IProject project = SelectionUtils.getSelectedProject(selection);
+        if (project != null) {
+            ProjectPreferences prefs = new ProjectPreferences(project);
+            if (Boolean.valueOf(prefs.get(ProjectPreferences.PLUGIN_PROJECT))) {
+                this.project = project;
+                projectNameText.setText(project.getName());
+            }
+        }
+    }
+
+    private void dialogChanged() {
+        setErrorMessage(null);
+        setPageComplete(isProjectValid() && isTargetLocationValid());
+    }
+
+    /** Side-effect: Update error status message */
+    private boolean isProjectValid() {
+        String containerName = getProjectName();
+
+        if (containerName.length() == 0) {
+            setErrorMessage("Project name must be specified");
+            return false;
+        }
+
+        IResource container = ResourcesPlugin
+                .getWorkspace()
+                .getRoot()
+                .findMember(new Path(containerName));
+
+        if (container == null
+                || (container.getType() & (IResource.PROJECT | IResource.FOLDER)) == 0) {
+            setErrorMessage("Project must exist");
+            return false;
+        }
+        if (!container.isAccessible()) {
+            setErrorMessage("Project must be readable");
+            return false;
+        }
+
+        return true;
+
+    }
+
+    /** Side-effect: Update error status message */
+    private boolean isTargetLocationValid() {
+        File thermostatHome = new File(installationLocationText.getText());
+        if (!thermostatHome.isDirectory()) {
+            setErrorMessage("Not a valid thermostat directory");
+            return false;
+        }
+
+        File pluginDir = new File(thermostatHome, "plugins");
+        if (!pluginDir.isDirectory()) {
+            setErrorMessage("Not a valid thermostat directory");
+            return false;
+        }
+
+        String pluginName = projectNameText.getText().replace("-distribution", "");
+        File pluginHome = new File(pluginDir, pluginName);
+        if (pluginHome.isDirectory()) {
+            setErrorMessage("Directory " + pluginHome + " already exists.");
+            return false;
+        }
+
+        return true;
+    }
+
+    private void handleBrowse() {
+        DirectoryDialog dialog = new DirectoryDialog(getShell());
+        String selectedDir = dialog.open();
+        if (selectedDir != null) {
+            installationLocationText.setText(selectedDir);
+        }
+    }
+
+    public IProject getProject() {
+        return this.project;
+    }
+
+    public String getProjectName() {
+        return this.project.getName();
+    }
+
+    public String getInstallationLocation() {
+        return installationLocationText.getText();
+    }
+
+    private List<String> getProjectNamesForExporting() {
+        ProjectFinder finder = new ProjectFinder();
+        return finder.findProjectNames(new ValidPluginProjectMatcher());
+    }
+
+    private static class ValidPluginProjectMatcher implements Criteria {
+        @Override
+        public boolean matches(IProject project) {
+            if (!project.isOpen()) {
+                return false;
+            }
+
+            ProjectPreferences prefs = new ProjectPreferences(project);
+            return Boolean.valueOf(prefs.get(ProjectPreferences.PLUGIN_PROJECT));
+        }
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/wizards/ExportPluginWizard.java	Thu Jun 05 11:53:06 2014 -0400
@@ -0,0 +1,127 @@
+package com.redhat.thermostat.tools.eclipse.plugin.wizards;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.zip.ZipFile;
+
+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.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.IExportWizard;
+import org.eclipse.ui.IWorkbench;
+
+import com.redhat.thermostat.tools.eclipse.plugin.Activator;
+import com.redhat.thermostat.tools.eclipse.plugin.Unzipper;
+
+public class ExportPluginWizard extends Wizard implements IExportWizard {
+
+    private IStructuredSelection selection;
+    private ExportPluginPage exportPage;
+
+    @Override
+    public void init(IWorkbench workbench, IStructuredSelection selection) {
+        setWindowTitle("Export Thermostat Plugin");
+        setNeedsProgressMonitor(true);
+
+        this.selection = selection;
+    }
+
+    @Override
+    public void addPages() {
+        exportPage = new ExportPluginPage(selection);
+        addPage(exportPage);
+    }
+
+    @Override
+    public boolean performFinish() {
+        IProject project = exportPage.getProject();
+        String targetLocation = exportPage.getInstallationLocation();
+
+        Job export = new ExportPlugin(project, targetLocation);
+        export.schedule();
+
+        return true;
+    }
+
+    private static class ExportPlugin extends Job {
+
+        private IProject project;
+        private String targetLocation;
+
+        public ExportPlugin(IProject project, String targetLocation) {
+            super("Exporting Thermostat plugin");
+            this.project = project;
+            this.targetLocation = targetLocation;
+        }
+
+        @Override
+        protected IStatus run(IProgressMonitor monitor) {
+            try {
+                // mvn clean package
+                new MavenRunner().run(project, "package");
+            } catch (CoreException e) {
+                e.printStackTrace();
+                return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Unable to run 'mvn clean package'", e);
+            }
+
+            final String distributionModuleName = project.getName() + "-distribution";
+            // TODO unzip and extract to thermostatLocation
+            File projectDir = project.getLocation().toFile();
+            // FIXME don't hardcode distribution project name
+            File distributionDir = new File(projectDir, distributionModuleName);
+            File distributionTargetDir = new File(distributionDir, "target");
+            String[] files = distributionTargetDir.list(new FilenameFilter() {
+                @Override
+                public boolean accept(File dir, String name) {
+                    return name.matches("\\Q" + distributionModuleName + "\\E.*\\.zip");
+                }
+            });
+
+            String zipFile = files[0];
+            try {
+                ZipFile pluginZip = new ZipFile(new File(distributionTargetDir, zipFile));
+                File installationDirectory = new File(targetLocation, "plugins");
+                new Unzipper().unzip(pluginZip, installationDirectory);
+                System.out.println("Done installing " + project.getName() + " to " + installationDirectory);
+            } catch (IOException e) {
+                e.printStackTrace();
+                return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Unable to install plugin in target location", e);
+            }
+
+            return Status.OK_STATUS;
+        }
+    }
+
+    private static class MavenRunner {
+
+        public void run(IProject project, String goal) throws CoreException {
+            try {
+                System.out.println("Starting packaging");
+                ProcessBuilder processBuilder = new ProcessBuilder("mvn", "clean", goal);
+                processBuilder.directory(project.getLocation().toFile());
+                processBuilder.redirectError(ProcessBuilder.Redirect.PIPE);
+                processBuilder.redirectOutput(ProcessBuilder.Redirect.PIPE);
+                Process process = processBuilder.start();
+
+                // FIXME make this non-blocking. Add tons of feedback.
+
+                boolean result = process.waitFor(5, TimeUnit.MINUTES);
+                if (!result) {
+                    throw new AssertionError("An error invoking maven. Maybe try 'mvn clean package' on command line?");
+                }
+                System.out.println("Done packaging");
+            } catch (IOException | InterruptedException e) {
+                IStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Error running maven", e);
+                throw new CoreException(status);
+            }
+        }
+
+    }
+}
--- a/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/wizards/PluginXmlProjectSelectionPage.java	Tue Jun 03 17:32:08 2014 -0400
+++ b/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/wizards/PluginXmlProjectSelectionPage.java	Thu Jun 05 11:53:06 2014 -0400
@@ -1,18 +1,15 @@
 package com.redhat.thermostat.tools.eclipse.plugin.wizards;
 
-import java.util.ArrayList;
 import java.util.List;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jface.fieldassist.ContentProposalAdapter;
 import org.eclipse.jface.fieldassist.SimpleContentProposalProvider;
 import org.eclipse.jface.fieldassist.TextContentAdapter;
 import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.wizard.WizardPage;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.ModifyEvent;
@@ -28,6 +25,9 @@
 import org.eclipse.ui.dialogs.ContainerSelectionDialog;
 
 import com.redhat.thermostat.tools.eclipse.plugin.Messages;
+import com.redhat.thermostat.tools.eclipse.plugin.ProjectFinder;
+import com.redhat.thermostat.tools.eclipse.plugin.ProjectFinder.Criteria;
+import com.redhat.thermostat.tools.eclipse.plugin.SelectionUtils;
 
 public class PluginXmlProjectSelectionPage extends WizardPage {
 
@@ -45,12 +45,12 @@
     }
 
     public void createControl(Composite parent) {
-        Composite container = new Composite(parent, SWT.NULL);
+        Composite container = new Composite(parent, SWT.NONE);
         GridLayout layout = new GridLayout();
         container.setLayout(layout);
         layout.numColumns = 3;
         layout.verticalSpacing = 9;
-        Label label = new Label(container, SWT.NULL);
+        Label label = new Label(container, SWT.NONE);
         label.setText(Messages.PluginXmlProjectSelectionPage_projectNameLabel);
 
         containerText = new Text(container, SWT.BORDER | SWT.SINGLE);
@@ -62,7 +62,7 @@
             }
         });
 
-        String[] proposals = getOpenProjectNames().toArray(new String[0]);
+        String[] proposals = getProjectNamesForPluginXmlFile().toArray(new String[0]);
         SimpleContentProposalProvider projectProposalProvider = new SimpleContentProposalProvider(proposals);
         TextContentAdapter contentAdapter = new TextContentAdapter();
         ContentProposalAdapter proposalAdapter = new ContentProposalAdapter(containerText, contentAdapter, projectProposalProvider, null, null);
@@ -82,18 +82,9 @@
     }
 
     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 IAdaptable) {
-                IProject container = (IProject)((IAdaptable)obj).getAdapter(IProject.class);
-
-                containerText.setText(container.getName().toString());
-            }
+        IProject project = SelectionUtils.getSelectedProject(selection);
+        if (project != null) {
+            containerText.setText(project.getName());
         }
     }
 
@@ -141,16 +132,13 @@
         return containerText.getText();
     }
 
-    private List<String> getOpenProjectNames() {
-        List<String> result = new ArrayList<>();
-
-        IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
-        for (IProject project : projects) {
-           if (project.isOpen()) {
-               result.add(project.getName());
-           }
-        }
-
-        return result;
+    private List<String> getProjectNamesForPluginXmlFile() {
+        ProjectFinder finder = new ProjectFinder();
+        return finder.findProjectNames(new Criteria() {
+            @Override
+            public boolean matches(IProject project) {
+                return project.isOpen();
+            }
+        });
     }
 }
--- a/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/wizards/ProjectCreator.java	Tue Jun 03 17:32:08 2014 -0400
+++ b/com.redhat.thermostat.tools.eclipse.plugin/src/com/redhat/thermostat/tools/eclipse/plugin/wizards/ProjectCreator.java	Thu Jun 05 11:53:06 2014 -0400
@@ -32,8 +32,10 @@
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.handlers.IHandlerService;
+import org.osgi.service.prefs.BackingStoreException;
 
 import com.redhat.thermostat.tools.eclipse.plugin.Activator;
+import com.redhat.thermostat.tools.eclipse.plugin.ProjectPreferences;
 import com.redhat.thermostat.tools.eclipse.plugin.wizards.PluginXmlCreator.Decisions;
 
 /** Creates a Thermostat project using the preferred thermostat defaults, settings, and style */
@@ -164,6 +166,8 @@
         String projectName = artifactId;
         Project project = createMavenProject(null, projectName);
 
+        addTag(project, ProjectPreferences.PLUGIN_PROJECT, Boolean.TRUE.toString());
+
         String pomContents = ""
                 + POM_HEADER
                 + "  <groupId>" + groupId + "</groupId>\n"
@@ -303,6 +307,8 @@
 
         Project projects = createJavaAndMavenProject(parent, artifactId);
 
+        addTag(projects, ProjectPreferences.PLUGIN_DISTRIBUTION_PROJECT, Boolean.TRUE.toString());
+
         String pomContents = ""
                 + POM_HEADER
                 + createParentSection(groupId, parentId, version)
@@ -486,6 +492,17 @@
             + "  </parent>\n";
     }
 
+    private void addTag(Project project, String key, String value) throws IOException {
+        IProject theProject = project.project;
+        ProjectPreferences prefs = new ProjectPreferences(theProject);
+        prefs.add(key, value);
+        try {
+            prefs.flush();
+        } catch (BackingStoreException e) {
+            throw new IOException(e);
+        }
+    }
+
     private void refreshProjects(List<Project> projects) throws CoreException {
         // Refresh projects
         ResourcesPlugin.getWorkspace().getRoot().refreshLocal(IWorkspaceRoot.DEPTH_INFINITE, new NullProgressMonitor());