| /* |
| * 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.google.common.annotations.VisibleForTesting; |
| import com.google.common.base.Function; |
| import com.google.common.base.Functions; |
| import com.google.common.base.Optional; |
| import com.google.common.base.Predicates; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.Iterables; |
| |
| import java.io.IOException; |
| import java.nio.file.Path; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * If we end up creating both an obfuscator function and a deobfuscator function, it would be |
| * nice to load the proguard mapping file once. This class enables sharing that work. |
| */ |
| class ProguardTranslatorFactory { |
| |
| private final Optional<Map<String, String>> rawMap; |
| |
| private ProguardTranslatorFactory(Optional<Map<String, String>> rawMap) { |
| this.rawMap = rawMap; |
| } |
| |
| static ProguardTranslatorFactory create( |
| ExecutionContext context, |
| Optional<Path> proguardFullConfigFile, |
| Optional<Path> proguardMappingFile) |
| throws IOException { |
| return new ProguardTranslatorFactory( |
| loadOptionalRawMap(context, proguardFullConfigFile, proguardMappingFile)); |
| } |
| |
| @VisibleForTesting |
| static ProguardTranslatorFactory createForTest(Optional<Map<String, String>> rawMap) { |
| return new ProguardTranslatorFactory(rawMap); |
| } |
| |
| private static Optional<Map<String, String>> loadOptionalRawMap( |
| ExecutionContext context, |
| Optional<Path> proguardFullConfigFile, |
| Optional<Path> proguardMappingFile) |
| throws IOException { |
| if (!proguardFullConfigFile.isPresent()) { |
| return Optional.absent(); |
| } |
| |
| ProjectFilesystem projectFilesystem = context.getProjectFilesystem(); |
| Path pathToProguardConfig = proguardFullConfigFile.get(); |
| |
| // Proguard doesn't print a mapping when obfuscation is disabled. |
| boolean obfuscationSkipped = Iterables.any( |
| projectFilesystem.readLines(pathToProguardConfig), |
| Predicates.equalTo("-dontobfuscate")); |
| if (obfuscationSkipped) { |
| return Optional.absent(); |
| } |
| |
| List<String> lines = projectFilesystem.readLines(proguardMappingFile.get()); |
| return Optional.of(ProguardMapping.readClassMapping(lines)); |
| } |
| |
| public Function<String, String> createDeobfuscationFunction() { |
| return createFunction(false); |
| } |
| |
| public Function<String, String> createObfuscationFunction() { |
| return createFunction(true); |
| } |
| |
| private Function<String, String> createFunction(boolean isForObfuscation) { |
| if (!rawMap.isPresent()) { |
| return Functions.identity(); |
| } |
| |
| ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); |
| for (Map.Entry<String, String> entry : rawMap.get().entrySet()) { |
| String original = entry.getKey().replace('.', '/'); |
| String obfuscated = entry.getValue().replace('.', '/'); |
| builder.put( |
| isForObfuscation ? original : obfuscated, |
| isForObfuscation ? obfuscated : original); |
| } |
| final Map<String, String> map = builder.build(); |
| |
| return new Function<String, String>() { |
| @Override |
| public String apply(String input) { |
| String mapped = map.get(input); |
| if (mapped != null) { |
| return mapped; |
| } else { |
| return input; |
| } |
| } |
| }; |
| } |
| } |