diff --git a/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java b/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java index 5e0fa5c87..9c7fd88c5 100644 --- a/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java +++ b/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java @@ -1734,8 +1734,17 @@ public RealJenkinsRule done() { } void writeTo(File jpi, String defaultJenkinsVersion) throws IOException, URISyntaxException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (ZipOutputStream zos = new ZipOutputStream(baos)) { + var mani = new Manifest(); + var attr = mani.getMainAttributes(); + attr.put(Attributes.Name.MANIFEST_VERSION, "1.0"); + attr.putValue("Short-Name", shortName); + attr.putValue("Plugin-Version", version); + attr.putValue("Jenkins-Version", defaultJenkinsVersion); + for (var entry : headers.entrySet()) { + attr.putValue(entry.getKey(), entry.getValue()); + } + var jar = new ByteArrayOutputStream(); + try (var jos = new JarOutputStream(jar, mani)) { String pkgSlash = pkg.replace('.', '/'); URL mainU = RealJenkinsRule.class.getClassLoader().getResource(pkgSlash); if (mainU == null) { @@ -1747,22 +1756,13 @@ void writeTo(File jpi, String defaultJenkinsVersion) throws IOException, URISynt } Path metaInf = Path.of(URI.create(mainU.toString().replaceFirst("\\Q" + pkgSlash + "\\E/?$", "META-INF"))); if (Files.isDirectory(metaInf)) { - zip(zos, metaInf, "META-INF/", pkg); + zip(jos, metaInf, "META-INF/", pkg); } - zip(zos, main, pkgSlash + "/", null); - } - Manifest mani = new Manifest(); - Attributes attr = mani.getMainAttributes(); - attr.put(Attributes.Name.MANIFEST_VERSION, "1.0"); - attr.putValue("Short-Name", shortName); - attr.putValue("Plugin-Version", version); - attr.putValue("Jenkins-Version", defaultJenkinsVersion); - for (Map.Entry entry : headers.entrySet()) { - attr.putValue(entry.getKey(), entry.getValue()); + zip(jos, main, pkgSlash + "/", null); } - try (OutputStream os = new FileOutputStream(jpi); JarOutputStream jos = new JarOutputStream(os, mani)) { + try (var os = new FileOutputStream(jpi); var jos = new JarOutputStream(os, mani)) { jos.putNextEntry(new JarEntry("WEB-INF/lib/" + shortName + ".jar")); - jos.write(baos.toByteArray()); + jos.write(jar.toByteArray()); } LOGGER.info(() -> "Generated " + jpi); } diff --git a/src/test/java/org/jvnet/hudson/test/RealJenkinsRuleSyntheticPluginTest.java b/src/test/java/org/jvnet/hudson/test/RealJenkinsRuleSyntheticPluginTest.java index cf5582af6..dc4a2b203 100644 --- a/src/test/java/org/jvnet/hudson/test/RealJenkinsRuleSyntheticPluginTest.java +++ b/src/test/java/org/jvnet/hudson/test/RealJenkinsRuleSyntheticPluginTest.java @@ -24,11 +24,15 @@ package org.jvnet.hudson.test; +import java.util.logging.Level; import jenkins.model.Jenkins; +import jenkins.security.ClassFilterImpl; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; import org.junit.Rule; import org.junit.Test; +import org.jvnet.hudson.test.sample.plugin.CustomJobProperty; import org.jvnet.hudson.test.sample.plugin.Stuff; public final class RealJenkinsRuleSyntheticPluginTest { @@ -45,4 +49,13 @@ private static void _smokes(JenkinsRule r) throws Throwable { is(Jenkins.get().getLegacyInstanceId())); } + @Test public void classFilter() throws Throwable { + rr.addSyntheticPlugin(CustomJobProperty.class.getPackage()).done().withLogger(ClassFilterImpl.class, Level.FINE); + rr.then(r -> { + var p = r.createFreeStyleProject(); + p.addProperty(new CustomJobProperty("expected in XML")); + assertThat(p.getConfigFile().asString(), containsString("expected in XML")); + }); + } + } diff --git a/src/test/java/org/jvnet/hudson/test/sample/plugin/CustomJobProperty.java b/src/test/java/org/jvnet/hudson/test/sample/plugin/CustomJobProperty.java new file mode 100644 index 000000000..d5ca47f14 --- /dev/null +++ b/src/test/java/org/jvnet/hudson/test/sample/plugin/CustomJobProperty.java @@ -0,0 +1,42 @@ +/* + * The MIT License + * + * Copyright 2025 CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.jvnet.hudson.test.sample.plugin; + +import hudson.model.Job; +import hudson.model.JobProperty; + +/** + * Sample describable. + * @see RealJenkinsRuleSyntheticPluginTest + */ +public final class CustomJobProperty extends JobProperty> { + + private final String value; + + public CustomJobProperty(String value) { + this.value = value; + } + +}