/*
* Copyright 2012-present Facebook, Inc.
*
* 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.facebook.buck.android;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.StepExecutionResult;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** Replaces placeholders in the android manifest. */
public class ReplaceManifestPlaceholdersStep implements Step {
private final ProjectFilesystem projectFilesystem;
private final Path androidManifest;
private final Path replacedManifest;
private final ImmutableMap<String, String> manifestEntries;
public ReplaceManifestPlaceholdersStep(
ProjectFilesystem projectFilesystem,
Path androidManifest,
Path replacedManifest,
ImmutableMap<String, String> manifestEntries) {
this.projectFilesystem = projectFilesystem;
this.androidManifest = androidManifest;
this.replacedManifest = replacedManifest;
this.manifestEntries = manifestEntries;
}
@Override
public StepExecutionResult execute(ExecutionContext context) throws InterruptedException {
try {
String content =
new String(
Files.readAllBytes(projectFilesystem.resolve(androidManifest)),
StandardCharsets.UTF_8);
String replaced = replacePlaceholders(content, manifestEntries);
projectFilesystem.writeContentsToPath(replaced, replacedManifest);
} catch (IOException e) {
context.logError(e, "Could not replace manifest placeholders.");
return StepExecutionResult.ERROR;
}
return StepExecutionResult.SUCCESS;
}
@Override
public String getShortName() {
return "replace_manifest_placeholders";
}
@Override
public String getDescription(ExecutionContext context) {
return String.format("%s: %s -> %s", getShortName(), androidManifest, replacedManifest);
}
@VisibleForTesting
static String replacePlaceholders(String content, ImmutableMap<String, String> placeholders) {
Iterable<String> escaped = Iterables.transform(placeholders.keySet(), Pattern::quote);
Joiner joiner = Joiner.on("|");
String patternString =
Pattern.quote("${") + "(" + joiner.join(escaped) + ")" + Pattern.quote("}");
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(content);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, placeholders.get(matcher.group(1)));
}
matcher.appendTail(sb);
return sb.toString();
}
}