com.google.devtools.build.lib.rules.objc.ReleaseBundling.java Source code

Java tutorial

Introduction

Here is the source code for com.google.devtools.build.lib.rules.objc.ReleaseBundling.java

Source

// Copyright 2016 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.rules.objc;

import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.BundlingRule.FAMILIES_ATTR;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.APP_ICON_ATTR;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.BUNDLE_ID_ATTR;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.DEFAULT_PROVISIONING_PROFILE_ATTR;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_IMAGE_ATTR;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_STORYBOARD_ATTR;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.PROVISIONING_PROFILE_ATTR;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.rules.objc.TargetDeviceFamily.InvalidFamilyNameException;
import com.google.devtools.build.lib.rules.objc.TargetDeviceFamily.RepeatedFamilyNameException;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.Preconditions;

import java.util.List;

/**
 * Contains information regarding the creation of a released bundle such as an application
 * or extension. The information which generally includes app icons, launch image, targeted devices
 * and other data for potential signing is used to create a releasable bundle out of the bundle
 * created using {@link Bundling} object.
 */
@Immutable
final class ReleaseBundling {
    static final class Builder {
        private Artifact ipaArtifact;
        private String bundleId;
        private String primaryBundleId;
        private String fallbackBundleId;
        private String appIcon;
        private String launchImage;
        private Artifact launchStoryboard;
        private Artifact provisioningProfile;
        private String provisioningProfileAttributeName;
        private final NestedSetBuilder<Artifact> infoplistInputs = NestedSetBuilder.stableOrder();
        private Iterable<Artifact> infoPlistsFromRule;
        private ImmutableSet<TargetDeviceFamily> families;
        private IntermediateArtifacts intermediateArtifacts;
        private String artifactPrefix;
        private Artifact entitlements;
        private Artifact extraEntitlements;

        public Builder setIpaArtifact(Artifact ipaArtifact) {
            this.ipaArtifact = ipaArtifact;
            return this;
        }

        public Builder setBundleId(String bundleId) {
            this.bundleId = bundleId;
            return this;
        }

        public Builder setPrimaryBundleId(String primaryId) {
            this.primaryBundleId = primaryId;
            return this;
        }

        public Builder setFallbackBundleId(String fallbackId) {
            this.fallbackBundleId = fallbackId;
            return this;
        }

        public Builder setAppIcon(String appIcon) {
            this.appIcon = appIcon;
            return this;
        }

        public Builder setLaunchImage(String launchImage) {
            this.launchImage = launchImage;
            return this;
        }

        public Builder setLaunchStoryboard(Artifact launchStoryboard) {
            this.launchStoryboard = launchStoryboard;
            return this;
        }

        public Builder setProvisioningProfile(Artifact provisioningProfile) {
            this.provisioningProfile = provisioningProfile;
            return this;
        }

        public Builder setProvisioningProfileAttributeName(String provisioningProfileAttributeName) {
            this.provisioningProfileAttributeName = provisioningProfileAttributeName;
            return this;
        }

        public Builder addInfoplistInput(Artifact infoPlist) {
            this.infoplistInputs.add(infoPlist);
            return this;
        }

        public Builder addInfoplistInputs(Iterable<Artifact> infoplists) {
            this.infoplistInputs.addAll(infoplists);
            return this;
        }

        public Builder setInfoPlistsFromRule(Iterable<Artifact> infoPlistsFromRule) {
            this.infoPlistsFromRule = infoPlistsFromRule;
            return this;
        }

        public Builder setIntermediateArtifacts(IntermediateArtifacts intermediateArtifacts) {
            this.intermediateArtifacts = intermediateArtifacts;
            return this;
        }

        public Builder setTargetDeviceFamilies(ImmutableSet<TargetDeviceFamily> families) {
            this.families = families;
            return this;
        }

        public Builder setArtifactPrefix(String artifactPrefix) {
            this.artifactPrefix = artifactPrefix;
            return this;
        }

        public Builder setEntitlements(Artifact entitlements) {
            this.entitlements = entitlements;
            return this;
        }

        public ReleaseBundling build() {
            Preconditions.checkNotNull(intermediateArtifacts, "intermediateArtifacts");
            Preconditions.checkNotNull(families, FAMILIES_ATTR);
            return new ReleaseBundling(ipaArtifact, bundleId, primaryBundleId, fallbackBundleId, appIcon,
                    launchImage, launchStoryboard, provisioningProfile, provisioningProfileAttributeName,
                    infoplistInputs.build(), infoPlistsFromRule, families, intermediateArtifacts, artifactPrefix,
                    entitlements, extraEntitlements);
        }
    }

    /**
     * Returns a {@link ReleaseBundling} object constructed using the information available in given
     * context.
     */
    public static ReleaseBundling releaseBundling(RuleContext ruleContext) throws InterruptedException {
        Preconditions.checkState(!Strings.isNullOrEmpty(ruleContext.attributes().get(BUNDLE_ID_ATTR, Type.STRING)),
                "requires a bundle_id value");
        String primaryBundleId = null;
        String fallbackBundleId = null;
        Artifact provisioningProfile;

        if (ruleContext.attributes().isAttributeValueExplicitlySpecified(BUNDLE_ID_ATTR)) {
            primaryBundleId = ruleContext.attributes().get(BUNDLE_ID_ATTR, Type.STRING);
        } else {
            fallbackBundleId = ruleContext.attributes().get(BUNDLE_ID_ATTR, Type.STRING);
        }

        Artifact explicitProvisioningProfile = ruleContext.getPrerequisiteArtifact(PROVISIONING_PROFILE_ATTR,
                Mode.TARGET);
        if (explicitProvisioningProfile != null) {
            provisioningProfile = explicitProvisioningProfile;
        } else {
            provisioningProfile = ruleContext.getPrerequisiteArtifact(DEFAULT_PROVISIONING_PROFILE_ATTR,
                    Mode.TARGET);
        }

        ImmutableSet<TargetDeviceFamily> families = null;
        List<String> rawFamilies = ruleContext.attributes().get(FAMILIES_ATTR, Type.STRING_LIST);
        try {
            families = ImmutableSet.copyOf(TargetDeviceFamily.fromNamesInRule(rawFamilies));
        } catch (InvalidFamilyNameException | RepeatedFamilyNameException e) {
            families = ImmutableSet.of();
        }

        if (families.isEmpty()) {
            ruleContext.attributeError(FAMILIES_ATTR, INVALID_FAMILIES_ERROR);
        }

        return new ReleaseBundling.Builder()
                .setIpaArtifact(ruleContext.getImplicitOutputArtifact(ReleaseBundlingSupport.IPA))
                .setBundleId(ruleContext.attributes().get(BUNDLE_ID_ATTR, Type.STRING))
                .setPrimaryBundleId(primaryBundleId).setFallbackBundleId(fallbackBundleId)
                .setAppIcon(Strings.emptyToNull(ruleContext.attributes().get(APP_ICON_ATTR, Type.STRING)))
                .setLaunchImage(Strings.emptyToNull(ruleContext.attributes().get(LAUNCH_IMAGE_ATTR, Type.STRING)))
                .setLaunchStoryboard(ruleContext.getPrerequisiteArtifact(LAUNCH_STORYBOARD_ATTR, Mode.TARGET))
                .setProvisioningProfile(provisioningProfile)
                .setProvisioningProfileAttributeName(PROVISIONING_PROFILE_ATTR).setTargetDeviceFamilies(families)
                .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext))
                .setEntitlements(ruleContext.getPrerequisiteArtifact("entitlements", Mode.TARGET)).build();
    }

    @VisibleForTesting
    static final String INVALID_FAMILIES_ERROR = "Expected one or two strings from the list 'iphone', 'ipad'";
    private final Artifact ipaArtifact;
    private final String bundleId;
    private final String fallbackBundleId;
    private final String primaryBundleId;
    private final String appIcon;
    private final String launchImage;
    private final Artifact launchStoryboard;
    private final Artifact provisioningProfile;
    private final String provisioningProfileAttributeName;
    private final NestedSet<Artifact> infoplistInputs;
    private final ImmutableSet<TargetDeviceFamily> families;
    private final IntermediateArtifacts intermediateArtifacts;
    private final Iterable<Artifact> infoPlistsFromRule;
    private final String artifactPrefix;
    private final Artifact entitlements;

    private ReleaseBundling(Artifact ipaArtifact, String bundleId, String primaryBundleId, String fallbackBundleId,
            String appIcon, String launchImage, Artifact launchStoryboard, Artifact provisioningProfile,
            String provisioningProfileAttributeName, NestedSet<Artifact> infoplistInputs,
            Iterable<Artifact> infoPlistsFromRule, ImmutableSet<TargetDeviceFamily> families,
            IntermediateArtifacts intermediateArtifacts, String artifactPrefix, Artifact entitlements,
            Artifact extraEntitlements) {
        this.ipaArtifact = Preconditions.checkNotNull(ipaArtifact);
        this.bundleId = bundleId;
        this.primaryBundleId = primaryBundleId;
        this.fallbackBundleId = fallbackBundleId;
        this.appIcon = appIcon;
        this.launchImage = launchImage;
        this.launchStoryboard = launchStoryboard;
        this.provisioningProfile = provisioningProfile;
        this.provisioningProfileAttributeName = Preconditions.checkNotNull(provisioningProfileAttributeName);
        this.infoplistInputs = Preconditions.checkNotNull(infoplistInputs);
        this.infoPlistsFromRule = infoPlistsFromRule;
        this.families = Preconditions.checkNotNull(families);
        this.intermediateArtifacts = Preconditions.checkNotNull(intermediateArtifacts);
        this.artifactPrefix = artifactPrefix;
        this.entitlements = entitlements;
    }

    /**
     * Returns the {@link Artifact} containing the final ipa bundle.
     */
    public Artifact getIpaArtifact() {
        return ipaArtifact;
    }

    /**
     * Returns the identifier of this bundle.
     */
    public String getBundleId() {
        return bundleId;
    }

    /**
     * Returns primary bundle ID to use, can be null.
     */
    public String getPrimaryBundleId() {
        return primaryBundleId;
    }

    /**
     * Returns fallback bundle ID to use when primary isn't set.
     */
    public String getFallbackBundleId() {
        return fallbackBundleId;
    }

    /**
     * Returns the app icon name for this bundle, can be null.
     */
    public String getAppIcon() {
        return appIcon;
    }

    /**
     * Returns the launch image name for this bundle, can be null.
     */
    public String getLaunchImage() {
        return launchImage;
    }

    /**
     * Returns an {@link Artifact} containing launch storyboard for this bundle, can be null.
     */
    public Artifact getLaunchStoryboard() {
        return launchStoryboard;
    }

    /**
     * Returns an {@link Artifact} containing provisioning profile used to sign this bundle,
     * can be null.
     */
    public Artifact getProvisioningProfile() {
        return provisioningProfile;
    }

    /**
     * Returns the list of plists to be merged to final bundle.
     */
    public NestedSet<Artifact> getInfoplistInputs() {
        return infoplistInputs;
    }

    /**
     * Returns the list of {@link TargetDeviceFamily} values this bundle is targeting.
     * If empty, the default values specified by {@link FAMILIES_ATTR} will be used.
     */
    public ImmutableSet<TargetDeviceFamily> getTargetDeviceFamilies() {
        return families;
    }

    /**
     * Returns {@link IntermediateArtifacts} used to create this bundle.
     */
    public IntermediateArtifacts getIntermediateArtifacts() {
        return intermediateArtifacts;
    }

    /**
     * Returns the name of the attribute which is used to specifiy the provisioning profile.
     */
    public String getProvisioningProfileAttrName() {
        return provisioningProfileAttributeName;
    }

    /**
     * Adds any info plists specified in the given rule's {@code infoplists} attribute as inputs to
     * this bundle's {@code Info.plist} (which is merged from any such added plists plus some
     * additional information).
     */
    public Iterable<Artifact> getInfoPlistsFromRule() {
        return infoPlistsFromRule;
    }

    /**
     * Returns the prefix to be added to all generated artifact names, can be null. This is useful
     * to disambiguate artifacts for multiple bundles created with different names withing same rule. 
     */
    public String getArtifactPrefix() {
        return artifactPrefix;
    }

    /**
     * Returns an {@link Artifact} containing the entitlements used to sign this bundle for
     * non-simulator builds; can be null.
     */
    public Artifact getEntitlements() {
        return entitlements;
    }
}