Index: installer/src/panels/com/izforge/izpack/installer/Unpacker.java
===================================================================
--- installer/src/panels/com/izforge/izpack/installer/Unpacker.java	(revision 11632)
+++ installer/src/panels/com/izforge/izpack/installer/Unpacker.java	(working copy)
@@ -1,18 +1,18 @@
 /*
  * $Id$
  * IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved.
- * 
+ *
  * http://izpack.org/
  * http://izpack.codehaus.org/
- * 
+ *
  * Copyright 2001 Johannes Lehtinen
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- *     
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -27,6 +27,7 @@
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
+import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.ObjectInputStream;
@@ -127,7 +128,7 @@
                     }
                     else
                     {
-                        // TODO: skip pack, because condition can not be checked 
+                        // TODO: skip pack, because condition can not be checked
                     }
                 }
 
@@ -141,8 +142,8 @@
 
                 // We get the internationalized name of the pack
                 final Pack pack = ((Pack) packs.get(i));
-                String stepname = pack.name;// the message to be passed to the                
-                
+                String stepname = pack.name;// the message to be passed to the
+
                 // installpanel
                 if (langpack != null && !(pack.id == null || "".equals(pack.id)))
                 {
@@ -155,27 +156,32 @@
                 if (pack.isHidden()){
                     // TODO: hide the pack completely
                     // hide the pack name if pack is hidden
-                    stepname = "";                                           
+                    stepname = "";
                 }
-                
+
                 if(pack.id.equals("jbds.update") || pack.id.equals("jbds.generate")) {
-                	
+
                 	String jvmLocation = this.idata.getVariable("JREPath");
                 	jvmLocation = jvmLocation==null || "".equals(jvmLocation.trim())? this.idata.getVariable("JAVA_HOME"): jvmLocation;
 					String installLocation = this.idata.getVariable("INSTALL_PATH");
-					String launcherLocation = 
-							installLocation + File.separator + 
-							"studio" + File.separator + 
-							"p2" + File.separator + 
-							"director" + File.separator + 
-							"plugins" + File.separator + 
-							"org.eclipse.equinox.launcher_1.2.0.v20110502.jar";
-					
+					File pluginsFolder = new File(installLocation + File.separator +
+							"studio" + File.separator +
+							"p2" + File.separator +
+							"director" + File.separator +
+							"plugins" + File.separator);
+					File[] launchers = pluginsFolder.listFiles(new FilenameFilter() {
+						@Override
+						public boolean accept(File dir, String name) {
+							return name.startsWith("org.eclipse.equinox.launcher") && name.endsWith(".jar");
+						}
+					});
+					String launcherLocation = launchers[0].getAbsolutePath();
+
 					String jarLocation = P2DirectorStarterListener.findPathJar(Unpacker.class);
                 	if(pack.id.equals("jbds.update")) {
 	                	// get list of IU's and size
 	                	// nfiles = request(-l) from director
-	                	
+
 	                	BundleListConsoleCommand listCmd = new BundleListConsoleCommand();
 						listCmd
 	                		.setParameter(jvmLocation)
@@ -184,31 +190,31 @@
 	                		.setParameter(installLocation)
 	                		.execute();
 	                	nfiles=listCmd.getBundles().size();
-	                	
+
 	                	FeatureInstallConsoleCommand featureInstallCmd = new FeatureInstallConsoleCommand(idata) {
 	                		int counter = 0;
                 			public void downloadProgress(int i, String line) {
                 				handler.progress(i,line);
-                				if(performInterrupted()) { 
+                				if(performInterrupted()) {
                 					close();
                 				}
                 			};
                 			public void configInstallProgress(int i, String line) {
                 				handler.progress(i,line);
-                				if(performInterrupted()) { 
+                				if(performInterrupted()) {
                 					close();
                 				}
                 			};
 	                	};
-	                	
+
 	                	handler.nextStep(pack.name, i + 1, featureInstallCmd.calculateAmountOfWork(nfiles));
-         	
+
 	                	featureInstallCmd.setParameter(jvmLocation)
 	                	 .setParameter(launcherLocation)
 	                	 .setParameter(jarLocation)
 	                	 .setParameter(installLocation)
 	                	 .execute();
-	
+
 //	                	handler.stopAction();
 	                } else if(pack.id.equals("jbds.generate")){
 	                	handler.nextStep(pack.name, i + 1, 1);
@@ -239,7 +245,7 @@
 	                        {
 	                            if (!pf.isBackReference()){
 	                                // skip, condition is not fulfilled
-	                                objIn.skip(pf.length());                                                          
+	                                objIn.skip(pf.length());
 	                            }
 	                            continue;
 	                        }
@@ -254,7 +260,7 @@
 	                        {
 	                            dest = pathFile.getParentFile();
 	                        }
-	
+
 	                        if (!dest.exists())
 	                        {
 	                            // If there are custom actions which would be called
@@ -278,27 +284,27 @@
 	                                }
 	                            }
 	                        }
-	
+
 	                        if (pf.isDirectory())
 	                        {
 	                            continue;
 	                        }
-	
+
 	                        // Custom action listener stuff --- beforeFile ----
 	                        informListeners(customActions, InstallerListener.BEFORE_FILE, pathFile, pf,
 	                                null);
 	                        // We add the path to the log,
 	                        udata.addFile(path, pack.uninstall);
-	
+
 	                        handler.progress(j, path);
-	
+
 	                        // if this file exists and should not be overwritten,
 	                        // check
 	                        // what to do
 	                        if ((pathFile.exists()) && (pf.override() != PackFile.OVERRIDE_TRUE))
 	                        {
 	                            boolean overwritefile = false;
-	
+
 	                            // don't overwrite file if the user said so
 	                            if (pf.override() != PackFile.OVERRIDE_FALSE)
 	                            {
@@ -321,7 +327,7 @@
 	                                else
 	                                {
 	                                    int def_choice = -1;
-	
+
 	                                    if (pf.override() == PackFile.OVERRIDE_ASK_FALSE)
 	                                    {
 	                                        def_choice = AbstractUIHandler.ANSWER_NO;
@@ -330,19 +336,19 @@
 	                                    {
 	                                        def_choice = AbstractUIHandler.ANSWER_YES;
 	                                    }
-	
+
 	                                    int answer = handler.askQuestion(idata.langpack
 	                                            .getString("InstallPanel.overwrite.title")
 	                                            + " - " + pathFile.getName(), idata.langpack
 	                                            .getString("InstallPanel.overwrite.question")
 	                                            + pathFile.getAbsolutePath(),
 	                                            AbstractUIHandler.CHOICES_YES_NO, def_choice);
-	
+
 	                                    overwritefile = (answer == AbstractUIHandler.ANSWER_YES);
 	                                }
-	
+
 	                            }
-	
+
 	                            if (!overwritefile)
 	                            {
 	                                if (!pf.isBackReference() && !((Pack) packs.get(i)).loose)
@@ -356,9 +362,9 @@
 	                                }
 	                                continue;
 	                            }
-	
+
 	                        }
-	
+
 	                        // We copy the file
 	                        InputStream pis = objIn;
 	                        if (pf.isBackReference())
@@ -380,7 +386,7 @@
 	                            * prefer using relative path's
 	                           pis = new FileInputStream(pf.sourcePath);
 	                            */
-	
+
 	                          File resolvedFile = new File(getAbsolutInstallSource(), pf
 	                              .getRelativeSourcePath());
 	                            if (!resolvedFile.exists())
@@ -409,7 +415,7 @@
 	                                continue;
 	                            }
 	                        }
-	
+
 	                        if (pf.isPack200Jar())
 	                        {
 	                            int key = objIn.readInt();
@@ -441,19 +447,19 @@
 	                                {
 	                                    throw new IOException("Unexpected end of stream (installer corrupted?)");
 	                                }
-	
+
 	                                out.write(buffer, 0, bytesInBuffer);
-	
+
 	                                bytesCopied += bytesInBuffer;
 	                            }
 	                            out.close();
 	                        }
-	
+
 	                        if (pis != objIn)
 	                        {
 	                            pis.close();
 	                        }
