
org.appops.service.entrypoint.ServiceEntryPoint Maven / Gradle / Ivy
/*
* AppOps is a Java framework to develop, deploy microservices with ease and is available for free
* and common use developed by AinoSoft ( www.ainosoft.com )
*
* AppOps and AinoSoft are registered trademarks of Aino Softwares private limited, India.
*
* Copyright (C) <2016>
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version along with applicable additional terms as
* provisioned by GPL 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License and applicable additional terms
* along with this program.
*
* If not, see and
*/
package org.appops.service.entrypoint;
import java.io.File;
import java.lang.annotation.Annotation;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.appops.configuration.ModuleConfig;
import org.appops.configuration.guice.ConfigServiceModule;
import org.appops.configuration.loader.ConfigurationLoader;
import org.appops.configuration.slimimpl.SlimImplStructure;
import org.appops.configuration.store.ConfigurationStore;
import org.appops.configuration.store.CurrentRunningServiceContext;
import org.appops.core.ClassPathAnalyser;
import org.appops.core.ServiceException;
import org.appops.core.deployment.DeploymentMode;
import org.appops.core.deployment.ServiceConfiguration;
import org.appops.core.service.meta.ServiceMeta;
import org.appops.marshaller.DescriptorType;
import org.appops.marshaller.Marshaller;
import org.appops.marshaller.guice.MarshallerModule;
import org.appops.service.ServiceInitializer;
import org.appops.service.deployment.ServiceJettyLauncher;
import org.appops.service.exception.AppEntryPointException;
import org.appops.service.exception.DeploymentException;
import org.appops.service.injection.ServiceBaseModule;
import org.appops.web.jetty.JettyWebServiceModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.name.Names;
/**
*
* ServiceEntryPoint class.
*
*
*/
public class ServiceEntryPoint {
private static Injector BASE_INJECTOR = null;
/**
* Process raw arguments to select profile to use and to replace other configurations from command
* line.
*
* @param args an array of {@link java.lang.String} objects.
* @throws org.appops.core.ServiceException if any.
*/
public void startService(String[] args) throws ServiceException {
startService(new ServiceArgs(args));
}
/**
* Read actual configurations and prepare modules to bind
*
* @param serviceArgs a {@link org.appops.service.entrypoint.ServiceArgs} object.
*/
protected void startService(ServiceArgs serviceArgs) {
try {
createBaseInjector();
String configString =
FileUtils.readFileToString(serviceArgs.getServiceConfig(), StandardCharsets.UTF_8);
Marshaller marshaller = BASE_INJECTOR.getInstance(Marshaller.class);
DescriptorType descriptorType =
DescriptorType.fromExtension(serviceArgs.getServiceConfig().getName());
ServiceConfiguration serviceConfiguration =
marshaller.unmarshall(configString, ServiceConfiguration.class, descriptorType);
String serviceDeploymentMode = serviceArgs.getDeploymentMode();
setDeployementMode(serviceDeploymentMode, serviceConfiguration);
String depConfigLight =
marshaller.marshall(serviceConfiguration.lightweightCopy(), descriptorType);
ConfigurationStore configurationStore = BASE_INJECTOR.getInstance(ConfigurationStore.class);
configurationStore.addConfiguration(ServiceConfiguration.class.getCanonicalName(),
depConfigLight, descriptorType);
String profileName = serviceArgs.getSelectedProfileName();
String profileRoot = serviceArgs.getProfileRoot();
File folder = new File(profileRoot + profileName);
File[] listOfFiles = folder.listFiles();
HashMap serviceConfigMap = new HashMap<>();
for (File file : listOfFiles) {
if (file.isDirectory()) {
String slimImplServiceName = file.getName();
boolean isCoreService = false;
if (serviceConfiguration.getServiceName().equals(slimImplServiceName)) {
isCoreService = true;
}
File[] files = file.listFiles();
for (File slimImplconfigfile : files) {
String configFileName = slimImplconfigfile.getName();
if (isYamlFile(configFileName)) {
if (isCoreService) {
populateServiceConfiguration(marshaller, slimImplconfigfile, serviceConfiguration,
serviceConfigMap);
} else if (serviceDeploymentMode.equalsIgnoreCase(DeploymentMode.CLUBBED.toString())
&& isImplYml(configFileName)) {
populateClubbedConfiguration(marshaller, slimImplconfigfile, slimImplServiceName,
serviceConfigMap, serviceConfiguration.getMode());
} else if (serviceDeploymentMode.equalsIgnoreCase(
DeploymentMode.STANDALONE.toString()) && !isImplYml(configFileName)) {
populateStandaloneConfiguration(marshaller, slimImplconfigfile, slimImplServiceName,
serviceConfigMap, serviceConfiguration.getMode());
}
}
}
}
}
Injector appInjector = createAppInjector(BASE_INJECTOR, serviceConfigMap,
serviceConfiguration.getMode(), serviceConfiguration);
initializeServices(serviceConfigMap, appInjector, serviceConfiguration, profileName,
profileRoot);
ServiceJettyLauncher appLauncher = appInjector.getInstance(ServiceJettyLauncher.class);
System.setProperty("currentProfile", profileName);
System.setProperty("baseUrl", serviceConfiguration.serviceUrl());
appLauncher.launch(serviceConfiguration);
} catch (Exception e) {
throw new AppEntryPointException(e);
}
}
/**
* It checks given file is yaml file or not and return appropriate result.
*
* @param configFileName configuration file name
* @return true, if file yaml file otherwise false
*/
private boolean isYamlFile(String configFileName) {
if (configFileName.endsWith(".yml") || configFileName.endsWith(".yaml")) {
return true;
}
return false;
}
/**
* It populates the given instance of {@link ServiceConfiguration} using given file.
*
* @param marshaller instance of {@link Marshaller}
* @param slimImplconfigfile instance of file contains service slim or impl configuration
* @param serviceConfiguration instance of {@link ServiceConfiguration}
* @param serviceConfigMap map of service name vs it's configuration
* @throws Exception
*/
private void populateServiceConfiguration(Marshaller marshaller, File slimImplconfigfile,
ServiceConfiguration serviceConfiguration,
HashMap serviceConfigMap) throws Exception {
try {
String serviceconfigString =
FileUtils.readFileToString(slimImplconfigfile, StandardCharsets.UTF_8);
DescriptorType configDescriptorType =
DescriptorType.fromExtension(slimImplconfigfile.getName());
SlimImplStructure slimImplConfig =
marshaller.unmarshall(serviceconfigString, SlimImplStructure.class, configDescriptorType);
if (slimImplconfigfile.getName().endsWith("slim.yml")) {
serviceConfiguration.getModules().getSlimModules().addAll(slimImplConfig.getModules());
serviceConfigMap.put(serviceConfiguration.getServiceName(), serviceConfiguration);
} else if (slimImplconfigfile.getName().endsWith("impl.yml")) {
serviceConfiguration.getModules().getImplModules().addAll(slimImplConfig.getModules());
serviceConfigMap.put(serviceConfiguration.getServiceName(), serviceConfiguration);
}
} catch (Exception e) {
throw e;
}
}
/**
* It sets the service deployment mode to given {@link ServiceConfiguration} instance.
*
* @param serviceDeploymentMode service deployment mode
* @param serviceConfiguration instance of {@link ServiceConfiguration}
* @throws Exception if occurred between validating service deployment mode.
*/
private void setDeployementMode(String serviceDeploymentMode,
ServiceConfiguration serviceConfiguration) throws Exception {
try {
if (serviceDeploymentMode.equals(DeploymentMode.STANDALONE.name())) {
serviceConfiguration.setMode(DeploymentMode.STANDALONE);
} else if (serviceDeploymentMode.equals(DeploymentMode.CLUBBED.name())) {
serviceConfiguration.setMode(DeploymentMode.CLUBBED);
} else {
throw new ServiceException("Invalid Deployment Mode :" + serviceDeploymentMode);
}
} catch (Exception e) {
throw e;
}
}
/**
* It populates the configuration depending upon standalone mode.
*
* @param marshaller instance of {@link Marshaller}
* @param configfile configuration file
* @param slimConfigServiceName service name
* @param serviceConfigMap map of service name vs its configuration
* @param deploymentMode service deployment mode
* @throws Exception If occurred while populating the service configuration map.
*/
private void populateStandaloneConfiguration(Marshaller marshaller, File configfile,
String slimConfigServiceName, HashMap serviceConfigMap,
DeploymentMode deploymentMode) throws Exception {
try {
String serviceconfigString = FileUtils.readFileToString(configfile, StandardCharsets.UTF_8);
DescriptorType configDescriptorType = DescriptorType.fromExtension(configfile.getName());
SlimImplStructure slimImplConfig =
marshaller.unmarshall(serviceconfigString, SlimImplStructure.class, configDescriptorType);
ServiceConfiguration serviceConfiguration =
populateServiceConfiguration(slimImplConfig, slimConfigServiceName, deploymentMode);
serviceConfigMap.put(slimConfigServiceName, serviceConfiguration);
} catch (Exception e) {
throw e;
}
}
/**
* It populates the configuration depending upon clubbed mode.
*
* @param marshaller instance of {@link Marshaller}
* @param configfile configuration file
* @param implConfigServiceName service name
* @param serviceConfigMap map of service name vs its configuration
* @param deploymentMode service deployment mode
* @throws Exception If occurred while populating the service configuration map.
*/
private void populateClubbedConfiguration(Marshaller marshaller, File configfile,
String implConfigServiceName, HashMap serviceConfigMap,
DeploymentMode deploymentMode) throws Exception {
try {
String serviceconfigString = FileUtils.readFileToString(configfile, StandardCharsets.UTF_8);
DescriptorType configDescriptorType = DescriptorType.fromExtension(configfile.getName());
SlimImplStructure slimImplConfig =
marshaller.unmarshall(serviceconfigString, SlimImplStructure.class, configDescriptorType);
ServiceConfiguration serviceConfiguration =
populateServiceConfiguration(slimImplConfig, implConfigServiceName, deploymentMode);
serviceConfigMap.put(implConfigServiceName, serviceConfiguration);
} catch (Exception e) {
throw e;
}
}
/**
* It populates the {@link ServiceConfiguration} instance using given configuration and return it.
*
* @param slimImplConfig instance of {@link SlimImplStructure}
* @param slimImplServiceName service name of given config file
* @param deploymentMode service deployment mode
* @return populated instance of {@link ServiceConfiguration}
* @throws Exception If occurred between populating the {@link ServiceConfiguration} instance
*/
private ServiceConfiguration populateServiceConfiguration(SlimImplStructure slimImplConfig,
String slimImplServiceName, DeploymentMode deploymentMode) throws Exception {
try {
if (slimImplConfig != null) {
ServiceConfiguration serviceConfiguration = new ServiceConfiguration();
serviceConfiguration.setAnnotationClass(Class.forName(slimImplConfig.getAnnotationClass()));
serviceConfiguration.setServiceConfig(slimImplConfig.getConfig());
serviceConfiguration.setServiceName(slimImplServiceName);
if (deploymentMode.equals(DeploymentMode.STANDALONE)) {
ModuleConfig slimModduleConfig = new ModuleConfig();
slimModduleConfig.setSlimModules(slimImplConfig.getModules());
serviceConfiguration.setModules(slimModduleConfig);
} else if (deploymentMode.equals(DeploymentMode.CLUBBED)) {
ModuleConfig implModuleConfig = new ModuleConfig();
implModuleConfig.setImplModules(slimImplConfig.getModules());
serviceConfiguration.setModules(implModuleConfig);
} else {
throw new DeploymentException("Deployment mode not matched " + deploymentMode.name());
}
return serviceConfiguration;
}
} catch (Exception e) {
throw e;
}
return null;
}
/**
* It checks whether given config file name ends with impl or not and return appropriate result.
*
* @param configFileName configuration file name
* @return true, if file name ends with impl.yml otherwise false
*/
private boolean isImplYml(String configFileName) {
if (configFileName.endsWith("impl.yml")) {
return true;
}
return false;
}
/**
* @return base injector with core modules
*/
private static Injector createBaseInjector() {
if (BASE_INJECTOR == null) {
List modules = new ArrayList<>();
modules.add(new ConfigServiceModule());
modules.add(new MarshallerModule());
BASE_INJECTOR = Guice.createInjector(modules);
}
return BASE_INJECTOR;
}
/**
* Initializes the services.
*
* @param services services configuration
* @param appInjector app injector
* @param entryPointConfig service entry point configuration
* @param currentProfile current profile
* @param profileRoot profile root
*/
private void initializeServices(Map services, Injector appInjector,
ServiceConfiguration entryPointConfig, String currentProfile, String profileRoot) {
ClassPathAnalyser classPathAnalyser =
new ClassPathAnalyser(entryPointConfig.getPackageToScan());
Collection> initializers =
classPathAnalyser.subTypesOf(ServiceInitializer.class);
String currentService = entryPointConfig.getServiceName();
String baseConfigPath = profileRoot + currentProfile;
try {
initializeService(currentService, entryPointConfig, appInjector, initializers, baseConfigPath,
entryPointConfig.getMode(), true);
for (String serviceName : services.keySet()) {
if (serviceName.contentEquals(currentService)) {
continue;
}
ServiceConfiguration config = services.get(serviceName);
initializeService(serviceName, config, appInjector, initializers, baseConfigPath,
entryPointConfig.getMode(), false);
}
} catch (Exception e) {
throw e;
}
}
/**
* It Initialize the service using given service configuration.
*
* @param serviceName name of the service
* @param config instance of {@link ServiceConfiguration}
* @param appInjector app injector
* @param initializers service initializers
* @param baseConfigPath base config path
* @param deploymentMode mode of deployment
* @param isCurrentService is the service is running service or not
*/
private static void initializeService(String serviceName, ServiceConfiguration config,
Injector appInjector, Collection> initializers,
String baseConfigPath, DeploymentMode deploymentMode, boolean isCurrentService) {
baseConfigPath = baseConfigPath.endsWith("/") ? baseConfigPath : baseConfigPath + "/";
File ymlConfig = new File(baseConfigPath + serviceName + "/");
if (ymlConfig.exists()) {
if (ymlConfig.isDirectory()) {
loadConfig(serviceName, ymlConfig, appInjector, deploymentMode, isCurrentService);
} else {
System.out.println("Warning : Configuration for " + serviceName
+ " does not exist on path -> " + ymlConfig.getPath());
}
}
Class extends Annotation> serviceAnnotation =
(Class extends Annotation>) config.getAnnotationClass();
for (Class extends ServiceInitializer> initializer : initializers) {
if (initializer.isAnnotationPresent(serviceAnnotation)) {
appInjector.getInstance(CurrentRunningServiceContext.class).setCurrentRunningService(serviceName);
appInjector.getInstance(initializer).initialize(serviceName, config, serviceAnnotation);
initializers.remove(initializer);
break;
}
}
}
/**
* Load the configuration into {@link ConfigurationStore}
*
* @param serviceName name of the service
* @param ymlConfig configuration file path
* @param appInjector app injector
* @param deploymentMode mode of deployment
* @param isCurrentService is the service is running service or not
*/
private static void loadConfig(String serviceName, File ymlConfig, Injector appInjector,
DeploymentMode deploymentMode, boolean isCurrentService) {
for (File ymlFile : ymlConfig.listFiles()) {
if (DeploymentMode.STANDALONE.equals(deploymentMode) && !isCurrentService
&& ymlFile.getName().contentEquals("impl.yml"))
continue;
appInjector.getInstance(ConfigurationLoader.class).loadConfigurationsFromFile(serviceName,
ymlFile);
}
}
/**
* It creates the app injector using given entry poine and other service configuration and return
* it.
*
* @param BASE_INJECTOR base injector
* @param services service and its configuration
* @param mode deployment mode
* @param entryPoint entry point service configuration
* @return populated app injector
*/
private static Injector createAppInjector(Injector BASE_INJECTOR,
Map services, DeploymentMode mode,
ServiceConfiguration entryPoint) {
ModuleConfig finalConfig = new ModuleConfig();
for (String serviceName : services.keySet()) {
if (!entryPoint.getServiceName().equals(serviceName)) {
finalConfig.merge(services.get(serviceName).getModules());
}
}
Set finalModules = new LinkedHashSet<>();
finalModules.addAll(finalConfig.enabledModules(mode));
finalModules.addAll(getEntryPointServiceModules(entryPoint));
finalModules.add(new ServiceBaseModule());
finalModules.add(new JettyWebServiceModule());
return BASE_INJECTOR.createChildInjector(finalModules);
}
/**
* It returns the module list from given service configuration.
*
* @param entryPoint entry point of configurations
* @return modules list from given entry point
*/
private static Collection extends Module> getEntryPointServiceModules(
ServiceConfiguration entryPoint) {
ModuleConfig moduleConfig = entryPoint.getModules();
return moduleConfig.instantiateModules(moduleConfig.getImplModules(), null);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy