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

org.openqa.grid.common.RegistrationRequest Maven / Gradle / Ivy

Go to download

Selenium automates browsers. That's it! What you do with that power is entirely up to you.

There is a newer version: 4.0.0-alpha-2
Show newest version
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you 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 org.openqa.grid.common;

import com.google.common.reflect.TypeToken;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import org.openqa.grid.common.exception.GridConfigurationException;
import org.openqa.grid.internal.utils.configuration.GridNodeConfiguration;
import org.openqa.grid.internal.utils.configuration.GridNodeConfiguration.CollectionOfDesiredCapabilitiesDeSerializer;
import org.openqa.grid.internal.utils.configuration.GridNodeConfiguration.CollectionOfDesiredCapabilitiesSerializer;
import org.openqa.selenium.MutableCapabilities;
import org.openqa.selenium.Platform;
import org.openqa.selenium.net.NetworkUtils;
import org.openqa.selenium.remote.CapabilityType;

import java.util.List;

/**
 * Helper to register to the grid. Using JSON to exchange the object between the node and the hub.
 */
public class RegistrationRequest {

  // some special param for capability
  public static final String MAX_INSTANCES = "maxInstances";
  // see enum SeleniumProtocol
  public static final String SELENIUM_PROTOCOL = "seleniumProtocol";
  public static final String PATH = "path";

  @SerializedName( "class" )
  @Expose( deserialize = false)
  private final String clazz = RegistrationRequest.class.getCanonicalName();
  @Expose
  private String name;
  @Expose
  private String description;
  @Expose
  private GridNodeConfiguration configuration;

  /**
   * Create a new registration request using the default values of a
   * {@link GridNodeConfiguration}
   */
  public RegistrationRequest() {
    this(new GridNodeConfiguration());
  }

  /**
   * Create a new registration request using the supplied {@link GridNodeConfiguration}
   *
   * @param configuration the {@link GridNodeConfiguration} to use. Internally calls {@code new
   *                      GridNodeConfiguration()} if a {@code null} value is provided since a
   *                      request without configuration is not valid.
   */
  public RegistrationRequest(GridNodeConfiguration configuration) {
    this(configuration, null, null);
  }

  /**
   * Create a new registration request using the supplied {@link GridNodeConfiguration}, and name
   *
   * @param configuration the {@link GridNodeConfiguration} to use. Internally calls {@code new
   *                      GridNodeConfiguration()} if a {@code null} value is provided since a
   *                      request without configuration is not valid.
   * @param name          the name for the remote
   */
  public RegistrationRequest(GridNodeConfiguration configuration, String name) {
    this(configuration, name, null);
  }

  /**
   * Create a new registration request using the supplied {@link GridNodeConfiguration}, name, and
   * description
   *
   * @param configuration the {@link GridNodeConfiguration} to use. Internally calls {@code new
   *                      GridNodeConfiguration()} if a {@code null} value is provided since a
   *                      request without configuration is not valid.
   * @param name          the name for the remote
   * @param description   the description for the remote host
   */
  public RegistrationRequest(GridNodeConfiguration configuration, String name, String description) {
    this.configuration = (configuration == null) ? new GridNodeConfiguration() : configuration;
    this.name = name;
    this.description = description;

    // make sure we have something that looks like a valid host
    fixUpHost();
    // make sure the capabilities are updated with required fields
    fixUpCapabilities();
  }

  public String getName() {
    return name;
  }

  public String getDescription() {
    return description;
  }

  public GridNodeConfiguration getConfiguration() {
    return configuration;
  }

  public JsonObject toJson() {
    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(new TypeToken>(){}.getType(),
                                new CollectionOfDesiredCapabilitiesSerializer());

    // note: it's very important that nulls are serialized for this type.
    return builder.serializeNulls()
        .excludeFieldsWithoutExposeAnnotation()
        .create()
        .toJsonTree(this, RegistrationRequest.class)
        .getAsJsonObject();
  }

  /**
   * Create an object from a registration request formatted as a JsonObject
   *
   * @param json JsonObject
   * @return
   */
  public static RegistrationRequest fromJson(JsonObject json) throws JsonSyntaxException {
    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(new TypeToken>(){}.getType(),
                                new CollectionOfDesiredCapabilitiesDeSerializer());

    RegistrationRequest request = builder.excludeFieldsWithoutExposeAnnotation().create()
      .fromJson(json, RegistrationRequest.class);

    return request;
  }

  /**
   * Create an object from a registration request formatted as a json string.
   *
   * @param json JSON String
   * @return
   */
  public static RegistrationRequest fromJson(String json) throws JsonSyntaxException {
    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(new TypeToken>(){}.getType(),
                                new CollectionOfDesiredCapabilitiesDeSerializer());

    RegistrationRequest request = builder.excludeFieldsWithoutExposeAnnotation().create()
      .fromJson(json, RegistrationRequest.class);

    return request;
  }

