aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Becker2012-08-09 13:11:20 (EDT)
committerThomas Becker2012-08-09 13:11:20 (EDT)
commit8ba068c73b7fea6580ed2f6de34bfeb2b956b47a (patch)
treef66b3e56da21e0cac5ff79d5446a52f4b06e76e5
parent03ebcc881cb07f5f949bb652590be6f51ec62fb8 (diff)
downloadorg.eclipse.jetty.project-8ba068c73b7fea6580ed2f6de34bfeb2b956b47a.zip
org.eclipse.jetty.project-8ba068c73b7fea6580ed2f6de34bfeb2b956b47a.tar.gz
org.eclipse.jetty.project-8ba068c73b7fea6580ed2f6de34bfeb2b956b47a.tar.bz2
jetty-9: jetty-plugins module added
-rw-r--r--jetty-plugins/pom.xml68
-rw-r--r--jetty-plugins/src/main/java/org/eclipse/jetty/plugins/Main.java129
-rw-r--r--jetty-plugins/src/main/java/org/eclipse/jetty/plugins/MavenService.java36
-rw-r--r--jetty-plugins/src/main/java/org/eclipse/jetty/plugins/PluginManager.java28
-rw-r--r--jetty-plugins/src/main/java/org/eclipse/jetty/plugins/impl/HttpMavenServiceImpl.java126
-rw-r--r--jetty-plugins/src/main/java/org/eclipse/jetty/plugins/impl/PluginManagerImpl.java110
-rw-r--r--jetty-plugins/src/main/java/org/eclipse/jetty/plugins/model/Plugin.java22
-rw-r--r--jetty-plugins/src/main/java/org/eclipse/jetty/plugins/util/RepositoryParser.java46
-rw-r--r--jetty-plugins/src/main/java/org/eclipse/jetty/plugins/util/StreamUtils.java21
-rw-r--r--jetty-plugins/src/test/java/org/eclipse/jetty/plugins/impl/HttpMavenServiceTest.java65
-rw-r--r--jetty-plugins/src/test/java/org/eclipse/jetty/plugins/impl/PluginManagerTest.java156
-rw-r--r--jetty-plugins/src/test/java/org/eclipse/jetty/plugins/util/RepositoryParserTest.java35
-rw-r--r--jetty-plugins/src/test/resources/example-plugin.jarbin0 -> 629 bytes
-rw-r--r--jetty-plugins/src/test/resources/jetty-jmx-7.6.0.v20120127-plugin.jarbin0 -> 22170 bytes
-rw-r--r--jetty-plugins/src/test/resources/jetty_home/.donotdelete0
-rw-r--r--jetty-plugins/src/test/resources/mavenRepoJettyDirectoryListing.html55
-rw-r--r--jetty-plugins/src/test/resources/mavenRepoJettyJMXDirectoryListing.html36
-rw-r--r--jetty-plugins/src/test/resources/mavenRepoJettyJNDIDirectoryListing.html30
-rw-r--r--pom.xml2
19 files changed, 964 insertions, 1 deletions
diff --git a/jetty-plugins/pom.xml b/jetty-plugins/pom.xml
new file mode 100644
index 0000000..dd7d7b5
--- /dev/null
+++ b/jetty-plugins/pom.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>jetty-project</artifactId>
+ <groupId>org.eclipse.jetty</groupId>
+ <version>7.6.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>jetty-plugins</artifactId>
+ <name>jetty-plugins</name>
+ <description>The jetty plugin artifact.</description>
+ <url>${jetty.url}</url>
+ <properties>
+ <aetherVersion>1.13.1</aetherVersion>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ <archive>
+ <manifest>
+ <mainClass>org.eclipse.jetty.plugins.Main</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <version>1.0</version> <!-- TODO: version should be inherited from parent pom.xml -->
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/Main.java b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/Main.java
new file mode 100644
index 0000000..a35f09f
--- /dev/null
+++ b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/Main.java
@@ -0,0 +1,129 @@
+// ========================================================================
+// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.plugins;
+
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jetty.plugins.impl.HttpMavenServiceImpl;
+import org.eclipse.jetty.plugins.impl.PluginManagerImpl;
+
+/* ------------------------------------------------------------ */
+/**
+ */
+public class Main {
+ private static final String JETTY_HOME = "JETTY_HOME";
+
+ private MavenService _mavenService = new HttpMavenServiceImpl();
+ private PluginManager _pluginManager;
+ private String _jettyHome;
+ private String _installPlugin;
+ private boolean _listPlugins;
+ private String _repositoryUrl;
+ private String _groupId;
+ private String _version;
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ Main main = new Main();
+ main.execute(args);
+ }
+
+ private void execute(String[] args) {
+ parseEnvironmentVariables();
+ parseCommandline(args);
+ configureMavenService();
+
+ _pluginManager = new PluginManagerImpl(_mavenService, _jettyHome);
+
+ if (_listPlugins) {
+ listPlugins();
+ } else if (_installPlugin != null) {
+ installPlugin();
+ }
+ }
+
+ private void configureMavenService() {
+ if (_repositoryUrl != null) {
+ _mavenService.setRepositoryUrl(_repositoryUrl);
+ }
+ if (_groupId != null) {
+ _mavenService.setGroupId(_groupId);
+ }
+ if (_version != null) {
+ _mavenService.setVersion(_version);
+ }
+ }
+
+ private void listPlugins() {
+ List<String> availablePlugins = _pluginManager.listAvailablePlugins();
+ for (String pluginName : availablePlugins) {
+ System.out.println(pluginName);
+ }
+ }
+
+ private void installPlugin() {
+ _pluginManager.installPlugin(_installPlugin);
+ System.out.println("Successfully installed plugin: " + _installPlugin
+ + " to " + _jettyHome);
+ }
+
+ private void parseEnvironmentVariables() {
+ Map<String, String> env = System.getenv();
+ if (env.containsKey(JETTY_HOME)) {
+ _jettyHome = env.get(JETTY_HOME);
+ }
+ }
+
+ private void parseCommandline(String[] args) {
+ int i = 0;
+ for (String arg : args) {
+ i++;
+
+ if (arg.startsWith("--jettyHome=")) {
+ _jettyHome = arg.substring(12);
+ }
+ if (arg.startsWith("--repositoryUrl=")) {
+ _repositoryUrl = arg.substring(16);
+ }
+ if (arg.startsWith("--groupId=")) {
+ _groupId = arg.substring(10);
+ }
+ if (arg.startsWith("--version=")) {
+ _version = arg.substring(10);
+ }
+ if (arg.startsWith("install")) {
+ _installPlugin = args[i];
+ }
+ if ("list".equals(arg)) {
+ _listPlugins = true;
+ }
+ }
+
+ // TODO: Usage instead of throwing exceptions
+ if (_jettyHome == null && _installPlugin != null)
+ throw new IllegalArgumentException(
+ "No --jettyHome commandline option specified and no \"JETTY_HOME\" environment variable found!");
+ if (_installPlugin == null && _listPlugins == false)
+ throw new IllegalArgumentException(
+ "Neither install <pluginname> nor list commandline option specified. Nothing to do for me!");
+ if (_installPlugin != null && _listPlugins)
+ throw new IllegalArgumentException(
+ "Please specify either install <pluginname> or list commandline options, but not both at the same time!");
+ }
+
+}
diff --git a/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/MavenService.java b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/MavenService.java
new file mode 100644
index 0000000..a1db631
--- /dev/null
+++ b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/MavenService.java
@@ -0,0 +1,36 @@
+// ========================================================================
+// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+
+package org.eclipse.jetty.plugins;
+
+import java.util.List;
+
+import org.eclipse.jetty.plugins.model.Plugin;
+
+
+/* ------------------------------------------------------------ */
+/**
+ */
+public interface MavenService
+{
+ public List<String> listAvailablePlugins();
+
+ public Plugin getPlugin(String pluginName);
+
+ public void setGroupId(String groupId);
+
+ public void setRepositoryUrl(String repositoryUrl);
+
+ public void setVersion(String version);
+}
diff --git a/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/PluginManager.java b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/PluginManager.java
new file mode 100644
index 0000000..33409e9
--- /dev/null
+++ b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/PluginManager.java
@@ -0,0 +1,28 @@
+// ========================================================================
+// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+
+package org.eclipse.jetty.plugins;
+
+import java.util.List;
+
+
+/* ------------------------------------------------------------ */
+/**
+ */
+public interface PluginManager
+{
+ public List<String> listAvailablePlugins();
+
+ public void installPlugin(String pluginName);
+}
diff --git a/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/impl/HttpMavenServiceImpl.java b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/impl/HttpMavenServiceImpl.java
new file mode 100644
index 0000000..582d738
--- /dev/null
+++ b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/impl/HttpMavenServiceImpl.java
@@ -0,0 +1,126 @@
+package org.eclipse.jetty.plugins.impl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jetty.plugins.MavenService;
+import org.eclipse.jetty.plugins.model.Plugin;
+import org.eclipse.jetty.plugins.util.RepositoryParser;
+import org.eclipse.jetty.plugins.util.StreamUtils;
+
+public class HttpMavenServiceImpl implements MavenService {
+ private static final String REPOSITORY_URL = "http://repo2.maven.org/maven2/";
+ private static final String GROUP_ID = "org/eclipse/jetty";
+ private static final String VERSION = "7.6.0.v20120127"; // TODO: should be
+ // automatically
+ // set
+ private String _repositoryUrl = REPOSITORY_URL;
+ private String _groupId = GROUP_ID;
+ private String _version = VERSION;
+
+ public List<String> listAvailablePlugins() {
+ List<String> availablePlugins = new ArrayList<String>();
+
+ String moduleListing = fetchDirectoryListingOfJettyModules();
+ List<String> modules = RepositoryParser
+ .parseLinksInDirectoryListing(moduleListing);
+
+ for (String module : modules) {
+ String listing = fetchModuleDirectoryListing(module);
+ if (RepositoryParser.isModuleAPlugin(listing)) {
+ availablePlugins.add(module);
+ }
+ }
+
+ return availablePlugins;
+ }
+
+ private String fetchDirectoryListingOfJettyModules() {
+ try {
+ URL url = new URL(_repositoryUrl + _groupId);
+ URLConnection connection = url.openConnection();
+ InputStream inputStream = connection.getInputStream();
+ return StreamUtils.inputStreamToString(inputStream);
+ } catch (MalformedURLException e) {
+ throw new IllegalStateException(e);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private String fetchModuleDirectoryListing(String module) {
+ try {
+ URL configJar = new URL(getModuleDirectory(module));
+ URLConnection connection = configJar.openConnection();
+ InputStream inputStream = connection.getInputStream();
+ return StreamUtils.inputStreamToString(inputStream);
+ } catch (MalformedURLException e) {
+ throw new IllegalStateException(e);
+ } catch (IOException e) {
+ // Honestly, I'm not a friend of ignoring exceptions as it might
+ // hide something important. In this case however it "usually"
+ // just means: THIS IS NOT A PLUGIN! However it still might hide
+ // things. If that'll be the case, I hope I'm not the one who
+ // has to debug my own code. ;)
+ return "not a plugin";
+ }
+ }
+
+ public Plugin getPlugin(String pluginName) {
+ File configJar = getFile(getModulePrefix(pluginName) + "-plugin.jar");
+ return new Plugin(pluginName, configJar);
+ }
+
+ private String getModuleDirectory(String pluginName) {
+ return _repositoryUrl + _groupId + "/" + pluginName + "/" + _version
+ + "/";
+ }
+
+ private String getModulePrefix(String pluginName) {
+ return getModuleDirectory(pluginName) + pluginName + "-" + _version;
+ }
+
+ private File getFile(String urlString) {
+ String fileName = urlString.substring(urlString.lastIndexOf("/") + 1);
+ try {
+ URL url = new URL(urlString);
+ URLConnection connection = url.openConnection();
+ InputStream inputStream = connection.getInputStream();
+ File tempFile = new File(System.getProperty("java.io.tmpdir"),
+ fileName);
+ OutputStream out = new FileOutputStream(tempFile);
+ byte buf[] = new byte[1024];
+ int len;
+ while ((len = inputStream.read(buf)) > 0)
+ out.write(buf, 0, len);
+ out.close();
+ inputStream.close();
+ return tempFile;
+ } catch (MalformedURLException e) {
+ throw new IllegalStateException(e);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void setGroupId(String groupId) {
+ this._groupId = groupId.replace(".", "/");
+ }
+
+ public void setRepositoryUrl(String repositoryUrl) {
+ this._repositoryUrl = repositoryUrl;
+ }
+
+ public void setVersion(String version) {
+ this._version = version;
+ }
+
+}
diff --git a/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/impl/PluginManagerImpl.java b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/impl/PluginManagerImpl.java
new file mode 100644
index 0000000..6b00fd6
--- /dev/null
+++ b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/impl/PluginManagerImpl.java
@@ -0,0 +1,110 @@
+// ========================================================================
+// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.plugins.impl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import org.eclipse.jetty.plugins.MavenService;
+import org.eclipse.jetty.plugins.PluginManager;
+import org.eclipse.jetty.plugins.model.Plugin;
+
+/* ------------------------------------------------------------ */
+/**
+ */
+public class PluginManagerImpl implements PluginManager {
+ private String _jettyHome;
+ private MavenService _mavenService;
+
+ private static List<String> excludes = Arrays.asList("META-INF");
+
+ public PluginManagerImpl(MavenService mavenService, String jettyHome) {
+ this._mavenService = mavenService;
+ this._jettyHome = jettyHome;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.plugins.PluginManager#listAvailablePlugins()
+ */
+ public List<String> listAvailablePlugins() {
+ return _mavenService.listAvailablePlugins();
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.plugins.PluginManager#installPlugin(String)
+ */
+ public void installPlugin(String pluginName) {
+ Plugin plugin = _mavenService.getPlugin(pluginName);
+ installPlugin(plugin);
+ }
+
+ private void installPlugin(Plugin plugin) {
+ try {
+ JarFile pluginJar = new JarFile(plugin.getPluginJar());
+ extractJar(pluginJar);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private void extractJar(JarFile file) {
+ Enumeration<JarEntry> entries = file.entries();
+ while (entries.hasMoreElements()) {
+ extractFileFromJar(file, entries.nextElement());
+ }
+ }
+
+ private void extractFileFromJar(JarFile jarFile, JarEntry jarEntry) {
+ for (String exclude : excludes)
+ if (jarEntry.getName().startsWith(exclude))
+ return;
+
+ System.out.println("Extracting: " + jarEntry.getName());
+ File f = new File(_jettyHome + File.separator + jarEntry.getName());
+ if (jarEntry.isDirectory()) { // if its a directory, create it
+ f.mkdir();
+ return;
+ }
+ InputStream is = null;
+ FileOutputStream fos = null;
+ try {
+ is = jarFile.getInputStream(jarEntry);
+ fos = new FileOutputStream(f);
+ while (is.available() > 0) {
+ fos.write(is.read());
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException(
+ "IOException while extracting plugin jar: ", e);
+ } finally {
+ try {
+ fos.close();
+ is.close();
+ } catch (IOException e) {
+ throw new IllegalStateException(
+ "Couldn't close InputStream or FileOutputStream. This might be a file leak!",
+ e);
+ }
+ }
+ }
+}
diff --git a/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/model/Plugin.java b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/model/Plugin.java
new file mode 100644
index 0000000..a9a06de
--- /dev/null
+++ b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/model/Plugin.java
@@ -0,0 +1,22 @@
+package org.eclipse.jetty.plugins.model;
+
+import java.io.File;
+
+public class Plugin {
+ private String name;
+
+ private File pluginJar;
+
+ public Plugin(String name, File configJar) {
+ this.name = name;
+ this.pluginJar = configJar;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public File getPluginJar() {
+ return pluginJar;
+ }
+}
diff --git a/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/util/RepositoryParser.java b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/util/RepositoryParser.java
new file mode 100644
index 0000000..e7b7038
--- /dev/null
+++ b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/util/RepositoryParser.java
@@ -0,0 +1,46 @@
+/**
+ *
+ */
+package org.eclipse.jetty.plugins.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author tbecker
+ *
+ */
+public class RepositoryParser {
+ private final static List<String> EXCLUDES = Arrays.asList("..");
+
+ public static List<String> parseLinksInDirectoryListing(String listing) {
+ List<String> modules = new ArrayList<String>();
+ List<String> lines = Arrays.asList(listing.split("\n"));
+ for (String line : lines) {
+ Pattern p = Pattern.compile(".*?<a href=\"[^>]+>(?=([^</]+)/).*");
+ Matcher m = p.matcher(line);
+ if (m.matches()) {
+ if (!EXCLUDES.contains(m.group(1))) {
+ modules.add(m.group(1));
+ }
+ }
+ }
+ return modules;
+ }
+
+ public static boolean isModuleAPlugin(String listing) {
+ List<String> lines = Arrays.asList(listing.split("\n"));
+ for (String line : lines) {
+ Pattern p = Pattern.compile("-plugin\\.jar");
+ Matcher m = p.matcher(line);
+ if (m.find()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/util/StreamUtils.java b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/util/StreamUtils.java
new file mode 100644
index 0000000..9de4241
--- /dev/null
+++ b/jetty-plugins/src/main/java/org/eclipse/jetty/plugins/util/StreamUtils.java
@@ -0,0 +1,21 @@
+package org.eclipse.jetty.plugins.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class StreamUtils {
+ public static String inputStreamToString(InputStream inputStream) throws IOException {
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ StringBuilder stringBuilder = new StringBuilder();
+ String line = null;
+
+ while ((line = bufferedReader.readLine()) != null) {
+ stringBuilder.append(line + "\n");
+ }
+
+ bufferedReader.close();
+ return stringBuilder.toString();
+ }
+}
diff --git a/jetty-plugins/src/test/java/org/eclipse/jetty/plugins/impl/HttpMavenServiceTest.java b/jetty-plugins/src/test/java/org/eclipse/jetty/plugins/impl/HttpMavenServiceTest.java
new file mode 100644
index 0000000..be4df02
--- /dev/null
+++ b/jetty-plugins/src/test/java/org/eclipse/jetty/plugins/impl/HttpMavenServiceTest.java
@@ -0,0 +1,65 @@
+package org.eclipse.jetty.plugins.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.jetty.plugins.MavenService;
+import org.eclipse.jetty.plugins.model.Plugin;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * This is currently more an integration test downloading real stuff from real
+ * maven repositories. Actually it's preferred to have a real unit test or at
+ * least a local repository server. But since HttpClient.send(exchange) has an
+ * api which is really hard to mock, I will leave that excercise for later.
+ *
+ * However this tests should be disabled for the general build and ci.
+ *
+ * @author tbecker
+ *
+ */
+public class HttpMavenServiceTest {
+ private MavenService _mavenService = new HttpMavenServiceImpl();
+
+ private static final String JETTY_JMX_PLUGIN_NAME = "jetty-jmx";
+ private static final String PRIVATE_NEXUS_REPOSITORY_URL = "http://gravity-design.de:8080/nexus/content/repositories/releases/";
+ private static final String MAVEN_CENTRAL_URL = "http://repo2.maven.org/maven2/";
+
+ @Before
+ public void setUp() throws Exception {
+ _mavenService.setRepositoryUrl(PRIVATE_NEXUS_REPOSITORY_URL);
+ }
+
+ @Test
+ @Ignore("requires online repo")
+ public void testListAvailablePlugins() {
+ List<String> pluginNames = _mavenService.listAvailablePlugins();
+ assertThat(pluginNames.size(), is(2));
+ }
+
+ @Test
+ @Ignore("requires online repo")
+ public void testGetPluginJar() throws IOException {
+ Plugin plugin = _mavenService.getPlugin(JETTY_JMX_PLUGIN_NAME);
+ assertThat("jetty-jmx should contain a plugin-jar",
+ plugin.getPluginJar(), is(notNullValue()));
+ }
+
+ @Test
+ @Ignore("requires online repo")
+ public void testGetConfigJar() throws IOException {
+ Plugin plugin = _mavenService.getPlugin(JETTY_JMX_PLUGIN_NAME);
+ File configJar = plugin.getPluginJar();
+ assertThat(configJar, is(not(nullValue())));
+ }
+
+}
diff --git a/jetty-plugins/src/test/java/org/eclipse/jetty/plugins/impl/PluginManagerTest.java b/jetty-plugins/src/test/java/org/eclipse/jetty/plugins/impl/PluginManagerTest.java
new file mode 100644
index 0000000..5d7c325
--- /dev/null
+++ b/jetty-plugins/src/test/java/org/eclipse/jetty/plugins/impl/PluginManagerTest.java
@@ -0,0 +1,156 @@
+// ========================================================================
+// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.plugins.impl;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jetty.plugins.MavenService;
+import org.eclipse.jetty.plugins.model.Plugin;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+/* ------------------------------------------------------------ */
+/**
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class PluginManagerTest {
+ @Mock
+ private MavenService _mavenService;
+
+ private PluginManagerImpl _pluginManager;
+
+ private List<String> availablePlugins = createAvailablePluginsTestData();
+ private ClassLoader _classLoader = this.getClass().getClassLoader();
+ private String _tmpDir;
+ private File _javaTmpDir = new File(System.getProperty("java.io.tmpdir"));
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ URL resource = this.getClass().getResource("/jetty_home");
+ _tmpDir = resource.getFile();
+ _pluginManager = new PluginManagerImpl(_mavenService, _tmpDir);
+ }
+
+ @Test
+ public void testListAvailablePlugins() {
+ when(_mavenService.listAvailablePlugins()).thenReturn(availablePlugins);
+ List<String> availablePlugins = _pluginManager.listAvailablePlugins();
+ assertThat("jetty-jmx not found",
+ availablePlugins.contains("jetty-jmx"), is(true));
+ assertThat("jetty-jta not found",
+ availablePlugins.contains("jetty-jta"), is(true));
+ }
+
+ @Test
+ public void testInstallPluginJar() {
+ String pluginName = "jetty-plugin-with-plugin-jar";
+ String pluginJar = _classLoader.getResource("example-plugin.jar")
+ .getFile();
+ File pluginJarFile = new File(pluginJar);
+ Plugin plugin = createTestPlugin(pluginName, pluginJarFile);
+
+ when(_mavenService.getPlugin(pluginName)).thenReturn(plugin);
+
+ _pluginManager.installPlugin(pluginName);
+
+ File someJar = new File(_tmpDir + File.separator + "lib"
+ + File.separator + "someJar.jar");
+ assertThat("someJar.jar does not exist", someJar.exists(), is(true));
+ File someOtherJar = new File(_tmpDir + File.separator + "lib"
+ + File.separator + "someOtherJar.jar");
+ assertThat("someOtherJar.jar does not exist", someOtherJar.exists(),
+ is(true));
+ }
+
+ @Test
+ public void testInstallPlugins() throws IOException {
+
+ String pluginName = "jetty-jmx";
+ String jmxPluginConfigJar = _classLoader.getResource(
+ "jetty-jmx-7.6.0.v20120127-plugin.jar").getFile();
+ File jmxPluginConfigJarFile = new File(jmxPluginConfigJar);
+
+ // Need to copy it to a temp file since the implementation will move the
+ // file and we need to keep the test files where they are.
+ File jmxPluginConfigTempCopy = copyToTempFile(jmxPluginConfigJarFile);
+
+ Plugin plugin = new Plugin(pluginName, jmxPluginConfigTempCopy);
+
+ when(_mavenService.getPlugin(pluginName)).thenReturn(plugin);
+
+ _pluginManager.installPlugin(pluginName);
+
+ File metaInf = new File(_tmpDir + File.separator + "META-INF");
+ File jettyXmlConfigFile = new File(_tmpDir + File.separator + "start.d"
+ + File.separator + "20-jetty-jmx.xml");
+ File jettyJmxJarFile = new File(_tmpDir + File.separator + "lib"
+ + File.separator + "jetty-jmx-7.6.0.v20120127.jar");
+ assertThat("META-INF should be skipped", metaInf.exists(), not(true));
+ assertThat("20-jetty-jmx.xml does not exist",
+ jettyXmlConfigFile.exists(), is(true));
+ assertThat("jetty-jmx-7.6.0.v20120127.jar does not exist",
+ jettyJmxJarFile.exists(), is(true));
+ }
+
+ public File copyToTempFile(File sourceFile) throws IOException {
+ File destFile = new File(_javaTmpDir + File.separator
+ + sourceFile.getName());
+ FileChannel source = null;
+ FileChannel destination = null;
+ try {
+ source = new FileInputStream(sourceFile).getChannel();
+ destination = new FileOutputStream(destFile).getChannel();
+ destination.transferFrom(source, 0, source.size());
+ } finally {
+ if (source != null) {
+ source.close();
+ }
+ if (destination != null) {
+ destination.close();
+ }
+ }
+ return destFile;
+ }
+
+ private List<String> createAvailablePluginsTestData() {
+ List<String> availablePlugins = new ArrayList<String>();
+ availablePlugins.add("jetty-jmx");
+ availablePlugins.add("jetty-jta");
+ return availablePlugins;
+ }
+
+ private Plugin createTestPlugin(String name, File jar) {
+ Plugin plugin = new Plugin(name, jar);
+ return plugin;
+ }
+
+}
diff --git a/jetty-plugins/src/test/java/org/eclipse/jetty/plugins/util/RepositoryParserTest.java b/jetty-plugins/src/test/java/org/eclipse/jetty/plugins/util/RepositoryParserTest.java
new file mode 100644
index 0000000..c8f27ae
--- /dev/null
+++ b/jetty-plugins/src/test/java/org/eclipse/jetty/plugins/util/RepositoryParserTest.java
@@ -0,0 +1,35 @@
+package org.eclipse.jetty.plugins.util;
+
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class RepositoryParserTest {
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ @Test
+ public void testParseLinksInDirectoryListing() throws IOException {
+ String listing = StreamUtils.inputStreamToString(this.getClass().getClassLoader().getResourceAsStream("mavenRepoJettyDirectoryListing.html"));
+ List<String> modules = RepositoryParser.parseLinksInDirectoryListing(listing);
+ assertThat("At least ten jetty modules expected",modules.size(), greaterThan(10));
+ assertThat("jetty-jmx module expected", modules.contains("jetty-jmx"), is(true));
+ }
+
+ @Test
+ public void testIsPlugin() throws IOException{
+ String listing = StreamUtils.inputStreamToString(this.getClass().getClassLoader().getResourceAsStream("mavenRepoJettyJMXDirectoryListing.html"));
+ assertThat("listing describes a plugin", RepositoryParser.isModuleAPlugin(listing), is(true));
+ String nonPluginListing = StreamUtils.inputStreamToString(this.getClass().getClassLoader().getResourceAsStream("mavenRepoJettyJNDIDirectoryListing.html"));
+ assertThat("listing doesn't describe a plugin", RepositoryParser.isModuleAPlugin(nonPluginListing), is(false));
+ }
+
+}
diff --git a/jetty-plugins/src/test/resources/example-plugin.jar b/jetty-plugins/src/test/resources/example-plugin.jar
new file mode 100644
index 0000000..31cd1e0
--- /dev/null
+++ b/jetty-plugins/src/test/resources/example-plugin.jar
Binary files differ
diff --git a/jetty-plugins/src/test/resources/jetty-jmx-7.6.0.v20120127-plugin.jar b/jetty-plugins/src/test/resources/jetty-jmx-7.6.0.v20120127-plugin.jar
new file mode 100644
index 0000000..ed99c27
--- /dev/null
+++ b/jetty-plugins/src/test/resources/jetty-jmx-7.6.0.v20120127-plugin.jar
Binary files differ
diff --git a/jetty-plugins/src/test/resources/jetty_home/.donotdelete b/jetty-plugins/src/test/resources/jetty_home/.donotdelete
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/jetty-plugins/src/test/resources/jetty_home/.donotdelete
diff --git a/jetty-plugins/src/test/resources/mavenRepoJettyDirectoryListing.html b/jetty-plugins/src/test/resources/mavenRepoJettyDirectoryListing.html
new file mode 100644
index 0000000..cd6549c
--- /dev/null
+++ b/jetty-plugins/src/test/resources/mavenRepoJettyDirectoryListing.html
@@ -0,0 +1,55 @@
+<html>
+<head><title>Index of /maven2/org/eclipse/jetty/</title></head>
+<body bgcolor="white">
+<h1>Index of /maven2/org/eclipse/jetty/</h1><hr><pre><a href="../">../</a>
+<a href="aggregate/">aggregate/</a> 22-Dec-2011 21:20 -
+<a href="example-async-rest/">example-async-rest/</a> 09-Mar-2012 16:06 -
+<a href="example-jetty-embedded/">example-jetty-embedded/</a> 09-Mar-2012 16:06 -
+<a href="jetty-ajp/">jetty-ajp/</a> 09-Mar-2012 16:06 -
+<a href="jetty-annotations/">jetty-annotations/</a> 09-Mar-2012 16:06 -
+<a href="jetty-client/">jetty-client/</a> 09-Mar-2012 16:06 -
+<a href="jetty-continuation/">jetty-continuation/</a> 09-Mar-2012 16:06 -
+<a href="jetty-deploy/">jetty-deploy/</a> 09-Mar-2012 16:06 -
+<a href="jetty-distribution/">jetty-distribution/</a> 09-Mar-2012 16:06 -
+<a href="jetty-embedded-examples/">jetty-embedded-examples/</a> 21-Sep-2009 15:50 -
+<a href="jetty-http/">jetty-http/</a> 09-Mar-2012 16:06 -
+<a href="jetty-http-spi/">jetty-http-spi/</a> 09-Mar-2012 16:06 -
+<a href="jetty-io/">jetty-io/</a> 09-Mar-2012 16:06 -
+<a href="jetty-jaspi/">jetty-jaspi/</a> 09-Mar-2012 16:06 -
+<a href="jetty-jmx/">jetty-jmx/</a> 09-Mar-2012 16:06 -
+<a href="jetty-jndi/">jetty-jndi/</a> 09-Mar-2012 16:06 -
+<a href="jetty-jsp/">jetty-jsp/</a> 09-Mar-2012 16:06 -
+<a href="jetty-jsp-2.1/">jetty-jsp-2.1/</a> 25-Oct-2011 01:05 -
+<a href="jetty-monitor/">jetty-monitor/</a> 09-Mar-2012 16:06 -
+<a href="jetty-nested/">jetty-nested/</a> 09-Mar-2012 16:06 -
+<a href="jetty-nosql/">jetty-nosql/</a> 09-Mar-2012 16:06 -
+<a href="jetty-overlay-deployer/">jetty-overlay-deployer/</a> 09-Mar-2012 16:06 -
+<a href="jetty-parent/">jetty-parent/</a> 20-Sep-2011 16:54 -
+<a href="jetty-plus/">jetty-plus/</a> 09-Mar-2012 16:06 -
+<a href="jetty-policy/">jetty-policy/</a> 09-Mar-2012 16:06 -
+<a href="jetty-project/">jetty-project/</a> 09-Mar-2012 16:06 -
+<a href="jetty-rewrite/">jetty-rewrite/</a> 09-Mar-2012 16:06 -
+<a href="jetty-security/">jetty-security/</a> 09-Mar-2012 16:06 -
+<a href="jetty-server/">jetty-server/</a> 09-Mar-2012 16:06 -
+<a href="jetty-servlet/">jetty-servlet/</a> 09-Mar-2012 16:06 -
+<a href="jetty-servlet-tester/">jetty-servlet-tester/</a> 21-Sep-2009 15:52 -
+<a href="jetty-servlets/">jetty-servlets/</a> 09-Mar-2012 16:06 -
+<a href="jetty-start/">jetty-start/</a> 09-Mar-2012 16:06 -
+<a href="jetty-test-webapp/">jetty-test-webapp/</a> 21-Sep-2009 15:50 -
+<a href="jetty-util/">jetty-util/</a> 09-Mar-2012 16:06 -
+<a href="jetty-webapp/">jetty-webapp/</a> 09-Mar-2012 16:06 -
+<a href="jetty-websocket/">jetty-websocket/</a> 09-Mar-2012 16:06 -
+<a href="jetty-xml/">jetty-xml/</a> 09-Mar-2012 16:06 -
+<a href="npn/">npn/</a> 09-Mar-2012 16:05 -
+<a href="orbit/">orbit/</a> 24-Jan-2012 23:22 -
+<a href="osgi/">osgi/</a> 27-May-2011 08:34 -
+<a href="spdy/">spdy/</a> 09-Mar-2012 16:05 -
+<a href="test-continuation/">test-continuation/</a> 01-Apr-2010 13:30 -
+<a href="test-continuation-jetty6/">test-continuation-jetty6/</a> 01-Apr-2010 13:30 -
+<a href="test-jetty-nested/">test-jetty-nested/</a> 09-Mar-2012 16:06 -
+<a href="test-jetty-servlet/">test-jetty-servlet/</a> 09-Mar-2012 16:06 -
+<a href="test-jetty-webapp/">test-jetty-webapp/</a> 09-Mar-2012 16:06 -
+<a href="tests/">tests/</a> 30-Nov-2011 02:16 -
+<a href="toolchain/">toolchain/</a> 06-Dec-2011 23:32 -
+</pre><hr></body>
+</html> \ No newline at end of file
diff --git a/jetty-plugins/src/test/resources/mavenRepoJettyJMXDirectoryListing.html b/jetty-plugins/src/test/resources/mavenRepoJettyJMXDirectoryListing.html
new file mode 100644
index 0000000..ac33b1a
--- /dev/null
+++ b/jetty-plugins/src/test/resources/mavenRepoJettyJMXDirectoryListing.html
@@ -0,0 +1,36 @@
+<html>
+<head><title>Index of /maven2/org/eclipse/jetty/jetty-jmx/7.6.0.v20120127/</title></head>
+<body bgcolor="white">
+<h1>Index of /maven2/org/eclipse/jetty/jetty-jmx/7.6.0.v20120127/</h1><hr><pre><a href="../">../</a>
+<a href="jetty-jmx-7.6.0.v20120127-plugin.jar">jetty-jmx-7.6.0.v20120127-plugin.jar</a> 27-Jan-2012 14:24 1873
+<a href="jetty-jmx-7.6.0.v20120127-plugin.jar.asc">jetty-jmx-7.6.0.v20120127-plugin.jar.asc</a> 27-Jan-2012 14:24 198
+<a href="jetty-jmx-7.6.0.v20120127-plugin.jar.asc.md5">jetty-jmx-7.6.0.v20120127-plugin.jar.asc.md5</a> 27-Jan-2012 14:24 32
+<a href="jetty-jmx-7.6.0.v20120127-plugin.jar.asc.sha1">jetty-jmx-7.6.0.v20120127-plugin.jar.asc.sha1</a> 27-Jan-2012 14:24 40
+<a href="jetty-jmx-7.6.0.v20120127-plugin.jar.md5">jetty-jmx-7.6.0.v20120127-plugin.jar.md5</a> 27-Jan-2012 14:24 32
+<a href="jetty-jmx-7.6.0.v20120127-plugin.jar.sha1">jetty-jmx-7.6.0.v20120127-plugin.jar.sha1</a> 27-Jan-2012 14:24 40
+<a href="jetty-jmx-7.6.0.v20120127-javadoc.jar">jetty-jmx-7.6.0.v20120127-javadoc.jar</a> 27-Jan-2012 14:24 52590
+<a href="jetty-jmx-7.6.0.v20120127-javadoc.jar.asc">jetty-jmx-7.6.0.v20120127-javadoc.jar.asc</a> 27-Jan-2012 14:24 198
+<a href="jetty-jmx-7.6.0.v20120127-javadoc.jar.asc.md5">jetty-jmx-7.6.0.v20120127-javadoc.jar.asc.md5</a> 27-Jan-2012 14:24 32
+<a href="jetty-jmx-7.6.0.v20120127-javadoc.jar.asc.sha1">jetty-jmx-7.6.0.v20120127-javadoc.jar.asc.sha1</a> 27-Jan-2012 14:24 40
+<a href="jetty-jmx-7.6.0.v20120127-javadoc.jar.md5">jetty-jmx-7.6.0.v20120127-javadoc.jar.md5</a> 27-Jan-2012 14:24 32
+<a href="jetty-jmx-7.6.0.v20120127-javadoc.jar.sha1">jetty-jmx-7.6.0.v20120127-javadoc.jar.sha1</a> 27-Jan-2012 14:24 40
+<a href="jetty-jmx-7.6.0.v20120127-sources.jar">jetty-jmx-7.6.0.v20120127-sources.jar</a> 27-Jan-2012 14:24 16675
+<a href="jetty-jmx-7.6.0.v20120127-sources.jar.asc">jetty-jmx-7.6.0.v20120127-sources.jar.asc</a> 27-Jan-2012 14:24 198
+<a href="jetty-jmx-7.6.0.v20120127-sources.jar.asc.md5">jetty-jmx-7.6.0.v20120127-sources.jar.asc.md5</a> 27-Jan-2012 14:24 32
+<a href="jetty-jmx-7.6.0.v20120127-sources.jar.asc.sha1">jetty-jmx-7.6.0.v20120127-sources.jar.asc.sha1</a> 27-Jan-2012 14:24 40
+<a href="jetty-jmx-7.6.0.v20120127-sources.jar.md5">jetty-jmx-7.6.0.v20120127-sources.jar.md5</a> 27-Jan-2012 14:24 32
+<a href="jetty-jmx-7.6.0.v20120127-sources.jar.sha1">jetty-jmx-7.6.0.v20120127-sources.jar.sha1</a> 27-Jan-2012 14:24 40
+<a href="jetty-jmx-7.6.0.v20120127.jar">jetty-jmx-7.6.0.v20120127.jar</a> 27-Jan-2012 14:24 23187
+<a href="jetty-jmx-7.6.0.v20120127.jar.asc">jetty-jmx-7.6.0.v20120127.jar.asc</a> 27-Jan-2012 14:24 198
+<a href="jetty-jmx-7.6.0.v20120127.jar.asc.md5">jetty-jmx-7.6.0.v20120127.jar.asc.md5</a> 27-Jan-2012 14:24 32
+<a href="jetty-jmx-7.6.0.v20120127.jar.asc.sha1">jetty-jmx-7.6.0.v20120127.jar.asc.sha1</a> 27-Jan-2012 14:24 40
+<a href="jetty-jmx-7.6.0.v20120127.jar.md5">jetty-jmx-7.6.0.v20120127.jar.md5</a> 27-Jan-2012 14:24 32
+<a href="jetty-jmx-7.6.0.v20120127.jar.sha1">jetty-jmx-7.6.0.v20120127.jar.sha1</a> 27-Jan-2012 14:24 40
+<a href="jetty-jmx-7.6.0.v20120127.pom">jetty-jmx-7.6.0.v20120127.pom</a> 27-Jan-2012 14:24 2655
+<a href="jetty-jmx-7.6.0.v20120127.pom.asc">jetty-jmx-7.6.0.v20120127.pom.asc</a> 27-Jan-2012 14:24 198
+<a href="jetty-jmx-7.6.0.v20120127.pom.asc.md5">jetty-jmx-7.6.0.v20120127.pom.asc.md5</a> 27-Jan-2012 14:24 32
+<a href="jetty-jmx-7.6.0.v20120127.pom.asc.sha1">jetty-jmx-7.6.0.v20120127.pom.asc.sha1</a> 27-Jan-2012 14:24 40
+<a href="jetty-jmx-7.6.0.v20120127.pom.md5">jetty-jmx-7.6.0.v20120127.pom.md5</a> 27-Jan-2012 14:24 32
+<a href="jetty-jmx-7.6.0.v20120127.pom.sha1">jetty-jmx-7.6.0.v20120127.pom.sha1</a> 27-Jan-2012 14:24 40
+</pre><hr></body>
+</html> \ No newline at end of file
diff --git a/jetty-plugins/src/test/resources/mavenRepoJettyJNDIDirectoryListing.html b/jetty-plugins/src/test/resources/mavenRepoJettyJNDIDirectoryListing.html
new file mode 100644
index 0000000..e1e6bf8
--- /dev/null
+++ b/jetty-plugins/src/test/resources/mavenRepoJettyJNDIDirectoryListing.html
@@ -0,0 +1,30 @@
+<html>
+<head><title>Index of /maven2/org/eclipse/jetty/jetty-jndi/7.6.0.v20120127/</title></head>
+<body bgcolor="white">
+<h1>Index of /maven2/org/eclipse/jetty/jetty-jndi/7.6.0.v20120127/</h1><hr><pre><a href="../">../</a>
+<a href="jetty-jndi-7.6.0.v20120127-javadoc.jar">jetty-jndi-7.6.0.v20120127-javadoc.jar</a> 27-Jan-2012 14:37 127695
+<a href="jetty-jndi-7.6.0.v20120127-javadoc.jar.asc">jetty-jndi-7.6.0.v20120127-javadoc.jar.asc</a> 27-Jan-2012 14:37 198
+<a href="jetty-jndi-7.6.0.v20120127-javadoc.jar.asc.md5">jetty-jndi-7.6.0.v20120127-javadoc.jar.asc.md5</a> 27-Jan-2012 14:37 32
+<a href="jetty-jndi-7.6.0.v20120127-javadoc.jar.asc.sha1">jetty-jndi-7.6.0.v20120127-javadoc.jar.asc.sha1</a> 27-Jan-2012 14:37 40
+<a href="jetty-jndi-7.6.0.v20120127-javadoc.jar.md5">jetty-jndi-7.6.0.v20120127-javadoc.jar.md5</a> 27-Jan-2012 14:37 32
+<a href="jetty-jndi-7.6.0.v20120127-javadoc.jar.sha1">jetty-jndi-7.6.0.v20120127-javadoc.jar.sha1</a> 27-Jan-2012 14:37 40
+<a href="jetty-jndi-7.6.0.v20120127-sources.jar">jetty-jndi-7.6.0.v20120127-sources.jar</a> 27-Jan-2012 14:37 26645
+<a href="jetty-jndi-7.6.0.v20120127-sources.jar.asc">jetty-jndi-7.6.0.v20120127-sources.jar.asc</a> 27-Jan-2012 14:37 198
+<a href="jetty-jndi-7.6.0.v20120127-sources.jar.asc.md5">jetty-jndi-7.6.0.v20120127-sources.jar.asc.md5</a> 27-Jan-2012 14:37 32
+<a href="jetty-jndi-7.6.0.v20120127-sources.jar.asc.sha1">jetty-jndi-7.6.0.v20120127-sources.jar.asc.sha1</a> 27-Jan-2012 14:37 40
+<a href="jetty-jndi-7.6.0.v20120127-sources.jar.md5">jetty-jndi-7.6.0.v20120127-sources.jar.md5</a> 27-Jan-2012 14:37 32
+<a href="jetty-jndi-7.6.0.v20120127-sources.jar.sha1">jetty-jndi-7.6.0.v20120127-sources.jar.sha1</a> 27-Jan-2012 14:37 40
+<a href="jetty-jndi-7.6.0.v20120127.jar">jetty-jndi-7.6.0.v20120127.jar</a> 27-Jan-2012 14:36 38073
+<a href="jetty-jndi-7.6.0.v20120127.jar.asc">jetty-jndi-7.6.0.v20120127.jar.asc</a> 27-Jan-2012 14:37 198
+<a href="jetty-jndi-7.6.0.v20120127.jar.asc.md5">jetty-jndi-7.6.0.v20120127.jar.asc.md5</a> 27-Jan-2012 14:37 32
+<a href="jetty-jndi-7.6.0.v20120127.jar.asc.sha1">jetty-jndi-7.6.0.v20120127.jar.asc.sha1</a> 27-Jan-2012 14:37 40
+<a href="jetty-jndi-7.6.0.v20120127.jar.md5">jetty-jndi-7.6.0.v20120127.jar.md5</a> 27-Jan-2012 14:36 32
+<a href="jetty-jndi-7.6.0.v20120127.jar.sha1">jetty-jndi-7.6.0.v20120127.jar.sha1</a> 27-Jan-2012 14:36 40
+<a href="jetty-jndi-7.6.0.v20120127.pom">jetty-jndi-7.6.0.v20120127.pom</a> 27-Jan-2012 14:36 2810
+<a href="jetty-jndi-7.6.0.v20120127.pom.asc">jetty-jndi-7.6.0.v20120127.pom.asc</a> 27-Jan-2012 14:37 198
+<a href="jetty-jndi-7.6.0.v20120127.pom.asc.md5">jetty-jndi-7.6.0.v20120127.pom.asc.md5</a> 27-Jan-2012 14:37 32
+<a href="jetty-jndi-7.6.0.v20120127.pom.asc.sha1">jetty-jndi-7.6.0.v20120127.pom.asc.sha1</a> 27-Jan-2012 14:37 40
+<a href="jetty-jndi-7.6.0.v20120127.pom.md5">jetty-jndi-7.6.0.v20120127.pom.md5</a> 27-Jan-2012 14:37 32
+<a href="jetty-jndi-7.6.0.v20120127.pom.sha1">jetty-jndi-7.6.0.v20120127.pom.sha1</a> 27-Jan-2012 14:37 40
+</pre><hr></body>
+</html> \ No newline at end of file
diff --git a/pom.xml b/pom.xml
index f087c77..6d83261 100644
--- a/pom.xml
+++ b/pom.xml
@@ -377,7 +377,7 @@
<!--<module>jetty-proxy</module>-->
<module>jetty-deploy</module>
<module>jetty-start</module>
-
+ <module>jetty-plugins</module>
<!--
<module>jetty-jaspi</module>
<module>jetty-ajp</module>