X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=opendaylight%2Fsal%2Fyang-prototype%2Fcode-generator%2Fmaven-yang-plugin%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fyang2sources%2Fplugin%2FYangToSourcesMojo.java;h=7dbd8568240b802d0c105a309eaca270ab5d1eae;hb=3556bca9524bd19e738ac0d86c4e8b4d5add0a21;hp=ab49a54fd1fa809a439ab42cc8c731973227cb54;hpb=bd12f1813d9bc6706eec5dca561506d3709c211c;p=controller.git diff --git a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesMojo.java b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesMojo.java index ab49a54fd1..7dbd856824 100644 --- a/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesMojo.java +++ b/opendaylight/sal/yang-prototype/code-generator/maven-yang-plugin/src/main/java/org/opendaylight/controller/yang2sources/plugin/YangToSourcesMojo.java @@ -7,26 +7,11 @@ */ package org.opendaylight.controller.yang2sources.plugin; -import java.io.Closeable; import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; +import java.util.Arrays; import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import org.apache.commons.io.IOUtils; -import org.apache.maven.model.Resource; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; @@ -35,19 +20,11 @@ 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.opendaylight.controller.yang.model.api.Module; import org.opendaylight.controller.yang.model.api.SchemaContext; -import org.opendaylight.controller.yang.model.parser.api.YangModelParser; -import org.opendaylight.controller.yang.parser.impl.YangParserImpl; import org.opendaylight.controller.yang2sources.plugin.ConfigArg.CodeGeneratorArg; -import org.opendaylight.controller.yang2sources.plugin.ConfigArg.ResourceProviderArg; import org.opendaylight.controller.yang2sources.spi.CodeGenerator; -import org.opendaylight.controller.yang2sources.spi.ResourceGenerator; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.io.Files; /** * Generate sources from yang files using user provided set of @@ -64,9 +41,6 @@ import com.google.common.io.Files; */ @Mojo(name = "generate-sources", defaultPhase = LifecyclePhase.GENERATE_SOURCES, requiresDependencyResolution = ResolutionScope.COMPILE, requiresProject = true) public final class YangToSourcesMojo extends AbstractMojo { - private static final String LOG_PREFIX = "yang-to-sources:"; - private static final String INPUT_RESOURCE_DIR = "META-INF/yang/"; - private static final String OUTPUT_RESOURCE_DIR = "/target/external-resources/"; /** * Classes implementing {@link CodeGenerator} interface. An instance will be @@ -74,402 +48,57 @@ public final class YangToSourcesMojo extends AbstractMojo { * CodeGenerator#generateSources(SchemaContext, File, Set * yangModulesNames)} will be called on every instance. */ - @Parameter(required = true) + @Parameter(required = false) private CodeGeneratorArg[] codeGenerators; /** * Source directory that will be recursively searched for yang files (ending * with .yang suffix). */ - @Parameter(required = true) - private String yangFilesRootDir; - - /** - * Classes implementing {@link ResourceGenerator} interface. An instance - * will be created out of every class using default constructor. Method - * {@link ResourceGenerator#generateResourceFiles(Collection, File)} will be - * called on every instance. - */ - @Parameter(required = true) - private ResourceProviderArg[] resourceProviders; + @Parameter(required = false) + private String yangFilesRootDir; // defaults to ${basedir}/src/main/yang @Parameter(property = "project", required = true, readonly = true) protected MavenProject project; - private transient final YangModelParser parser; + @Parameter(property = "inspectDependencies", required = true, readonly = true) + private boolean inspectDependencies; + + public YangToSourcesMojo() { + + } @VisibleForTesting - YangToSourcesMojo(ResourceProviderArg[] resourceProviderArgs, - CodeGeneratorArg[] codeGeneratorArgs, YangModelParser parser, + YangToSourcesMojo(CodeGeneratorArg[] codeGeneratorArgs, String yangFilesRootDir) { - super(); - this.resourceProviders = resourceProviderArgs; this.codeGenerators = codeGeneratorArgs; this.yangFilesRootDir = yangFilesRootDir; - this.parser = parser; - } - - public YangToSourcesMojo() { - super(); - parser = new YangParserImpl(); } @Override public void execute() throws MojoExecutionException, MojoFailureException { - ContextHolder context = processYang(); - generateSources(context); - generateResources(); - - closeResources(); - } - - /** - * Generate {@link SchemaContext} with {@link YangModelParserImpl} - */ - private ContextHolder processYang() throws MojoExecutionException { - try { - List yangFiles = Util - .listFilesAsStream(yangFilesRootDir); - Set yangModules = parser - .parseYangModelsFromStreams(yangFiles); - - Set yangModulesNames = new HashSet(); - for (Module module : yangModules) { - yangModulesNames.add(module.getName()); - } - - List yangFilesFromDependencies = getFilesFromDependenciesAsStream(); - Set yangModulesFromDependencies = parser - .parseYangModelsFromStreams(yangFilesFromDependencies); - - Set parsedYang = new HashSet(yangModules); - parsedYang.addAll(yangModulesFromDependencies); - - if (yangFiles.isEmpty() && yangFilesFromDependencies.isEmpty()) { - getLog().warn( - Util.message( - "No %s file found in %s or in dependencies", - LOG_PREFIX, Util.YANG_SUFFIX, yangFilesRootDir)); - Set names = Collections.emptySet(); - return new ContextHolder(null, names); - } - - SchemaContext resolveSchemaContext = parser - .resolveSchemaContext(parsedYang); - getLog().info( - Util.message("%s files parsed from %s", LOG_PREFIX, - Util.YANG_SUFFIX, yangFiles)); - return new ContextHolder(resolveSchemaContext, yangModulesNames); - - // MojoExecutionException is thrown since execution cannot continue - } catch (Exception e) { - String message = Util.message("Unable to parse %s files from %s", - LOG_PREFIX, Util.YANG_SUFFIX, yangFilesRootDir); - getLog().error(message, e); - throw new MojoExecutionException(message, e); - } - } - - private void generateResources() throws MojoExecutionException, - MojoFailureException { - if (resourceProviders.length == 0) { - getLog().warn( - Util.message("No resource provider classes provided", - LOG_PREFIX)); - return; - } - - Resource res = new Resource(); - String baseDirName = project.getBasedir().getAbsolutePath(); - res.setDirectory(baseDirName + OUTPUT_RESOURCE_DIR); - res.setTargetPath(INPUT_RESOURCE_DIR); - project.addResource(res); - - Map thrown = Maps.newHashMap(); - - Collection yangFiles = new ArrayList(); - - // load files from yang root - yangFiles.addAll(getFilesFromYangRoot()); - - // load files from dependencies - Collection filesFromDependencies = getFilesFromDependencies(); - yangFiles.addAll(filesFromDependencies); - - for (ResourceProviderArg resourceProvider : resourceProviders) { - try { - provideResourcesWithOneProvider(yangFiles, resourceProvider); - } catch (Exception e) { - // try other generators, exception will be thrown after - getLog().error( - Util.message( - "Unable to provide resources with %s resource provider", - LOG_PREFIX, - resourceProvider.getResourceProviderClass()), e); - thrown.put(resourceProvider.getResourceProviderClass(), e - .getClass().getCanonicalName()); - } - } - - if (!thrown.isEmpty()) { - String message = Util - .message( - "One or more code resource provider failed, including failed list(resourceProviderClass=exception) %s", - LOG_PREFIX, thrown.toString()); - getLog().error(message); - throw new MojoFailureException(message); - } - } - - private Collection getFilesFromYangRoot() { - Collection yangFilesLoaded = null; - - File rootDir = new File(yangFilesRootDir); - try { - if (rootDir.isAbsolute()) { - yangFilesLoaded = Util.listFiles(yangFilesRootDir); + List codeGeneratorArgs; + if (codeGenerators == null) { + codeGeneratorArgs = Collections.emptyList(); + } else { + codeGeneratorArgs = Arrays.asList(codeGenerators); + } + + // defaults to ${basedir}/src/main/yang + File yangFilesRootFile; + if (yangFilesRootDir == null) { + yangFilesRootFile = new File(project.getBasedir(), "src" + + File.separator + "main" + File.separator + "yang"); + } else { + File file = new File(yangFilesRootDir); + if (file.isAbsolute()) { + yangFilesRootFile = file; } else { - String path = project.getBasedir().getAbsolutePath() - + File.separator + yangFilesRootDir; - yangFilesLoaded = Util.listFiles(path); + yangFilesRootFile = new File(project.getBasedir(), + file.getPath()); } - } catch (FileNotFoundException e) { - getLog().warn( - "yangFilesRootDir[" + rootDir.getAbsolutePath() - + "] does not exists."); - yangFilesLoaded = new ArrayList(); } - - Collection yangFiles = new ArrayList(yangFilesLoaded); - - try { - for (File yangFile : yangFilesLoaded) { - InputStream is = new FileInputStream(yangFile); - yangFiles.add(createFileFromStream(is, - project.getBasedir().getAbsolutePath() - + OUTPUT_RESOURCE_DIR + yangFile.getName())); - resources.add(is); - } - } catch (IOException e) { - getLog().warn("Exception while loading yang files.", e); - } - return yangFiles; + new YangToSourcesProcessor(getLog(), yangFilesRootFile, + codeGeneratorArgs, project, inspectDependencies).execute(); } - - private Collection getFilesFromDependencies() { - Collection yangFiles = new ArrayList(); - - try { - List filesOnCp = Util.getClassPath(project); - List filter = Lists.newArrayList(".yang"); - for (File file : filesOnCp) { - ZipFile zip = new ZipFile(file); - Enumeration entries = zip.entries(); - - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - String entryName = entry.getName(); - if (entryName.startsWith(INPUT_RESOURCE_DIR)) { - if (entry.isDirectory()) { - continue; - } - if (!Util.acceptedFilter(entryName, filter)) { - continue; - } - InputStream entryStream = zip.getInputStream(entry); - String newEntryName = entryName - .substring(INPUT_RESOURCE_DIR.length()); - File tmp = Files.createTempDir(); - File f = createFileFromStream(entryStream, - tmp.getAbsolutePath() + newEntryName); - yangFiles.add(f); - - resources.add(entryStream); - } - } - - resources.add(zip); - } - } catch (Exception e) { - getLog().warn("Exception while loading external yang files.", e); - } - return yangFiles; - } - - private File createFileFromStream(InputStream is, String absoluteName) - throws IOException { - File f = new File(absoluteName); - if (!f.exists()) { - f.getParentFile().mkdirs(); - } - f.createNewFile(); - - FileOutputStream fos = new FileOutputStream(f); - IOUtils.copy(is, fos); - return f; - } - - /** - * Instantiate provider from class and call required method - */ - private void provideResourcesWithOneProvider(Collection yangFiles, - ResourceProviderArg resourceProvider) - throws ClassNotFoundException, InstantiationException, - IllegalAccessException { - - resourceProvider.check(); - - ResourceGenerator g = Util.getInstance( - resourceProvider.getResourceProviderClass(), - ResourceGenerator.class); - getLog().info( - Util.message("Resource provider instantiated from %s", - LOG_PREFIX, resourceProvider.getResourceProviderClass())); - - g.generateResourceFiles(yangFiles, resourceProvider.getOutputBaseDir()); - getLog().info( - Util.message("Resource provider %s call successful", - LOG_PREFIX, resourceProvider.getResourceProviderClass())); - } - - /** - * Call generate on every generator from plugin configuration - */ - private void generateSources(ContextHolder context) - throws MojoFailureException { - if (codeGenerators.length == 0) { - getLog().warn( - Util.message("No code generators provided", LOG_PREFIX)); - return; - } - - Map thrown = Maps.newHashMap(); - for (CodeGeneratorArg codeGenerator : codeGenerators) { - try { - generateSourcesWithOneGenerator(context, codeGenerator); - } catch (Exception e) { - // try other generators, exception will be thrown after - getLog().error( - Util.message( - "Unable to generate sources with %s generator", - LOG_PREFIX, - codeGenerator.getCodeGeneratorClass()), e); - thrown.put(codeGenerator.getCodeGeneratorClass(), e.getClass() - .getCanonicalName()); - } - } - - if (!thrown.isEmpty()) { - String message = Util - .message( - "One or more code generators failed, including failed list(generatorClass=exception) %s", - LOG_PREFIX, thrown.toString()); - getLog().error(message); - throw new MojoFailureException(message); - } - } - - /** - * Instantiate generator from class and call required method - */ - private void generateSourcesWithOneGenerator(ContextHolder context, - CodeGeneratorArg codeGeneratorCfg) throws ClassNotFoundException, - InstantiationException, IllegalAccessException, IOException { - - codeGeneratorCfg.check(); - - CodeGenerator g = Util.getInstance( - codeGeneratorCfg.getCodeGeneratorClass(), CodeGenerator.class); - getLog().info( - Util.message("Code generator instantiated from %s", LOG_PREFIX, - codeGeneratorCfg.getCodeGeneratorClass())); - - File outputDir = codeGeneratorCfg.getOutputBaseDir(); - if (project != null && outputDir != null) { - project.addCompileSourceRoot(outputDir.getPath()); - } - Collection generated = g.generateSources(context.getContext(), - outputDir, context.getYangModulesNames()); - getLog().info( - Util.message("Sources generated by %s: %s", LOG_PREFIX, - codeGeneratorCfg.getCodeGeneratorClass(), generated)); - } - - /** - * Collection of resources which should be closed after use. - */ - private final List resources = new ArrayList(); - - /** - * Search for yang files in dependent projects. - * - * @return files found as List of InputStream - */ - private List getFilesFromDependenciesAsStream() { - final List yangsFromDependencies = new ArrayList(); - try { - List filesOnCp = Util.getClassPath(project); - - List filter = Lists.newArrayList(".yang"); - for (File file : filesOnCp) { - ZipFile zip = new ZipFile(file); - Enumeration entries = zip.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - String entryName = entry.getName(); - - if (entryName.startsWith(INPUT_RESOURCE_DIR)) { - if (entry.isDirectory()) { - continue; - } - if (!Util.acceptedFilter(entryName, filter)) { - continue; - } - - InputStream entryStream = zip.getInputStream(entry); - yangsFromDependencies.add(entryStream); - resources.add(entryStream); - } - - } - resources.add(zip); - } - } catch (Exception e) { - getLog().warn("Exception while searching yangs in dependencies", e); - } - return yangsFromDependencies; - } - - /** - * Internal utility method for closing open resources. - */ - private void closeResources() { - for (Closeable resource : resources) { - try { - resource.close(); - } catch (IOException e) { - getLog().warn("Failed to close resources: " + resource, e); - } - } - } - - private class ContextHolder { - private final SchemaContext context; - private final Set yangModulesNames; - - private ContextHolder(SchemaContext context, - Set yangModulesNames) { - this.context = context; - this.yangModulesNames = yangModulesNames; - } - - public SchemaContext getContext() { - return context; - } - - public Set getYangModulesNames() { - return yangModulesNames; - } - } - }