Package org.platformlayer.ops

Source Code of org.platformlayer.ops.ServiceProviderBase

package org.platformlayer.ops;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.security.PublicKey;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import org.platformlayer.core.model.Action;
import org.platformlayer.core.model.Generate;
import org.platformlayer.core.model.ItemBase;
import org.platformlayer.core.model.PlatformLayerKey;
import org.platformlayer.core.model.Secret;
import org.platformlayer.core.model.ServiceInfo;
import org.platformlayer.ids.ItemType;
import org.platformlayer.ids.ServiceType;
import org.platformlayer.inject.ObjectInjector;
import org.platformlayer.metrics.model.MetricDataSource;
import org.platformlayer.metrics.model.MetricQuery;
import org.platformlayer.ops.crypto.Passwords;
import org.platformlayer.ops.helpers.ServiceContext;
import org.platformlayer.ops.helpers.SshKey;
import org.platformlayer.ops.metrics.MetricFetcher;
import org.platformlayer.xaas.Controller;
import org.platformlayer.xaas.Service;
import org.platformlayer.xaas.discovery.AnnotatedClass;
import org.platformlayer.xaas.discovery.AnnotationDiscovery;
import org.platformlayer.xaas.model.ServiceAuthorization;
import org.platformlayer.xaas.services.ModelClass;
import org.platformlayer.xaas.services.Models;
import org.platformlayer.xaas.services.ServiceProvider;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.inject.Injector;

public abstract class ServiceProviderBase implements ServiceProvider {
  private final ServiceType serviceType;

  private final String description;

  @Inject
  AnnotationDiscovery discovery;

  @Inject
  protected ObjectInjector injector;

  @Inject
  CloudContextRegistry cloudContextRegistry;

  public ServiceProviderBase() {
    Service serviceAnnotation = getServiceAnnotation();

    String key = serviceAnnotation.value();

    // this.serviceType = serviceType;
    this.description = key;
    this.serviceType = new ServiceType(key);
  }

  Models models;

  @Override
  public Models getModels() {
    if (models == null) {
      models = new Models(buildModels());
    }
    return models;
  }

  protected List<ModelClass<?>> buildModels() {
    List<ModelClass<?>> modelClasses = Lists.newArrayList();
    for (AnnotatedClass clazz : discovery.findAnnotatedClasses(Controller.class)) {
      ModelClass<?> modelClass = asModelClass((Class<? extends ItemBase>) clazz.getSubjectClass());
      if (modelClass != null) {
        modelClasses.add(modelClass);
      }
    }
    return modelClasses;
  }

  private Service getServiceAnnotation() {
    return getClass().getAnnotation(Service.class);
  }

  @Override
  public ServiceType getServiceType() {
    return serviceType;
  }

  @Override
  public ServiceInfo getServiceInfo() {
    ServiceInfo serviceInfo = new ServiceInfo();
    serviceInfo.serviceType = getServiceType().getKey();
    serviceInfo.description = description;
    // serviceInfo.schema =

    for (ModelClass<?> modelClass : getModels().all()) {
      ItemType itemType = modelClass.getItemType();

      if (serviceInfo.getNamespace() == null) {
        serviceInfo.namespace = modelClass.getPrimaryNamespace();
      }

      if (serviceInfo.itemTypes == null) {
        serviceInfo.itemTypes = Lists.newArrayList();
      }
      serviceInfo.itemTypes.add(itemType.getKey());
    }

    return serviceInfo;
  }

  @Override
  public void initialize() {
  }

  @Override
  public void beforeCreateItem(ItemBase item) throws OpsException {
    resolveKeys(item);

    autoPopulate(item);

    CreationValidator validator = Injection.getInstance(CreationValidator.class);
    validator.validateCreateItem(item);
  }

  @Override
  public void beforeDeleteItem(ItemBase managedItem) throws OpsException {
  }

  protected ModelClass<?> asModelClass(Class<? extends ItemBase> clazz) {
    Class<? extends ServiceProviderBase> myClass = getClass();
    Package myPackage = myClass.getPackage();

    Package clazzPackage = clazz.getPackage();

    // TODO: This is a bit hacky..
    String packagePrefix = myPackage.getName() + ".";
    if (!clazzPackage.getName().startsWith(packagePrefix)) {
      return null;
    }

    Controller modelAnnotation = clazz.getAnnotation(Controller.class);
    if (modelAnnotation == null) {
      return null;
    }

    return ModelClass.publicModel(this, clazz);
  }

  @Override
  public void validateAuthorization(ServiceAuthorization serviceAuthorization) throws OpsException {
    CloudContext cloudContext = cloudContextRegistry.getCloudContext();
    cloudContext.validate();
  }

  @Override
  public Object getController(Class<?> managedItemClass) throws OpsException {
    Class<?> controllerClass = getControllerClass(managedItemClass);

    ensureInitialized();

    return injector.getInstance(controllerClass);
  }

  @Override
  public Object getController(Object item) throws OpsException {
    Class<?> managedItemClass = item.getClass();

    Class<?> controllerClass = getControllerClass(managedItemClass);

    ensureInitialized();

    Object controller = injector.getInstance(controllerClass);

    Injector guiceInjector = injector.getInstance(Injector.class);

    Map<Class<?>, Object> prebound = Maps.newHashMap();
    prebound.put(item.getClass(), item);

    BindingHelper helper = new BindingHelper(guiceInjector, prebound);
    helper.bind(controller);

    return controller;
  }

  @Override
  public Class<?> getControllerClass(Class<?> managedItemClass) throws OpsException {
    Controller controller = managedItemClass.getAnnotation(Controller.class);
    if (controller == null) {
      throw new IllegalArgumentException("No @Controller annotation found for " + managedItemClass.getName());
    }

    ensureInitialized();

    return controller.value();
  }

  boolean initialized;

  protected void ensureInitialized() throws OpsException {
    if (initialized) {
      return;
    }

    ServiceInitializer initializer = injector.getInstance(ServiceInitializer.class);
    initializer.initialize(this);

    initialized = true;
  }

  @Override
  public MetricDataSource getMetricValues(ItemBase item, MetricQuery query) throws OpsException {
    MetricFetcher metricFetcher = injector.getInstance(MetricFetcher.class);
    return metricFetcher.fetch(this, item, query);
  }

  @Override
  public Class<?> getJavaClass(ItemType itemType) {
    ModelClass<?> modelClass = findModelClass(itemType);
    if (modelClass == null) {
      return null;
    }

    return modelClass.getJavaClass();
  }

  @Override
  public ModelClass<?> getModelClass(ItemType itemType) {
    ModelClass<?> modelClass = findModelClass(itemType);
    return modelClass;
  }

  private ModelClass<?> findModelClass(ItemType itemType) {
    for (ModelClass<?> modelClass : getModels().all()) {
      if (!itemType.equals(modelClass.getItemType())) {
        continue;
      }

      return modelClass;
    }
    return null;
  }

  @Override
  public PublicKey getSshPublicKey() throws OpsException {
    ServiceContext serviceContext = injector.getInstance(ServiceContext.class);

    SshKey sshKey = serviceContext.getSshKey();
    if (sshKey == null) {
      return null;
    }
    PublicKey publicKey = sshKey.getKeyPair().getPublic();
    return publicKey;
  }

  public void resolveKeys(Object item) throws OpsException {
    Class<? extends Object> itemClass = item.getClass();
    for (Field field : itemClass.getFields()) {
      Class<?> fieldType = field.getType();

      if (fieldType == PlatformLayerKey.class) {
        PlatformLayerKey key;
        try {
          key = (PlatformLayerKey) field.get(item);
        } catch (IllegalAccessException e) {
          throw new IllegalStateException("Error getting field: " + field, e);
        }

        if (key != null) {
          PlatformLayerKey newKey = resolveKey(key);

          if (newKey != key) {
            try {
              field.set(item, newKey);
            } catch (IllegalAccessException e) {
              throw new IllegalStateException("Error setting field: " + field, e);
            }
          }
        }
      }

      if (fieldType == List.class) {
        Type genericFieldType = field.getGenericType();

        if (genericFieldType instanceof ParameterizedType) {
          ParameterizedType aType = (ParameterizedType) genericFieldType;
          Type[] fieldArgTypes = aType.getActualTypeArguments();
          if (fieldArgTypes.length == 1) {
            Type fieldArgType = fieldArgTypes[0];
            if (fieldArgType instanceof Class) {
              Class fieldArg = (Class) fieldArgType;

              if (fieldArg.equals(PlatformLayerKey.class)) {
                List<PlatformLayerKey> list;
                try {
                  list = (List<PlatformLayerKey>) field.get(item);
                } catch (IllegalAccessException e) {
                  throw new IllegalStateException("Error getting field: " + field, e);
                }
                if (list != null) {
                  for (int i = 0; i < list.size(); i++) {
                    PlatformLayerKey key = list.get(i);
                    PlatformLayerKey newKey = resolveKey(key);

                    if (newKey != key) {
                      list.set(i, newKey);
                    }
                  }

                  try {
                    field.set(item, list);
                  } catch (IllegalAccessException e) {
                    throw new IllegalStateException("Error setting field: " + field, e);
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  private PlatformLayerKey resolveKey(PlatformLayerKey key) throws OpsException {
    if (key.getServiceType() == null) {
      ItemType itemType = key.getItemType();
      ServiceType serviceType = OpsContext.get().getOpsSystem().getServiceType(itemType);
      key = key.withServiceType(serviceType);
    }

    if (key.getProject() == null) {
      key = key.withProject(OpsContext.get().getPlatformLayerClient().getProject());
    }

    return key;
  }

  public void autoPopulate(Object item) throws OpsException {
    Class<? extends Object> itemClass = item.getClass();
    for (Field field : itemClass.getFields()) {
      Generate defaultAnnotation = field.getAnnotation(Generate.class);

      if (defaultAnnotation != null) {
        Class<?> fieldType = field.getType();

        Object value;
        try {
          value = field.get(item);
        } catch (IllegalAccessException e) {
          throw new IllegalStateException("Error getting field: " + field, e);
        }

        if (value == null) {
          String defaultValue = defaultAnnotation.value();
          if (!Strings.isNullOrEmpty(defaultValue)) {
            value = defaultValue;
          } else {
            if (fieldType == Secret.class) {
              Passwords passwords = new Passwords();

              Secret secret = passwords.generateRandomPassword(12);
              value = secret;

            }
          }

          if (value != null) {
            try {
              field.set(item, value);
            } catch (IllegalAccessException e) {
              throw new IllegalStateException("Error setting field: " + field, e);
            }
          }
        }
      }
    }
  }

  @Override
  public List<Class<? extends Action>> getActions() {
    return Collections.emptyList();
  }

  @Override
  public Object getExtensionResource() {
    return null;
  }

  @Override
  public Object getItemExtensionResource(Object item) throws OpsException {
    Object controller = getController(item);
    if (controller instanceof HasResource) {
      return ((HasResource) controller).getItemExtensionResource();
    }
    return null;
  }

  @Override
  public String buildItemId(ModelClass<?> modelClass, ItemBase item) {
    String id = modelClass.getItemType().getKey();
    return id;
  }
}
TOP

Related Classes of org.platformlayer.ops.ServiceProviderBase

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.