blob: e5d4012940bfe5b5433bf5f6340caf6a68719b03 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tradefed.invoker;
import com.android.tradefed.util.FileUtil;
import com.google.common.collect.ImmutableMap;
import java.io.File;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListSet;
/**
* Files dependencies generated during the execution of a test or invocation that need to be carried
* for testing.
*/
public class ExecutionFiles {
/** Enumeration of known standard key for the map. */
public static enum FilesKey {
ADB_BINARY,
// Describes the directory containing the build target tests artifacts.
TESTS_DIRECTORY,
// Sub-directory of TESTS_DIRECTORY that contains target artifacts
TARGET_TESTS_DIRECTORY,
// Sub-directory of TESTS_DIRECTORY that contains host-side artifacts
HOST_TESTS_DIRECTORY
}
private final ConcurrentMap<String, File> mFiles = new ConcurrentHashMap<>();
private final ConcurrentSkipListSet<String> mShouldNotDelete = new ConcurrentSkipListSet<>();
// Package private to avoid new instantiation.
ExecutionFiles() {}
/**
* Associates the specified value with the specified key in this map.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with {@code key}, or {@code null} if there was no
* mapping for {@code key}.
* @see ConcurrentMap
*/
public File put(String key, File value) {
return mFiles.put(key, value);
}
/**
* Variation of {@link #put(String, File)} with a known key.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with {@code key}, or {@code null} if there was no
* mapping for {@code key}.
*/
public File put(FilesKey key, File value) {
return mFiles.put(key.toString(), value);
}
/**
* Variation of {@link #put(FilesKey, File)} with option to prevent the file from being deleted
* at the end of the invocation.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @param shouldNotDelete prevent the file from being deleted at the end of invocation.
* @return the previous value associated with {@code key}, or {@code null} if there was no
* mapping for {@code key}.
*/
public File put(FilesKey key, File value, boolean shouldNotDelete) {
File f = mFiles.put(key.toString(), value);
if (shouldNotDelete) {
mShouldNotDelete.add(key.toString());
} else {
mShouldNotDelete.remove(key.toString());
}
return f;
}
/**
* If the specified key is not already associated with a value, associates it with the given
* value.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or {@code null} if there was no
* mapping for the key.
*/
public File putIfAbsent(String key, File value) {
return mFiles.putIfAbsent(key, value);
}
/**
* Copies all of the mappings from the specified map to this map.
*
* @param properties mappings to be stored in this map
* @return The final mapping
*/
public ExecutionFiles putAll(Map<String, File> properties) {
mFiles.putAll(properties);
return this;
}
/** Returns whether or not the map of properties is empty. */
public boolean isEmpty() {
return mFiles.isEmpty();
}
/**
* Returns the value to which the specified key is mapped, or {@code null} if this map contains
* no mapping for the key.
*
* @param key the key whose associated value is to be returned
* @return the value to which the specified key is mapped, or {@code null} if this map contains
* no mapping for the key
*/
public File get(String key) {
return mFiles.get(key);
}
/**
* Variation of {@link #get(String)} with a known key.
*
* @param key the key whose associated value is to be returned
* @return the value to which the specified key is mapped, or {@code null} if this map contains
* no mapping for the key
*/
public File get(FilesKey key) {
return mFiles.get(key.toString());
}
/**
* Returns {@code true} if this map contains a mapping for the specified key.
*
* @param key key whose presence in this map is to be tested
* @return {@code true} if this map contains a mapping for the specified key
*/
public boolean containsKey(String key) {
return mFiles.containsKey(key);
}
/** Returns all the properties in a copy of the map */
public ImmutableMap<String, File> getAll() {
return ImmutableMap.copyOf(mFiles);
}
/**
* Removes the mapping for a key from this map if it is present (optional operation).
*
* @param key key whose mapping is to be removed from the map
* @return the previous value associated with {@code key}, or {@code null} if there was no
* mapping for {@code key}.
*/
public File remove(String key) {
return mFiles.remove(key);
}
/** Delete all the files that are tracked and not marked as 'should not delete'. */
public void clearFiles() {
for (String key : mFiles.keySet()) {
if (mShouldNotDelete.contains(key)) {
continue;
}
FileUtil.recursiveDelete(mFiles.get(key));
}
}
}