All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.prd.mobile.ios.mios.BuildContextAwareMojo Maven / Gradle / Ivy

Go to download

This plugin is used to run iOS Xcode builds with Maven. It also uses the Maven integration with a central artifact repository and the dependency resolution.

There is a newer version: 1.14.7
Show newest version
/*
 * #%L
 * xcode-maven-plugin
 * %%
 * Copyright (C) 2012 SAP AG
 * %%
 * 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.
 * #L%
 */
package com.sap.prd.mobile.ios.mios;

import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecutionException;

/**
 * Contains all parameters and methods that are needed for mojos that invoke the 'xcodebuild'
 * command.
 * 
 */
public abstract class BuildContextAwareMojo extends AbstractXCodeMojo
{

  private static final String PREFIX_XCODE_OPTIONS = "xcode.options.";
  private static final String PREFIX_XCODE_SETTINGS = "xcode.settings.";

  protected final static List DEFAULT_BUILD_ACTIONS = Collections.unmodifiableList(Arrays.asList("clean",
        "build"));

  /**
   * The Xcode build action to to execute (e.g. clean, build, install). By default
   * clean and build are executed.
   * 
   * @parameter
   */
  protected List buildActions;

  /**
   * The code sign identity is used to select the provisioning profile (e.g.
   * iPhone Distribution, iPhone Developer).
   * 
   * @parameter expression="${xcode.codeSignIdentity}"
   * @since 1.2.0
   */
  protected String codeSignIdentity;

  /**
   * The code signing required is used to disable code signing when no
   * developer provisioning certificate is available (e.g.
   * NO, YES).
   * 
   * @parameter expression="${xcode.codeSigningRequired}" default-value = "true"
   * @since 1.14.1
   */
  protected boolean codeSigningRequired;
  
  /**
   * Can be used to override the provisioning profile defined in the Xcode project target. You can
   * set it to an empty String if you want to use the default provisioning profile.
   * 
   * @parameter expression="${xcode.provisioningProfile}"
   * @since 1.2.1
   */
  protected String provisioningProfile;

  /**
   * The Xcode target to be built. If not specified, the default target (the first target) will be
   * built.
   * 
   * @parameter expression="${xcode.target}"
   * @since 1.4.1
   */
  protected String target;

  /**
   * @parameter expression="${product.name}"
   */
  private String productName;

  /**
   * Settings to pass to XCode - if any are explicitly defined here, this plugin will not provide
   * default settings to XCode.
   * 
   * @parameter
   * @since 1.6.2
   */
  private Map settings;

  /**
   * Options to pass to XCode - if any are explicitly defined here, this plugin will not provide
   * default options to XCode.
   * 
   * @parameter
   * @since 1.6.2
   */
  private Map options;

  /**
   * @parameter expression="${session}"
   * @required
   * @readonly
   */
  private MavenSession session;

