diff --git a/core/pom.xml b/core/pom.xml index 612d7b754b..e95bb5b592 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -45,6 +45,17 @@ THE SOFTWARE. + + org.jenkins-ci.tools + maven-hpi-plugin + + + + generate-taglib-interface + + + + org.jvnet.hudson.tools maven-encoding-plugin @@ -387,8 +398,8 @@ THE SOFTWARE. org.kohsuke.stapler - stapler-jelly - 1.164 + stapler-groovy + 1.167 commons-jelly @@ -398,6 +409,11 @@ THE SOFTWARE. commons-jexl commons-jexl + + + org.codehaus.groovy + groovy + diff --git a/core/src/main/java/hudson/ExtensionComponent.java b/core/src/main/java/hudson/ExtensionComponent.java index ed2a3211ae..8c48632c2c 100644 --- a/core/src/main/java/hudson/ExtensionComponent.java +++ b/core/src/main/java/hudson/ExtensionComponent.java @@ -77,7 +77,7 @@ public class ExtensionComponent implements Comparable> // make the order bit more deterministic among extensions of the same ordinal if (this.instance instanceof Descriptor) { - return Util.fixNull(((Descriptor)this.instance).getDisplayName()).compareTo(Util.fixNull((((Descriptor)that.instance).getDisplayName()))); + return Util.fixNull(((Descriptor)this.instance).getDisplayName()).compareTo(Util.fixNull(((Descriptor)that.instance).getDisplayName())); } else { return this.instance.getClass().getName().compareTo(that.instance.getClass().getName()); } diff --git a/core/src/main/java/hudson/WebAppMain.java b/core/src/main/java/hudson/WebAppMain.java index 3dbb1bcb8b..c02bdb9f9a 100644 --- a/core/src/main/java/hudson/WebAppMain.java +++ b/core/src/main/java/hudson/WebAppMain.java @@ -222,20 +222,20 @@ public final class WebAppMain implements ServletContextListener { } }, 1000*10); } catch (Error e) { - LOGGER.log(Level.SEVERE, "Failed to initialize Hudson",e); + LOGGER.log(Level.SEVERE, "Failed to initialize Jenkins",e); context.setAttribute(APP,new HudsonFailedToLoad(e)); throw e; } catch (Exception e) { - LOGGER.log(Level.SEVERE, "Failed to initialize Hudson",e); + LOGGER.log(Level.SEVERE, "Failed to initialize Jenkins",e); context.setAttribute(APP,new HudsonFailedToLoad(e)); } } }.start(); } catch (Error e) { - LOGGER.log(Level.SEVERE, "Failed to initialize Hudson",e); + LOGGER.log(Level.SEVERE, "Failed to initialize Jenkins",e); throw e; } catch (RuntimeException e) { - LOGGER.log(Level.SEVERE, "Failed to initialize Hudson",e); + LOGGER.log(Level.SEVERE, "Failed to initialize Jenkins",e); throw e; } } diff --git a/core/src/main/java/hudson/model/Descriptor.java b/core/src/main/java/hudson/model/Descriptor.java index e9ef934e3e..617ad1ce93 100644 --- a/core/src/main/java/hudson/model/Descriptor.java +++ b/core/src/main/java/hudson/model/Descriptor.java @@ -37,6 +37,7 @@ import jenkins.model.Jenkins; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.kohsuke.stapler.*; +import org.kohsuke.stapler.jelly.JellyCompatibleFacet; import org.springframework.util.StringUtils; import org.jvnet.tiger_types.Types; import org.apache.commons.io.IOUtils; @@ -649,18 +650,24 @@ public abstract class Descriptor> implements Saveable { } public String getConfigPage() { - return getViewPage(clazz, "config.jelly"); + return getViewPage(clazz, getPossibleViewNames("config"), "config.jelly"); } public String getGlobalConfigPage() { - return getViewPage(clazz, "global.jelly",null); + return getViewPage(clazz, getPossibleViewNames("global"), null); + } + + private String getViewPage(Class clazz, String pageName, String defaultValue) { + return getViewPage(clazz,Collections.singleton(pageName),defaultValue); } - private String getViewPage(Class clazz, String pageName, String defaultValue) { + private String getViewPage(Class clazz, Collection pageNames, String defaultValue) { while(clazz!=Object.class) { - String name = clazz.getName().replace('.', '/').replace('$', '/') + "/" + pageName; - if(clazz.getClassLoader().getResource(name)!=null) - return '/'+name; + for (String pageName : pageNames) { + String name = clazz.getName().replace('.', '/').replace('$', '/') + "/" + pageName; + if(clazz.getClassLoader().getResource(name)!=null) + return '/'+name; + } clazz = clazz.getSuperclass(); } return defaultValue; @@ -675,6 +682,17 @@ public abstract class Descriptor> implements Saveable { return getViewPage(clazz,pageName,pageName); } + private List getPossibleViewNames(String baseName) { + List names = new ArrayList(); + for (Facet f : WebApp.get(Hudson.getInstance().servletContext).facets) { + if (f instanceof JellyCompatibleFacet) { + JellyCompatibleFacet jcf = (JellyCompatibleFacet) f; + names.add(baseName +jcf.getDefaultScriptExtension()); + } + } + return names; + } + /** * Saves the configuration info to the disk. diff --git a/core/src/main/java/hudson/model/Hudson.java b/core/src/main/java/hudson/model/Hudson.java index ee3380999d..24f78760a0 100644 --- a/core/src/main/java/hudson/model/Hudson.java +++ b/core/src/main/java/hudson/model/Hudson.java @@ -63,9 +63,9 @@ public class Hudson extends Jenkins { /** * List of registered {@link hudson.slaves.ComputerListener}s. - * @deprecated as of 1.286 - */ - private transient final CopyOnWriteList computerListeners = ExtensionListView.createCopyOnWriteList(ComputerListener.class); + * @deprecated as of 1.286 + */ + private transient final CopyOnWriteList computerListeners = ExtensionListView.createCopyOnWriteList(ComputerListener.class); @CLIResolver @@ -79,7 +79,7 @@ public class Hudson extends Jenkins { public Hudson(File root, ServletContext context, PluginManager pluginManager) throws IOException, InterruptedException, ReactorException { super(root, context, pluginManager); - } + } /** * Gets all the installed {@link ItemListener}s. @@ -127,7 +127,7 @@ public class Hudson extends Jenkins { * Use {@link #getNodes()}. Since 1.252. */ public List getSlaves() { - return (List) Collections.unmodifiableList(slaves); + return (List)Collections.unmodifiableList(slaves); } /** @@ -140,7 +140,7 @@ public class Hudson extends Jenkins { setNodes(slaves); } - /** + /** * @deprecated * Left only for the compatibility of URLs. * Should not be invoked for any other purpose. @@ -157,9 +157,9 @@ public class Hudson extends Jenkins { String match = Functions.toEmailSafeString(name); for(TopLevelItem item : getItems()) { if(Functions.toEmailSafeString(item.getName()).equalsIgnoreCase(match)) { - return item; - } - } + return item; + } + } return null; } diff --git a/core/src/main/java/hudson/model/Items.java b/core/src/main/java/hudson/model/Items.java index 6e12b1667b..e49d855a36 100644 --- a/core/src/main/java/hudson/model/Items.java +++ b/core/src/main/java/hudson/model/Items.java @@ -138,6 +138,11 @@ public class Items { */ public static final XStream XSTREAM = new XStream2(); + /** + * Alias to {@link #XSTREAM} so that one can access additional methods on {@link XStream2} more easily. + */ + public static final XStream2 XSTREAM2 = (XStream2)XSTREAM; + static { XSTREAM.alias("project",FreeStyleProject.class); XSTREAM.alias("matrix-project",MatrixProject.class); diff --git a/core/src/main/java/hudson/model/Run.java b/core/src/main/java/hudson/model/Run.java index 27e7838fbd..bf3ed52fff 100644 --- a/core/src/main/java/hudson/model/Run.java +++ b/core/src/main/java/hudson/model/Run.java @@ -1871,6 +1871,12 @@ public abstract class Run ,RunT extends Run * This is the instance the servlet container creates, but @@ -59,7 +59,7 @@ public class HudsonFilter implements Filter { private volatile Filter filter; /** - * The {@link #init(FilterConfig)} may be called before the Hudson instance is up (which is + * The {@link #init(FilterConfig)} may be called before the Jenkins instance is up (which is * required for initialization of the filter). So we store the * filterConfig for later lazy-initialization of the filter. */ @@ -115,7 +115,7 @@ public class HudsonFilter implements Filter { // the whole thing fail hard before a nicer error check // in WebAppMain.contextInitialized. So for now, // just report it here, and let the WebAppMain handle the failure gracefully. - LOGGER.log(SEVERE, "Failed to initialize Hudson",e); + LOGGER.log(SEVERE, "Failed to initialize Jenkins",e); } } diff --git a/core/src/main/java/hudson/taglibs/IntelliJ.gdsl b/core/src/main/java/hudson/taglibs/IntelliJ.gdsl new file mode 100644 index 0000000000..f16398adab --- /dev/null +++ b/core/src/main/java/hudson/taglibs/IntelliJ.gdsl @@ -0,0 +1,69 @@ +import com.intellij.openapi.module.*; +import com.intellij.openapi.roots.*; + +def ctx = context(scope:scriptScope()) // TODO: make this more restrictive + +// TODO: how to complete "it", "descriptor", "instance", and other interesting variables? +// TODO: do view pages need packages? +contributor(ctx) { + + property name:"app", type:"hudson.model.Hudson" + + def ct = classType + if (ct.getClass().name.endsWith(".GroovyScriptClass")) { + // if we are completing Groovy script + + def roots = new HashSet/**/() + ModuleManager.getInstance(ct.project).modules.each { m -> + roots.addAll(ModuleRootManager.getInstance(m).sourceRoots) + } + + // figure out the path that this file is in + def contentPaths = [] + for (def f=ct.containingFile.virtualFile; f!=null && !roots.contains(f); f=f.parent) { + contentPaths << f.name + } + def fqcn = contentPaths.reverse()[0..-2].join('.') + + property name:"my", type:fqcn // but this is still shadowed by JellyBuilder.getMy + property name:"instance", type:fqcn + property name:"descriptor", type:fqcn+".DescriptorImpl" + } + + // normally, built-in delegateTo function would do, except in this case + // we'd like to avoid binding getMy. + for ( String t : ["org.kohsuke.stapler.jelly.groovy.JellyBuilder","org.kohsuke.stapler.jelly.groovy.StaplerClosureScript"]) { + def c = findClass(t); + c.allMethods.findAll { !it.isConstructor() && it.name!="getMy" }.each { add it; } + c.allFields.each { add it; } + } +} + +// Record of past experiments +/* +try to infer "it" from the class name of Groovy page + +PsiElement.getProject() +ModuleManager.getInstance(project).getModules() +Module -> ModuleRootModel -> .getSourceRoots() + +classType=Script Class:manag_ : class org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass +place=Reference expression : class org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceExpressionImpl +psiType=PsiType:manag_ : class com.intellij.psi.impl.source.PsiImmediateClassType + +System.out.println("classType=${classType} : ${classType.getClass()}") +System.out.println("qualifiedName="+ct.qualifiedName) +System.out.println("containingFile="+ct.containingFile) +System.out.println("containingFile.name="+ct.containingFile.name) +System.out.println("scope=${ct.scope}:${ct.scope.getClass()}") +System.out.println("scope.package=${ct.scope.getPackageName()}") + +if (0) { + // file system reference goes all the way to '/' in the POSIX file system + def f = ct.containingFile + while (f!=null) { + System.out.println(" name="+f.name) + f=f.parent + } +} +*/ diff --git a/core/src/main/java/hudson/taglibs/LayoutTagLib.java b/core/src/main/java/hudson/taglibs/LayoutTagLib.java new file mode 100644 index 0000000000..4056b9f57d --- /dev/null +++ b/core/src/main/java/hudson/taglibs/LayoutTagLib.java @@ -0,0 +1,22 @@ +package hudson.taglibs; + +import groovy.lang.Closure; +import org.kohsuke.stapler.jelly.groovy.TagLibraryUri; +import org.kohsuke.stapler.jelly.groovy.TypedTagLibrary; + +import java.util.Map; + +/** + * Experimenting. This is to be auto-generated. + * + * @author Kohsuke Kawaguchi + */ +@TagLibraryUri("/lib/layout") +public interface LayoutTagLib extends TypedTagLibrary { + void layout(Map args, Closure body); + void layout(Map args); + void layout(Closure body); + void layout(); + + void main_panel(Closure c); +} diff --git a/core/src/main/java/hudson/taglibs/eclipse.dsld b/core/src/main/java/hudson/taglibs/eclipse.dsld new file mode 100644 index 0000000000..63dfb2b6e8 --- /dev/null +++ b/core/src/main/java/hudson/taglibs/eclipse.dsld @@ -0,0 +1,10 @@ +// fileExtension(...) and fileName(...) +(isScript() /*& sourceFolderOfCurrentFile("src/main/resources")*/).accept { + provider "Jenkins Groovy View"; + + property name:"app", type:"hudson.model.Hudson"; + + for ( String t : ["org.kohsuke.stapler.jelly.groovy.JellyBuilder","org.kohsuke.stapler.jelly.groovy.StaplerClosureScript"]) { + delegatesTo t; + } +} \ No newline at end of file diff --git a/core/src/main/java/hudson/util/XStream2.java b/core/src/main/java/hudson/util/XStream2.java index 7298c06c0d..931bce40ff 100644 --- a/core/src/main/java/hudson/util/XStream2.java +++ b/core/src/main/java/hudson/util/XStream2.java @@ -49,6 +49,8 @@ import hudson.util.xstream.ImmutableMapConverter; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** @@ -59,6 +61,8 @@ public class XStream2 extends XStream { private Converter reflectionConverter; private ThreadLocal oldData = new ThreadLocal(); + private final Map compatibilityAliases = new ConcurrentHashMap(); + public XStream2() { init(); } @@ -124,6 +128,23 @@ public class XStream2 extends XStream { return a; } + /** + * Adds an alias in case class names change. + * + * Unlike {@link #alias(String, Class)}, which uses the registered alias name for writing XML, + * this method registers an alias to be used only for the sake of reading from XML. This makes + * this method usable for the situation when class names change. + * + * @param oldClassName + * Fully qualified name of the old class name. + * @param newClass + * New class that's field-compatible with the given old class name. + * @since 1.416 + */ + public void addCompatibilityAlias(String oldClassName, Class newClass) { + compatibilityAliases.put(oldClassName,newClass); + } + /** * Prior to Hudson 1.106, XStream 1.1.x was used which encoded "$" in class names * as "-" instead of "_-" that is used now. Up through Hudson 1.348 compatibility @@ -138,6 +159,9 @@ public class XStream2 extends XStream { @Override public Class realClass(String elementName) { + Class s = compatibilityAliases.get(elementName); + if (s!=null) return s; + try { return super.realClass(elementName); } catch (CannotResolveClassException e) { diff --git a/core/src/main/java/jenkins/model/Jenkins.java b/core/src/main/java/jenkins/model/Jenkins.java index 8c02d13b84..5e753b44ce 100644 --- a/core/src/main/java/jenkins/model/Jenkins.java +++ b/core/src/main/java/jenkins/model/Jenkins.java @@ -3410,6 +3410,11 @@ public class Jenkins extends AbstractCIBase implements ItemGroup, */ public static final XStream XSTREAM = new XStream2(); + /** + * Alias to {@link #XSTREAM} so that one can access additional methods on {@link XStream2} more easily. + */ + public static final XStream2 XSTREAM2 = (XStream2)XSTREAM; + private static final int TWICE_CPU_NUM = Runtime.getRuntime().availableProcessors() * 2; /** diff --git a/core/src/main/resources/hudson/PluginManager/sidepanel.groovy b/core/src/main/resources/hudson/PluginManager/sidepanel.groovy new file mode 100644 index 0000000000..593bfae961 --- /dev/null +++ b/core/src/main/resources/hudson/PluginManager/sidepanel.groovy @@ -0,0 +1,37 @@ +/* + * 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. + */ +import hudson.taglibs.LayoutTagLib + +l=namespace(LayoutTagLib) + +l.header() +l.side_panel { + l.tasks { + l.task(icon:"images/24x24/up.png", href:rootURL+'/', title:_("Back to Dashboard")) + l.task(icon:"images/24x24/setting.png", href:"${rootURL}/manage", title:_("Manage Jenkins"), permission:app.ADMINISTER, it:app) + if (!app.updateCenter.jobs.isEmpty()) { + l.task(icon:"images/24x24/plugin.png", href:"${rootURL}/updateCenter/", title:_("Update Center")) + } + } +} diff --git a/core/src/main/resources/hudson/PluginManager/sidepanel.jelly b/core/src/main/resources/hudson/PluginManager/sidepanel.jelly deleted file mode 100644 index 1e51f415ab..0000000000 --- a/core/src/main/resources/hudson/PluginManager/sidepanel.jelly +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/core/src/main/resources/hudson/model/Hudson/manag_.groovy b/core/src/main/resources/hudson/model/Hudson/manag_.groovy new file mode 100644 index 0000000000..77ed9fd48f --- /dev/null +++ b/core/src/main/resources/hudson/model/Hudson/manag_.groovy @@ -0,0 +1,65 @@ +import hudson.taglibs.LayoutTagLib + +l=namespace(LayoutTagLib) +t=namespace("/lib/hudson") +st=namespace("jelly:stapler") + +def feature(String icon, String href, String title, Closure body=null) { + t.summary(icon:icon, href:href, iconOnly:true) { + div(class:"link") { + a(href:href, title) + } + div(style:"color:gray; text-decoration:none;",body) + } +} + +l.layout(title:_("Manage Jenkins"),permission:app.ADMINISTER) { + + st.include(page:"sidepanel") + l.main_panel { + h1(_("Manage Jenkins")) + + if (my.isCheckURIEncodingEnabled()) { + script """ + var url='checkURIEncoding'; + var params='value=\u57f7\u4e8b'; + var checkAjax=new Ajax.Updater( + 'message', url, + { + method: 'get', parameters: params + } + ); + """ + span(id:"message") + } + + app.administrativeMonitors.each { am -> + if (am.isActivated() && am.isEnabled()) + st.include(it:am, page:"message") + } + + st.include(page:"downgrade") + + table(style:"padding-left: 2em;",id:"management-links") { + feature("setting.gif", "configure", _("Configure System")) { + raw(_("Configure global settings and paths.")) + } + // TODO: more features + + app.managementLinks.each { m -> + if (m.iconFileName==null) return; + feature(m.iconFileName, m.urlName, m.displayName) { + raw(m.description) + } + } + + if (app.quietingDown) { + feature("system-log-out.gif","cancelQuietDown",_("Cancel Shutdown")) + } else { + feature("system-log-out.gif","quietDown",_("Prepare for Shutdown")) { + raw(_("Stops executing new builds, so that the system can be eventually shut down safely.")) + } + } + } + } +} \ No newline at end of file diff --git a/core/src/main/resources/hudson/tasks/Ant/config.groovy b/core/src/main/resources/hudson/tasks/Ant/config.groovy new file mode 100644 index 0000000000..dc4d6bcf72 --- /dev/null +++ b/core/src/main/resources/hudson/tasks/Ant/config.groovy @@ -0,0 +1,51 @@ +/* + * 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. + */ +f=namespace(lib.FormTagLib) + +if (!descriptor.installations) { + f.entry(title:_("Ant Version")) { + select(class:"setting-input",name:"ant.antName") { + option(value:"(Default)", _("Default")) + descriptor.installations.each { + f.option(selected:it.name==instance?.ant?.name, value:it.name, it.name) + } + } + } +} + +f.entry(title:_("Targets"),help:"/help/ant/ant-targets.html") { + f.expandableTextbox(name:"ant.targets",value:instance?.targets) +} + +f.advanced { + f.entry(title:_("Build File"),help:"/help/ant/ant-buildfile.html") { + f.expandableTextbox(name:"ant.buildFile",value:instance?.buildFile) + } + f.entry(title:_("Properties"),help:"/help/ant/ant-properties.html") { + f.expandableTextbox(name:"ant.properties",value:instance?.properties) + } + f.entry(title:_("Java Options"),help:"/help/ant/ant-opts.html") { + f.expandableTextbox(name:"ant.antOpts",value:instance?.antOpts) + } +} diff --git a/core/src/main/resources/hudson/tasks/Ant/config.jelly b/core/src/main/resources/hudson/tasks/Ant/config.jelly deleted file mode 100644 index 2a011af5f5..0000000000 --- a/core/src/main/resources/hudson/tasks/Ant/config.jelly +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/core/src/main/resources/hudson/tasks/Shell/config.groovy b/core/src/main/resources/hudson/tasks/Shell/config.groovy new file mode 100644 index 0000000000..56cd525907 --- /dev/null +++ b/core/src/main/resources/hudson/tasks/Shell/config.groovy @@ -0,0 +1,28 @@ +/* + * 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. + */ +f=namespace("/lib/form") + +f.entry(title:_("Command"),description:_("description",rootURL)) { + f.textarea(name:"command",value:instance?.command,class:"fixed-width") +} diff --git a/core/src/main/resources/hudson/tasks/Shell/config.jelly b/core/src/main/resources/hudson/tasks/Shell/config.jelly deleted file mode 100644 index bea70c99d6..0000000000 --- a/core/src/main/resources/hudson/tasks/Shell/config.jelly +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - diff --git a/core/src/main/resources/hudson/tasks/Shell/global.groovy b/core/src/main/resources/hudson/tasks/Shell/global.groovy new file mode 100644 index 0000000000..d11ec0536a --- /dev/null +++ b/core/src/main/resources/hudson/tasks/Shell/global.groovy @@ -0,0 +1,30 @@ +/* + * 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. + */ +f=namespace("/lib/form") + +f.section(title:_("Shell")) { + f.entry(title:_("Shell executable"),help:"/help/shell/shellexe.html") { + f.textbox(name:"shell",value:descriptor.shell,checkUrl:"'${rootURL}/builder/Shell/check?value='+encodeURIComponent(this.value)") + } +} diff --git a/core/src/main/resources/hudson/tasks/Shell/global.jelly b/core/src/main/resources/hudson/tasks/Shell/global.jelly deleted file mode 100644 index cd5a3e2304..0000000000 --- a/core/src/main/resources/hudson/tasks/Shell/global.jelly +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - diff --git a/core/src/main/resources/lib/foo.jelly b/core/src/main/resources/lib/foo.jelly deleted file mode 100644 index cffa14e994..0000000000 --- a/core/src/main/resources/lib/foo.jelly +++ /dev/null @@ -1,26 +0,0 @@ - - - -JELLY TAG FILE ${value} \ No newline at end of file diff --git a/core/src/main/resources/lib/form/hetero-list.jelly b/core/src/main/resources/lib/form/hetero-list.jelly index e8e92ee9f2..9c50b3489e 100644 --- a/core/src/main/resources/lib/form/hetero-list.jelly +++ b/core/src/main/resources/lib/form/hetero-list.jelly @@ -110,7 +110,7 @@ THE SOFTWARE.
- + diff --git a/core/src/main/resources/lib/taglib b/core/src/main/resources/lib/taglib deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/core/src/test/java/hudson/util/XStream2Test.java b/core/src/test/java/hudson/util/XStream2Test.java index 1626aaefe1..9a4cef91fc 100644 --- a/core/src/test/java/hudson/util/XStream2Test.java +++ b/core/src/test/java/hudson/util/XStream2Test.java @@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableMap; import junit.framework.TestCase; import hudson.model.Result; import hudson.model.Run; +import org.jvnet.hudson.test.Bug; import java.util.Map; @@ -165,9 +166,25 @@ public class XStream2Test extends TestCase { assertEquals(m,a.m); } - // @Bug(8006) -- Previously a null entry in an array caused NPE + @Bug(8006) // Previously a null entry in an array caused NPE public void testEmptyStack() { assertEquals("", Run.XSTREAM.toXML(new Object[2]).replaceAll("[ \n\r\t]+", "")); } + + @Bug(9843) + public void testCompatibilityAlias() { + XStream2 xs = new XStream2(); + xs.addCompatibilityAlias("legacy.Point",Point.class); + Point pt = (Point)xs.fromXML("12"); + assertEquals(1,pt.x); + assertEquals(2,pt.y); + String xml = xs.toXML(pt); + System.out.println(xml); + assertFalse("Shouldn't use the alias when writing back",xml.contains("legacy")); + } + + public static class Point { + public int x,y; + } } diff --git a/maven-plugin/src/main/java/hudson/maven/MavenRedeployer.java b/maven-plugin/src/main/java/hudson/maven/MavenRedeployer.java deleted file mode 100644 index f1206cff48..0000000000 --- a/maven-plugin/src/main/java/hudson/maven/MavenRedeployer.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * - * 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.maven; - -import hudson.model.AbstractBuild; -import hudson.model.BuildListener; -import hudson.model.Result; -import hudson.tasks.BuildStepDescriptor; -import hudson.tasks.Notifier; -import hudson.tasks.BuildStepMonitor; -import hudson.Launcher; -import hudson.maven.reporters.MavenArtifactRecord; -import hudson.tasks.Publisher; - -import java.io.IOException; - -/** - * {@link Publisher} for Maven projects to deploy artifacts to a Maven repository - * after the fact. - * - *

- * When a build breaks in the middle, this is a convenient way to prevent - * modules from being deployed partially. This can be combined with promoted builds - * plugin to deploy artifacts after testing, for example. - * - * @author Kohsuke Kawaguchi - */ -public class MavenRedeployer extends Notifier { - public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { - MavenArtifactRecord mar = build.getAction(MavenArtifactRecord.class); - if(mar==null) { - if(build.getResult().isBetterThan(Result.FAILURE)) { - listener.getLogger().println("There's no record of artifact information. Is this really a Maven build?"); - build.setResult(Result.FAILURE); - } - // failed - return true; - } - - listener.getLogger().println("TODO"); - - return true; - } - - public BuildStepMonitor getRequiredMonitorService() { - return BuildStepMonitor.NONE; - } - - public BuildStepDescriptor getDescriptor() { - return DESCRIPTOR; - } - - public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); - - public static final class DescriptorImpl extends BuildStepDescriptor { - public boolean isApplicable(Class jobType) { - return AbstractMavenProject.class.isAssignableFrom(jobType); - } - - public String getDisplayName() { - return Messages.MavenRedeployer_DisplayName(); - } - } -} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 7d5cfaa06d..403f79b528 100644 --- a/pom.xml +++ b/pom.xml @@ -141,6 +141,11 @@ THE SOFTWARE. maven-resources-plugin 2.5 + + org.jenkins-ci.tools + maven-hpi-plugin + 1.70 + -P release,sign + + clean install -DskipTests javadoc:javadoc animal-sniffer:check deploy javadoc:aggregate false true diff --git a/test/src/test/java/hudson/maven/Maven3BuildTest.java b/test/src/test/java/hudson/maven/Maven3BuildTest.java index 7a31e5232c..fd0c577246 100755 --- a/test/src/test/java/hudson/maven/Maven3BuildTest.java +++ b/test/src/test/java/hudson/maven/Maven3BuildTest.java @@ -210,6 +210,32 @@ public class Maven3BuildTest extends HudsonTestCase { System.out.println("modules size " + m.getModules()); + MavenModule testModule = null; + for (MavenModule mavenModule : m.getModules()) { + System.out.println("module " + mavenModule.getName() + "/" + mavenModule.getDisplayName()); + if ("org.foobar:org.foobar.test".equals( mavenModule.getName() )) testModule = mavenModule; + } + + AbstractTestResultAction trpa = testModule.getLastBuild().getTestResultAction(); + + int totalCount = trpa.getTotalCount(); + assertEquals(1, totalCount); + } + + @Bug(9326) + public void testTychoEclipseTestResults() throws Exception { + MavenInstallation mavenInstallation = configureMaven3(); + MavenModuleSet m = createMavenProject(); + m.setRootPOM( "org.foobar.build/pom.xml" ); + m.setMaven( mavenInstallation.getName() ); + m.getReporters().add(new TestReporter()); + m.setScm(new ExtractResourceSCM(getClass().getResource("foobar_eclipse_with_fix.zip"),"foobar_eclipse")); + m.setGoals("verify"); + buildAndAssertSuccess(m); + + System.out.println("modules size " + m.getModules()); + + MavenModule testModule = null; for (MavenModule mavenModule : m.getModules()) { System.out.println("module " + mavenModule.getName() + "/" + mavenModule.getDisplayName()); diff --git a/test/src/test/resources/hudson/maven/foobar_eclipse_with_fix.zip b/test/src/test/resources/hudson/maven/foobar_eclipse_with_fix.zip new file mode 100644 index 0000000000..5d7f2f2cd5 Binary files /dev/null and b/test/src/test/resources/hudson/maven/foobar_eclipse_with_fix.zip differ