1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.tradefed.config.proxy; 17 18 import com.android.tradefed.command.CommandOptions; 19 import com.android.tradefed.config.ConfigurationException; 20 import com.android.tradefed.config.Option; 21 import com.android.tradefed.util.FileUtil; 22 import com.android.tradefed.util.UniqueMultiMap; 23 24 import com.google.common.base.Joiner; 25 26 import java.io.File; 27 import java.io.IOException; 28 import java.util.ArrayList; 29 import java.util.Arrays; 30 import java.util.List; 31 import java.util.Set; 32 33 /** Objects that helps delegating the invocation to another Tradefed binary. */ 34 public class TradefedDelegator { 35 36 /** The object reference in the configuration. */ 37 public static final String DELEGATE_OBJECT = "DELEGATE"; 38 39 private static final String DELETEGATED_OPTION_NAME = "delegated-tf"; 40 41 @Option( 42 name = DELETEGATED_OPTION_NAME, 43 description = 44 "Points to the root dir of another Tradefed binary that will be used to drive" 45 + " the invocation") 46 private File mDelegatedTfRootDir; 47 48 @Option( 49 name = CommandOptions.INVOCATION_DATA, 50 description = "Mirror of CommandOptions#INVOCATION_DATA") 51 private UniqueMultiMap<String, String> mInvocationData = new UniqueMultiMap<>(); 52 53 // Not used directly but needed for proper parsing. 54 @SuppressWarnings("unused") 55 @Option( 56 name = "cts-params", 57 description = 58 "This option is special and can mess up the best effort parser, define " 59 + "it so it knows how to parse it.") 60 private List<String> mCtsParams = new ArrayList<>(); 61 62 private String[] mCommandLine = null; 63 64 /** Whether or not trigger the delegation logic. */ shouldUseDelegation()65 public boolean shouldUseDelegation() { 66 return mDelegatedTfRootDir != null; 67 } 68 69 /** Returns the directory of a Tradefed binary. */ getTfRootDir()70 public File getTfRootDir() { 71 return mDelegatedTfRootDir; 72 } 73 74 /** Creates the classpath out of the jars in the directory. */ createClasspath()75 public String createClasspath() throws IOException { 76 Set<File> jars = FileUtil.findFilesObject(mDelegatedTfRootDir, ".*\\.jar"); 77 return Joiner.on(":").join(jars); 78 } 79 setCommandLine(String[] command)80 public void setCommandLine(String[] command) { 81 mCommandLine = command; 82 } 83 getCommandLine()84 public String[] getCommandLine() { 85 return mCommandLine; 86 } 87 88 /** 89 * Returns whether or not this is the staging environment. We do not want to delegate in staging 90 * by default, only if the "staging_delegated" is set. 91 */ isStaging()92 public boolean isStaging() { 93 return mInvocationData.containsKey("staging") 94 && !mInvocationData.containsKey("staging_delegated"); 95 } 96 97 /** 98 * Remove from the original command line the delegate options so the underlying config does not 99 * delegate again. 100 */ clearCommandline(String[] originalCommand)101 public static String[] clearCommandline(String[] originalCommand) 102 throws ConfigurationException { 103 String[] commandLine = clearCommandlineFromOneArg(originalCommand, DELETEGATED_OPTION_NAME); 104 return commandLine; 105 } 106 107 /** Remove a given option from the command line. */ clearCommandlineFromOneArg(String[] originalCommand, String optionName)108 private static String[] clearCommandlineFromOneArg(String[] originalCommand, String optionName) 109 throws ConfigurationException { 110 List<String> argsList = new ArrayList<>(Arrays.asList(originalCommand)); 111 try { 112 while (argsList.contains("--" + optionName)) { 113 int index = argsList.indexOf("--" + optionName); 114 if (index != -1) { 115 argsList.remove(index + 1); 116 argsList.remove(index); 117 } 118 } 119 } catch (RuntimeException e) { 120 throw new ConfigurationException(e.getMessage(), e); 121 } 122 return argsList.toArray(new String[0]); 123 } 124 } 125