Adding script to set up sonar-project.properties

Change-Id: I6820092d57ffe9b47aef14712c522878f6f67b45
diff --git a/bucklets/onos.bucklet b/bucklets/onos.bucklet
index 8636a2a..f0730ea 100644
--- a/bucklets/onos.bucklet
+++ b/bucklets/onos.bucklet
@@ -91,6 +91,31 @@
       visibility = visibility,
 )
 
+def sonar(
+    name,
+    test = False
+    ):
+
+  cmd = '; '.join([ 'rm -f $OUT',
+          'printf "%(src_base)s = " >> $OUT',
+          '%(srcs)s >> $OUT',
+          'echo "%(binary_base)s = %(classes)s" >> $OUT',
+          'printf "%(lib_base)s = " >> $OUT',
+          '%(libraries)s >> $OUT'
+        ]) % {
+          'srcs' : "echo $(srcs :%s) | sed 's/ /,/g'" % name,
+          'classes' : ("$(bin_dir :%s#non-osgi)" if not test else "$(bin_dir :%s)") % name,
+          'libraries' : "echo $(classpath :%s) | sed 's/:/,/g'" % name,
+          'src_base' : 'sonar.sources' if not test else 'sonar.tests',
+          'binary_base' : 'sonar.java.binaries' if not test else 'sonar.java.test.binaries',
+          'lib_base' : 'sonar.java.libraries' if not test else 'sonar.java.test.libraries'
+        }
+  # FIXME do we need to specify dep here or with the expander cover it?
+  genrule(
+      name = name + "-sonar",
+      cmd = cmd,
+      out = 'sonar-project.properties'
+  )
 
 def osgi_jar(
     name = None,
@@ -206,6 +231,9 @@
     out = 'install.log',
     visibility = visibility,
   )
