/* * Copyright 2015-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.aapt; import com.android.ide.common.res2.MergedResourceWriter; import com.android.ide.common.res2.MergingException; import com.android.ide.common.res2.NoOpResourcePreprocessor; import com.android.ide.common.res2.ResourceMerger; import com.android.ide.common.res2.ResourceSet; import com.android.utils.ILogger; import com.facebook.buck.android.BuckEventAndroidLogger; import com.facebook.buck.event.BuckEventBus; import com.facebook.buck.log.Logger; import com.facebook.buck.step.ExecutionContext; import com.facebook.buck.step.Step; import com.facebook.buck.step.StepExecutionResult; import com.facebook.buck.util.immutables.BuckStyleImmutable; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import java.io.IOException; import java.nio.file.Path; import org.immutables.value.Value; /** Merges multiple directories containing Android resource sources into one directory. */ @Value.Immutable @BuckStyleImmutable abstract class AbstractMergeAndroidResourceSourcesStep implements Step { private static final Logger LOG = Logger.get(AbstractMergeAndroidResourceSourcesStep.class); @Value.Parameter protected abstract ImmutableList<Path> getResPaths(); @Value.Parameter protected abstract Path getOutFolderPath(); @Value.Parameter protected abstract Path getTmpFolderPath(); @Value.Check protected void check() { Preconditions.checkArgument( getOutFolderPath().isAbsolute(), "Android merge out folder path must be absolute but was %s", getOutFolderPath()); Preconditions.checkArgument( getTmpFolderPath().isAbsolute(), "Android merge tmp folder path must be absolute but was %s", getOutFolderPath()); for (Path resPath : getResPaths()) { Preconditions.checkArgument( resPath.isAbsolute(), "Android merge resource path must be absolute but was %s", resPath); } } @Override public StepExecutionResult execute(ExecutionContext context) throws IOException, InterruptedException { ResourceMerger merger = new ResourceMerger(1); try { for (Path resPath : getResPaths()) { ResourceSet set = new ResourceSet(resPath.toString(), true); set.setDontNormalizeQualifiers(true); set.addSource(resPath.toFile()); set.loadFromFiles(new ResourcesSetLoadLogger(context.getBuckEventBus())); merger.addDataSet(set); } MergedResourceWriter writer = MergedResourceWriter.createWriterWithoutPngCruncher( getOutFolderPath().toFile(), null /*publicFile*/, null /*blameLogFolder*/, new NoOpResourcePreprocessor(), getTmpFolderPath().toFile()); merger.mergeData(writer, /* cleanUp */ false); } catch (MergingException e) { LOG.error(e, "Failed merging resources."); return StepExecutionResult.ERROR; } return StepExecutionResult.SUCCESS; } @Override public String getShortName() { return "merge-resources"; } @Override public String getDescription(ExecutionContext context) { StringBuilder sb = new StringBuilder(getShortName()); sb.append(' '); Joiner.on(',').appendTo(sb, getResPaths()); sb.append(" -> "); sb.append(getOutFolderPath().toString()); return sb.toString(); } private static class ResourcesSetLoadLogger extends BuckEventAndroidLogger implements ILogger { public ResourcesSetLoadLogger(BuckEventBus eventBus) { super(eventBus); } } }