You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2007/09/03 19:39:06 UTC

svn commit: r572395 [10/11] - in /geronimo/server/trunk: ./ applications/console/geronimo-console-standard/src/main/java/org/apache/geronimo/console/car/ applications/console/geronimo-console-standard/src/main/webapp/WEB-INF/view/car/ applications/gero...

Modified: geronimo/server/trunk/modules/geronimo-system/src/main/java/org/apache/geronimo/system/plugin/PluginInstallerGBean.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-system/src/main/java/org/apache/geronimo/system/plugin/PluginInstallerGBean.java?rev=572395&r1=572394&r2=572395&view=diff
==============================================================================
--- geronimo/server/trunk/modules/geronimo-system/src/main/java/org/apache/geronimo/system/plugin/PluginInstallerGBean.java (original)
+++ geronimo/server/trunk/modules/geronimo-system/src/main/java/org/apache/geronimo/system/plugin/PluginInstallerGBean.java Mon Sep  3 10:38:54 2007
@@ -16,12 +16,15 @@
  */
 package org.apache.geronimo.system.plugin;
 
+import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.BufferedOutputStream;
+import java.io.FileInputStream;
+import java.io.OutputStream;
+import java.io.Writer;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -30,6 +33,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -38,33 +42,45 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
-import java.util.Vector;
-import java.util.Enumeration;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
+
 import javax.security.auth.login.FailedLoginException;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.Marshaller;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.stream.XMLOutputFactory;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.geronimo.gbean.GBeanInfo;
 import org.apache.geronimo.gbean.GBeanInfoBuilder;
+import org.apache.geronimo.gbean.AbstractName;
 import org.apache.geronimo.kernel.config.ConfigurationData;
 import org.apache.geronimo.kernel.config.ConfigurationManager;
 import org.apache.geronimo.kernel.config.ConfigurationStore;
 import org.apache.geronimo.kernel.config.InvalidConfigException;
 import org.apache.geronimo.kernel.config.NoSuchConfigException;
+import org.apache.geronimo.kernel.config.NoSuchStoreException;
+import org.apache.geronimo.kernel.config.ConfigurationInfo;
 import org.apache.geronimo.kernel.repository.Artifact;
 import org.apache.geronimo.kernel.repository.ArtifactResolver;
 import org.apache.geronimo.kernel.repository.DefaultArtifactResolver;
@@ -75,11 +91,18 @@
 import org.apache.geronimo.kernel.repository.Repository;
 import org.apache.geronimo.kernel.repository.Version;
 import org.apache.geronimo.kernel.repository.WritableListableRepository;
-import org.apache.geronimo.kernel.InvalidGBeanException;
 import org.apache.geronimo.kernel.util.XmlUtil;
 import org.apache.geronimo.system.configuration.ConfigurationStoreUtil;
-import org.apache.geronimo.system.configuration.GBeanOverride;
 import org.apache.geronimo.system.configuration.PluginAttributeStore;
+import org.apache.geronimo.system.plugin.model.PluginArtifactType;
+import org.apache.geronimo.system.plugin.model.PluginListType;
+import org.apache.geronimo.system.plugin.model.PluginType;
+import org.apache.geronimo.system.plugin.model.HashType;
+import org.apache.geronimo.system.plugin.model.ArtifactType;
+import org.apache.geronimo.system.plugin.model.PrerequisiteType;
+import org.apache.geronimo.system.plugin.model.CopyFileType;
+import org.apache.geronimo.system.plugin.model.DependencyType;
+import org.apache.geronimo.system.plugin.model.ObjectFactory;
 import org.apache.geronimo.system.serverinfo.ServerInfo;
 import org.apache.geronimo.system.threads.ThreadPool;
 import org.apache.geronimo.util.encoders.Base64;
@@ -88,9 +111,7 @@
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.Attributes;
-import org.xml.sax.ErrorHandler;
 import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
 import org.xml.sax.helpers.DefaultHandler;
 
 /**
@@ -100,6 +121,20 @@
  */
 public class PluginInstallerGBean implements PluginInstaller {
     private final static Log log = LogFactory.getLog(PluginInstallerGBean.class);
+
+    private static final XMLInputFactory XMLINPUT_FACTORY = XMLInputFactory.newInstance();
+    private static final JAXBContext PLUGIN_CONTEXT;
+    private static final JAXBContext PLUGIN_LIST_CONTEXT;
+
+    static {
+        try {
+            PLUGIN_CONTEXT = JAXBContext.newInstance(PluginType.class);
+            PLUGIN_LIST_CONTEXT = JAXBContext.newInstance(PluginListType.class);
+        } catch (JAXBException e) {
+            throw new RuntimeException("Could not create jaxb contexts for plugin types");
+        }
+    }
+
     private static int counter;
     private ConfigurationManager configManager;
     private WritableListableRepository writeableRepo;
@@ -135,26 +170,26 @@
         for (Iterator i = artifacts.iterator(); i.hasNext();) {
             Artifact configId = (Artifact) i.next();
             File dir = writeableRepo.getLocation(configId);
-            if(dir.isDirectory()) {
+            if (dir.isDirectory()) {
                 File meta = new File(dir, "META-INF");
-                if(!meta.isDirectory() || !meta.canRead()) {
+                if (!meta.isDirectory() || !meta.canRead()) {
                     continue;
                 }
                 File xml = new File(meta, "geronimo-plugin.xml");
-                if(!xml.isFile() || !xml.canRead() || xml.length() == 0) {
+                if (!xml.isFile() || !xml.canRead() || xml.length() == 0) {
                     continue;
                 }
                 readNameAndID(xml, plugins);
             } else {
-                if(!dir.isFile() || !dir.canRead()) {
-                    log.error("Cannot read artifact dir "+dir.getAbsolutePath());
-                    throw new IllegalStateException("Cannot read artifact dir "+dir.getAbsolutePath());
+                if (!dir.isFile() || !dir.canRead()) {
+                    log.error("Cannot read artifact dir " + dir.getAbsolutePath());
+                    throw new IllegalStateException("Cannot read artifact dir " + dir.getAbsolutePath());
                 }
                 try {
                     JarFile jar = new JarFile(dir);
                     try {
                         ZipEntry entry = jar.getEntry("META-INF/geronimo-plugin.xml");
-                        if(entry == null) {
+                        if (entry == null) {
                             continue;
                         }
                         InputStream in = jar.getInputStream(entry);
@@ -164,7 +199,7 @@
                         jar.close();
                     }
                 } catch (IOException e) {
-                    log.error("Unable to read JAR file "+dir.getAbsolutePath(), e);
+                    log.error("Unable to read JAR file " + dir.getAbsolutePath(), e);
                 }
             }
         }
@@ -172,7 +207,7 @@
     }
 
     /**
-     * Gets a CofigurationMetadata for a configuration installed in the local
+     * Gets a ConfigurationMetadata for a configuration installed in the local
      * server.  Should load a saved one if available, or else create a new
      * default one to the best of its abilities.
      *
@@ -180,13 +215,13 @@
      *                 configuration currently installed in the local server.
      *                 The configId must be fully resolved (isResolved() == true)
      */
-    public PluginMetadata getPluginMetadata(Artifact moduleId) {
-        if(configManager != null) {
-            if(!configManager.isConfiguration(moduleId)) {
+    public PluginType getPluginMetadata(Artifact moduleId) {
+        if (configManager != null) {
+            if (!configManager.isConfiguration(moduleId)) {
                 return null;
             }
         } else {
-            if(!configStore.containsConfiguration(moduleId)) {
+            if (!configStore.containsConfiguration(moduleId)) {
                 return null;
             }
         }
@@ -194,50 +229,51 @@
         Document doc;
         ConfigurationData configData;
         String source = dir.getAbsolutePath();
+        InputStream in;
         try {
-            if(dir.isDirectory()) {
+            if (dir.isDirectory()) {
                 File meta = new File(dir, "META-INF");
-                if(!meta.isDirectory() || !meta.canRead()) {
+                if (!meta.isDirectory() || !meta.canRead()) {
                     return null;
                 }
                 File xml = new File(meta, "geronimo-plugin.xml");
                 configData = configStore.loadConfiguration(moduleId);
-                if(!xml.isFile() || !xml.canRead() || xml.length() == 0) {
+                if (!xml.isFile() || !xml.canRead() || xml.length() == 0) {
                     return createDefaultMetadata(configData);
                 }
-                source = xml.getAbsolutePath();
-                DocumentBuilder builder = createDocumentBuilder();
-                doc = builder.parse(xml);
+                in = new FileInputStream(xml);
             } else {
-                if(!dir.isFile() || !dir.canRead()) {
-                    log.error("Cannot read configuration "+dir.getAbsolutePath());
-                    throw new IllegalStateException("Cannot read configuration "+dir.getAbsolutePath());
+                if (!dir.isFile() || !dir.canRead()) {
+                    log.error("Cannot read configuration " + dir.getAbsolutePath());
+                    throw new IllegalStateException("Cannot read configuration " + dir.getAbsolutePath());
                 }
                 configData = configStore.loadConfiguration(moduleId);
                 JarFile jar = new JarFile(dir);
                 try {
                     ZipEntry entry = jar.getEntry("META-INF/geronimo-plugin.xml");
-                    if(entry == null) {
+                    if (entry == null) {
                         return createDefaultMetadata(configData);
                     }
-                    source = dir.getAbsolutePath()+"#META-INF/geronimo-plugin.xml";
-                    InputStream in = jar.getInputStream(entry);
-                    DocumentBuilder builder = createDocumentBuilder();
-                    doc = builder.parse(in);
-                    in.close();
+                    source = dir.getAbsolutePath() + "#META-INF/geronimo-plugin.xml";
+                    in = jar.getInputStream(entry);
                 } finally {
                     jar.close();
                 }
             }
-            PluginMetadata result = loadPluginMetadata(doc, source);
+            PluginType result;
+            try {
+                result = loadPluginMetadata(in);
+            } finally {
+                in.close();
+            }
             overrideDependencies(configData, result);
             return result;
         } catch (InvalidConfigException e) {
             e.printStackTrace();
-            log.warn("Unable to generate metadata for "+moduleId, e);
+            log.warn("Unable to generate metadata for " + moduleId, e);
         } catch (Exception e) {
             e.printStackTrace();
-            log.warn("Invalid XML at "+source, e);
+            log.warn("Invalid XML at " + source, e);
         }
         return null;
     }
@@ -252,39 +288,37 @@
      *                 be fully resolved) identifies the configuration to save
      *                 this for.
      */
-    public void updatePluginMetadata(PluginMetadata metadata) {
-        File dir = writeableRepo.getLocation(metadata.getModuleId());
-        if(dir == null) {
-            log.error(metadata.getModuleId()+" is not installed!");
-            throw new IllegalArgumentException(metadata.getModuleId()+" is not installed!");
+    public void updatePluginMetadata(PluginType metadata) {
+        PluginArtifactType instance = metadata.getPluginArtifact().get(0);
+        Artifact artifact = toArtifact(instance.getModuleId());
+        File dir = writeableRepo.getLocation(artifact);
+        if (dir == null) {
+            log.error(artifact + " is not installed!");
+            throw new IllegalArgumentException(artifact + " is not installed!");
         }
-        if(!dir.isDirectory()) { // must be a packed (JAR-formatted) plugin
+        if (!dir.isDirectory()) { // must be a packed (JAR-formatted) plugin
             try {
-                File temp = new File(dir.getParentFile(), dir.getName()+".temp");
+                File temp = new File(dir.getParentFile(), dir.getName() + ".temp");
                 JarFile input = new JarFile(dir);
                 Manifest manifest = input.getManifest();
-                JarOutputStream out = manifest == null ? new JarOutputStream(new BufferedOutputStream(new FileOutputStream(temp)))
+                JarOutputStream out = manifest == null ? new JarOutputStream(
+                        new BufferedOutputStream(new FileOutputStream(temp)))
                         : new JarOutputStream(new BufferedOutputStream(new FileOutputStream(temp)), manifest);
                 Enumeration en = input.entries();
                 byte[] buf = new byte[4096];
                 int count;
                 while (en.hasMoreElements()) {
                     JarEntry entry = (JarEntry) en.nextElement();
-                    if(entry.getName().equals("META-INF/geronimo-plugin.xml")) {
+                    if (entry.getName().equals("META-INF/geronimo-plugin.xml")) {
                         entry = new JarEntry(entry.getName());
                         out.putNextEntry(entry);
-                        Document doc = writePluginMetadata(metadata);
-                        TransformerFactory xfactory = XmlUtil.newTransformerFactory();
-                        Transformer xform = xfactory.newTransformer();
-                        xform.setOutputProperty(OutputKeys.INDENT, "yes");
-                        xform.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
-                        xform.transform(new DOMSource(doc), new StreamResult(out));
-                    } else if(entry.getName().equals("META-INF/MANIFEST.MF")) {
+                        writePluginMetadata(metadata, out);
+                    } else if (entry.getName().equals("META-INF/MANIFEST.MF")) {
                         // do nothing, already passed in a manifest
                     } else {
                         out.putNextEntry(entry);
                         InputStream in = input.getInputStream(entry);
-                        while((count = in.read(buf)) > -1) {
+                        while ((count = in.read(buf)) > -1) {
                             out.write(buf, 0, count);
                         }
                         in.close();
@@ -294,13 +328,14 @@
                 out.flush();
                 out.close();
                 input.close();
-                if(!dir.delete()) {
-                    log.error("Unable to delete old plugin at "+dir.getAbsolutePath());
-                    throw new IOException("Unable to delete old plugin at "+dir.getAbsolutePath());
-                }
-                if(!temp.renameTo(dir)) {
-                    log.error("Unable to move new plugin "+temp.getAbsolutePath()+" to "+dir.getAbsolutePath());
-                    throw new IOException("Unable to move new plugin "+temp.getAbsolutePath()+" to "+dir.getAbsolutePath());
+                if (!dir.delete()) {
+                    log.error("Unable to delete old plugin at " + dir.getAbsolutePath());
+                    throw new IOException("Unable to delete old plugin at " + dir.getAbsolutePath());
+                }
+                if (!temp.renameTo(dir)) {
+                    log.error("Unable to move new plugin " + temp.getAbsolutePath() + " to " + dir.getAbsolutePath());
+                    throw new IOException(
+                            "Unable to move new plugin " + temp.getAbsolutePath() + " to " + dir.getAbsolutePath());
                 }
             } catch (Exception e) {
                 log.error("Unable to update plugin metadata", e);
@@ -308,31 +343,23 @@
             } // TODO this really should have a finally block to ensure streams are closed
         } else {
             File meta = new File(dir, "META-INF");
-            if(!meta.isDirectory() || !meta.canRead()) {
-                log.error(metadata.getModuleId()+" is not a plugin!");
-                throw new IllegalArgumentException(metadata.getModuleId()+" is not a plugin!");
+            if (!meta.isDirectory() || !meta.canRead()) {
+                log.error(artifact + " is not a plugin!");
+                throw new IllegalArgumentException(artifact + " is not a plugin!");
             }
             File xml = new File(meta, "geronimo-plugin.xml");
             FileOutputStream fos = null;
             try {
-                if(!xml.isFile()) {
-                    if(!xml.createNewFile()) {
-                        log.error("Cannot create plugin metadata file for "+metadata.getModuleId());
-                        throw new RuntimeException("Cannot create plugin metadata file for "+metadata.getModuleId());
+                if (!xml.isFile()) {
+                    if (!xml.createNewFile()) {
+                        log.error("Cannot create plugin metadata file for " + artifact);
+                        throw new RuntimeException("Cannot create plugin metadata file for " + artifact);
                     }
                 }
-                Document doc = writePluginMetadata(metadata);
-                TransformerFactory xfactory = XmlUtil.newTransformerFactory();
-                Transformer xform = xfactory.newTransformer();
-                xform.setOutputProperty(OutputKeys.INDENT, "yes");
-                xform.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
                 fos = new FileOutputStream(xml);
-                // use a FileOutputStream instead of a File on the StreamResult 
-                // constructor as problems were encountered with the file not being closed.
-                StreamResult sr = new StreamResult(fos); 
-                xform.transform(new DOMSource(doc), sr);
+                writePluginMetadata(metadata, fos);
             } catch (Exception e) {
-                log.error("Unable to save plugin metadata for "+metadata.getModuleId(), e);
+                log.error("Unable to save plugin metadata for " + artifact, e);
             } finally {
                 if (fos != null) {
                     try {
@@ -345,29 +372,43 @@
         }
     }
 
+    public static void writePluginMetadata(PluginType metadata, OutputStream out) throws XMLStreamException, JAXBException {
+        Marshaller marshaller = PLUGIN_CONTEXT.createMarshaller();
+        marshaller.setProperty("jaxb.formatted.output", true);
+        JAXBElement<PluginType> element = new ObjectFactory().createGeronimoPlugin(metadata);
+        marshaller.marshal(element, out);
+    }
+
+    public static void writePluginList(PluginListType metadata, Writer out) throws XMLStreamException, JAXBException {
+        Marshaller marshaller = PLUGIN_LIST_CONTEXT.createMarshaller();
+        marshaller.setProperty("jaxb.formatted.output", true);
+        JAXBElement<PluginListType> element = new ObjectFactory().createGeronimoPluginList(metadata);
+        marshaller.marshal(element, out);
+    }
+
     /**
      * Lists the plugins available for download in a particular Geronimo repository.
      *
      * @param mavenRepository The base URL to the maven repository.  This must
      *                        contain the file geronimo-plugins.xml
-     * @param username Optional username, if the maven repo uses HTTP Basic authentication.
-     *                 Set this to null if no authentication is required.
-     * @param password Optional password, if the maven repo uses HTTP Basic authentication.
-     *                 Set this to null if no authentication is required.
+     * @param username        Optional username, if the maven repo uses HTTP Basic authentication.
+     *                        Set this to null if no authentication is required.
+     * @param password        Optional password, if the maven repo uses HTTP Basic authentication.
+     *                        Set this to null if no authentication is required.
      */
-    public PluginList listPlugins(URL mavenRepository, String username, String password) throws IOException, FailedLoginException {
+    public PluginListType listPlugins(URL mavenRepository, String username, String password) throws IOException, FailedLoginException {
         String repository = mavenRepository.toString().trim();
-        if(!repository.endsWith("/")) {
-            repository = repository+"/";
+        if (!repository.endsWith("/")) {
+            repository = repository + "/";
         }
         //todo: Try downloading a .gz first
-        URL url = new URL(repository+"geronimo-plugins.xml");
+        String url = repository + "geronimo-plugins.xml";
         try {
             //todo: use a progress monitor
-            InputStream in = openStream(null, new URL[]{url}, username, password, null).getStream();
+            InputStream in = openStream(null, Collections.singletonList(url), username, password, null).getStream();
             return loadPluginList(mavenRepository, in);
         } catch (MissingDependencyException e) {
-            log.error("Cannot find plugin index at site "+url);
+            log.error("Cannot find plugin index at site " + url);
             return null;
         } catch (Exception e) {
             log.error("Unable to load repository configuration data", e);
@@ -387,7 +428,7 @@
      *                         Set this to null if no authentication is required.
      * @param pluginsToInstall The list of configurations to install
      */
-    public DownloadResults install(PluginList pluginsToInstall, String username, String password) {
+    public DownloadResults install(PluginListType pluginsToInstall, String username, String password) {
         DownloadResults results = new DownloadResults();
         install(pluginsToInstall, username, password, results);
         return results;
@@ -409,32 +450,31 @@
      *                         Set this to null if no authentication is required.
      * @param poller           Will be notified with status updates as the download proceeds
      */
-    public void install(PluginList pluginsToInstall, String username, String password, DownloadPoller poller) {
+    public void install(PluginListType pluginsToInstall, String username, String password, DownloadPoller poller) {
         try {
-            Map metaMap = new HashMap();
+            Map<Artifact, PluginType> metaMap = new HashMap<Artifact, PluginType>();
             // Step 1: validate everything
-            for (int i = 0; i < pluginsToInstall.getPlugins().length; i++) {
-                PluginMetadata metadata = pluginsToInstall.getPlugins()[i];
+            for (PluginType metadata: pluginsToInstall.getPlugin()) {
                 validatePlugin(metadata);
-                if(metadata.getModuleId() != null) {
-                    metaMap.put(metadata.getModuleId(), metadata);
+                PluginArtifactType instance = metadata.getPluginArtifact().get(0);
+
+                if (instance.getModuleId() != null) {
+                    metaMap.put(toArtifact(instance.getModuleId()), metadata);
                 }
             }
 
             // Step 2: everything is valid, do the installation
-            for (int i = 0; i < pluginsToInstall.getPlugins().length; i++) {
-                // 1. Identify the configuration
-                PluginMetadata metadata = pluginsToInstall.getPlugins()[i];
+            for (PluginType metadata: pluginsToInstall.getPlugin()) {
                 // 2. Unload obsoleted configurations
-                List obsoletes = new ArrayList();
-                for (int j = 0; j < metadata.getObsoletes().length; j++) {
-                    String name = metadata.getObsoletes()[j];
-                    Artifact obsolete = Artifact.create(name);
+                PluginArtifactType instance = metadata.getPluginArtifact().get(0);
+                List<Artifact> obsoletes = new ArrayList<Artifact>();
+                for (ArtifactType obs: instance.getObsoletes()) {
+                    Artifact obsolete = toArtifact(obs);
                     Artifact[] list = configManager.getArtifactResolver().queryArtifacts(obsolete);
                     for (int k = 0; k < list.length; k++) {
                         Artifact artifact = list[k];
-                        if(configManager.isLoaded(artifact)) {
-                            if(configManager.isRunning(artifact)) {
+                        if (configManager.isLoaded(artifact)) {
+                            if (configManager.isRunning(artifact)) {
                                 configManager.stopConfiguration(artifact);
                             }
                             configManager.unloadConfiguration(artifact);
@@ -443,46 +483,45 @@
                     }
                 }
                 // 3. Download the artifact if necessary, and its dependencies
-                Set working = new HashSet();
-                if(metadata.getModuleId() != null) {
-                    URL[] repos = pluginsToInstall.getRepositories();
-                    if(metadata.getRepositories().length > 0) {
-                        repos = metadata.getRepositories();
+                Set<Artifact> working = new HashSet<Artifact>();
+                if (instance.getModuleId() != null) {
+                    List<String> repos = pluginsToInstall.getDefaultRepository();
+                    if (!instance.getSourceRepository().isEmpty()) {
+                        repos = instance.getSourceRepository();
                     }
-                    downloadArtifact(metadata.getModuleId(), metaMap, repos,
+                    downloadArtifact(toArtifact(instance.getModuleId()), metaMap, repos,
                             username, password, new ResultsFileWriteMonitor(poller), working, false);
                 } else {
-                    String[] deps = metadata.getDependencies();
-                    for (int j = 0; j < deps.length; j++) {
-                        String dep = deps[j];
-                        Artifact entry = Artifact.create(dep);
-                        URL[] repos = pluginsToInstall.getRepositories();
-                        if(metadata.getRepositories().length > 0) {
-                            repos = metadata.getRepositories();
+                    List<DependencyType> deps = instance.getDependency();
+                    for (DependencyType dep: deps) {
+                        Artifact entry = toArtifact(dep);
+                        List<String> repos = pluginsToInstall.getDefaultRepository();
+                        if (!instance.getSourceRepository().isEmpty()) {
+                            repos = instance.getSourceRepository();
                         }
                         downloadArtifact(entry, metaMap, repos,
                                 username, password, new ResultsFileWriteMonitor(poller), working, false);
                     }
                 }
                 // 4. Uninstall obsolete configurations
-                for (int j = 0; j < obsoletes.size(); j++) {
-                    Artifact artifact = (Artifact) obsoletes.get(j);
+                for (Artifact artifact : obsoletes) {
                     configManager.uninstallConfiguration(artifact);
                 }
                 // 5. Installation of this configuration finished successfully
             }
 
             // Step 3: Start anything that's marked accordingly
-            for (int i = 0; i < pluginsToInstall.getPlugins().length; i++) {
-                PluginMetadata metadata = pluginsToInstall.getPlugins()[i];
-                for (int j = 0; j < metadata.getForceStart().length; j++) {
-                    String id = metadata.getForceStart()[j];
-                    Artifact artifact = Artifact.create(id);
-                    if(configManager.isConfiguration(artifact)) {
-                        poller.setCurrentFilePercent(-1);
-                        poller.setCurrentMessage("Starting "+artifact);
-                        configManager.loadConfiguration(artifact);
-                        configManager.startConfiguration(artifact);
+            for (PluginType metadata: pluginsToInstall.getPlugin()) {
+                PluginArtifactType instance = metadata.getPluginArtifact().get(0);
+                for (DependencyType dep: instance.getDependency()) {
+                    if (dep.isStart()) {
+                        Artifact artifact = toArtifact(dep);
+                        if (configManager.isConfiguration(artifact)) {
+                            poller.setCurrentFilePercent(-1);
+                            poller.setCurrentMessage("Starting " + artifact);
+                            configManager.loadConfiguration(artifact);
+                            configManager.startConfiguration(artifact);
+                        }
                     }
                 }
             }
@@ -505,10 +544,9 @@
      *                         Set this to null if no authentication is required.
      * @param password         Optional password, if the maven repo uses HTTP Basic authentication.
      *                         Set this to null if no authentication is required.
-     *
      * @return A key that can be passed to checkOnInstall
      */
-    public Object startInstall(final PluginList pluginsToInstall, final String username, final String password) {
+    public Object startInstall(final PluginListType pluginsToInstall, final String username, final String password) {
         Object key = getNextKey();
         final DownloadResults results = new DownloadResults();
         Runnable work = new Runnable() {
@@ -533,17 +571,16 @@
      * installation does not throw exceptions on failure, but instead sets the failure
      * property of the DownloadResults that the caller can poll for.
      *
-     * @param carFile   A CAR file downloaded from a remote repository.  This is a packaged
-     *                  configuration with included configuration information, but it may
-     *                  still have external dependencies that need to be downloaded
-     *                  separately.  The metadata in the CAR file includes a repository URL
-     *                  for these downloads, and the username and password arguments are
-     *                  used in conjunction with that.
-     * @param username  Optional username, if the maven repo uses HTTP Basic authentication.
-     *                  Set this to null if no authentication is required.
-     * @param password  Optional password, if the maven repo uses HTTP Basic authentication.
-     *                  Set this to null if no authentication is required.
-     *
+     * @param carFile  A CAR file downloaded from a remote repository.  This is a packaged
+     *                 configuration with included configuration information, but it may
+     *                 still have external dependencies that need to be downloaded
+     *                 separately.  The metadata in the CAR file includes a repository URL
+     *                 for these downloads, and the username and password arguments are
+     *                 used in conjunction with that.
+     * @param username Optional username, if the maven repo uses HTTP Basic authentication.
+     *                 Set this to null if no authentication is required.
+     * @param password Optional password, if the maven repo uses HTTP Basic authentication.
+     *                 Set this to null if no authentication is required.
      * @return A key that can be passed to checkOnInstall
      */
     public Object startInstall(final File carFile, final String username, final String password) {
@@ -575,7 +612,7 @@
     public DownloadResults checkOnInstall(Object key) {
         DownloadResults results = (DownloadResults) asyncKeys.get(key);
         results = results.duplicate();
-        if(results.isFinished()) {
+        if (results.isFinished()) {
             asyncKeys.remove(key);
         }
         return results;
@@ -587,29 +624,33 @@
     public void install(File carFile, String username, String password, DownloadPoller poller) {
         try {
             // 1. Extract the configuration metadata
-            PluginMetadata data = loadCARFile(carFile, true);
-            if(data == null) {
-                log.error("Invalid Configuration Archive "+carFile.getAbsolutePath()+" see server log for details");
-                throw new IllegalArgumentException("Invalid Configuration Archive "+carFile.getAbsolutePath()+" see server log for details");
+            PluginType data = loadCARFile(carFile, true);
+            if (data == null) {
+                log.error("Invalid Configuration Archive " + carFile.getAbsolutePath() + " see server log for details");
+                throw new IllegalArgumentException(
+                        "Invalid Configuration Archive " + carFile.getAbsolutePath() + " see server log for details");
             }
 
             // 2. Validate that we can install this
             validatePlugin(data);
-
+            PluginArtifactType instance = data.getPluginArtifact().get(0);
             // 3. Install the CAR into the repository (it shouldn't be re-downloaded)
-            if(data.getModuleId() != null) {
+            if (instance.getModuleId() != null) {
+                Artifact pluginArtifact = toArtifact(instance.getModuleId());
                 ResultsFileWriteMonitor monitor = new ResultsFileWriteMonitor(poller);
-                writeableRepo.copyToRepository(carFile, data.getModuleId(), monitor);
-                installConfigXMLData(data.getModuleId(), data);
-                if(data.getFilesToCopy() != null) {
-                    extractPluginFiles(data.getModuleId(), data, monitor);
+                writeableRepo.copyToRepository(carFile, pluginArtifact, monitor);
+                installConfigXMLData(pluginArtifact, instance);
+                if (instance.getCopyFile() != null) {
+                    extractPluginFiles(pluginArtifact, data, monitor);
                 }
             }
 
             // 4. Use the standard logic to remove obsoletes, install dependencies, etc.
             //    This will validate all over again (oh, well)
-            install(new PluginList(data.getRepositories(), new PluginMetadata[]{data}),
-                    username, password, poller);
+            PluginListType pluginList = new PluginListType();
+            pluginList.getPlugin().add(data);
+            pluginList.getDefaultRepository().addAll(instance.getSourceRepository());
+            install(pluginList, username, password, poller);
         } catch (Exception e) {
             poller.setFailure(e);
         } finally {
@@ -620,42 +661,51 @@
     /**
      * Ensures that a plugin is installable.
      */
-    private void validatePlugin(PluginMetadata metadata) throws MissingDependencyException {
+    private void validatePlugin(PluginType plugin) throws MissingDependencyException {
+        if (plugin.getPluginArtifact().size() != 1) {
+            throw new IllegalArgumentException("A plugin configuration must include one plugin artifact, not " + plugin.getPluginArtifact().size());
+        }
+        PluginArtifactType metadata = plugin.getPluginArtifact().get(0);
         // 1. Check that it's not already running
-        if(metadata.getModuleId() != null) { // that is, it's a real configuration not a plugin list
-            if(configManager.isRunning(metadata.getModuleId())) {
+        if (metadata.getModuleId() != null) { // that is, it's a real configuration not a plugin list
+            Artifact artifact = toArtifact(metadata.getModuleId());
+            if (configManager.isRunning(artifact)) {
                 boolean upgrade = false;
-                for (int i = 0; i < metadata.getObsoletes().length; i++) {
-                    String obsolete = metadata.getObsoletes()[i];
-                    Artifact test = Artifact.create(obsolete);
-                    if(test.matches(metadata.getModuleId())) {
+                for (ArtifactType obsolete: metadata.getObsoletes()) {
+                    Artifact test = toArtifact(obsolete);
+                    if (test.matches(artifact)) {
                         upgrade = true;
                         break;
                     }
                 }
-                if(!upgrade) {
-                    log.error("Configuration "+metadata.getModuleId()+" is already running!");
-                    throw new IllegalArgumentException("Configuration "+metadata.getModuleId()+" is already running!");
+                if (!upgrade) {
+                    log.error("Configuration " + artifact + " is already running!");
+                    throw new IllegalArgumentException(
+                            "Configuration " + artifact + " is already running!");
                 }
             }
         }
         // 2. Check that we meet the prerequisites
-        PluginMetadata.Prerequisite[] prereqs = metadata.getPrerequisites();
-        for (int i = 0; i < prereqs.length; i++) {
-            PluginMetadata.Prerequisite prereq = prereqs[i];
-            if(resolver.queryArtifacts(prereq.getModuleId()).length == 0) {
-                log.error("Required configuration '"+prereq.getModuleId()+"' is not installed.");
-                throw new MissingDependencyException("Required configuration '"+prereq.getModuleId()+"' is not installed.");
+        List<PrerequisiteType> prereqs = metadata.getPrerequisite();
+        for (PrerequisiteType prereq: prereqs) {
+            if (resolver.queryArtifacts(toArtifact(prereq.getId())).length == 0) {
+                log.error("Required configuration '" + prereq.getId() + "' is not installed.");
+                throw new MissingDependencyException(
+                        "Required configuration '" + prereq.getId() + "' is not installed.");
             }
         }
         // 3. Check that we meet the Geronimo, JVM versions
-        if(metadata.getGeronimoVersions().length > 0 && !checkGeronimoVersions(metadata.getGeronimoVersions())) {
-            log.error("Cannot install plugin "+metadata.getModuleId()+" on Geronimo "+serverInfo.getVersion());
-            throw new MissingDependencyException("Cannot install plugin "+metadata.getModuleId()+" on Geronimo "+serverInfo.getVersion());
-        }
-        if(metadata.getJvmVersions().length > 0 && !checkJVMVersions(metadata.getJvmVersions())) {
-            log.error("Cannot install plugin "+metadata.getModuleId()+" on JVM "+System.getProperty("java.version"));
-            throw new MissingDependencyException("Cannot install plugin "+metadata.getModuleId()+" on JVM "+System.getProperty("java.version"));
+        if (metadata.getGeronimoVersion().size() > 0 && !checkGeronimoVersions(metadata.getGeronimoVersion())) {
+            log.error("Cannot install plugin " + metadata.getModuleId() + " on Geronimo " + serverInfo.getVersion());
+            throw new MissingDependencyException(
+                    "Cannot install plugin " + metadata.getModuleId() + " on Geronimo " + serverInfo.getVersion());
+        }
+        if (metadata.getJvmVersion().size() > 0 && !checkJVMVersions(metadata.getJvmVersion())) {
+            log.error("Cannot install plugin " + metadata.getModuleId() + " on JVM " + System.getProperty(
+                    "java.version"));
+            throw new MissingDependencyException(
+                    "Cannot install plugin " + metadata.getModuleId() + " on JVM " + System.getProperty(
+                            "java.version"));
         }
     }
 
@@ -664,41 +714,41 @@
      * be just a JAR.  For each artifact processed, all its dependencies will be
      * processed as well.
      *
-     * @param configID  Identifies the artifact to install
-     * @param repos     The URLs to contact the repositories (in order of preference)
-     * @param username  The username used for repositories secured with HTTP Basic authentication
-     * @param password  The password used for repositories secured with HTTP Basic authentication
-     * @param monitor   The ongoing results of the download operations, with some monitoring logic
-     *
-     * @throws IOException                 When there's a problem reading or writing data
-     * @throws FailedLoginException        When a repository requires authentication and either no username
-     *                                     and password are supplied or the username and password supplied
-     *                                     are not accepted
-     * @throws MissingDependencyException  When a dependency cannot be located in any of the listed repositories
-     */
-    private void downloadArtifact(Artifact configID, Map metadata, URL[] repos, String username, String password, ResultsFileWriteMonitor monitor, Set soFar, boolean dependency) throws IOException, FailedLoginException, MissingDependencyException {
-        if(soFar.contains(configID)) {
-            return; // Avoid enless work due to circular dependencies
+     * @param configID Identifies the artifact to install
+     * @param repos    The URLs to contact the repositories (in order of preference)
+     * @param username The username used for repositories secured with HTTP Basic authentication
+     * @param password The password used for repositories secured with HTTP Basic authentication
+     * @param monitor  The ongoing results of the download operations, with some monitoring logic
+     * @throws IOException                When there's a problem reading or writing data
+     * @throws FailedLoginException       When a repository requires authentication and either no username
+     *                                    and password are supplied or the username and password supplied
+     *                                    are not accepted
+     * @throws MissingDependencyException When a dependency cannot be located in any of the listed repositories
+     */
+    private void downloadArtifact(Artifact configID, Map<Artifact, PluginType> metadata, List<String> repos, String username, String password, ResultsFileWriteMonitor monitor, Set<Artifact> soFar, boolean dependency) throws IOException, FailedLoginException, MissingDependencyException {
+        if (soFar.contains(configID)) {
+            return; // Avoid endless work due to circular dependencies
         } else {
             soFar.add(configID);
         }
         // Download and install the main artifact
         boolean pluginWasInstalled = false;
         Artifact[] matches = configManager.getArtifactResolver().queryArtifacts(configID);
-        if(matches.length == 0) { // not present, needs to be downloaded
+        if (matches.length == 0) {
+            // not present, needs to be downloaded
             monitor.getResults().setCurrentMessage("Downloading " + configID);
             monitor.getResults().setCurrentFilePercent(-1);
             OpenResult result = openStream(configID, repos, username, password, monitor);
             // Check if the result is already in server's repository
-            if(configManager.getArtifactResolver().queryArtifacts(result.getConfigID()).length > 0) {
-                String msg = "Not downloading "+configID+". Query for "+configID+" resulted in "+result.getConfigID()
-                             +" which is already available in server's repository.";
+            if (configManager.getArtifactResolver().queryArtifacts(result.getConfigID()).length > 0) {
+                String msg = "Not downloading " + configID + ". Query for " + configID + " resulted in " + result.getConfigID()
+                        + " which is already available in server's repository.";
                 monitor.getResults().setCurrentMessage(msg);
                 log.info(msg);
-                if(result.getStream() != null) {
+                if (result.getStream() != null) {
                     try {
                         result.getStream().close();
-                    } catch(IOException ignored) {
+                    } catch (IOException ignored) {
                     }
                 }
                 return;
@@ -706,42 +756,49 @@
             try {
                 File tempFile = downloadFile(result, monitor);
                 if (tempFile == null) {
-                    log.error("Null filehandle was returned for "+configID);
-                    throw new IllegalArgumentException("Null filehandle was returned for "+configID);
+                    log.error("Null filehandle was returned for " + configID);
+                    throw new IllegalArgumentException("Null filehandle was returned for " + configID);
                 }
-                PluginMetadata pluginData = ((PluginMetadata) metadata.get(configID));
+                PluginType pluginData = metadata.get(configID);
                 // Only bother with the hash if we got it from a source other than the download file itself
-                PluginMetadata.Hash hash = pluginData == null ? null : pluginData.getHash();
-                if(hash != null) {
+                HashType hash = pluginData == null ? null : pluginData.getPluginArtifact().get(0).getHash();
+                if (hash != null) {
                     String actual = ConfigurationStoreUtil.getActualChecksum(tempFile, hash.getType());
-                    if(!actual.equals(hash.getValue())) {
-                        log.error("File download incorrect (expected "+hash.getType()+" hash "+hash.getValue()+" but got "+actual+")");
-                        throw new IOException("File download incorrect (expected "+hash.getType()+" hash "+hash.getValue()+" but got "+actual+")");
+                    if (!actual.equals(hash.getValue())) {
+                        log.error(
+                                "File download incorrect (expected " + hash.getType() + " hash " + hash.getValue() + " but got " + actual + ")");
+                        throw new IOException(
+                                "File download incorrect (expected " + hash.getType() + " hash " + hash.getValue() + " but got " + actual + ")");
                     }
                 }
                 // See if the download file has plugin metadata
-                if(pluginData == null) {
+                if (pluginData == null) {
                     try {
                         pluginData = loadCARFile(tempFile, false);
                     } catch (Exception e) {
-                        log.error("Unable to read plugin metadata: "+e.getMessage());
-                        throw (IOException)new IOException("Unable to read plugin metadata: "+e.getMessage()).initCause(e);
+                        log.error("Unable to read plugin metadata: " + e.getMessage());
+                        throw (IOException) new IOException(
+                                "Unable to read plugin metadata: " + e.getMessage()).initCause(e);
                     }
                 }
-                if(pluginData != null) { // it's a plugin, not a plain JAR
+                PluginArtifactType instance = null;
+                if (pluginData != null) { // it's a plugin, not a plain JAR
                     validatePlugin(pluginData);
+                    instance = pluginData.getPluginArtifact().get(0);
                 }
                 monitor.getResults().setCurrentMessage("Copying " + result.getConfigID() + " to the repository");
-                writeableRepo.copyToRepository(tempFile, result.getConfigID(), monitor); //todo: download SNAPSHOTS if previously available?
-                if(!tempFile.delete()) {
-                    log.warn("Unable to delete temporary download file "+tempFile.getAbsolutePath());
+                writeableRepo.copyToRepository(tempFile, result.getConfigID(),
+                        monitor); //todo: download SNAPSHOTS if previously available?
+                if (!tempFile.delete()) {
+                    log.warn("Unable to delete temporary download file " + tempFile.getAbsolutePath());
                     tempFile.deleteOnExit();
                 }
-                if (pluginData != null)
-                    installConfigXMLData(result.getConfigID(), pluginData);
-                else
+                if (pluginData != null) {
+                    installConfigXMLData(result.getConfigID(), instance);
+                } else {
                     log.debug("No config XML data to install.");
-                if(dependency) {
+                }
+                if (dependency) {
                     monitor.getResults().addDependencyInstalled(configID);
                     configID = result.getConfigID();
                 } else {
@@ -750,14 +807,15 @@
                 }
                 pluginWasInstalled = true;
                 if (pluginData != null)
-                    log.info("Installed plugin with moduleId="+pluginData.getModuleId() + " and name="+pluginData.getName());
+                    log.info(
+                            "Installed plugin with moduleId=" + pluginData.getPluginArtifact().get(0).getModuleId() + " and name=" + pluginData.getName());
                 else
-                    log.info("Installed artifact="+configID);
+                    log.info("Installed artifact=" + configID);
             } finally {
                 result.getStream().close();
             }
         } else {
-            if(dependency) {
+            if (dependency) {
                 monitor.getResults().addDependencyPresent(configID);
             } else {
                 monitor.getResults().addInstalledConfigID(configID);
@@ -766,25 +824,25 @@
         // Download and install the dependencies
         try {
             ConfigurationData data = null;
-            if(!configID.isResolved()) {
+            if (!configID.isResolved()) {
                 // See if something's running
-                for (int i = matches.length-1; i >= 0; i--) {
+                for (int i = matches.length - 1; i >= 0; i--) {
                     Artifact match = matches[i];
-                    if(configStore.containsConfiguration(match) && configManager.isRunning(match)) {
-                        log.debug("Found required configuration="+match+" and it is running.");
+                    if (configStore.containsConfiguration(match) && configManager.isRunning(match)) {
+                        log.debug("Found required configuration=" + match + " and it is running.");
                         return; // its dependencies must be OK
                     } else {
-                        log.debug("Either required configuration="+match+" is not installed or it is not running.");
+                        log.debug("Either required configuration=" + match + " is not installed or it is not running.");
                     }
                 }
                 // Go with something that's installed
-                configID = matches[matches.length-1];
+                configID = matches[matches.length - 1];
             }
-            if(configStore.containsConfiguration(configID)) {
-                if(configManager.isRunning(configID)) {
+            if (configStore.containsConfiguration(configID)) {
+                if (configManager.isRunning(configID)) {
                     return; // its dependencies must be OK
                 }
-                log.debug("Loading configuration="+configID);
+                log.debug("Loading configuration=" + configID);
                 data = configStore.loadConfiguration(configID);
             }
             Dependency[] dependencies = data == null ? getDependencies(writeableRepo, configID) : getDependencies(data);
@@ -792,67 +850,73 @@
             for (int i = 0; i < dependencies.length; i++) {
                 Dependency dep = dependencies[i];
                 Artifact artifact = dep.getArtifact();
-                log.debug("Attempting to download dependency="+artifact+" for configuration="+configID);
+                log.debug("Attempting to download dependency=" + artifact + " for configuration=" + configID);
                 downloadArtifact(artifact, metadata, repos, username, password, monitor, soFar, true);
             }
         } catch (NoSuchConfigException e) {
-            log.error("Installed configuration into repository but ConfigStore does not see it: "+e.getMessage());
-            throw new IllegalStateException("Installed configuration into repository but ConfigStore does not see it: "+e.getMessage(), e);
+            log.error("Installed configuration into repository but ConfigStore does not see it: " + e.getMessage());
+            throw new IllegalStateException(
+                    "Installed configuration into repository but ConfigStore does not see it: " + e.getMessage(), e);
         } catch (InvalidConfigException e) {
-            log.error("Installed configuration into repository but ConfigStore cannot load it: "+e.getMessage());
-            throw new IllegalStateException("Installed configuration into repository but ConfigStore cannot load it: "+e.getMessage(), e);
+            log.error("Installed configuration into repository but ConfigStore cannot load it: " + e.getMessage());
+            throw new IllegalStateException(
+                    "Installed configuration into repository but ConfigStore cannot load it: " + e.getMessage(), e);
         }
         // Copy any files out of the artifact
-        PluginMetadata currentPlugin = configManager.isConfiguration(configID) ? getPluginMetadata(configID) : null;
-        if(pluginWasInstalled && currentPlugin != null && currentPlugin.getFilesToCopy() != null) {
+        PluginType currentPlugin = configManager.isConfiguration(configID) ? getPluginMetadata(configID) : null;
+        if (pluginWasInstalled && currentPlugin != null) {
             extractPluginFiles(configID, currentPlugin, monitor);
         }
     }
 
-    private void extractPluginFiles(Artifact configID, PluginMetadata currentPlugin, ResultsFileWriteMonitor monitor) throws IOException {
-        for (int i = 0; i < currentPlugin.getFilesToCopy().length; i++) {
-            PluginMetadata.CopyFile data = currentPlugin.getFilesToCopy()[i];
+    private void extractPluginFiles(Artifact configID, PluginType currentPlugin, ResultsFileWriteMonitor monitor) throws IOException {
+        PluginArtifactType instance = currentPlugin.getPluginArtifact().get(0);
+        for (CopyFileType data: instance.getCopyFile()) {
             monitor.getResults().setCurrentFilePercent(-1);
-            monitor.getResults().setCurrentFile(data.getSourceFile());
-            monitor.getResults().setCurrentMessage("Copying "+data.getSourceFile()+" from plugin to Geronimo installation");
-            Set set;
-            String sourceFile = data.getSourceFile().trim();
+            monitor.getResults().setCurrentFile(data.getValue());
+            monitor.getResults().setCurrentMessage(
+                    "Copying " + data.getValue() + " from plugin to Geronimo installation");
+            Set<URL> set;
+            String sourceFile = data.getValue().trim();
             try {
                 set = configStore.resolve(configID, null, sourceFile);
             } catch (NoSuchConfigException e) {
-                log.error("Unable to identify module "+configID+" to copy files from");
-                throw new IllegalStateException("Unable to identify module "+configID+" to copy files from", e);
+                log.error("Unable to identify module " + configID + " to copy files from");
+                throw new IllegalStateException("Unable to identify module " + configID + " to copy files from", e);
             }
-            if(set.size() == 0) {
-                log.error("Installed configuration into repository but cannot locate file to copy "+sourceFile);
+            if (set.size() == 0) {
+                log.error("Installed configuration into repository but cannot locate file to copy " + sourceFile);
                 continue;
             }
-            File targetDir = data.isRelativeToServer() ? serverInfo.resolveServer(data.getDestDir()) : serverInfo.resolve(data.getDestDir());
+            boolean relativeToServer = "server".equals(data.getRelativeTo());
+            File targetDir = relativeToServer ? serverInfo.resolveServer(
+                    data.getDestDir()) : serverInfo.resolve(data.getDestDir());
 
             createDirectory(targetDir);
-            if(!targetDir.isDirectory()) {
-                log.error("Plugin install cannot write file "+data.getSourceFile()+" to "+data.getDestDir()+" because "+targetDir.getAbsolutePath()+" is not a directory");
+            if (!targetDir.isDirectory()) {
+                log.error(
+                        "Plugin install cannot write file " + data.getValue() + " to " + data.getDestDir() + " because " + targetDir.getAbsolutePath() + " is not a directory");
                 continue;
             }
-            if(!targetDir.canWrite()) {
-                log.error("Plugin install cannot write file "+data.getSourceFile()+" to "+data.getDestDir()+" because "+targetDir.getAbsolutePath()+" is not writable");
+            if (!targetDir.canWrite()) {
+                log.error(
+                        "Plugin install cannot write file " + data.getValue() + " to " + data.getDestDir() + " because " + targetDir.getAbsolutePath() + " is not writable");
                 continue;
             }
-            for (Iterator it = set.iterator(); it.hasNext();) {
-                URL url = (URL) it.next();
+            for (URL url: set) {
                 String path = url.getPath();
-                if(path.lastIndexOf('/') > -1) {
+                if (path.lastIndexOf('/') > -1) {
                     path = path.substring(path.lastIndexOf('/'));
                 }
                 File target = new File(targetDir, path);
-                if(!target.exists()) {
-                    if(!target.createNewFile()) {
-                        log.error("Plugin install cannot create new file "+target.getAbsolutePath());
+                if (!target.exists()) {
+                    if (!target.createNewFile()) {
+                        log.error("Plugin install cannot create new file " + target.getAbsolutePath());
                         continue;
                     }
                 }
-                if(!target.canWrite()) {
-                    log.error("Plugin install cannot write to file "+target.getAbsolutePath());
+                if (!target.canWrite()) {
+                    log.error("Plugin install cannot write to file " + target.getAbsolutePath());
                     continue;
                 }
                 copyFile(url.openStream(), new FileOutputStream(target));
@@ -872,7 +936,7 @@
     private void copyFile(InputStream in, FileOutputStream out) throws IOException {
         byte[] buf = new byte[4096];
         int count;
-        while((count = in.read(buf)) > -1) {
+        while ((count = in.read(buf)) > -1) {
             out.write(buf, 0, count);
         }
         in.close();
@@ -886,42 +950,44 @@
      */
     private File downloadFile(OpenResult result, ResultsFileWriteMonitor monitor) throws IOException {
         InputStream in = result.getStream();
-        if(in == null) {
+        if (in == null) {
             log.error("Invalid InputStream for downloadFile");
             throw new IllegalStateException();
         }
         FileOutputStream out = null;
         byte[] buf = null;
-        try {        
+        try {
             monitor.writeStarted(result.getConfigID().toString(), result.fileSize);
             File file = File.createTempFile("geronimo-plugin-download-", ".tmp");
             out = new FileOutputStream(file);
             buf = new byte[65536];
             int count, total = 0;
-            while((count = in.read(buf)) > -1) {
+            while ((count = in.read(buf)) > -1) {
                 out.write(buf, 0, count);
                 monitor.writeProgress(total += count);
             }
             monitor.writeComplete(total);
-            log.info(((DownloadResults)monitor.getResults()).getCurrentMessage());
+            log.info(((DownloadResults) monitor.getResults()).getCurrentMessage());
             in.close();
             in = null;
             out.close();
             out = null;
             buf = null;
-            return file;            
+            return file;
         } finally {
             if (in != null) {
                 try {
                     in.close();
                     in = null;
-                } catch (IOException ignored) { }
+                } catch (IOException ignored) {
+                }
             }
             if (out != null) {
                 try {
                     out.close();
                     out = null;
-                } catch (IOException ignored) { }
+                } catch (IOException ignored) {
+                }
             }
             buf = null;
         }
@@ -933,7 +999,7 @@
     private static Dependency[] getDependencies(Repository repo, Artifact artifact) {
         Set set = repo.getDependencies(artifact);
         Dependency[] results = new Dependency[set.size()];
-        int index=0;
+        int index = 0;
         for (Iterator it = set.iterator(); it.hasNext(); ++index) {
             Artifact dep = (Artifact) it.next();
             results[index] = new Dependency(dep, ImportType.CLASSES);
@@ -958,26 +1024,26 @@
      * Constructs a URL to a particular artifact in a particular repository
      */
     private static URL getURL(Artifact configId, URL repository) throws MalformedURLException {
-	URL context;
-	if(repository.toString().trim().endsWith("/")) {
-	    context = repository;
-	} else {
-	    context = new URL(repository.toString().trim()+"/");
-	}
-
-	String qualifiedVersion = configId.getVersion().toString();
-	if (configId.getVersion() instanceof SnapshotVersion) {
-            SnapshotVersion ssVersion = (SnapshotVersion)configId.getVersion();
+        URL context;
+        if (repository.toString().trim().endsWith("/")) {
+            context = repository;
+        } else {
+            context = new URL(repository.toString().trim() + "/");
+        }
+
+        String qualifiedVersion = configId.getVersion().toString();
+        if (configId.getVersion() instanceof SnapshotVersion) {
+            SnapshotVersion ssVersion = (SnapshotVersion) configId.getVersion();
             String timestamp = ssVersion.getTimestamp();
             int buildNumber = ssVersion.getBuildNumber();
-            if (timestamp!=null && buildNumber!=0) {
+            if (timestamp != null && buildNumber != 0) {
                 qualifiedVersion = qualifiedVersion.replaceAll("SNAPSHOT", timestamp + "-" + buildNumber);
             }
-	}
-        return new URL(context, configId.getGroupId().replace('.','/') + "/"
-                     + configId.getArtifactId() + "/" + configId.getVersion()
-                     + "/" +configId.getArtifactId() + "-"
-                     + qualifiedVersion + "." +configId.getType());
+        }
+        return new URL(context, configId.getGroupId().replace('.', '/') + "/"
+                + configId.getArtifactId() + "/" + configId.getVersion()
+                + "/" + configId.getArtifactId() + "-"
+                + qualifiedVersion + "." + configId.getType());
     }
 
     /**
@@ -985,52 +1051,51 @@
      * The username and password provided are only used if one of the repositories
      * returns an HTTP authentication failure on the first try.
      *
-     * @param artifact  The artifact we're looking for, or null to just connect to the base repo URL
-     * @param repos     The base URLs to the repositories to search for the artifact
-     * @param username  A username if one of the repositories might require authentication
-     * @param password  A password if one of the repositories might require authentication
-     * @param monitor   Callback for progress on the connection operation
-     *
-     * @throws IOException Occurs when the IO with the repository failed
-     * @throws FailedLoginException Occurs when a repository requires authentication and either
-     *                              no username and password were provided or they weren't
-     *                              accepted
+     * @param artifact The artifact we're looking for, or null to just connect to the base repo URL
+     * @param repos    The base URLs to the repositories to search for the artifact
+     * @param username A username if one of the repositories might require authentication
+     * @param password A password if one of the repositories might require authentication
+     * @param monitor  Callback for progress on the connection operation
+     * @throws IOException                Occurs when the IO with the repository failed
+     * @throws FailedLoginException       Occurs when a repository requires authentication and either
+     *                                    no username and password were provided or they weren't
+     *                                    accepted
      * @throws MissingDependencyException Occurs when none of the repositories has the artifact
      *                                    in question
      */
-    private static OpenResult openStream(Artifact artifact, URL[] repos, String username, String password, ResultsFileWriteMonitor monitor) throws IOException, FailedLoginException, MissingDependencyException {
-        if(artifact != null) {
+    private static OpenResult openStream(Artifact artifact, List<String> repos, String username, String password, ResultsFileWriteMonitor monitor) throws IOException, FailedLoginException, MissingDependencyException {
+        if (artifact != null) {
             if (!artifact.isResolved() || artifact.getVersion().toString().indexOf("SNAPSHOT") >= 0) {
                 artifact = findArtifact(artifact, repos, username, password, monitor);
             }
         }
-        if(monitor != null) {
+        if (monitor != null) {
             monitor.getResults().setCurrentFilePercent(-1);
-            monitor.getResults().setCurrentMessage("Downloading "+artifact+"...");
+            monitor.getResults().setCurrentMessage("Downloading " + artifact + "...");
             monitor.setTotalBytes(-1); // In case the server doesn't say
         }
         InputStream in;
-        LinkedList list = new LinkedList();
-        list.addAll(Arrays.asList(repos));
+        LinkedList<String> list = new LinkedList<String>();
+        list.addAll(repos);
         while (true) {
-            if(list.isEmpty()) {
-                log.error("Unable to download dependency artifact="+artifact);
-                throw new MissingDependencyException("Unable to download dependency "+artifact);
+            if (list.isEmpty()) {
+                log.error("Unable to download dependency artifact=" + artifact);
+                throw new MissingDependencyException("Unable to download dependency " + artifact);
             }
-            if(monitor != null) {
+            if (monitor != null) {
                 monitor.setTotalBytes(-1); // Just to be sure
             }
-            URL repository = (URL) list.removeFirst();
+            URL repository = new URL(list.removeFirst());
             URL url = artifact == null ? repository : getURL(artifact, repository);
             if (artifact != null)
-                log.info("Attempting to download "+artifact+" from "+url);
+                log.info("Attempting to download " + artifact + " from " + url);
             else
-                log.info("Attempting to download "+url);
+                log.info("Attempting to download " + url);
             in = connect(url, username, password, monitor);
-            if(in != null) {
+            if (in != null) {
                 return new OpenResult(artifact, in, monitor == null ? -1 : monitor.getTotalBytes());
             } else {
-                log.info("Failed to download artifact="+artifact+" from url="+url);
+                log.info("Failed to download artifact=" + artifact + " from url=" + url);
             }
         }
     }
@@ -1048,47 +1113,49 @@
      */
     private static InputStream connect(URL url, String username, String password, ResultsFileWriteMonitor monitor, String method) throws IOException, FailedLoginException {
         URLConnection con = url.openConnection();
-        if(con instanceof HttpURLConnection) {
+        if (con instanceof HttpURLConnection) {
             HttpURLConnection http = (HttpURLConnection) url.openConnection();
-            if(method != null) {
+            if (method != null) {
                 http.setRequestMethod(method);
             }
             http.connect();
-            if(http.getResponseCode() == 401) { // need to authenticate
-                if(username == null || username.equals("")) {
-                    log.error("Server returned 401 "+http.getResponseMessage());
-                    throw new FailedLoginException("Server returned 401 "+http.getResponseMessage());
+            if (http.getResponseCode() == 401) { // need to authenticate
+                if (username == null || username.equals("")) {
+                    log.error("Server returned 401 " + http.getResponseMessage());
+                    throw new FailedLoginException("Server returned 401 " + http.getResponseMessage());
                 }
                 http = (HttpURLConnection) url.openConnection();
-                http.setRequestProperty("Authorization", "Basic " + new String(Base64.encode((username + ":" + password).getBytes())));
-                if(method != null) {
+                http.setRequestProperty("Authorization",
+                        "Basic " + new String(Base64.encode((username + ":" + password).getBytes())));
+                if (method != null) {
                     http.setRequestMethod(method);
                 }
                 http.connect();
-                if(http.getResponseCode() == 401) {
-                    log.error("Server returned 401 "+http.getResponseMessage());
-                    throw new FailedLoginException("Server returned 401 "+http.getResponseMessage());
-                } else if(http.getResponseCode() == 404) {
+                if (http.getResponseCode() == 401) {
+                    log.error("Server returned 401 " + http.getResponseMessage());
+                    throw new FailedLoginException("Server returned 401 " + http.getResponseMessage());
+                } else if (http.getResponseCode() == 404) {
                     return null; // Not found at this repository
                 }
-                if(monitor != null && http.getContentLength() > 0) {
+                if (monitor != null && http.getContentLength() > 0) {
                     monitor.setTotalBytes(http.getContentLength());
                 }
                 return http.getInputStream();
-            } else if(http.getResponseCode() == 404) {
+            } else if (http.getResponseCode() == 404) {
                 return null; // Not found at this repository
             } else {
-                if(monitor != null && http.getContentLength() > 0) {
+                if (monitor != null && http.getContentLength() > 0) {
                     monitor.setTotalBytes(http.getContentLength());
                 }
                 return http.getInputStream();
             }
         } else {
-            if(username != null && !username.equals("")) {
-                con.setRequestProperty("Authorization", "Basic " + new String(Base64.encode((username + ":" + password).getBytes())));
+            if (username != null && !username.equals("")) {
+                con.setRequestProperty("Authorization",
+                        "Basic " + new String(Base64.encode((username + ":" + password).getBytes())));
                 try {
                     con.connect();
-                    if(monitor != null && con.getContentLength() > 0) {
+                    if (monitor != null && con.getContentLength() > 0) {
                         monitor.setTotalBytes(con.getContentLength());
                     }
                     return con.getInputStream();
@@ -1098,7 +1165,7 @@
             } else {
                 try {
                     con.connect();
-                    if(monitor != null && con.getContentLength() > 0) {
+                    if (monitor != null && con.getContentLength() > 0) {
                         monitor.setTotalBytes(con.getContentLength());
                     }
                     return con.getInputStream();
@@ -1113,29 +1180,25 @@
      * Searches for an artifact in the listed repositories, where the artifact
      * may have wildcards in the ID.
      */
-    private static Artifact findArtifact(Artifact query, URL[] repos, String username, String password, ResultsFileWriteMonitor monitor) throws MissingDependencyException {
-        if(query.getGroupId() == null || query.getArtifactId() == null || query.getType() == null) {
-            log.error("No support yet for dependencies missing more than a version: "+query);
-            throw new MissingDependencyException("No support yet for dependencies missing more than a version: "+query);
-        }
-        List list = new ArrayList();
-        for (int i = 0; i < repos.length; i++) {
-            list.add(repos[i]);
+    private static Artifact findArtifact(Artifact query, List<String> repos, String username, String password, ResultsFileWriteMonitor monitor) throws MissingDependencyException {
+        if (query.getGroupId() == null || query.getArtifactId() == null || query.getType() == null) {
+            log.error("No support yet for dependencies missing more than a version: " + query);
+            throw new MissingDependencyException(
+                    "No support yet for dependencies missing more than a version: " + query);
         }
         Artifact result = null;
-        for (int i = 0; i < list.size(); i++) {
-            URL url = (URL) list.get(i);
+        for (String repo : repos) {
             try {
-                result = findArtifact(query, url, username, password, monitor);
+                result = findArtifact(query, new URL(repo), username, password, monitor);
             } catch (Exception e) {
-                log.warn("Unable to read from "+url, e);
+                log.warn("Unable to read from " + repo, e);
             }
-            if(result != null) {
+            if (result != null) {
                 return result;
             }
         }
-        log.error("No repository has a valid artifact for "+query);
-        throw new MissingDependencyException("No repository has a valid artifact for "+query);
+        log.error("No repository has a valid artifact for " + query);
+        throw new MissingDependencyException("No repository has a valid artifact for " + query);
     }
 
     /**
@@ -1143,19 +1206,19 @@
      * have wildcards in the ID.
      */
     private static Artifact findArtifact(Artifact query, URL url, String username, String password, ResultsFileWriteMonitor monitor) throws IOException, FailedLoginException, ParserConfigurationException, SAXException {
-        monitor.getResults().setCurrentMessage("Searching for "+query+" at "+url);
+        monitor.getResults().setCurrentMessage("Searching for " + query + " at " + url);
         String base = query.getGroupId().replace('.', '/') + "/" + query.getArtifactId();
-        String path = base +"/maven-metadata.xml";
-        URL metaURL = new URL(url.toString().trim().endsWith("/") ? url : new URL(url.toString().trim()+"/"), path);
+        String path = base + "/maven-metadata.xml";
+        URL metaURL = new URL(url.toString().trim().endsWith("/") ? url : new URL(url.toString().trim() + "/"), path);
         InputStream in = connect(metaURL, username, password, monitor);
         if (in == null) {
-            log.error("No meta-data file was found at "+metaURL.toString());
-            path=base+"/maven-metadata-local.xml";
-            metaURL = new URL(url.toString().endsWith("/") ? url : new URL(url.toString()+"/"), path);
+            log.error("No meta-data file was found at " + metaURL.toString());
+            path = base + "/maven-metadata-local.xml";
+            metaURL = new URL(url.toString().endsWith("/") ? url : new URL(url.toString() + "/"), path);
             in = connect(metaURL, username, password, monitor);
         }
-        if(in == null) {
-            log.error("No meta-data file was found at "+metaURL.toString());
+        if (in == null) {
+            log.error("No meta-data file was found at " + metaURL.toString());
             return null;
         }
 
@@ -1164,40 +1227,42 @@
         Document doc = builder.parse(in);
         Element root = doc.getDocumentElement();
         NodeList list = root.getElementsByTagName("versions");
-        if(list.getLength() == 0) {
-            log.error("No artifact versions found in "+metaURL.toString());
+        if (list.getLength() == 0) {
+            log.error("No artifact versions found in " + metaURL.toString());
             return null;
         }
-        list = ((Element)list.item(0)).getElementsByTagName("version");
+        list = ((Element) list.item(0)).getElementsByTagName("version");
         Version[] available = new Version[list.getLength()];
         for (int i = 0; i < available.length; i++) {
             available[i] = new Version(getText(list.item(i)));
         }
         List availableList = Arrays.asList(available);
-        if(availableList.contains(query.getVersion())){
+        if (availableList.contains(query.getVersion())) {
             available = new Version[]{query.getVersion()};
         } else {
             Arrays.sort(available);
         }
-        for(int i=available.length-1; i>=0; i--) {
+        for (int i = available.length - 1; i >= 0; i--) {
             Version version = available[i];
-            URL metadataURL = new URL(url.toString().trim().endsWith("/") ? url : new URL(url.toString().trim()+"/"), base+"/"+version+"/maven-metadata.xml");
+            URL metadataURL = new URL(url.toString().trim().endsWith("/") ? url : new URL(url.toString().trim() + "/"),
+                    base + "/" + version + "/maven-metadata.xml");
             InputStream metadataStream = connect(metadataURL, username, password, monitor);
-            
+
             if (metadataStream == null) {
-                metadataURL = new URL(url.toString().trim().endsWith("/") ? url : new URL(url.toString().trim()+"/"), base+"/"+version+"/maven-metadata-local.xml");
+                metadataURL = new URL(url.toString().trim().endsWith("/") ? url : new URL(url.toString().trim() + "/"),
+                        base + "/" + version + "/maven-metadata-local.xml");
                 metadataStream = connect(metadataURL, username, password, monitor);
-            }            
+            }
             // check for a snapshot qualifier
             if (metadataStream != null) {
                 DocumentBuilder metadatabuilder = XmlUtil.newDocumentBuilderFactory().newDocumentBuilder();
                 Document metadatadoc = metadatabuilder.parse(metadataStream);
                 NodeList snapshots = metadatadoc.getDocumentElement().getElementsByTagName("snapshot");
                 if (snapshots.getLength() >= 1) {
-                    Element snapshot = (Element)snapshots.item(0);
+                    Element snapshot = (Element) snapshots.item(0);
                     String[] timestamp = getChildrenText(snapshot, "timestamp");
                     String[] buildNumber = getChildrenText(snapshot, "buildNumber");
-                    if (timestamp.length>=1 && buildNumber.length>=1) {
+                    if (timestamp.length >= 1 && buildNumber.length >= 1) {
                         try {
                             SnapshotVersion snapshotVersion = new SnapshotVersion(version);
                             snapshotVersion.setBuildNumber(Integer.parseInt(buildNumber[0]));
@@ -1210,20 +1275,22 @@
                 }
                 metadataStream.close();
             }
-            
+
             // look for the artifact in the maven repo
-            Artifact verifiedArtifact = new Artifact(query.getGroupId(), query.getArtifactId(), version, query.getType()); 
+            Artifact verifiedArtifact = new Artifact(query.getGroupId(), query.getArtifactId(), version,
+                    query.getType());
             URL test = getURL(verifiedArtifact, url);
             InputStream testStream = connect(test, username, password, monitor, "HEAD");
-            if(testStream == null) {
-                log.debug("Maven repository "+url+" listed artifact "+query+" version "+version+" but I couldn't find it at "+test);
+            if (testStream == null) {
+                log.debug(
+                        "Maven repository " + url + " listed artifact " + query + " version " + version + " but I couldn't find it at " + test);
                 continue;
             }
             testStream.close();
-            log.debug("Found artifact at "+test);
-            return verifiedArtifact; 
+            log.debug("Found artifact at " + test);
+            return verifiedArtifact;
         }
-        log.error("Could not find an acceptable version of artifact="+query+" from Maven repository="+url);
+        log.error("Could not find an acceptable version of artifact=" + query + " from Maven repository=" + url);
         return null;
     }
 
@@ -1240,11 +1307,11 @@
             SAXParser parser = factory.newSAXParser();
             PluginNameIDHandler handler = new PluginNameIDHandler();
             parser.parse(xml, handler);
-            if(handler.isComplete()) {
+            if (handler.isComplete()) {
                 plugins.put(handler.getName(), Artifact.create(handler.getID()));
             }
         } catch (Exception e) {
-            log.warn("Invalid XML at "+xml.getAbsolutePath(), e);
+            log.warn("Invalid XML at " + xml.getAbsolutePath(), e);
         }
     }
 
@@ -1261,7 +1328,7 @@
             SAXParser parser = factory.newSAXParser();
             PluginNameIDHandler handler = new PluginNameIDHandler();
             parser.parse(xml, handler);
-            if(handler.isComplete()) {
+            if (handler.isComplete()) {
                 plugins.put(handler.getName(), Artifact.create(handler.getID()));
             }
         } catch (Exception e) {
@@ -1273,373 +1340,96 @@
      * Replaces all the dependency elements in the argument configuration data
      * with the dependencies from the actual data for that module.
      */
-    private void overrideDependencies(ConfigurationData data, PluginMetadata metadata) {
+    private void overrideDependencies(ConfigurationData data, PluginType metadata) {
         //todo: this ends up doing a little more work than necessary
-        PluginMetadata temp = createDefaultMetadata(data);
-        metadata.setDependencies(temp.getDependencies());
+        PluginType temp = createDefaultMetadata(data);
+        PluginArtifactType instance = temp.getPluginArtifact().get(0);
+        List<DependencyType> dependencyTypes = metadata.getPluginArtifact().get(0).getDependency();
+        dependencyTypes.clear();
+        dependencyTypes.addAll(instance.getDependency());
     }
 
     /**
      * Generates a default plugin metadata based on the data for this module
      * in the server.
      */
-    private PluginMetadata createDefaultMetadata(ConfigurationData data) {
-        PluginMetadata meta = new PluginMetadata(data.getId().toString(), // name
-                data.getId(), // module ID
-                "Unknown", // category
-                "Please provide a description",
-                null, // URL
-                null, // author
-                null, // hash
-                true, // installed
-                false);
-        meta.setGeronimoVersions(new PluginMetadata.geronimoVersions[]{new PluginMetadata.geronimoVersions(serverInfo.getVersion(), null, null, null)});
-        meta.setJvmVersions(new String[0]);
-        meta.setLicenses(new PluginMetadata.License[0]);
-        meta.setObsoletes(new String[]{new Artifact(data.getId().getGroupId(), data.getId().getArtifactId(), (Version)null, data.getId().getType()).toString()});
-        meta.setFilesToCopy(new PluginMetadata.CopyFile[0]);
-        List deps = new ArrayList();
-        PluginMetadata.Prerequisite prereq = null;
+    private PluginType createDefaultMetadata(ConfigurationData data) {
+        PluginType meta = new PluginType();
+        PluginArtifactType instance = new PluginArtifactType();
+        meta.getPluginArtifact().add(instance);
+        meta.setName(toArtifactType(data.getId()).toString());
+        instance.setModuleId(toArtifactType(data.getId()));
+        meta.setCategory("Unknown");
+//        true, // installed
+//                false);
+        instance.getGeronimoVersion().add(serverInfo.getVersion());
+        instance.getObsoletes().add(toArtifactType(new Artifact(data.getId().getGroupId(),
+                data.getId().getArtifactId(),
+                (Version) null,
+                data.getId().getType())));
+        List<DependencyType> deps = instance.getDependency();
+        PrerequisiteType prereq = null;
         prereq = processDependencyList(data.getEnvironment().getDependencies(), prereq, deps);
         Map children = data.getChildConfigurations();
         for (Iterator it = children.values().iterator(); it.hasNext();) {
             ConfigurationData child = (ConfigurationData) it.next();
             prereq = processDependencyList(child.getEnvironment().getDependencies(), prereq, deps);
         }
-        meta.setDependencies((String[]) deps.toArray(new String[deps.size()]));
-        meta.setPrerequisites(prereq == null ? new PluginMetadata.Prerequisite[0] : new PluginMetadata.Prerequisite[]{prereq});
+        if (prereq != null) {
+            instance.getPrerequisite().add(prereq);
+        }
         return meta;
     }
 
     /**
      * Read the plugin metadata out of a plugin CAR file on disk.
      */
-    private PluginMetadata loadCARFile(File file, boolean definitelyCAR) throws IOException, ParserConfigurationException, SAXException {
-        if(!file.canRead()) {
-            log.error("Cannot read from downloaded CAR file "+file.getAbsolutePath());
+    private PluginType loadCARFile(File file, boolean definitelyCAR) throws IOException, ParserConfigurationException, SAXException, JAXBException, XMLStreamException {
+        if (!file.canRead()) {
+            log.error("Cannot read from downloaded CAR file " + file.getAbsolutePath());
             return null;
         }
         JarFile jar = new JarFile(file);
-        Document doc;
         try {
             JarEntry entry = jar.getJarEntry("META-INF/geronimo-plugin.xml");
-            if(entry == null) {
-                if(definitelyCAR) {
+            if (entry == null) {
+                if (definitelyCAR) {
                     log.error("Downloaded CAR file does not contain META-INF/geronimo-plugin.xml file");
                 }
-                jar.close();
                 return null;
             }
             InputStream in = jar.getInputStream(entry);
-            DocumentBuilder builder = createDocumentBuilder();
-            doc = builder.parse(in);
-            in.close();
+            try {
+                return loadPluginMetadata(in);
+            } finally {
+                in.close();
+            }
         } finally {
             jar.close();
         }
-        return loadPluginMetadata(doc, file.getAbsolutePath());
     }
 
     /**
      * Read a set of plugin metadata from a DOM document.
      */
-    private PluginMetadata loadPluginMetadata(Document doc, String file) throws SAXException, MalformedURLException {
-        Element root = doc.getDocumentElement();
-        if(!root.getNodeName().equals("geronimo-plugin")) {
-            log.error("Configuration archive "+file+" does not have a geronimo-plugin in META-INF/geronimo-plugin.xml");
-            return null;
-        }
-        return processPlugin(root);
+    private PluginType loadPluginMetadata(InputStream in) throws SAXException, MalformedURLException, JAXBException, XMLStreamException {
+        XMLStreamReader xmlStream = XMLINPUT_FACTORY.createXMLStreamReader(in);
+        Unmarshaller unmarshaller = PLUGIN_CONTEXT.createUnmarshaller();

[... 803 lines stripped ...]