From 386618dca4198e215e1c7d5994fcb7da2356d6cd Mon Sep 17 00:00:00 2001 From: imod Date: Sun, 18 Dec 2011 17:31:00 +0100 Subject: [PATCH] support new JenkinsPlugin type (jpi) --- .../java/hudson/ClassicPluginStrategy.java | 2 +- .../main/java/hudson/LocalPluginManager.java | 6 +- core/src/main/java/hudson/Plugin.java | 2 +- core/src/main/java/hudson/PluginManager.java | 23 ++++--- core/src/main/java/hudson/PluginStrategy.java | 2 +- core/src/main/java/hudson/PluginWrapper.java | 6 +- .../java/hudson/cli/InstallPluginCommand.java | 2 +- .../main/java/hudson/init/InitStrategy.java | 27 ++++---- .../main/java/hudson/model/UpdateCenter.java | 35 ++++++++++- core/src/main/java/jenkins/model/Jenkins.java | 2 +- .../org/jvnet/hudson/test/HudsonTestCase.java | 56 +++++++++++------ .../org/jvnet/hudson/test/JenkinsRule.java | 58 ++++++++++++------ .../jvnet/hudson/test/TestPluginManager.java | 21 +++++-- .../{htmlpublisher.hpi => htmlpublisher.jpi} | Bin test/src/main/resources/plugins/legacy.hpi | Bin 0 -> 8727 bytes .../plugins/{tasks.hpi => tasks.jpi} | Bin .../test/java/hudson/PluginManagerTest.java | 44 ++++++++++--- .../hudson/util/FormFieldValidatorTest.java | 2 +- 18 files changed, 200 insertions(+), 88 deletions(-) rename test/src/main/resources/plugins/{htmlpublisher.hpi => htmlpublisher.jpi} (100%) create mode 100644 test/src/main/resources/plugins/legacy.hpi rename test/src/main/resources/plugins/{tasks.hpi => tasks.jpi} (100%) diff --git a/core/src/main/java/hudson/ClassicPluginStrategy.java b/core/src/main/java/hudson/ClassicPluginStrategy.java index 2d7e9f95a6..d55182a8f0 100644 --- a/core/src/main/java/hudson/ClassicPluginStrategy.java +++ b/core/src/main/java/hudson/ClassicPluginStrategy.java @@ -86,7 +86,7 @@ public class ClassicPluginStrategy implements PluginStrategy { File expandDir = null; // if .hpi, this is the directory where war is expanded - boolean isLinked = archive.getName().endsWith(".hpl"); + boolean isLinked = archive.getName().endsWith(".hpl") || archive.getName().endsWith(".jpl"); if (isLinked) { // resolve the .hpl file to the location of the manifest file final String firstLine = IOUtils.readFirstLine(new FileInputStream(archive), "UTF-8"); diff --git a/core/src/main/java/hudson/LocalPluginManager.java b/core/src/main/java/hudson/LocalPluginManager.java index 184ce191c5..4cfbf6ad93 100644 --- a/core/src/main/java/hudson/LocalPluginManager.java +++ b/core/src/main/java/hudson/LocalPluginManager.java @@ -52,14 +52,14 @@ public class LocalPluginManager extends PluginManager { } /** - * If the war file has any "/WEB-INF/plugins/*.hpi", extract them into the plugin directory. + * If the war file has any "/WEB-INF/plugins/*.jpi", extract them into the plugin directory. * * @return - * File names of the bundled plugins. Like {"ssh-slaves.hpi","subvesrion.hpi"} + * File names of the bundled plugins. Like {"ssh-slaves.jpi","subvesrion.jpi"} */ @Override protected Collection loadBundledPlugins() { - // this is used in tests, when we want to override the default bundled plugins with .hpl versions + // this is used in tests, when we want to override the default bundled plugins with .jpl (or .hpl) versions if (System.getProperty("hudson.bundled.plugins") != null) { return Collections.emptySet(); } diff --git a/core/src/main/java/hudson/Plugin.java b/core/src/main/java/hudson/Plugin.java index bd3223fbbf..bf5f4a6821 100644 --- a/core/src/main/java/hudson/Plugin.java +++ b/core/src/main/java/hudson/Plugin.java @@ -54,7 +54,7 @@ import com.thoughtworks.xstream.XStream; * *

* A plugin is bound to URL space of Hudson as ${rootURL}/plugin/foo/, - * where "foo" is taken from your plugin name "foo.hpi". All your web resources + * where "foo" is taken from your plugin name "foo.jpi". All your web resources * in src/main/webapp are visible from this URL, and you can also define Jelly * views against your Plugin class, and those are visible in this URL, too. * diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java index 80d1a0927f..900c4f3fc8 100644 --- a/core/src/main/java/hudson/PluginManager.java +++ b/core/src/main/java/hudson/PluginManager.java @@ -206,7 +206,7 @@ public abstract class PluginManager extends AbstractModelObject { /** * Inspects duplication. this happens when you run hpi:run on a bundled plugin, - * as well as putting numbered hpi files, like "cobertura-1.0.hpi" and "cobertura-1.1.hpi" + * as well as putting numbered jpi files, like "cobertura-1.0.jpi" and "cobertura-1.1.jpi" */ private boolean isDuplicate(PluginWrapper p) { String shortName = p.getShortName(); @@ -382,17 +382,17 @@ public abstract class PluginManager extends AbstractModelObject { } /** - * If the war file has any "/WEB-INF/plugins/*.hpi", extract them into the plugin directory. + * If the war file has any "/WEB-INF/plugins/[*.jpi | *.hpi]", extract them into the plugin directory. * * @return - * File names of the bundled plugins. Like {"ssh-slaves.hpi","subvesrion.hpi"} + * File names of the bundled plugins. Like {"ssh-slaves.hpi","subvesrion.jpi"} * @throws Exception * Any exception will be reported and halt the startup. */ protected abstract Collection loadBundledPlugins() throws Exception; /** - * Copies the bundled plugin from the given URL to the destination of the given file name (like 'abc.hpi'), + * Copies the bundled plugin from the given URL to the destination of the given file name (like 'abc.jpi'), * with a reasonable up-to-date check. A convenience method to be used by the {@link #loadBundledPlugins()}. */ protected void copyBundledPlugin(URL src, String fileName) throws IOException { @@ -639,16 +639,21 @@ public abstract class PluginManager extends AbstractModelObject { // Parse the request FileItem fileItem = (FileItem) upload.parseRequest(req).get(0); String fileName = Util.getFileName(fileItem.getName()); - if("".equals(fileName)) + if("".equals(fileName)){ return new HttpRedirect("advanced"); - if(!fileName.endsWith(".hpi")) + } + // we allow the upload of the new jpi's and the legacy hpi's + if(!fileName.endsWith(".jpi") && !fileName.endsWith(".hpi")){ throw new Failure(hudson.model.Messages.Hudson_NotAPlugin(fileName)); - fileItem.write(new File(rootDir, fileName)); + } + final String baseName = FilenameUtils.getBaseName(fileName); + fileItem.write(new File(rootDir, baseName + ".jpi")); // rename all new plugins to *.jpi fileItem.delete(); - PluginWrapper existing = getPlugin(FilenameUtils.getBaseName(fileName)); - if (existing!=null && existing.isBundled) + PluginWrapper existing = getPlugin(baseName); + if (existing!=null && existing.isBundled){ existing.doPin(); + } pluginUploaded = true; diff --git a/core/src/main/java/hudson/PluginStrategy.java b/core/src/main/java/hudson/PluginStrategy.java index d1a06d53c2..6024c3571f 100644 --- a/core/src/main/java/hudson/PluginStrategy.java +++ b/core/src/main/java/hudson/PluginStrategy.java @@ -45,7 +45,7 @@ public interface PluginStrategy extends ExtensionPoint { /** * Creates a plugin wrapper, which provides a management interface for the plugin * @param archive - * Either a directory that points to a pre-exploded plugin, or an hpi file, or an hpl file. + * Either a directory that points to a pre-exploded plugin, or an jpi file, or an jpl file. */ PluginWrapper createPluginWrapper(File archive) throws IOException; diff --git a/core/src/main/java/hudson/PluginWrapper.java b/core/src/main/java/hudson/PluginWrapper.java index 16f158bc89..aa51b0a2b8 100644 --- a/core/src/main/java/hudson/PluginWrapper.java +++ b/core/src/main/java/hudson/PluginWrapper.java @@ -55,7 +55,7 @@ import java.util.jar.JarFile; * for Jenkins to control {@link Plugin}. * *

- * A plug-in is packaged into a jar file whose extension is ".hpi", + * A plug-in is packaged into a jar file whose extension is ".jpi" (or ".hpi" for backward compatability), * A plugin needs to have a special manifest entry to identify what it is. * *

@@ -115,7 +115,7 @@ public class PluginWrapper implements Comparable { /** * Short name of the plugin. The artifact Id of the plugin. * This is also used in the URL within Jenkins, so it needs - * to remain stable even when the *.hpi file name is changed + * to remain stable even when the *.jpi file name is changed * (like Maven does.) */ private final String shortName; @@ -165,7 +165,7 @@ public class PluginWrapper implements Comparable { /** * @param archive - * A .hpi archive file jar file, or a .hpl linked plugin. + * A .jpi archive file jar file, or a .jpl linked plugin. * @param manifest * The manifest for the plugin * @param baseResourceURL diff --git a/core/src/main/java/hudson/cli/InstallPluginCommand.java b/core/src/main/java/hudson/cli/InstallPluginCommand.java index 1ee9282538..a7736609fd 100644 --- a/core/src/main/java/hudson/cli/InstallPluginCommand.java +++ b/core/src/main/java/hudson/cli/InstallPluginCommand.java @@ -150,6 +150,6 @@ public class InstallPluginCommand extends CLICommand { } private File getTargetFile() { - return new File(Jenkins.getInstance().getPluginManager().rootDir,name+".hpi"); + return new File(Jenkins.getInstance().getPluginManager().rootDir,name+".jpi"); } } diff --git a/core/src/main/java/hudson/init/InitStrategy.java b/core/src/main/java/hudson/init/InitStrategy.java index 8495173196..9813bea920 100644 --- a/core/src/main/java/hudson/init/InitStrategy.java +++ b/core/src/main/java/hudson/init/InitStrategy.java @@ -15,10 +15,10 @@ import hudson.PluginManager; import hudson.util.Service; /** - * Strategy pattern of the various key decision making during the Hudson initialization. + * Strategy pattern of the various key decision making during the Jenkins initialization. * *

- * Because the act of initializing plugins is a part of the Hudson initialization, + * Because the act of initializing plugins is a part of the Jenkins initialization, * this extension point cannot be implemented in a plugin. You need to place your jar * inside {@code WEB-INF/lib} instead. * @@ -29,27 +29,31 @@ import hudson.util.Service; */ public class InitStrategy { /** - * Returns the list of *.hpi and *.hpl to expand and load. + * Returns the list of *.jpi, *.hpi and *.hpl to expand and load. * *

- * Normally we look at {@code $JENKINS_HOME/plugins/*.hpi} and *.hpl. + * Normally we look at {@code $JENKINS_HOME/plugins/*.jpi} and *.hpi and *.hpl. * * @return * never null but can be empty. The list can contain different versions of the same plugin, - * and when that happens, Hudson will ignore all but the first one in the list. + * and when that happens, Jenkins will ignore all but the first one in the list. */ public List listPluginArchives(PluginManager pm) throws IOException { - File[] hpi = pm.rootDir.listFiles(new FilterByExtension(".hpi")); // plugin jar file - File[] hpl = pm.rootDir.listFiles(new FilterByExtension(".hpl")); // linked plugin. for debugging. + File[] jpi = pm.rootDir.listFiles(new FilterByExtension(".jpi")); // plugin jar file + File[] hpi = pm.rootDir.listFiles(new FilterByExtension(".hpi")); // plugin jar file (for backward compatibility) + File[] jpl = pm.rootDir.listFiles(new FilterByExtension(".jpl")); // linked plugin. for debugging. + File[] hpl = pm.rootDir.listFiles(new FilterByExtension(".hpl")); // linked plugin. for debugging. (for backward compatibility) if (hpi==null || hpl==null) - throw new IOException("Hudson is unable to create " + pm.rootDir + "\nPerhaps its security privilege is insufficient"); + throw new IOException("Jenkins is unable to create " + pm.rootDir + "\nPerhaps its security privilege is insufficient"); List r = new ArrayList(); // the ordering makes sure that during the debugging we get proper precedence among duplicates. - // for example, while doing "mvn hpi:run" on a plugin that's bundled with Hudson, we want to the - // *.hpl file to override the bundled hpi file. + // for example, while doing "mvn jpi:run" or "mvn hpi:run" on a plugin that's bundled with Jenkins, we want to the + // *.jpl file to override the bundled jpi/hpi file. getBundledPluginsFromProperty(r); + r.addAll(Arrays.asList(jpl)); + r.addAll(Arrays.asList(jpi)); r.addAll(Arrays.asList(hpl)); r.addAll(Arrays.asList(hpi)); @@ -109,7 +113,8 @@ public class InitStrategy { public boolean accept(File dir, String name) { return name.endsWith(extension) // plugin jar file - || name.endsWith(".hpl"); // linked plugin. for debugging. + || name.endsWith(".hpl") // linked plugin. for debugging. (for backward compatibility) + || name.endsWith(".jpl"); // linked plugin. for debugging. } } } diff --git a/core/src/main/java/hudson/model/UpdateCenter.java b/core/src/main/java/hudson/model/UpdateCenter.java index 584b95e13b..ac18b2b379 100644 --- a/core/src/main/java/hudson/model/UpdateCenter.java +++ b/core/src/main/java/hudson/model/UpdateCenter.java @@ -36,7 +36,6 @@ import static hudson.init.InitMilestone.PLUGINS_STARTED; import hudson.init.Initializer; import hudson.lifecycle.Lifecycle; import hudson.lifecycle.RestartNotSupportedException; -import hudson.model.UpdateCenter.DownloadJob; import hudson.model.UpdateSite.Data; import hudson.model.UpdateSite.Plugin; import hudson.model.listeners.SaveableListener; @@ -1102,6 +1101,11 @@ public class UpdateCenter extends AbstractModelObject implements Saveable { } protected File getDestination() { + File baseDir = pm.rootDir; + return new File(baseDir, plugin.name + ".jpi"); + } + + private File getLegacyDestination() { File baseDir = pm.rootDir; return new File(baseDir, plugin.name + ".hpi"); } @@ -1145,6 +1149,29 @@ public class UpdateCenter extends AbstractModelObject implements Saveable { public String toString() { return super.toString()+"[plugin="+plugin.title+"]"; } + + /** + * Called when the download is completed to overwrite + * the old file with the new file. + */ + @Override + protected void replace(File dst, File src) throws IOException { + File bak = Util.changeExtension(dst,".bak"); + + bak.delete(); + final File legacy = getLegacyDestination(); + if(legacy.exists()){ + legacy.renameTo(bak); + }else{ + dst.renameTo(bak); + } + legacy.delete(); + dst.delete(); // any failure up to here is no big deal + + if(!src.renameTo(dst)) { + throw new IOException("Failed to rename "+src+" to "+dst); + } + } } /** @@ -1169,7 +1196,11 @@ public class UpdateCenter extends AbstractModelObject implements Saveable { protected File getDestination() { File baseDir = pm.rootDir; - return new File(baseDir, plugin.name + ".hpi"); + final File legacy = new File(baseDir, plugin.name + ".hpi"); + if(legacy.exists()){ + return legacy; + } + return new File(baseDir, plugin.name + ".jpi"); } protected File getBackup() { diff --git a/core/src/main/java/jenkins/model/Jenkins.java b/core/src/main/java/jenkins/model/Jenkins.java index 429c5e6f83..b5611e9a23 100644 --- a/core/src/main/java/jenkins/model/Jenkins.java +++ b/core/src/main/java/jenkins/model/Jenkins.java @@ -1101,7 +1101,7 @@ public class Jenkins extends AbstractCIBase implements ModifiableItemGrouptarget/test-classes/the.hpl + * If this test harness is launched for a Jenkins plugin, locate the target/test-classes/the.jpl * and add a recipe to install that to the new Jenkins. * *

@@ -1379,21 +1381,26 @@ public abstract class HudsonTestCase extends TestCase implements RootAction { * packaging is hpi. */ protected void recipeLoadCurrentPlugin() throws Exception { - final Enumeration e = getClass().getClassLoader().getResources("the.hpl"); - if(!e.hasMoreElements()) return; // nope + final Enumeration jpls = getClass().getClassLoader().getResources("the.jpl"); + final Enumeration hpls = getClass().getClassLoader().getResources("the.hpl"); + + final List all = Collections.list(jpls); + all.addAll(Collections.list(hpls)); + + if(all.isEmpty()) return; // nope recipes.add(new Runner() { @Override public void decorateHome(HudsonTestCase testCase, File home) throws Exception { - while (e.hasMoreElements()) { - final URL hpl = e.nextElement(); - + + for (URL hpl : all) { + // make the plugin itself available Manifest m = new Manifest(hpl.openStream()); String shortName = m.getMainAttributes().getValue("Short-Name"); if(shortName==null) throw new Error(hpl+" doesn't have the Short-Name attribute"); - FileUtils.copyURLToFile(hpl,new File(home,"plugins/"+shortName+".hpl")); + FileUtils.copyURLToFile(hpl,new File(home,"plugins/"+shortName+".jpl")); // make dependency plugins available // TODO: probably better to read POM, but where to read from? @@ -1412,7 +1419,7 @@ public abstract class HudsonTestCase extends TestCase implements RootAction { String version = tokens[1]; File dependencyJar=resolveDependencyJar(embedder,artifactId,version); - File dst = new File(home, "plugins/" + artifactId + ".hpi"); + File dst = new File(home, "plugins/" + artifactId + ".jpi"); if(!dst.exists() || dst.lastModified()!=dependencyJar.lastModified()) { FileUtils.copyFile(dependencyJar, dst); } @@ -1446,20 +1453,33 @@ public abstract class HudsonTestCase extends TestCase implements RootAction { // found it return Which.jarFile(dependencyPomResource); } else { - Artifact a; - a = embedder.createArtifact(groupId, artifactId, version, "compile"/*doesn't matter*/, "hpi"); - try { - embedder.resolve(a, Arrays.asList(embedder.createRepository("http://maven.glassfish.org/content/groups/public/","repo")),embedder.getLocalRepository()); - return a.getFile(); - } catch (AbstractArtifactResolutionException x) { - // could be a wrong groupId - resolutionError = x; - } + + try { + // currently the most of the plugins are still hpi + return resolvePluginFile(embedder, artifactId, version, groupId, "hpi"); + } catch(AbstractArtifactResolutionException x){ + try { + // but also try with the new jpi + return resolvePluginFile(embedder, artifactId, version, groupId, "jpi"); + } catch(AbstractArtifactResolutionException x2){ + // could be a wrong groupId + resolutionError = x; + } + } + } } - throw new Exception("Failed to resolve plugin: "+artifactId+" version "+version,resolutionError); + throw new Exception("Failed to resolve plugin (tryied with types: 'jpi' and 'hpi'): "+artifactId+" version "+version, resolutionError); } + + private File resolvePluginFile(MavenEmbedder embedder, String artifactId, String version, String groupId, String type) + throws MavenEmbedderException, ComponentLookupException, AbstractArtifactResolutionException { + final Artifact jpi = embedder.createArtifact(groupId, artifactId, version, "compile"/*doesn't matter*/, type); + embedder.resolve(jpi, Arrays.asList(embedder.createRepository("http://maven.glassfish.org/content/groups/public/","repo")),embedder.getLocalRepository()); + return jpi.getFile(); + + } }); } diff --git a/test/src/main/java/org/jvnet/hudson/test/JenkinsRule.java b/test/src/main/java/org/jvnet/hudson/test/JenkinsRule.java index b02bad6c23..f348de05ad 100644 --- a/test/src/main/java/org/jvnet/hudson/test/JenkinsRule.java +++ b/test/src/main/java/org/jvnet/hudson/test/JenkinsRule.java @@ -59,6 +59,7 @@ import hudson.matrix.MatrixProject; import hudson.matrix.MatrixRun; import hudson.maven.MavenBuild; import hudson.maven.MavenEmbedder; +import hudson.maven.MavenEmbedderException; import hudson.maven.MavenModule; import hudson.maven.MavenModuleSet; import hudson.maven.MavenModuleSetBuild; @@ -128,6 +129,7 @@ import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.io.FileUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.resolver.AbstractArtifactResolutionException; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.hamcrest.Matchers; import org.junit.rules.TemporaryFolder; import org.junit.rules.TestRule; @@ -1419,31 +1421,34 @@ public class JenkinsRule implements TestRule, RootAction { } /** - * If this test harness is launched for a Jenkins plugin, locate the target/test-classes/the.hpl + * If this test harness is launched for a Jenkins plugin, locate the target/test-classes/the.jpl * and add a recipe to install that to the new Jenkins. * *

* This file is created by maven-hpi-plugin at the testCompile phase when the current - * packaging is hpi. + * packaging is jpi. */ protected void recipeLoadCurrentPlugin() throws Exception { - final Enumeration e = getClass().getClassLoader().getResources("the.hpl"); - if(!e.hasMoreElements()) return; // nope - - final URL hpl = e.nextElement(); - + final Enumeration jpls = getClass().getClassLoader().getResources("the.jpl"); + final Enumeration hpls = getClass().getClassLoader().getResources("the.hpl"); + + final List all = Collections.list(jpls); + all.addAll(Collections.list(hpls)); + + if(all.isEmpty()) return; // nope + recipes.add(new JenkinsRecipe.Runner() { @Override public void decorateHome(JenkinsRule testCase, File home) throws Exception { - while (e.hasMoreElements()) { - final URL hpl = e.nextElement(); + + for (URL hpl : all) { // make the plugin itself available Manifest m = new Manifest(hpl.openStream()); String shortName = m.getMainAttributes().getValue("Short-Name"); if(shortName==null) throw new Error(hpl+" doesn't have the Short-Name attribute"); - FileUtils.copyURLToFile(hpl, new File(home, "plugins/" + shortName + ".hpl")); + FileUtils.copyURLToFile(hpl, new File(home, "plugins/" + shortName + ".jpl")); // make dependency plugins available // TODO: probably better to read POM, but where to read from? @@ -1464,7 +1469,7 @@ public class JenkinsRule implements TestRule, RootAction { String version = tokens[1]; File dependencyJar=resolveDependencyJar(embedder,artifactId,version); - File dst = new File(home, "plugins/" + artifactId + ".hpi"); + File dst = new File(home, "plugins/" + artifactId + ".jpi"); if(!dst.exists() || dst.lastModified()!=dependencyJar.lastModified()) { FileUtils.copyFile(dependencyJar, dst); } @@ -1498,20 +1503,33 @@ public class JenkinsRule implements TestRule, RootAction { // found it return Which.jarFile(dependencyPomResource); } else { - Artifact a; - a = embedder.createArtifact(groupId, artifactId, version, "compile"/*doesn't matter*/, "hpi"); - try { - embedder.resolve(a, Arrays.asList(embedder.createRepository("http://maven.glassfish.org/content/groups/public/","repo")),embedder.getLocalRepository()); - return a.getFile(); - } catch (AbstractArtifactResolutionException x) { - // could be a wrong groupId - resolutionError = x; - } + + try { + // currently the most of the plugins are still hpi + return resolvePluginFile(embedder, artifactId, version, groupId, "hpi"); + } catch(AbstractArtifactResolutionException x){ + try { + // but also try with the new jpi + return resolvePluginFile(embedder, artifactId, version, groupId, "jpi"); + } catch(AbstractArtifactResolutionException x2){ + // could be a wrong groupId + resolutionError = x; + } + } + } } throw new Exception("Failed to resolve plugin: "+artifactId+" version "+version,resolutionError); } + + private File resolvePluginFile(MavenEmbedder embedder, String artifactId, String version, String groupId, String type) + throws MavenEmbedderException, ComponentLookupException, AbstractArtifactResolutionException { + final Artifact jpi = embedder.createArtifact(groupId, artifactId, version, "compile"/*doesn't matter*/, type); + embedder.resolve(jpi, Arrays.asList(embedder.createRepository("http://maven.glassfish.org/content/groups/public/","repo")),embedder.getLocalRepository()); + return jpi.getFile(); + + } }); } diff --git a/test/src/main/java/org/jvnet/hudson/test/TestPluginManager.java b/test/src/main/java/org/jvnet/hudson/test/TestPluginManager.java index 20f925b09c..1978bcec44 100644 --- a/test/src/main/java/org/jvnet/hudson/test/TestPluginManager.java +++ b/test/src/main/java/org/jvnet/hudson/test/TestPluginManager.java @@ -75,15 +75,18 @@ public class TestPluginManager extends PluginManager { } } // If running tests for a plugin, include the plugin being tested - URL u = getClass().getClassLoader().getResource("the.hpl"); + URL u = getClass().getClassLoader().getResource("the.jpl"); + if(u==null){ + u = getClass().getClassLoader().getResource("the.hpl"); // keep backward compatible + } if (u!=null) try { - names.add("the.hpl"); - copyBundledPlugin(u, "the.hpl"); + names.add("the.jpl"); + copyBundledPlugin(u, "the.jpl"); } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Failed to copy the.hpl",e); + LOGGER.log(Level.SEVERE, "Failed to copy the.jpl",e); } - // and pick up test dependency *.hpi that are placed by maven-hpi-plugin TestDependencyMojo. + // and pick up test dependency *.jpi that are placed by maven-hpi-plugin TestDependencyMojo. // and copy them into $JENKINS_HOME/plugins. URL index = getClass().getResource("/test-dependencies/index"); if (index!=null) {// if built with maven-hpi-plugin < 1.52 this file won't exist. @@ -91,7 +94,13 @@ public class TestPluginManager extends PluginManager { try { String line; while ((line=r.readLine())!=null) { - copyBundledPlugin(new URL(index, line + ".hpi"), line + ".hpi"); + final URL url = new URL(index, line + ".jpi"); + File f = new File(url.toURI()); + if(f.exists()){ + copyBundledPlugin(url, line + ".jpi"); + }else{ + copyBundledPlugin(new URL(index, line + ".hpi"), line + ".jpi"); // fallback to hpi + } } } finally { r.close(); diff --git a/test/src/main/resources/plugins/htmlpublisher.hpi b/test/src/main/resources/plugins/htmlpublisher.jpi similarity index 100% rename from test/src/main/resources/plugins/htmlpublisher.hpi rename to test/src/main/resources/plugins/htmlpublisher.jpi diff --git a/test/src/main/resources/plugins/legacy.hpi b/test/src/main/resources/plugins/legacy.hpi new file mode 100644 index 0000000000000000000000000000000000000000..ac8cc6fae6a291bcac758e13fbb01b445b5be345 GIT binary patch literal 8727 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