1 /*
2  * Copyright (C) 2019 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.cluster;
17 
18 import com.android.tradefed.config.Configuration;
19 import com.android.tradefed.config.ConfigurationUtil;
20 import com.android.tradefed.result.LegacySubprocessResultsReporter;
21 
22 import org.kxml2.io.KXmlSerializer;
23 
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.PrintWriter;
27 
28 /**
29  * Build a wrapper TF config XML for an existing TF config.
30  *
31  * <p>A wrapper XML allows to enable subprocess reporting on an existing TF config.
32  */
33 public class SubprocessConfigBuilder {
34     private static final String INCLUDE_NAME = "include";
35     private static final String REPORTER_CLASS = LegacySubprocessResultsReporter.class.getName();
36     private static final String OPTION_KEY = "subprocess-report-port";
37     private static final String CONFIG_DESCRIPTION = "Cluster Command Launcher config";
38 
39     private File mWorkdir;
40 
41     private String mOriginalConfig;
42 
43     private String mPort;
44 
setWorkingDir(File dir)45     public SubprocessConfigBuilder setWorkingDir(File dir) {
46         mWorkdir = dir;
47         return this;
48     }
49 
setOriginalConfig(String config)50     public SubprocessConfigBuilder setOriginalConfig(String config) {
51         mOriginalConfig = config;
52         return this;
53     }
54 
setPort(String port)55     public SubprocessConfigBuilder setPort(String port) {
56         mPort = port;
57         return this;
58     }
59 
60     /**
61      * Current handling of ATS for the naming of injected config. Exposed so it can be used to align
62      * the test harness side.
63      */
createConfigName(String originalConfigName)64     public static String createConfigName(String originalConfigName) {
65         return "_" + originalConfigName.replace("/", "$") + ".xml";
66     }
67 
build()68     public File build() throws IOException {
69         // Make a new config name based on the original config name to make it possible to find
70         // out the original command line from a modified one.
71         // FIXME: Find a better way to preserve the original command line.
72         String configName = createConfigName(mOriginalConfig);
73         // mOriginalConfig is from another test suite, so its content is hard to know at this
74         // time. So it doesn't load mOriginalConfig as IConfiguration and add additional config.
75         // Instead, it creates a wrapper config including mOriginalConfig.
76         File f = new File(mWorkdir, configName);
77         PrintWriter writer = new PrintWriter(f);
78         KXmlSerializer serializer = new KXmlSerializer();
79         serializer.setOutput(writer);
80         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
81         serializer.startDocument("UTF-8", null);
82         serializer.startTag(null, ConfigurationUtil.CONFIGURATION_NAME);
83         serializer.attribute(
84                 null, Configuration.CONFIGURATION_DESCRIPTION_TYPE_NAME, CONFIG_DESCRIPTION);
85 
86         serializer.startTag(null, INCLUDE_NAME);
87         serializer.attribute(null, ConfigurationUtil.NAME_NAME, mOriginalConfig);
88         serializer.endTag(null, INCLUDE_NAME);
89 
90         if (mPort != null) {
91             serializer.startTag(null, Configuration.RESULT_REPORTER_TYPE_NAME);
92             serializer.attribute(null, ConfigurationUtil.CLASS_NAME, REPORTER_CLASS);
93 
94             serializer.startTag(null, ConfigurationUtil.OPTION_NAME);
95             serializer.attribute(null, ConfigurationUtil.NAME_NAME, OPTION_KEY);
96             serializer.attribute(null, ConfigurationUtil.VALUE_NAME, mPort);
97             serializer.endTag(null, ConfigurationUtil.OPTION_NAME);
98 
99             serializer.endTag(null, Configuration.RESULT_REPORTER_TYPE_NAME);
100         }
101 
102         serializer.endTag(null, ConfigurationUtil.CONFIGURATION_NAME);
103         serializer.endDocument();
104 
105         writer.close();
106         return f;
107     }
108 }
109