pax_global_header00006660000000000000000000000064120714227430014514gustar00rootroot0000000000000052 comment=9cb0078d6bd38ffc062a425d3814ece0ad39c819 maven-hpi-plugin-maven-hpi-plugin-1.93/000077500000000000000000000000001207142274300200065ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/.gitignore000066400000000000000000000000671207142274300220010ustar00rootroot00000000000000*.iml *.ipr *.iws target .classpath .settings .project maven-hpi-plugin-maven-hpi-plugin-1.93/README.md000066400000000000000000000004721207142274300212700ustar00rootroot00000000000000Maven plugin to build Jenkins plugins. See the [Extend Jenkins](https://wiki.jenkins-ci.org/display/JENKINS/Extend+Jenkins) wiki page for details. [![Build Status](https://buildhive.cloudbees.com/job/jenkinsci/job/maven-hpi-plugin/badge/icon)](https://buildhive.cloudbees.com/job/jenkinsci/job/maven-hpi-plugin/) maven-hpi-plugin-maven-hpi-plugin-1.93/copyArchetype.xml000066400000000000000000000034531207142274300233540ustar00rootroot00000000000000 maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/000077500000000000000000000000001207142274300225505ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/pom.xml000066400000000000000000000021151207142274300240640ustar00rootroot00000000000000 4.0.0 org.jenkins-ci.plugins plugin 1.466 org.jenkins-ci.tools hpi-archetype 1.0-SNAPSHOT hpi repo.jenkins-ci.org http://repo.jenkins-ci.org/public/ repo.jenkins-ci.org http://repo.jenkins-ci.org/public/ maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/src/000077500000000000000000000000001207142274300233375ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/src/main/000077500000000000000000000000001207142274300242635ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/src/main/java/000077500000000000000000000000001207142274300252045ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/src/main/java/HelloWorldBuilder.java000066400000000000000000000117231207142274300314350ustar00rootroot00000000000000import hudson.Launcher; import hudson.Extension; import hudson.util.FormValidation; import hudson.model.AbstractBuild; import hudson.model.BuildListener; import hudson.model.AbstractProject; import hudson.tasks.Builder; import hudson.tasks.BuildStepDescriptor; import net.sf.json.JSONObject; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.QueryParameter; import javax.servlet.ServletException; import java.io.IOException; /** * Sample {@link Builder}. * *

* When the user configures the project and enables this builder, * {@link DescriptorImpl#newInstance(StaplerRequest)} is invoked * and a new {@link HelloWorldBuilder} is created. The created * instance is persisted to the project configuration XML by using * XStream, so this allows you to use instance fields (like {@link #name}) * to remember the configuration. * *

* When a build is performed, the {@link #perform(AbstractBuild, Launcher, BuildListener)} * method will be invoked. * * @author Kohsuke Kawaguchi */ public class HelloWorldBuilder extends Builder { private final String name; // Fields in config.jelly must match the parameter names in the "DataBoundConstructor" @DataBoundConstructor public HelloWorldBuilder(String name) { this.name = name; } /** * We'll use this from the config.jelly. */ public String getName() { return name; } @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) { // This is where you 'build' the project. // Since this is a dummy, we just say 'hello world' and call that a build. // This also shows how you can consult the global configuration of the builder if (getDescriptor().getUseFrench()) listener.getLogger().println("Bonjour, "+name+"!"); else listener.getLogger().println("Hello, "+name+"!"); return true; } // Overridden for better type safety. // If your plugin doesn't really define any property on Descriptor, // you don't have to do this. @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl)super.getDescriptor(); } /** * Descriptor for {@link HelloWorldBuilder}. Used as a singleton. * The class is marked as public so that it can be accessed from views. * *

* See src/main/resources/hudson/plugins/hello_world/HelloWorldBuilder/*.jelly * for the actual HTML fragment for the configuration screen. */ @Extension // This indicates to Jenkins that this is an implementation of an extension point. public static final class DescriptorImpl extends BuildStepDescriptor { /** * To persist global configuration information, * simply store it in a field and call save(). * *

* If you don't want fields to be persisted, use transient. */ private boolean useFrench; /** * Performs on-the-fly validation of the form field 'name'. * * @param value * This parameter receives the value that the user has typed. * @return * Indicates the outcome of the validation. This is sent to the browser. */ public FormValidation doCheckName(@QueryParameter String value) throws IOException, ServletException { if (value.length() == 0) return FormValidation.error("Please set a name"); if (value.length() < 4) return FormValidation.warning("Isn't the name too short?"); return FormValidation.ok(); } public boolean isApplicable(Class aClass) { // Indicates that this builder can be used with all kinds of project types return true; } /** * This human readable name is used in the configuration screen. */ public String getDisplayName() { return "Say hello world"; } @Override public boolean configure(StaplerRequest req, JSONObject formData) throws FormException { // To persist global configuration information, // set that to properties and call save(). useFrench = formData.getBoolean("useFrench"); // ^Can also use req.bindJSON(this, formData); // (easier when there are many fields; need set* methods for this, like setUseFrench) save(); return super.configure(req,formData); } /** * This method returns true if the global configuration says we should speak French. * * The method name is bit awkward because global.jelly calls this method to determine * the initial state of the checkbox by the naming convention. */ public boolean getUseFrench() { return useFrench; } } } maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/src/main/resources/000077500000000000000000000000001207142274300262755ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/src/main/resources/HelloWorldBuilder/000077500000000000000000000000001207142274300316575ustar00rootroot00000000000000config.jelly000066400000000000000000000010221207142274300341010ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/src/main/resources/HelloWorldBuilder global.jelly000066400000000000000000000016211207142274300341010ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/src/main/resources/HelloWorldBuilder help-name.html000066400000000000000000000004571207142274300343420ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/src/main/resources/HelloWorldBuilder

Help file for fields are discovered through a file name convention. This file is help for the "name" field. You can have arbitrary HTML here. You can write this file as a Jelly script if you need a dynamic content (but if you do so, change the extension to .jelly).
help-useFrench.html000066400000000000000000000003511207142274300353350ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/src/main/resources/HelloWorldBuilder
This HTML fragment will be injected into the configuration screen when the user clicks the 'help' icon. See global.jelly for how the form decides which page to load. You can have any HTML fragment here.
maven-hpi-plugin-maven-hpi-plugin-1.93/hpi-archetype/src/main/resources/index.jelly000066400000000000000000000002241207142274300304430ustar00rootroot00000000000000
This plugin is a sample to explain how to write a Jenkins plugin.
maven-hpi-plugin-maven-hpi-plugin-1.93/pom.xml000066400000000000000000000205271207142274300213310ustar00rootroot00000000000000 4.0.0 org.jenkins-ci jenkins 1.26 org.jenkins-ci.tools maven-hpi-plugin maven-plugin Maven Jenkins Plugin 1.93 Maven2 plugin for developing Jenkins plugins The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt src/main/resources true org.apache.maven.plugins maven-release-plugin 2.3.2 org.apache.maven.plugins maven-plugin-plugin 2.7 hpi maven-antrun-plugin process-resources run ant ant-apache-regexp 1.6.5 runtime jakarta-regexp jakarta-regexp 1.4 org.apache.maven.wagon wagon-ssh 1.0-beta-7 org.eclipse.m2e lifecycle-mapping 1.0.0 org.apache.maven.plugins maven-antrun-plugin [1.3,) run ${${$}}{ $} $ { UTF-8 com.sun.codemodel codemodel 2.1 org.kohsuke.stapler stapler-groovy 1.169 org.apache.maven maven-plugin-api 2.2.0 org.apache.maven maven-project 2.2.0 org.apache.maven maven-archiver 2.0.1 org.codehaus.plexus plexus-utils 1.0.4 org.apache.maven maven-artifact 2.2.0 org.mortbay.jetty maven-jetty-plugin 6.1.1 net.java.sezpoz sezpoz 1.9 org.apache.maven.plugins maven-archetype-plugin 1.0-alpha-4 org.codehaus.plexus plexus-interactivity-api 1.0-alpha-4 org.kohsuke.stapler maven-stapler-plugin 1.16 javax.servlet servlet-api org.apache.maven.plugins maven-plugin-plugin 2.7 scm:git:git://github.com/jenkinsci/maven-hpi-plugin.git scm:git:ssh://git@github.com/jenkinsci/maven-hpi-plugin.git https://github.com/jenkinsci/maven-hpi-plugin maven-hpi-plugin-1.93 jenkins-ci.org:/var/www scp://jenkins-ci.org/var/www/jenkins-ci.org/maven-hpi-plugin/ jenkins https://buildhive.cloudbees.com/job/jenkinsci/job/maven-hpi-plugin/ repo.jenkins-ci.org http://repo.jenkins-ci.org/public/ run-its org.apache.maven.plugins maven-invoker-plugin 1.6 */pom.xml verify ${basedir}/target/local-repo clean site src/it/settings.xml ${project.build.directory}/its integration-test install run repo.jenkins-ci.org http://repo.jenkins-ci.org/public/ maven-hpi-plugin-maven-hpi-plugin-1.93/src/000077500000000000000000000000001207142274300205755ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/000077500000000000000000000000001207142274300212115ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/000077500000000000000000000000001207142274300242125ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/invoker.properties000066400000000000000000000014611207142274300300070ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # invoker.goals=clean compilemaven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/pom.xml000066400000000000000000000026071207142274300255340ustar00rootroot00000000000000 4.0.0 org.jenkins-ci.plugins plugin 1.424 org.jenkins-ci.tools.hpi.its compile-it 1.0-SNAPSHOT hpi MyNewPlugin @pom.version@ org.jenkins-ci.tools maven-hpi-plugin ${hpiPluginVersion} true org.kohsuke access-modifier-checker 1.0 org.jenkins-ci.tools maven-hpi-plugin ${hpiPluginVersion} maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/000077500000000000000000000000001207142274300250015ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/000077500000000000000000000000001207142274300257255ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/java/000077500000000000000000000000001207142274300266465ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/java/org/000077500000000000000000000000001207142274300274355ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/java/org/jenkinsci/000077500000000000000000000000001207142274300314125ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/java/org/jenkinsci/tools/000077500000000000000000000000001207142274300325525ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/java/org/jenkinsci/tools/hpi/000077500000000000000000000000001207142274300333325ustar00rootroot00000000000000000077500000000000000000000000001207142274300340525ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/java/org/jenkinsci/tools/hpi/itsHelloWorldBuilder.java000066400000000000000000000115501207142274300403010ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/java/org/jenkinsci/tools/hpi/itspackage org.jenkinsci.tools.hpi.its; import hudson.Launcher; import hudson.Extension; import hudson.util.FormValidation; import hudson.model.AbstractBuild; import hudson.model.BuildListener; import hudson.model.AbstractProject; import hudson.tasks.Builder; import hudson.tasks.BuildStepDescriptor; import net.sf.json.JSONObject; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.QueryParameter; import javax.servlet.ServletException; import java.io.IOException; /** * Sample {@link Builder}. * *

* When the user configures the project and enables this builder, * {@link org.jenkins.HelloWorldBuilder.DescriptorImpl#newInstance(org.kohsuke.stapler.StaplerRequest)} is invoked * and a new {@link org.jenkins.HelloWorldBuilder} is created. The created * instance is persisted to the project configuration XML by using * XStream, so this allows you to use instance fields (like {@link #name}) * to remember the configuration. * *

* When a build is performed, the {@link #perform(AbstractBuild, Launcher, BuildListener)} method * will be invoked. * * @author Kohsuke Kawaguchi */ public class HelloWorldBuilder extends Builder { private final String name; // Fields in config.jelly must match the parameter names in the "DataBoundConstructor" @DataBoundConstructor public HelloWorldBuilder(String name) { this.name = name; } /** * We'll use this from the config.jelly. */ public String getName() { return name; } @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) { // this is where you 'build' the project // since this is a dummy, we just say 'hello world' and call that a build // this also shows how you can consult the global configuration of the builder if(getDescriptor().useFrench()) listener.getLogger().println("Bonjour, "+name+"!"); else listener.getLogger().println("Hello, "+name+"!"); return true; } // overrided for better type safety. // if your plugin doesn't really define any property on Descriptor, // you don't have to do this. @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl)super.getDescriptor(); } /** * Descriptor for {@link org.jenkins.HelloWorldBuilder}. Used as a singleton. * The class is marked as public so that it can be accessed from views. * *

* See views/hudson/plugins/hello_world/HelloWorldBuilder/*.jelly * for the actual HTML fragment for the configuration screen. */ @Extension // this marker indicates Hudson that this is an implementation of an extension point. public static final class DescriptorImpl extends BuildStepDescriptor { /** * To persist global configuration information, * simply store it in a field and call save(). * *

* If you don't want fields to be persisted, use transient. */ private boolean useFrench; /** * Performs on-the-fly validation of the form field 'name'. * * @param value * This parameter receives the value that the user has typed. * @return * Indicates the outcome of the validation. This is sent to the browser. */ public FormValidation doCheckName(@QueryParameter String value) throws IOException, ServletException { if(value.length()==0) return FormValidation.error("Please set a name"); if(value.length()<4) return FormValidation.warning("Isn't the name too short?"); return FormValidation.ok(); } public boolean isApplicable(Class aClass) { // indicates that this builder can be used with all kinds of project types return true; } /** * This human readable name is used in the configuration screen. */ public String getDisplayName() { return "Say hello world"; } @Override public boolean configure(StaplerRequest req, JSONObject formData) throws FormException { // To persist global configuration information, // set that to properties and call save(). useFrench = formData.getBoolean("useFrench"); // ^Can also use req.bindJSON(this, formData); // (easier when there are many fields; need set* methods for this, like setUseFrench) save(); return super.configure(req,formData); } /** * This method returns true if the global configuration says we should speak French. */ public boolean useFrench() { return useFrench; } } } maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/resources/000077500000000000000000000000001207142274300277375ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/resources/index.jelly000066400000000000000000000003461207142274300321120ustar00rootroot00000000000000

This plugin is a sample plugin to explain how to write a Jenkins plugin.
maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/resources/org/000077500000000000000000000000001207142274300305265ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/resources/org/jenkinsci/000077500000000000000000000000001207142274300325035ustar00rootroot00000000000000000077500000000000000000000000001207142274300335645ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/resources/org/jenkinsci/tools000077500000000000000000000000001207142274300343445ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/resources/org/jenkinsci/tools/hpi000077500000000000000000000000001207142274300351435ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/resources/org/jenkinsci/tools/hpi/its000077500000000000000000000000001207142274300405255ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/resources/org/jenkinsci/tools/hpi/its/HelloWorldBuilderconfig.jelly000066400000000000000000000010221207142274300430260ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/resources/org/jenkinsci/tools/hpi/its/HelloWorldBuilder global.jelly000066400000000000000000000030271207142274300430300ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/resources/org/jenkinsci/tools/hpi/its/HelloWorldBuilder help-name.html000066400000000000000000000004601207142274300432610ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/resources/org/jenkinsci/tools/hpi/its/HelloWorldBuilder
Help file for fields are discovered through a file name convention. This file is an line help for the "name" field. You can have arbitrary HTML here. You can write this file as a Jelly script if you need a dynamic content (but if you do so, change the extension to .jelly)
maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/webapp/000077500000000000000000000000001207142274300272035ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/src/main/webapp/help-globalConfig.html000066400000000000000000000003651207142274300334110ustar00rootroot00000000000000

This HTML fragment will be injected into the configuration screen when the user clicks the 'help' icon. See global.jelly for how the form decides which page to load. You can have any HTML fragment here.

maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/test.properties000066400000000000000000000000341207142274300273040ustar00rootroot00000000000000maven.hpi.compiler.fork=truemaven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-fork-it/verify.groovy000066400000000000000000000024071207142274300267700ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ assert new File(basedir, 'target/classes').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/HelloWorldBuilder.class').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/HelloWorldBuilder$DescriptorImpl.class').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/HelloWorldBuilder.stapler').exists(); return true;maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/000077500000000000000000000000001207142274300232535ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/invoker.properties000066400000000000000000000014611207142274300270500ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # invoker.goals=clean compilemaven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/pom.xml000066400000000000000000000024641207142274300245760ustar00rootroot00000000000000 4.0.0 org.jenkins-ci.plugins plugin 1.424 org.jenkins-ci.tools.hpi.its compile-it 1.0-SNAPSHOT hpi MyNewPlugin @pom.version@ org.jenkins-ci.tools maven-hpi-plugin ${hpiPluginVersion} org.kohsuke access-modifier-checker 1.0 org.jenkins-ci.tools maven-hpi-plugin ${hpiPluginVersion} maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/000077500000000000000000000000001207142274300240425ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/000077500000000000000000000000001207142274300247665ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/java/000077500000000000000000000000001207142274300257075ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/java/org/000077500000000000000000000000001207142274300264765ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/java/org/jenkinsci/000077500000000000000000000000001207142274300304535ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/java/org/jenkinsci/tools/000077500000000000000000000000001207142274300316135ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/java/org/jenkinsci/tools/hpi/000077500000000000000000000000001207142274300323735ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/java/org/jenkinsci/tools/hpi/its/000077500000000000000000000000001207142274300331725ustar00rootroot00000000000000HelloWorldBuilder.java000066400000000000000000000115241207142274300373430ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/java/org/jenkinsci/tools/hpi/itspackage org.jenkinsci.tools.hpi.its; import hudson.Launcher; import hudson.Extension; import hudson.util.FormValidation; import hudson.model.AbstractBuild; import hudson.model.BuildListener; import hudson.model.AbstractProject; import hudson.tasks.Builder; import hudson.tasks.BuildStepDescriptor; import net.sf.json.JSONObject; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.QueryParameter; import javax.servlet.ServletException; import java.io.IOException; /** * Sample {@link Builder}. * *

* When the user configures the project and enables this builder, * {@link org.jenkins.HelloWorldBuilder.DescriptorImpl#newInstance(StaplerRequest)} is invoked * and a new {@link org.jenkins.HelloWorldBuilder} is created. The created * instance is persisted to the project configuration XML by using * XStream, so this allows you to use instance fields (like {@link #name}) * to remember the configuration. * *

* When a build is performed, the {@link #perform(AbstractBuild, Launcher, BuildListener)} method * will be invoked. * * @author Kohsuke Kawaguchi */ public class HelloWorldBuilder extends Builder { private final String name; // Fields in config.jelly must match the parameter names in the "DataBoundConstructor" @DataBoundConstructor public HelloWorldBuilder(String name) { this.name = name; } /** * We'll use this from the config.jelly. */ public String getName() { return name; } @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) { // this is where you 'build' the project // since this is a dummy, we just say 'hello world' and call that a build // this also shows how you can consult the global configuration of the builder if(getDescriptor().useFrench()) listener.getLogger().println("Bonjour, "+name+"!"); else listener.getLogger().println("Hello, "+name+"!"); return true; } // overrided for better type safety. // if your plugin doesn't really define any property on Descriptor, // you don't have to do this. @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl)super.getDescriptor(); } /** * Descriptor for {@link org.jenkins.HelloWorldBuilder}. Used as a singleton. * The class is marked as public so that it can be accessed from views. * *

* See views/hudson/plugins/hello_world/HelloWorldBuilder/*.jelly * for the actual HTML fragment for the configuration screen. */ @Extension // this marker indicates Hudson that this is an implementation of an extension point. public static final class DescriptorImpl extends BuildStepDescriptor { /** * To persist global configuration information, * simply store it in a field and call save(). * *

* If you don't want fields to be persisted, use transient. */ private boolean useFrench; /** * Performs on-the-fly validation of the form field 'name'. * * @param value * This parameter receives the value that the user has typed. * @return * Indicates the outcome of the validation. This is sent to the browser. */ public FormValidation doCheckName(@QueryParameter String value) throws IOException, ServletException { if(value.length()==0) return FormValidation.error("Please set a name"); if(value.length()<4) return FormValidation.warning("Isn't the name too short?"); return FormValidation.ok(); } public boolean isApplicable(Class aClass) { // indicates that this builder can be used with all kinds of project types return true; } /** * This human readable name is used in the configuration screen. */ public String getDisplayName() { return "Say hello world"; } @Override public boolean configure(StaplerRequest req, JSONObject formData) throws FormException { // To persist global configuration information, // set that to properties and call save(). useFrench = formData.getBoolean("useFrench"); // ^Can also use req.bindJSON(this, formData); // (easier when there are many fields; need set* methods for this, like setUseFrench) save(); return super.configure(req,formData); } /** * This method returns true if the global configuration says we should speak French. */ public boolean useFrench() { return useFrench; } } } maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/resources/000077500000000000000000000000001207142274300270005ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/resources/index.jelly000066400000000000000000000003461207142274300311530ustar00rootroot00000000000000

This plugin is a sample plugin to explain how to write a Jenkins plugin.
maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/resources/org/000077500000000000000000000000001207142274300275675ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/resources/org/jenkinsci/000077500000000000000000000000001207142274300315445ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/resources/org/jenkinsci/tools/000077500000000000000000000000001207142274300327045ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/resources/org/jenkinsci/tools/hpi/000077500000000000000000000000001207142274300334645ustar00rootroot00000000000000000077500000000000000000000000001207142274300342045ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/resources/org/jenkinsci/tools/hpi/its000077500000000000000000000000001207142274300375665ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/resources/org/jenkinsci/tools/hpi/its/HelloWorldBuilderconfig.jelly000066400000000000000000000010221207142274300420670ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/resources/org/jenkinsci/tools/hpi/its/HelloWorldBuilder global.jelly000066400000000000000000000030271207142274300420710ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/resources/org/jenkinsci/tools/hpi/its/HelloWorldBuilder help-name.html000066400000000000000000000004601207142274300423220ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/resources/org/jenkinsci/tools/hpi/its/HelloWorldBuilder
Help file for fields are discovered through a file name convention. This file is an line help for the "name" field. You can have arbitrary HTML here. You can write this file as a Jelly script if you need a dynamic content (but if you do so, change the extension to .jelly)
maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/webapp/000077500000000000000000000000001207142274300262445ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/src/main/webapp/help-globalConfig.html000066400000000000000000000003651207142274300324520ustar00rootroot00000000000000

This HTML fragment will be injected into the configuration screen when the user clicks the 'help' icon. See global.jelly for how the form decides which page to load. You can have any HTML fragment here.

maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/compile-it/verify.groovy000066400000000000000000000024071207142274300260310ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ assert new File(basedir, 'target/classes').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/HelloWorldBuilder.class').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/HelloWorldBuilder$DescriptorImpl.class').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/HelloWorldBuilder.stapler').exists(); return true;maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/settings.xml000066400000000000000000000046601207142274300236010ustar00rootroot00000000000000 it-repo true local.central @localRepositoryUrl@ true true repo.jenkins-ci.org http://repo.jenkins-ci.org/public/ true true local.central @localRepositoryUrl@ true true repo.jenkins-ci.org http://repo.jenkins-ci.org/public/ true true maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/000077500000000000000000000000001207142274300231275ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/invoker.properties000066400000000000000000000014601207142274300267230ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # invoker.goals=clean verifymaven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/pom.xml000066400000000000000000000024631207142274300244510ustar00rootroot00000000000000 4.0.0 org.jenkins-ci.plugins plugin 1.424 org.jenkins-ci.tools.hpi.its verify-it 1.0-SNAPSHOT hpi MyNewPlugin @pom.version@ org.jenkins-ci.tools maven-hpi-plugin ${hpiPluginVersion} org.kohsuke access-modifier-checker 1.0 org.jenkins-ci.tools maven-hpi-plugin ${hpiPluginVersion} maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/000077500000000000000000000000001207142274300237165ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/000077500000000000000000000000001207142274300246425ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/java/000077500000000000000000000000001207142274300255635ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/java/org/000077500000000000000000000000001207142274300263525ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/java/org/jenkinsci/000077500000000000000000000000001207142274300303275ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/java/org/jenkinsci/tools/000077500000000000000000000000001207142274300314675ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/java/org/jenkinsci/tools/hpi/000077500000000000000000000000001207142274300322475ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/java/org/jenkinsci/tools/hpi/its/000077500000000000000000000000001207142274300330465ustar00rootroot00000000000000HelloWorldBuilder.java000066400000000000000000000115241207142274300372170ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/java/org/jenkinsci/tools/hpi/itspackage org.jenkinsci.tools.hpi.its; import hudson.Launcher; import hudson.Extension; import hudson.util.FormValidation; import hudson.model.AbstractBuild; import hudson.model.BuildListener; import hudson.model.AbstractProject; import hudson.tasks.Builder; import hudson.tasks.BuildStepDescriptor; import net.sf.json.JSONObject; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.QueryParameter; import javax.servlet.ServletException; import java.io.IOException; /** * Sample {@link Builder}. * *

* When the user configures the project and enables this builder, * {@link org.jenkins.HelloWorldBuilder.DescriptorImpl#newInstance(StaplerRequest)} is invoked * and a new {@link org.jenkins.HelloWorldBuilder} is created. The created * instance is persisted to the project configuration XML by using * XStream, so this allows you to use instance fields (like {@link #name}) * to remember the configuration. * *

* When a build is performed, the {@link #perform(AbstractBuild, Launcher, BuildListener)} method * will be invoked. * * @author Kohsuke Kawaguchi */ public class HelloWorldBuilder extends Builder { private final String name; // Fields in config.jelly must match the parameter names in the "DataBoundConstructor" @DataBoundConstructor public HelloWorldBuilder(String name) { this.name = name; } /** * We'll use this from the config.jelly. */ public String getName() { return name; } @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) { // this is where you 'build' the project // since this is a dummy, we just say 'hello world' and call that a build // this also shows how you can consult the global configuration of the builder if(getDescriptor().useFrench()) listener.getLogger().println("Bonjour, "+name+"!"); else listener.getLogger().println("Hello, "+name+"!"); return true; } // overrided for better type safety. // if your plugin doesn't really define any property on Descriptor, // you don't have to do this. @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl)super.getDescriptor(); } /** * Descriptor for {@link org.jenkins.HelloWorldBuilder}. Used as a singleton. * The class is marked as public so that it can be accessed from views. * *

* See views/hudson/plugins/hello_world/HelloWorldBuilder/*.jelly * for the actual HTML fragment for the configuration screen. */ @Extension // this marker indicates Hudson that this is an implementation of an extension point. public static final class DescriptorImpl extends BuildStepDescriptor { /** * To persist global configuration information, * simply store it in a field and call save(). * *

* If you don't want fields to be persisted, use transient. */ private boolean useFrench; /** * Performs on-the-fly validation of the form field 'name'. * * @param value * This parameter receives the value that the user has typed. * @return * Indicates the outcome of the validation. This is sent to the browser. */ public FormValidation doCheckName(@QueryParameter String value) throws IOException, ServletException { if(value.length()==0) return FormValidation.error("Please set a name"); if(value.length()<4) return FormValidation.warning("Isn't the name too short?"); return FormValidation.ok(); } public boolean isApplicable(Class aClass) { // indicates that this builder can be used with all kinds of project types return true; } /** * This human readable name is used in the configuration screen. */ public String getDisplayName() { return "Say hello world"; } @Override public boolean configure(StaplerRequest req, JSONObject formData) throws FormException { // To persist global configuration information, // set that to properties and call save(). useFrench = formData.getBoolean("useFrench"); // ^Can also use req.bindJSON(this, formData); // (easier when there are many fields; need set* methods for this, like setUseFrench) save(); return super.configure(req,formData); } /** * This method returns true if the global configuration says we should speak French. */ public boolean useFrench() { return useFrench; } } } maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/resources/000077500000000000000000000000001207142274300266545ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/resources/index.jelly000066400000000000000000000003461207142274300310270ustar00rootroot00000000000000

This plugin is a sample plugin to explain how to write a Jenkins plugin.
maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/resources/org/000077500000000000000000000000001207142274300274435ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/resources/org/jenkinsci/000077500000000000000000000000001207142274300314205ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/resources/org/jenkinsci/tools/000077500000000000000000000000001207142274300325605ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/resources/org/jenkinsci/tools/hpi/000077500000000000000000000000001207142274300333405ustar00rootroot00000000000000000077500000000000000000000000001207142274300340605ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/resources/org/jenkinsci/tools/hpi/its000077500000000000000000000000001207142274300374425ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/resources/org/jenkinsci/tools/hpi/its/HelloWorldBuilderconfig.jelly000066400000000000000000000010221207142274300417430ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/resources/org/jenkinsci/tools/hpi/its/HelloWorldBuilder global.jelly000066400000000000000000000030271207142274300417450ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/resources/org/jenkinsci/tools/hpi/its/HelloWorldBuilder help-name.html000066400000000000000000000004601207142274300421760ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/resources/org/jenkinsci/tools/hpi/its/HelloWorldBuilder
Help file for fields are discovered through a file name convention. This file is an line help for the "name" field. You can have arbitrary HTML here. You can write this file as a Jelly script if you need a dynamic content (but if you do so, change the extension to .jelly)
Messages.properties000066400000000000000000000000211207142274300377360ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/resources/org/jenkinsci/tools/hpi/itsit.msg=It rocks maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/webapp/000077500000000000000000000000001207142274300261205ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/src/main/webapp/help-globalConfig.html000066400000000000000000000003651207142274300323260ustar00rootroot00000000000000

This HTML fragment will be injected into the configuration screen when the user clicks the 'help' icon. See global.jelly for how the form decides which page to load. You can have any HTML fragment here.

maven-hpi-plugin-maven-hpi-plugin-1.93/src/it/verify-it/verify.groovy000066400000000000000000000034501207142274300257040ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ assert new File(basedir, 'target/classes').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/HelloWorldBuilder.class').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/HelloWorldBuilder$DescriptorImpl.class').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/HelloWorldBuilder.stapler').exists(); assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/Messages.class').exists(); assert new File(basedir, 'target/verify-it.hpi').exists(); assert new File(basedir, 'target/verify-it.jar').exists(); assert new File(basedir, 'target/generated-sources/localizer/org/jenkinsci/tools/hpi/its/Messages.java').exists(); content = new File(basedir, 'target/generated-sources/localizer/org/jenkinsci/tools/hpi/its/Messages.java').text; assert content.contains(" holder.format(\"it.msg\");"); // TODO add some test on hpi file content return true;maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/000077500000000000000000000000001207142274300215215ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/000077500000000000000000000000001207142274300224425ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/hudson/000077500000000000000000000000001207142274300237425ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/hudson/Extension.java000066400000000000000000000025521207142274300265650ustar00rootroot00000000000000/* * The MIT License * * Copyright (c) 2011, 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 hudson; import jenkins.YesNoMaybe; import static jenkins.YesNoMaybe.MAYBE; /** * Minimal clone to convince Sezpoz. * * @author Kohsuke Kawaguchi */ public @interface Extension { YesNoMaybe dynamicLoadable() default MAYBE; } maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/jenkins/000077500000000000000000000000001207142274300241035ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/jenkins/YesNoMaybe.java000066400000000000000000000023441207142274300267640ustar00rootroot00000000000000/* * The MIT License * * Copyright (c) 2011, 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 jenkins; /** * @author Kohsuke Kawaguchi */ public enum YesNoMaybe { YES, NO, MAYBE } maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/000077500000000000000000000000001207142274300232315ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/000077500000000000000000000000001207142274300252065ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/000077500000000000000000000000001207142274300263145ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/000077500000000000000000000000001207142274300277755ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpi/000077500000000000000000000000001207142274300305555ustar00rootroot00000000000000AbstractHpiMojo.java000066400000000000000000001141211207142274300343720ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; /* * Copyright 2001-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import hudson.Extension; import jenkins.YesNoMaybe; import net.java.sezpoz.Index; import net.java.sezpoz.IndexItem; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; import org.apache.maven.model.Resource; import org.apache.maven.model.Developer; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectBuilder; import org.codehaus.plexus.archiver.ArchiverException; import org.codehaus.plexus.archiver.UnArchiver; import org.codehaus.plexus.archiver.jar.Manifest.Attribute; import org.codehaus.plexus.archiver.jar.Manifest.Section; import org.codehaus.plexus.archiver.jar.ManifestException; import org.codehaus.plexus.archiver.manager.ArchiverManager; import org.codehaus.plexus.archiver.manager.NoSuchArchiverException; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.InterpolationFilterReader; import org.codehaus.plexus.util.StringUtils; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.net.URL; import java.net.URLClassLoader; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.EnumSet; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.Collection; public abstract class AbstractHpiMojo extends AbstractJenkinsMojo { /** * The directory for the generated WAR. * * @parameter expression="${project.build.directory}" * @required */ protected String outputDirectory; /** * The directory containing generated classes. * * @parameter expression="${project.build.outputDirectory}" * @required */ private File classesDirectory; /** * Name of the plugin that Jenkins uses for display purpose. * It should be one line text. * * @parameter expression="${project.name}" * @required * @readonly */ protected String pluginName; /** * The directory where the webapp is built. * * @parameter expression="${project.build.directory}/${project.build.finalName}" * @required */ private File webappDirectory; /** * Optional - the oldest version of this plugin which the current version is * configuration-compatible with. * * @parameter */ private String compatibleSinceVersion; /** * Optional - sandbox status of this plugin. * * @parameter */ private String sandboxStatus; /** * Single directory for extra files to include in the WAR. * * @parameter expression="${basedir}/src/main/webapp" * @required */ protected File warSourceDirectory; /** * The list of webResources we want to transfer. * * @parameter */ private Resource[] webResources; /** * @parameter expression="${project.build.filters}" */ private List filters; /** * The path to the context.xml file to use. * * @parameter expression="${maven.war.containerConfigXML}" */ private File containerConfigXML; /** * Directory to unpack dependent WARs into if needed * * @parameter expression="${project.build.directory}/war/work" * @required */ private File workDirectory; /** * To look up Archiver/UnArchiver implementations * * @component role="org.codehaus.plexus.archiver.manager.ArchiverManager" * @required */ protected ArchiverManager archiverManager; private static final String WEB_INF = "WEB-INF"; private static final String META_INF = "META-INF"; private static final String[] DEFAULT_INCLUDES = {"**/**"}; /** * The comma separated list of tokens to include in the WAR. * Default is '**'. * * @parameter alias="includes" */ private String warSourceIncludes = "**"; /** * The comma separated list of tokens to exclude from the WAR. * * @parameter alias="excludes" */ private String warSourceExcludes; /** * The comma separated list of tokens to include when doing * a war overlay. * Default is '**' * * @parameter */ private String dependentWarIncludes = "**"; /** * The comma separated list of tokens to exclude when doing * a way overlay. * * @parameter */ private String dependentWarExcludes; /** * [ws|tab|CR|LF]+ separated list of package prefixes that your plugin doesn't want to see * from the core. * *

* Tokens in this list is prefix-matched against the fully-qualified class name, so add * "." to the end of each package name, like "com.foo. com.bar." * * @parameter */ protected String maskClasses; /** * Like the maskClasses parameter, but it applies at the boundary between core and * all the plugins. * *

* This mechanism is intended for those plugins that bring JavaEE APIs (such as the database plugin, * which brings in the JPA API.) Other plugins that depend on the database plugin can still see * the JPA API through the container classloader, so to make them all resolve to the JPA API in the * database plugin, the database plugin needs to rely on this mechanism. * * @parameter * @since 1.92 */ protected String globalMaskClasses; /** * @since 1.53 * @parameter */ private boolean pluginFirstClassLoader = false; /** * If true, test scope dependencies count as if they are normal dependencies. * This is only useful during hpi:run, so not exposing it as a configurable parameter. */ boolean includeTestScope; /** * @component */ protected MavenProjectBuilder projectBuilder; /** * @parameter expression="${localRepository}" */ protected ArtifactRepository localRepository; private static final String[] EMPTY_STRING_ARRAY = {}; public File getClassesDirectory() { return classesDirectory; } public void setClassesDirectory(File classesDirectory) { this.classesDirectory = classesDirectory; } public File getWebappDirectory() { return webappDirectory; } public void setWebappDirectory(File webappDirectory) { this.webappDirectory = webappDirectory; } public void setWarSourceDirectory(File warSourceDirectory) { this.warSourceDirectory = warSourceDirectory; } public File getContainerConfigXML() { return containerConfigXML; } public void setContainerConfigXML(File containerConfigXML) { this.containerConfigXML = containerConfigXML; } /** * Returns a string array of the excludes to be used * when assembling/copying the war. * * @return an array of tokens to exclude */ protected String[] getExcludes() { List excludeList = new ArrayList(); if (StringUtils.isNotEmpty(warSourceExcludes)) { excludeList.addAll(Arrays.asList(StringUtils.split(warSourceExcludes, ","))); } // if contextXML is specified, omit the one in the source directory if (containerConfigXML != null && StringUtils.isNotEmpty(containerConfigXML.getName())) { excludeList.add("**/" + META_INF + "/" + containerConfigXML.getName()); } return excludeList.toArray(EMPTY_STRING_ARRAY); } /** * Returns a string array of the includes to be used * when assembling/copying the war. * * @return an array of tokens to include */ protected String[] getIncludes() { return StringUtils.split(StringUtils.defaultString(warSourceIncludes), ","); } /** * Returns a string array of the excludes to be used * when adding dependent wars as an overlay onto this war. * * @return an array of tokens to exclude */ protected String[] getDependentWarExcludes() { String[] excludes; if (StringUtils.isNotEmpty(dependentWarExcludes)) { excludes = StringUtils.split(dependentWarExcludes, ","); } else { excludes = EMPTY_STRING_ARRAY; } return excludes; } /** * Returns a string array of the includes to be used * when adding dependent wars as an overlay onto this war. * * @return an array of tokens to include */ protected String[] getDependentWarIncludes() { return StringUtils.split(StringUtils.defaultString(dependentWarIncludes), ","); } public void buildExplodedWebapp(File webappDirectory) throws MojoExecutionException { getLog().info("Exploding webapp..."); webappDirectory.mkdirs(); File webinfDir = new File(webappDirectory, WEB_INF); webinfDir.mkdirs(); File metainfDir = new File(webappDirectory, META_INF); metainfDir.mkdirs(); try { List webResources = this.webResources != null ? Arrays.asList(this.webResources) : null; if (webResources != null && webResources.size() > 0) { Properties filterProperties = getBuildFilterProperties(); for (Resource resource : webResources) { copyResources(resource, webappDirectory, filterProperties); } } copyResources(warSourceDirectory, webappDirectory); if (containerConfigXML != null && StringUtils.isNotEmpty(containerConfigXML.getName())) { metainfDir = new File(webappDirectory, META_INF); String xmlFileName = containerConfigXML.getName(); copyFileIfModified(containerConfigXML, new File(metainfDir, xmlFileName)); } buildWebapp(project, webappDirectory); } catch (IOException e) { throw new MojoExecutionException("Could not explode webapp...", e); } } private Properties getBuildFilterProperties() throws MojoExecutionException { // System properties Properties filterProperties = new Properties(System.getProperties()); // Project properties filterProperties.putAll(project.getProperties()); for (String filter : filters) { try { Properties properties = PropertyUtils.loadPropertyFile(new File(filter), true, true); filterProperties.putAll(properties); } catch (IOException e) { throw new MojoExecutionException("Error loading property file '" + filter + "'", e); } } return filterProperties; } /** * Copies webapp webResources from the specified directory. *

* Note that the webXml parameter could be null and may * specify a file which is not named web.xml. If the file * exists, it will be copied to the META-INF directory and * renamed accordingly. * * @param resource the resource to copy * @param webappDirectory the target directory * @param filterProperties * @throws java.io.IOException if an error occurred while copying webResources */ public void copyResources(Resource resource, File webappDirectory, Properties filterProperties) throws IOException { if (!resource.getDirectory().equals(webappDirectory.getPath())) { getLog().info("Copy webapp webResources to " + webappDirectory.getAbsolutePath()); if (webappDirectory.exists()) { String[] fileNames = getWarFiles(resource); for (String fileName : fileNames) { if (resource.isFiltering()) { copyFilteredFile(new File(resource.getDirectory(), fileName), new File(webappDirectory, fileName), null, getFilterWrappers(), filterProperties); } else { copyFileIfModified(new File(resource.getDirectory(), fileName), new File(webappDirectory, fileName)); } } } } } /** * Copies webapp webResources from the specified directory. *

* Note that the webXml parameter could be null and may * specify a file which is not named web.xml. If the file * exists, it will be copied to the META-INF directory and * renamed accordingly. * * @param sourceDirectory the source directory * @param webappDirectory the target directory * @throws java.io.IOException if an error occurred while copying webResources */ public void copyResources(File sourceDirectory, File webappDirectory) throws IOException { if (!sourceDirectory.equals(webappDirectory)) { getLog().info("Copy webapp webResources to " + webappDirectory.getAbsolutePath()); if (warSourceDirectory.exists()) { String[] fileNames = getWarFiles(sourceDirectory); for (String fileName : fileNames) { copyFileIfModified(new File(sourceDirectory, fileName), new File(webappDirectory, fileName)); } } } } /** * Returns all the transitive dependencies. */ public Set getProjectArtfacts() { return wrap(Artifacts.of(project)); } /** * Returns all just the direct dependencies. */ public Set getDirectDependencyArtfacts() { return wrap(Artifacts.ofDirectDependencies(project)); } protected Set wrap(Iterable artifacts) { Set r = new HashSet(); for (Artifact a : artifacts) { r.add(wrap(a)); } return r; } protected MavenArtifact wrap(Artifact a) { return new MavenArtifact(a,projectBuilder,project.getRemoteArtifactRepositories(),localRepository); } /** * Builds the webapp for the specified project. *

* Classes, libraries and tld files are copied to * the webappDirectory during this phase. * * @param project the maven project * @param webappDirectory * @throws java.io.IOException if an error occurred while building the webapp */ public void buildWebapp(MavenProject project, File webappDirectory) throws MojoExecutionException, IOException { getLog().info("Assembling webapp " + project.getArtifactId() + " in " + webappDirectory); File libDirectory = new File(webappDirectory, WEB_INF + "/lib"); File tldDirectory = new File(webappDirectory, WEB_INF + "/tld"); File webappClassesDirectory = new File(webappDirectory, WEB_INF + "/classes"); if (classesDirectory.exists() && !classesDirectory.equals(webappClassesDirectory)) { copyDirectoryStructureIfModified(classesDirectory, webappClassesDirectory); } Set artifacts = getProjectArtfacts(); List duplicates = findDuplicates(artifacts); List dependentWarDirectories = new ArrayList(); // List up IDs of Jenkins plugin dependencies Set jenkinsPlugins = new HashSet(); for (MavenArtifact artifact : artifacts) { if(artifact.isPlugin()) jenkinsPlugins.add(artifact.getId()); } OUTER: for (MavenArtifact artifact : artifacts) { if(jenkinsPlugins.contains(artifact.getId())) continue; // plugin dependency need not be WEB-INF/lib if(artifact.getDependencyTrail().size() >= 1 && jenkinsPlugins.contains(artifact.getDependencyTrail().get(1))) continue; // no need to have transitive dependencies through plugins in WEB-INF/lib. // if the dependency goes through jenkins core, we don't need to bundle it in the war // because jenkins-core comes in the scope, I think this is a bug in Maven that it puts such // dependencies into the artifact list. for (String trail : artifact.getDependencyTrail()) { if (trail.contains(":hudson-core:") || trail.contains(":jenkins-core:")) continue OUTER; } String targetFileName = artifact.getDefaultFinalName(); getLog().debug("Processing: " + targetFileName); if (duplicates.contains(targetFileName)) { getLog().debug("Duplicate found: " + targetFileName); targetFileName = artifact.getGroupId() + "-" + targetFileName; getLog().debug("Renamed to: " + targetFileName); } // TODO: utilise appropriate methods from project builder ScopeArtifactFilter filter = new ScopeArtifactFilter(Artifact.SCOPE_RUNTIME); if (!artifact.isOptional() && filter.include(artifact.artifact)) { String type = artifact.getType(); if ("tld".equals(type)) { copyFileIfModified(artifact.getFile(), new File(tldDirectory, targetFileName)); } else { if ("jar".equals(type) || "ejb".equals(type) || "ejb-client".equals(type)) { copyFileIfModified(artifact.getFile(), new File(libDirectory, targetFileName)); } else { if ("par".equals(type)) { targetFileName = targetFileName.substring(0, targetFileName.lastIndexOf('.')) + ".jar"; getLog().debug( "Copying " + artifact.getFile() + " to " + new File(libDirectory, targetFileName)); copyFileIfModified(artifact.getFile(), new File(libDirectory, targetFileName)); } else { if ("war".equals(type)) { dependentWarDirectories.add(unpackWarToTempDirectory(artifact)); } else { getLog().debug("Skipping artifact of type " + type + " for WEB-INF/lib"); } } } } } } if (dependentWarDirectories.size() > 0) { getLog().info("Overlaying " + dependentWarDirectories.size() + " war(s)."); // overlay dependent wars for (Iterator iter = dependentWarDirectories.iterator(); iter.hasNext();) { copyDependentWarContents((File) iter.next(), webappDirectory); } } } /** * Searches a set of artifacts for duplicate filenames and returns a list of duplicates. * * @param artifacts set of artifacts * @return List of duplicated artifacts */ private List findDuplicates(Set artifacts) { List duplicates = new ArrayList(); List identifiers = new ArrayList(); for (MavenArtifact artifact : artifacts) { String candidate = artifact.getDefaultFinalName(); if (identifiers.contains(candidate)) { duplicates.add(candidate); } else { identifiers.add(candidate); } } return duplicates; } /** * Unpacks war artifacts into a temporary directory inside workDirectory * named with the name of the war. * * @param artifact War artifact to unpack. * @return Directory containing the unpacked war. * @throws MojoExecutionException */ private File unpackWarToTempDirectory(MavenArtifact artifact) throws MojoExecutionException { String name = artifact.getFile().getName(); File tempLocation = new File(workDirectory, name.substring(0, name.length() - 4)); boolean process = false; if (!tempLocation.exists()) { tempLocation.mkdirs(); process = true; } else if (artifact.getFile().lastModified() > tempLocation.lastModified()) { process = true; } if (process) { File file = artifact.getFile(); try { unpack(file, tempLocation); } catch (NoSuchArchiverException e) { this.getLog().info("Skip unpacking dependency file with unknown extension: " + file.getPath()); } } return tempLocation; } /** * Unpacks the archive file. * * @param file File to be unpacked. * @param location Location where to put the unpacked files. */ private void unpack(File file, File location) throws MojoExecutionException, NoSuchArchiverException { String archiveExt = FileUtils.getExtension(file.getAbsolutePath()).toLowerCase(); try { UnArchiver unArchiver = archiverManager.getUnArchiver(archiveExt); unArchiver.setSourceFile(file); unArchiver.setDestDirectory(location); unArchiver.extract(); } catch (IOException e) { throw new MojoExecutionException("Error unpacking file: " + file + "to: " + location, e); } catch (ArchiverException e) { throw new MojoExecutionException("Error unpacking file: " + file + "to: " + location, e); } } /** * Recursively copies contents of srcDir into targetDir. * This will not overwrite any existing files. * * @param srcDir Directory containing unpacked dependent war contents * @param targetDir Directory to overlay srcDir into */ private void copyDependentWarContents(File srcDir, File targetDir) throws MojoExecutionException { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(srcDir); scanner.setExcludes(getDependentWarExcludes()); scanner.addDefaultExcludes(); scanner.setIncludes(getDependentWarIncludes()); scanner.scan(); for (String dir : scanner.getIncludedDirectories()) { new File(targetDir, dir).mkdirs(); } for (String file : scanner.getIncludedFiles()) { File targetFile = new File(targetDir, file); // Do not overwrite existing files. if (!targetFile.exists()) { try { targetFile.getParentFile().mkdirs(); copyFileIfModified(new File(srcDir, file), targetFile); } catch (IOException e) { throw new MojoExecutionException("Error copying file '" + file + "' to '" + targetFile + "'", e); } } } } /** * Returns a list of filenames that should be copied * over to the destination directory. * * @param sourceDir the directory to be scanned * @return the array of filenames, relative to the sourceDir */ private String[] getWarFiles(File sourceDir) { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(sourceDir); scanner.setExcludes(getExcludes()); scanner.addDefaultExcludes(); scanner.setIncludes(getIncludes()); scanner.scan(); return scanner.getIncludedFiles(); } /** * Returns a list of filenames that should be copied * over to the destination directory. * * @param resource the resource to be scanned * @return the array of filenames, relative to the sourceDir */ private String[] getWarFiles(Resource resource) { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(resource.getDirectory()); if (resource.getIncludes() != null && !resource.getIncludes().isEmpty()) { scanner.setIncludes((String[]) resource.getIncludes().toArray(EMPTY_STRING_ARRAY)); } else { scanner.setIncludes(DEFAULT_INCLUDES); } if (resource.getExcludes() != null && !resource.getExcludes().isEmpty()) { scanner.setExcludes((String[]) resource.getExcludes().toArray(EMPTY_STRING_ARRAY)); } scanner.addDefaultExcludes(); scanner.scan(); return scanner.getIncludedFiles(); } /** * Copy file from source to destination only if source is newer than the target file. * If destinationDirectory does not exist, it * (and any parent directories) will be created. If a file source in * destinationDirectory exists, it will be overwritten. * * @param source An existing File to copy. * @param destinationDirectory A directory to copy source into. * @throws java.io.FileNotFoundException if source isn't a normal file. * @throws IllegalArgumentException if destinationDirectory isn't a directory. * @throws java.io.IOException if source does not exist, the file in * destinationDirectory cannot be written to, or an IO error occurs during copying. *

* TO DO: Remove this method when Maven moves to plexus-utils version 1.4 */ private static void copyFileToDirectoryIfModified(File source, File destinationDirectory) throws IOException { // TO DO: Remove this method and use the method in WarFileUtils when Maven 2 changes // to plexus-utils 1.2. if (destinationDirectory.exists() && !destinationDirectory.isDirectory()) { throw new IllegalArgumentException("Destination is not a directory"); } copyFileIfModified(source, new File(destinationDirectory, source.getName())); } private FilterWrapper[] getFilterWrappers() { return new FilterWrapper[]{ // support ${token} new FilterWrapper() { public Reader getReader(Reader fileReader, Properties filterProperties) { return new InterpolationFilterReader(fileReader, filterProperties, "${", "}"); } }, // support @token@ new FilterWrapper() { public Reader getReader(Reader fileReader, Properties filterProperties) { return new InterpolationFilterReader(fileReader, filterProperties, "@", "@"); } }}; } /** * @param from * @param to * @param encoding * @param wrappers * @param filterProperties * @throws IOException TO DO: Remove this method when Maven moves to plexus-utils version 1.4 */ private static void copyFilteredFile(File from, File to, String encoding, FilterWrapper[] wrappers, Properties filterProperties) throws IOException { // buffer so it isn't reading a byte at a time! Reader fileReader = null; Writer fileWriter = null; try { // fix for MWAR-36, ensures that the parent dir are created first to.getParentFile().mkdirs(); if (encoding == null || encoding.length() < 1) { fileReader = new BufferedReader(new FileReader(from)); fileWriter = new FileWriter(to); } else { FileInputStream instream = new FileInputStream(from); FileOutputStream outstream = new FileOutputStream(to); fileReader = new BufferedReader(new InputStreamReader(instream, encoding)); fileWriter = new OutputStreamWriter(outstream, encoding); } Reader reader = fileReader; for (FilterWrapper wrapper : wrappers) { reader = wrapper.getReader(reader, filterProperties); } IOUtil.copy(reader, fileWriter); } finally { IOUtil.close(fileReader); IOUtil.close(fileWriter); } } /** * Copy file from source to destination only if source timestamp is later than the destination timestamp. * The directories up to destination will be created if they don't already exist. * destination will be overwritten if it already exists. * * @param source An existing non-directory File to copy bytes from. * @param destination A non-directory File to write bytes to (possibly * overwriting). * @throws IOException if source does not exist, destination cannot be * written to, or an IO error occurs during copying. * @throws java.io.FileNotFoundException if destination is a directory *

* TO DO: Remove this method when Maven moves to plexus-utils version 1.4 */ private static void copyFileIfModified(File source, File destination) throws IOException { // TO DO: Remove this method and use the method in WarFileUtils when Maven 2 changes // to plexus-utils 1.2. if (destination.lastModified() < source.lastModified()) { FileUtils.copyFile(source, destination); } } /** * Copies a entire directory structure but only source files with timestamp later than the destinations'. *

* Note: *

* * @param sourceDirectory * @param destinationDirectory * @throws IOException TO DO: Remove this method when Maven moves to plexus-utils version 1.4 */ private static void copyDirectoryStructureIfModified(File sourceDirectory, File destinationDirectory) throws IOException { if (!sourceDirectory.exists()) { throw new IOException("Source directory doesn't exists (" + sourceDirectory.getAbsolutePath() + ")."); } String sourcePath = sourceDirectory.getAbsolutePath(); for (File file : sourceDirectory.listFiles()) { String dest = file.getAbsolutePath(); dest = dest.substring(sourcePath.length() + 1); File destination = new File(destinationDirectory, dest); if (file.isFile()) { destination = destination.getParentFile(); copyFileToDirectoryIfModified(file, destination); } else if (file.isDirectory()) { if (!destination.exists() && !destination.mkdirs()) { throw new IOException( "Could not create destination directory '" + destination.getAbsolutePath() + "'."); } copyDirectoryStructureIfModified(file, destination); } else { throw new IOException("Unknown file type: " + file.getAbsolutePath()); } } } /** * TO DO: Remove this interface when Maven moves to plexus-utils version 1.4 */ private interface FilterWrapper { Reader getReader(Reader fileReader, Properties filterProperties); } protected void setAttributes(Section mainSection) throws MojoExecutionException, ManifestException, IOException { File pluginImpl = new File(project.getBuild().getOutputDirectory(), "META-INF/services/hudson.Plugin"); if(pluginImpl.exists()) { BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(pluginImpl),"UTF-8")); String pluginClassName = in.readLine(); in.close(); mainSection.addAttributeAndCheck(new Attribute("Plugin-Class",pluginClassName)); } mainSection.addAttributeAndCheck(new Attribute("Group-Id",project.getGroupId())); mainSection.addAttributeAndCheck(new Attribute("Short-Name",project.getArtifactId())); mainSection.addAttributeAndCheck(new Attribute("Long-Name",pluginName)); String url = project.getUrl(); if(url!=null) mainSection.addAttributeAndCheck(new Attribute("Url", url)); if (compatibleSinceVersion!=null) mainSection.addAttributeAndCheck(new Attribute("Compatible-Since-Version", compatibleSinceVersion)); if (sandboxStatus!=null) mainSection.addAttributeAndCheck(new Attribute("Sandbox-Status", sandboxStatus)); String v = project.getVersion(); if(v.endsWith("-SNAPSHOT")) { String dt = new SimpleDateFormat("MM/dd/yyyy HH:mm").format(new Date()); v += " (private-"+dt+"-"+System.getProperty("user.name")+")"; } if (!project.getPackaging().equals("jenkins-module")) { // Earlier maven-hpi-plugin used to look for this attribute to determine if a jar file is a Jenkins plugin. // While that's fixed, people out there might be still using it, so as a precaution when building a module // don't put this information in there. // The "Implementation-Version" baked by Maven should serve the same purpose if someone needs to know the version. mainSection.addAttributeAndCheck(new Attribute("Plugin-Version",v)); } String jv = findJenkinsVersion(); mainSection.addAttributeAndCheck(new Attribute("Hudson-Version",jv)); mainSection.addAttributeAndCheck(new Attribute("Jenkins-Version",jv)); if(maskClasses!=null) mainSection.addAttributeAndCheck(new Attribute("Mask-Classes",maskClasses)); if (globalMaskClasses!=null) mainSection.addAttributeAndCheck(new Attribute("Global-Mask-Classes",globalMaskClasses)); if(pluginFirstClassLoader) mainSection.addAttributeAndCheck( new Attribute( "PluginFirstClassLoader", "true" ) ); String dep = findDependencyPlugins(); if(dep.length()>0) mainSection.addAttributeAndCheck(new Attribute("Plugin-Dependencies",dep)); if (project.getDevelopers() != null) { mainSection.addAttributeAndCheck(new Attribute("Plugin-Developers",getDevelopersForManifest())); } Boolean b = isSupportDynamicLoading(); if (b!=null) mainSection.addAttributeAndCheck(new Attribute("Support-Dynamic-Loading",b.toString())); } /** * Is the dynamic loading supported? * * False, if the answer is known to be "No". Otherwise null, if there are some extensions * we don't know we can dynamic load. Otherwise, if everything is known to be dynamic loadable, return true. */ protected Boolean isSupportDynamicLoading() throws IOException { URLClassLoader cl = new URLClassLoader(new URL[]{ new File(project.getBuild().getOutputDirectory()).toURI().toURL() }, getClass().getClassLoader()); EnumSet e = EnumSet.noneOf(YesNoMaybe.class); for (IndexItem i : Index.load(Extension.class, Object.class, cl)) { e.add(i.annotation().dynamicLoadable()); } if (e.contains(YesNoMaybe.NO)) return false; if (e.contains(YesNoMaybe.MAYBE)) return null; return true; } /** * Finds and lists developers specified in POM. */ private String getDevelopersForManifest() throws IOException { StringBuilder buf = new StringBuilder(); for (Object o : project.getDevelopers()) { Developer d = (Developer) o; if (buf.length() > 0) { buf.append(','); } buf.append(d.getName() != null ? d.getName() : ""); buf.append(':'); buf.append(d.getId() != null ? d.getId() : ""); buf.append(':'); buf.append(d.getEmail() != null ? d.getEmail() : ""); } return buf.toString(); } /** * Finds and lists dependency plugins. */ private String findDependencyPlugins() throws IOException, MojoExecutionException { StringBuilder buf = new StringBuilder(); for (MavenArtifact a : getDirectDependencyArtfacts()) { if(a.isPlugin() && (includeTestScope || !"test".equals(a.getScope())) && !a.hasSameGAAs(project)) { if(buf.length()>0) buf.append(','); buf.append(a.getArtifactId()); buf.append(':'); buf.append(a.getVersion()); if (a.isOptional()) { buf.append(";resolution:=optional"); } } } // check any "provided" scope plugin dependencies that are probably not what the user intended. // see http://www.nabble.com/Classloading-problem-when-referencing-classes-from-another-plugin-during-the-initialization-phase-of-a-plugin-%28ClassicPluginStrategy%29-td25426117.html for (Artifact a : (Collection)project.getDependencyArtifacts()) if ("provided".equals(a.getScope()) && wrap(a).isPlugin()) throw new MojoExecutionException(a.getId()+" is marked as 'provided' scope dependency, but it should be the 'compile' scope."); return buf.toString(); } } AbstractJenkinsMojo.java000066400000000000000000000030751207142274300352600ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import java.util.List; /** * Mojos that need to figure out the Jenkins version it's working with. * * @author Kohsuke Kawaguchi */ public abstract class AbstractJenkinsMojo extends AbstractMojo { /** * The maven project. * * @parameter expression="${project}" * @required * @readonly */ protected MavenProject project; /** * Optional string that represents "groupId:artifactId" of Jenkins core jar. * If left unspecified, the default groupId/artifactId pair for Jenkins is looked for. * * @parameter * @since 1.65 */ protected String jenkinsCoreId; protected String findJenkinsVersion() throws MojoExecutionException { for(Dependency a : (List)project.getDependencies()) { boolean match; if (jenkinsCoreId!=null) match = (a.getGroupId()+':'+a.getArtifactId()).equals(jenkinsCoreId); else match = (a.getGroupId().equals("org.jenkins-ci.main") || a.getGroupId().equals("org.jvnet.hudson.main")) && (a.getArtifactId().equals("jenkins-core") || a.getArtifactId().equals("hudson-core")); if (match) return a.getVersion(); } throw new MojoExecutionException("Failed to determine Jenkins version this plugin depends on."); } } AbstractJetty6Mojo.java000066400000000000000000000041531207142274300350420ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; import org.mortbay.jetty.Connector; import org.mortbay.jetty.RequestLog; import org.mortbay.jetty.plugin.Jetty6PluginServer; import org.mortbay.jetty.plugin.util.JettyPluginServer; import org.mortbay.jetty.security.UserRealm; import org.mortbay.xml.XmlConfiguration; import java.io.File; /** * DO NOT MODIFY. * * Copied verbatim from Jetty code, just so that Maven's qdox can find * all the injection points. All the changes should go to {@link RunMojo}. */ public abstract class AbstractJetty6Mojo extends AbstractJettyMojo { /** * List of connectors to use. If none are configured * then we use a single SelectChannelConnector at port 8080 * * @parameter */ private Connector[] connectors; /** * List of security realms to set up. Optional. * @parameter */ private UserRealm[] userRealms; /** * A RequestLog implementation to use for the webapp at runtime. * Optional. * @parameter */ private RequestLog requestLog; /** * @see org.mortbay.jetty.plugin.AbstractJettyMojo#getConfiguredUserRealms() */ public Object[] getConfiguredUserRealms() { return this.userRealms; } /** * @see org.mortbay.jetty.plugin.AbstractJettyMojo#getConfiguredConnectors() */ public Object[] getConfiguredConnectors() { return this.connectors; } public Object getConfiguredRequestLog() { return this.requestLog; } public void applyJettyXml() throws Exception { if (getJettyXmlFileName() == null) return; getLog().info( "Configuring Jetty from xml configuration file = " + getJettyXmlFileName() ); File f = new File (getJettyXmlFileName()); XmlConfiguration xmlConfiguration = new XmlConfiguration(f.toURL()); xmlConfiguration.configure(getServer().getProxiedObject()); } /** * @see org.mortbay.jetty.plugin.AbstractJettyMojo#createServer() */ public JettyPluginServer createServer() throws Exception { return new Jetty6PluginServer(); } } AbstractJettyMojo.java000066400000000000000000000265301207142274300347570ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpi//======================================================================== //$Id: AbstractJettyMojo.java 36040 2010-10-18 11:24:56Z kohsuke $ //Copyright 2000-2004 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //Licensed under the Apache License, Version 2.0 (the "License"); //you may not use this file except in compliance with the License. //You may obtain a copy of the License at //http://www.apache.org/licenses/LICENSE-2.0 //Unless required by applicable law or agreed to in writing, software //distributed under the License is distributed on an "AS IS" BASIS, //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //See the License for the specific language governing permissions and //limitations under the License. //======================================================================== package org.jenkinsci.maven.plugins.hpi; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.mortbay.jetty.plugin.util.JettyPluginServer; import org.mortbay.jetty.plugin.util.JettyPluginWebApplication; import org.mortbay.jetty.plugin.util.PluginLog; import org.mortbay.jetty.plugin.util.Scanner; import org.mortbay.jetty.plugin.util.SystemProperty; import java.io.File; import java.util.ArrayList; /** * DO NOT MODIFY. * * Copied verbatim from Jetty code, just so that Maven's qdox can find * all the injection points. All the changes should go to {@link RunMojo}. */ public abstract class AbstractJettyMojo extends AbstractMojo { /** * The "virtual" webapp created by the plugin */ private JettyPluginWebApplication webapp; /** * The proxy for the Server object */ private JettyPluginServer server; /** * The maven project. * * @parameter expression="${project}" * @required * @readonly */ private MavenProject project; /** * The context path for the webapp. Defaults to "/" * * @parameter expression="${hpi.prefix}" default-value="/" * @required */ private String contextPath; /** * The temporary directory to use for the webapp. * Defaults to target/jetty-tmp * * @parameter expression="${project.build.directory}/work" * @required */ private File tmpDirectory; /** * A webdefault.xml file to use instead * of the default for the webapp. Optional. * * @parameter */ private File webDefaultXml; /** * The interval in seconds to scan the webapp for changes * and restart the context if necessary. Disabled by default. * * @parameter expression="${scanIntervalSeconds}" default-value="0" * @required */ private int scanIntervalSeconds; /** * System properties to set before execution. * Note that these properties will NOT override System properties * that have been set on the command line or by the JVM. Optional. * @parameter */ private SystemProperty[] systemProperties; /** * Location of a jetty xml configuration file whose contents * will be applied before any plugin configuration. Optional. * @parameter */ private String jettyConfig; /** * List of files and directories to scan */ private ArrayList scanList; /** * List of Listeners for the scanner */ private ArrayList scannerListeners; public String PORT_SYSPROPERTY = "jetty.port"; /** * @return Returns the realms configured in the pom */ public abstract Object[] getConfiguredUserRealms(); /** * @return Returns the connectors configured in the pom */ public abstract Object[] getConfiguredConnectors(); public abstract Object getConfiguredRequestLog(); public abstract void checkPomConfiguration() throws MojoExecutionException; public abstract void configureScanner () throws MojoExecutionException; public abstract void applyJettyXml () throws Exception; /** * create a proxy that wraps a particular jetty version Server object * @return */ public abstract JettyPluginServer createServer() throws Exception; public abstract void finishConfigurationBeforeStart() throws Exception; public MavenProject getProject() { return this.project; } public File getTmpDirectory() { return this.tmpDirectory; } public File getWebDefaultXml() { return this.webDefaultXml; } /** * @return Returns the contextPath. */ public String getContextPath() { return this.contextPath; } /** * @return Returns the scanIntervalSeconds. */ public int getScanIntervalSeconds() { return this.scanIntervalSeconds; } public SystemProperty[] getSystemProperties() { return this.systemProperties; } public String getJettyXmlFileName () { return this.jettyConfig; } public JettyPluginWebApplication getWebApplication() { return this.webapp; } public void setWebApplication (JettyPluginWebApplication webapp) { this.webapp = webapp; } public JettyPluginServer getServer () { return this.server; } public void setServer (JettyPluginServer server) { this.server = server; } public void setScanList (ArrayList list) { this.scanList = new ArrayList(list); } public ArrayList getScanList () { return this.scanList; } public void setScannerListeners (ArrayList listeners) { this.scannerListeners = new ArrayList(listeners); } public ArrayList getScannerListeners () { return this.scannerListeners; } public void execute() throws MojoExecutionException, MojoFailureException { getLog().info("Configuring Jetty for project: " + getProject().getName()); PluginLog.setLog(getLog()); checkPomConfiguration(); startJetty(); } public void startJetty () throws MojoExecutionException { try { getLog().debug("Starting Jetty Server ..."); configureSystemProperties(); setServer(createServer()); //apply any config from a jetty.xml file first which is able to //be overwritten by config in the pom.xml applyJettyXml (); JettyPluginServer plugin=getServer(); // if the user hasn't configured their project's pom to use a // different set of connectors, // use the default Object[] configuredConnectors = getConfiguredConnectors(); if (configuredConnectors == null|| configuredConnectors.length == 0) { //if a SystemProperty -Djetty.port= has been supplied, use that as the default port configuredConnectors = new Object[] { plugin.createDefaultConnector(getDefaultHttpPort()) }; } plugin.setConnectors(configuredConnectors); //set up a RequestLog if one is provided if (getConfiguredRequestLog() != null) getServer().setRequestLog(getConfiguredRequestLog()); //set up the webapp and any context provided getServer().configureHandlers(); setWebApplication(getServer().createWebApplication()); configureWebApplication(); getServer().addWebApplication(getWebApplication()); // set up security realms Object[] configuredRealms = getConfiguredUserRealms(); for (int i = 0; (configuredRealms != null) && i < configuredRealms.length; i++) getLog().debug(configuredRealms[i].getClass().getName() + ": "+ configuredRealms[i].toString()); plugin.setUserRealms(configuredRealms); //do any other configuration required by the //particular Jetty version finishConfigurationBeforeStart(); // start Jetty server.start(); getLog().info("Started Jetty Server"); // start the scanner thread (if necessary) on the main webapp configureScanner (); startScanner(); // keep the thread going server.join(); } catch (Exception e) { throw new MojoExecutionException("Failure", e); } finally { getLog().info("Jetty server exiting."); } } protected String getDefaultHttpPort() { return System.getProperty(PORT_SYSPROPERTY, null); } /** * Subclasses should invoke this to setup basic info * on the webapp * * @throws MojoExecutionException */ public void configureWebApplication () throws Exception { if (getWebApplication() == null) return; JettyPluginWebApplication webapp = getWebApplication(); webapp.setTempDirectory(getTmpDirectory()); webapp.setWebDefaultXmlFile(getWebDefaultXml()); String contextPath = getContextPath(); webapp.setContextPath((contextPath.startsWith("/") ? contextPath : "/"+ contextPath)); getLog().info("Context path = " + webapp.getContextPath()); getLog().info("Tmp directory = "+(getTmpDirectory()==null?" jetty default":getTmpDirectory().toString())); getLog().info("Web defaults = "+(getWebDefaultXml()==null?" jetty default":getWebDefaultXml().toString())); } /** * Run a scanner thread on the given list of files and directories, calling * stop/start on the given list of LifeCycle objects if any of the watched * files change. * */ protected void startScanner() { // check if scanning is enabled if (getScanIntervalSeconds() <= 0) return; Scanner scanner = new Scanner(); scanner.setScanInterval(getScanIntervalSeconds()); scanner.setRoots(getScanList()); scanner.setListeners(getScannerListeners()); getLog().info("Starting scanner at interval of " + getScanIntervalSeconds()+ " seconds."); scanner.start(); } private void configureSystemProperties () { // get the system properties set up for (int i = 0; (getSystemProperties() != null) && i < getSystemProperties().length; i++) { boolean result = getSystemProperties()[i].setIfNotSetAlready(); getLog().info("Property " + getSystemProperties()[i].getName() + "=" + getSystemProperties()[i].getValue() + " was " + (result ? "set" : "skipped")); } } /** * Try and find a jetty-web.xml file, using some * historical naming conventions if necessary. * @param webInfDir * @return */ public File findJettyWebXmlFile (File webInfDir) { if (webInfDir == null) return null; if (!webInfDir.exists()) return null; File f = new File (webInfDir, "jetty-web.xml"); if (f.exists()) return f; //try some historical alternatives f = new File (webInfDir, "web-jetty.xml"); if (f.exists()) return f; f = new File (webInfDir, "jetty6-web.xml"); if (f.exists()) return f; return null; } } maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpi/Artifacts.java000066400000000000000000000072571207142274300333530ustar00rootroot00000000000000package org.jenkinsci.maven.plugins.hpi; import com.google.common.base.Predicate; import org.apache.maven.artifact.Artifact; import org.apache.maven.project.MavenProject; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * Collection filter operations on a set of {@link Artifact}s. * * @author Kohsuke Kawaguchi */ public class Artifacts extends ArrayList { public Artifacts() { } public Artifacts(Collection c) { super(c); } /** * Return the {@link Artifact}s representing dependencies of the given project. * * A thin-wrapper of p.getArtifacts() */ public static Artifacts of(MavenProject p) { return new Artifacts(p.getArtifacts()); } public static Artifacts ofDirectDependencies(MavenProject p) { return new Artifacts(p.getDependencyArtifacts()); } public Artifacts retainAll(Predicate filter) { for (Iterator itr = iterator(); itr.hasNext(); ) { if (!filter.apply(itr.next())) itr.remove(); } return this; } public Artifacts removeAll(Predicate filter) { for (Iterator itr = iterator(); itr.hasNext(); ) { if (filter.apply(itr.next())) itr.remove(); } return this; } public Artifacts scopeIs(String... scopes) { final List s = Arrays.asList(scopes); return retainAll(new Predicate() { public boolean apply(Artifact a) { return s.contains(a.getScope()); } }); } public Artifacts scopeIsNot(String... scopes) { final List s = Arrays.asList(scopes); return removeAll(new Predicate() { public boolean apply(Artifact a) { return s.contains(a.getScope()); } }); } public Artifacts typeIs(String... type) { final List s = Arrays.asList(type); return retainAll(new Predicate() { public boolean apply(Artifact a) { return s.contains(a.getType()); } }); } public Artifacts typeIsNot(String... type) { final List s = Arrays.asList(type); return removeAll(new Predicate() { public boolean apply(Artifact a) { return s.contains(a.getType()); } }); } public Artifacts groupIdIs(String... groupId) { final List s = Arrays.asList(groupId); return retainAll(new Predicate() { public boolean apply(Artifact a) { return s.contains(a.getType()); } }); } public Artifacts groupIdIsNot(String... groupId) { final List s = Arrays.asList(groupId); return removeAll(new Predicate() { public boolean apply(Artifact a) { return s.contains(a.getType()); } }); } public Artifacts artifactIdIs(String... artifactId) { final List s = Arrays.asList(artifactId); return retainAll(new Predicate() { public boolean apply(Artifact a) { return s.contains(a.getType()); } }); } public Artifacts artifactIdIsNot(String... artifactId) { final List s = Arrays.asList(artifactId); return removeAll(new Predicate() { public boolean apply(Artifact a) { return s.contains(a.getType()); } }); } } ConsoleScanner.java000066400000000000000000000047601207142274300342640ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; import org.mortbay.jetty.plugin.util.Scanner; import org.mortbay.jetty.plugin.util.Scanner.Listener; import java.io.IOException; import java.util.Collections; import java.util.List; public class ConsoleScanner extends Thread { private final AbstractJettyMojo mojo; private final Scanner dummy = new Scanner(); public ConsoleScanner(AbstractJettyMojo mojo) { this.mojo = mojo; setName("Console scanner"); setDaemon(true); } public void run() { try { while (true) { checkSystemInput(); getSomeSleep(); } } catch (IOException e) { mojo.getLog().warn(e); } } private void getSomeSleep() { try { Thread.sleep(500); } catch (InterruptedException e) { mojo.getLog().debug(e); } } private void checkSystemInput() throws IOException { while (System.in.available() > 0) { int inputByte = System.in.read(); if (inputByte >= 0) { char c = (char)inputByte; if (c == '\n') { restartWebApp(); } } } } /** * Skip buffered bytes of system console. */ private void clearInputBuffer() { try { while (System.in.available() > 0) { // System.in.skip doesn't work properly. I don't know why long available = System.in.available(); for (int i = 0; i < available; i++) { if (System.in.read() == -1) { break; } } } } catch (IOException e) { mojo.getLog().warn("Error discarding console input buffer", e); } } private void restartWebApp() { try { for (Listener sc : (List)mojo.getScannerListeners()) { sc.changesDetected(dummy, Collections.emptyList()); } // Clear input buffer to discard anything entered on the console // while the application was being restarted. clearInputBuffer(); } catch (Exception e) { mojo.getLog().error("Error reconfiguring/restarting webapp after a new line on the console", e); } } } maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpi/CreateMojo.java000066400000000000000000000206401207142274300334520ustar00rootroot00000000000000/* * Copyright 2001-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jenkinsci.maven.plugins.hpi; import org.apache.maven.archetype.Archetype; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.ArtifactRepositoryFactory; import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.components.interactivity.Prompter; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.StringUtils; import java.io.File; import java.io.FileWriter; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; /** * Builds a new plugin template. *

*

* Most of this is really just a rip-off from the archetype:create goal, * but since Maven doesn't really let one Mojo calls another Mojo, this turns * out to be the easiest. * * @requiresProject false * @goal create */ public class CreateMojo extends AbstractMojo { /** * @component */ private Archetype archetype; /** * @component */ private Prompter prompter; /** * @component */ private ArtifactRepositoryFactory artifactRepositoryFactory; /** * @component role="org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout" roleHint="default" */ private ArtifactRepositoryLayout defaultArtifactRepositoryLayout; /** * @parameter expression="${localRepository}" * @required */ private ArtifactRepository localRepository; /** * @parameter expression="${groupId}" */ private String groupId; /** * @parameter expression="${artifactId}" */ private String artifactId; /** * @parameter expression="${version}" default-value="1.0-SNAPSHOT" * @required */ private String version; /** * @parameter expression="${packageName}" alias="package" */ private String packageName; /** * @parameter expression="${project.remoteArtifactRepositories}" * @required */ private List pomRemoteRepositories; /** * @parameter expression="${remoteRepositories}" */ private String remoteRepositories; /** * @parameter expression="${project}" */ private MavenProject project; public void execute() throws MojoExecutionException { try { // ---------------------------------------------------------------------- // archetypeGroupId // archetypeArtifactId // archetypeVersion // // localRepository // remoteRepository // parameters // ---------------------------------------------------------------------- if (project.getFile() != null && groupId == null) { groupId = project.getGroupId(); } if(groupId==null) { groupId = prompter.prompt("Enter the groupId of your plugin ["+DEFAULT_GROUPID+']'); if (StringUtils.isEmpty(groupId)) groupId = DEFAULT_GROUPID; } String basedir = System.getProperty("user.dir"); if (packageName == null) { getLog().info("Defaulting package to group ID + artifact ID: " + groupId+'.'+artifactId); packageName = replaceInvalidPackageNameChars(groupId+'.'+artifactId); } if(artifactId==null) { artifactId = prompter.prompt("Enter the artifactId of your plugin (normally without '-plugin' suffix)"); } // TODO: context mojo more appropriate? Map map = new HashMap(); map.put("basedir", basedir); map.put("package", packageName); map.put("groupId", groupId); map.put("artifactId", artifactId); map.put("version", version); List archetypeRemoteRepositories = new ArrayList(pomRemoteRepositories); if (remoteRepositories != null) { getLog().info("We are using command line specified remote repositories: " + remoteRepositories); archetypeRemoteRepositories = new ArrayList(); String[] s = StringUtils.split(remoteRepositories, ","); for (int i = 0; i < s.length; i++) { archetypeRemoteRepositories.add(createRepository(s[i], "id" + i)); } } Properties props = new Properties(); props.load(getClass().getResourceAsStream("plugin.properties")); archetype.createArchetype( props.getProperty("groupId"), props.getProperty("artifactId"), props.getProperty("version"), localRepository, archetypeRemoteRepositories, map); // copy view resource files. So far maven archetype doesn't seem to be able to handle it. File outDir = new File( basedir, artifactId ); char sep = File.separatorChar; File viewDir = new File( outDir, "src"+sep+"main"+sep+"resources"+sep+packageName.replace('.',sep)+sep+"HelloWorldBuilder" ); viewDir.mkdirs(); for( String s : new String[]{"config.jelly","global.jelly","help-name.html","help-useFrench.html"} ) { InputStream in = getClass().getResourceAsStream("/archetype-resources/src/main/resources/HelloWorldBuilder/"+s); FileWriter out = new FileWriter(new File(viewDir, s)); out.write(IOUtil.toString(in).replace("@artifactId@", artifactId)); in.close(); out.close(); } } catch (Exception e) { throw new MojoExecutionException("Failed to create a new Jenkins plugin",e); } } /** * Replaces all characters which are invalid in package names. * * TODO: Currently this only handles '-' */ private String replaceInvalidPackageNameChars(String packageName) { StringBuilder buf = new StringBuilder(packageName); boolean changed = false; int i = 0; while (i < buf.length()) { char c = buf.charAt(i); if (c == '-') { buf.deleteCharAt(i); changed = true; } else { i++; } } if (changed && !packageName.equals(DEFAULT_GROUPID)) { getLog().warn("Package name contains invalid characters. Replacing it with '" + buf + "'"); } return buf.toString(); } //TODO: this should be put in John's artifact utils and used from there instead of being repeated here. Creating // artifact repositories is somewhat cumbersome atm. public ArtifactRepository createRepository(String url, String repositoryId) { // snapshots vs releases // offline = to turning the update policy off //TODO: we'll need to allow finer grained creation of repositories but this will do for now String updatePolicyFlag = ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS; String checksumPolicyFlag = ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN; ArtifactRepositoryPolicy snapshotsPolicy = new ArtifactRepositoryPolicy(true, updatePolicyFlag, checksumPolicyFlag); ArtifactRepositoryPolicy releasesPolicy = new ArtifactRepositoryPolicy(true, updatePolicyFlag, checksumPolicyFlag); return artifactRepositoryFactory.createArtifactRepository(repositoryId, url, defaultArtifactRepositoryLayout, snapshotsPolicy, releasesPolicy); } private static final String DEFAULT_GROUPID = "org.jenkins-ci.plugins"; } maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpi/HpiMojo.java000066400000000000000000000154771207142274300330030ustar00rootroot00000000000000package org.jenkinsci.maven.plugins.hpi; /* * Copyright 2001-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import org.apache.maven.archiver.MavenArchiveConfiguration; import org.apache.maven.archiver.MavenArchiver; import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProjectHelper; import org.codehaus.plexus.archiver.ArchiverException; import org.codehaus.plexus.archiver.jar.JarArchiver; import org.codehaus.plexus.archiver.jar.Manifest; import org.codehaus.plexus.archiver.jar.Manifest.Section; import org.codehaus.plexus.archiver.jar.ManifestException; import org.codehaus.plexus.util.IOUtil; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; /** * Build a war/webapp. * * @author Emmanuel Venisse * @version $Id: HpiMojo.java 33552 2010-08-03 23:28:55Z olamy $ * @goal hpi * @phase package * @requiresDependencyResolution runtime */ public class HpiMojo extends AbstractHpiMojo { /** * The name of the generated hpi. * * @parameter expression="${project.build.finalName}" * @required */ private String hpiName; /** * Used to create .jar archive. * * @component role="org.codehaus.plexus.archiver.Archiver" role-hint="jar" * @required */ private JarArchiver jarArchiver; /** * Used to create .hpi archive. * * @component role="org.codehaus.plexus.archiver.Archiver" role-hint="jar" * @required */ private JarArchiver hpiArchiver; /** * The maven archive configuration to use. * * @parameter */ private MavenArchiveConfiguration archive = new MavenArchiveConfiguration(); /** * @component */ private MavenProjectHelper projectHelper; // ---------------------------------------------------------------------- // Implementation // ---------------------------------------------------------------------- protected File getOutputFile(String extension) { return new File(new File(outputDirectory), hpiName + extension); } /** * Executes the WarMojo on the current project. * * @throws MojoExecutionException if an error occurred while building the webapp */ public void execute() throws MojoExecutionException { try { performPackaging(); } catch (DependencyResolutionRequiredException e) { throw new MojoExecutionException("Error assembling hpi: " + e.getMessage(), e); } catch (ManifestException e) { throw new MojoExecutionException("Error assembling hpi", e); } catch (IOException e) { throw new MojoExecutionException("Error assembling hpi", e); } catch (ArchiverException e) { throw new MojoExecutionException("Error assembling hpi: " + e.getMessage(), e); } } /** * Generates the webapp according to the mode attribute. * * @throws IOException * @throws ArchiverException * @throws ManifestException * @throws DependencyResolutionRequiredException * */ private void performPackaging() throws IOException, ArchiverException, ManifestException, DependencyResolutionRequiredException, MojoExecutionException { File hpiFile = getOutputFile(".hpi"); buildExplodedWebapp(getWebappDirectory()); //generate war file getLog().info("Generating hpi " + hpiFile.getAbsolutePath()); MavenArchiver archiver = new MavenArchiver(); archiver.setArchiver(hpiArchiver); archiver.setOutputFile(hpiFile); File manifestFile = new File(getWebappDirectory(), "META-INF/MANIFEST.MF"); generateManifest(manifestFile); Manifest manifest = loadManifest(manifestFile); hpiArchiver.addConfiguredManifest(manifest); hpiArchiver.addDirectory(getWebappDirectory(), getIncludes(), getExcludes()); // create archive archiver.createArchive(project, archive); project.getArtifact().setFile(hpiFile); // also creates a jar file to be used when other plugins depend on this plugin. File jarFile = getOutputFile(".jar"); archiver = new MavenArchiver(); archiver.setArchiver(jarArchiver); archiver.setOutputFile(jarFile); jarArchiver.addConfiguredManifest(manifest); jarArchiver.addDirectory(getClassesDirectory()); archiver.createArchive(project,archive); projectHelper.attachArtifact(project, "jar", null, jarFile); } private Manifest loadManifest(File f) throws IOException, ManifestException { InputStreamReader r = new InputStreamReader(new FileInputStream(f), "UTF-8"); try { return new Manifest(r); } finally { IOUtil.close(r); } } /** * Generates a manifest file to be included in the .hpi file */ private void generateManifest(File manifestFile) throws MojoExecutionException { // create directory if it doesn't exist yet if(!manifestFile.getParentFile().exists()) manifestFile.getParentFile().mkdirs(); getLog().info("Generating "+manifestFile); MavenArchiver ma = new MavenArchiver(); ma.setOutputFile(manifestFile); PrintWriter printWriter = null; try { Manifest mf = ma.getManifest(project, archive.getManifest()); Section mainSection = mf.getMainSection(); setAttributes(mainSection); printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(manifestFile),"UTF-8")); mf.write(printWriter); } catch (ManifestException e) { throw new MojoExecutionException("Error preparing the manifest: " + e.getMessage(), e); } catch (DependencyResolutionRequiredException e) { throw new MojoExecutionException("Error preparing the manifest: " + e.getMessage(), e); } catch (IOException e) { throw new MojoExecutionException("Error preparing the manifest: " + e.getMessage(), e); } finally { IOUtil.close(printWriter); } } } maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpi/HplMojo.java000066400000000000000000000074611207142274300330000ustar00rootroot00000000000000package org.jenkinsci.maven.plugins.hpi; import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.model.Resource; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.codehaus.plexus.archiver.jar.Manifest; import org.codehaus.plexus.archiver.jar.Manifest.Attribute; import org.codehaus.plexus.archiver.jar.Manifest.Section; import org.codehaus.plexus.archiver.jar.ManifestException; import org.codehaus.plexus.util.IOUtil; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.List; /** * Generate .hpl file. * * @author Kohsuke Kawaguchi * @goal hpl * @requiresDependencyResolution runtime */ public class HplMojo extends AbstractHpiMojo { /** * Path to $JENKINS_HOME. A .hpl file will be generated to this location. * * @parameter expression="${hudsonHome} */ private File hudsonHome; public void setHudsonHome(File hudsonHome) { this.hudsonHome = hudsonHome; } public void execute() throws MojoExecutionException, MojoFailureException { if(!project.getPackaging().equals("hpi")) { getLog().info("Skipping "+project.getName()+" because it's not hpi"); return; } File hplFile = computeHplFile(); getLog().info("Generating "+hplFile); PrintWriter printWriter = null; try { Manifest mf = new Manifest(); Section mainSection = mf.getMainSection(); setAttributes(mainSection); // compute Libraries entry StringBuilder buf = new StringBuilder(); // we want resources to be picked up before target/classes, // so that the original (not in the copy) will be picked up first. for (Resource r : (List) project.getBuild().getResources()) { if(buf.length()>0) buf.append(','); if(new File(project.getBasedir(),r.getDirectory()).exists()) buf.append(r.getDirectory()); } try { for (String f : (List) project.getRuntimeClasspathElements()) { if (buf.length() > 0) { buf.append(','); } buf.append(f); } } catch (DependencyResolutionRequiredException x) { throw new MojoExecutionException("Failed to resolve " + x, x); } mainSection.addAttributeAndCheck(new Attribute("Libraries",buf.toString())); // compute Resource-Path entry mainSection.addAttributeAndCheck(new Attribute("Resource-Path",warSourceDirectory.getAbsolutePath())); printWriter = new PrintWriter(new FileWriter(hplFile)); mf.write(printWriter); } catch (ManifestException e) { throw new MojoExecutionException("Error preparing the manifest: " + e.getMessage(), e); } catch (IOException e) { throw new MojoExecutionException("Error preparing the manifest: " + e.getMessage(), e); } finally { IOUtil.close(printWriter); } } /** * Determine where to produce the .hpl file. */ protected File computeHplFile() throws MojoExecutionException { if(hudsonHome==null) { throw new MojoExecutionException( "Property hudsonHome needs to be set to $HUDSON_HOME. Please use 'mvn -DhudsonHome=...' or" + "put ..." ); } File hplFile = new File(hudsonHome, "plugins/" + project.getBuild().getFinalName() + ".hpl"); return hplFile; } } ListPluginDependenciesMojo.java000066400000000000000000000026751207142274300366010ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.codehaus.groovy.control.io.NullWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; /** * List up all the plugin dependencies. * * @goal list-plugin-dependencies * @requiresDependencyResolution compile * @author Kohsuke Kawaguchi */ public class ListPluginDependenciesMojo extends AbstractHpiMojo { /** * If non-null, the output will be sent to a file * * @parameter expression="${outputFile}" */ protected File outputFile; public void execute() throws MojoExecutionException, MojoFailureException { try { Writer w = outputFile==null ? new NullWriter() : new OutputStreamWriter(new FileOutputStream(outputFile),"UTF-8"); for (MavenArtifact a : getDirectDependencyArtfacts()) { if(!a.isPlugin()) continue; String line = String.format("%s:%s:%s", a.getGroupId(), a.getArtifactId(), a.artifact.getBaseVersion()); w.write(line); w.write('\n'); getLog().info(line); } w.close(); } catch (IOException e) { throw new MojoExecutionException("Failed to list plugin dependencies",e); } } } MavenArtifact.java000066400000000000000000000063711207142274300340740ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectBuilder; import org.apache.maven.project.ProjectBuildingException; import org.kohsuke.stapler.framework.io.IOException2; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.jar.JarFile; import java.util.jar.Manifest; /** * {@link Artifact} is a bare data structure without any behavior and therefore * hard to write OO programs around it. * * This class wraps {@link Artifact} and adds behaviours. * * @author Kohsuke Kawaguchi */ public class MavenArtifact { public final MavenProjectBuilder builder; public final List remoteRepositories; public final ArtifactRepository localRepository; public final Artifact artifact; public MavenArtifact(Artifact artifact, MavenProjectBuilder builder, List remoteRepositories, ArtifactRepository localRepository) { this.artifact = artifact; this.builder = builder; this.remoteRepositories = remoteRepositories; this.localRepository = localRepository; } public MavenProject resolvePom() throws ProjectBuildingException { return builder.buildFromRepository(artifact,remoteRepositories,localRepository); } /** * Is this a Jenkins plugin? */ public boolean isPlugin() throws IOException { try { // some artifacts aren't even Java, so ignore those. if(!artifact.getType().equals("jar")) return false; return resolvePom().getPackaging().equals("hpi"); } catch (ProjectBuildingException e) { throw new IOException2("Failed to open artifact "+artifact.toString()+" at "+artifact.getFile(),e); } } public String getId() { return artifact.getId(); } /** * Converts the filename of an artifact to artifactId-version.type format. * * @return converted filename of the artifact */ public String getDefaultFinalName() { return artifact.getArtifactId() + "-" + artifact.getVersion() + "." + artifact.getArtifactHandler().getExtension(); } public boolean isOptional() { return artifact.isOptional(); } public String getType() { return artifact.getType(); } public File getFile() { // TODO: should we resolve? return artifact.getFile(); } public List getDependencyTrail() { return artifact.getDependencyTrail(); } public String getGroupId() { return artifact.getGroupId(); } public String getScope() { return artifact.getScope(); } public String getArtifactId() { return artifact.getArtifactId(); } public String getVersion() { return artifact.getVersion(); } /** * Returns true if this artifact has the same groupId and artifactId as the given project. */ public boolean hasSameGAAs(MavenProject project) { return getGroupId().equals(project.getGroupId()) && getArtifactId().equals(project.getArtifactId()); } } PropertyUtils.java000066400000000000000000000104451207142274300342120ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; /* * Copyright 2001-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import org.codehaus.plexus.util.IOUtil; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Enumeration; import java.util.Properties; /** * @author Kenney Westerhof * @version $Id: PropertyUtils.java 10807 2008-07-14 18:56:05Z btosabre $ * @todo this is duplicated from the resources plugin - migrate to plexus-utils */ public final class PropertyUtils { private PropertyUtils() { // prevent instantiation } /** * Reads a property file, resolving all internal variables. * * @param propfile The property file to load * @param fail whether to throw an exception when the file cannot be loaded or to return null * @param useSystemProps whether to incorporate System.getProperties settings into the returned Properties object. * @return the loaded and fully resolved Properties object */ public static Properties loadPropertyFile(File propfile, boolean fail, boolean useSystemProps) throws IOException { Properties props = new Properties(); if (useSystemProps) { props = new Properties(System.getProperties()); } if (propfile.exists()) { FileInputStream inStream = new FileInputStream(propfile); try { props.load(inStream); } finally { IOUtil.close(inStream); } } else if (fail) { throw new FileNotFoundException(propfile.toString()); } for (Enumeration n = props.propertyNames(); n.hasMoreElements();) { String k = (String) n.nextElement(); props.setProperty(k, PropertyUtils.getPropertyValue(k, props)); } return props; } /** * Retrieves a property value, replacing values like ${token} * using the Properties to look them up. *

* It will leave unresolved properties alone, trying for System * properties, and implements reparsing (in the case that * the value of a property contains a key), and will * not loop endlessly on a pair like * test = ${test}. */ private static String getPropertyValue(String k, Properties p) { // This can also be done using InterpolationFilterReader, // but it requires reparsing the file over and over until // it doesn't change. String v = p.getProperty(k); String ret = ""; int idx, idx2; while ((idx = v.indexOf("${")) >= 0) { // append prefix to result ret += v.substring(0, idx); // strip prefix from original v = v.substring(idx + 2); // if no matching } then bail if ((idx2 = v.indexOf('}')) < 0) { break; } // strip out the key and resolve it // resolve the key/value for the ${statement} String nk = v.substring(0, idx2); v = v.substring(idx2 + 1); String nv = p.getProperty(nk); // try global environment.. if (nv == null) { nv = System.getProperty(nk); } // if the key cannot be resolved, // leave it alone ( and don't parse again ) // else prefix the original string with the // resolved property ( so it can be parsed further ) // taking recursion into account. if (nv == null || nv.equals(k)) { ret += "${" + nk + "}"; } else { v = nv + v; } } return ret + v; } } ReservedName.java000066400000000000000000000024001207142274300337150ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * @author Kohsuke Kawaguchi */ class ReservedName { static Set NAMES = new HashSet(Arrays.asList( "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while", // technically these are not reserved words but they cannot be used as identifiers. "true", "false", "null" )); } maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpi/RunMojo.java000066400000000000000000000520301207142274300330110ustar00rootroot00000000000000//======================================================================== //$Id: RunMojo.java 36037 2010-10-18 09:48:58Z kohsuke $ //Copyright 2000-2004 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //Licensed under the Apache License, Version 2.0 (the "License"); //you may not use this file except in compliance with the License. //You may obtain a copy of the License at //http://www.apache.org/licenses/LICENSE-2.0 //Unless required by applicable law or agreed to in writing, software //distributed under the License is distributed on an "AS IS" BASIS, //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //See the License for the specific language governing permissions and //limitations under the License. //======================================================================== package org.jenkinsci.maven.plugins.hpi; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.metadata.ArtifactMetadataSource; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.ArtifactNotFoundException; import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.artifact.resolver.ArtifactResolutionResult; import org.apache.maven.artifact.resolver.ArtifactResolver; import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; import org.apache.maven.model.Resource; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProjectBuilder; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.Copy; import org.apache.commons.io.FileUtils; import org.mortbay.jetty.nio.SelectChannelConnector; import org.mortbay.jetty.plugin.Jetty6PluginServer; import org.mortbay.jetty.plugin.util.JettyPluginServer; import org.mortbay.jetty.plugin.util.Scanner; import org.mortbay.jetty.plugin.util.Scanner.Listener; import org.mortbay.jetty.plugin.util.SystemProperty; import org.mortbay.jetty.webapp.WebAppClassLoader; import org.mortbay.jetty.webapp.WebAppContext; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.regex.Pattern; /** * Runs Jenkins with the current plugin project. * *

* This only needs the source files to be compiled, so run in the compile phase. *

* *

* To specify the HTTP port, use -Djetty.port=PORT *

* * @goal run * @execute phase=compile * @description Runs Jenkins with the current plugin * @author Kohsuke Kawaguchi */ public class RunMojo extends AbstractJetty6Mojo { /** * The location of the war file. * *

* Normally this should be left empty, in which case the plugin loads it from the repository. * But this parameter allows that to be overwritten. *

* * @parameter */ private File webApp; /** * Path to $JENKINS_HOME. The launched Jenkins will use this directory as the workspace. * * @parameter expression="${HUDSON_HOME}" */ private File jenkinsHome; /** * Decides the level of dependency resolution. * * @parameter */ private String dependencyResolution = "compile"; /** * Single directory for extra files to include in the WAR. * * @parameter expression="${basedir}/src/main/webapp" * @required */ protected File warSourceDirectory; /** * @component */ protected ArtifactResolver artifactResolver; /** * @component */ protected ArtifactFactory artifactFactory; /** * @parameter expression="${localRepository}" * @required */ protected ArtifactRepository localRepository; /** * @component */ protected ArtifactMetadataSource artifactMetadataSource; /** * Specifies the HTTP port number. * * If connectors are configured in the Mojo, that'll take precedence. * * @parameter expression="${port}" */ protected String defaultPort; /** * If true, the context will be restarted after a line feed on * the input console. Disabled by default. * * @parameter expression="${jetty.consoleForceReload}" default-value="true" */ protected boolean consoleForceReload; /** * @component */ protected MavenProjectBuilder projectBuilder; /** * Optional string that represents "groupId:artifactId" of Jenkins core jar. * If left unspecified, the default groupId/artifactId pair for Jenkins is looked for. * * @parameter * @since 1.65 */ protected String jenkinsCoreId; /** * Optional string that represents "groupId:artifactId" of Jenkins war. * If left unspecified, the default groupId/artifactId pair for Jenkins is looked for. * * @parameter * @since 1.68 */ protected String jenkinsWarId; /** * [ws|tab|CR|LF]+ separated list of package prefixes that your plugin doesn't want to see * from the core. * *

* Tokens in this list is prefix-matched against the fully-qualified class name, so add * "." to the end of each package name, like "com.foo. com.bar." * * @parameter */ protected String maskClasses; /** * List of additionnal System properties to set * * @parameter * @since 1.85 */ private Map systemProperties; public void execute() throws MojoExecutionException, MojoFailureException { getProject().setArtifacts(resolveDependencies(dependencyResolution)); // compute hudsonHome if(jenkinsHome ==null) { String h = System.getenv("HUDSON_HOME"); if(h!=null) jenkinsHome = new File(h); else jenkinsHome = new File("./work"); } // auto-enable stapler trace, unless otherwise configured already. setSystemPropertyIfEmpty("stapler.trace", "true"); // run YUI in the debug mode, unless otherwise configured setSystemPropertyIfEmpty("debug.YUI","true"); // allow Jetty to accept a bigger form so that it can handle update center JSON post setSystemPropertyIfEmpty("org.mortbay.jetty.Request.maxFormContentSize","-1"); // general-purpose system property so that we can tell from Jenkins if we are running in the hpi:run mode. setSystemPropertyIfEmpty("hudson.hpi.run","true"); // this adds 3 secs to the shutdown time. Skip it. setSystemPropertyIfEmpty("hudson.DNSMultiCast.disabled","true"); // expose the current top-directory of the plugin setSystemPropertyIfEmpty("jenkins.moduleRoot",new File(".").getAbsolutePath()); if (systemProperties != null && !systemProperties.isEmpty()) { for (Map.Entry entry : systemProperties.entrySet()) { if (entry.getKey() != null && entry.getValue()!=null) { System.setProperty( entry.getKey(), entry.getValue() ); } } } // look for jenkins.war Artifacts jenkinsArtifacts = Artifacts.of(getProject()) .groupIdIs("org.jenkins-ci.main","org.jvnet.hudson.main") .artifactIdIsNot("remoting"); // remoting moved to its own release cycle webApp = getJenkinsWarArtifact().getFile(); // make sure all the relevant Jenkins artifacts have the same version for (Artifact a : jenkinsArtifacts) { Artifact ba = jenkinsArtifacts.get(0); if(!a.getVersion().equals(ba.getVersion())) throw new MojoExecutionException("Version of "+a.getId()+" is inconsistent with "+ba.getId()); } // set HUDSON_HOME SystemProperty sp = new SystemProperty(); sp.setName("HUDSON_HOME"); sp.setValue(jenkinsHome.getAbsolutePath()); sp.setIfNotSetAlready(); File pluginsDir = new File(jenkinsHome, "plugins"); pluginsDir.mkdirs(); // enable view auto refreshing via stapler sp = new SystemProperty(); sp.setName("stapler.jelly.noCache"); sp.setValue("true"); sp.setIfNotSetAlready(); List res = getProject().getBuild().getResources(); if(!res.isEmpty()) { // pick up the first one and use it Resource r = (Resource) res.get(0); sp = new SystemProperty(); sp.setName("stapler.resourcePath"); sp.setValue(r.getDirectory()); sp.setIfNotSetAlready(); } generateHpl(); // copy other dependency Jenkins plugins try { for( MavenArtifact a : getProjectArtfacts() ) { if(!a.isPlugin()) continue; getLog().info("Copying dependency Jenkins plugin "+a.getFile()); // find corresponding .hpi file Artifact hpi = artifactFactory.createArtifact(a.getGroupId(),a.getArtifactId(),a.getVersion(),null,"hpi"); artifactResolver.resolve(hpi,getProject().getRemoteArtifactRepositories(), localRepository); // check recursive dependency. this is a rare case that happens when we split out some things from the core // into a plugin if (hasSameGavAsProject(hpi)) continue; if (hpi.getFile().isDirectory()) throw new UnsupportedOperationException(hpi.getFile()+" is a directory and not packaged yet. this isn't supported"); copyFile(hpi.getFile(),new File(pluginsDir,a.getArtifactId()+".hpi")); // pin the dependency plugin, so that even if a different version of the same plugin is bundled to Jenkins, // we still use the plugin as specified by the POM of the plugin. FileUtils.writeStringToFile(new File(pluginsDir,a.getArtifactId()+".hpi.pinned"),"pinned"); } } catch (IOException e) { throw new MojoExecutionException("Unable to copy dependency plugin",e); } catch (ArtifactNotFoundException e) { throw new MojoExecutionException("Unable to copy dependency plugin",e); } catch (ArtifactResolutionException e) { throw new MojoExecutionException("Unable to copy dependency plugin",e); } super.execute(); } private boolean hasSameGavAsProject(Artifact a) { return getProject().getGroupId().equals(a.getGroupId()) && getProject().getArtifactId().equals(a.getArtifactId()) && getProject().getVersion().equals(a.getVersion()); } private void setSystemPropertyIfEmpty(String name, String value) { if(System.getProperty(name)==null) System.setProperty(name, value); } private void copyFile(File src, File dst) { Copy cp = new Copy(); cp.setProject(new Project()); cp.setFile(src); cp.setTofile(dst); cp.execute(); } /** * Create a dot-hpl file. * *

* All I want to do here is to invoke the hpl target. * there must be a better way to do this! * *

* Besides, if the user wants to change the plugin name, etc, * this forces them to do it in two places. */ private void generateHpl() throws MojoExecutionException, MojoFailureException { HplMojo hpl = new HplMojo(); hpl.project = getProject(); hpl.setHudsonHome(jenkinsHome); hpl.setLog(getLog()); hpl.pluginName = getProject().getName(); hpl.warSourceDirectory = warSourceDirectory; hpl.includeTestScope = true; hpl.projectBuilder = this.projectBuilder; hpl.localRepository = this.localRepository; hpl.jenkinsCoreId = this.jenkinsCoreId; hpl.maskClasses = this.maskClasses; hpl.execute(); } public void configureWebApplication() throws Exception { // Jetty tries to do this in WebAppContext.resolveWebApp but it failed to delete the directory. File extractedWebAppDir= new File(getTmpDirectory(), "webapp"); if(extractedWebAppDir.lastModified() < webApp.lastModified()) FileUtils.deleteDirectory(extractedWebAppDir); super.configureWebApplication(); getWebApplication().setWebAppSrcDir(webApp); } public void configureScanner() throws MojoExecutionException { setUpScanList(new ArrayList()); ArrayList listeners = new ArrayList(); listeners.add(new Listener() { public void changesDetected(Scanner scanner, List changes) { try { getLog().info("Restarting webapp ..."); getLog().debug("Stopping webapp ..."); getWebApplication().stop(); getLog().debug("Reconfiguring webapp ..."); checkPomConfiguration(); // check if we need to reconfigure the scanner, // which is if the pom changes if (changes.contains(getProject().getFile().getCanonicalPath())) { getLog().info("Reconfiguring scanner after change to pom.xml ..."); generateHpl(); // regenerate hpl if POM changes. ArrayList scanList = getScanList(); scanList.clear(); setUpScanList(scanList); scanner.setRoots(scanList); } getLog().debug("Restarting webapp ..."); getWebApplication().start(); getLog().info("Restart completed."); } catch (Exception e) { getLog().error("Error reconfiguring/restarting webapp after change in watched files", e); } } }); setScannerListeners(listeners); } private void setUpScanList(ArrayList scanList) { scanList.add(getProject().getFile()); scanList.add(webApp); scanList.add(new File(getProject().getBuild().getOutputDirectory())); setScanList(scanList); } @Override protected void startScanner() { super.startScanner(); if (consoleForceReload) { getLog().info("Console reloading is ENABLED. Hit ENTER on the console to restart the context."); new ConsoleScanner(this).start(); } } public void checkPomConfiguration() throws MojoExecutionException { } public void finishConfigurationBeforeStart() { // working around JETTY-1226. This bug affects those who use Axis from plugins, for example. WebAppContext wac = (WebAppContext)getWebApplication().getProxiedObject(); List sc = new ArrayList(Arrays.asList(wac.getSystemClasses())); sc.add("javax.activation."); wac.setSystemClasses(sc.toArray(new String[sc.size()])); // to allow the development environment to run multiple "mvn hpi:run" with different port, // use different session cookie names. Otherwise they can mix up. See // http://stackoverflow.com/questions/1612177/are-http-cookies-port-specific wac.getSessionHandler().getSessionManager().setSessionCookie("JSESSIONID."+UUID.randomUUID().toString().replace("-","").substring(0,8)); try { // for Jenkins modules, swap the component from jenkins.war by target/classes // via classloader magic WebAppClassLoader wacl = new WebAppClassLoader(new ServletApiOnlyClassLoader(null,getClass().getClassLoader()),wac) { private final Pattern exclusionPattern; { if (getProject().getPackaging().equals("jenkins-module")) { // classes compiled from jenkins module should behave as if it's a part of the core // load resources from source folders directly for (Resource r : (List)getProject().getResources()) super.addURL(new File(r.getDirectory()).toURL()); super.addURL(new File(getProject().getBuild().getOutputDirectory()).toURL()); // add all the jar dependencies of the module // "provided" includes all core and others, so drop them // similarly, "test" would pull in all the harness // pom dependency is sometimes used so that one can depend on its transitive dependencies for (Artifact a : Artifacts.of(getProject()).scopeIsNot("provided","test").typeIsNot("pom")) { super.addURL(a.getFile().toURI().toURL()); } exclusionPattern = Pattern.compile("[/\\\\]\\Q"+getProject().getArtifactId()+"\\E-[0-9]([^/\\\\]+)\\.jar$"); } else { exclusionPattern = Pattern.compile("this should never match"); } } @Override public void addClassPath(String classPath) throws IOException { if (exclusionPattern.matcher(classPath).find()) return; super.addClassPath(classPath); } @Override public void addJars(org.mortbay.resource.Resource lib) { super.addJars(lib); } }; wac.setClassLoader(wacl); } catch (IOException e) { throw new Error(e); } } @Override protected String getDefaultHttpPort() { if (defaultPort!=null) return defaultPort; return super.getDefaultHttpPort(); } public JettyPluginServer createServer() throws Exception { return new Jetty6PluginServer() { @Override public Object createDefaultConnector(String portnum) throws Exception { SelectChannelConnector con = (SelectChannelConnector)super.createDefaultConnector(portnum); con.setHeaderBufferSize(12*1024); // use a bigger buffer as Stapler traces can get pretty large on deeply nested URL return con; } }; } /** * Performs the equivalent of "@requireDependencyResolution" mojo attribute, * so that we can choose the scope at runtime. * @param scope */ private Set resolveDependencies(String scope) throws MojoExecutionException { try { ArtifactResolutionResult result = artifactResolver.resolveTransitively( getProject().getDependencyArtifacts(), getProject().getArtifact(), getProject().getManagedVersionMap(), localRepository, getProject().getRemoteArtifactRepositories(), artifactMetadataSource, new ScopeArtifactFilter(scope)); return result.getArtifacts(); } catch (ArtifactNotFoundException e) { throw new MojoExecutionException("Unable to copy dependency plugin",e); } catch (ArtifactResolutionException e) { throw new MojoExecutionException("Unable to copy dependency plugin",e); } } public Set getProjectArtfacts() { Set r = new HashSet(); for (Artifact a : (Collection)getProject().getArtifacts()) { r.add(wrap(a)); } return r; } protected MavenArtifact wrap(Artifact a) { return new MavenArtifact(a,projectBuilder,getProject().getRemoteArtifactRepositories(),localRepository); } protected Artifact getJenkinsWarArtifact() throws MojoExecutionException { for( Artifact a : resolveDependencies("test") ) { boolean match; if (jenkinsWarId!=null) match = (a.getGroupId()+':'+a.getArtifactId()).equals(jenkinsWarId); else match = (a.getArtifactId().equals("jenkins-war") || a.getArtifactId().equals("hudson-war")) && a.getType().equals("war"); if(match) return a; } if (jenkinsWarId!=null) { getLog().error("Unable to locate jenkins.war in '"+jenkinsWarId+"'"); } else { getLog().error( "Unable to locate jenkins.war. Add the following dependency in your POM:\n" + "\n" + "\n" + " org.jenkins-ci.main\n" + " jenkins-war\n" + " war\n" + " 1.396\n" + " test\n" + "" ); } throw new MojoExecutionException("Unable to find jenkins.war"); } } ServletApiOnlyClassLoader.java000066400000000000000000000016121207142274300363760ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; /** * Only exposes servlet API from Jetty to the web application, then JavaSE. * *

* This is because the classloader that loads this plugin brings in a whole lot of baggage, such as * Maven, Xalan, commons libraries, and etc., which can interfere with what's in Jenkins and plugins. * * @author Kohsuke Kawaguchi */ public class ServletApiOnlyClassLoader extends ClassLoader { private final ClassLoader jettyClassLoader; public ServletApiOnlyClassLoader(ClassLoader parent, ClassLoader jettyClassLoader) { super(parent); this.jettyClassLoader = jettyClassLoader; } @Override protected Class findClass(String name) throws ClassNotFoundException { if (name.startsWith("javax.")) return jettyClassLoader.loadClass(name); else throw new ClassNotFoundException(name); } } TagLibInterfaceGeneratorMojo.java000066400000000000000000000127451207142274300370310ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; import com.sun.codemodel.JClassAlreadyExistsException; import com.sun.codemodel.JCodeModel; import com.sun.codemodel.JDefinedClass; import com.sun.codemodel.JDocComment; import com.sun.codemodel.JJavaName; import com.sun.codemodel.JMethod; import com.sun.codemodel.JPackage; import groovy.lang.Closure; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang.StringUtils; import org.apache.maven.model.Resource; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.QName; import org.dom4j.io.SAXReader; import org.kohsuke.stapler.jelly.groovy.TagFile; import org.kohsuke.stapler.jelly.groovy.TagLibraryUri; import org.kohsuke.stapler.jelly.groovy.TypedTagLibrary; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; import java.io.IOException; import java.util.List; import java.util.Map; /** * Generates the strongly-typed Java interfaces for Groovy taglibs. * * @author Kohsuke Kawaguchi * @goal generate-taglib-interface * @phase generate-resources */ public class TagLibInterfaceGeneratorMojo extends AbstractMojo { /** * The maven project. * * @parameter expression="${project}" * @required * @readonly */ protected MavenProject project; /** * The directory for the generated WAR. * * @parameter expression="${project.basedir}/target/generated-sources/taglib-interface" * @required */ protected File outputDirectory; private SAXReader saxReader = new SAXReader(); public void execute() throws MojoExecutionException, MojoFailureException { try { JCodeModel codeModel = new JCodeModel(); for (Resource res: (List)project.getBuild().getResources()) { walk(new File(res.getDirectory()),codeModel.rootPackage(),""); } outputDirectory.mkdirs(); codeModel.build(outputDirectory); project.getCompileSourceRoots().add(outputDirectory.getAbsolutePath()); } catch (IOException e) { throw new MojoExecutionException("Failed to generate taglib type interface",e); } catch (JClassAlreadyExistsException e) { throw new MojoExecutionException("Duplicate class: "+e.getExistingClass().fullName(),e); } } private void walk(File dir,JPackage pkg,String dirName) throws JClassAlreadyExistsException, IOException { File[] children = dir.listFiles(new FileFilter() { public boolean accept(File f) { return f.isDirectory(); } }); if (children!=null) { for (File child : children) walk(child,pkg.subPackage(h2j(child.getName())),dirName+'/'+child.getName()); } File taglib = new File(dir,"taglib"); if (taglib.exists()) { JDefinedClass c = pkg.parent()._interface(StringUtils.capitalize(h2j(dir.getName())) + "TagLib"); c._implements(TypedTagLibrary.class); c.annotate(TagLibraryUri.class).param("value",dirName); File[] tags = dir.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".jelly"); } }); long timestamp = -1; for (File tag : tags) { timestamp = Math.max(tag.lastModified(),timestamp); try { Document dom = saxReader.read(tag); Element doc = dom.getRootElement().element(QName.get("st:documentation", "jelly:stapler")); String baseName = FilenameUtils.getBaseName(tag.getName()); String methodName; if (!JJavaName.isJavaIdentifier(tag.getName())) { methodName = baseName.replace('-', '_'); if (ReservedName.NAMES.contains(methodName)) methodName += '_'; } else { methodName = baseName; } for (int i=0; i<4; i++) { JMethod m = c.method(0, void.class, methodName); if (!methodName.equals(baseName)) m.annotate(TagFile.class).param("value",baseName); if (i%2==0) m.param(Map.class,"args"); if ((i/2)%2==0) m.param(Closure.class,"body"); JDocComment javadoc = m.javadoc(); if (doc!=null) javadoc.append(doc.getText().replace("&","&").replace("<","<")); } } catch (DocumentException e) { throw (IOException)new IOException("Failed to parse "+tag).initCause(e); } } // up to date check. if the file already exists and is newer, don't regenerate it File dst = new File(outputDirectory, c.fullName().replace('.', '/') + ".java"); if (dst.exists() && dst.lastModified()>timestamp) c.hide(); } } private static String h2j(String s) { if (s.equals("hudson")) return "jenkins"; return s; } } TestDependencyMojo.java000066400000000000000000000030651207142274300351100ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; import org.apache.commons.io.FileUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import java.io.*; import java.util.Set; /** * Places test-dependency plugins into somewhere the test harness can pick up. * *

* See {@code TestPluginManager.loadBundledPlugins()} where the test harness uses it. * * @goal resolve-test-dependencies * @requiresDependencyResolution test * @author Kohsuke Kawaguchi */ public class TestDependencyMojo extends AbstractHpiMojo { public void execute() throws MojoExecutionException, MojoFailureException { File testDir = new File(project.getBuild().getTestOutputDirectory(),"test-dependencies"); testDir.mkdirs(); try { Writer w = new OutputStreamWriter(new FileOutputStream(new File(testDir,"index")),"UTF-8"); for (MavenArtifact a : getProjectArtfacts()) { if(!a.isPlugin()) continue; getLog().debug("Copying "+a.getId()+" as a test dependency"); File dst = new File(testDir, a.getArtifactId() + ".hpi"); FileUtils.copyFile(a.getFile(),dst); w.write(a.getArtifactId()+"\n"); } w.close(); } catch (IOException e) { throw new MojoExecutionException("Failed to copy dependency plugins",e); } } } TestHplMojo.java000066400000000000000000000012221207142274300335460ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; import org.apache.maven.plugin.MojoExecutionException; import java.io.File; /** * Generate .hpl file in the test class directory so that test harness can locate the plugin. * * @goal test-hpl * @requiresDependencyResolution test * @author Kohsuke Kawaguchi */ public class TestHplMojo extends HplMojo { /** * Generates the hpl file in a known location. */ @Override protected File computeHplFile() throws MojoExecutionException { File testDir = new File(project.getBuild().getTestOutputDirectory()); testDir.mkdirs(); return new File(testDir,"the.hpl"); } } TestInsertionMojo.java000066400000000000000000000070301207142274300350000ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import java.io.File; import java.io.PrintWriter; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.FileNotFoundException; /** * Insert default test suite. * * @author Kohsuke Kawaguchi * @goal insert-test * @phase generate-test-sources * @requiresDependencyResolution test */ public class TestInsertionMojo extends AbstractJenkinsMojo { /** * If true, the automatic test injection will be skipped. * * @parameter */ private boolean disabledTestInjection; /** * If true, verify that all the jelly scripts have the Jelly XSS PI in them. * * @parameter expression="${jelly.requirePI}" */ private boolean requirePI; private static String quote(String s) { return '"'+s.replace("\\", "\\\\")+'"'; } public void execute() throws MojoExecutionException, MojoFailureException { if (disabledTestInjection) { getLog().info("Skipping auto-test generation"); return; } String target = findJenkinsVersion(); if (new VersionNumber(target).compareTo(new VersionNumber("1.327"))<0) { getLog().info("Skipping auto-test generation because we are targeting Jenkins "+target+" (at least 1.327 is required)."); return; } try { File f = new File(project.getBasedir(), "target/inject-tests"); f.mkdirs(); File javaFile = new File(f, "InjectedTest.java"); PrintWriter w = new PrintWriter(new OutputStreamWriter(new FileOutputStream(javaFile))); w.println("import java.util.*;"); w.println("/**"); w.println(" * Entry point to auto-generated tests (generated by maven-hpi-plugin)."); w.println(" * If this fails to compile, you are probably using Hudson < 1.327. If so, disable"); w.println(" * this code generation by configuring maven-hpi-plugin to <disabledTestInjection>true</disabledTestInjection>."); w.println(" */"); w.println("public class InjectedTest extends junit.framework.TestCase {"); w.println(" public static junit.framework.Test suite() throws Exception {"); w.println(" Map parameters = new HashMap();"); w.println(" parameters.put(\"basedir\","+quote(project.getBasedir().getAbsolutePath())+");"); w.println(" parameters.put(\"artifactId\","+quote(project.getArtifactId())+");"); w.println(" parameters.put(\"outputDirectory\","+quote(project.getBuild().getOutputDirectory())+");"); w.println(" parameters.put(\"testOutputDirectory\","+quote(project.getBuild().getTestOutputDirectory())+");"); w.println(" parameters.put(\"requirePI\","+quote(String.valueOf(requirePI))+");"); w.println(" return new org.jvnet.hudson.test.PluginAutomaticTestBuilder().build(parameters);"); w.println(" }"); w.println("}"); w.close(); project.addTestCompileSourceRoot(f.getAbsolutePath()); // always set the same time stamp on this file, so that Maven will not re-compile this // every time we run this mojo. javaFile.setLastModified(0); } catch (FileNotFoundException e) { e.printStackTrace(); } } } ValidateMojo.java000066400000000000000000000020641207142274300337210ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpipackage org.jenkinsci.maven.plugins.hpi; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; /** * Make sure that we are running in the right environment. * * @author Kohsuke Kawaguchi * @goal validate * @phase validate */ public class ValidateMojo extends AbstractJenkinsMojo { public void execute() throws MojoExecutionException, MojoFailureException { if (!isMustangOrAbove()) throw new MojoExecutionException("JDK6 or later is necessary to build a Jenkins plugin"); if (new VersionNumber(findJenkinsVersion()).compareTo(new VersionNumber("1.419.99"))<=0) throw new MojoExecutionException("This version of maven-hpi-plugin requires Jenkins 1.420 or later"); } /** * Are we running on JDK6 or above? */ private static boolean isMustangOrAbove() { try { Class.forName("javax.annotation.processing.Processor"); return true; } catch(ClassNotFoundException e) { return false; } } } VersionNumber.java000066400000000000000000000123251207142274300341420ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/java/org/jenkinsci/maven/plugins/hpi/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can obtain * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. * Sun designates this particular file as subject to the "Classpath" exception * as provided by Sun in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the License * Header, with the fields enclosed by brackets [] replaced by your own * identifying information: "Portions Copyrighted [year] * [name of copyright owner]" * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package org.jenkinsci.maven.plugins.hpi; import java.util.StringTokenizer; /** * Immutable representation of a dot or '-'-separated digits (such as "1.0.1" or "1.0-52"). * * {@link VersionNumber}s are {@link Comparable}. * *

Special tokens

*

* We allow a component to be not just a number, but also "ea", "ea1", "ea2". * "ea" is treated as "ea0", and eaN < M for any M > 0. * *

* '*' is also allowed as a component, and '*' > M for any M > 0. * *

* 'SNAPSHOT' is also allowed as a component, and "N.SNAPSHOT" is interpreted as "N-1.*" * *

 * 2.0.* > 2.0.1 > 2.0.1-SNAPSHOT > 2.0.0.99 > 2.0.0 > 2.0.ea > 2.0
 * 
* * @author * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) * @since 1.139 */ public class VersionNumber implements Comparable { private final int[] digits; /** * Parses a string like "1.0.2" into the version number. * * @throws IllegalArgumentException * if the parsing fails. */ public VersionNumber( String num ) { StringTokenizer tokens = new StringTokenizer(num,".-"); digits = new int[tokens.countTokens()]; if(digits.length<2) throw new IllegalArgumentException("Failed to parse "+num+" as version number"); int i=0; while( tokens.hasMoreTokens() ) { String token = tokens.nextToken().toLowerCase(); if(token.equals("*")) { digits[i++] = 1000; } else if(token.startsWith("snapshot")) { digits[i-1]--; digits[i++] = 1000; break; } else if(token.startsWith("ea")) { if(token.length()==2) digits[i++] = -1000; // just "ea" else digits[i++] = -1000 + Integer.parseInt(token.substring(2)); // "eaNNN" } else { int n =0; try { n = Integer.parseInt(token); } catch (NumberFormatException e) { // ignore } digits[i++] = n; } } } @Override public String toString() { StringBuffer buf = new StringBuffer(); for( int i=0; i0; } @Override public boolean equals( Object o ) { if (!(o instanceof VersionNumber)) return false; return compareTo((VersionNumber)o)==0; } @Override public int hashCode() { int x=0; for (int i : digits) x = (x << 1) | i; return x; } public int compareTo(VersionNumber rhs) { for( int i=0; ; i++ ) { if( i==this.digits.length && i==rhs.digits.length ) return 0; // equals if( i==this.digits.length ) return -1; // rhs is larger if( i==rhs.digits.length ) return 1; int r = this.digits[i] - rhs.digits[i]; if(r!=0) return r; } } } maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/000077500000000000000000000000001207142274300235335ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/META-INF/000077500000000000000000000000001207142274300246735ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/META-INF/archetype.xml000066400000000000000000000006121207142274300274000ustar00rootroot00000000000000 hudson-plugin src/main/java/HelloWorldBuilder.java pom.xml src/main/resources/index.jelly maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/META-INF/m2e/000077500000000000000000000000001207142274300253565ustar00rootroot00000000000000lifecycle-mapping-metadata.xml000066400000000000000000000010111207142274300331600ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/META-INF/m2e test-hpl insert-test resolve-test-dependencies validate false true maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/META-INF/maven/000077500000000000000000000000001207142274300260015ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/META-INF/maven/archetype-metadata.xml000066400000000000000000000021061207142274300322640ustar00rootroot00000000000000 src/main/java . pom.xml src/main/resources index.jelly src/main/resources index.jelly maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/META-INF/plexus/000077500000000000000000000000001207142274300262135ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/META-INF/plexus/components.xml000066400000000000000000000144331207142274300311270ustar00rootroot00000000000000 org.apache.maven.lifecycle.mapping.LifecycleMapping hpi org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping default org.jenkins-ci.tools:maven-hpi-plugin:validate org.apache.maven.plugins:maven-resources-plugin:resources org.apache.maven.plugins:maven-compiler-plugin:compile org.kohsuke:access-modifier-checker:enforce org.apache.maven.plugins:maven-resources-plugin:testResources org.jenkins-ci.tools:maven-hpi-plugin:insert-test org.apache.maven.plugins:maven-compiler-plugin:testCompile,org.jenkins-ci.tools:maven-hpi-plugin:test-hpl,org.jenkins-ci.tools:maven-hpi-plugin:resolve-test-dependencies org.apache.maven.plugins:maven-surefire-plugin:test org.jenkins-ci.tools:maven-hpi-plugin:hpi org.apache.maven.plugins:maven-install-plugin:install org.apache.maven.plugins:maven-deploy-plugin:deploy org.apache.maven.artifact.handler.ArtifactHandler hpi org.apache.maven.artifact.handler.DefaultArtifactHandler hpi hudson-plugin hpi java true org.apache.maven.lifecycle.mapping.LifecycleMapping jm org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping default org.apache.maven.plugins:maven-resources-plugin:resources org.apache.maven.plugins:maven-compiler-plugin:compile org.kohsuke:access-modifier-checker:enforce org.apache.maven.plugins:maven-resources-plugin:testResources org.jenkins-ci.tools:maven-hpi-plugin:insert-test org.apache.maven.plugins:maven-compiler-plugin:testCompile,org.jenkins-ci.tools:maven-hpi-plugin:test-hpl,org.jenkins-ci.tools:maven-hpi-plugin:resolve-test-dependencies org.apache.maven.plugins:maven-surefire-plugin:test org.jenkins-ci.tools:maven-hpi-plugin:hpi org.apache.maven.plugins:maven-install-plugin:install org.apache.maven.plugins:maven-deploy-plugin:deploy org.apache.maven.artifact.handler.ArtifactHandler jm org.apache.maven.artifact.handler.DefaultArtifactHandler jm jenkins-module jm java true org.apache.maven.lifecycle.mapping.LifecycleMapping jenkins-module org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping default org.apache.maven.plugins:maven-resources-plugin:resources org.apache.maven.plugins:maven-compiler-plugin:compile org.kohsuke:access-modifier-checker:enforce org.apache.maven.plugins:maven-resources-plugin:testResources org.jenkins-ci.tools:maven-hpi-plugin:insert-test org.apache.maven.plugins:maven-compiler-plugin:testCompile,org.jenkins-ci.tools:maven-hpi-plugin:test-hpl,org.jenkins-ci.tools:maven-hpi-plugin:resolve-test-dependencies org.apache.maven.plugins:maven-surefire-plugin:test org.jenkins-ci.tools:maven-hpi-plugin:hpi org.apache.maven.plugins:maven-install-plugin:install org.apache.maven.plugins:maven-deploy-plugin:deploy org.apache.maven.artifact.handler.ArtifactHandler jenkins-module org.apache.maven.artifact.handler.DefaultArtifactHandler jm jenkins-module jm java true maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/org/000077500000000000000000000000001207142274300243225ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/org/jenkinsci/000077500000000000000000000000001207142274300262775ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/org/jenkinsci/maven/000077500000000000000000000000001207142274300274055ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/org/jenkinsci/maven/plugins/000077500000000000000000000000001207142274300310665ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/org/jenkinsci/maven/plugins/hpi/000077500000000000000000000000001207142274300316465ustar00rootroot00000000000000plugin.properties000066400000000000000000000002351207142274300352030ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/main/resources/org/jenkinsci/maven/plugins/hpi# ... so that we can access the plugin version from the plugin itself groupId=${project.groupId} artifactId=${project.artifactId} version=${project.version} maven-hpi-plugin-maven-hpi-plugin-1.93/src/site/000077500000000000000000000000001207142274300215415ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/site/apt/000077500000000000000000000000001207142274300223255ustar00rootroot00000000000000maven-hpi-plugin-maven-hpi-plugin-1.93/src/site/apt/index.apt000066400000000000000000000011041207142274300241360ustar00rootroot00000000000000 ------ Maven Jenkins Plugin ------ ------ Maven Jenkins Plugin This maven2 plugin provides various goals for developing Jenkins plugins. * Goals Overview * {{{./create-mojo.html}hpi:create}} Creates a skeleton of a new plugin. * {{{./hpi-mojo.html}hpi:hpi}} Builds the .hpi file * {{{./hpl-mojo.html}hpi:hpl}} Generates the .hpl file * {{{./run-mojo.html}hpi:run}} Runs Jenkins with the current plugin project For more information about how to develop Jenkins plugins, refer to the {{{http://wiki.jenkins-ci.org/display/JENKINS/Extend+Jenkins}Wiki}}