  /**
   * @parameter expression="${xcode.watchapp}"
   * For watchos2.0 we should not send the sdk value to xcodebuild, To differentiate between regular app and watch2.0 (Now it's specific)
   * expecting this property from developer in pom.xml, on demand this will be considered.
   *
   * pom.xml entry:
   *
   * 
   * {@code
   * 
   *  watchos2.0
   * 
   * }
   * 
* * @since 1.14.3 */ private String watchapp; /** * Allowed developers to override the SYMROOT settings * * @parameter expression="${xcode.symroot}" default-value = "build" * @since 1.14.4 */ private String symRootDir; protected XCodeContext getXCodeContext(final XCodeContext.SourceCodeLocation sourceCodeLocation, String configuration, String sdk) { final String projectName = project.getArtifactId(); File projectDirectory = null; if (sourceCodeLocation == XCodeContext.SourceCodeLocation.WORKING_COPY) { projectDirectory = getXCodeCompileDirectory(); } else if (sourceCodeLocation == XCodeContext.SourceCodeLocation.ORIGINAL) { projectDirectory = getXCodeSourceDirectory(); } else { throw new IllegalStateException("Invalid source code location: '" + sourceCodeLocation + "'"); } HashMap managedSettings = new HashMap(); if (codeSignIdentity != null) managedSettings.put(Settings.ManagedSetting.CODE_SIGN_IDENTITY.name(), codeSignIdentity); if (symRootDir != null) managedSettings.put(Settings.ManagedSetting.SYMROOT.name(), symRootDir); if (!codeSigningRequired) managedSettings.put(Settings.ManagedSetting.CODE_SIGNING_REQUIRED.name(), "NO"); if (provisioningProfile != null) managedSettings.put(Settings.ManagedSetting.PROVISIONING_PROFILE.name(), provisioningProfile); HashMap managedOptions = new HashMap(); if (configuration != null && !configuration.trim().isEmpty()) managedOptions.put(Options.ManagedOption.CONFIGURATION.getOptionName(), configuration); /** * No specific check has been done here, If property specified then sdk entry will be ignored * This can be extended with the specific check. I kept this as Generic because watchosX.X should support with this check, * without confusing developers it will serve the purpose */ if (sdk != null && !sdk.trim().isEmpty() && watchapp ==null) managedOptions.put(Options.ManagedOption.SDK.getOptionName(), sdk); if (target != null && !target.trim().isEmpty()) managedOptions.put(Options.ManagedOption.TARGET.getOptionName(), target); Map _settings = new HashMap(settings == null ? new HashMap() : settings); for (String key : getKeys(PREFIX_XCODE_SETTINGS)) { _settings.put(key.substring(PREFIX_XCODE_SETTINGS.length()), getProperty(key)); } Map _options = new HashMap(options == null ? new HashMap() : options); for (String key : getKeys(PREFIX_XCODE_OPTIONS)) { _options.put(key.substring(PREFIX_XCODE_OPTIONS.length()), getProperty(key)); } if (null == _options.get("scheme")) managedOptions.put(Options.ManagedOption.PROJECT.getOptionName(), projectName + ".xcodeproj"); return new XCodeContext(getBuildActions(), projectDirectory, System.out, new Settings(_settings, managedSettings), new Options(_options, managedOptions)); } protected List getBuildActions() { return (buildActions == null || buildActions.isEmpty()) ? DEFAULT_BUILD_ACTIONS : Collections .unmodifiableList(buildActions); } /** * Retrieves the Info Plist out of the effective Xcode project settings and returns the accessor * to it. */ protected PListAccessor getInfoPListAccessor(XCodeContext.SourceCodeLocation location, String configuration, String sdk) throws MojoExecutionException, XCodeException { File plistFile = getPListFile(location, configuration, sdk); if (!plistFile.isFile()) { throw new MojoExecutionException("The Xcode project refers to the Info.plist file '" + plistFile + "' that does not exist."); } return new PListAccessor(plistFile); } protected File getPListFile(XCodeContext.SourceCodeLocation location, String configuration, String sdk) throws XCodeException { XCodeContext context = getXCodeContext(location, configuration, sdk); String plistFileName = EffectiveBuildSettings.getBuildSetting(context, EffectiveBuildSettings.INFOPLIST_FILE); File srcRoot = new File(EffectiveBuildSettings.getBuildSetting(context, EffectiveBuildSettings.SRC_ROOT)); final File plistFile = new File(plistFileName); if (!plistFile.isAbsolute()) { return new File(srcRoot, plistFileName); } if (FileUtils.isChild(srcRoot, plistFile)) return plistFile; throw new IllegalStateException("Plist file " + plistFile + " is not located inside the xcode project " + srcRoot + "."); } protected File getProjectRootDirectory(XCodeContext.SourceCodeLocation location, String configuration, String sdk) throws XCodeException { XCodeContext context = getXCodeContext(location, configuration, sdk); File srcRoot = new File(EffectiveBuildSettings.getBuildSetting(context, EffectiveBuildSettings.SRC_ROOT)); return srcRoot; } protected String getProductName(final String configuration, final String sdk) throws MojoExecutionException { final String productName; if (this.productName != null) { productName = this.productName; getLog().info("Production name obtained from pom file"); } else { try { productName = EffectiveBuildSettings.getBuildSetting( getXCodeContext(XCodeContext.SourceCodeLocation.WORKING_COPY, configuration, sdk), EffectiveBuildSettings.PRODUCT_NAME); getLog().info("Product name obtained from effective build settings file"); } catch (final XCodeException ex) { throw new MojoExecutionException("Cannot get product name: " + ex.getMessage(), ex); } } if (productName == null || productName.trim().length() == 0) throw new MojoExecutionException("Invalid product name. Was null or empty."); return productName; } /** * Returns all keys of project properties and user properties matching the prefix. * * @param prefix * all keys if null * @return */ @SuppressWarnings("unchecked") protected Set getKeys(String prefix) { Set result = new HashSet(); @SuppressWarnings("rawtypes") final Set keys = new HashSet(); keys.addAll(session.getUserProperties().keySet()); keys.addAll(project.getProperties().keySet()); if (prefix == null) return keys; for (Object key : keys) { if (((String) key).startsWith(prefix)) result.add((String) key); } return result; } protected String getProperty(String key) { String value = session.getUserProperties().getProperty(key); if (value == null) { value = project.getProperties().getProperty(key); } return value; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy