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

io.alauda.kubernetes.client.utils.Serialization Maven / Gradle / Ivy

/**
 * Copyright (C) 2018 Alauda
 *
 * 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 io.alauda.kubernetes.client.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import io.alauda.kubernetes.api.model.KubernetesResource;
import io.alauda.kubernetes.client.KubernetesClientException;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Serialization {

  private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
  private static final ObjectMapper YAML_MAPPER = new ObjectMapper(new YAMLFactory());
  private static final String DOCUMENT_DELIMITER = "---";

  public static ObjectMapper jsonMapper() {
    return JSON_MAPPER;
  }

  public static ObjectMapper yamlMapper() {
    return YAML_MAPPER;
  }

  public static  String asJson(T object) throws KubernetesClientException {
    try {
      return JSON_MAPPER.writeValueAsString(object);
    } catch (JsonProcessingException e) {
      throw KubernetesClientException.launderThrowable(e);
    }
  }

  public static  String asYaml(T object) throws KubernetesClientException {
    try {
      return YAML_MAPPER.writeValueAsString(object);
    } catch (JsonProcessingException e) {
      throw KubernetesClientException.launderThrowable(e);
    }
  }

  /**
   * Unmarshals a stream.
   * @param is    The {@link InputStream}.
   * @param    The target type.
   * @return
   * @throws KubernetesClientException
   */
  public static  T unmarshal(InputStream is) throws KubernetesClientException {
    return unmarshal(is, JSON_MAPPER);
  }

  /**
   * Unmarshals a stream optionally performing placeholder substitution to the stream.
   * @param is    The {@link InputStream}.
   * @param parameters  A {@link Map} with parameters for placeholder substitution.
   * @param    The target type.
   * @return
   * @throws KubernetesClientException
   */
  public static  T unmarshal(InputStream is, Map parameters) throws KubernetesClientException {
    String specFile = readSpecFileFromInputStream(is);
    if (containsMultipleDocuments(specFile)) {
      return (T) getKubernetesResourceList(parameters, specFile);
    }
    return unmarshal(new ByteArrayInputStream(specFile.getBytes()), JSON_MAPPER, parameters);
  }

  /**
   * Unmarshals a stream.
   * @param is      The {@link InputStream}.
   * @param mapper  The {@link ObjectMapper} to use.
   * @param      The target type.
   * @return
   * @throws KubernetesClientException
   */
  public static  T unmarshal(InputStream is, ObjectMapper mapper) {
   return unmarshal(is, mapper, Collections.emptyMap());
  }

  /**
   * Unmarshals a stream optionally performing placeholder substitution to the stream.
   * @param is          The {@link InputStream}.
   * @param mapper      The {@link ObjectMapper} to use.
   * @param parameters  A {@link Map} with parameters for placeholder substitution.
   * @param          The target type.
   * @return
   * @throws KubernetesClientException
   */
  public static  T unmarshal(InputStream is, ObjectMapper mapper, Map parameters) {
    try (BufferedInputStream bis = new BufferedInputStream(is)) {
      bis.mark(-1);
      int intch;
      do {
        intch = bis.read();
      } while (intch > -1 && Character.isWhitespace(intch));
      bis.reset();

      if (intch != '{') {
        mapper = YAML_MAPPER;
      }
      return mapper.readerFor(KubernetesResource.class).readValue(bis);
    } catch (IOException e) {
      throw KubernetesClientException.launderThrowable(e);
    }
  }

  /**
   * Unmarshals a {@link String}
   * @param str   The {@link String}.
   * @param type  The target type.
   * @param 
   * @return
   * @throws KubernetesClientException
   */
  public static  T unmarshal(String str, final Class type) throws KubernetesClientException {
    return unmarshal(str, type, Collections.emptyMap());
  }

  /**
   * Unmarshals a {@link String} optionally performing placeholder substitution to the String.
   * @param str   The {@link String}.
   * @param type  The target type.
   * @param 
   * @return
   * @throws KubernetesClientException
     */
  public static  T unmarshal(String str, final Class type, Map parameters) throws KubernetesClientException {
    try (InputStream is = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));) {
      return unmarshal(is, new TypeReference() {
        @Override
        public Type getType() {
          return type;
        }
      }, parameters);
    } catch (IOException e) {
      throw KubernetesClientException.launderThrowable(e);
    }
  }

  /**
   * Unmarshals an {@link InputStream}.
   * @param is              The {@link InputStream}.
   * @param type            The type.
   * @param 
   * @return
   * @throws KubernetesClientException
   */
  public static  T unmarshal(InputStream is, final Class type) throws KubernetesClientException {
    return unmarshal(is, type, Collections.emptyMap());
  }

  /**
   * Unmarshals an {@link InputStream} optionally performing placeholder substitution to the stream.
   * @param is              The {@link InputStream}.
   * @param type            The type.
   * @param parameters      A {@link Map} with parameters for placeholder substitution.
   * @param 
   * @return
   * @throws KubernetesClientException
   */
  public static  T unmarshal(InputStream is, final Class type, Map parameters) throws KubernetesClientException {
    return unmarshal(is, new TypeReference() {
      @Override
      public Type getType() {
        return type;
      }
    }, parameters);
  }


  /**
   * Unmarshals an {@link InputStream}.
   * @param is            The {@link InputStream}.
   * @param type          The {@link TypeReference}.
   * @param 
   * @return
   * @throws KubernetesClientException
   */
  public static  T unmarshal(InputStream is, TypeReference type) throws KubernetesClientException {
   return unmarshal(is, type, Collections.emptyMap());
  }

  /**
   * Unmarshals an {@link InputStream} optionally performing placeholder substitution to the stream.
   *
   * @param is            The {@link InputStream}.
   * @param type          The {@link TypeReference}.
   * @param parameters    A {@link Map} with parameters for placeholder substitution.
   * @param 
   * @return
   * @throws KubernetesClientException
   */
  public static  T unmarshal(InputStream is, TypeReference type, Map parameters) throws KubernetesClientException {
    InputStream wrapped = parameters != null && !parameters.isEmpty() ? new ReplaceValueStream(parameters).createInputStream(is) : is;
    try (BufferedInputStream bis = new BufferedInputStream(wrapped)) {
      bis.mark(-1);
      int intch;
      do {
        intch = bis.read();
      } while (intch > -1 && Character.isWhitespace(intch));
      bis.reset();

      ObjectMapper mapper = JSON_MAPPER;
      if (intch != '{') {
        mapper = YAML_MAPPER;
      }
      return mapper.readValue(bis, type);
    } catch (IOException e) {
      throw KubernetesClientException.launderThrowable(e);
    }
  }


  private static List getKubernetesResourceList(Map parameters, String specFile) {
    List documentList = new ArrayList<>();
    String[] documents = specFile.split(DOCUMENT_DELIMITER);
    for (String document : documents) {
      if (validate(document)) {
        ByteArrayInputStream documentInputStream = new ByteArrayInputStream(document.getBytes());
        Object resource = Serialization.unmarshal(documentInputStream, parameters);
        documentList.add((KubernetesResource) resource);
      }
    }
    return documentList;
  }

  private static boolean containsMultipleDocuments(String specFile) {
    Pattern p = Pattern.compile(DOCUMENT_DELIMITER);
    Matcher m = p.matcher(specFile);
    int count = 0;
    while (m.find()) {
      count++;
    }
    if (count == 1) {
      String[] documents = specFile.split(DOCUMENT_DELIMITER);
      return validate(documents[0]);
    }
    return count > 1;
  }

  private static boolean validate(String document) {
    Matcher keyValueMatcher = Pattern.compile("(\\S+):\\s(\\S*)(?:\\b(?!:)|$)").matcher(document);
    return !document.isEmpty() && keyValueMatcher.find();
  }

  private static String readSpecFileFromInputStream(InputStream inputStream) {
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int length;
    try {
      while ((length = inputStream.read(buffer)) != -1) {
        outputStream.write(buffer, 0, length);
      }
      return outputStream.toString();
    } catch (IOException e) {
      throw new RuntimeException("Unable to read InputStream." + e);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy