PageRenderTime 27ms CodeModel.GetById 19ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/hudson-core/src/main/java/hudson/tasks/Shell.java

http://github.com/hudson/hudson
Java | 161 lines | 96 code | 20 blank | 45 comment | 9 complexity | cdf558ca094617263e93a99f40f97b35 MD5 | raw file
  1/*
  2 * The MIT License
  3 * 
  4 * Copyright (c) 2004-2011, 2011, Oracle Corporation, Kohsuke Kawaguchi, Jene Jasper, Yahoo! Inc., Nikita Levyankov
  5 * 
  6 * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 * of this software and associated documentation files (the "Software"), to deal
  8 * in the Software without restriction, including without limitation the rights
  9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10 * copies of the Software, and to permit persons to whom the Software is
 11 * furnished to do so, subject to the following conditions:
 12 * 
 13 * The above copyright notice and this permission notice shall be included in
 14 * all copies or substantial portions of the Software.
 15 * 
 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22 * THE SOFTWARE.
 23 */
 24package hudson.tasks;
 25
 26import hudson.FilePath;
 27import hudson.Functions;
 28import hudson.Util;
 29import hudson.Extension;
 30import hudson.model.AbstractProject;
 31import hudson.util.FormValidation;
 32import net.sf.json.JSONObject;
 33import org.kohsuke.stapler.DataBoundConstructor;
 34import org.kohsuke.stapler.StaplerRequest;
 35import org.kohsuke.stapler.QueryParameter;
 36
 37import java.util.List;
 38import java.util.ArrayList;
 39import java.util.Arrays;
 40
 41/**
 42 * Executes a series of commands by using a shell.
 43 *
 44 * @author Kohsuke Kawaguchi
 45 */
 46public class Shell extends CommandInterpreter {
 47    @DataBoundConstructor
 48    public Shell(String command) {
 49        super(fixCrLf(command));
 50    }
 51
 52    /**
 53     * Fix CR/LF and always make it Unix style.
 54     */
 55    private static String fixCrLf(String s) {
 56        // eliminate CR
 57        int idx;
 58        if (null != s) { //avoid potential NullPointerException if command is null.
 59            while ((idx = s.indexOf("\r\n")) != -1) {
 60                s = s.substring(0, idx) + s.substring(idx + 1);
 61            }
 62        }
 63        return s;
 64    }
 65
 66    /**
 67     * Older versions of bash have a bug where non-ASCII on the first line
 68     * makes the shell think the file is a binary file and not a script. Adding
 69     * a leading line feed works around this problem.
 70     */
 71    private static String addCrForNonASCII(String s) {
 72        if(!s.startsWith("#!")) {
 73            if (s.indexOf('\n')!=0) {
 74                return "\n" + s;
 75            }
 76        }
 77
 78        return s;
 79    }
 80
 81    public String[] buildCommandLine(FilePath script) {
 82        if(command.startsWith("#!")) {
 83            // interpreter override
 84            int end = command.indexOf('\n');
 85            if(end<0)   end=command.length();
 86            List<String> args = new ArrayList<String>();
 87            args.addAll(Arrays.asList(Util.tokenize(command.substring(0,end).trim())));
 88            args.add(script.getRemote());
 89            args.set(0,args.get(0).substring(2));   // trim off "#!"
 90            return args.toArray(new String[args.size()]);
 91        } else
 92            return new String[] { getDescriptor().getShellOrDefault(),"-xe",script.getRemote()};
 93    }
 94
 95    protected String getContents() {
 96        return addCrForNonASCII(fixCrLf(command));
 97    }
 98
 99    protected String getFileExtension() {
100        return ".sh";
101    }
102
103    @Override
104    public DescriptorImpl getDescriptor() {
105        return (DescriptorImpl)super.getDescriptor();
106    }
107
108    @Extension
109    public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
110        /**
111         * Shell executable, or null to default.
112         */
113        private String shell;
114
115        public DescriptorImpl() {
116            load();
117        }
118
119        public boolean isApplicable(Class<? extends AbstractProject> jobType) {
120            return true;
121        }
122
123        public String getShell() {
124            return shell;
125        }
126
127        public String getShellOrDefault() {
128            if(shell==null)
129                return Functions.isWindows() ?"sh":"/bin/sh";
130            return shell;
131        }
132
133        public void setShell(String shell) {
134            this.shell = Util.fixEmptyAndTrim(shell);
135            save();
136        }
137
138        public String getDisplayName() {
139            return Messages.Shell_DisplayName();
140        }
141
142        @Override
143        public Builder newInstance(StaplerRequest req, JSONObject data) {
144            return new Shell(data.getString("command"));
145        }
146
147        @Override
148        public boolean configure(StaplerRequest req, JSONObject data) {
149            setShell(req.getParameter("shell"));
150            return true;
151        }
152
153        /**
154         * Check the existence of sh in the given location.
155         */
156        public FormValidation doCheck(@QueryParameter String value) {
157            // Executable requires admin permission
158            return FormValidation.validateExecutable(value); 
159        }
160    }
161}