com.facebook.buck.rules.keys.ReflectiveRuleKeyBuilderFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.rules.keys.ReflectiveRuleKeyBuilderFactory.java

Source

/*
 * 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.rules.keys;

import com.facebook.buck.log.Logger;
import com.facebook.buck.model.BuckVersion;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.RuleKeyAppendable;
import com.facebook.buck.rules.RuleKeyBuilder;
import com.facebook.buck.rules.RuleKeyBuilderFactory;
import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableCollection;

import java.util.concurrent.ExecutionException;

public abstract class ReflectiveRuleKeyBuilderFactory<T extends RuleKeyBuilder> implements RuleKeyBuilderFactory {

    private static final Logger LOG = Logger.get(ReflectiveRuleKeyBuilderFactory.class);

    private final LoadingCache<Class<? extends BuildRule>, ImmutableCollection<AlterRuleKey>> knownFields;
    private final LoadingCache<BuildRule, RuleKey> knownRules;

    public ReflectiveRuleKeyBuilderFactory() {
        knownFields = CacheBuilder.newBuilder().build(new ReflectiveAlterKeyLoader());
        knownRules = CacheBuilder.newBuilder().weakKeys().build(new CacheLoader<BuildRule, RuleKey>() {
            @Override
            public RuleKey load(BuildRule key) throws Exception {
                return newInstance(key).build();
            }
        });
    }

    /**
     * @return sub-classes should override this to provide specialized {@link RuleKeyBuilder}s.
     */
    protected abstract T newBuilder(BuildRule rule);

    @Override
    public T newInstance(BuildRule buildRule) {
        T builder = newBuilder(buildRule);
        builder.setReflectively("name", buildRule.getBuildTarget().getFullyQualifiedName());
        // Keyed as "buck.type" rather than "type" in case a build rule has its own "type" argument.
        builder.setReflectively("buck.type", buildRule.getType());
        builder.setReflectively("buckVersionUid", BuckVersion.getVersion());

        if (buildRule instanceof RuleKeyAppendable) {
            // We call `setAppendableRuleKey` explicitly, since using `setReflectively` will try to add
            // the rule key of the `BuildRule`, which is what we're trying to calculate now.
            //
            // "." is not a valid first character for a field name, and so will never be seen in the
            // reflective rule key setting.
            builder.setAppendableRuleKey(".buck", (RuleKeyAppendable) buildRule);
        }

        try {
            for (AlterRuleKey alterRuleKey : knownFields.get(buildRule.getClass())) {
                alterRuleKey.amendKey(builder, buildRule);
            }
        } catch (ExecutionException | RuntimeException e) {
            LOG.warn(e, "Error creating rule key for %s (%s)", buildRule, buildRule.getType());
            throw Throwables.propagate(e);
        }

        return builder;
    }

    @Override
    public final RuleKey build(BuildRule buildRule) {
        try {
            return knownRules.getUnchecked(buildRule);
        } catch (RuntimeException e) {
            LOG.warn(e, "When building %s", buildRule);
            throw e;
        }
    }

}