andrea
Committed by Gerrit Code Review

[ONOS-3314] yang model translation into ONOS behaviour interface

Change-Id: Id86e7b696fe4362548d456253f77283c19faa710
1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 + <modelVersion>4.0.0</modelVersion>
6 + <groupId>org.onosproject</groupId>
7 + <artifactId>yangloader</artifactId>
8 + <version>1.0-SNAPSHOT</version>
9 + <dependencies>
10 + <dependency>
11 + <groupId>commons-configuration</groupId>
12 + <artifactId>commons-configuration</artifactId>
13 + <version>1.10</version>
14 + </dependency>
15 + <dependency>
16 + <groupId>commons-io</groupId>
17 + <artifactId>commons-io</artifactId>
18 + <version>2.4</version>
19 + </dependency>
20 + <dependency>
21 + <groupId>com.google.guava</groupId>
22 + <artifactId>guava</artifactId>
23 + <version>18.0</version>
24 + </dependency>
25 + <dependency>
26 + <groupId>org.onosproject</groupId>
27 + <artifactId>onlab-misc</artifactId>
28 + <version>1.4.0-SNAPSHOT</version>
29 + </dependency>
30 + <dependency>
31 + <groupId>commons-collections</groupId>
32 + <artifactId>commons-collections</artifactId>
33 + <version>3.2.1</version>
34 + <optional>true</optional>
35 + </dependency>
36 + <dependency>
37 + <groupId>org.slf4j</groupId>
38 + <artifactId>slf4j-jdk14</artifactId>
39 + <version>1.7.12</version>
40 + </dependency>
41 + </dependencies>
42 + <build>
43 + <plugins>
44 + <plugin>
45 + <groupId>org.apache.maven.plugins</groupId>
46 + <artifactId>maven-compiler-plugin</artifactId>
47 + <version>3.3</version>
48 + <configuration>
49 + <source>1.8</source>
50 + <target>1.8</target>
51 + </configuration>
52 + </plugin>
53 + <plugin>
54 + <groupId>org.apache.maven.plugins</groupId>
55 + <artifactId>maven-shade-plugin</artifactId>
56 + <version>2.3</version>
57 + <executions>
58 + <execution>
59 + <phase>package</phase>
60 + <goals>
61 + <goal>shade</goal>
62 + </goals>
63 + <configuration>
64 + <transformers>
65 + <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
66 + <mainClass>org.onoproject.yangtool.YangLoaderMain</mainClass>
67 + </transformer>
68 + </transformers>
69 + </configuration>
70 + </execution>
71 + </executions>
72 + </plugin>
73 + </plugins>
74 + </build>
75 +
76 +</project>
1 +package org.onoproject.yangtool;
2 +
3 +import com.google.common.io.Files;
4 +import org.apache.commons.configuration.ConfigurationException;
5 +import org.apache.commons.configuration.XMLConfiguration;
6 +import org.apache.commons.io.FileUtils;
7 +import org.apache.commons.io.IOUtils;
8 +import org.onlab.util.Tools;
9 +
10 +import java.io.BufferedReader;
11 +import java.io.File;
12 +import java.io.FileInputStream;
13 +import java.io.IOException;
14 +import java.io.InputStream;
15 +import java.io.InputStreamReader;
16 +import java.io.PrintWriter;
17 +import java.nio.charset.Charset;
18 +import java.util.ArrayList;
19 +import java.util.Arrays;
20 +import java.util.List;
21 +import java.util.stream.Collectors;
22 +
23 +/**
24 + * Class that takes in input two paths, one to the yang file and one where
25 + * to generate the interface, and a yang container name, generates the sources
26 + * through OpenDaylight code generator plugin from yang, and modifies
27 + * them accordingly to the needs of the ONOS behavior system.
28 + */
29 +public class YangLoader {
30 + /**
31 + * Public method to take a yang file from the input folder and generate classes
32 + * to the output folder.
33 + * @param inputFolder forlder with the yang files
34 + * @param completeOuputFolder folder where to put the desired classes
35 + * @throws IOException
36 + * @throws ConfigurationException
37 + * @throws InterruptedException
38 + */
39 + public void generateBehaviourInterface(String inputFolder,
40 + String completeOuputFolder)
41 + throws IOException, ConfigurationException, InterruptedException {
42 + File projectDir = createTemporaryProject(inputFolder);
43 + List<String> containerNames = findContainerName(
44 + new File(projectDir.getAbsolutePath() + "/src"));
45 + System.out.println("Containers " + containerNames);
46 + generateJava(projectDir);
47 + //modifyClasses(containerName, projectDir, completeInterfaceOuputFolder);
48 + copyFiles(new File(projectDir.getAbsolutePath() + "/dst"),
49 + new File(completeOuputFolder));
50 + //System.out.println("Sources in " + completeOuputFolder);
51 +
52 + }
53 +
54 + private List<String> findContainerName(File scrDir) {
55 + List<String> allContainers = new ArrayList<>();
56 + Arrays.asList(scrDir.listFiles()).stream().forEach(f -> {
57 + try {
58 + FileUtils.readLines(f).stream()
59 + .filter(line -> line.matches("(.*)container(.*)\\{"))
60 + .collect(Collectors.toList()).forEach(s -> {
61 + s = s.replace("container", "");
62 + s = s.replace("{", "");
63 + allContainers.add(s.trim());
64 + });
65 +
66 + } catch (IOException e) {
67 + throw new RuntimeException(e);
68 + }
69 + });
70 + return allContainers;
71 + }
72 +
73 + private File createTemporaryProject(String inputFolder) throws IOException,
74 + ConfigurationException {
75 + File tempDir = Files.createTempDir();
76 + File scrDir = new File(tempDir, "src");
77 + scrDir.mkdir();
78 + copyFiles(new File(inputFolder), scrDir);
79 + createPomFile(tempDir, scrDir);
80 + return tempDir;
81 +
82 + }
83 +
84 + private void copyFiles(File inputFolder, File scrDir) throws IOException {
85 + Tools.copyDirectory(inputFolder, scrDir);
86 + }
87 +
88 + private void createPomFile(File tempDir, File scrDir) throws ConfigurationException {
89 + File pom = new File(tempDir, "pom.xml");
90 + File dstDir = new File(tempDir, "dst");
91 + dstDir.mkdir();
92 + XMLConfiguration cfg = new XMLConfiguration();
93 + cfg.load(getClass().getResourceAsStream("/pom-template.xml"));
94 + cfg.setProperty("build.plugins.plugin.executions.execution." +
95 + "configuration.yangFilesRootDir", scrDir.getPath());
96 + cfg.setProperty("build.plugins.plugin.executions." +
97 + "execution.configuration.codeGenerators." +
98 + "generator.outputBaseDir", dstDir.getPath());
99 + cfg.save(pom);
100 + }
101 +
102 + private void generateJava(File projectDir)
103 + throws IOException, InterruptedException {
104 + Runtime rt = Runtime.getRuntime();
105 + Process pr = rt.exec("mvn generate-sources", null, projectDir);
106 + String s = IOUtils.toString(pr.getInputStream(), "UTF-8");
107 + if (pr.waitFor() == 0) {
108 + if (s.contains("[WARNING]")) {
109 + System.out.println("Sources not generated, warning log: \n" + s);
110 + } else {
111 + System.out.println("Sources generated");
112 + }
113 + } else {
114 + System.out.println("Sources not generated. " + s +
115 + " \nError " + pr.getInputStream().read());
116 + }
117 + }
118 +
119 + //parsing classes part, for now is not used.
120 + private void modifyClasses(String containerName, File projectDir,
121 + String pathToNewInterface) throws IOException {
122 + String odlInterfacepath = getPathWithFileName(containerName, projectDir.getPath());
123 + odlInterfacepath = odlInterfacepath + "/";
124 + parseClass(odlInterfacepath, pathToNewInterface, containerName);
125 + System.out.println("ONOS behaviour interface generated " +
126 + "correctly at " + pathToNewInterface);
127 + }
128 +
129 + private String getPathWithFileName(String filename, String pathToGenerated) {
130 + File[] directories = new File(pathToGenerated).listFiles(File::isDirectory);
131 + while (directories.length != 0) {
132 + pathToGenerated = pathToGenerated + "/" + directories[0].getName();
133 + directories = new File(pathToGenerated).listFiles(File::isDirectory);
134 + }
135 + File dir = new File(pathToGenerated);
136 + File behaviour = (File) Arrays.asList(dir.listFiles()).stream()
137 + .filter(f -> f.getName().equals(filename)).toArray()[0];
138 + return behaviour.getParentFile().getAbsolutePath();
139 + }
140 +
141 + private void parseClass(String filePath, String pathToNewInterface,
142 + String filename) throws IOException {
143 + InputStream fis = null;
144 + String newFile = "package org.onosproject.net.behaviour;\n" +
145 + "import org.onosproject.net.driver.HandlerBehaviour;\n";
146 + fis = new FileInputStream(filePath + filename);
147 + InputStreamReader isr = new InputStreamReader(fis, Charset.forName("UTF-8"));
148 + BufferedReader br = new BufferedReader(isr);
149 + String line;
150 + while ((line = br.readLine()) != null) {
151 + if (!line.contains("org.opendaylight.")) {
152 + if (line.contains("ChildOf")) {
153 + newFile = newFile + "HandlerBehaviour\n";
154 + } else {
155 + newFile = newFile + line + "\n";
156 + }
157 + }
158 + }
159 + PrintWriter out = new PrintWriter(pathToNewInterface +
160 + filename.replace(".java", "")
161 + + "Interface.java");
162 + out.print(newFile);
163 + out.flush();
164 + }
165 +
166 +
167 +}
1 +package org.onoproject.yangtool;
2 +
3 +import org.apache.commons.configuration.ConfigurationException;
4 +
5 +import java.io.IOException;
6 +
7 +/**
8 + * Main of the uangloader tool in order to be called through command line.
9 + */
10 +public class YangLoaderMain {
11 + public static void main (String args []) throws IOException,
12 + ConfigurationException, InterruptedException {
13 + YangLoader yl = new YangLoader();
14 + yl.generateBehaviourInterface(args[0], args[1]);
15 + }
16 +}
1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 + <modelVersion>4.0.0</modelVersion>
6 + <groupId>groupId</groupId>
7 + <artifactId>yangloader</artifactId>
8 + <version>1.0-SNAPSHOT</version>
9 + <pluginRepositories>
10 + <pluginRepository>
11 + <id>opendaylight-release</id>
12 + <name>opendaylight-release</name>
13 + <url>
14 + http://nexus.opendaylight.org/content/repositories/opendaylight.release/
15 + </url>
16 + </pluginRepository>
17 + <pluginRepository>
18 + <id>opendaylight-snapshot</id>
19 + <name>opendaylight-snapshot</name>
20 + <url>
21 + http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/
22 + </url>
23 + </pluginRepository>
24 + </pluginRepositories>
25 + <repositories>
26 + <repository>
27 + <id>opendaylight-release</id>
28 + <name>opendaylight-release</name>
29 + <url>
30 + http://nexus.opendaylight.org/content/repositories/opendaylight.release/
31 + </url>
32 + </repository>
33 + <repository>
34 + <id>opendaylight-snapshot</id>
35 + <name>opendaylight-snapshot</name>
36 + <url>
37 + http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/
38 + </url>
39 + </repository>
40 + </repositories>
41 + <dependencies>
42 + <dependency>
43 + <groupId>org.opendaylight.yangtools</groupId>
44 + <artifactId>yang-binding</artifactId>
45 + <version>0.7.2-Lithium-SR2</version>
46 + </dependency>
47 + </dependencies>
48 + <build>
49 + <plugins>
50 + <plugin>
51 + <groupId>org.opendaylight.yangtools</groupId>
52 + <artifactId>yang-maven-plugin</artifactId>
53 + <version>0.7.2-Lithium-SR2</version>
54 + <executions>
55 + <execution>
56 + <goals>
57 + <goal>generate-sources</goal>
58 + </goals>
59 + <configuration>
60 + <!-- directory containing yang files to parse and generate code -->
61 + <yangFilesRootDir>INPUTDIR</yangFilesRootDir>
62 + <codeGenerators>
63 + <generator>
64 + <codeGeneratorClass>
65 + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
66 + </codeGeneratorClass>
67 + <!-- directory into which generated files will be placed -->
68 + <outputBaseDir>OUTPUTDIR</outputBaseDir>
69 + </generator>
70 + </codeGenerators>
71 + <inspectDependencies>false</inspectDependencies>
72 + </configuration>
73 + </execution>
74 + </executions>
75 + <dependencies>
76 + <dependency>
77 + <groupId>org.opendaylight.yangtools</groupId>
78 + <artifactId>maven-sal-api-gen-plugin</artifactId>
79 + <version>0.7.2-Lithium-SR2</version>
80 + <type>jar</type>
81 + </dependency>
82 + </dependencies>
83 + </plugin>
84 + <plugin>
85 + <groupId>org.apache.maven.plugins</groupId>
86 + <artifactId>maven-compiler-plugin</artifactId>
87 + <version>3.3</version>
88 + <configuration>
89 + <source>1.8</source>
90 + <target>1.8</target>
91 + </configuration>
92 + </plugin>
93 + </plugins>
94 + </build>
95 +</project>