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

org.openqa.selenium.remote.BeanToJsonConverter Maven / Gradle / Ivy

// 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.selenium.remote;

import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;

import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.logging.LogEntries;
import org.openqa.selenium.logging.LogLevelMapping;
import org.openqa.selenium.logging.LoggingPreferences;
import org.openqa.selenium.logging.SessionLogs;

import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

/**
 * Utility class for converting between JSON and Java Objects.
 */
public class BeanToJsonConverter {

  private static final int MAX_DEPTH = 5;

  /**
   * Convert an object that may or may not be a JsonElement into its JSON string
   * representation, handling the case where it is neither in a graceful way.
   *
   * @param object which needs conversion
   * @return the JSON string representation of object
   */
  public String convert(Object object) {
    if (object == null) {
      return null;
    }

    try {
      JsonElement json = convertObject(object);
      return new GsonBuilder().disableHtmlEscaping().serializeNulls().create().toJson(json);
    } catch (Exception e) {
      throw new WebDriverException("Unable to convert: " + object, e);
    }
  }

  /**
   * Convert an object that may or may not be a JsonElement into its JSON object
   * representation, handling the case where it is neither in a graceful way.
   *
   * @param object which needs conversion
   * @return the JSON object representation of object
   */
  public JsonElement convertObject(Object object) {
    if (object == null) {
      return JsonNull.INSTANCE;
    }

    try {
      return convertObject(object, MAX_DEPTH);
    } catch (Exception e) {
      throw new WebDriverException("Unable to convert: " + object, e);
    }
  }

  @SuppressWarnings("unchecked")
  private JsonElement convertObject(Object toConvert, int maxDepth) throws Exception {
    if (toConvert == null) {
      return JsonNull.INSTANCE;
    }

    if (toConvert instanceof Boolean) {
      return new JsonPrimitive((Boolean) toConvert);
    }

    if (toConvert instanceof CharSequence) {
      return new JsonPrimitive(String.valueOf(toConvert));
    }

    if (toConvert instanceof Number) {
      return new JsonPrimitive((Number) toConvert);
    }

    if (toConvert instanceof Level) {
      return new JsonPrimitive(LogLevelMapping.getName((Level) toConvert));
    }

    if (toConvert.getClass().isEnum() || toConvert instanceof Enum) {
      return new JsonPrimitive(toConvert.toString());
    }

    if (toConvert instanceof LoggingPreferences) {
      LoggingPreferences prefs = (LoggingPreferences) toConvert;
      JsonObject converted = new JsonObject();
      for (String logType : prefs.getEnabledLogTypes()) {
        converted.addProperty(logType, LogLevelMapping.getName(prefs.getLevel(logType)));
      }
      return converted;
    }

    if (toConvert instanceof SessionLogs) {
      return convertObject(((SessionLogs)toConvert).getAll(), maxDepth - 1);
    }

    if (toConvert instanceof LogEntries) {
      return convertObject(((LogEntries)toConvert).getAll(), maxDepth - 1);
    }

    if (toConvert instanceof Map) {
      Map map = (Map) toConvert;
      if (map.size() == 1 && map.containsKey("w3c cookie")) {
        return convertObject(map.get("w3c cookie"));
      }

      JsonObject converted = new JsonObject();
      for (Map.Entry entry : map.entrySet()) {
        converted.add(entry.getKey(), convertObject(entry.getValue(), maxDepth - 1));
      }
      return converted;
    }

    if (toConvert instanceof JsonElement) {
      return (JsonElement) toConvert;
    }

    if (toConvert instanceof Collection) {
      JsonArray array = new JsonArray();
      for (Object o : (Collection) toConvert) {
        array.add(convertObject(o, maxDepth - 1));
      }
      return array;
    }

    if (toConvert.getClass().isArray()) {
      JsonArray converted = new JsonArray();
      int length = Array.getLength(toConvert);
      for (int i = 0; i < length; i++) {
        converted.add(convertObject(Array.get(toConvert, i), maxDepth - 1));
      }
      return converted;
    }

    if (toConvert instanceof SessionId) {
      JsonObject converted = new JsonObject();
      converted.addProperty("value", toConvert.toString());
      return converted;
    }

    if (toConvert instanceof Date) {
      return new JsonPrimitive(TimeUnit.MILLISECONDS.toSeconds(((Date) toConvert).getTime()));
    }

    if (toConvert instanceof File) {
      return new JsonPrimitive(((File) toConvert).getAbsolutePath());
    }

    Method toMap = getMethod(toConvert, "toMap");
    if (toMap == null) {
      toMap = getMethod(toConvert, "asMap");
    }
    if (toMap != null) {
      try {
        return convertObject(toMap.invoke(toConvert), maxDepth - 1);
      } catch (IllegalArgumentException e) {
        throw new WebDriverException(e);
      } catch (IllegalAccessException e) {
        throw new WebDriverException(e);
      } catch (InvocationTargetException e) {
        throw new WebDriverException(e);
      }
    }

    Method toList = getMethod(toConvert, "toList");
    if (toList == null) {
      toList = getMethod(toConvert, "asList");
    }
    if (toList != null) {
      try {
        return convertObject(toList.invoke(toConvert), maxDepth - 1);
      } catch (IllegalArgumentException e) {
        throw new WebDriverException(e);
      } catch (IllegalAccessException e) {
        throw new WebDriverException(e);
      } catch (InvocationTargetException e) {
        throw new WebDriverException(e);
      }
    }

    Method toJson = getMethod(toConvert, "toJson");
    if (toJson != null) {
      try {
        Object res = toJson.invoke(toConvert);
        if (res instanceof JsonElement) {
          return (JsonElement) res;
        }
        try {
          return new JsonParser().parse((String) res);
        } catch (JsonParseException e) {
          return new JsonPrimitive((String) res);
        }
      } catch (IllegalArgumentException e) {
        throw new WebDriverException(e);
      } catch (IllegalAccessException e) {
        throw new WebDriverException(e);
      } catch (InvocationTargetException e) {
        throw new WebDriverException(e);
      }
    }

    try {
      return mapObject(toConvert, maxDepth - 1, toConvert instanceof Cookie);
    } catch (Exception e) {
      throw new WebDriverException(e);
    }
  }

  private Method getMethod(Object toConvert, String methodName) {
    try {
      return toConvert.getClass().getMethod(methodName);
    } catch (SecurityException e) {
      // fall through
    } catch (NoSuchMethodException e) {
      // fall through
    }

    return null;

  }

  private JsonElement mapObject(Object toConvert, int maxDepth, boolean skipNulls) throws Exception {
    if (maxDepth < 1) {
      return JsonNull.INSTANCE;
    }

    // Raw object via reflection? Nope, not needed
    JsonObject mapped = new JsonObject();
    for (SimplePropertyDescriptor pd : SimplePropertyDescriptor
        .getPropertyDescriptors(toConvert.getClass())) {
      if ("class".equals(pd.getName())) {
        mapped.addProperty("class", toConvert.getClass().getName());
        continue;
      }

      Method readMethod = pd.getReadMethod();
      if (readMethod == null) {
        continue;
      }

      if (readMethod.getParameterTypes().length > 0) {
        continue;
      }

      readMethod.setAccessible(true);

      Object result = readMethod.invoke(toConvert);
      if (!skipNulls || result != null) {
        mapped.add(pd.getName(), convertObject(result, maxDepth - 1));
      }
    }

    return mapped;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy