/* * Copyright 2015-present Open Networking Laboratory * * 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 org.onosproject.maven; import com.thoughtworks.qdox.JavaProjectBuilder; import com.thoughtworks.qdox.model.JavaAnnotation; import com.thoughtworks.qdox.model.JavaClass; import com.thoughtworks.qdox.model.JavaField; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; /** * Produces ONOS component configuration catalogue resources. */ @Mojo(name = "cfg", defaultPhase = LifecyclePhase.GENERATE_RESOURCES) @java.lang.SuppressWarnings("squid:S1148") public class OnosCfgMojo extends AbstractMojo { private static final String COMPONENT = "org.apache.felix.scr.annotations.Component"; private static final String PROPERTY = "org.apache.felix.scr.annotations.Property"; private static final String SEP = "|"; /** * The directory where the generated catalogue file will be put. */ @Parameter(defaultValue = "${basedir}") protected File srcDirectory; /** * The directory where the generated catalogue file will be put. */ @Parameter(defaultValue = "${project.build.outputDirectory}") protected File dstDirectory; @Override public void execute() throws MojoExecutionException { getLog().info("Generating ONOS component configuration catalogues..."); try { JavaProjectBuilder builder = new JavaProjectBuilder(); builder.addSourceTree(new File(srcDirectory, "src/main/java")); builder.getClasses().forEach(this::processClass); } catch (Exception e) { e.printStackTrace(); throw e; } } private void processClass(JavaClass javaClass) { boolean isComponent = javaClass.getAnnotations().stream() .map(ja -> ja.getType().getName().equals(COMPONENT)) .findFirst().isPresent(); if (isComponent) { List<String> lines = new ArrayList<>(); javaClass.getFields().forEach(field -> processField(lines, javaClass, field)); if (!lines.isEmpty()) { writeCatalog(javaClass, lines); } } } private void writeCatalog(JavaClass javaClass, List<String> lines) { File dir = new File(dstDirectory, javaClass.getPackageName().replace('.', '/')); dir.mkdirs(); File cfgDef = new File(dir, javaClass.getName().replace('.', '/') + ".cfgdef"); try (FileWriter fw = new FileWriter(cfgDef); PrintWriter pw = new PrintWriter(fw)) { pw.println("# This file is auto-generated by onos-maven-plugin"); lines.forEach(pw::println); } catch (IOException e) { System.err.println("Unable to write catalog for " + javaClass.getName()); e.printStackTrace(); } } private void processField(List<String> lines, JavaClass javaClass, JavaField field) { field.getAnnotations().forEach(ja -> { if (ja.getType().getName().equals(PROPERTY)) { lines.add(expand(javaClass, ja.getNamedParameter("name").toString()) + SEP + type(field) + SEP + defaultValue(javaClass, field, ja) + SEP + description(ja)); } }); } // TODO: Stuff below is very much hack-ish and should be redone; it works for now though. private String description(JavaAnnotation annotation) { String description = (String) annotation.getNamedParameter("label"); return description.replaceAll("\" \\+ \"", "") .replaceFirst("^[^\"]*\"", "").replaceFirst("\"$", ""); } private String type(JavaField field) { String ft = field.getType().getName().toUpperCase(); return ft.equals("INT") ? "INTEGER" : ft; } private String defaultValue(JavaClass javaClass, JavaField field, JavaAnnotation annotation) { String ft = field.getType().getName().toLowerCase(); String defValueName = ft.equals("boolean") ? "boolValue" : ft.equals("string") ? "value" : ft + "Value"; Object dv = annotation.getNamedParameter(defValueName); return dv == null ? "" : expand(javaClass, dv.toString()); } private String stripQuotes(String string) { return string.trim().replaceFirst("^[^\"]*\"", "").replaceFirst("\"$", ""); } private String expand(JavaClass javaClass, String value) { JavaField field = javaClass.getFieldByName(value); return field == null ? stripQuotes(value) : stripQuotes(field.getCodeBlock().replaceFirst(".*=", "").replaceFirst(";$", "")); } }