diff --git a/build.xml b/build.xml index 3ef76bce1ac4da9f4a0ae443a906b44c5ad7e191..b53cc023666520a8c6fa6a5aad544abb4c6d22b7 100644 --- a/build.xml +++ b/build.xml @@ -250,10 +250,15 @@ <target name="coverage" depends="instrument,test,coverage-report"/> <target name="dist" depends="compile,compile-test"> + <xmlproperty file="pom.xml" prefix="pom"/> + <echo message="Setting Floodlight version: ${pom.project.version}"/> + <echo message="Setting Floodlight name: ${pom.project.name}"/> <jar destfile="${floodlight-jar}" filesetmanifest="mergewithoutmain"> <manifest> <attribute name="Main-Class" value="${main-class}"/> <attribute name="Class-Path" value="."/> + <attribute name="Implementation-Version" value="${pom.project.version}"/> + <attribute name="Implementation-Title" value="${pom.project.name}"/> </manifest> <fileset dir="${build}"/> <fileset dir="${resources}"/> diff --git a/pom.xml b/pom.xml index 6437750bdc52f935a48c50e4644ac6b7394a4498..462a5f384c0174a7e8a689757db1577421ac0924 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ <build> <plugins> <plugin> + <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.0</version> <configuration> @@ -48,6 +49,10 @@ </execution> </executions> </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + </plugin> </plugins> <pluginManagement> <plugins> @@ -83,6 +88,38 @@ </lifecycleMappingMetadata> </configuration> </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <version>2.5</version> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + <archive> + <manifestEntries> + <Class-Path>.</Class-Path> + </manifestEntries> + <manifest> + <!-- <addClasspath>true</addClasspath> + <classpathPrefix>../lib/</classpathPrefix> --> + <mainClass>net.floodlightcontroller.core.Main</mainClass> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> + </manifest> + </archive> + <appendAssemblyId>false</appendAssemblyId> + <finalName>floodlight</finalName> + </configuration> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + </plugin> </plugins> </pluginManagement> <resources> @@ -94,6 +131,12 @@ <include>README.md</include> </includes> </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + <resource> + <directory>src/test/resources</directory> + </resource> </resources> </build> <dependencies> diff --git a/src/main/java/net/floodlightcontroller/core/util/ControllerVersion.java b/src/main/java/net/floodlightcontroller/core/util/ControllerVersion.java new file mode 100644 index 0000000000000000000000000000000000000000..cc48fdf9347af7d614010cc231c8e08a2037dcc3 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/util/ControllerVersion.java @@ -0,0 +1,148 @@ +package net.floodlightcontroller.core.util; + +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; + +public class ControllerVersion { + private static final Logger log = LoggerFactory.getLogger(ControllerVersion.class); + + public synchronized static final String getFloodlightVersion() { + /* First, check our manifest to see if it's been set */ + String version = null; + String title = null; + Package pkg = ControllerVersion.class.getPackage(); + if (pkg != null) { + version = pkg.getImplementationVersion(); + if (version == null) { + version = pkg.getSpecificationVersion(); + } + if (version != null) { + version = version.trim(); + if (!version.isEmpty()) { + log.info("Floodlight version {} found in manifest", version); + return version; + } + } + title = pkg.getImplementationTitle(); + if (title == null) { + title = pkg.getSpecificationTitle(); + } + } + + + /* Try to get version number from pom.xml (available in Eclipse) */ + try { + String className = ControllerVersion.class.getName(); + String classfileName = "/" + className.replace('.', '/') + ".class"; + URL classfileResource = ControllerVersion.class.getResource(classfileName); + if (classfileResource != null) { + Path absolutePackagePath = Paths.get(classfileResource.toURI()) + .getParent(); + int packagePathSegments = className.length() + - className.replace(".", "").length(); + /* + * Remove package segments from path, plus two more levels + * for "target/classes", which is the standard location for + * classes in Eclipse. + */ + Path path = absolutePackagePath; + for (int i = 0, segmentsToRemove = packagePathSegments + 2; + i < segmentsToRemove; i++) { + path = path.getParent(); + } + Path pom = path.resolve("pom.xml"); + try (InputStream is = Files.newInputStream(pom)) { + Document doc = DocumentBuilderFactory.newInstance() + .newDocumentBuilder().parse(is); + doc.getDocumentElement().normalize(); + version = (String) XPathFactory.newInstance() + .newXPath().compile("/project/version") + .evaluate(doc, XPathConstants.STRING); + if (version != null) { + version = version.trim(); + if (version.isEmpty()) { + return "unknown"; + } else { + log.info("Floodlight version {} found in pom.xml", version); + return version; + } + } + } + } + } catch (Exception e) { } + return "unknown"; + } + + public synchronized static final String getFloodlightName() { + /* First, check our manifest to see if it's been set */ + String title = null; + Package pkg = ControllerVersion.class.getPackage(); + if (pkg != null) { + title = pkg.getImplementationTitle(); + if (title == null) { + title = pkg.getSpecificationTitle(); + } + if (title != null) { + title = title.trim(); + if (!title.isEmpty()) { + log.info("Floodlight name {} found in manifest", title); + return title; + } + } + } + + + /* Try to get version number from pom.xml (available in Eclipse) */ + try { + String className = ControllerVersion.class.getName(); + String classfileName = "/" + className.replace('.', '/') + ".class"; + URL classfileResource = ControllerVersion.class.getResource(classfileName); + if (classfileResource != null) { + Path absolutePackagePath = Paths.get(classfileResource.toURI()) + .getParent(); + int packagePathSegments = className.length() + - className.replace(".", "").length(); + /* + * Remove package segments from path, plus two more levels + * for "target/classes", which is the standard location for + * classes in Eclipse. + */ + Path path = absolutePackagePath; + for (int i = 0, segmentsToRemove = packagePathSegments + 2; + i < segmentsToRemove; i++) { + path = path.getParent(); + } + Path pom = path.resolve("pom.xml"); + try (InputStream is = Files.newInputStream(pom)) { + Document doc = DocumentBuilderFactory.newInstance() + .newDocumentBuilder().parse(is); + doc.getDocumentElement().normalize(); + title = (String) XPathFactory.newInstance() + .newXPath().compile("/project/name") + .evaluate(doc, XPathConstants.STRING); + if (title != null) { + title = title.trim(); + if (title.isEmpty()) { + return "unknown"; + } else { + log.info("Floodlight name {} found in pom.xml", title); + return title; + } + } + } + } + } catch (Exception e) { } + return "unknown"; + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/web/ControllerVersionResource.java b/src/main/java/net/floodlightcontroller/core/web/ControllerVersionResource.java new file mode 100644 index 0000000000000000000000000000000000000000..4aab0bae471bbc33f24a66c4100ae635af064215 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/web/ControllerVersionResource.java @@ -0,0 +1,40 @@ +/** +* Copyright 2011, Big Switch Networks, Inc. +* Originally created by David Erickson, Stanford University +* +* 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 net.floodlightcontroller.core.web; + +import java.util.HashMap; +import java.util.Map; + +import org.restlet.resource.Get; +import org.restlet.resource.ServerResource; + +import net.floodlightcontroller.core.util.ControllerVersion; + +/** + * Retrieve Floodlight version + * @author rizard + */ +public class ControllerVersionResource extends ServerResource { + @Get("json") + public Map<String, Object> retrieve() { + HashMap<String, Object> model = new HashMap<String, Object>(); + model.put("version", ControllerVersion.getFloodlightVersion()); + model.put("name", ControllerVersion.getFloodlightName()); + return model; + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java index effd2fb27938ef51372a8cc4d79afeb919ee5506..0bfad3a6b9a471a3ae37de46e0ef9fd6863dfa65 100644 --- a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java +++ b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java @@ -61,6 +61,7 @@ public class CoreWebRoutable implements RestletRoutable { router.attach("/role/json", ControllerRoleResource.class); router.attach("/health/json", HealthCheckResource.class); router.attach("/system/uptime/json", SystemUptimeResource.class); + router.attach("/version/json", ControllerVersionResource.class); return router; } } diff --git a/src/test/java/net/floodlightcontroller/core/util/VersionTest.java b/src/test/java/net/floodlightcontroller/core/util/VersionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..24b10ff75a51f568deba9d4bfc3ba411fd740498 --- /dev/null +++ b/src/test/java/net/floodlightcontroller/core/util/VersionTest.java @@ -0,0 +1,29 @@ +package net.floodlightcontroller.core.util; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VersionTest { + private static final Logger log = LoggerFactory.getLogger(VersionTest.class); + + @Test + public void testVersion() { + String version = ControllerVersion.getFloodlightVersion(); + if (version.equals("unknown")) { + assertTrue("Version should have been detected", false); + } + log.info("Found Floodlight version {}", version); + } + + @Test + public void testName() { + String name = ControllerVersion.getFloodlightName(); + if (name.equals("unknown")) { + assertTrue("Name should have been detected", false); + } + log.info("Found Floodlight name {}", name); + } +} \ No newline at end of file