Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.util;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.mozilla.gecko.annotation.ReflectionTarget;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.error.YAMLException;
// Raptor writes a *-config.yaml file to specify Gecko runtime settings (e.g.
// the profile dir). This file gets deserialized into a DebugConfig object.
// Yaml uses reflection to create this class so we have to tell PG to keep it.
@ReflectionTarget
public class DebugConfig {
private static final String LOGTAG = "GeckoDebugConfig";
protected Map<String, Object> prefs;
protected Map<String, String> env;
protected List<String> args;
public static class ConfigException extends RuntimeException {
public ConfigException(final String message) {
super(message);
}
}
public static @NonNull DebugConfig fromFile(final @NonNull File configFile)
throws FileNotFoundException {
final LoaderOptions options = new LoaderOptions();
final Constructor constructor = new Constructor(DebugConfig.class, options);
final TypeDescription description = new TypeDescription(DebugConfig.class);
description.putMapPropertyType("prefs", String.class, Object.class);
description.putMapPropertyType("env", String.class, String.class);
description.putListPropertyType("args", String.class);
final Yaml yaml = new Yaml(constructor);
yaml.addTypeDescription(description);
final FileInputStream fileInputStream = new FileInputStream(configFile);
try {
return yaml.load(fileInputStream);
} catch (final YAMLException e) {
throw new ConfigException(e.getMessage());
} finally {
try {
if (fileInputStream != null) {
((Closeable) fileInputStream).close();
}
} catch (final IOException e) {
}
}
}
@Nullable
public Bundle mergeIntoExtras(final @Nullable Bundle extras) {
if (env == null) {
return extras;
}
Log.d(LOGTAG, "Adding environment variables from debug config: " + env);
final Bundle result = extras != null ? extras : new Bundle();
int c = 0;
while (result.getString("env" + c) != null) {
c += 1;
}
for (final Map.Entry<String, String> entry : env.entrySet()) {
result.putString("env" + c, entry.getKey() + "=" + entry.getValue());
c += 1;
}
return result;
}
@Nullable
public String[] mergeIntoArgs(final @Nullable String[] initArgs) {
if (args == null) {
return initArgs;
}
Log.d(LOGTAG, "Adding arguments from debug config: " + args);
final ArrayList<String> combinedArgs = new ArrayList<>();
if (initArgs != null) {
combinedArgs.addAll(Arrays.asList(initArgs));
}
combinedArgs.addAll(args);
return combinedArgs.toArray(new String[combinedArgs.size()]);
}
@Nullable
public Map<String, Object> mergeIntoPrefs(final @Nullable Map<String, Object> initPrefs) {
if (prefs == null) {
return initPrefs;
}
Log.d(LOGTAG, "Adding prefs from debug config: " + prefs);
final Map<String, Object> combinedPrefs = new HashMap<>();
if (initPrefs != null) {
combinedPrefs.putAll(initPrefs);
}
combinedPrefs.putAll(prefs);
return Collections.unmodifiableMap(combinedPrefs);
}
}