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