  /**
   * Build a RegistrationRequest.
   * @return
   */
  public static RegistrationRequest build() {
    return RegistrationRequest.build(new GridNodeConfiguration(), null, null);
  }

  /**
   * Build a RegistrationRequest from the provided {@link GridNodeConfiguration}. This is different
   * than {@code new RegistrationRequest(GridNodeConfiguration)} because it will first load any
   * specified {@link GridNodeConfiguration#nodeConfigFile} and then merge the provided
   * configuration onto it.
   *
   * @param configuration the {@link GridNodeConfiguration} to use. Internally calls {@code new
   *                      GridNodeConfiguration()} if a {@code null} value is provided since a
   *                      request without configuration is not valid.
   */
  public static RegistrationRequest build(GridNodeConfiguration configuration) {
    return RegistrationRequest.build(configuration, null, null);
  }

  /**
   * Build a RegistrationRequest from the provided {@link GridNodeConfiguration}, use the provided
   * name. This is different than {@code new RegistrationRequest(GridNodeConfiguration, String)}
   * because it will first load any specified {@link GridNodeConfiguration#nodeConfigFile} and then
   * merge the provided configuration onto it.
   *
   * @param configuration the {@link GridNodeConfiguration} to use. Internally calls {@code new
   *                      GridNodeConfiguration()} if a {@code null} value is provided since a
   *                      request without configuration is not valid.
   * @param name          the name for the remote
   */
  public static RegistrationRequest build(GridNodeConfiguration configuration, String name) {
    return RegistrationRequest.build(configuration, name, null);
  }

  /**
   * Build a RegistrationRequest from the provided {@link GridNodeConfiguration}, use the provided
   * name and description. This is different than {@code new RegistrationRequest(GridNodeConfiguration,
   * String, String)} because it will first load any specified {@link
   * GridNodeConfiguration#nodeConfigFile} and then merge the provided configuration onto it.
   *
   * @param configuration the {@link GridNodeConfiguration} to use. Internally calls {@code new
   *                      GridNodeConfiguration()} if a {@code null} value is provided since a
   *                      request without configuration is not valid.
   * @param name          the name for the remote
   * @param description   the description for the remote host
   */
  public static RegistrationRequest build(GridNodeConfiguration configuration, String name, String description) {
    RegistrationRequest pendingRequest = new RegistrationRequest(configuration, name, description);
    GridNodeConfiguration pendingConfiguration = pendingRequest.configuration;

    if (pendingConfiguration.nodeConfigFile != null) {
      pendingRequest.configuration = GridNodeConfiguration.loadFromJSON(pendingConfiguration.nodeConfigFile);
    }

    pendingRequest.configuration.merge(pendingConfiguration);
    //update important merge protected values for the pendingRequest we are building.
    if (pendingConfiguration.host != null) {
      pendingRequest.configuration.host = pendingConfiguration.host;
    }
    if (pendingConfiguration.port != null) {
      pendingRequest.configuration.port = pendingConfiguration.port;
    }

    // make sure we have a valid host
    pendingRequest.fixUpHost();
    // make sure the capabilities are updated with required fields
    pendingRequest.fixUpCapabilities();

    return pendingRequest;
  }

  private void fixUpCapabilities() {
    if (configuration.capabilities == null) {
      return; // assumes the caller set it/wants it this way
    }

    Platform current = Platform.getCurrent();
    for (MutableCapabilities cap : configuration.capabilities) {
      if (cap.getPlatform() == null) {
        cap.setCapability(CapabilityType.PLATFORM, current);
      }
      if (cap.getCapability(SELENIUM_PROTOCOL) == null) {
        cap.setCapability(SELENIUM_PROTOCOL, SeleniumProtocol.WebDriver.toString());
      }
    }
  }

  private void fixUpHost() {
    NetworkUtils util = new NetworkUtils();
    if (configuration.host == null || "ip".equalsIgnoreCase(configuration.host)) {
      configuration.host = util.getIp4NonLoopbackAddressOfThisMachine().getHostAddress();
    } else if ("host".equalsIgnoreCase(configuration.host)) {
      configuration.host = util.getIp4NonLoopbackAddressOfThisMachine().getHostName();
    }
  }

  /**
   * Validate the current setting and throw a config exception is an invalid setup is detected.
   *
   * @throws GridConfigurationException grid configuration
   */
  public void validate() throws GridConfigurationException {
    // validations occur here in the getters called on the configuration.
    try {
      configuration.getHubHost();
      configuration.getHubPort();
    } catch (RuntimeException e) {
      throw new GridConfigurationException(e.getMessage());
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy