|  | // Copyright 2015 The Bazel Authors. All rights reserved. | 
|  | // | 
|  | // 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.google.devtools.build.lib.packages; | 
|  |  | 
|  | import com.google.common.base.Verify; | 
|  | import com.google.common.collect.Maps; | 
|  | import com.google.devtools.build.lib.cmdline.Label; | 
|  | import com.google.devtools.build.lib.cmdline.LabelSyntaxException; | 
|  | import com.google.devtools.build.lib.events.Location; | 
|  | import com.google.devtools.build.lib.events.StoredEventHandler; | 
|  | import com.google.devtools.build.lib.packages.Package.Builder; | 
|  | import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap; | 
|  | import com.google.devtools.build.lib.syntax.FuncallExpression; | 
|  | import com.google.devtools.build.lib.util.Preconditions; | 
|  | import java.util.Map; | 
|  |  | 
|  | /** | 
|  | * A builder that helps constructing the //external package. | 
|  | */ | 
|  | public class ExternalPackageBuilder { | 
|  |  | 
|  | public Rule createAndAddRepositoryRule( | 
|  | Package.Builder pkg, | 
|  | RuleClass ruleClass, | 
|  | RuleClass bindRuleClass, | 
|  | Map<String, Object> kwargs, | 
|  | FuncallExpression ast) | 
|  | throws RuleFactory.InvalidRuleException, Package.NameConflictException, LabelSyntaxException, | 
|  | InterruptedException { | 
|  |  | 
|  | StoredEventHandler eventHandler = new StoredEventHandler(); | 
|  | BuildLangTypedAttributeValuesMap attributeValues = new BuildLangTypedAttributeValuesMap(kwargs); | 
|  | Rule rule = | 
|  | RuleFactory.createRule( | 
|  | pkg, | 
|  | ruleClass, | 
|  | attributeValues, | 
|  | eventHandler, | 
|  | ast, | 
|  | ast.getLocation(), | 
|  | /*env=*/ null, | 
|  | new AttributeContainer(ruleClass)); | 
|  | pkg.addEvents(eventHandler.getEvents()); | 
|  | overwriteRule(pkg, rule); | 
|  | for (Map.Entry<String, Label> entry : | 
|  | ruleClass.getExternalBindingsFunction().apply(rule).entrySet()) { | 
|  | Label nameLabel = Label.parseAbsolute("//external:" + entry.getKey()); | 
|  | addBindRule( | 
|  | pkg, | 
|  | bindRuleClass, | 
|  | nameLabel, | 
|  | entry.getValue(), | 
|  | rule.getLocation(), | 
|  | new AttributeContainer(bindRuleClass)); | 
|  | } | 
|  | return rule; | 
|  | } | 
|  |  | 
|  | static void addBindRule( | 
|  | Builder pkg, | 
|  | RuleClass bindRuleClass, | 
|  | Label virtual, | 
|  | Label actual, | 
|  | Location location, | 
|  | AttributeContainer attributeContainer) | 
|  | throws RuleFactory.InvalidRuleException, Package.NameConflictException, InterruptedException { | 
|  |  | 
|  | Map<String, Object> attributes = Maps.newHashMap(); | 
|  | // Bound rules don't have a name field, but this works because we don't want more than one | 
|  | // with the same virtual name. | 
|  | attributes.put("name", virtual.getName()); | 
|  | if (actual != null) { | 
|  | attributes.put("actual", actual); | 
|  | } | 
|  | StoredEventHandler handler = new StoredEventHandler(); | 
|  | BuildLangTypedAttributeValuesMap attributeValues = | 
|  | new BuildLangTypedAttributeValuesMap(attributes); | 
|  | Rule rule = | 
|  | RuleFactory.createRule( | 
|  | pkg, | 
|  | bindRuleClass, | 
|  | attributeValues, | 
|  | handler, | 
|  | /*ast=*/ null, | 
|  | location, | 
|  | /*env=*/ null, | 
|  | attributeContainer); | 
|  | overwriteRule(pkg, rule); | 
|  | rule.setVisibility(ConstantRuleVisibility.PUBLIC); | 
|  | } | 
|  |  | 
|  | private static void overwriteRule(Package.Builder pkg, Rule rule) | 
|  | throws Package.NameConflictException, InterruptedException { | 
|  | Preconditions.checkArgument(rule.getOutputFiles().isEmpty()); | 
|  | Target old = pkg.targets.get(rule.getName()); | 
|  | if (old != null) { | 
|  | if (old instanceof Rule) { | 
|  | Verify.verify(((Rule) old).getOutputFiles().isEmpty()); | 
|  | } | 
|  |  | 
|  | pkg.targets.remove(rule.getName()); | 
|  | } | 
|  |  | 
|  | pkg.addRule(rule); | 
|  | } | 
|  | } |