2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.config.yangjmxgenerator.plugin;
10 import static org.hamcrest.CoreMatchers.equalTo;
11 import static org.hamcrest.CoreMatchers.is;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertFalse;
14 import static org.junit.Assert.assertNotNull;
15 import static org.junit.Assert.assertThat;
16 import static org.junit.Assert.assertTrue;
17 import static org.junit.Assert.fail;
18 import static org.junit.matchers.JUnitMatchers.containsString;
19 import static org.mockito.Matchers.any;
20 import static org.mockito.Mockito.doNothing;
21 import static org.mockito.Mockito.doReturn;
22 import static org.mockito.Mockito.mock;
25 import java.io.IOException;
26 import java.nio.charset.Charset;
29 import javax.xml.parsers.DocumentBuilder;
30 import javax.xml.parsers.DocumentBuilderFactory;
32 import org.apache.commons.io.FileUtils;
33 import org.apache.maven.plugin.logging.Log;
34 import org.apache.maven.project.MavenProject;
35 import org.eclipse.jdt.core.JavaCore;
36 import org.eclipse.jdt.core.compiler.IProblem;
37 import org.eclipse.jdt.core.dom.AST;
38 import org.eclipse.jdt.core.dom.ASTParser;
39 import org.eclipse.jdt.core.dom.ASTVisitor;
40 import org.eclipse.jdt.core.dom.CompilationUnit;
41 import org.eclipse.jdt.core.dom.FieldDeclaration;
42 import org.eclipse.jdt.core.dom.MethodDeclaration;
43 import org.eclipse.jdt.core.dom.NormalAnnotation;
44 import org.eclipse.jdt.core.dom.PackageDeclaration;
45 import org.eclipse.jdt.core.dom.TypeDeclaration;
46 import org.junit.Before;
47 import org.junit.Test;
48 import org.opendaylight.controller.config.api.annotations.Description;
49 import org.opendaylight.controller.config.api.annotations.RequireInterface;
50 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
51 import org.opendaylight.controller.config.spi.Module;
52 import org.opendaylight.controller.config.spi.ModuleFactory;
53 import org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants;
54 import org.opendaylight.controller.config.yangjmxgenerator.PackageTranslatorTest;
55 import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntryTest;
56 import org.xml.sax.ErrorHandler;
57 import org.xml.sax.InputSource;
58 import org.xml.sax.SAXException;
59 import org.xml.sax.SAXParseException;
61 import com.google.common.base.Predicate;
62 import com.google.common.collect.Collections2;
63 import com.google.common.collect.Maps;
64 import com.google.common.collect.Sets;
65 import com.google.common.io.Files;
67 public class JMXGeneratorTest extends AbstractGeneratorTest {
69 JMXGenerator jmxGenerator;
71 protected final HashMap<String, String> map = Maps.newHashMap();
72 protected File outputBaseDir;
73 File generatedResourcesDir;
75 private static final List<String> expectedModuleFileNames = ServiceInterfaceEntryTest
76 .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, " +
77 "AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, " +
78 "AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, " +
79 "AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, " +
80 "AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, " +
81 "AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, " +
82 "AsyncEventBusRuntimeRegistrator.java, DynamicThreadPoolModule.java, " +
83 "DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, " +
84 "DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, " +
85 "DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, " +
86 "EventBusModuleMXBean.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, " +
87 "InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, " +
88 "NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, Peer.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]");
90 private static final List<String> expectedBGPNames = ServiceInterfaceEntryTest
91 .toFileNames("[AbstractBgpListenerImplModule.java, " + "AbstractBgpListenerImplModuleFactory.java, " +
92 "BgpListenerImplModule.java, " + "BgpListenerImplModuleFactory.java, " +
93 "BgpListenerImplModuleMXBean.java, Peers.java]");
95 private static final List<String> expectedNetconfNames = ServiceInterfaceEntryTest
96 .toFileNames("[AbstractNetconfTestImplModule.java, " + "AbstractNetconfTestImplModuleFactory.java, " +
97 "AbstractTestImplModule.java, " + "AbstractTestImplModuleFactory.java, " +
98 "AutoCloseableServiceInterface.java, " + "ComplexDtoBInner.java, ComplexList.java, Deep.java, " +
99 "DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, DtoC.java," + "NetconfTestImplModule.java, NetconfTestImplModuleFactory.java," + "NetconfTestImplModuleMXBean.java, Peer.java, SimpleList.java, TestImplModule.java, " + "TestImplModuleFactory.java," + " TestImplModuleMXBean.java" + "]");
100 private static final List<String> expectedTestFiles = ServiceInterfaceEntryTest
101 .toFileNames("[AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, " +
102 "AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, " +
103 "AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, " +
104 "AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, DtoA.java, " +
105 "DtoA.java, NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, " +
106 "NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, " +
107 "NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, " +
108 "NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, " +
109 "NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java]");
110 private static final List<String> expectedAllFileNames = ServiceInterfaceEntryTest
111 .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, " +
112 "AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, " +
113 "AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, " +
114 "AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, " +
115 "AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, " +
116 "AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, " +
117 "AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, " +
118 "AbstractNetconfTestImplModule.java, AbstractNetconfTestImplModuleFactory.java, " +
119 "AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, " +
120 "AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, " +
121 "AbstractTestImplModule.java, AbstractTestImplModuleFactory.java, AsyncEventBusModule.java, " +
122 "AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, " +
123 "AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, " +
124 "AsyncEventBusRuntimeRegistrator.java, AutoCloseableServiceInterface.java, " +
125 "BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java," +
126 " BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, " +
127 "BgpListenerImplRuntimeRegistrator.java, ComplexDtoBInner.java, ComplexList.java, Deep.java, " +
128 "DtoA.java, DtoA.java, DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, " +
129 "DtoC.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, " +
130 "DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, " +
131 "DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, " +
132 "EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, " +
133 "EventBusServiceInterface.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, " +
134 "InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, " +
135 "NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, " +
136 "NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, " +
137 "NetconfTestFileImplModule.java, NetconfTestFileImplModuleFactory.java, " +
138 "NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, " +
139 "NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, " +
140 "NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, " +
141 "NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, " +
142 "NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, NetconfTestImplModule.java, NetconfTestImplModuleFactory.java, NetconfTestImplModuleMXBean.java, NetconfTestImplRuntimeMXBean.java, NetconfTestImplRuntimeRegistration.java, NetconfTestImplRuntimeRegistrator.java, Peer.java, Peer.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java, ScheduledThreadPoolServiceInterface.java, SimpleList.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java, TestImplModule.java, TestImplModuleFactory.java, TestImplModuleMXBean.java, TestImplRuntimeMXBean.java, TestImplRuntimeRegistration.java, TestImplRuntimeRegistrator.java, ThreadFactoryServiceInterface.java, ThreadPoolServiceInterface.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]");
143 private static final List<String> expectedGenerateMBEsListNames = ServiceInterfaceEntryTest
144 .toFileNames("[AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java]");
147 public void setUp() {
148 map.put(JMXGenerator.NAMESPACE_TO_PACKAGE_PREFIX + "1",
149 ConfigConstants.CONFIG_NAMESPACE
150 + JMXGenerator.NAMESPACE_TO_PACKAGE_DIVIDER
151 + PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX);
152 map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "false");
153 jmxGenerator = new JMXGenerator(new FreeMarkerCodeWriterImpl());
154 jmxGenerator.setAdditionalConfig(map);
155 File targetDir = new File(generatorOutputPath, "target");
156 generatedResourcesDir = new File(targetDir, "generated-resources");
157 jmxGenerator.setResourceBaseDir(generatedResourcesDir);
158 Log mockedLog = mock(Log.class);
159 doReturn(false).when(mockedLog).isDebugEnabled();
160 doNothing().when(mockedLog).debug(any(CharSequence.class));
161 doNothing().when(mockedLog).info(any(CharSequence.class));
162 doNothing().when(mockedLog).error(any(CharSequence.class),
163 any(Throwable.class));
164 jmxGenerator.setLog(mockedLog);
165 MavenProject project = mock(MavenProject.class);
166 doReturn(generatorOutputPath).when(project).getBasedir();
167 jmxGenerator.setMavenProject(project);
168 outputBaseDir = JMXGenerator.concatFolders(targetDir,
169 "generated-sources", "config");
173 public void generateSIsMBsTest() {
174 Collection<File> files = jmxGenerator.generateSources(context,
175 outputBaseDir, context.getModules());
176 List<String> expectedFileNames = new ArrayList<>();
178 .addAll(ServiceInterfaceEntryTest.expectedSIEFileNames);
179 expectedFileNames.addAll(expectedModuleFileNames);
181 expectedFileNames.addAll(expectedBGPNames);
182 expectedFileNames.addAll(expectedNetconfNames);
183 expectedFileNames.addAll(expectedTestFiles);
184 Collections.sort(expectedFileNames);
185 // TODO: separate expectedAllFileNames into expectedBGPNames,
186 // expectedNetconfNames
187 assertEquals(expectedAllFileNames, toFileNames(files));
189 verifyModuleFactoryFile(false);
192 private void verifyModuleFactoryFile(boolean shouldBePresent) {
193 File factoryFile = new File(generatedResourcesDir, "META-INF"
194 + File.separator + "services" + File.separator
195 + ModuleFactory.class.getName());
196 if (!shouldBePresent)
197 assertFalse("Factory file should not be generated",
198 factoryFile.exists());
200 assertTrue("Factory file should be generated", factoryFile.exists());
203 public static List<String> toFileNames(Collection<File> files) {
204 List<String> result = new ArrayList<>();
205 for (File f : files) {
206 result.add(f.getName());
208 Collections.sort(result);
213 public void generateSIEsTest() throws IOException {
214 Collection<File> files = jmxGenerator.generateSources(context,
215 outputBaseDir, Sets.newHashSet(threadsModule));
216 assertEquals(ServiceInterfaceEntryTest.expectedSIEFileNames,
219 Map<String, ASTVisitor> verifiers = Maps.newHashMap();
221 for (File file : files) {
222 verifiers.put(file.getName(), new SieASTVisitor());
225 processGeneratedCode(files, verifiers);
227 for (File file : files) {
228 String fileName = file.getName();
229 SieASTVisitor verifier = (SieASTVisitor) verifiers.get(fileName);
231 assertEquals(fileName.substring(0, fileName.length() - 5),
235 containsString("org.opendaylight.controller.config.api.annotations.AbstractServiceInterface"));
236 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
237 + ".threads", verifier.packageName);
238 assertNotNull(verifier.javadoc);
240 if ("ThreadPoolServiceInterface.java".equals(fileName)) {
241 assertContains(verifier.descriptionAnotValue,
242 "A simple pool of threads able to execute work.");
243 assertContains(verifier.sieAnnotValue, "threadpool");
244 assertContains(verifier.sieAnnotOsgiRegistrationType,
245 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
246 + ".threadpool.ThreadPool.class");
247 } else if ("ScheduledThreadPoolServiceInterface.java"
249 assertContains(verifier.extnds,
250 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
251 + ".threads.ThreadPoolServiceInterface");
253 verifier.descriptionAnotValue,
254 "An extension of the simple pool of threads able to schedule work to be executed at some point in time.");
255 assertContains(verifier.sieAnnotValue, "scheduled-threadpool");
256 assertContains(verifier.sieAnnotOsgiRegistrationType,
257 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
258 + ".threadpool.ScheduledThreadPool.class");
259 } else if ("EventBusServiceInterface.java".equals(fileName)) {
261 verifier.descriptionAnotValue,
262 "Service representing an event bus. The service acts as message router between event producers and event consumers");
263 assertContains(verifier.sieAnnotValue, "eventbus");
264 assertContains(verifier.sieAnnotOsgiRegistrationType,
265 "com.google.common.eventbus.EventBus.class");
266 } else if ("ThreadFactoryServiceInterface.java".equals(fileName)) {
268 verifier.descriptionAnotValue,
269 "Service representing a ThreadFactory instance. It is directly useful in Java world, where various library pieces need to create threads and you may want to inject a customized thread implementation.");
270 assertContains(verifier.sieAnnotValue, "threadfactory");
271 assertContains(verifier.sieAnnotOsgiRegistrationType,
272 "java.util.concurrent.ThreadFactory.class");
274 } else if ("ScheduledExecutorServiceServiceInterface.java"
276 assertContains(verifier.sieAnnotOsgiRegistrationType,
277 "java.util.concurrent.ScheduledExecutorService.class");
279 fail("Unknown generated sie " + fileName);
285 public void generateMBEsListTest() throws Exception {
286 // default value for module factory file is true
287 map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "randomValue");
288 jmxGenerator.setAdditionalConfig(map);
290 Collection<File> files = jmxGenerator.generateSources(context,
291 outputBaseDir, Sets.newHashSet(bgpListenerJavaModule));
293 assertEquals(expectedGenerateMBEsListNames, toFileNames(files));
297 public void generateMBEsTest() throws Exception {
298 // default value for module factory file is true
299 map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "randomValue");
300 jmxGenerator.setAdditionalConfig(map);
302 Collection<File> files = jmxGenerator.generateSources(context,
303 outputBaseDir, Sets.newHashSet(threadsJavaModule));
305 assertEquals(expectedModuleFileNames, toFileNames(files));
307 Map<String, ASTVisitor> verifiers = Maps.newHashMap();
309 Collection<File> xmlFiles = Collections2.filter(files,
310 new Predicate<File>() {
313 public boolean apply(File input) {
314 return input.getName().endsWith("xml");
318 Collection<File> javaFiles = Collections2.filter(files,
319 new Predicate<File>() {
322 public boolean apply(File input) {
323 return input.getName().endsWith("java");
327 MbeASTVisitor abstractDynamicThreadPoolModuleVisitor = null;
328 MbeASTVisitor asyncEventBusModuleMXBeanVisitor = null;
329 MbeASTVisitor abstractNamingThreadFactoryModuleFactoryVisitor = null;
330 MbeASTVisitor asyncEventBusModuleVisitor = null;
331 MbeASTVisitor eventBusModuleFactoryVisitor = null;
333 for (File file : javaFiles) {
334 String name = file.getName();
335 MbeASTVisitor visitor = new MbeASTVisitor();
336 verifiers.put(name, visitor);
337 if (name.equals("AbstractDynamicThreadPoolModule.java"))
338 abstractDynamicThreadPoolModuleVisitor = visitor;
339 if (name.equals("AsyncEventBusModuleMXBean.java"))
340 asyncEventBusModuleMXBeanVisitor = visitor;
341 if (name.equals("AbstractNamingThreadFactoryModuleFactory.java"))
342 abstractNamingThreadFactoryModuleFactoryVisitor = visitor;
343 if (name.equals("AsyncEventBusModule.java"))
344 asyncEventBusModuleVisitor = visitor;
345 if (name.equals("EventBusModuleFactory.java"))
346 eventBusModuleFactoryVisitor = visitor;
349 processGeneratedCode(javaFiles, verifiers);
351 assertAbstractDynamicThreadPoolModule(abstractDynamicThreadPoolModuleVisitor);
352 assertAsyncEventBusModuleMXBean(asyncEventBusModuleMXBeanVisitor);
353 assertAbstractNamingThreadFactoryModuleFactory(abstractNamingThreadFactoryModuleFactoryVisitor);
354 assertAsyncEventBusModule(asyncEventBusModuleVisitor);
355 assertEventBusModuleFactory(eventBusModuleFactoryVisitor);
357 verifyXmlFiles(xmlFiles);
358 // verify ModuleFactory file
359 File moduleFactoryFile = JMXGenerator.concatFolders(
360 generatedResourcesDir, "META-INF", "services",
361 ModuleFactory.class.getName());
362 assertThat(moduleFactoryFile.exists(), is(true));
363 Set<String> lines = Sets.newHashSet(FileUtils
364 .readLines(moduleFactoryFile));
365 Set<String> expectedLines = Sets.newHashSet(//
366 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
367 + ".threads.java.EventBusModuleFactory",//
368 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
369 + ".threads.java.AsyncEventBusModuleFactory", //
370 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
371 + ".threads.java.DynamicThreadPoolModuleFactory",//
372 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
373 + ".threads.java.NamingThreadFactoryModuleFactory");
374 assertThat(lines, equalTo(expectedLines));
378 private void verifyXmlFiles(Collection<File> xmlFiles) throws Exception {
379 ErrorHandler errorHandler = new ErrorHandler() {
382 public void warning(SAXParseException exception)
383 throws SAXException {
384 fail("Generated blueprint xml is not well formed "
385 + exception.getMessage());
389 public void fatalError(SAXParseException exception)
390 throws SAXException {
391 fail("Generated blueprint xml is not well formed "
392 + exception.getMessage());
396 public void error(SAXParseException exception) throws SAXException {
397 fail("Generated blueprint xml is not well formed "
398 + exception.getMessage());
402 for (File file : xmlFiles) {
403 DocumentBuilderFactory factory = DocumentBuilderFactory
405 factory.setValidating(false);
406 factory.setNamespaceAware(true);
408 DocumentBuilder builder = factory.newDocumentBuilder();
410 builder.setErrorHandler(errorHandler);
411 builder.parse(new InputSource(file.getPath()));
416 private void assertEventBusModuleFactory(MbeASTVisitor visitor) {
417 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
418 + ".threads.java", visitor.packageName);
419 assertEquals("EventBusModuleFactory", visitor.type);
420 assertContains(visitor.extnds,
421 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
422 + ".threads.java.AbstractEventBusModuleFactory");
424 assertEquals(0, visitor.fieldDeclarations.size());
426 assertEquals("Incorrenct number of generated methods", 0,
427 visitor.methods.size());
428 assertEquals("Incorrenct number of generated constructors", 0,
429 visitor.constructors.size());
430 assertEquals("Incorrenct number of generated method descriptions", 0,
431 visitor.methodDescriptions.size());
432 assertEquals("Incorrenct number of generated method javadoc", 0,
433 visitor.methodJavadoc.size());
436 private void assertAsyncEventBusModule(MbeASTVisitor visitor) {
437 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
438 + ".threads.java", visitor.packageName);
439 assertEquals("AsyncEventBusModule", visitor.type);
440 assertContains(visitor.extnds,
441 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
442 + ".threads.java.AbstractAsyncEventBusModule");
444 assertEquals(0, visitor.fieldDeclarations.size());
446 assertEquals("Incorrenct number of generated methods", 2,
447 visitor.methods.size());
448 assertEquals("Incorrenct number of generated constructors", 2,
449 visitor.constructors.size());
450 assertEquals("Incorrenct number of generated method descriptions", 0,
451 visitor.methodDescriptions.size());
452 assertEquals("Incorrenct number of generated method javadoc", 0,
453 visitor.methodJavadoc.size());
456 private void assertAbstractNamingThreadFactoryModuleFactory(
457 MbeASTVisitor visitor) {
458 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
459 + ".threads.java", visitor.packageName);
460 assertEquals("AbstractNamingThreadFactoryModuleFactory", visitor.type);
461 assertContains(visitor.implmts,
462 "org.opendaylight.controller.config.spi.ModuleFactory");
463 Set<String> fieldDeclarations = visitor.fieldDeclarations;
464 assertDeclaredField(fieldDeclarations,
465 "public static final java.lang.String NAME=\"threadfactory-naming\"");
468 "private static final java.util.Set<Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>> serviceIfcs=new java.util.HashSet<Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>>()");
470 assertEquals(2, fieldDeclarations.size());
473 Set<String> expectedMethods = new HashSet<>(Arrays.asList("String getImplementationName()",
474 "org.opendaylight.controller.config.spi.Module createModule(String instanceName,org.opendaylight.controller.config.api.DependencyResolver dependencyResolver)",
475 "org.opendaylight.controller.config.spi.Module createModule(String instanceName,org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,org.opendaylight.controller.config.api.DynamicMBeanWithInstance old)",
476 "org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule handleChangedClass(org.opendaylight.controller.config.api.DynamicMBeanWithInstance old)",
477 "org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule instantiateModule(String instanceName,org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule oldModule,java.lang.AutoCloseable oldInstance)",
478 "org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule instantiateModule(String instanceName,org.opendaylight.controller.config.api.DependencyResolver dependencyResolver)",
479 "java.util.Set<org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule> getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory dependencyResolverFactory)",
480 "boolean isModuleImplementingServiceInterface(Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface> serviceInterface)"));
481 assertEquals("Incorrenct number of generated methods", expectedMethods, visitor.methods);
482 assertEquals("Incorrenct number of generated method descriptions", 0,
483 visitor.methodDescriptions.size());
484 assertEquals("Incorrenct number of generated method javadoc", 0,
485 visitor.methodJavadoc.size());
489 private void assertAsyncEventBusModuleMXBean(MbeASTVisitor visitor) {
490 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
491 + ".threads.java", visitor.packageName);
492 assertEquals("AsyncEventBusModuleMXBean", visitor.type);
494 assertEquals("Incorrenct number of generated methods", 2,
495 visitor.methods.size());
498 private void assertAbstractDynamicThreadPoolModule(MbeASTVisitor visitor) {
499 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
500 + ".threads.java", visitor.packageName);
501 assertNotNull(visitor.javadoc);
502 assertContains(visitor.descriptionAnotValue,
503 "threadpool-dynamic description");
504 assertEquals("AbstractDynamicThreadPoolModule", visitor.type);
505 assertContains(visitor.implmts,
506 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
507 + ".threads.java.DynamicThreadPoolModuleMXBean",
508 Module.class.getCanonicalName(),
509 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
510 + ".threads.ScheduledThreadPoolServiceInterface",
511 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
512 + ".threads.ThreadPoolServiceInterface");
513 assertEquals(2, visitor.constructors.size());
514 Set<String> fieldDeclarations = visitor.fieldDeclarations;
515 assertDeclaredField(fieldDeclarations,
516 "private java.lang.Long maximumSize");
517 assertDeclaredField(fieldDeclarations,
518 "private javax.management.ObjectName threadfactory");
519 assertDeclaredField(fieldDeclarations,
520 "private java.util.concurrent.ThreadFactory threadfactoryDependency");
521 assertDeclaredField(fieldDeclarations,
522 "private java.lang.Long keepAlive=10");
523 assertDeclaredField(fieldDeclarations,
524 "private java.lang.Long coreSize");
525 assertDeclaredField(fieldDeclarations, "private byte[] binary");
526 assertEquals(22, fieldDeclarations.size());
528 assertEquals(1, visitor.requireIfc.size());
529 String reqIfc = visitor.requireIfc.get("setThreadfactory");
530 assertNotNull("Missing generated setter for threadfactory", reqIfc);
531 assertContains(reqIfc, PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
532 + ".threads.ThreadFactoryServiceInterface");
534 assertEquals("Incorrenct number of generated methods", 24,
535 visitor.methods.size());
536 assertEquals("Incorrenct number of generated method descriptions", 3,
537 visitor.methodDescriptions.size());
538 assertEquals("Incorrenct number of generated method javadoc", 3,
539 visitor.methodJavadoc.size());
540 assertNotNull("Missing javadoc for setMaximumSize method " + visitor.methodJavadoc,
541 visitor.methodJavadoc.get("void setMaximumSize(java.lang.Long maximumSize)"));
544 private void assertDeclaredField(Set<String> fieldDeclarations,
545 String declaration) {
546 assertTrue("Missing field " + declaration + ", got: "
548 fieldDeclarations.contains(declaration + ";\n"));
551 private static class SieASTVisitor extends ASTVisitor {
552 protected String packageName, descriptionAnotValue, sieAnnotValue,
553 sieAnnotOsgiRegistrationType, type, extnds, javadoc;
554 protected Map<String, String> methodDescriptions = Maps.newHashMap();
557 public boolean visit(PackageDeclaration node) {
558 packageName = node.getName().toString();
559 return super.visit(node);
563 public boolean visit(NormalAnnotation node) {
564 if (node.getTypeName().toString()
565 .equals(Description.class.getCanonicalName())) {
566 if (node.getParent() instanceof TypeDeclaration) {
567 descriptionAnotValue = node.values().get(0).toString();
568 } else if (node.getParent() instanceof MethodDeclaration) {
569 String descr = node.values().get(0).toString();
570 methodDescriptions.put(((MethodDeclaration) node
571 .getParent()).getName().toString(), descr);
576 .equals(ServiceInterfaceAnnotation.class.getCanonicalName())) {
577 String text1 = node.values().get(0).toString();
578 String text2 = node.values().get(1).toString();
579 if (text1.contains("value")) {
580 sieAnnotValue = text1;
581 sieAnnotOsgiRegistrationType = text2;
583 sieAnnotValue = text2;
584 sieAnnotOsgiRegistrationType = text1;
587 return super.visit(node);
591 public boolean visit(TypeDeclaration node) {
592 javadoc = node.getJavadoc() == null ? null : node.getJavadoc()
594 type = node.getName().toString();
595 List<?> superIfcs = node.superInterfaceTypes();
596 extnds = superIfcs != null && !superIfcs.isEmpty() ? superIfcs
598 return super.visit(node);
602 private static class MbeASTVisitor extends SieASTVisitor {
603 private String implmts;
604 private final Set<String> fieldDeclarations = Sets.newHashSet();
605 private final Set<String> constructors = Sets.newHashSet();
606 private final Set<String> methods = new HashSet<String>();
607 private final Map<String, String> requireIfc = Maps.newHashMap();
608 private final Map<String, String> methodJavadoc = Maps.newHashMap();
611 public boolean visit(NormalAnnotation node) {
612 boolean result = super.visit(node);
613 if (node.getTypeName().toString()
614 .equals(RequireInterface.class.getCanonicalName())
615 && node.getParent() instanceof MethodDeclaration) {
616 // remember only top level description annotation
617 String reqVal = node.values().get(0).toString();
618 requireIfc.put(((MethodDeclaration) node.getParent()).getName()
619 .toString(), reqVal);
625 public boolean visit(FieldDeclaration node) {
626 fieldDeclarations.add(node.toString());
627 return super.visit(node);
631 public boolean visit(MethodDeclaration node) {
632 if (node.isConstructor())
633 constructors.add(node.toString());
635 String methodSignature = node.getReturnType2() + " " + node.getName() + "(";
636 boolean first = true;
637 for (Object o : node.parameters()) {
641 methodSignature += ",";
643 methodSignature += o.toString();
645 methodSignature += ")";
646 methods.add(methodSignature);
647 if (node.getJavadoc() != null) {
648 methodJavadoc.put(methodSignature, node.getJavadoc().toString());
651 return super.visit(node);
655 public boolean visit(TypeDeclaration node) {
656 boolean visit = super.visit(node);
657 List<?> superIfcs = node.superInterfaceTypes();
658 implmts = superIfcs != null && !superIfcs.isEmpty() ? superIfcs
660 extnds = node.getSuperclassType() == null ? null : node
661 .getSuperclassType().toString();
667 private void assertContains(String source, String... contained) {
668 for (String string : contained) {
669 assertThat(source, containsString(string));
673 private void processGeneratedCode(Collection<File> files,
674 Map<String, ASTVisitor> verifiers) throws IOException {
675 ASTParser parser = ASTParser.newParser(AST.JLS3);
676 Map<?, ?> options = JavaCore.getOptions();
677 JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
678 parser.setCompilerOptions(options);
680 parser.setKind(ASTParser.K_COMPILATION_UNIT);
682 for (File file : files) {
683 char[] source = readFileAsChars(file);
684 parser.setSource(source);
685 parser.setResolveBindings(true);
687 CompilationUnit cu = (CompilationUnit) parser.createAST(null);
688 // Check for compilation problems in generated file
689 for (IProblem c : cu.getProblems()) {
690 // 1610613332 = Syntax error, annotations are only available if
691 // source level is 5.0
692 if (c.getID() == 1610613332)
694 // 1610613332 = Syntax error, parameterized types are only
695 // available if source level is 5.0
696 if (c.getID() == 1610613329)
698 fail("Error in generated source code " + file + ":"
699 + c.getSourceLineNumber() + " " + c.toString());
702 ASTVisitor visitor = verifiers.get(file.getName());
704 fail("Unknown generated file " + file.getName());
710 public static char[] readFileAsChars(File file) throws IOException {
711 List<String> readLines = Files
712 .readLines(file, Charset.forName("utf-8"));
713 char[] retVal = new char[0];
714 for (String string : readLines) {
715 char[] line = string.toCharArray();
716 int beforeLength = retVal.length;
717 retVal = Arrays.copyOf(retVal, retVal.length + line.length + 1);
718 System.arraycopy(line, 0, retVal, beforeLength, line.length);
719 retVal[retVal.length - 1] = '\n';