-	
+
 	                        // Set file modification time if specified
 	                        if (pf.lastModified() >= 0)
 	                        {
@@ -462,7 +468,7 @@
 	                        // Custom action listener stuff --- afterFile ----
 	                        informListeners(customActions, InstallerListener.AFTER_FILE, pathFile, pf,
 	                                null);
-	
+
 	                    }
 	                    else
 	                    {
Index: installer/src/config/install-pack-universal.xml
===================================================================
--- installer/src/config/install-pack-universal.xml	(revision 11632)
+++ installer/src/config/install-pack-universal.xml	(working copy)
@@ -7,14 +7,12 @@
       <description>
         P2 Director to install JBoss Developer Studio @{specification.version.presentstring}
       </description>
-      
+
       <singlefile src="config/resources/EULA/JBoss-EULA.html" target="$INSTALL_PATH/JBoss-EULA.html" />
       <singlefile src="config/resources/readme.txt" target="$INSTALL_PATH/readme.txt" />
 
       <fileset dir="studio" targetdir="$INSTALL_PATH/studio">
       </fileset>
-      
-      <executable targetfile="$INSTALL_PATH/studio/p2/director/director" />
 
       <singlefile src="config/resources/jbdevstudio-unity" target="$INSTALL_PATH/jbdevstudio-unity" condition="izpack.linuxinstall" />
       <executable targetfile="$INSTALL_PATH/jbdevstudio-unity" condition="izpack.linuxinstall" />
@@ -25,9 +23,9 @@
       <singlefile src="config/resources/jbdevstudio.bat" target="$INSTALL_PATH/jbdevstudio.bat" os="windows" />
       <parsable targetfile="$INSTALL_PATH/jbdevstudio.bat" os="windows" />
       <executable targetfile="$INSTALL_PATH/jbdevstudio.bat" os="windows" />
-      
+
       <singlefile src="config/resources/runtimes-readme.txt" target="$INSTALL_PATH/runtimes/readme.txt" />
-      
+
     </pack>
     <pack name="JBoss Developer Studio @{specification.version.presentstring}" id="jbds.update" installGroups="jbosseap,jbds" required="no">
       <description>
@@ -39,14 +37,14 @@
         JBoss Developer Studio @{specification.version.presentstring} Metadata Generation
       </description>
     </pack>
-    
+
     <pack name="JBoss Developer Studio @{specification.version.presentstring} Metadata Generation" id="jbds.plist" installGroups="jbosseap,jbds" required="no">
       <description>
         JBoss Developer Studio @{specification.version.presentstring} Mac OSX Package Properties Update
       </description>
       <singlefile src="config/resources/JBoss Developer Studio.app/Contents/Info.plist" target="$INSTALL_PATH/studio/jbdevstudio.app/Contents/Info.plist" override="true" os="mac" />
     </pack>
-    
+
     <pack name="JBoss Enterprise Application Platform" id="jbosseap" installGroups="jbosseap" required="no">
       <description>
         JBoss Enterprise Application Platform
Index: installer/pom.xml
===================================================================
--- installer/pom.xml	(revision 11632)
+++ installer/pom.xml	(working copy)
@@ -87,13 +87,32 @@
                 <artifactItem>
                   <groupId>com.jboss.jbds.site</groupId>
                   <artifactId>com.jboss.jbds.site.product</artifactId>
-                  <version>7.0.0-SNAPSHOT</version>
+                  <version>${project.version}</version>
                   <type>zip</type>
                 </artifactItem>
               </artifactItems>
               <outputDirectory>${project.build.directory}/update/jbds</outputDirectory>
             </configuration>
           </execution>
+          <execution>
+            <id>copy-director</id>
+            <phase>prepare-package</phase>
+            <goals>
+              <goal>copy</goal>
+            </goals>
+            <configuration>
+              <artifactItems>
+                <artifactItem>
+                  <groupId>com.jboss.jbds.installer.p2-director</groupId>
+                  <artifactId>p2-director</artifactId>
+                  <version>${project.version}</version>
+                  <type>zip</type>
+                  <classifier>dist</classifier>
+                  <destFileName>p2-director.zip</destFileName>
+                </artifactItem>
+              </artifactItems>
+            </configuration>
+          </execution>
         </executions>
       </plugin>
       <plugin>
@@ -186,7 +205,7 @@
                   <property name="platform.name" value="universal" />
                   <!-- TODO: once it contains an executable, replace this with latest 0.16.0 version from 
                     https://github.com/eclipse/tycho/tree/master/tycho-bundles/tycho-standalone-p2-director -->
-                  <property name="artifacts.p2-director" value="${basedir}/p2-director.zip" />
+                  <property name="artifacts.p2-director" value="${project.build.directory}/requirements/p2-director.zip" />
                   <property name="artifacts.jbds.update"
                     value="${project.build.directory}/jbdevstudio-product-installer-Update-${buildQualifier}.zip" />
                   <property name="artifacts.jbosseap"
Index: installer/p2-director.zip
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: installer/build.xml
===================================================================
--- installer/build.xml	(revision 11632)
+++ installer/build.xml	(working copy)
@@ -214,8 +214,8 @@
     <delete includeemptydirs="true" defaultexcludes="false" failonerror="false">
       <fileset dir="${studio.dist}" />
     </delete>
-    <mkdir dir="${studio.dist}/p2" />
-    <unzip dest="${studio.dist}/p2" src="${artifacts.p2-director}" />
+    <mkdir dir="${studio.dist}/p2/director" />
+    <unzip dest="${studio.dist}/p2/director" src="${artifacts.p2-director}" />
   </target>
 
   <macrodef name="expandproperties">
Index: pom.xml
===================================================================
--- pom.xml	(revision 11632)
+++ pom.xml	(working copy)
@@ -17,6 +17,7 @@
     <module>plugins</module>
     <module>features</module>
     <module>site</module>
+    <module>p2-director</module>
     <module>installer</module>
     <module>sources</module>
     <module>results</module>
Index: p2-director/p2-director/.project
===================================================================
--- p2-director/p2-director/.project	(revision 0)
+++ p2-director/p2-director/.project	(revision 0)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>p2-director</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+	</natures>
+</projectDescription>
Index: p2-director/p2-director/p2-director.product
===================================================================
--- p2-director/p2-director/p2-director.product	(revision 0)
+++ p2-director/p2-director/p2-director.product	(revision 0)
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?pde version="3.5"?>
+
+<product name="Tweaked P2 Director application" uid="com.jboss.jbds.p2.director.product" id="org.eclipse.equinox.p2.director.product" application="com.jboss.jbds.p2.director" version="7.0.0.qualifier" useFeatures="false" includeLaunchers="false">
+
+   <configIni use="default">
+   </configIni>
+
+   <launcherArgs>
+      <vmArgsMac>-XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts</vmArgsMac>
+   </launcherArgs>
+
+   <windowImages/>
+
+   <launcher>
+      <solaris/>
+      <win useIco="false">
+         <bmp/>
+      </win>
+   </launcher>
+
+   <vm>
+   </vm>
+
+   <plugins>
+      <plugin id="com.jboss.jbds.p2.director"/>
+      <plugin id="javax.xml"/>
+      <plugin id="org.eclipse.core.contenttype"/>
+      <plugin id="org.eclipse.core.jobs"/>
+      <plugin id="org.eclipse.core.runtime"/>
+      <plugin id="org.eclipse.ecf"/>
+      <plugin id="org.eclipse.ecf.filetransfer"/>
+      <plugin id="org.eclipse.ecf.identity"/>
+      <plugin id="org.eclipse.ecf.provider.filetransfer"/>
+      <plugin id="org.eclipse.equinox.app"/>
+      <plugin id="org.eclipse.equinox.common"/>
+      <plugin id="org.eclipse.equinox.ds"/>
+      <plugin id="org.eclipse.equinox.frameworkadmin"/>
+      <plugin id="org.eclipse.equinox.frameworkadmin.equinox"/>
+      <plugin id="org.eclipse.equinox.launcher"/>
+      <plugin id="org.eclipse.equinox.p2.artifact.repository"/>
+      <plugin id="org.eclipse.equinox.p2.core"/>
+      <plugin id="org.eclipse.equinox.p2.director"/>
+      <plugin id="org.eclipse.equinox.p2.director.app"/>
+      <plugin id="org.eclipse.equinox.p2.engine"/>
+      <plugin id="org.eclipse.equinox.p2.garbagecollector"/>
+      <plugin id="org.eclipse.equinox.p2.jarprocessor"/>
+      <plugin id="org.eclipse.equinox.p2.metadata"/>
+      <plugin id="org.eclipse.equinox.p2.metadata.repository"/>
+      <plugin id="org.eclipse.equinox.p2.publisher"/>
+      <plugin id="org.eclipse.equinox.p2.publisher.eclipse"/>
+      <plugin id="org.eclipse.equinox.p2.repository"/>
+      <plugin id="org.eclipse.equinox.p2.repository.tools"/>
+      <plugin id="org.eclipse.equinox.p2.touchpoint.eclipse"/>
+      <plugin id="org.eclipse.equinox.p2.touchpoint.natives"/>
+      <plugin id="org.eclipse.equinox.p2.transport.ecf"/>
+      <plugin id="org.eclipse.equinox.preferences"/>
+      <plugin id="org.eclipse.equinox.registry"/>
+      <plugin id="org.eclipse.equinox.security"/>
+      <plugin id="org.eclipse.equinox.simpleconfigurator"/>
+      <plugin id="org.eclipse.equinox.simpleconfigurator.manipulator"/>
+      <plugin id="org.eclipse.equinox.util"/>
+      <plugin id="org.eclipse.osgi"/>
+      <plugin id="org.eclipse.osgi.services"/>
+      <plugin id="org.sat4j.core"/>
+      <plugin id="org.sat4j.pb"/>
+   </plugins>
+
+   <configurations>
+      <plugin id="org.eclipse.core.runtime" autoStart="true" startLevel="2" />
+      <plugin id="org.eclipse.equinox.ds" autoStart="true" startLevel="3" />
+   </configurations>
+
+</product>

Property changes on: p2-director/p2-director/p2-director.product
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: p2-director/p2-director/pom.xml
===================================================================
--- p2-director/p2-director/pom.xml	(revision 0)
+++ p2-director/p2-director/pom.xml	(revision 0)
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.jboss.jbds.installer</groupId>
+		<artifactId>p2-director</artifactId>
+		<version>7.0.0-SNAPSHOT</version>
+	</parent>
+	<groupId>com.jboss.jbds.installer.p2-director</groupId>
+	<artifactId>p2-director</artifactId>
+	<packaging>eclipse-repository</packaging>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.eclipse.tycho</groupId>
+				<artifactId>tycho-p2-repository-plugin</artifactId>
+				<version>${tychoVersion}</version>
+				<configuration>
+					<includeAllDependencies>true</includeAllDependencies>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.eclipse.tycho</groupId>
+				<artifactId>tycho-p2-director-plugin</artifactId>
+				<version>${tychoVersion}</version>
+				<executions>
+					<execution>
+						<id>materialize-products</id>
+						<goals>
+							<goal>materialize-products</goal>
+						</goals>
+					</execution>
+					<execution>
+						<id>archive-products</id>
+						<goals>
+							<goal>archive-products</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+			    <groupId>org.codehaus.mojo</groupId>
+			    <artifactId>build-helper-maven-plugin</artifactId>
+			    <version>1.7</version>
+			    <executions>
+			        <execution>
+			        	<phase>package</phase>
+			        	<goals>
+							<goal>attach-artifact</goal>
+			        	</goals>
+			        	<configuration>
+			            	<artifacts>
+			            	    <artifact>
+				            	    <file>${project.build.directory}/products/com.jboss.jbds.p2.director.product-win32.win32.x86.zip</file>
+				            	    <type>zip</type>
+				            	    <classifier>dist</classifier>
+				            	</artifact>
+			            	</artifacts>
+			            </configuration>
+			        </execution>
+			    </executions>
+			</plugin>
+		</plugins>
+	</build>
+
+
+</project>
Index: p2-director/pom.xml
===================================================================
--- p2-director/pom.xml	(revision 0)
+++ p2-director/pom.xml	(revision 0)
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.jboss.jbds</groupId>
+    <artifactId>product</artifactId>
+    <version>7.0.0-SNAPSHOT</version>
+  </parent>
+  <groupId>com.jboss.jbds.installer</groupId>
+  <artifactId>p2-director</artifactId>
+  <packaging>pom</packaging>
+
+  <modules>
+      <module>com.jboss.jbds.p2.director</module>
+      <module>p2-director</module>
+  </modules>
+
+  <build>
+       <plugins>
+         <plugin>
+           <groupId>org.jboss.tools.tycho-plugins</groupId>
+           <artifactId>repository-utils</artifactId>
+           <version>0.16.0-SNAPSHOT</version>
+         </plugin>
+       </plugins>
+  </build>
+</project>
Index: p2-director/com.jboss.jbds.p2.director/.classpath
===================================================================
--- p2-director/com.jboss.jbds.p2.director/.classpath	(revision 0)
+++ p2-director/com.jboss.jbds.p2.director/.classpath	(revision 0)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src/"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
Index: p2-director/com.jboss.jbds.p2.director/META-INF/MANIFEST.MF
===================================================================
--- p2-director/com.jboss.jbds.p2.director/META-INF/MANIFEST.MF	(revision 0)
+++ p2-director/com.jboss.jbds.p2.director/META-INF/MANIFEST.MF	(revision 0)
@@ -0,0 +1,16 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Director
+Bundle-SymbolicName: com.jboss.jbds.p2.director;singleton:=true
+Bundle-Version: 7.0.0.qualifier
+Bundle-Vendor: JBoss by RedHat
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
+Require-Bundle: org.eclipse.equinox.p2.director.app;bundle-version="1.0.300",
+ org.eclipse.core.runtime;bundle-version="3.7.0",
+ org.eclipse.equinox.p2.core;bundle-version="2.1.0",
+ org.eclipse.equinox.p2.director;bundle-version="2.1.0",
+ org.eclipse.equinox.p2.engine;bundle-version="2.1.0",
+ org.eclipse.equinox.p2.metadata;bundle-version="2.1.0",
+ org.eclipse.equinox.p2.repository;bundle-version="2.1.0"
+Export-Package: com.jboss.jbds.internal.p2.director
Index: p2-director/com.jboss.jbds.p2.director/.project
===================================================================
--- p2-director/com.jboss.jbds.p2.director/.project	(revision 0)
+++ p2-director/com.jboss.jbds.p2.director/.project	(revision 0)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>com.jboss.jbds.p2.director</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
Index: p2-director/com.jboss.jbds.p2.director/src/com/jboss/jbds/internal/p2/director/InstallerDirectorApplication.java
===================================================================
--- p2-director/com.jboss.jbds.p2.director/src/com/jboss/jbds/internal/p2/director/InstallerDirectorApplication.java	(revision 0)
+++ p2-director/com.jboss.jbds.p2.director/src/com/jboss/jbds/internal/p2/director/InstallerDirectorApplication.java	(revision 0)
@@ -0,0 +1,1299 @@
+package com.jboss.jbds.internal.p2.director;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+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.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.URIUtil;
+import org.eclipse.equinox.app.IApplication;
+import org.eclipse.equinox.app.IApplicationContext;
+import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
+import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
+import org.eclipse.equinox.internal.p2.core.helpers.StringHelper;
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
+import org.eclipse.equinox.internal.p2.director.app.Activator;
+import org.eclipse.equinox.internal.p2.director.app.DirectorApplication;
+import org.eclipse.equinox.internal.p2.director.app.ILog;
+import org.eclipse.equinox.internal.p2.director.app.Messages;
+import org.eclipse.equinox.internal.p2.director.app.PrettyQuery;
+import org.eclipse.equinox.internal.provisional.p2.director.IDirector;
+import org.eclipse.equinox.internal.provisional.p2.director.PlanExecutionHelper;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.equinox.p2.core.IProvisioningAgentProvider;
+import org.eclipse.equinox.p2.core.ProvisionException;
+import org.eclipse.equinox.p2.core.UIServices;
+import org.eclipse.equinox.p2.engine.IEngine;
+import org.eclipse.equinox.p2.engine.IProfile;
+import org.eclipse.equinox.p2.engine.IProfileRegistry;
+import org.eclipse.equinox.p2.engine.IProvisioningPlan;
+import org.eclipse.equinox.p2.engine.PhaseSetFactory;
+import org.eclipse.equinox.p2.engine.ProvisioningContext;
+import org.eclipse.equinox.p2.engine.query.UserVisibleRootQuery;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.metadata.IVersionedId;
+import org.eclipse.equinox.p2.metadata.Version;
+import org.eclipse.equinox.p2.metadata.VersionRange;
+import org.eclipse.equinox.p2.metadata.VersionedId;
+import org.eclipse.equinox.p2.planner.IPlanner;
+import org.eclipse.equinox.p2.planner.IProfileChangeRequest;
+import org.eclipse.equinox.p2.query.Collector;
+import org.eclipse.equinox.p2.query.IQuery;
+import org.eclipse.equinox.p2.query.IQueryResult;
+import org.eclipse.equinox.p2.query.IQueryable;
+import org.eclipse.equinox.p2.query.QueryUtil;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
+import org.eclipse.osgi.framework.log.FrameworkLog;
+import org.eclipse.osgi.service.environment.EnvironmentInfo;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+public class InstallerDirectorApplication extends  DirectorApplication {
+	class AvoidTrustPromptService extends UIServices {
+		@Override
+		public AuthenticationInfo getUsernamePassword(String location) {
+			return null;
+		}
+
+		@Override
+		public AuthenticationInfo getUsernamePassword(String location, AuthenticationInfo previousInfo) {
+			return null;
+		}
+
+		@Override
+		public TrustInfo getTrustInfo(Certificate[][] untrustedChain, String[] unsignedDetail) {
+			return new TrustInfo(null, false, true);
+		}
+	}
+
+	class LocationQueryable implements IQueryable<IInstallableUnit> {
+		private URI location;
+
+		public LocationQueryable(URI location) {
+			this.location = location;
+			Assert.isNotNull(location);
+		}
+
+		public IQueryResult<IInstallableUnit> query(IQuery<IInstallableUnit> query, IProgressMonitor monitor) {
+			return getInstallableUnits(location, query, monitor);
+		}
+	}
+
+	private static class CommandLineOption {
+		private final String[] identifiers;
+		private final String optionSyntaxString;
+		private final String helpString;
+
+		CommandLineOption(String[] identifiers, String optionSyntaxString, String helpString) {
+			this.identifiers = identifiers;
+			this.optionSyntaxString = optionSyntaxString;
+			this.helpString = helpString;
+		}
+
+		boolean isOption(String opt) {
+			int idx = identifiers.length;
+			while (--idx >= 0)
+				if (identifiers[idx].equalsIgnoreCase(opt))
+					return true;
+			return false;
+		}
+
+		void appendHelp(PrintStream out) {
+			out.print(identifiers[0]);
+			for (int idx = 1; idx < identifiers.length; ++idx) {
+				out.print(" | "); //$NON-NLS-1$
+				out.print(identifiers[idx]);
+			}
+			if (optionSyntaxString != null) {
+				out.print(' ');
+				out.print(optionSyntaxString);
+			}
+			out.println();
+			out.print("  "); //$NON-NLS-1$
+			out.println(helpString);
+		}
+	}
+
+	private static final CommandLineOption OPTION_HELP = new CommandLineOption(new String[] {"-help", "-h", "-?"}, null, Messages.Help_Prints_this_command_line_help); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	private static final CommandLineOption OPTION_LIST = new CommandLineOption(new String[] {"-list", "-l"}, Messages.Help_lb_lt_comma_separated_list_gt_rb, Messages.Help_List_all_IUs_found_in_repos); //$NON-NLS-1$ //$NON-NLS-2$
+	private static final CommandLineOption OPTION_LIST_INSTALLED = new CommandLineOption(new String[] {"-listInstalledRoots", "-lir"}, null, Messages.Help_List_installed_roots); //$NON-NLS-1$ //$NON-NLS-2$	
+	private static final CommandLineOption OPTION_INSTALL_IU = new CommandLineOption(new String[] {"-installIU", "-installIUs", "-i"}, Messages.Help_lt_comma_separated_list_gt, Messages.Help_Installs_the_listed_IUs); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	private static final CommandLineOption OPTION_UNINSTALL_IU = new CommandLineOption(new String[] {"-uninstallIU", "-uninstallIUs", "-u"}, Messages.Help_lt_comma_separated_list_gt, Messages.Help_Uninstalls_the_listed_IUs); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	private static final CommandLineOption OPTION_REVERT = new CommandLineOption(new String[] {"-revert"}, Messages.Help_lt_comma_separated_list_gt, Messages.Help_Revert_to_previous_state); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_DESTINATION = new CommandLineOption(new String[] {"-destination", "-d"}, Messages.Help_lt_path_gt, Messages.Help_The_folder_in_which_the_targetd_product_is_located); //$NON-NLS-1$ //$NON-NLS-2$
+	private static final CommandLineOption OPTION_METADATAREPOS = new CommandLineOption(new String[] {"-metadatarepository", "metadatarepositories", "-m"}, Messages.Help_lt_comma_separated_list_gt, Messages.Help_A_list_of_URLs_denoting_metadata_repositories); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	private static final CommandLineOption OPTION_ARTIFACTREPOS = new CommandLineOption(new String[] {"-artifactrepository", "artifactrepositories", "-a"}, Messages.Help_lt_comma_separated_list_gt, Messages.Help_A_list_of_URLs_denoting_artifact_repositories); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	private static final CommandLineOption OPTION_REPOSITORIES = new CommandLineOption(new String[] {"-repository", "repositories", "-r"}, Messages.Help_lt_comma_separated_list_gt, Messages.Help_A_list_of_URLs_denoting_colocated_repositories); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	private static final CommandLineOption OPTION_VERIFY_ONLY = new CommandLineOption(new String[] {"-verifyOnly"}, null, Messages.Help_Only_verify_dont_install); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_PROFILE = new CommandLineOption(new String[] {"-profile", "-p"}, Messages.Help_lt_name_gt, Messages.Help_Defines_what_profile_to_use_for_the_actions); //$NON-NLS-1$ //$NON-NLS-2$
+	private static final CommandLineOption OPTION_FLAVOR = new CommandLineOption(new String[] {"-flavor", "-f"}, Messages.Help_lt_name_gt, Messages.Help_Defines_flavor_to_use_for_created_profile); //$NON-NLS-1$ //$NON-NLS-2$
+	private static final CommandLineOption OPTION_SHARED = new CommandLineOption(new String[] {"-shared", "-s"}, Messages.Help_lb_lt_path_gt_rb, Messages.Help_Use_a_shared_location_for_the_install); //$NON-NLS-1$ //$NON-NLS-2$
+	private static final CommandLineOption OPTION_BUNDLEPOOL = new CommandLineOption(new String[] {"-bundlepool", "-b"}, Messages.Help_lt_path_gt, Messages.Help_The_location_where_the_plugins_and_features_will_be_stored); //$NON-NLS-1$ //$NON-NLS-2$
+	private static final CommandLineOption OPTION_IU_PROFILE_PROPS = new CommandLineOption(new String[] {"-iuProfileproperties"}, Messages.Help_lt_path_gt, Messages.Help_path_to_IU_profile_properties_file); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_PROFILE_PROPS = new CommandLineOption(new String[] {"-profileproperties"}, Messages.Help_lt_comma_separated_list_gt, Messages.Help_A_list_of_properties_in_the_form_key_value_pairs); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_ROAMING = new CommandLineOption(new String[] {"-roaming"}, null, Messages.Help_Indicates_that_the_product_can_be_moved); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_P2_OS = new CommandLineOption(new String[] {"-p2.os"}, null, Messages.Help_The_OS_when_profile_is_created); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_P2_WS = new CommandLineOption(new String[] {"-p2.ws"}, null, Messages.Help_The_WS_when_profile_is_created); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_P2_ARCH = new CommandLineOption(new String[] {"-p2.arch"}, null, Messages.Help_The_ARCH_when_profile_is_created); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_P2_NL = new CommandLineOption(new String[] {"-p2.nl"}, null, Messages.Help_The_NL_when_profile_is_created); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_PURGEHISTORY = new CommandLineOption(new String[] {"-purgeHistory"}, null, Messages.Help_Purge_the_install_registry); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_FOLLOW_REFERENCES = new CommandLineOption(new String[] {"-followReferences"}, null, Messages.Help_Follow_references); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_TAG = new CommandLineOption(new String[] {"-tag"}, Messages.Help_lt_name_gt, Messages.Help_Defines_a_tag_for_provisioning_session); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_LIST_TAGS = new CommandLineOption(new String[] {"-listTags"}, null, Messages.Help_List_Tags); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_DOWNLOAD_ONLY = new CommandLineOption(new String[] {"-downloadOnly"}, null, Messages.Help_Download_Only); //$NON-NLS-1$
+	private static final CommandLineOption OPTION_IGNORED = new CommandLineOption(new String[] {"-showLocation", "-eclipse.password", "-eclipse.keyring"}, null, ""); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
+
+	private static final Integer EXIT_ERROR = new Integer(13);
+	static private final String FLAVOR_DEFAULT = "tooling"; //$NON-NLS-1$
+	static private final String PROP_P2_PROFILE = "eclipse.p2.profile"; //$NON-NLS-1$
+	static private final String NO_ARTIFACT_REPOSITORIES_AVAILABLE = "noArtifactRepositoriesAvailable"; //$NON-NLS-1$
+
+	private static final String FOLLOW_ARTIFACT_REPOSITORY_REFERENCES = "org.eclipse.equinox.p2.director.followArtifactRepositoryReferences"; //$NON-NLS-1$
+	private static final String LIST_GROUPS_SHORTCUT = "Q:GROUP"; //$NON-NLS-1$ 
+	private static final String QUERY_SEPARATOR = "Q:"; //$NON-NLS-1$
+	private static final String QUERY_SEPARATOR_SMALL = "q:"; //$NON-NLS-1$
+
+	public static final String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
+
+	private static void getURIs(List<URI> uris, String spec) throws CoreException {
+		if (spec == null)
+			return;
+		String[] urlSpecs = StringHelper.getArrayFromString(spec, ',');
+		for (int i = 0; i < urlSpecs.length; i++) {
+			try {
+				uris.add(new URI(urlSpecs[i]));
+			} catch (URISyntaxException e1) {
+				try {
+					uris.add(URIUtil.fromString(urlSpecs[i]));
+				} catch (URISyntaxException e) {
+					throw new ProvisionException(NLS.bind(Messages.unable_to_parse_0_to_uri_1, urlSpecs[i], e.getMessage()));
+				}
+			}
+
+		}
+	}
+
+	private static String getRequiredArgument(String[] args, int argIdx) throws CoreException {
+		if (argIdx < args.length) {
+			String arg = args[argIdx];
+			if (!arg.startsWith("-")) //$NON-NLS-1$
+				return arg;
+		}
+		throw new ProvisionException(NLS.bind(Messages.option_0_requires_an_argument, args[argIdx - 1]));
+	}
+
+	private static String getOptionalArgument(String[] args, int argIdx) {
+		//Look ahead to the next argument
+		++argIdx;
+		if (argIdx < args.length) {
+			String arg = args[argIdx];
+			if (!arg.startsWith("-")) //$NON-NLS-1$
+				return arg;
+		}
+		return null;
+	}
+
+	private static void parseIUsArgument(List<IQuery<IInstallableUnit>> vnames, String arg) {
+		String[] roots = StringHelper.getArrayFromString(arg, ',');
+		for (int i = 0; i < roots.length; ++i) {
+			if (roots[i].equalsIgnoreCase(LIST_GROUPS_SHORTCUT)) {
+				vnames.add(new PrettyQuery<IInstallableUnit>(QueryUtil.createIUGroupQuery(), "All groups")); //$NON-NLS-1$
+				continue;
+			}
+			if (roots[i].startsWith(QUERY_SEPARATOR) || roots[i].startsWith(QUERY_SEPARATOR_SMALL)) {
+				String queryString = roots[i].substring(2);
+				vnames.add(new PrettyQuery<IInstallableUnit>(QueryUtil.createQuery(queryString, new Object[0]), queryString));
+				continue;
+			}
+			IVersionedId vId = VersionedId.parse(roots[i]);
+			Version v = vId.getVersion();
+			IQuery<IInstallableUnit> query = new PrettyQuery<IInstallableUnit>(QueryUtil.createIUQuery(vId.getId(), Version.emptyVersion.equals(v) ? VersionRange.emptyRange : new VersionRange(v, true, v, true)), roots[i]);
+			vnames.add(query);
+		}
+	}
+
+	private static File processFileArgument(String arg) {
+		if (arg.startsWith("file:")) //$NON-NLS-1$
+			arg = arg.substring(5);
+
+		// we create a path object here to handle ../ entries in the middle of paths
+		return Path.fromOSString(arg).toFile();
+	}
+
+	private IArtifactRepositoryManager artifactManager;
+	IMetadataRepositoryManager metadataManager;
+
+	private URI[] artifactReposForRemoval;
+	private URI[] metadataReposForRemoval;
+
+	private final List<URI> artifactRepositoryLocations = new ArrayList<URI>();
+	private final List<URI> metadataRepositoryLocations = new ArrayList<URI>();
+	private final List<IQuery<IInstallableUnit>> rootsToInstall = new ArrayList<IQuery<IInstallableUnit>>();
+	private final List<IQuery<IInstallableUnit>> rootsToUninstall = new ArrayList<IQuery<IInstallableUnit>>();
+	private final List<IQuery<IInstallableUnit>> rootsToList = new ArrayList<IQuery<IInstallableUnit>>();
+
+	private File bundlePool = null;
+	private File destination;
+	private File sharedLocation;
+	private String flavor;
+	private boolean printHelpInfo = false;
+	private boolean printIUList = false;
+	private boolean printRootIUList = false;
+	private boolean printTags = false;
+
+	private String revertToPreviousState = NOTHING_TO_REVERT_TO;
+	private static String NOTHING_TO_REVERT_TO = "-1"; //$NON-NLS-1$
+	private static String REVERT_TO_PREVIOUS = "0"; //$NON-NLS-1$
+	private boolean verifyOnly = false;
+	private boolean roamingProfile = false;
+	private boolean purgeRegistry = false;
+	private boolean stackTrace = false;
+	private boolean followReferences = false;
+	private boolean downloadOnly = false;
+	private String profileId;
+	private String profileProperties; // a comma-separated list of property pairs "tag=value"
+	private String iuProfileProperties; // path to Properties file with IU profile properties
+	private String ws;
+	private String os;
+	private String arch;
+	private String nl;
+	private String tag;
+
+	private IEngine engine;
+	private boolean noProfileId = false;
+	private PackageAdmin packageAdmin;
+	private ServiceReference<PackageAdmin> packageAdminRef;
+	private IPlanner planner;
+	private ILog log = null;
+
+	private IProvisioningAgent targetAgent;
+	private boolean noArtifactRepositorySpecified = false;
+
+	private ProfileChangeRequest buildProvisioningRequest(IProfile profile, Collection<IInstallableUnit> installs, Collection<IInstallableUnit> uninstalls) {
+		ProfileChangeRequest request = new ProfileChangeRequest(profile);
+		markRoots(request, installs);
+		markRoots(request, uninstalls);
+		request.addAll(installs);
+		request.removeAll(uninstalls);
+		buildIUProfileProperties(request);
+		return request;
+	}
+
+	// read the given file into a Properties object
+	private Properties loadProperties(File file) {
+		if (!file.exists()) {
+			// log a warning and return
+			logStatus(new Status(IStatus.WARNING, Activator.ID, NLS.bind(Messages.File_does_not_exist, file.getAbsolutePath())));
+			return null;
+		}
+		Properties properties = new Properties();
+		InputStream input = null;
+		try {
+			input = new BufferedInputStream(new FileInputStream(file));
+			properties.load(input);
+		} catch (IOException e) {
+			logFailure(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.Problem_loading_file, file.getAbsolutePath()), e));
+			return null;
+		} finally {
+			if (input != null)
+				try {
+					input.close();
+				} catch (IOException e) {
+					// ignore
+				}
+		}
+		return properties;
+	}
+
+	private void buildIUProfileProperties(IProfileChangeRequest request) {
+		final String KEYWORD_KEY = "key"; //$NON-NLS-1$
+		final String KEYWORD_VALUE = "value"; //$NON-NLS-1$
+		final String KEYWORD_VERSION = "version"; //$NON-NLS-1$
+
+		if (iuProfileProperties == null)
+			return;
+
+		// read the file into a Properties object for easier processing
+		Properties properties = loadProperties(new File(iuProfileProperties));
+		if (properties == null)
+			return;
+
+		// format for a line in the properties input file is <id>.<keyword>.<uniqueNumber>=value
+		// id is the IU id
+		// keyword is either "key" or "value"
+		// uniqueNumber is used to group keys and values together
+		Set<String> alreadyProcessed = new HashSet<String>();
+		for (Iterator<Object> iter = properties.keySet().iterator(); iter.hasNext();) {
+			String line = (String) iter.next();
+			int index = line.lastIndexOf('.');
+			if (index == -1)
+				continue;
+			int num = -1;
+			String id = null;
+			try {
+				num = Integer.parseInt(line.substring(index + 1));
+				line = line.substring(0, index);
+				index = line.lastIndexOf('.');
+				if (index == -1)
+					continue;
+				// skip over the keyword
+				id = line.substring(0, index);
+			} catch (NumberFormatException e) {
+				logStatus(new Status(IStatus.WARNING, Activator.ID, NLS.bind(Messages.Bad_format, line, iuProfileProperties), e));
+				continue;
+			} catch (IndexOutOfBoundsException e) {
+				logStatus(new Status(IStatus.WARNING, Activator.ID, NLS.bind(Messages.Bad_format, line, iuProfileProperties), e));
+				continue;
+			}
+
+			String versionLine = id + '.' + KEYWORD_VERSION + '.' + num;
+			String keyLine = id + '.' + KEYWORD_KEY + '.' + num;
+			String valueLine = id + '.' + KEYWORD_VALUE + '.' + num;
+
+			if (alreadyProcessed.contains(versionLine) || alreadyProcessed.contains(keyLine) || alreadyProcessed.contains(valueLine))
+				continue;
+
+			// skip over this key/value pair next time we see it
+			alreadyProcessed.add(versionLine);
+			alreadyProcessed.add(keyLine);
+			alreadyProcessed.add(valueLine);
+
+			Version version = Version.create((String) properties.get(versionLine)); // it is ok to have a null version
+			String key = (String) properties.get(keyLine);
+			String value = (String) properties.get(valueLine);
+
+			if (key == null || value == null) {
+				String message = NLS.bind(Messages.Unmatched_iu_profile_property_key_value, key + '/' + value);
+				logStatus(new Status(IStatus.WARNING, Activator.ID, message));
+				continue;
+			}
+
+			// lookup the IU - a null version matches all versions
+			IQuery<IInstallableUnit> query = QueryUtil.createIUQuery(id, version);
+			// if we don't have a version the choose the latest. 
+			if (version == null)
+				query = QueryUtil.createLatestQuery(query);
+			IQueryResult<IInstallableUnit> qr = getInstallableUnits(null, query, null);
+			if (qr.isEmpty()) {
+				String msg = NLS.bind(Messages.Cannot_set_iu_profile_property_iu_does_not_exist, id + '/' + version);
+				logStatus(new Status(IStatus.WARNING, Activator.ID, msg));
+				continue;
+			}
+			IInstallableUnit iu = qr.iterator().next();
+			request.setInstallableUnitProfileProperty(iu, key, value);
+		}
+
+	}
+
+	private void cleanupRepositories() {
+		if (artifactReposForRemoval != null && artifactManager != null) {
+			for (int i = 0; i < artifactReposForRemoval.length && artifactReposForRemoval[i] != null; i++) {
+				artifactManager.removeRepository(artifactReposForRemoval[i]);
+			}
+		}
+		if (metadataReposForRemoval != null && metadataManager != null) {
+			for (int i = 0; i < metadataReposForRemoval.length && metadataReposForRemoval[i] != null; i++) {
+				metadataManager.removeRepository(metadataReposForRemoval[i]);
+			}
+		}
+	}
+
+	private IQueryResult<IInstallableUnit> collectRootIUs(IQuery<IInstallableUnit> query) {
+		IProgressMonitor nullMonitor = new NullProgressMonitor();
+
+		int top = metadataRepositoryLocations.size();
+		if (top == 0)
+			return getInstallableUnits(null, query, nullMonitor);
+
+		List<IQueryable<IInstallableUnit>> locationQueryables = new ArrayList<IQueryable<IInstallableUnit>>(top);
+		for (int i = 0; i < top; i++)
+			locationQueryables.add(new LocationQueryable(metadataRepositoryLocations.get(i)));
+		return QueryUtil.compoundQueryable(locationQueryables).query(query, nullMonitor);
+	}
+
+	private Collection<IInstallableUnit> collectRoots(IProfile profile, List<IQuery<IInstallableUnit>> rootNames, boolean forInstall) throws CoreException {
+		ArrayList<IInstallableUnit> allRoots = new ArrayList<IInstallableUnit>();
+		for (IQuery<IInstallableUnit> rootQuery : rootNames) {
+			IQueryResult<IInstallableUnit> roots = null;
+			if (forInstall)
+				roots = collectRootIUs(QueryUtil.createLatestQuery(rootQuery));
+
+			if (roots == null || roots.isEmpty())
+				roots = profile.query(rootQuery, new NullProgressMonitor());
+
+			Iterator<IInstallableUnit> itor = roots.iterator();
+			if (!itor.hasNext())
+				throw new CoreException(new Status(IStatus.ERROR, org.eclipse.equinox.internal.p2.director.app.Activator.ID, NLS.bind(Messages.Missing_IU, rootQuery)));
+			do {
+				allRoots.add(itor.next());
+			} while (itor.hasNext());
+		}
+		return allRoots;
+	}
+
+	synchronized Bundle getBundle(String symbolicName) {
+		if (packageAdmin == null)
+			return null;
+
+		Bundle[] bundles = packageAdmin.getBundles(symbolicName, null);
+		if (bundles == null)
+			return null;
+		//Return the first bundle that is not installed or uninstalled
+		for (int i = 0; i < bundles.length; i++) {
+			if ((bundles[i].getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0) {
+				return bundles[i];
+			}
+		}
+		return null;
+	}
+
+	private String getEnvironmentProperty() {
+		HashMap<String, String> values = new HashMap<String, String>();
+		if (os != null)
+			values.put("osgi.os", os); //$NON-NLS-1$
+		if (nl != null)
+			values.put("osgi.nl", nl); //$NON-NLS-1$
+		if (ws != null)
+			values.put("osgi.ws", ws); //$NON-NLS-1$
+		if (arch != null)
+			values.put("osgi.arch", arch); //$NON-NLS-1$
+		return values.isEmpty() ? null : toString(values);
+	}
+
+	private IProfile getProfile() {
+		IProfileRegistry profileRegistry = (IProfileRegistry) targetAgent.getService(IProfileRegistry.SERVICE_NAME);
+		if (profileId == null) {
+			profileId = IProfileRegistry.SELF;
+			noProfileId = true;
+		}
+		return profileRegistry.getProfile(profileId);
+	}
+
+	private IProfile initializeProfile() throws CoreException {
+		IProfile profile = getProfile();
+		if (profile == null) {
+			if (destination == null)
+				missingArgument("destination"); //$NON-NLS-1$
+			if (flavor == null)
+				flavor = System.getProperty("eclipse.p2.configurationFlavor", FLAVOR_DEFAULT); //$NON-NLS-1$
+
+			Map<String, String> props = new HashMap<String, String>();
+			props.put(IProfile.PROP_INSTALL_FOLDER, destination.toString());
+			if (bundlePool == null)
+				props.put(IProfile.PROP_CACHE, sharedLocation == null ? destination.getAbsolutePath() : sharedLocation.getAbsolutePath());
+			else
+				props.put(IProfile.PROP_CACHE, bundlePool.getAbsolutePath());
+			if (roamingProfile)
+				props.put(IProfile.PROP_ROAMING, Boolean.TRUE.toString());
+
+			String env = getEnvironmentProperty();
+			if (env != null)
+				props.put(IProfile.PROP_ENVIRONMENTS, env);
+			if (profileProperties != null)
+				putProperties(profileProperties, props);
+			profile = ((IProfileRegistry) targetAgent.getService(IProfileRegistry.SERVICE_NAME)).addProfile(profileId, props);
+		}
+		return profile;
+	}
+
+	private void initializeRepositories() throws CoreException {
+		if (rootsToInstall.isEmpty() && revertToPreviousState == NOTHING_TO_REVERT_TO && !printIUList)
+			// Not much point initializing repositories if we have nothing to install
+			return;
+		if (artifactRepositoryLocations == null)
+			missingArgument("-artifactRepository"); //$NON-NLS-1$
+
+		artifactManager = (IArtifactRepositoryManager) targetAgent.getService(IArtifactRepositoryManager.SERVICE_NAME);
+		if (artifactManager == null)
+			throw new ProvisionException(Messages.Application_NoManager);
+
+		int removalIdx = 0;
+		boolean anyValid = false; // do we have any valid repos or did they all fail to load?
+		artifactReposForRemoval = new URI[artifactRepositoryLocations.size()];
+		for (int i = 0; i < artifactRepositoryLocations.size(); i++) {
+			URI location = artifactRepositoryLocations.get(i);
+			try {
+				if (!artifactManager.contains(location)) {
+					artifactManager.loadRepository(location, null);
+					artifactReposForRemoval[removalIdx++] = location;
+				}
+				anyValid = true;
+			} catch (ProvisionException e) {
+				//one of the repositories did not load
+				logStatus(e.getStatus());
+			}
+		}
+		if (!anyValid)
+			noArtifactRepositorySpecified = true;
+
+		if (metadataRepositoryLocations == null)
+			missingArgument("metadataRepository"); //$NON-NLS-1$
+
+		metadataManager = (IMetadataRepositoryManager) targetAgent.getService(IMetadataRepositoryManager.SERVICE_NAME);
+		if (metadataManager == null)
+			throw new ProvisionException(Messages.Application_NoManager);
+
+		removalIdx = 0;
+		anyValid = false; // do we have any valid repos or did they all fail to load?
+		int top = metadataRepositoryLocations.size();
+		metadataReposForRemoval = new URI[top];
+		for (int i = 0; i < top; i++) {
+			URI location = metadataRepositoryLocations.get(i);
+			try {
+				if (!metadataManager.contains(location)) {
+					metadataManager.loadRepository(location, null);
+					metadataReposForRemoval[removalIdx++] = location;
+				}
+				anyValid = true;
+			} catch (ProvisionException e) {
+				//one of the repositories did not load
+				logStatus(e.getStatus());
+			}
+		}
+		if (!anyValid)
+			//all repositories failed to load
+			throw new ProvisionException(Messages.Application_NoRepositories);
+	}
+
+	private void initializeServices() throws CoreException {
+		BundleContext context = Activator.getContext();
+		packageAdminRef = context.getServiceReference(PackageAdmin.class);
+		packageAdmin = context.getService(packageAdminRef);
+		ServiceReference<IProvisioningAgentProvider> agentProviderRef = context.getServiceReference(IProvisioningAgentProvider.class);
+		IProvisioningAgentProvider provider = context.getService(agentProviderRef);
+		URI p2DataArea;
+		if (destination != null || sharedLocation != null) {
+			File dataAreaFile = sharedLocation == null ? new File(destination, "p2") : sharedLocation;//$NON-NLS-1$
+			p2DataArea = dataAreaFile.toURI();
+		} else {
+			p2DataArea = null;
+		}
+		targetAgent = provider.createAgent(p2DataArea);
+		targetAgent.registerService(IProvisioningAgent.INSTALLER_AGENT, provider.createAgent(null));
+
+		context.ungetService(agentProviderRef);
+		if (profileId == null) {
+			if (destination != null) {
+				File configIni = new File(destination, "configuration/config.ini"); //$NON-NLS-1$
+				InputStream in = null;
+				try {
+					Properties ciProps = new Properties();
+					in = new BufferedInputStream(new FileInputStream(configIni));
+					ciProps.load(in);
+					profileId = ciProps.getProperty(PROP_P2_PROFILE);
+				} catch (IOException e) {
+					// Ignore
+				} finally {
+					if (in != null)
+						try {
+							in.close();
+						} catch (IOException e) {
+							// Ignore;
+						}
+				}
+				if (profileId == null)
+					profileId = destination.toString();
+			}
+		}
+		if (profileId != null)
+			targetAgent.registerService(PROP_P2_PROFILE, profileId);
+		else
+			targetAgent.unregisterService(PROP_P2_PROFILE, null);
+
+		IDirector director = (IDirector) targetAgent.getService(IDirector.SERVICE_NAME);
+		if (director == null)
+			throw new ProvisionException(Messages.Missing_director);
+
+		planner = (IPlanner) targetAgent.getService(IPlanner.SERVICE_NAME);
+		if (planner == null)
+			throw new ProvisionException(Messages.Missing_planner);
+
+		engine = (IEngine) targetAgent.getService(IEngine.SERVICE_NAME);
+		if (engine == null)
+			throw new ProvisionException(Messages.Missing_Engine);
+
+		targetAgent.registerService(UIServices.SERVICE_NAME, new AvoidTrustPromptService());
+	}
+
+	private void logStatus(IStatus status) {
+		if (log != null)
+			log.log(status);
+		else
+			LogHelper.log(status);
+	}
+
+	private void printMessage(String message) {
+		if (log != null)
+			log.log(message);
+		else
+			System.out.println(message);
+	}
+
+	private void logFailure(IStatus status) {
+		if (log == null) {
+			FrameworkLog frameworkLog = (FrameworkLog) ServiceHelper.getService(Activator.getContext(), FrameworkLog.class.getName());
+			if (frameworkLog != null)
+				System.err.println("Application failed, log file location: " + frameworkLog.getFile()); //$NON-NLS-1$
+		}
+
+		logStatus(status);
+	}
+
+	private void markRoots(IProfileChangeRequest request, Collection<IInstallableUnit> roots) {
+		for (IInstallableUnit root : roots) {
+			request.setInstallableUnitProfileProperty(root, IProfile.PROP_PROFILE_ROOT_IU, Boolean.TRUE.toString());
+		}
+	}
+
+	private void missingArgument(String argumentName) throws CoreException {
+		throw new ProvisionException(NLS.bind(Messages.Missing_Required_Argument, argumentName));
+	}
+
+	private void performList() throws CoreException {
+		if (metadataRepositoryLocations.isEmpty())
+			missingArgument("metadataRepository"); //$NON-NLS-1$
+
+		ArrayList<IInstallableUnit> allRoots = new ArrayList<IInstallableUnit>();
+		if (rootsToList.size() == 0) {
+			Iterator<IInstallableUnit> roots = collectRootIUs(QueryUtil.createIUAnyQuery()).iterator();
+			while (roots.hasNext())
+				allRoots.add(roots.next());
+		} else {
+			for (IQuery<IInstallableUnit> root : rootsToList) {
+				Iterator<IInstallableUnit> roots = collectRootIUs(root).iterator();
+				while (roots.hasNext())
+					allRoots.add(roots.next());
+			}
+		}
+
+		Collections.sort(allRoots);
+		for (IInstallableUnit iu : allRoots) {
+			System.out.println(iu.getId() + '=' + iu.getVersion());
+		}
+	}
+
+	private void performProvisioningActions() throws CoreException {
+		IProfile profile = initializeProfile();
+		Collection<IInstallableUnit> installs = collectRoots(profile, rootsToInstall, true);
+		Collection<IInstallableUnit> uninstalls = collectRoots(profile, rootsToUninstall, false);
+
+		// keep this result status in case there is a problem so we can report it to the user
+		boolean wasRoaming = Boolean.valueOf(profile.getProperty(IProfile.PROP_ROAMING)).booleanValue();
+		try {
+			updateRoamingProperties(profile);
+			ProvisioningContext context = new ProvisioningContext(targetAgent);
+			context.setMetadataRepositories(metadataRepositoryLocations.toArray(new URI[metadataRepositoryLocations.size()]));
+			context.setArtifactRepositories(artifactRepositoryLocations.toArray(new URI[artifactRepositoryLocations.size()]));
+			context.setProperty(ProvisioningContext.FOLLOW_REPOSITORY_REFERENCES, String.valueOf(followReferences));
+			context.setProperty(FOLLOW_ARTIFACT_REPOSITORY_REFERENCES, String.valueOf(followReferences));
+			ProfileChangeRequest request = buildProvisioningRequest(profile, installs, uninstalls);
+			printRequest(request);
+			planAndExecute(profile, context, request);
+		} finally {
+			// if we were originally were set to be roaming and we changed it, change it back before we return
+			if (wasRoaming && !Boolean.valueOf(profile.getProperty(IProfile.PROP_ROAMING)).booleanValue())
+				setRoaming(profile);
+		}
+	}
+
+	private void planAndExecute(IProfile profile, ProvisioningContext context, ProfileChangeRequest request) throws CoreException {
+		IProvisioningPlan result = planner.getProvisioningPlan(request, context, new NullProgressMonitor());
+		IStatus operationStatus = result.getStatus();
+		if (!operationStatus.isOK())
+			throw new CoreException(operationStatus);
+		executePlan(context, result);
+	}
+
+	private void executePlan(ProvisioningContext context, IProvisioningPlan result) throws CoreException {
+		IStatus operationStatus;
+		if (!verifyOnly) {
+			if (!downloadOnly)
+				operationStatus = PlanExecutionHelper.executePlan(result, engine, context, new NullProgressMonitor() {
+					public void subTask(String name) {
+						System.out.println(name);
+						File cancel = new File(destination, "cancel");
+						if(cancel.canRead()) {
+							throw new RuntimeException("Installation canceled");
+						}
+					}
+				});
+			else
+				operationStatus = PlanExecutionHelper.executePlan(result, engine, PhaseSetFactory.createPhaseSetIncluding(new String[] {PhaseSetFactory.PHASE_COLLECT, PhaseSetFactory.PHASE_CHECK_TRUST}), context, new NullProgressMonitor() {
+					public void subTask(String name) {
+						System.out.println(name);
+						File cancel = new File(destination, "cancel");
+						if(cancel.canRead()) {
+							throw new RuntimeException("Installation canceled");
+						}
+					}
+				}
+			);
+			if (!operationStatus.isOK()) {
+				if (noArtifactRepositorySpecified && hasNoRepositoryFound(operationStatus))
+					throw new ProvisionException(Messages.Application_NoRepositories);
+				throw new CoreException(operationStatus);
+			}
+			if (tag != null) {
+				long newState = result.getProfile().getTimestamp();
+				IProfileRegistry registry = (IProfileRegistry) targetAgent.getService(IProfileRegistry.SERVICE_NAME);
+				registry.setProfileStateProperty(result.getProfile().getProfileId(), newState, IProfile.STATE_PROP_TAG, tag);
+			}
+		}
+	}
+
+	private boolean hasNoRepositoryFound(IStatus status) {
+		if (status.getException() != null && NO_ARTIFACT_REPOSITORIES_AVAILABLE.equals(status.getException().getMessage()))
+			return true;
+		if (status.isMultiStatus()) {
+			for (IStatus child : status.getChildren()) {
+				if (hasNoRepositoryFound(child))
+					return true;
+			}
+		}
+		return false;
+	}
+
+	private void printRequest(ProfileChangeRequest request) {
+		Collection<IInstallableUnit> toAdd = request.getAdditions();
+		for (IInstallableUnit added : toAdd) {
+			printMessage(NLS.bind(Messages.Installing, added.getId(), added.getVersion()));
+		}
+		Collection<IInstallableUnit> toRemove = request.getRemovals();
+		for (IInstallableUnit removed : toRemove) {
+			printMessage(NLS.bind(Messages.Uninstalling, removed.getId(), removed.getVersion()));
+		}
+	}
+
+	public void processArguments(String[] args) throws CoreException {
+		if (args == null) {
+			printHelpInfo = true;
+			return;
+		}
+
+		// Set platform environment defaults
+		EnvironmentInfo info = (EnvironmentInfo) ServiceHelper.getService(Activator.getContext(), EnvironmentInfo.class.getName());
+		os = info.getOS();
+		ws = info.getWS();
+		nl = info.getNL();
+		arch = info.getOSArch();
+
+		for (int i = 0; i < args.length; i++) {
+			// check for args without parameters (i.e., a flag arg)
+			String opt = args[i];
+			if (OPTION_LIST.isOption(opt)) {
+				printIUList = true;
+				String optionalArgument = getOptionalArgument(args, i);
+				if (optionalArgument != null) {
+					parseIUsArgument(rootsToList, optionalArgument);
+					i++;
+				}
+				continue;
+			}
+
+			if (OPTION_LIST_INSTALLED.isOption(opt)) {
+				printRootIUList = true;
+				continue;
+			}
+
+			if (OPTION_LIST_TAGS.isOption(opt)) {
+				printTags = true;
+				continue;
+			}
+
+			if (OPTION_DOWNLOAD_ONLY.isOption(opt)) {
+				downloadOnly = true;
+				continue;
+			}
+
+			if (OPTION_HELP.isOption(opt)) {
+				printHelpInfo = true;
+				continue;
+			}
+
+			if (OPTION_INSTALL_IU.isOption(opt)) {
+				parseIUsArgument(rootsToInstall, getRequiredArgument(args, ++i));
+				continue;
+			}
+
+			if (OPTION_UNINSTALL_IU.isOption(opt)) {
+				parseIUsArgument(rootsToUninstall, getRequiredArgument(args, ++i));
+				continue;
+			}
+
+			if (OPTION_REVERT.isOption(opt)) {
+				String targettedState = getOptionalArgument(args, i);
+				if (targettedState == null) {
+					revertToPreviousState = REVERT_TO_PREVIOUS;
+				} else {
+					i++;
+					revertToPreviousState = targettedState;
+				}
+				continue;
+
+			}
+			if (OPTION_PROFILE.isOption(opt)) {
+				profileId = getRequiredArgument(args, ++i);
+				continue;
+			}
+
+			if (OPTION_FLAVOR.isOption(opt)) {
+				flavor = getRequiredArgument(args, ++i);
+				continue;
+			}
+
+			if (OPTION_SHARED.isOption(opt)) {
+				if (++i < args.length) {
+					String nxt = args[i];
+					if (nxt.startsWith("-")) //$NON-NLS-1$
+						--i; // Oops, that's the next option, not an argument
+					else
+						sharedLocation = processFileArgument(nxt);
+				}
+				if (sharedLocation == null)
+					// -shared without an argument means "Use default shared area"
+					sharedLocation = Path.fromOSString(System.getProperty("user.home")).append(".p2/").toFile(); //$NON-NLS-1$ //$NON-NLS-2$
+				continue;
+			}
+
+			if (OPTION_DESTINATION.isOption(opt)) {
+				destination = processFileArgument(getRequiredArgument(args, ++i));
+				continue;
+			}
+
+			if (OPTION_BUNDLEPOOL.isOption(opt)) {
+				bundlePool = processFileArgument(getRequiredArgument(args, ++i));
+				continue;
+			}
+
+			if (OPTION_METADATAREPOS.isOption(opt)) {
+				getURIs(metadataRepositoryLocations, getRequiredArgument(args, ++i));
+				continue;
+			}
+
+			if (OPTION_ARTIFACTREPOS.isOption(opt)) {
+				getURIs(artifactRepositoryLocations, getRequiredArgument(args, ++i));
+				continue;
+			}
+
+			if (OPTION_REPOSITORIES.isOption(opt)) {
+				String arg = getRequiredArgument(args, ++i);
+				getURIs(metadataRepositoryLocations, arg);
+				getURIs(artifactRepositoryLocations, arg);
+				continue;
+			}
+
+			if (OPTION_PROFILE_PROPS.isOption(opt)) {
+				profileProperties = getRequiredArgument(args, ++i);
+				continue;
+			}
+
+			if (OPTION_IU_PROFILE_PROPS.isOption(opt)) {
+				iuProfileProperties = getRequiredArgument(args, ++i);
+				continue;
+			}
+
+			if (OPTION_ROAMING.isOption(opt)) {
+				roamingProfile = true;
+				continue;
+			}
+
+			if (OPTION_VERIFY_ONLY.isOption(opt)) {
+				verifyOnly = true;
+				continue;
+			}
+
+			if (OPTION_PURGEHISTORY.isOption(opt)) {
+				purgeRegistry = true;
+				continue;
+			}
+
+			if (OPTION_FOLLOW_REFERENCES.isOption(opt)) {
+				followReferences = true;
+				continue;
+			}
+
+			if (OPTION_P2_OS.isOption(opt)) {
+				os = getRequiredArgument(args, ++i);
+				continue;
+			}
+
+			if (OPTION_P2_WS.isOption(opt)) {
+				ws = getRequiredArgument(args, ++i);
+				continue;
+			}
+
+			if (OPTION_P2_NL.isOption(opt)) {
+				nl = getRequiredArgument(args, ++i);
+				continue;
+			}
+
+			if (OPTION_P2_ARCH.isOption(opt)) {
+				arch = getRequiredArgument(args, ++i);
+				continue;
+			}
+
+			if (OPTION_TAG.isOption(opt)) {
+				tag = getRequiredArgument(args, ++i);
+				continue;
+			}
+
+			if (OPTION_IGNORED.isOption(opt)) {
+				String optionalArgument = getOptionalArgument(args, i);
+				if (optionalArgument != null) {
+					i++;
+				}
+				continue;
+			}
+			throw new ProvisionException(NLS.bind(Messages.unknown_option_0, opt));
+		}
+
+		if (!printHelpInfo && !printIUList && !printRootIUList && !printTags && !purgeRegistry && rootsToInstall.isEmpty() && rootsToUninstall.isEmpty() && revertToPreviousState == NOTHING_TO_REVERT_TO) {
+			printMessage(Messages.Help_Missing_argument);
+			printHelpInfo = true;
+		}
+	}
+
+	/**
+	 * @param pairs	a comma separated list of tag=value pairs
+	 * @param properties the collection into which the pairs are put
+	 */
+	private void putProperties(String pairs, Map<String, String> properties) {
+		String[] propPairs = StringHelper.getArrayFromString(pairs, ',');
+		for (int i = 0; i < propPairs.length; ++i) {
+			String propPair = propPairs[i];
+			int eqIdx = propPair.indexOf('=');
+			if (eqIdx < 0)
+				continue;
+			String tag = propPair.substring(0, eqIdx).trim();
+			if (tag.length() == 0)
+				continue;
+			String value = propPair.substring(eqIdx + 1).trim();
+			if (value.length() > 0)
+				properties.put(tag, value);
+		}
+	}
+
+	private void cleanupServices() {
+		BundleContext context = Activator.getContext();
+		//dispose agent
+		if (targetAgent != null) {
+			targetAgent.stop();
+			targetAgent = null;
+		}
+		if (packageAdminRef != null)
+			context.ungetService(packageAdminRef);
+	}
+
+	public Object run(String[] args) {
+		long time = System.currentTimeMillis();
+
+		try {
+			processArguments(args);
+			if (printHelpInfo)
+				performHelpInfo();
+			else {
+				initializeServices();
+				initializeRepositories();
+				if (revertToPreviousState != NOTHING_TO_REVERT_TO) {
+					revertToPreviousState();
+				} else if (!(rootsToInstall.isEmpty() && rootsToUninstall.isEmpty()))
+					System.out.println("Installer");
+					performProvisioningActions();
+				if (printIUList)
+					performList();
+				if (printRootIUList)
+					performListInstalledRoots();
+				if (printTags)
+					performPrintTags();
+				if (purgeRegistry)
+					purgeRegistry();
+				printMessage(NLS.bind(Messages.Operation_complete, new Long(System.currentTimeMillis() - time)));
+			}
+			return IApplication.EXIT_OK;
+		} catch (CoreException e) {
+			printMessage(Messages.Operation_failed);
+			deeplyPrint(e.getStatus(), System.err, 0);
+			logFailure(e.getStatus());
+			//set empty exit data to suppress error dialog from launcher
+			setSystemProperty("eclipse.exitdata", ""); //$NON-NLS-1$ //$NON-NLS-2$
+			return EXIT_ERROR;
+		} finally {
+			if (packageAdminRef != null) {
+				cleanupRepositories();
+				cleanupServices();
+			}
+		}
+	}
+
+	private void purgeRegistry() throws ProvisionException {
+		if (getProfile() == null)
+			return;
+		IProfileRegistry registry = (IProfileRegistry) targetAgent.getService(IProfileRegistry.SERVICE_NAME);
+		long[] allProfiles = registry.listProfileTimestamps(profileId);
+		for (int i = 0; i < allProfiles.length - 1; i++) {
+			registry.removeProfile(profileId, allProfiles[i]);
+		}
+	}
+
+	private void revertToPreviousState() throws CoreException {
+		IProfile profile = initializeProfile();
+		IProfileRegistry profileRegistry = (IProfileRegistry) targetAgent.getService(IProfileRegistry.SERVICE_NAME);
+		IProfile targetProfile = null;
+		if (revertToPreviousState == REVERT_TO_PREVIOUS) {
+			long[] profiles = profileRegistry.listProfileTimestamps(profile.getProfileId());
+			if (profiles.length == 0)
+				return;
+			targetProfile = profileRegistry.getProfile(profile.getProfileId(), profiles[profiles.length - 1]);
+		} else {
+			targetProfile = profileRegistry.getProfile(profile.getProfileId(), getTimestampToRevertTo(profileRegistry, profile.getProfileId()));
+		}
+
+		if (targetProfile == null)
+			throw new CoreException(new Status(IStatus.ERROR, Activator.ID, Messages.Missing_profile));
+		IProvisioningPlan plan = planner.getDiffPlan(profile, targetProfile, new NullProgressMonitor());
+
+		ProvisioningContext context = new ProvisioningContext(targetAgent);
+		context.setMetadataRepositories(metadataRepositoryLocations.toArray(new URI[metadataRepositoryLocations.size()]));
+		context.setArtifactRepositories(artifactRepositoryLocations.toArray(new URI[artifactRepositoryLocations.size()]));
+		context.setProperty(ProvisioningContext.FOLLOW_REPOSITORY_REFERENCES, String.valueOf(followReferences));
+		context.setProperty(FOLLOW_ARTIFACT_REPOSITORY_REFERENCES, String.valueOf(followReferences));
+		executePlan(context, plan);
+	}
+
+	private long getTimestampToRevertTo(IProfileRegistry profileRegistry, String profId) {
+		long timestampToRevertTo = -1;
+		try {
+			//Deal with the case where the revert points to a timestamp
+			timestampToRevertTo = Long.valueOf(revertToPreviousState).longValue();
+		} catch (NumberFormatException e) {
+			//Deal with the case where the revert points to tag
+			Map<String, String> tags = profileRegistry.getProfileStateProperties(profId, IProfile.STATE_PROP_TAG);
+			Set<Entry<String, String>> entries = tags.entrySet();
+			for (Entry<String, String> entry : entries) {
+				if (entry.getValue().equals(revertToPreviousState))
+					try {
+						long tmp = Long.valueOf(entry.getKey()).longValue();
+						if (tmp > timestampToRevertTo)
+							timestampToRevertTo = tmp;
+					} catch (NumberFormatException e2) {
+						//Not expected since the value is supposed to be a timestamp as per API
+					}
+			}
+		}
+		return timestampToRevertTo;
+	}
+
+	/**
+	 * Sets a system property, using the EnvironmentInfo service if possible.
+	 */
+	private void setSystemProperty(String key, String value) {
+		EnvironmentInfo env = (EnvironmentInfo) ServiceHelper.getService(Activator.getContext(), EnvironmentInfo.class.getName());
+		if (env != null) {
+			env.setProperty(key, value);
+		} else {
+			System.getProperties().put(key, value);
+		}
+	}
+
+	private static void appendLevelPrefix(PrintStream strm, int level) {
+		for (int idx = 0; idx < level; ++idx)
+			strm.print(' ');
+	}
+
+	IQueryResult<IInstallableUnit> getInstallableUnits(URI location, IQuery<IInstallableUnit> query, IProgressMonitor monitor) {
+		IQueryable<IInstallableUnit> queryable = null;
+		if (location == null) {
+			queryable = metadataManager;
+		} else {
+			try {
+				queryable = metadataManager.loadRepository(location, monitor);
+			} catch (ProvisionException e) {
+				//repository is not available - just return empty result
+			}
+		}
+		if (queryable != null)
+			return queryable.query(query, monitor);
+		return Collector.emptyCollector();
+	}
+
+	private void deeplyPrint(CoreException ce, PrintStream strm, int level) {
+		appendLevelPrefix(strm, level);
+		if (stackTrace)
+			ce.printStackTrace(strm);
+		deeplyPrint(ce.getStatus(), strm, level);
+	}
+
+	private void deeplyPrint(IStatus status, PrintStream strm, int level) {
+		appendLevelPrefix(strm, level);
+		String msg = status.getMessage();
+		strm.println(msg);
+		Throwable cause = status.getException();
+		if (cause != null) {
+			strm.print("Caused by: "); //$NON-NLS-1$
+			if (stackTrace || !(msg.equals(cause.getMessage()) || msg.equals(cause.toString())))
+				deeplyPrint(cause, strm, level);
+		}
+
+		if (status.isMultiStatus()) {
+			IStatus[] children = status.getChildren();
+			for (int i = 0; i < children.length; i++)
+				deeplyPrint(children[i], strm, level + 1);
+		}
+	}
+
+	private void deeplyPrint(Throwable t, PrintStream strm, int level) {
+		if (t instanceof CoreException)
+			deeplyPrint((CoreException) t, strm, level);
+		else {
+			appendLevelPrefix(strm, level);
+			if (stackTrace)
+				t.printStackTrace(strm);
+			else {
+				strm.println(t.toString());
+				Throwable cause = t.getCause();
+				if (cause != null) {
+					strm.print("Caused by: "); //$NON-NLS-1$
+					deeplyPrint(cause, strm, level);
+				}
+			}
+		}
+	}
+
+	private void performHelpInfo() {
+		CommandLineOption[] allOptions = new CommandLineOption[] {OPTION_HELP, OPTION_LIST, OPTION_LIST_INSTALLED, OPTION_INSTALL_IU, OPTION_UNINSTALL_IU, OPTION_REVERT, OPTION_DESTINATION, OPTION_METADATAREPOS, OPTION_ARTIFACTREPOS, OPTION_REPOSITORIES, OPTION_VERIFY_ONLY, OPTION_PROFILE, OPTION_FLAVOR, OPTION_SHARED, OPTION_BUNDLEPOOL, OPTION_PROFILE_PROPS, OPTION_IU_PROFILE_PROPS, OPTION_ROAMING, OPTION_P2_OS, OPTION_P2_WS, OPTION_P2_ARCH, OPTION_P2_NL, OPTION_PURGEHISTORY, OPTION_FOLLOW_REFERENCES};
+		for (int i = 0; i < allOptions.length; ++i) {
+			allOptions[i].appendHelp(System.out);
+		}
+	}
+
+	/*
+	 * Set the roaming property on the given profile.
+	 */
+	private IStatus setRoaming(IProfile profile) {
+		ProfileChangeRequest request = new ProfileChangeRequest(profile);
+		request.setProfileProperty(IProfile.PROP_ROAMING, "true"); //$NON-NLS-1$
+		ProvisioningContext context = new ProvisioningContext(targetAgent);
+		context.setMetadataRepositories(new URI[0]);
+		context.setArtifactRepositories(new URI[0]);
+		IProvisioningPlan result = planner.getProvisioningPlan(request, context, new NullProgressMonitor());
+		return PlanExecutionHelper.executePlan(result, engine, context, new NullProgressMonitor());
+	}
+
+	public Object start(IApplicationContext context) throws Exception {
+		return run((String[]) context.getArguments().get("application.args")); //$NON-NLS-1$
+	}
+
+	private String toString(Map<String, String> context) {
+		StringBuffer result = new StringBuffer();
+		for (Map.Entry<String, String> entry : context.entrySet()) {
+			if (result.length() > 0)
+				result.append(',');
+			result.append(entry.getKey());
+			result.append('=');
+			result.append(entry.getValue());
+		}
+		return result.toString();
+	}
+
+	private void updateRoamingProperties(IProfile profile) throws CoreException {
+		// if the user didn't specify a destination path on the command-line
+		// then we assume they are installing into the currently running
+		// instance and we don't have anything to update
+		if (destination == null)
+			return;
+
+		// if the user didn't set a profile id on the command-line this is ok if they
+		// also didn't set the destination path. (handled in the case above) otherwise throw an error.
+		if (noProfileId) // && destination != null
+			throw new ProvisionException(Messages.Missing_profileid);
+
+		// make sure that we are set to be roaming before we update the values
+		if (!Boolean.valueOf(profile.getProperty(IProfile.PROP_ROAMING)).booleanValue())
+			return;
+
+		ProfileChangeRequest request = new ProfileChangeRequest(profile);
+		if (!destination.equals(new File(profile.getProperty(IProfile.PROP_INSTALL_FOLDER))))
+			request.setProfileProperty(IProfile.PROP_INSTALL_FOLDER, destination.getAbsolutePath());
+
+		File cacheLocation = null;
+		if (bundlePool == null)
+			cacheLocation = sharedLocation == null ? destination.getAbsoluteFile() : sharedLocation.getAbsoluteFile();
+		else
+			cacheLocation = bundlePool.getAbsoluteFile();
+		if (!cacheLocation.equals(new File(profile.getProperty(IProfile.PROP_CACHE))))
+			request.setProfileProperty(IProfile.PROP_CACHE, cacheLocation.getAbsolutePath());
+		if (request.getProfileProperties().size() == 0)
+			return;
+
+		// otherwise we have to make a change so set the profile to be non-roaming so the 
+		// values don't get recalculated to the wrong thing if we are flushed from memory - we
+		// will set it back later (see bug 269468)
+		request.setProfileProperty(IProfile.PROP_ROAMING, "false"); //$NON-NLS-1$
+
+		ProvisioningContext context = new ProvisioningContext(targetAgent);
+		context.setMetadataRepositories(new URI[0]);
+		context.setArtifactRepositories(new URI[0]);
+		IProvisioningPlan result = planner.getProvisioningPlan(request, context, new NullProgressMonitor());
+		IStatus status = PlanExecutionHelper.executePlan(result, engine, context, new NullProgressMonitor());
+		if (!status.isOK())
+			throw new CoreException(new MultiStatus(org.eclipse.equinox.internal.p2.director.app.Activator.ID, IStatus.ERROR, new IStatus[] {status}, NLS.bind(Messages.Cant_change_roaming, profile.getProfileId()), null));
+	}
+
+	public void stop() {
+		if (log != null)
+			log.close();
+	}
+
+	public void setLog(ILog log) {
+		this.log = log;
+	}
+
+	private void performListInstalledRoots() throws CoreException {
+		IProfile profile = initializeProfile();
+		IQueryResult<IInstallableUnit> roots = profile.query(new UserVisibleRootQuery(), null);
+		Set<IInstallableUnit> sorted = new TreeSet<IInstallableUnit>(roots.toUnmodifiableSet());
+		for (IInstallableUnit iu : sorted)
+			System.out.println(iu.getId() + '/' + iu.getVersion());
+	}
+
+	private void performPrintTags() throws CoreException {
+		IProfile profile = initializeProfile();
+		IProfileRegistry registry = (IProfileRegistry) targetAgent.getService(IProfileRegistry.SERVICE_NAME);
+		Map<String, String> tags = registry.getProfileStateProperties(profile.getProfileId(), IProfile.STATE_PROP_TAG);
+		//Sort the tags from the most recent to the oldest
+		List<String> timeStamps = new ArrayList<String>(tags.keySet());
+		Collections.sort(timeStamps, Collections.reverseOrder());
+		for (String timestamp : timeStamps) {
+			System.out.println(tags.get(timestamp));
+		}
+	}
+}
Index: p2-director/com.jboss.jbds.p2.director/build.properties
===================================================================
--- p2-director/com.jboss.jbds.p2.director/build.properties	(revision 0)
+++ p2-director/com.jboss.jbds.p2.director/build.properties	(revision 0)
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml
Index: p2-director/com.jboss.jbds.p2.director/pom.xml
===================================================================
--- p2-director/com.jboss.jbds.p2.director/pom.xml	(revision 0)
+++ p2-director/com.jboss.jbds.p2.director/pom.xml	(revision 0)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.jboss.jbds.installer</groupId>
+    <artifactId>p2-director</artifactId>
+    <version>7.0.0-SNAPSHOT</version>
+  </parent>
+  <groupId>com.jboss.jbds.installer.p2-director</groupId>
+  <artifactId>com.jboss.jbds.p2.director</artifactId>
+  <packaging>eclipse-plugin</packaging>
+
+</project>
\ No newline at end of file
Index: p2-director/com.jboss.jbds.p2.director/plugin.xml
===================================================================
--- p2-director/com.jboss.jbds.p2.director/plugin.xml	(revision 0)
+++ p2-director/com.jboss.jbds.p2.director/plugin.xml	(revision 0)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension
+         id="com.jboss.jbds.p2.director"
+         point="org.eclipse.core.runtime.applications">
+      <application
+            cardinality="singleton-global"
+            thread="main"
+            visible="true">
+         <run
+               class="com.jboss.jbds.internal.p2.director.InstallerDirectorApplication">
+         </run>
+      </application>
+   </extension>
+
+</plugin>
Index: p2-director/com.jboss.jbds.p2.director/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- p2-director/com.jboss.jbds.p2.director/.settings/org.eclipse.jdt.core.prefs	(revision 0)
+++ p2-director/com.jboss.jbds.p2.director/.settings/org.eclipse.jdt.core.prefs	(revision 0)
@@ -0,0 +1,8 @@
+#Mon Dec 05 10:59:11 PST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