+  sonar(
+    name = name,
+  )
 
 def osgi_jar_with_tests(
         name = None,
@@ -223,14 +251,6 @@
   if name is None:
       name = _get_name()
 
-  osgi_jar(name = name,
-           deps = deps,
-           group_id = group_id,
-           version = version,
-           visibility = visibility,
-           tests = [':' + name + '-tests'],
-           **kwargs)
-
   if test_resources and not test_resources_root:
       test_resources_root = TEST_RESOURCES_ROOT
   if test_resources_root and not test_resources:
@@ -245,23 +265,44 @@
 
   mvn_coords = group_id + ':' + name + ':jar:tests:' + version
 
-  java_test(
-    name = name + '-tests',
-    srcs = test_srcs,
-    deps = deps +
-           test_deps +
-           [':' + name + '#non-osgi'],
-    resources = test_resources,
-    resources_root = test_resources_root,
-    maven_coords = mvn_coords,
-    visibility = visibility,
-  )
+  if test_srcs:
+      java_test(
+        name = name + '-tests',
+        srcs = test_srcs,
+        deps = deps +
+               test_deps +
+               [':' + name + '#non-osgi'],
+        resources = test_resources,
+        resources_root = test_resources_root,
+        maven_coords = mvn_coords,
+        visibility = visibility,
+      )
 
-  checkstyle(
-      name = name + '-tests',
-      srcs = test_srcs,
-      jar_target = ':' + name + '-tests',
-  )
+      checkstyle(
+          name = name + '-tests',
+          srcs = test_srcs,
+          jar_target = ':' + name + '-tests',
+      )
+
+      sonar(
+          name = name + '-tests',
+          test = True
+      )
+
+      osgi_jar(name = name,
+               deps = deps,
+               group_id = group_id,
+               version = version,
+               visibility = visibility,
+               tests = [':' + name + '-tests'],
+               **kwargs)
+  else:
+      osgi_jar(name = name,
+               deps = deps,
+               group_id = group_id,
+               version = version,
+               visibility = visibility,
+               **kwargs)
 
 def tar_file(
    name,
diff --git a/tools/build/onos-prepare-sonar b/tools/build/onos-prepare-sonar
new file mode 100755
index 0000000..bcef1d1
--- /dev/null
+++ b/tools/build/onos-prepare-sonar
@@ -0,0 +1,124 @@
+#!/usr/bin/env python
+
+# This script prepares this ONOS directory so that the Sonar Scanner can be run.
+#  - Build ONOS
+#  - Run tests on a per module basis, stage surefire-reports and jacoco.exec
+#  - Generate sonar-project.properties file
+
+import json
+import os
+
+from shutil import copy, copytree, rmtree
+from subprocess import call, check_call, check_output
+
+# SonarQube property file name and template
+FILE_NAME = 'sonar-project.properties'
+ROOT_TEMPLATE = '''# Auto-generated properties file
+sonar.projectKey=%(key)s
+sonar.projectName=%(name)s
+sonar.projectVersion=%(version)s
+ 
+#sonar.sources=src
+sonar.sourceEncoding=UTF-8
+sonar.java.target = 1.8
+sonar.java.source = 1.8
+sonar.language=java
+
+sonar.junit.reportsPath = surefire-reports
+# global jacoco
+#sonar.jacoco.reportPath = %(jacoco)s
+# local jacoco
+sonar.jacoco.reportPath = jacoco.exec
+
+sonar.modules=%(modules)s
+
+'''
+
+BUCK = 'onos-buck'
+
+# Change to $ONOS_ROOT
+ONOS_ROOT = os.environ[ 'ONOS_ROOT' ]
+if ONOS_ROOT:
+  os.chdir( ONOS_ROOT )
+
+def splitTarget(target):
+  path, module = target.split(':', 2)
+  path = path.replace('//', '', 1)
+  return path, module
+
+def runCmd(cmd):
+  output = check_output( cmd ).rstrip()
+  return output.split('\n') if output else []
+
+# TODO do we need to start with a clean slate?
+#runCmd([BUCK, 'clean'])
+
+# Find all onos_jar rules
+targets = runCmd([BUCK, 'query', "kind('onos_jar', '//...')"])
+#targets = ['//core/net:onos-core-net']
+print targets
+non_osgi_targets = ['%s#non-osgi' % t for t in targets]
+
+# Build all targets to fill buck-out/bin
+print runCmd([BUCK, 'build', '--no-cache'] + targets + non_osgi_targets)
+
+# Find all tests associated with onos_jar rules
+#FIXME we may want to insert kind('java_test', testsof...)
+output = runCmd([BUCK, 'query', '--json', "testsof('%s')"] + targets)
+test_map = json.loads(output[0])
+
+# Flatten the values in the test target map
+test_targets = [t for ts in test_map.values() for t in ts]
+print test_targets
+
+# Build run tests
+#print runCmd([BUCK, 'test', '--no-cache', '--code-coverage', '--no-results-cache'] + test_targets)
+
+# Build the sonar rules for each target
+sonar_files = runCmd([BUCK, 'build', '--show-output'] + ['%s-sonar' % t for t in (targets + test_targets)])
+sonar_files = dict([i.split(' ') for i in sonar_files[1:]]) # drop the first line; it's boilerplate
+print sonar_files
+
+
+def write_module(target, out):
+  path, module_name = splitTarget(target)
+  out.write('%s.sonar.projectBaseDir=%s\n' % ( module_name, path ))
+  out.write('%(name)s.sonar.projectName=%(name)s\n' % {'name': module_name})
+
+  tests = test_map[target] if target in test_map else []
+
+  module_targets = [target] + tests
+  for property in [sonar_files[t+'-sonar'] for t in module_targets]:
+    print property
+    with open(property, 'r') as f:
+      for line in f.readlines():
+        out.write('%s.%s' % (module_name, line))
+
+  if tests:
+    rmtree(path + '/surefire-reports', ignore_errors=True)
+    rmtree('surefire-reports', ignore_errors=True)
+    runCmd(['buck',
+            'test',
+            '--no-cache', '--no-results-cache',
+            '--code-coverage',
+            '--no-results-cache',
+            '--surefire-xml', 'surefire-reports'
+            ] + tests)
+    copy('buck-out/gen/jacoco/jacoco.exec', path)
+    #write jacoco.exec path to out; not needed.. this is the default
+    copytree('surefire-reports', path + '/surefire-reports')
+    rmtree('surefire-reports')
+
+# Write the sonar properties file
+# FIXME pull the version from the Buck version file
+with open(FILE_NAME, 'w') as out:
+  out.write(ROOT_TEMPLATE % {
+    'name': 'onos',
+    'key': 'org.onosproject:onos',
+    'version': '1.8.0-SNAPSHOT',
+    'jacoco': '%s/buck-out/gen/jacoco/jacoco.exec' % ONOS_ROOT,
+    'modules': ','.join([splitTarget(t)[1] for t in targets])
+  })
+  for target in targets:
+    print target
+    write_module(target, out)