
org.appops.maven.plugin.mojo.ConfigGeneratorMojo Maven / Gradle / Ivy
package org.appops.maven.plugin.mojo;
import com.google.common.collect.Table;
/*
* 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
*/
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.appops.configuration.guice.ConfigServiceModule;
import org.appops.configuration.slimimpl.SlimImplConfigTable;
import org.appops.configuration.slimimpl.SlimImplIdentifier;
import org.appops.configuration.slimimpl.SlimImplStructure;
import org.appops.core.ClassPathAnalyser;
import org.appops.core.TypeScanner;
import org.appops.core.annotation.Config;
import org.appops.core.annotation.CoreConfig;
import org.appops.core.annotation.Slim;
import org.appops.core.constant.ConfigType;
import org.appops.core.deployment.ServiceConfiguration;
import org.appops.core.service.annotation.Service;
import org.appops.marshaller.DescriptorType;
import org.appops.marshaller.Marshaller;
import org.appops.marshaller.guice.MarshallerModule;
import org.appops.maven.plugin.helper.MojoHelper;
/**
* Appops maven plugin which generate appops service configuration using configuration parameters
* provided.
*/
@Mojo(name = "gen-config", requiresDependencyResolution = ResolutionScope.RUNTIME)
public class ConfigGeneratorMojo extends AbstractMojo {
@Parameter(required = true, alias = "profileRoot")
private String profileRoot = "env-config/";
@Parameter(defaultValue = "${project}", required = true)
private MavenProject project;
@Parameter(required = true)
private String serviceAnnotation;
private Injector injector;
private Marshaller marshaller;
private ClassPathAnalyser classPathAnalyser;
private URLClassLoader classLoader;
/**
* Default constructor.
*/
public ConfigGeneratorMojo() {
injector = createGuiceInjector();
marshaller = injector.getInstance(Marshaller.class);
if (!profileRoot.endsWith(File.separator)) {
profileRoot += File.separator;
}
}
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
try {
classLoader = new MojoHelper().getClassLoader(project);
Thread.currentThread().setContextClassLoader(classLoader);
classPathAnalyser = new ClassPathAnalyser(classLoader);
classPathAnalyser.setTypeScanner(new TypeScanner());
Set> configClasses = classPathAnalyser.getAnnotatedTypes(Config.class);
SlimImplConfigTable table = new SlimImplConfigTable();
for (Class> clazz : configClasses) {
if (!clazz.isAnnotation()) {
SlimImplIdentifier slimImplConfig = analyzeAnnotations(clazz.getAnnotations());
String configJson = marshaller.marshall(clazz.newInstance(), DescriptorType.YML);
table.addConfiguration(slimImplConfig.getServiceName(), slimImplConfig.getConfigType(),
clazz.getCanonicalName(), configJson);
}
}
populateModuleConfig(classPathAnalyser, table);
generateConfig(table);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Populate modules configuration into {@link SlimImplConfigTable}.
*
* @param classPathAnalyser Performs java reflection based classpath analysis. It provides
* functionalities such as find-classes-from-annotation, find-class-methods etc.
* @param table configuration table to populate values.
*/
private void populateModuleConfig(ClassPathAnalyser classPathAnalyser,
SlimImplConfigTable table) {
Map>> slimModules =
classPathAnalyser.getSlimModuleAnnotatedTypeMap();
for (String serviceName : slimModules.keySet()) {
table.addSlimModules(serviceName, slimModules.get(serviceName));
}
populateImplModules(classPathAnalyser, table);
}
/**
* Populate impl modules into {@link SlimImplConfigTable}.
*
* @param classPathAnalyser Performs java reflection based classpath analysis. It provides
* functionalities such as find-classes-from-annotation, find-class-methods etc.
* @param table configuration table to populate values.
*/
private void populateImplModules(ClassPathAnalyser classPathAnalyser, SlimImplConfigTable table) {
Map>> slimModules =
classPathAnalyser.getImplModuleAnnotatedTypeMap();
for (String serviceName : slimModules.keySet()) {
table.addImplModules(serviceName, slimModules.get(serviceName));
}
}
/**
* Generate configuration as per {@link SlimImplConfigTable}.
*
* @param table configuration table to generate files.
* @throws Exception throws if occurred in between process
*/
private void generateConfig(SlimImplConfigTable table) throws Exception {
createCoreConfig();
Table configTable = table.getConfigTable();
Map> map = configTable.rowMap();
for (String servicename : map.keySet()) {
Map configMap = map.get(servicename);
for (ConfigType configType : configMap.keySet()) {
String folderName = servicename.substring(servicename.lastIndexOf(".") + 1);
String data = marshaller.marshall(configMap.get(configType).setAnnotationClass(servicename),
DescriptorType.YML);
FileUtils.writeStringToFile(
new File(profileRoot + folderName + "/" + configType.name().toLowerCase() + ".yml"),
data, Charset.defaultCharset());
}
}
}
/**
* Create core {@link ServiceConfiguration} configuration.
*
* @throws IOException throws an exception if file operation fails.
*/
private void createCoreConfig() throws Exception {
ServiceConfiguration configuration = injector.getInstance(ServiceConfiguration.class);
configuration
.setAnnotationClass((Class extends Annotation>) classLoader.loadClass(serviceAnnotation));
String serviceName = serviceAnnotation.substring(serviceAnnotation.lastIndexOf(".") + 1);
configuration.setServiceName(serviceName);
populateCoreConfig(configuration);
String coreConfig = marshaller.marshall(configuration, DescriptorType.YML);
FileUtils.writeStringToFile(new File(profileRoot + "core.yml"), coreConfig,
Charset.defaultCharset());
}
/**
* Populate {@link ServiceConfiguration} object.
*
* @param configuration object of {@link ServiceConfiguration} to be populate.
* @throws Exception throws an exception if class instaniation fails.
*/
private void populateCoreConfig(ServiceConfiguration configuration) throws Exception {
Set> coreConfigMap = classPathAnalyser.getAnnotatedTypes(CoreConfig.class);
for (Class> clazz : coreConfigMap) {
configuration.addConfig(clazz.getCanonicalName(), clazz.newInstance());
}
}
/**
* Analyze the service name and whether it is slim class or impl class and populate into
* {@link SlimImplIdentifier}.
*
* @param annotations annotations present on the config class.
* @return object of {@link SlimImplIdentifier}.
*/
private SlimImplIdentifier analyzeAnnotations(Annotation[] annotations) {
String serviceName = null;
SlimImplIdentifier slimImplConfig = new SlimImplIdentifier();
for (Annotation annotation : annotations) {
if (annotation.annotationType().getName().equals(Slim.class.getTypeName())) {
slimImplConfig.setConfigType(ConfigType.SLIM);
continue;
// slim
}
Annotation[] onTopAnnotation = annotation.annotationType().getAnnotations();
serviceName = getServiceName(onTopAnnotation);
if (serviceName != null) {
break;
}
}
slimImplConfig.setServiceName(serviceName);
return slimImplConfig;
}
/**
* Find service name from annotation list by cheking is the {@link Service} present on annotation
* or not.
*
* @param onTopAnnotation annotation list from which service name to be find.
* @return string service name .
*/
private String getServiceName(Annotation[] onTopAnnotation) {
String serviceName = null;
for (Annotation annotation : onTopAnnotation) {
if (annotation.annotationType().isAnnotationPresent(Service.class)) {
serviceName = annotation.annotationType().getName();
break;
}
}
return serviceName;
}
/**
* Creates guice injector required for the goal.
*/
private Injector createGuiceInjector() {
return Guice.createInjector(new ConfigServiceModule(), new MarshallerModule());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy