001/*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019 */
020package org.sonar.api.utils.command;
021
022import com.google.common.base.Joiner;
023import com.google.common.base.Preconditions;
024import com.google.common.collect.ImmutableList;
025import com.google.common.collect.ImmutableMap;
026import com.google.common.collect.Lists;
027import com.google.common.collect.Maps;
028import org.apache.commons.lang.StringUtils;
029import org.apache.commons.lang.SystemUtils;
030
031import java.io.File;
032import java.util.Collections;
033import java.util.List;
034import java.util.Map;
035
036/**
037 * @since 2.7
038 */
039public class Command {
040  private final String executable;
041  private final List<String> arguments = Lists.newArrayList();
042  private final Map<String, String> env = Maps.newHashMap(System.getenv());
043  private File directory;
044  private boolean newShell = false;
045
046  private Command(String executable) {
047    Preconditions.checkArgument(!StringUtils.isBlank(executable), "Command executable can not be blank");
048    this.executable = executable;
049  }
050
051  public String getExecutable() {
052    return executable;
053  }
054
055  public List<String> getArguments() {
056    return ImmutableList.copyOf(arguments);
057  }
058
059  public Command addArgument(String arg) {
060    arguments.add(arg);
061    return this;
062  }
063
064  public Command addArguments(List<String> args) {
065    arguments.addAll(args);
066    return this;
067  }
068
069  public Command addArguments(String[] args) {
070    Collections.addAll(arguments, args);
071    return this;
072  }
073
074  public File getDirectory() {
075    return directory;
076  }
077
078  /**
079   * Sets working directory.
080   */
081  public Command setDirectory(File d) {
082    this.directory = d;
083    return this;
084  }
085
086  /**
087   * @see {@link org.sonar.api.utils.command.Command#getEnvironmentVariables()}
088   * @since 3.2
089   */
090  public Command setEnvironmentVariable(String name, String value) {
091    this.env.put(name, value);
092    return this;
093  }
094
095  /**
096   * Environment variables that are propagated during command execution.
097   * The initial value is a copy of the environment of the current process.
098   *
099   * @return a non-null and immutable map of variables
100   * @since 3.2
101   */
102  public Map<String, String> getEnvironmentVariables() {
103    return ImmutableMap.copyOf(env);
104  }
105
106  /**
107   * <code>true</code> if a new shell should be used to execute the command.
108   * The default behavior is to not use a new shell.
109   *
110   * @since 3.3
111   */
112  public boolean isNewShell() {
113    return newShell;
114  }
115
116  /**
117   * Set to <code>true</code> if a new shell should be used to execute the command.
118   * This is useful when the executed command is a script with no execution rights (+x on unix).
119   *
120   * On windows, the command will be executed with <code>cmd /C executable</code>.
121   * On other platforms, the command will be executed with <code>sh executable</code>.
122   *
123   * @since 3.3
124   */
125  public Command setNewShell(boolean b) {
126    this.newShell = b;
127    return this;
128  }
129
130  List<String> toStrings() {
131    ImmutableList.Builder<String> command = ImmutableList.builder();
132    if (newShell) {
133      if (SystemUtils.IS_OS_WINDOWS) {
134        command.add("cmd", "/C", "call");
135      } else {
136        command.add("sh");
137      }
138    }
139    command.add(executable);
140    command.addAll(arguments);
141    return command.build();
142  }
143
144  public String toCommandLine() {
145    return Joiner.on(" ").join(toStrings());
146  }
147
148  @Override
149  public String toString() {
150    return toCommandLine();
151  }
152
153  /**
154   * Create a command line without any arguments
155   *
156   * @param executable
157   */
158  public static Command create(String executable) {
159    return new Command(executable);
160  }
161}