diff --git a/.travis.yml b/.travis.yml index 0a2dc6c..7391247 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,9 @@ language: scala scala: - - 2.12.4 + - 2.13.1 script: - 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then sbt ++$TRAVIS_SCALA_VERSION test; fi' - - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then sbt ++$TRAVIS_SCALA_VERSION coverage test coverageReport coverageAggregate codacyCoverage; fi' + - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then sbt ++$TRAVIS_SCALA_VERSION test; fi' +# - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then sbt ++$TRAVIS_SCALA_VERSION coverage test coverageReport coverageAggregate codacyCoverage; fi' after_success: - - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash <(curl -s https://codecov.io/bash); fi' +# - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash <(curl -s https://codecov.io/bash); fi' diff --git a/build.sbt b/build.sbt index 5311634..67d8b21 100644 --- a/build.sbt +++ b/build.sbt @@ -1,25 +1,25 @@ name := "delphi-webapi" -version := "1.0.0-SNAPSHOT" +version := "0.9.5" -scalaVersion := "2.12.4" +scalaVersion := "2.13.1" -val akkaVersion = "2.5.16" +val akkaVersion = "2.6.1" libraryDependencies ++= Seq( "com.typesafe.akka" %% "akka-stream" % akkaVersion, "com.typesafe.akka" %% "akka-slf4j" % akkaVersion ) -val akkaHttpVersion = "10.1.5" +val akkaHttpVersion = "10.1.10" libraryDependencies ++= Seq( "com.typesafe.akka" %% "akka-http" % akkaHttpVersion, "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion, "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion ) //Including http client for elastic4s -libraryDependencies += "org.apache.httpcomponents" % "httpclient" % "4.5.3" +libraryDependencies += "org.apache.httpcomponents" % "httpclient" % "4.5.9" -val elastic4sVersion = "6.3.8" +val elastic4sVersion = "6.7.4" libraryDependencies ++= Seq( "com.sksamuel.elastic4s" %% "elastic4s-core" % elastic4sVersion, //Excluding default 4.5.2 due to https://snyk.io/vuln/SNYK-JAVA-ORGAPACHEHTTPCOMPONENTS-31517 @@ -27,13 +27,14 @@ libraryDependencies ++= Seq( "com.sksamuel.elastic4s" %% "elastic4s-http-streams" % elastic4sVersion, ) +libraryDependencies += "de.upb.cs.swt.delphi" %% "delphi-core" % "0.9.2" -libraryDependencies += "com.pauldijou" %% "jwt-core" % "1.0.0" +libraryDependencies += "com.pauldijou" %% "jwt-core" % "4.2.0" -libraryDependencies += "org.parboiled" %% "parboiled" % "2.1.4" +libraryDependencies += "org.parboiled" %% "parboiled" % "2.1.8" libraryDependencies += "io.spray" %% "spray-json" % "1.3.5" -libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.4" -libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.4" % "it,test" +libraryDependencies += "org.scalactic" %% "scalactic" % "3.1.0" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.0" % "it,test" libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3" % Runtime lazy val webapi = (project in file(".")). @@ -60,7 +61,7 @@ scalastyleConfig := baseDirectory.value / "project" / "scalastyle-config.xml" // Pinning secure versions of insecure transitive libraryDependencies // Please update when updating dependencies above (including Play plugin) libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.1" + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" ) trapExit := false diff --git a/project/plugins.sbt b/project/plugins.sbt index 77bfe2c..f15d120 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -3,8 +3,8 @@ addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0") addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.2") // coverage -addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1") -addSbtPlugin("com.codacy" % "sbt-codacy-coverage" % "1.3.14") +// addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.0") +// addSbtPlugin("com.codacy" % "sbt-codacy-coverage" % "1.3.14") // preparation for dependency checking addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.1") diff --git a/project/scalastyle-config.xml b/project/scalastyle-config.xml index 88ff84c..e8347c4 100644 --- a/project/scalastyle-config.xml +++ b/project/scalastyle-config.xml @@ -8,7 +8,7 @@ - 10 McCabe", + "name": "metrics.mccabe.>10" + }, + { + "description": "", + "internalName": "hermes.features.FanIn - Category 1", + "name": "metrics.fanin.cat1" + }, + { + "description": "", + "internalName": "hermes.features.FanIn - Category 2", + "name": "metrics.fanin.cat2" + }, + { + "description": "", + "internalName": "hermes.features.FanIn - Category 3", + "name": "metrics.fanin.cat3" + }, + { + "description": "", + "internalName": "hermes.features.FanIn - Category 4", + "name": "metrics.fanin.cat4" + }, + { + "description": "", + "internalName": "hermes.features.FanIn - Category 5", + "name": "metrics.fanin.cat5" + }, + { + "description": "", + "internalName": "hermes.features.FanIn - Category 6", + "name": "metrics.fanin.cat6" + }, + { + "description": "", + "internalName": "hermes.features.FanIn/FanOut - Category 1", + "name": "metrics.faninfanout.cat1" + }, + { + "description": "", + "internalName": "hermes.features.FanIn/FanOut - Category 2", + "name": "metrics.faninfanout.cat2" + }, + { + "description": "", + "internalName": "hermes.features.FanIn/FanOut - Category 3", + "name": "metrics.faninfanout.cat3" + }, + { + "description": "", + "internalName": "hermes.features.FanIn/FanOut - Category 4", + "name": "metrics.faninfanout.cat4" + }, + { + "description": "", + "internalName": "hermes.features.FanIn/FanOut - Category 5", + "name": "metrics.faninfanout.cat5" + }, + { + "description": "", + "internalName": "hermes.features.FanIn/FanOut - Category 6", + "name": "metrics.faninfanout.cat6" + }, + { + "description": "", + "internalName": "hermes.features.FanOut - Category 1", + "name": "metrics.fanout.cat1" + }, + { + "description": "", + "internalName": "hermes.features.FanOut - Category 2", + "name": "metrics.fanout.cat2" + }, + { + "description": "", + "internalName": "hermes.features.FanOut - Category 3", + "name": "metrics.fanout.cat3" + }, + { + "description": "", + "internalName": "hermes.features.FanOut - Category 4", + "name": "metrics.fanout.cat4" + }, + { + "description": "", + "internalName": "hermes.features.FanOut - Category 5", + "name": "metrics.fanout.cat5" + }, + { + "description": "", + "internalName": "hermes.features.FanOut - Category 6", + "name": "metrics.fanout.cat6" + }, + { + "description": "", + "internalName": "hermes.features.0 FPC", + "name": "metrics.fpc.0" + }, + { + "description": "", + "internalName": "hermes.features.1-3 FPC", + "name": "metrics.fpc.1-3" + }, + { + "description": "", + "internalName": "hermes.features.4-10 FPC", + "name": "metrics.fpc.4-10" + }, + { + "description": "", + "internalName": "hermes.features.>10 FPC", + "name": "metrics.fpc.>10" + }, + { + "description": "", + "internalName": "hermes.features.1-3 CPP", + "name": "metrics.cpp.1-3" + }, + { + "description": "", + "internalName": "hermes.features.4-10 CPP", + "name": "metrics.cpp.4-10" + }, + { + "description": "", + "internalName": "hermes.features.>10 CPP", + "name": "metrics.cpp.>10" + }, + { + "description": "", + "internalName": "hermes.features.0 NOC", + "name": "metrics.noc.0" + }, + { + "description": "", + "internalName": "hermes.features.1-3 NOC", + "name": "metrics.noc.1-3" + }, + { + "description": "", + "internalName": "hermes.features.4-10 NOC", + "name": "metrics.noc.4-10" + }, + { + "description": "", + "internalName": "hermes.features.>10 NOC", + "name": "metrics.noc.>10" + }, + { + "description": "", + "internalName": "hermes.features.0 MPC", + "name": "metrics.mpc.0" + }, + { + "description": "", + "internalName": "hermes.features.1-3 MPC", + "name": "metrics.mpc.1-3" + }, + { + "description": "", + "internalName": "hermes.features.4-10 MPC", + "name": "metrics.mpc.4-10" + }, + { + "description": "", + "internalName": "hermes.features.>10 MPC", + "name": "metrics.mpc.>10" + }, + { + "description": "", + "internalName": "hermes.features.Very Small Inheritance Tree", + "name": "metrics.inheritancetree.verysmall" + }, + { + "description": "", + "internalName": "hermes.features.Very Large Inheritance Tree", + "name": "metrics.inheritancetree.verylarge" + }, + { + "description": "", + "internalName": "hermes.features.Medium Inheritance Tree", + "name": "metrics.inheritancetree.medium" + }, + { + "description": "", + "internalName": "hermes.features.Huge Inheritance Tree", + "name": "metrics.inheritancetree.huge" + }, + { + "description": "", + "internalName": "hermes.features.Large Inheritance Tree", + "name": "metrics.inheritancetree.large" + }, + { + "description": "", + "internalName": "hermes.features.Size of the Inheritance Tree Unknown", + "name": "metrics.inheritancetree.unknown" + }, + { + "description": "", + "internalName": "hermes.features.Small Inheritance Tree", + "name": "metrics.inheritancetree.small" + }, + { + "description": "Augmented Type - Only abstract methods and three or more static final fields of the same type. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Augmented Type", + "name": "metrics.micropatterns.augmentedtype" + }, + { + "description": "Access to environment variables. Ben Hermann, Michael Reif, Michael Eichberg, and Mira Mezini. 2015. Getting to know you: towards a capability model for Java. In Proceedings of the 2015 10th Joint Meeting on Foundations of Software Engineering (ESEC/FSE 2015).", + "internalName": "hermes.features.Environment", + "name": "metrics.capabilities.environment" + }, + { + "description": "", + "internalName": "hermes.features.Class File\nJava 5", + "name": "metrics.classversion.5" + }, + { + "description": "", + "internalName": "hermes.features.Class File\nJava 7", + "name": "metrics.classversion.7" + }, + { + "description": "", + "internalName": "hermes.features.Class File\nJava 6", + "name": "metrics.classversion.6" + }, + { + "description": "", + "internalName": "hermes.features.Class File\nJava 8", + "name": "metrics.classversion.8" + }, + { + "description": "", + "internalName": "hermes.features.Class File\nJDK 1.1 (JDK 1.0.2)", + "name": "metrics.classversion.1.1" + }, + { + "description": "", + "internalName": "hermes.features.Class File\nJava 9", + "name": "metrics.classversion.9" + }, + { + "description": "", + "internalName": "hermes.features.Class File\nJDK 1", + "name": "metrics.classversion.1" + }, + { + "description": "", + "internalName": "hermes.features.custom ClassLoader implementation", + "name": "metrics.api.classloader.customimplementation" + }, + { + "description": "Number of bridge methods.", + "internalName": "hermes.features.bridge methods", + "name": "metrics.methods.bridge" + }, + { + "description": "Number of synchronized methods.", + "internalName": "hermes.features.synchronized methods", + "name": "metrics.methods.synchronized" + }, + { + "description": "Module Declarations (Java >9)", + "internalName": "hermes.features.module (Java >9)", + "name": "metrics.classtypes.moduledeclaration" + }, + { + "description": "Canopy - A class with exactly one instance field that it assigned exactly once, during instance construction. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Canopy", + "name": "metrics.micropatterns.canopy" + }, + { + "description": "Pool - A class which declares only static final fields, but no methods. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Pool", + "name": "metrics.micropatterns.pool" + }, + { + "description": "", + "internalName": "hermes.features.unused public fields", + "name": "metrics.unusedfield.public" + }, + { + "description": "Number of mutually-recursive data structures involving 2 types", + "internalName": "hermes.features.Mutually-recursive Data Structure\n2 Types", + "name": "metrics.rds.2" + }, + { + "description": "Number of mutually-recursive data structures involving more than 4 types", + "internalName": "hermes.features.Mutually-recursive Data Structure\nmore than 4 Types", + "name": "metrics.rds.>4" + }, + { + "description": "Calls to getUnsafe. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.sun.misc.Unsafe\nsun.misc.Unsafe getUnsafe()", + "name": "metrics.api.unsafe.getunsafe" + }, + { + "description": "The Array group contains methods and fields for computing relative addresses of array elements. The fields were added as a simpler and potentially faster alternative in a more recent version of Unsafe. The value of all fields in this group are constants initialized with the result of a call to either arrayBaseOffset or arrayIndexScale in the Array group. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Array", + "name": "metrics.api.unsafe.array" + }, + { + "description": "The Ordered Put group has methods to store to a Java variable without emitting any memory barrier but guaranteeing no reordering across the store. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Ordered Put", + "name": "metrics.api.unsafe.orderedput" + }, + { + "description": "The Heap group methods are used to directly access memory in the Java heap. The Heap Get and Heap Put groups allow the developer to load and store a Java variable. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Heap", + "name": "metrics.api.unsafe.heap" + }, + { + "description": "Methods of the Offset group are used to compute the location of fields within Java objects. The offsets are used in calls to many other sun.misc.Unsafe methods, for instance those in the Heap Get, Heap Put, and the CAS groups. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Offset", + "name": "metrics.api.unsafe.offset" + }, + { + "description": "The CAS group contains methods to atomically compare-and-swap a Java variable. These operations are implemented using processor-specific atomic instructions. For instance, on x86 architectures, compareAndSwapInt is implemented using the CMPXCHG machine instruction. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - compareAndSwap", + "name": "metrics.api.unsafe.compareAndSwap" + }, + { + "description": "The Off-Heap group provides access to unmanaged memory, enabling explicit memory management. Similarly to the Heap Get and Heap Put groups, the OffHeap Get and Off-Heap Put groups allow the developer to load and store values in Off-Heap memory. The usage of these methods is non-negligible, with getByte and putByte dominating the rest. The value of the ADDRESS SIZE field is the result of the method addressSize(). Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Off-Heap", + "name": "metrics.api.unsafe.offheap" + }, + { + "description": "The Heap group methods are used to directly access memory in the Java heap. The Heap Get and Heap Put groups allow the developer to load and store a Java variable. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Heap Get", + "name": "metrics.api.unsafe.heapget" + }, + { + "description": "The methods of the Fence group provide memory fences to ensure loads and stores are visible to other threads. These methods are implemented using processor-specific instructions. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Fence", + "name": "metrics.api.unsafe.fence" + }, + { + "description": "The Fetch & Add group, like the CAS group, allows the programmer to atomically update a Java variable. This group of methods was also added recently in Java 8. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Fetch & Add", + "name": "metrics.api.unsafe.fetchAndAdd" + }, + { + "description": "The Alloc group contains only the allocateInstance method, which allows the developer to allocate a Java object without executing a constructor. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Alloc", + "name": "metrics.api.unsafe.alloc" + }, + { + "description": "The throwException method is contained in the Throw group, and allows one to throw checked exceptions without declaring them in the throws clause. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Throw", + "name": "metrics.api.unsafe.throw" + }, + { + "description": "The Heap group methods are used to directly access memory in the Java heap. The Heap Get and Heap Put groups allow the developer to load and store a Java variable. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Heap Put", + "name": "metrics.api.unsafe.heapput" + }, + { + "description": "The Volatile Get and Volatile Put groups allow the developer to store a value in a Java variable with volatile semantics. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Volatile Put", + "name": "metrics.api.unsafe.volatileput" + }, + { + "description": "Methods of the Class group are used to dynamically load and check Java classes. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Class", + "name": "metrics.api.unsafe.class" + }, + { + "description": "The Monitor group contains methods to explicitly manage Java monitors. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Monitor", + "name": "metrics.api.unsafe.monitor" + }, + { + "description": "The park and unpark methods are contained in the Park group. With them, it is possible to block and unblock a thread's execution. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Park", + "name": "metrics.api.unsafe.park" + }, + { + "description": "The Volatile Get and Volatile Put groups allow the developer to store a value in a Java variable with volatile semantics. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015", + "internalName": "hermes.features.Unsafe - Volatile Get", + "name": "metrics.api.unsafe.volatileget" + }, + { + "description": "Non-functional interface with default methods (Java >8)", + "internalName": "hermes.features.non-functional interface\nwith default methods (Java >8)", + "name": "metrics.classtypes.non-functional.default" + }, + { + "description": "Number of methods that neither return normally nor abnormally.", + "internalName": "hermes.features.Method with Infinite Loop", + "name": "metrics.methods.infiniteloop" + }, + { + "description": "Number of instance methods.", + "internalName": "hermes.features.instance methods", + "name": "metrics.methods.instance" + }, + { + "description": "Number of package visible fields only used by their defining type.", + "internalName": "hermes.features.package visible fields\nonly used by defining type", + "name": "metrics.fields.packagevisiblelocal" + }, + { + "description": "", + "internalName": "hermes.features.unused private fields", + "name": "metrics.unusedfield.private" + }, + { + "description": "", + "internalName": "hermes.features.unused package visible fields", + "name": "metrics.unusedfield.packagevisible" + }, + { + "description": "", + "internalName": "hermes.features.cryptographic key handling", + "name": "metrics.api.crypto.KeyHandling" + }, + { + "description": "", + "internalName": "hermes.features.using KeyStore", + "name": "metrics.api.crypto.KeyStore" + }, + { + "description": "", + "internalName": "hermes.features.using SecureRandom", + "name": "metrics.api.crypto.SecureRandom" + }, + { + "description": "", + "internalName": "hermes.features.using MessageDigest", + "name": "metrics.api.crypto.MessageDigest" + }, + { + "description": "", + "internalName": "hermes.features.using Mac", + "name": "metrics.api.crypto.Mac" + }, + { + "description": "", + "internalName": "hermes.features.using Signature", + "name": "metrics.api.crypto.Signature" + }, + { + "description": "", + "internalName": "hermes.features.using Certificates", + "name": "metrics.api.crypto.Certificates" + }, + { + "description": "Joiner - An empty interface joining two or more superinterfaces. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Joiner", + "name": "metrics.micropatterns.joiner" + }, + { + "description": "Pseudo Class - A class which can be rewritten as an interface: no concrete methods, only static fields. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Pseudo Class", + "name": "metrics.micropatterns.pseudoclass" + }, + { + "description": "Reflective accessibility changes via Field.setAccessible", + "internalName": "hermes.features.makes fields accessible", + "name": "metrics.api.reflection.makesfieldsaccessible" + }, + { + "description": "Number of methods with a varargs parameter.", + "internalName": "hermes.features.varargs methods", + "name": "metrics.methods.varargs" + }, + { + "description": "Function Pointer - A class with a single public instance method, but with no fields. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Function Pointer", + "name": "metrics.micropatterns.functionpointer" + }, + { + "description": "Number of synthetic methods.", + "internalName": "hermes.features.synthetic methods", + "name": "metrics.methods.synthetic" + }, + { + "description": "State Machine - An interface whose methods accept no parameters. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.State Machine", + "name": "metrics.micropatterns.statemachine" + }, + { + "description": "Calls to MethodHandles.lookup", + "internalName": "hermes.features.java.lang.invoke.MethodHandles\nlookup", + "name": "metrics.api.reflection.MethodHandles.lookup" + }, + { + "description": "Calls to MethodHandles.lookup", + "internalName": "hermes.features.java.lang.invoke.MethodHandles\npublicLookup", + "name": "metrics.api.reflection.MethodHandles.publicLookup" + }, + { + "description": "Calls to java.lang.reflect.Method.invoke", + "internalName": "hermes.features.java.lang.reflect.Method\nObject invoke(Object,Object[])", + "name": "metrics.api.reflection.Method.invoke" + }, + { + "description": "Calls to Proxy.newProxyInstance", + "internalName": "hermes.features.java.lang.reflect.Proxy\nnewProxyInstance", + "name": "metrics.api.reflection.Proxy.newProxyInstance" + }, + { + "description": "Calls to Class.forName", + "internalName": "hermes.features.java.lang.Class\nforName", + "name": "metrics.api.reflection.Class.forName" + }, + { + "description": "Call to MethodHandle.invoke*", + "internalName": "hermes.features.method handle invocation", + "name": "metrics.api.reflection.methodhandleinvocation" + }, + { + "description": "Call to DriverManager.getConnection", + "internalName": "hermes.features.java.sql.DriverManager\ngetConnection", + "name": "metrics.api.jdbc.DriverManager.getConnection" + }, + { + "description": "Call to java.sql.Connection\nrollback", + "internalName": "hermes.features.java.sql.Connection\nrollback", + "name": "metrics.api.jdbc.Connection.rollback" + }, + { + "description": "(Standard) interface.", + "internalName": "hermes.features.(standard) interface", + "name": "metrics.classtypes.interface" + }, + { + "description": "", + "internalName": "hermes.features.unused protected fields", + "name": "metrics.unusedfield.protected" + }, + { + "description": "Restricted Creation - A class with no public constructors, and at least one static field of the same type as the class. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Restricted Creation", + "name": "metrics.micropatterns.restrictedcreation" + }, + { + "description": "", + "internalName": "hermes.features.Usage of Thread API", + "name": "metrics.api.thread" + }, + { + "description": "", + "internalName": "hermes.features.Usage of ThreadGroup API", + "name": "metrics.api.threadgroup" + }, + { + "description": "Cobol Like - A class with a single static method, but no instance members. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Cobol Like", + "name": "metrics.micropatterns.cobollike" + }, + { + "description": "Overrider - A class in which all methods override inherited, non-abstract methods. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Overrider", + "name": "metrics.micropatterns.overrider" + }, + { + "description": "The Misc group contains the method getLoadAverage, to get the load average in the operating system run queue assigned to the available processors. Luis Mastrangelo, et al. 2015. Use at your own risk: the Java unsafe API in the wild. OOPSLA 2015.", + "internalName": "hermes.features.Misc", + "name": "metrics.api.unsafe.misc" + }, + { + "description": "Non-functional interface with static methods (Java >8)", + "internalName": "hermes.features.non-functional interface\nwith static methods (Java >8)", + "name": "metrics.classtypes.non-functional.static" + }, + { + "description": "Number of mutually-recursive data structures involving 3 types", + "internalName": "hermes.features.Mutually-recursive Data Structure\n3 Types", + "name": "metrics.rds.3" + }, + { + "description": "Box - A class which has exactly one, mutable, instance field. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Box", + "name": "metrics.micropatterns.box" + }, + { + "description": "Stateless - A class with no fields, other than static final ones. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Stateless", + "name": "metrics.micropatterns.stateless" + }, + { + "description": "Nontrivial reflection via Class.forName.", + "internalName": "hermes.features.Nontrivial Class.forName Usage", + "name": "metrics.reflections.nontrivial" + }, + { + "description": "", + "internalName": "hermes.features.(concrete) classes", + "name": "metrics.classtypes.concrete" + }, + { + "description": "Calls to Instrumentation.getAllLoadedClasses, getInitiatedClasses, or getObjectSize.", + "internalName": "hermes.features.retrieve classes information", + "name": "metrics.api.instrumentation.retrieveclassesinformation" + }, + { + "description": "Methods with Local Variable Table", + "internalName": "hermes.features.Method With\nLocal Variable Table", + "name": "metrics.debug.methodswithlvt" + }, + { + "description": "Class File With Source Attribute", + "internalName": "hermes.features.Class File With\nSource Attribute", + "name": "metrics.debug.classsourceattribute" + }, + { + "description": "Accessing resources via a ClassLoader.", + "internalName": "hermes.features.accessing resources", + "name": "metrics.api.classloader.resourceaccess" + }, + { + "description": "Immutable - A class with several instance fields, which are assigned exactly once, during instance construction. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Immutable", + "name": "metrics.micropatterns.immutable" + }, + { + "description": "Number of static initializer methods.", + "internalName": "hermes.features.static initializers", + "name": "metrics.methods.staticinitializers" + }, + { + "description": "Number of methods that only return abnormally.", + "internalName": "hermes.features.Never Returns Normally", + "name": "metrics.methods.neverreturnsnormally" + }, + { + "description": "Data Manager - A class where all methods are either setters or getters. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Data Manager", + "name": "metrics.micropatterns.datamanager" + }, + { + "description": "Number of public fields only used by their definining type.", + "internalName": "hermes.features.public fields\nonly used by defininig type ", + "name": "metrics.fields.publicvisiblelocal" + }, + { + "description": "", + "internalName": "hermes.features.sun", + "name": "sun" + }, + { + "description": "Object-based Thread Notification (Object.notify, notifyAll, or wait).", + "internalName": "hermes.features.Object-based Thread Notification", + "name": "metrics.api.threadnotificiation" + }, + { + "description": "", + "internalName": "hermes.features.abstract classes", + "name": "metrics.classtypes.abstract" + }, + { + "description": "Usage of methods to retrieve the system class loader.", + "internalName": "hermes.features.Retrieving the SystemClassLoader", + "name": "metrics.api.classloader.SystemClassLoader" + }, + { + "description": "Taxonomy - An empty interface extending another interface. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Taxonomy", + "name": "metrics.micropatterns.taxonomy" + }, + { + "description": "Record - A class in which all fields are public, no declared methods. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Record", + "name": "metrics.micropatterns.record" + }, + { + "description": "", + "internalName": "hermes.features.marker interfaces", + "name": "metrics.classtypes.markerinterfaces" + }, + { + "description": "Methods with Line Number Table", + "internalName": "hermes.features.Method With\nLine Number Table", + "name": "metrics.debug.methodswithlnt" + }, + { + "description": "Sink - A class whose methods do not propagate calls to any other class. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Sink", + "name": "metrics.micropatterns.sink" + }, + { + "description": "Calls to Instrumentation.appendToBootstrapClassLoaderSearch or appendToSystemClassLoaderSearch.", + "internalName": "hermes.features.appending class loader search", + "name": "metrics.api.instrumentation.appendingclassloadersearch" + }, + { + "description": "Reflective accessibility changes via Method.setAccessible or Constructior.setAccessible.", + "internalName": "hermes.features.makes methods or constructors accessible", + "name": "metrics.api.reflection.makesmethodsaccessible" + }, + { + "description": "Field reads via the Reflection API", + "internalName": "hermes.features.reflective field read", + "name": "metrics.api.reflection.fieldread" + }, + { + "description": "", + "internalName": "hermes.features.enumerations", + "name": "metrics.classtypes.enumerations" + }, + { + "description": "Simple functional interfaces (single abstract method (SAM) interface).", + "internalName": "hermes.features.simple functional interfaces\n(single abstract method (SAM) interface)", + "name": "metrics.classtypes.sam" + }, + { + "description": "Usage of the Sound API. Ben Hermann, Michael Reif, Michael Eichberg, and Mira Mezini. 2015. Getting to know you: towards a capability model for Java. In Proceedings of the 2015 10th Joint Meeting on Foundations of Software Engineering (ESEC/FSE 2015).", + "internalName": "hermes.features.Sound", + "name": "metrics.capabilities.sound" + }, + { + "description": "", + "internalName": "hermes.features.annotations", + "name": "metrics.classtypes.annotations" + }, + { + "description": "Trait - An abstract class which has no state. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Trait", + "name": "metrics.micropatterns.trait" + }, + { + "description": "Usage of the JavaFX API.", + "internalName": "hermes.features.JavaFX", + "name": "metrics.api.gui.javafx" + }, + { + "description": "", + "internalName": "hermes.features.javax.crypto.Cipher\ngetInstance", + "name": "metrics.api.crypto.Cipher.getInstance" + }, + { + "description": "Compound Box - A class with exactly one non primitive instance field. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Compound Box", + "name": "metrics.micropatterns.compoundbox" + }, + { + "description": "Common State - A class in which all fields are static. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Common State", + "name": "metrics.micropatterns.commonstate" + }, + { + "description": "Designator - An interface with absolutely no members. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Designator", + "name": "metrics.micropatterns.designator" + }, + { + "description": "Usage of the AWT GUI API.", + "internalName": "hermes.features.AWT", + "name": "metrics.api.gui.awt" + }, + { + "description": "Usage of the SWT GUI API.", + "internalName": "hermes.features.SWT", + "name": "metrics.api.gui.swt" + }, + { + "description": "Trivial reflection via Class.forName.", + "internalName": "hermes.features.Trivial Class.forName Usage", + "name": "metrics.reflections.trivial" + }, + { + "description": "Creation and execution of java.sql.CallableStatement.", + "internalName": "hermes.features.creation and execution of\njava.sql.CallableStatement", + "name": "metrics.api.jdbc.CallableStatement" + }, + { + "description": "Creation and execution of java.sql.PreparedStatement.", + "internalName": "hermes.features.creation and execution of\njava.sql.PreparedStatement", + "name": "metrics.api.jdbc.PreparedStatement" + }, + { + "description": "Creation and execution of java.sql.Statement.", + "internalName": "hermes.features.creation and execution of\njava.sql.Statement", + "name": "metrics.api.jdbc.Statement" + }, + { + "description": "Function Object - A class with a single public instance method, and at least one instance field. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Function Object", + "name": "metrics.micropatterns.functionobject" + }, + { + "description": "Number of constructor methods.", + "internalName": "hermes.features.constructors", + "name": "metrics.methods.constructors" + }, + { + "description": "Methods With Local Variable Type Table", + "internalName": "hermes.features.Method With\nLocal Variable Type Table", + "name": "metrics.debug.methodswithlvtt" + }, + { + "description": "Usage of methods to retrieve some class loader.", + "internalName": "hermes.features.Retrieving some ClassLoader", + "name": "metrics.api.classloader.retrieveclassLoader" + }, + { + "description": "Sampler - A class with one or more public constructors, and at least one static field of the same type as the class. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Sampler", + "name": "metrics.micropatterns.sampler" + }, + { + "description": "Implementor - A concrete class, where all the methods override inherited abstract methods. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Implementor", + "name": "metrics.micropatterns.implementor" + }, + { + "description": "Field writes via the Reflection API", + "internalName": "hermes.features.reflective field write", + "name": "metrics.api.reflection.fieldwrite" + }, + { + "description": "Instance creation via the Reflection API", + "internalName": "hermes.features.reflective instance creation", + "name": "metrics.api.reflection.instancecreation" + }, + { + "description": "Number of self-recursive data structures.", + "internalName": "hermes.features.Self-recursive Data Structure", + "name": "metrics.rds.self" + }, + { + "description": "Number of protected fields only used by their defining type.", + "internalName": "hermes.features.protected fields\nonly used by defining type", + "name": "metrics.fieldds.protectedvisiblelocal" + }, + { + "description": "Number of mutually-recursive data structures involving 4 types", + "internalName": "hermes.features.Mutually-recursive Data Structure\n4 Types", + "name": "metrics.rds.4" + }, + { + "description": "Usage of the process capability. Ben Hermann, Michael Reif, Michael Eichberg, and Mira Mezini. 2015. Getting to know you: towards a capability model for Java. In Proceedings of the 2015 10th Joint Meeting on Foundations of Software Engineering (ESEC/FSE 2015).", + "internalName": "hermes.features.Process", + "name": "metrics.capabilities.process" + }, + { + "description": "Usage of the JVM exit capability. Ben Hermann, Michael Reif, Michael Eichberg, and Mira Mezini. 2015. Getting to know you: towards a capability model for Java. In Proceedings of the 2015 10th Joint Meeting on Foundations of Software Engineering (ESEC/FSE 2015).", + "internalName": "hermes.features.JVM exit", + "name": "metrics.capabilities.jvmexit" + }, + { + "description": "Number of static methods (not including static initializers)", + "internalName": "hermes.features.static methods\n(not including static initializers)", + "name": "metrics.methods.static" + }, + { + "description": "Pure Type - A class with only abstract methods, and no static members, and no fields. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Pure Type", + "name": "metrics.micropatterns.puretype" + }, + { + "description": "Extender - A class which extends the inherited protocol, without overriding any methods. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Extender", + "name": "metrics.micropatterns.extender" + }, + { + "description": "Reflective API calls to make an AccessibleObject accessible (exact type unknown).", + "internalName": "hermes.features.makes an AccessibleObject accessible\n(exact type unknown)", + "name": "metrics.api.reflection.makeaccessibleobjectaccessible" + }, + { + "description": "Number of native methods.", + "internalName": "hermes.features.native methods", + "name": "metrics.methods.native" + }, + { + "description": "Outline - A class where at least two methods invoke an abstract method on this. Gil, Joseph and Itay Maman. “Micro patterns in Java code.” OOPSLA '05 (2005).", + "internalName": "hermes.features.Outline", + "name": "metrics.micropatterns.outline" + }, + { + "description": "Usage of network capabilities. Ben Hermann, Michael Reif, Michael Eichberg, and Mira Mezini. 2015. Getting to know you: towards a capability model for Java. In Proceedings of the 2015 10th Joint Meeting on Foundations of Software Engineering (ESEC/FSE 2015).", + "internalName": "hermes.features.Network sockets", + "name": "metrics.capabilities.network" + }, + { + "description": "Usage of the Swing GUI API.", + "internalName": "hermes.features.Swing", + "name": "metrics.api.gui.swing" + }, + { + "description": "Calls to Instrumentation.retransformClasses, addTransformer, isModifiableClass, isRetransformClassesSupported, isRedefineClassesSupported, or redefineClasses.", + "internalName": "hermes.features.class file retransformation", + "name": "metrics.api.instrumentation.classfileretransformation" + }, + { + "description": "Calls to ClassLoader.defineClass or definePackage.", + "internalName": "hermes.features.define new classes/packages", + "name": "metrics.api.classloader.definenewclassorpackage" + }, + { + "description": "Calls to Instrumentation.setNativeMethodPrefix or isNativeMethodPrefixSupported.", + "internalName": "hermes.features.instrumenting native methods", + "name": "metrics.api.instrumentation.nativemethods" + }, + { + "description": "Usages of dynamic native library loading. Ben Hermann, Michael Reif, Michael Eichberg, and Mira Mezini. 2015. Getting to know you: towards a capability model for Java. In Proceedings of the 2015 10th Joint Meeting on Foundations of Software Engineering (ESEC/FSE 2015).", + "internalName": "hermes.features.Native Libraries", + "name": "metrics.capabilities.nativelibraryloading" + }, + { + "description": "", + "internalName": "hermes.features.aconst_null (opcode:1)", + "name": "metrics.bytecode.aconst_null" + }, + { + "description": "", + "internalName": "hermes.features.lload_1 (opcode:31)", + "name": "metrics.bytecode.lload_1" + }, + { + "description": "", + "internalName": "hermes.features.dcmpl (opcode:151)", + "name": "metrics.bytecode.dcmpl" + }, + { + "description": "", + "internalName": "hermes.features.invokedynamic (opcode:186)", + "name": "metrics.bytecode.invokedynamic" + }, + { + "description": "", + "internalName": "hermes.features.dstore_0 (opcode:71)", + "name": "metrics.bytecode.dstore_0" + }, + { + "description": "", + "internalName": "hermes.features.aastore (opcode:83)", + "name": "metrics.bytecode.aastore" + }, + { + "description": "", + "internalName": "hermes.features.land (opcode:127)", + "name": "metrics.bytecode.land" + }, + { + "description": "", + "internalName": "hermes.features.lstore_2 (opcode:65)", + "name": "metrics.bytecode.lstore_2" + }, + { + "description": "", + "internalName": "hermes.features.dup2 (opcode:92)", + "name": "metrics.bytecode.dup2" + }, + { + "description": "", + "internalName": "hermes.features.invokeinterface (opcode:185)", + "name": "metrics.bytecode.invokeinterface" + }, + { + "description": "", + "internalName": "hermes.features.castore (opcode:85)", + "name": "metrics.bytecode.castore" + }, + { + "description": "", + "internalName": "hermes.features.lshl (opcode:121)", + "name": "metrics.bytecode.lshl" + }, + { + "description": "", + "internalName": "hermes.features.irem (opcode:112)", + "name": "metrics.bytecode.irem" + }, + { + "description": "", + "internalName": "hermes.features.lushr (opcode:125)", + "name": "metrics.bytecode.lushr" + }, + { + "description": "", + "internalName": "hermes.features.dload_0 (opcode:38)", + "name": "metrics.bytecode.dload_0" + }, + { + "description": "", + "internalName": "hermes.features.ineg (opcode:116)", + "name": "metrics.bytecode.ineg" + }, + { + "description": "", + "internalName": "hermes.features.iconst_0 (opcode:3)", + "name": "metrics.bytecode.iconst_0" + }, + { + "description": "", + "internalName": "hermes.features.lastore (opcode:80)", + "name": "metrics.bytecode.lastore" + }, + { + "description": "", + "internalName": "hermes.features.dneg (opcode:119)", + "name": "metrics.bytecode.dneg" + }, + { + "description": "", + "internalName": "hermes.features.ldc (opcode:18)", + "name": "metrics.bytecode.ldc" + }, + { + "description": "", + "internalName": "hermes.features.pop2 (opcode:88)", + "name": "metrics.bytecode.pop2" + }, + { + "description": "", + "internalName": "hermes.features.lstore_0 (opcode:63)", + "name": "metrics.bytecode.lstore_0" + }, + { + "description": "", + "internalName": "hermes.features.dload_1 (opcode:39)", + "name": "metrics.bytecode.dload_1" + }, + { + "description": "", + "internalName": "hermes.features.dconst_1 (opcode:15)", + "name": "metrics.bytecode.dconst_1" + }, + { + "description": "", + "internalName": "hermes.features.if_icmplt (opcode:161)", + "name": "metrics.bytecode.if_icmplt" + }, + { + "description": "", + "internalName": "hermes.features.nop (opcode:0)", + "name": "metrics.bytecode.nop" + }, + { + "description": "", + "internalName": "hermes.features.goto (opcode:167)", + "name": "metrics.bytecode.goto" + }, + { + "description": "", + "internalName": "hermes.features.fadd (opcode:98)", + "name": "metrics.bytecode.fadd" + }, + { + "description": "", + "internalName": "hermes.features.ifgt (opcode:157)", + "name": "metrics.bytecode.ifgt" + }, + { + "description": "", + "internalName": "hermes.features.dcmpg (opcode:152)", + "name": "metrics.bytecode.dcmpg" + }, + { + "description": "", + "internalName": "hermes.features.lor (opcode:129)", + "name": "metrics.bytecode.lor" + }, + { + "description": "", + "internalName": "hermes.features.aload_0 (opcode:42)", + "name": "metrics.bytecode.aload_0" + }, + { + "description": "", + "internalName": "hermes.features.baload (opcode:51)", + "name": "metrics.bytecode.baload" + }, + { + "description": "", + "internalName": "hermes.features.daload (opcode:49)", + "name": "metrics.bytecode.daload" + }, + { + "description": "", + "internalName": "hermes.features.l2f (opcode:137)", + "name": "metrics.bytecode.l2f" + }, + { + "description": "", + "internalName": "hermes.features.if_acmpeq (opcode:165)", + "name": "metrics.bytecode.if_acmpeq" + }, + { + "description": "", + "internalName": "hermes.features.ifle (opcode:158)", + "name": "metrics.bytecode.ifle" + }, + { + "description": "", + "internalName": "hermes.features.iconst_1 (opcode:4)", + "name": "metrics.bytecode.iconst_1" + }, + { + "description": "", + "internalName": "hermes.features.newarray (opcode:188)", + "name": "metrics.bytecode.newarray" + }, + { + "description": "", + "internalName": "hermes.features.aaload (opcode:50)", + "name": "metrics.bytecode.aaload" + }, + { + "description": "", + "internalName": "hermes.features.getfield (opcode:180)", + "name": "metrics.bytecode.getfield" + }, + { + "description": "", + "internalName": "hermes.features.dstore (opcode:57)", + "name": "metrics.bytecode.dstore" + }, + { + "description": "", + "internalName": "hermes.features.istore_2 (opcode:61)", + "name": "metrics.bytecode.istore_2" + }, + { + "description": "", + "internalName": "hermes.features.ldiv (opcode:109)", + "name": "metrics.bytecode.ldiv" + }, + { + "description": "", + "internalName": "hermes.features.idiv (opcode:108)", + "name": "metrics.bytecode.idiv" + }, + { + "description": "", + "internalName": "hermes.features.istore_3 (opcode:62)", + "name": "metrics.bytecode.istore_3" + }, + { + "description": "", + "internalName": "hermes.features.fload (opcode:23)", + "name": "metrics.bytecode.fload" + }, + { + "description": "", + "internalName": "hermes.features.iadd (opcode:96)", + "name": "metrics.bytecode.iadd" + }, + { + "description": "", + "internalName": "hermes.features.getstatic (opcode:178)", + "name": "metrics.bytecode.getstatic" + }, + { + "description": "", + "internalName": "hermes.features.fconst_2 (opcode:13)", + "name": "metrics.bytecode.fconst_2" + }, + { + "description": "", + "internalName": "hermes.features.lmul (opcode:105)", + "name": "metrics.bytecode.lmul" + }, + { + "description": "", + "internalName": "hermes.features.f2l (opcode:140)", + "name": "metrics.bytecode.f2l" + }, + { + "description": "", + "internalName": "hermes.features.invokevirtual (opcode:182)", + "name": "metrics.bytecode.invokevirtual" + }, + { + "description": "", + "internalName": "hermes.features.dstore_1 (opcode:72)", + "name": "metrics.bytecode.dstore_1" + }, + { + "description": "", + "internalName": "hermes.features.i2l (opcode:133)", + "name": "metrics.bytecode.i2l" + }, + { + "description": "", + "internalName": "hermes.features.fload_1 (opcode:35)", + "name": "metrics.bytecode.fload_1" + }, + { + "description": "", + "internalName": "hermes.features.fload_0 (opcode:34)", + "name": "metrics.bytecode.fload_0" + }, + { + "description": "", + "internalName": "hermes.features.fsub (opcode:102)", + "name": "metrics.bytecode.fsub" + }, + { + "description": "", + "internalName": "hermes.features.dload (opcode:24)", + "name": "metrics.bytecode.dload" + }, + { + "description": "", + "internalName": "hermes.features.aload_1 (opcode:43)", + "name": "metrics.bytecode.aload_1" + }, + { + "description": "", + "internalName": "hermes.features.iflt (opcode:155)", + "name": "metrics.bytecode.iflt" + }, + { + "description": "", + "internalName": "hermes.features.putstatic (opcode:179)", + "name": "metrics.bytecode.putstatic" + }, + { + "description": "", + "internalName": "hermes.features.jsr (opcode:168)", + "name": "metrics.bytecode.jsr" + }, + { + "description": "", + "internalName": "hermes.features.d2f (opcode:144)", + "name": "metrics.bytecode.d2f" + }, + { + "description": "", + "internalName": "hermes.features.ifeq (opcode:153)", + "name": "metrics.bytecode.ifeq" + }, + { + "description": "", + "internalName": "hermes.features.imul (opcode:104)", + "name": "metrics.bytecode.imul" + }, + { + "description": "", + "internalName": "hermes.features.lload_0 (opcode:30)", + "name": "metrics.bytecode.lload_0" + }, + { + "description": "", + "internalName": "hermes.features.drem (opcode:115)", + "name": "metrics.bytecode.drem" + }, + { + "description": "", + "internalName": "hermes.features.aload_2 (opcode:44)", + "name": "metrics.bytecode.aload_2" + }, + { + "description": "", + "internalName": "hermes.features.swap (opcode:95)", + "name": "metrics.bytecode.swap" + }, + { + "description": "", + "internalName": "hermes.features.invokestatic (opcode:184)", + "name": "metrics.bytecode.invokestatic" + }, + { + "description": "", + "internalName": "hermes.features.dup2_x2 (opcode:94)", + "name": "metrics.bytecode.dup2_x2" + }, + { + "description": "", + "internalName": "hermes.features.fmul (opcode:106)", + "name": "metrics.bytecode.fmul" + }, + { + "description": "", + "internalName": "hermes.features.pop (opcode:87)", + "name": "metrics.bytecode.pop" + }, + { + "description": "", + "internalName": "hermes.features.ireturn (opcode:172)", + "name": "metrics.bytecode.ireturn" + }, + { + "description": "", + "internalName": "hermes.features.fconst_0 (opcode:11)", + "name": "metrics.bytecode.fconst_0" + }, + { + "description": "", + "internalName": "hermes.features.tableswitch (opcode:170)", + "name": "metrics.bytecode.tableswitch" + }, + { + "description": "", + "internalName": "hermes.features.iload_2 (opcode:28)", + "name": "metrics.bytecode.iload_2" + }, + { + "description": "", + "internalName": "hermes.features.lstore_3 (opcode:66)", + "name": "metrics.bytecode.lstore_3" + }, + { + "description": "", + "internalName": "hermes.features.iconst_5 (opcode:8)", + "name": "metrics.bytecode.iconst_5" + }, + { + "description": "", + "internalName": "hermes.features.fcmpl (opcode:149)", + "name": "metrics.bytecode.fcmpl" + }, + { + "description": "", + "internalName": "hermes.features.iconst_4 (opcode:7)", + "name": "metrics.bytecode.iconst_4" + }, + { + "description": "", + "internalName": "hermes.features.f2i (opcode:139)", + "name": "metrics.bytecode.f2i" + }, + { + "description": "", + "internalName": "hermes.features.if_icmpeq (opcode:159)", + "name": "metrics.bytecode.if_icmpeq" + }, + { + "description": "", + "internalName": "hermes.features.anewarray (opcode:189)", + "name": "metrics.bytecode.anewarray" + }, + { + "description": "", + "internalName": "hermes.features.laload (opcode:47)", + "name": "metrics.bytecode.laload" + }, + { + "description": "", + "internalName": "hermes.features.new (opcode:187)", + "name": "metrics.bytecode.new" + }, + { + "description": "", + "internalName": "hermes.features.dastore (opcode:82)", + "name": "metrics.bytecode.dastore" + }, + { + "description": "", + "internalName": "hermes.features.invokespecial (opcode:183)", + "name": "metrics.bytecode.invokespecial" + }, + { + "description": "", + "internalName": "hermes.features.istore_0 (opcode:59)", + "name": "metrics.bytecode.istore_0" + }, + { + "description": "", + "internalName": "hermes.features.astore_1 (opcode:76)", + "name": "metrics.bytecode.astore_1" + }, + { + "description": "", + "internalName": "hermes.features.ifnull (opcode:198)", + "name": "metrics.bytecode.ifnull" + }, + { + "description": "", + "internalName": "hermes.features.multianewarray (opcode:197)", + "name": "metrics.bytecode.multianewarray" + }, + { + "description": "", + "internalName": "hermes.features.astore_2 (opcode:77)", + "name": "metrics.bytecode.astore_2" + }, + { + "description": "", + "internalName": "hermes.features.dsub (opcode:103)", + "name": "metrics.bytecode.dsub" + }, + { + "description": "", + "internalName": "hermes.features.ixor (opcode:130)", + "name": "metrics.bytecode.ixor" + }, + { + "description": "", + "internalName": "hermes.features.ishl (opcode:120)", + "name": "metrics.bytecode.ishl" + }, + { + "description": "", + "internalName": "hermes.features.fdiv (opcode:110)", + "name": "metrics.bytecode.fdiv" + }, + { + "description": "", + "internalName": "hermes.features.ladd (opcode:97)", + "name": "metrics.bytecode.ladd" + }, + { + "description": "", + "internalName": "hermes.features.bipush (opcode:16)", + "name": "metrics.bytecode.bipush" + }, + { + "description": "", + "internalName": "hermes.features.if_icmpne (opcode:160)", + "name": "metrics.bytecode.if_icmpne" + }, + { + "description": "", + "internalName": "hermes.features.f2d (opcode:141)", + "name": "metrics.bytecode.f2d" + }, + { + "description": "", + "internalName": "hermes.features.astore_0 (opcode:75)", + "name": "metrics.bytecode.astore_0" + }, + { + "description": "", + "internalName": "hermes.features.dup_x2 (opcode:91)", + "name": "metrics.bytecode.dup_x2" + }, + { + "description": "", + "internalName": "hermes.features.lreturn (opcode:173)", + "name": "metrics.bytecode.lreturn" + }, + { + "description": "", + "internalName": "hermes.features.lstore_1 (opcode:64)", + "name": "metrics.bytecode.lstore_1" + }, + { + "description": "", + "internalName": "hermes.features.ior (opcode:128)", + "name": "metrics.bytecode.ior" + }, + { + "description": "", + "internalName": "hermes.features.sastore (opcode:86)", + "name": "metrics.bytecode.sastore" + }, + { + "description": "", + "internalName": "hermes.features.d2l (opcode:143)", + "name": "metrics.bytecode.d2l" + }, + { + "description": "", + "internalName": "hermes.features.l2i (opcode:136)", + "name": "metrics.bytecode.l2i" + }, + { + "description": "", + "internalName": "hermes.features.i2s (opcode:147)", + "name": "metrics.bytecode.i2s" + }, + { + "description": "", + "internalName": "hermes.features.dstore_2 (opcode:73)", + "name": "metrics.bytecode.dstore_2" + }, + { + "description": "", + "internalName": "hermes.features.d2i (opcode:142)", + "name": "metrics.bytecode.d2i" + }, + { + "description": "", + "internalName": "hermes.features.dup_x1 (opcode:90)", + "name": "metrics.bytecode.dup_x1" + }, + { + "description": "", + "internalName": "hermes.features.l2d (opcode:138)", + "name": "metrics.bytecode.l2d" + }, + { + "description": "", + "internalName": "hermes.features.iconst_2 (opcode:5)", + "name": "metrics.bytecode.iconst_2" + }, + { + "description": "", + "internalName": "hermes.features.i2f (opcode:134)", + "name": "metrics.bytecode.i2f" + }, + { + "description": "", + "internalName": "hermes.features.putfield (opcode:181)", + "name": "metrics.bytecode.putfield" + }, + { + "description": "", + "internalName": "hermes.features.dup2_x1 (opcode:93)", + "name": "metrics.bytecode.dup2_x1" + }, + { + "description": "", + "internalName": "hermes.features.saload (opcode:53)", + "name": "metrics.bytecode.saload" + }, + { + "description": "", + "internalName": "hermes.features.fstore_0 (opcode:67)", + "name": "metrics.bytecode.fstore_0" + }, + { + "description": "", + "internalName": "hermes.features.instanceof (opcode:193)", + "name": "metrics.bytecode.instanceof" + }, + { + "description": "", + "internalName": "hermes.features.fstore_3 (opcode:70)", + "name": "metrics.bytecode.fstore_3" + }, + { + "description": "", + "internalName": "hermes.features.iload_0 (opcode:26)", + "name": "metrics.bytecode.iload_0" + }, + { + "description": "", + "internalName": "hermes.features.arraylength (opcode:190)", + "name": "metrics.bytecode.arraylength" + }, + { + "description": "", + "internalName": "hermes.features.aload_3 (opcode:45)", + "name": "metrics.bytecode.aload_3" + }, + { + "description": "", + "internalName": "hermes.features.lshr (opcode:123)", + "name": "metrics.bytecode.lshr" + }, + { + "description": "", + "internalName": "hermes.features.dmul (opcode:107)", + "name": "metrics.bytecode.dmul" + }, + { + "description": "", + "internalName": "hermes.features.faload (opcode:48)", + "name": "metrics.bytecode.faload" + }, + { + "description": "", + "internalName": "hermes.features.astore (opcode:58)", + "name": "metrics.bytecode.astore" + }, + { + "description": "", + "internalName": "hermes.features.areturn (opcode:176)", + "name": "metrics.bytecode.areturn" + }, + { + "description": "", + "internalName": "hermes.features.lrem (opcode:113)", + "name": "metrics.bytecode.lrem" + }, + { + "description": "", + "internalName": "hermes.features.dup (opcode:89)", + "name": "metrics.bytecode.dup" + }, + { + "description": "", + "internalName": "hermes.features.iconst_3 (opcode:6)", + "name": "metrics.bytecode.iconst_3" + }, + { + "description": "", + "internalName": "hermes.features.checkcast (opcode:192)", + "name": "metrics.bytecode.checkcast" + }, + { + "description": "", + "internalName": "hermes.features.lstore (opcode:55)", + "name": "metrics.bytecode.lstore" + }, + { + "description": "", + "internalName": "hermes.features.fload_3 (opcode:37)", + "name": "metrics.bytecode.fload_3" + }, + { + "description": "", + "internalName": "hermes.features.fstore_2 (opcode:69)", + "name": "metrics.bytecode.fstore_2" + }, + { + "description": "", + "internalName": "hermes.features.dload_3 (opcode:41)", + "name": "metrics.bytecode.dload_3" + }, + { + "description": "", + "internalName": "hermes.features.i2c (opcode:146)", + "name": "metrics.bytecode.i2c" + }, + { + "description": "", + "internalName": "hermes.features.ifnonnull (opcode:199)", + "name": "metrics.bytecode.ifnonnull" + }, + { + "description": "", + "internalName": "hermes.features.dreturn (opcode:175)", + "name": "metrics.bytecode.dreturn" + }, + { + "description": "", + "internalName": "hermes.features.astore_3 (opcode:78)", + "name": "metrics.bytecode.astore_3" + }, + { + "description": "", + "internalName": "hermes.features.wide (opcode:196)", + "name": "metrics.bytecode.wide" + }, + { + "description": "", + "internalName": "hermes.features.ret (opcode:169)", + "name": "metrics.bytecode.ret" + }, + { + "description": "", + "internalName": "hermes.features.jsr_w (opcode:201)", + "name": "metrics.bytecode.jsr_w" + }, + { + "description": "", + "internalName": "hermes.features.fconst_1 (opcode:12)", + "name": "metrics.bytecode.fconst_1" + }, + { + "description": "", + "internalName": "hermes.features.iload_3 (opcode:29)", + "name": "metrics.bytecode.iload_3" + }, + { + "description": "", + "internalName": "hermes.features.iconst_m1 (opcode:2)", + "name": "metrics.bytecode.iconst_m1" + }, + { + "description": "", + "internalName": "hermes.features.if_icmple (opcode:164)", + "name": "metrics.bytecode.if_icmple" + }, + { + "description": "", + "internalName": "hermes.features.iload_1 (opcode:27)", + "name": "metrics.bytecode.iload_1" + }, + { + "description": "", + "internalName": "hermes.features.if_icmpge (opcode:162)", + "name": "metrics.bytecode.if_icmpge" + }, + { + "description": "", + "internalName": "hermes.features.isub (opcode:100)", + "name": "metrics.bytecode.isub" + }, + { + "description": "", + "internalName": "hermes.features.ddiv (opcode:111)", + "name": "metrics.bytecode.ddiv" + }, + { + "description": "", + "internalName": "hermes.features.monitorenter (opcode:194)", + "name": "metrics.bytecode.monitorenter" + }, + { + "description": "", + "internalName": "hermes.features.fstore_1 (opcode:68)", + "name": "metrics.bytecode.fstore_1" + }, + { + "description": "", + "internalName": "hermes.features.freturn (opcode:174)", + "name": "metrics.bytecode.freturn" + }, + { + "description": "", + "internalName": "hermes.features.iinc (opcode:132)", + "name": "metrics.bytecode.iinc" + }, + { + "description": "", + "internalName": "hermes.features.i2d (opcode:135)", + "name": "metrics.bytecode.i2d" + }, + { + "description": "", + "internalName": "hermes.features.iushr (opcode:124)", + "name": "metrics.bytecode.iushr" + }, + { + "description": "", + "internalName": "hermes.features.if_icmpgt (opcode:163)", + "name": "metrics.bytecode.if_icmpgt" + }, + { + "description": "", + "internalName": "hermes.features.iand (opcode:126)", + "name": "metrics.bytecode.iand" + }, + { + "description": "", + "internalName": "hermes.features.dload_2 (opcode:40)", + "name": "metrics.bytecode.dload_2" + }, + { + "description": "", + "internalName": "hermes.features.istore_1 (opcode:60)", + "name": "metrics.bytecode.istore_1" + }, + { + "description": "", + "internalName": "hermes.features.monitorexit (opcode:195)", + "name": "metrics.bytecode.monitorexit" + }, + { + "description": "", + "internalName": "hermes.features.fneg (opcode:118)", + "name": "metrics.bytecode.fneg" + }, + { + "description": "", + "internalName": "hermes.features.istore (opcode:54)", + "name": "metrics.bytecode.istore" + }, + { + "description": "", + "internalName": "hermes.features.lcmp (opcode:148)", + "name": "metrics.bytecode.lcmp" + }, + { + "description": "", + "internalName": "hermes.features.fcmpg (opcode:150)", + "name": "metrics.bytecode.fcmpg" + }, + { + "description": "", + "internalName": "hermes.features.caload (opcode:52)", + "name": "metrics.bytecode.caload" + }, + { + "description": "", + "internalName": "hermes.features.aload (opcode:25)", + "name": "metrics.bytecode.aload" + }, + { + "description": "", + "internalName": "hermes.features.fload_2 (opcode:36)", + "name": "metrics.bytecode.fload_2" + }, + { + "description": "", + "internalName": "hermes.features.lxor (opcode:131)", + "name": "metrics.bytecode.lxor" + }, + { + "description": "", + "internalName": "hermes.features.ldc_w (opcode:19)", + "name": "metrics.bytecode.ldc_w" + }, + { + "description": "", + "internalName": "hermes.features.lload_2 (opcode:32)", + "name": "metrics.bytecode.lload_2" + }, + { + "description": "", + "internalName": "hermes.features.lsub (opcode:101)", + "name": "metrics.bytecode.lsub" + }, + { + "description": "", + "internalName": "hermes.features.iaload (opcode:46)", + "name": "metrics.bytecode.iaload" + }, + { + "description": "", + "internalName": "hermes.features.lload_3 (opcode:33)", + "name": "metrics.bytecode.lload_3" + }, + { + "description": "", + "internalName": "hermes.features.fstore (opcode:56)", + "name": "metrics.bytecode.fstore" + }, + { + "description": "", + "internalName": "hermes.features.iastore (opcode:79)", + "name": "metrics.bytecode.iastore" + }, + { + "description": "", + "internalName": "hermes.features.fastore (opcode:81)", + "name": "metrics.bytecode.fastore" + }, + { + "description": "", + "internalName": "hermes.features.dconst_0 (opcode:14)", + "name": "metrics.bytecode.dconst_0" + }, + { + "description": "", + "internalName": "hermes.features.ifne (opcode:154)", + "name": "metrics.bytecode.ifne" + }, + { + "description": "", + "internalName": "hermes.features.lconst_0 (opcode:9)", + "name": "metrics.bytecode.lconst_0" + }, + { + "description": "", + "internalName": "hermes.features.i2b (opcode:145)", + "name": "metrics.bytecode.i2b" + }, + { + "description": "", + "internalName": "hermes.features.ishr (opcode:122)", + "name": "metrics.bytecode.ishr" + }, + { + "description": "", + "internalName": "hermes.features.lneg (opcode:117)", + "name": "metrics.bytecode.lneg" + }, + { + "description": "", + "internalName": "hermes.features.lconst_1 (opcode:10)", + "name": "metrics.bytecode.lconst_1" + }, + { + "description": "", + "internalName": "hermes.features.athrow (opcode:191)", + "name": "metrics.bytecode.athrow" + }, + { + "description": "", + "internalName": "hermes.features.bastore (opcode:84)", + "name": "metrics.bytecode.bastore" + }, + { + "description": "", + "internalName": "hermes.features.goto_w (opcode:200)", + "name": "metrics.bytecode.goto_w" + }, + { + "description": "", + "internalName": "hermes.features.dstore_3 (opcode:74)", + "name": "metrics.bytecode.dstore_3" + }, + { + "description": "", + "internalName": "hermes.features.dadd (opcode:99)", + "name": "metrics.bytecode.dadd" + }, + { + "description": "", + "internalName": "hermes.features.if_acmpne (opcode:166)", + "name": "metrics.bytecode.if_acmpne" + }, + { + "description": "", + "internalName": "hermes.features.iload (opcode:21)", + "name": "metrics.bytecode.iload" + }, + { + "description": "", + "internalName": "hermes.features.ifge (opcode:156)", + "name": "metrics.bytecode.ifge" + }, + { + "description": "", + "internalName": "hermes.features.return (opcode:177)", + "name": "metrics.bytecode.return" + }, + { + "description": "", + "internalName": "hermes.features.sipush (opcode:17)", + "name": "metrics.bytecode.sipush" + }, + { + "description": "", + "internalName": "hermes.features.frem (opcode:114)", + "name": "metrics.bytecode.frem" + }, + { + "description": "", + "internalName": "hermes.features.lookupswitch (opcode:171)", + "name": "metrics.bytecode.lookupswitch" + }, + { + "description": "", + "internalName": "hermes.features.lload (opcode:22)", + "name": "metrics.bytecode.lload" + }, + { + "description": "", + "internalName": "hermes.features.ldc2_w (opcode:20)", + "name": "metrics.bytecode.ldc2_w" + }, + { + "description": "Calls to java.lang.System.getSecurityManager", + "internalName": "hermes.features.java.lang.System\ngetSecurityManager", + "name": "metrics.security.getSecurityManager" + }, + { + "description": "Calls to java.lang.System.setSecurityManager", + "internalName": "hermes.features.java.lang.System\nsetSecurityManager", + "name": "metrics.security.setSecurityManager" + } +] \ No newline at end of file diff --git a/src/main/scala/de/upb/cs/swt/delphi/instancemanagement/InstanceRegistry.scala b/src/main/scala/de/upb/cs/swt/delphi/instancemanagement/InstanceRegistry.scala index 6a7517c..84af433 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/instancemanagement/InstanceRegistry.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/instancemanagement/InstanceRegistry.scala @@ -31,6 +31,7 @@ import spray.json._ import scala.concurrent.duration._ import scala.concurrent.{Await, Future} import scala.util.{Failure, Success, Try} +import scala.language.postfixOps object InstanceRegistry extends InstanceJsonSupport with AppLogging { diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/Configuration.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/Configuration.scala index 9573eae..6b64d09 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/Configuration.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/webapi/Configuration.scala @@ -81,7 +81,7 @@ class Configuration( //Server and Elasticsearch configuration if (hostString.count(c => c == ':') == 2) { hostString.substring(0, hostString.lastIndexOf(":")) } else { - defaultElasticSearchHost + hostString } case None => defaultElasticSearchHost diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/DelphiRoutes.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/DelphiRoutes.scala index 4fcfd8b..683425a 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/DelphiRoutes.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/webapi/DelphiRoutes.scala @@ -23,9 +23,11 @@ import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import akka.pattern.ask import akka.stream.scaladsl.Source +import de.upb.cs.swt.delphi.core.model.ArtifactJson._ +import de.upb.cs.swt.delphi.webapi.search.SearchResultsJson._ +import de.upb.cs.swt.delphi.webapi.FeatureJson._ import de.upb.cs.swt.delphi.webapi.IpLogActor._ import de.upb.cs.swt.delphi.webapi.StatisticsJson._ -import de.upb.cs.swt.delphi.webapi.artifacts.ArtifactJson._ import de.upb.cs.swt.delphi.webapi.search.QueryRequestJson._ import de.upb.cs.swt.delphi.webapi.search.{QueryRequest, SearchError, SearchQuery} import spray.json._ @@ -71,27 +73,18 @@ class DelphiRoutes(requestLimiter: RequestLimitScheduler) extends JsonSupport wi private def features = { get { - parameter('pretty.?) { (pretty) => - complete( - //TODO: Introduce failure concept for feature extractor - prettyPrint(pretty, featureExtractor.featureList.toJson) - ) - } + complete(featureExtractor.featureList.toJson) } } private def statistics = { get { - parameter('pretty.?) { (pretty) => - complete { - val result = new StatisticsQuery(configuration).retrieveStandardStatistics - result match { - case Some(stats) => { - prettyPrint(pretty, stats.toJson) - } - case _ => HttpResponse(StatusCodes.InternalServerError) - } + complete { + val result = new StatisticsQuery(configuration).retrieveStandardStatistics + result match { + case Some(stats) => stats.toJson + case _ => HttpResponse(StatusCodes.InternalServerError) } } } @@ -99,38 +92,34 @@ class DelphiRoutes(requestLimiter: RequestLimitScheduler) extends JsonSupport wi private def retrieve(identifier: String): Route = { get { - parameter('pretty.?) { (pretty) => - complete( - RetrieveQuery.retrieve(identifier) match { - case Some(result) => prettyPrint(pretty, result.toJson) - case None => HttpResponse(StatusCodes.NotFound) - } - ) - } + complete( + RetrieveQuery.retrieve(identifier) match { + case Some(result) => result.toJson + case None => HttpResponse(StatusCodes.NotFound) + } + ) } } def search: Route = { post { - parameter('pretty.?) { (pretty) => - entity(as[QueryRequest]) { input => - log.info(s"Received search query: ${input.query}") - complete( - new SearchQuery(configuration, featureExtractor).search(input) match { - case Success(result) => prettyPrint(pretty, result.toJson) - case Failure(e) => { - e match { - case se: SearchError => { - se.toJson - } - case _ => { - new SearchError("Search query failed").toJson - } + entity(as[QueryRequest]) { input => + log.info(s"Received search query: ${input.query}") + complete( + new SearchQuery(configuration, featureExtractor).search(input) match { + case Success(result) => result.toJson + case Failure(e) => { + e match { + case se: SearchError => { + HttpResponse(StatusCodes.ServerError(StatusCodes.InternalServerError.intValue)(se.toJson.toString(), "")) + } + case _ => { + HttpResponse(StatusCodes.ServerError(StatusCodes.InternalServerError.intValue)("Search query failed", "")) } } } - ) - } + } + ) } } } diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/ArtifactMetadata.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/Feature.scala similarity index 61% rename from src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/ArtifactMetadata.scala rename to src/main/scala/de/upb/cs/swt/delphi/webapi/Feature.scala index f35dbfb..390f8d7 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/ArtifactMetadata.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/webapi/Feature.scala @@ -1,4 +1,4 @@ -// Copyright (C) 2018 The Delphi Team. +// Copyright (C) 2019 The Delphi Team. // See the LICENCE file distributed with this work for additional // information regarding copyright ownership. // @@ -13,9 +13,14 @@ // 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 de.upb.cs.swt.delphi.webapi -package de.upb.cs.swt.delphi.webapi.artifacts +import spray.json.DefaultJsonProtocol -import org.joda.time.DateTime +case class Feature(name : String, description : String) +case class InternalFeature(name : String, description: String, internalName : String) -case class ArtifactMetadata(source: String, discovered: DateTime, groupId: String, artifactId: String, version: String) +object FeatureJson extends DefaultJsonProtocol { + implicit val featureFormat = jsonFormat2(Feature) + implicit val internalFeatureFormat = jsonFormat3(InternalFeature) +} diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/FeatureQuery.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/FeatureQuery.scala index 623e64f..bd09b41 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/FeatureQuery.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/webapi/FeatureQuery.scala @@ -16,38 +16,25 @@ package de.upb.cs.swt.delphi.webapi +import java.io.{BufferedWriter, File, FileWriter} + import com.sksamuel.elastic4s.http.ElasticDsl._ import com.sksamuel.elastic4s.http.{ElasticClient, RequestSuccess} import org.slf4j.LoggerFactory import spray.json._ +import de.upb.cs.swt.delphi.webapi.FeatureJson._ + +import scala.io.Source class FeatureQuery(configuration: Configuration) { private val log = LoggerFactory.getLogger(this.getClass) - lazy val featureList: Iterable[String] = { - val client = ElasticClient(configuration.elasticsearchClientUri) - val mappingRequest = client.execute { - getMapping(configuration.esProjectIndex) - }.await - - mappingRequest match { - case RequestSuccess(_, body, _, mappings) => { - val bodyJson = body.getOrElse("").parseJson.asJsObject - - bodyJson - .fields("delphi").asJsObject - .fields("mappings").asJsObject - .fields("project").asJsObject - .fields("properties").asJsObject - .fields("hermes").asJsObject - .fields("properties").asJsObject - .fields("features").asJsObject - .fields("properties").asJsObject.fields.keys - } - case _ => { - log.warn(s"Could not retrieve current feature list. Error was: $mappingRequest") - List() - } - } - } + lazy val featureList: Iterable[Feature] = + Source.fromResource("features.json") + .getLines() + .mkString("\n") + .parseJson + .asInstanceOf[JsArray] + .elements + .map(r => r.convertTo[Feature]) } diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/MavenIdentifier.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/MavenIdentifier.scala deleted file mode 100644 index 81be0c1..0000000 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/MavenIdentifier.scala +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2018 The Delphi Team. -// See the LICENCE file distributed with this work for additional -// information regarding copyright ownership. -// -// 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 de.upb.cs.swt.delphi.webapi - -import java.net.{URI, URLEncoder} -import java.nio.charset.StandardCharsets - -import de.upb.cs.swt.delphi.webapi.artifacts.Identifier - -case class MavenIdentifier(val repository: Option[String], val groupId: String, val artifactId: String, val version: Option[String]) extends Identifier { - - def toUniqueString: String = { - repository.getOrElse(MavenIdentifier.DefaultRepository) + ":" + groupId + ":" + artifactId + ":" + version.getOrElse("") - } - - override val toString: String = groupId + ":" + artifactId + ":" + version - - def toJarLocation : URI = { - constructArtifactBaseUri().resolve(encode(artifactId) + "-" + encode(version.getOrElse("")) + ".jar") - } - - def toPomLocation : URI = { - constructArtifactBaseUri().resolve(encode(artifactId) + "-" + encode(version.getOrElse("")) + ".pom") - } - - private def constructArtifactBaseUri(): URI = - new URI(repository.getOrElse(MavenIdentifier.DefaultRepository)) - .resolve(encode(groupId).replace('.', '/') + "/") - .resolve(encode(artifactId) + "/") - .resolve(encode(version.getOrElse("")) + "/") - - private def encode(input : String) : String = - URLEncoder.encode(input, StandardCharsets.UTF_8.toString()) -} - -object MavenIdentifier { - private val DefaultRepository = "http://repo1.maven.org/maven2/" - - private implicit def wrapOption[A](value : A) : Option[A] = Some(value) - - def apply(s: String): Option[MavenIdentifier] = { - val splitString: Array[String] = s.split(':') - if (splitString.length < 2 || splitString.length > 3) return None - - MavenIdentifier(None, splitString(0), splitString(1), if (splitString.length < 3) None else splitString(2)) - - } -} \ No newline at end of file diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/RetrieveQuery.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/RetrieveQuery.scala index 6c8a942..ccc44f9 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/RetrieveQuery.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/webapi/RetrieveQuery.scala @@ -19,7 +19,8 @@ package de.upb.cs.swt.delphi.webapi import com.sksamuel.elastic4s.http.ElasticDsl._ import com.sksamuel.elastic4s.http.get.GetResponse import com.sksamuel.elastic4s.http.{ElasticClient, RequestSuccess, Response} -import de.upb.cs.swt.delphi.webapi.artifacts.{Artifact, ArtifactTransformer} +import de.upb.cs.swt.delphi.core.model._ +import de.upb.cs.swt.delphi.webapi.artifacts.ArtifactTransformer object RetrieveQuery { diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/Artifact.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/Artifact.scala deleted file mode 100644 index 265409b..0000000 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/Artifact.scala +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (C) 2018 The Delphi Team. -// See the LICENCE file distributed with this work for additional -// information regarding copyright ownership. -// -// 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 de.upb.cs.swt.delphi.webapi.artifacts - -case class Artifact(id: String, metadata: ArtifactMetadata, metricResults: Map[String, Int]) diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/ArtifactJson.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/ArtifactJson.scala deleted file mode 100644 index 617815c..0000000 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/ArtifactJson.scala +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2018 The Delphi Team. -// See the LICENCE file distributed with this work for additional -// information regarding copyright ownership. -// -// 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 de.upb.cs.swt.delphi.webapi.artifacts - -import org.joda.time.DateTime -import org.joda.time.format.{DateTimeFormatter, ISODateTimeFormat} -import spray.json.{DefaultJsonProtocol, DeserializationException, JsString, JsValue, RootJsonFormat} - -object ArtifactJson extends DefaultJsonProtocol { - - implicit object DateJsonFormat extends RootJsonFormat[DateTime] { - - private val parserISO: DateTimeFormatter = ISODateTimeFormat.dateTime() - - override def write(obj: DateTime) = JsString(parserISO.print(obj)) - - override def read(json: JsValue): DateTime = json match { - case JsString(s) => parserISO.parseDateTime(s) - case _ => throw new DeserializationException("Error info you want here ...") - } - } - - implicit val artifactMetadataFormat = jsonFormat5(ArtifactMetadata) - implicit val artifactFormat = jsonFormat3(Artifact) - - def prettyPrint(pretty: Option[_], value: JsValue): String = { - pretty.isDefined match { - case true => value.sortedPrint - case false => value.compactPrint - } - } -} diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/ArtifactTransformer.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/ArtifactTransformer.scala index a34fd12..7e1e0e3 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/ArtifactTransformer.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/ArtifactTransformer.scala @@ -17,9 +17,28 @@ package de.upb.cs.swt.delphi.webapi.artifacts import com.sksamuel.elastic4s.http.search.{SearchHit, SearchHits} +import de.upb.cs.swt.delphi.core.model._ +import de.upb.cs.swt.delphi.webapi.InternalFeature import org.joda.time.format.ISODateTimeFormat +import spray.json.JsArray + +import scala.io.Source +import spray.json._ +import de.upb.cs.swt.delphi.webapi.FeatureJson._ +import de.upb.cs.swt.delphi.webapi.search.SearchResults object ArtifactTransformer { + private lazy val internalFeatures = Source.fromResource("features.json") + .getLines() + .mkString("\n") + .parseJson + .asInstanceOf[JsArray] + .elements + .map(r => r.convertTo[InternalFeature]) + + lazy val internalToExternalFeature = internalFeatures.map(i => i.internalName -> i.name).toMap + + private def getHermesResults(sourceMap: Map[String, AnyRef]): Map[String, Int] = { if (!sourceMap.contains("hermes")) return Map() @@ -28,7 +47,7 @@ object ArtifactTransformer { val hermesMap = sourceMap("hermes").asInstanceOf[Map[String, AnyRef]] - hermesMap("features").asInstanceOf[Map[String, Int]] + hermesMap("features").asInstanceOf[Map[String, Int]].map(f => (internalToExternalFeature.getOrElse("hermes.features." + f._1, f._1), f._2)) } private def getMetadata(sourceMap: Map[String, AnyRef]): ArtifactMetadata = { @@ -48,8 +67,8 @@ object ArtifactTransformer { } - def transformResults(hits: SearchHits): Array[Artifact] = { - hits.hits.map(h => transformResult(h)) + def transformResults(hits: SearchHits): SearchResults = { + SearchResults(hits.total, hits.hits.map(h => transformResult(h))) } val baseFields = Seq("source", "discovered", "identifier.groupId", "identifier.artifactId", "identifier.version") diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/Identifier.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/Identifier.scala deleted file mode 100644 index ed419b3..0000000 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/artifacts/Identifier.scala +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2018 The Delphi Team. -// See the LICENCE file distributed with this work for additional -// information regarding copyright ownership. -// -// 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 de.upb.cs.swt.delphi.webapi.artifacts - -/** - * Represents an identifier for a software artifact - */ -trait Identifier diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/authorization/AuthProvider.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/authorization/AuthProvider.scala index f03ad12..fb04dbb 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/authorization/AuthProvider.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/webapi/authorization/AuthProvider.scala @@ -15,11 +15,15 @@ // limitations under the License. package de.upb.cs.swt.delphi.webapi.authorization +import java.time.Clock + import de.upb.cs.swt.delphi.webapi import pdi.jwt.{Jwt, JwtAlgorithm, JwtClaim} object AuthProvider { + implicit val clock: Clock = Clock.systemUTC + def generateJwt(validFor: Long = 1, useGenericName: Boolean = false): String = { val claim = JwtClaim() .issuedNow diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/search/SearchQuery.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/search/SearchQuery.scala index 3caa421..9a9249f 100644 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/search/SearchQuery.scala +++ b/src/main/scala/de/upb/cs/swt/delphi/webapi/search/SearchQuery.scala @@ -20,22 +20,57 @@ import com.sksamuel.elastic4s.http.ElasticDsl._ import com.sksamuel.elastic4s.http.search.SearchHits import com.sksamuel.elastic4s.http.{ElasticClient, RequestFailure, RequestSuccess} import com.sksamuel.elastic4s.searches.queries.{NoopQuery, Query} -import de.upb.cs.swt.delphi.webapi.artifacts.{Artifact, ArtifactTransformer} -import de.upb.cs.swt.delphi.webapi.search.querylanguage._ -import de.upb.cs.swt.delphi.webapi.{Configuration, FeatureQuery} +import de.upb.cs.swt.delphi.core.model._ +import de.upb.cs.swt.delphi.core.ql._ +import de.upb.cs.swt.delphi.webapi.artifacts.ArtifactTransformer +import de.upb.cs.swt.delphi.webapi.{Configuration, Feature, FeatureQuery, InternalFeature} +import spray.json.JsArray +import scala.io.Source import scala.util.{Failure, Success, Try} +import spray.json._ +import de.upb.cs.swt.delphi.webapi.FeatureJson._ + class SearchQuery(configuration: Configuration, featureExtractor: FeatureQuery) { private val client = ElasticClient(configuration.elasticsearchClientUri) - private def checkAndExecuteParsedQuery(ast: CombinatorialExpr, limit: Int): Try[SearchHits] = { - val fields = collectFieldNames(ast) - if (fields.diff(featureExtractor.featureList.toSeq).size > 0) return Failure(new IllegalArgumentException("Unknown field name used.")) + lazy val internalFeatures = Source.fromResource("features.json") + .getLines() + .mkString("\n") + .parseJson + .asInstanceOf[JsArray] + .elements + .map(r => r.convertTo[InternalFeature]) + + lazy val externalToInternalFeature = internalFeatures.map(i => i.name -> i.internalName).toMap + + private def checkAndExecuteParsedQuery(parsedQuery: de.upb.cs.swt.delphi.core.ql.Query, limit: Int): Try[SearchHits] = { + val fields = collectFieldNames(parsedQuery.expr) + + val publicFieldNames = internalFeatures.map(i => i.name) + val invalidFields = fields.toSet.filter(f => !publicFieldNames.contains(f)) + + if (invalidFields.size > 0) return Failure(new IllegalArgumentException(s"Unknown field name(s) used. (${invalidFields.mkString(",")})")) + + val translatedFields = fields.toSet.map(externalToInternalFeature(_)) + def getPrefix (in: String) : String = { + if (in.contains("*")) { + in.substring(0, in.indexOf("*")) + } + else { + in + } + } + val selectedFields = parsedQuery + .selections + .flatMap(f => internalFeatures.filter(i => i.name.startsWith(getPrefix(f.fieldName)))) + .map(i => i.internalName) + val query = searchWithType(configuration.esProjectIndex) - .query(translate(ast)) - .sourceInclude(ArtifactTransformer.baseFields ++ fields.intersect(featureExtractor.featureList.toSeq).map(i => addPrefix(i))) + .query(translate(parsedQuery.expr)) + .sourceInclude(ArtifactTransformer.baseFields ++ translatedFields ++ selectedFields) .limit(limit) val response = client.execute { @@ -48,8 +83,6 @@ class SearchQuery(configuration: Configuration, featureExtractor: FeatureQuery) } } - private def addPrefix(fieldName: String): String = s"hermes.features.$fieldName" - private def translate(node: CombinatorialExpr): Query = { node match { case AndExpr(left, right) => bool { @@ -79,13 +112,13 @@ class SearchQuery(configuration: Configuration, featureExtractor: FeatureQuery) ) ) } - case EqualExpr(field, value) => matchQuery(addPrefix(field.fieldName), value) - case NotEqualExpr(field, value) => bool(not(matchQuery(addPrefix(field.fieldName), value))) - case GreaterThanExpr(field, value) => rangeQuery(addPrefix(field.fieldName)).gt(value.toLong) - case GreaterOrEqualExpr(field, value) => rangeQuery(addPrefix(field.fieldName)).gte(value.toLong) - case LessThanExpr(field, value) => rangeQuery(addPrefix(field.fieldName)).lt(value.toLong) - case LessOrEqualExpr(field, value) => rangeQuery(addPrefix(field.fieldName)).lte(value.toLong) - case LikeExpr(field, value) => prefixQuery(addPrefix(field.fieldName), value) + case EqualExpr(field, value) => matchQuery(externalToInternalFeature(field.fieldName), value) + case NotEqualExpr(field, value) => bool(not(matchQuery(externalToInternalFeature(field.fieldName), value))) + case GreaterThanExpr(field, value) => rangeQuery(externalToInternalFeature(field.fieldName)).gt(value.toLong) + case GreaterOrEqualExpr(field, value) => rangeQuery(externalToInternalFeature(field.fieldName)).gte(value.toLong) + case LessThanExpr(field, value) => rangeQuery(externalToInternalFeature(field.fieldName)).lt(value.toLong) + case LessOrEqualExpr(field, value) => rangeQuery(externalToInternalFeature(field.fieldName)).lte(value.toLong) + case LikeExpr(field, value) => prefixQuery(externalToInternalFeature(field.fieldName), value) case _ => NoopQuery } } @@ -127,15 +160,15 @@ class SearchQuery(configuration: Configuration, featureExtractor: FeatureQuery) } } - def search(query: QueryRequest): Try[Array[Artifact]] = { + def search(query: QueryRequest): Try[SearchResults] = { lazy val size = checkValidSize val validSize = size.exists(query.limit.getOrElse(defaultFetchSize) <= _) if (validSize) { val parserResult = new Syntax(query.query).QueryRule.run() parserResult match { case Failure(e) => Failure(e) - case Success(ast) => { - checkAndExecuteParsedQuery(ast, query.limit.getOrElse(defaultFetchSize)) match { + case Success(parsedQuery) => { + checkAndExecuteParsedQuery(parsedQuery, query.limit.getOrElse(defaultFetchSize)) match { case Failure(e) => Failure(e) case Success(hits) => Success(ArtifactTransformer.transformResults(hits)) } diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/search/SearchResults.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/search/SearchResults.scala new file mode 100644 index 0000000..ced9246 --- /dev/null +++ b/src/main/scala/de/upb/cs/swt/delphi/webapi/search/SearchResults.scala @@ -0,0 +1,12 @@ +package de.upb.cs.swt.delphi.webapi.search + +import de.upb.cs.swt.delphi.core.model.Artifact +import de.upb.cs.swt.delphi.core.model.ArtifactJson._ +import org.joda.time.DateTime +import spray.json.DefaultJsonProtocol + +case class SearchResults(totalHits : Long, hits : Array[Artifact], queried : DateTime = DateTime.now()) + +object SearchResultsJson extends DefaultJsonProtocol { + implicit val SearchResultsFormat = jsonFormat3(SearchResults) +} diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/search/querylanguage/AST.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/search/querylanguage/AST.scala deleted file mode 100644 index ccece70..0000000 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/search/querylanguage/AST.scala +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2018 The Delphi Team. -// See the LICENCE file distributed with this work for additional -// information regarding copyright ownership. -// -// 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 de.upb.cs.swt.delphi.webapi.search.querylanguage - -trait CombinatorialExpr - -case class AndExpr(left: CombinatorialExpr, right: CombinatorialExpr) extends CombinatorialExpr -case class OrExpr(left: CombinatorialExpr, right: CombinatorialExpr) extends CombinatorialExpr -case class NotExpr(expr: CombinatorialExpr) extends CombinatorialExpr -case class XorExpr(left: CombinatorialExpr, right: CombinatorialExpr) extends CombinatorialExpr - -trait SingularConditionExpr extends CombinatorialExpr - -case class EqualExpr(left: FieldReference, right: String) extends SingularConditionExpr -case class NotEqualExpr(left: FieldReference, right: String) extends SingularConditionExpr -case class GreaterThanExpr(left: FieldReference, right: String) extends SingularConditionExpr -case class GreaterOrEqualExpr(left: FieldReference, right: String) extends SingularConditionExpr -case class LessThanExpr(left: FieldReference, right: String) extends SingularConditionExpr -case class LessOrEqualExpr(left: FieldReference, right: String) extends SingularConditionExpr -case class LikeExpr(left: FieldReference, right: String) extends SingularConditionExpr -case class IsTrueExpr(fieldName: FieldReference) extends SingularConditionExpr -case class FieldReference(fieldName: String) extends CombinatorialExpr \ No newline at end of file diff --git a/src/main/scala/de/upb/cs/swt/delphi/webapi/search/querylanguage/Syntax.scala b/src/main/scala/de/upb/cs/swt/delphi/webapi/search/querylanguage/Syntax.scala deleted file mode 100644 index 2df2cb4..0000000 --- a/src/main/scala/de/upb/cs/swt/delphi/webapi/search/querylanguage/Syntax.scala +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2018 The Delphi Team. -// See the LICENCE file distributed with this work for additional -// information regarding copyright ownership. -// -// 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 de.upb.cs.swt.delphi.webapi.search.querylanguage - -import org.parboiled2.{CharPredicate, Parser, ParserInput, Rule1} - -/** - * The syntax definition and parser for the Delphi QL. - * - * @author Lisa Nguyen Quang Do - * @author Ben Hermann - * - */ -class Syntax(val input : ParserInput) extends Parser { - - def QueryRule = rule { - CombinatorialRule ~ EOI - } - - // Combinatorial rules. - def CombinatorialRule : Rule1[CombinatorialExpr] = rule { - OrOrElseRule | NotRule - } - def OrOrElseRule = rule { - AndOrElseRule ~ zeroOrMore("||" ~ AndOrElseRule ~> OrExpr) - } - def AndOrElseRule = rule { - XorOrElseRule ~ zeroOrMore("&&" ~ XorOrElseRule ~> AndExpr) - } - def XorOrElseRule = rule { - Factor ~ zeroOrMore("%%" ~ Factor ~> XorExpr) - } - - // Handling parentheses. - def Factor : Rule1[CombinatorialExpr] = rule { - Parentheses | SingularConditionRule | NotRule - } - def Parentheses = rule { '(' ~ CombinatorialRule ~ ')' } - def NotRule = rule { '!' ~ Factor ~> NotExpr } - - // Singular conditions. - def SingularConditionRule = rule { - EqualRule | NotEqualRule | GreaterThanRule | GreaterOrEqual | - LessThan | LessOrEqual | Like | IsTrue - } - def EqualRule = rule { FieldReferenceRule ~ "=" ~ Literal ~> EqualExpr } - def NotEqualRule = rule { FieldReferenceRule ~ "!=" ~ Literal ~> NotEqualExpr } - def GreaterThanRule = rule { FieldReferenceRule ~ ">" ~ Literal ~> GreaterThanExpr } - def GreaterOrEqual = rule { FieldReferenceRule ~ ">=" ~ Literal ~> GreaterOrEqualExpr } - def LessThan = rule { FieldReferenceRule ~ "<" ~ Literal ~> LessThanExpr } - def LessOrEqual = rule { FieldReferenceRule ~ "<=" ~ Literal ~> LessOrEqualExpr } - def Like = rule { FieldReferenceRule ~ "%" ~ Literal ~> LikeExpr } - def IsTrue = rule { FieldReferenceRule ~> IsTrueExpr } - - // Literals - def FieldReferenceRule = rule { "[" ~ capture(oneOrMore(CharPredicate.AlphaNum ++ '-' ++ ' ' ++ '_' ++ '(' ++ ':' ++')')) ~ "]" ~> FieldReference } - def Literal = rule { capture(oneOrMore(CharPredicate.AlphaNum)) ~> (_.toString) } -} - - diff --git a/src/test/scala/de/upb/cs/swt/delphi/webapi/MavenIdentifierApplyTest.scala b/src/test/scala/de/upb/cs/swt/delphi/webapi/MavenIdentifierApplyTest.scala deleted file mode 100644 index ae55a7c..0000000 --- a/src/test/scala/de/upb/cs/swt/delphi/webapi/MavenIdentifierApplyTest.scala +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2018 The Delphi Team. -// See the LICENCE file distributed with this work for additional -// information regarding copyright ownership. -// -// 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 de.upb.cs.swt.delphi.webapi - -import org.scalatest.{FlatSpec, Matchers} - -class MavenIdentifierApplyTest extends FlatSpec with Matchers { - "Valid identifiers with version" should "convert nicely" in { - val fullIdentifier = MavenIdentifier("log4j:log4j-test:1.4.2") - fullIdentifier match { - case Some(m) => { - m.repository.isDefined shouldBe false - m.groupId shouldBe "log4j" - m.artifactId shouldBe "log4j-test" - m.version.isDefined shouldBe true - m.version.getOrElse("") shouldBe "1.4.2" - } - case _ => fail("Identifier could not be properly parsed.") - } - } - "Valid identifiers without version" should "convert nicely" in { - val partial = MavenIdentifier("log4j:log4j-test") - partial match { - case Some(m) => { - m.repository.isDefined shouldBe false - m.groupId shouldBe "log4j" - m.artifactId shouldBe "log4j-test" - m.version.isDefined shouldBe false - } - case _ => fail("Identifier could not be properly parsed.") - } - } - - "Invalid identifiers" should "fail" in { - val invalid = MavenIdentifier("log4j") - invalid.isDefined shouldBe false - - val invalid2 = MavenIdentifier("log4j:::") - invalid2.isDefined shouldBe false - - val invalid3 = MavenIdentifier("log4j::") - invalid3.isDefined shouldBe false - - val invalid4 = MavenIdentifier("") - invalid4.isDefined shouldBe false - } -} diff --git a/src/test/scala/de/upb/cs/swt/delphi/webapi/search/querylanguage/SyntaxTest.scala b/src/test/scala/de/upb/cs/swt/delphi/webapi/search/querylanguage/SyntaxTest.scala deleted file mode 100644 index 94a79d0..0000000 --- a/src/test/scala/de/upb/cs/swt/delphi/webapi/search/querylanguage/SyntaxTest.scala +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (C) 2018 The Delphi Team. -// See the LICENCE file distributed with this work for additional -// information regarding copyright ownership. -// -// 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 de.upb.cs.swt.delphi.webapi.search.querylanguage - -import org.scalatest.{FlatSpec, Matchers} -import scala.util.{Failure, Success} - -/** - * Tests for the DelphiQL syntax. - * - * @author Lisa Nguyen Quang Do - */ -class SyntaxTest extends FlatSpec with Matchers { - - "Syntax.singularConditionWithOperator" should "be valid" in { - val parseResult = new Syntax("[Filter1]=abc").QueryRule.run() - parseResult shouldBe a [Success[_]] - parseResult match { - case Success(ast) => { - ast.toString shouldEqual "EqualExpr(FieldReference(Filter1),abc)" - } - } - } - - - "Syntax.singularConditionNoOperator" should "be valid" in { - val parseResult = new Syntax("[Filter1]").QueryRule.run() - parseResult shouldBe a [Success[_]] - parseResult match { - case Success(ast) => { - ast.toString shouldEqual "IsTrueExpr(FieldReference(Filter1))" - } - } - } - - - "Syntax.singularConditionTypo" should "be valid" in { - val parseResult = new Syntax("[Filter1]=<3").QueryRule.run() - parseResult shouldBe a [Failure[_]] - } - - "Syntax.singularConditionOddCharacters" should "be valid" in { - val parseResult = new Syntax("[Filter1]%[Filter2]%'}.:").QueryRule.run() - parseResult shouldBe a [Failure[_]] - } - - - "Syntax.combinatoryConditionSimple" should "be valid" in { - val parseResult = new Syntax("[Filter1]&&[Filter2]=3").QueryRule.run() - parseResult shouldBe a [Success[_]] - parseResult match { - case Success(ast) => { - ast.toString shouldEqual "AndExpr(IsTrueExpr(FieldReference(Filter1)),EqualExpr(FieldReference(Filter2),3))" - } - } - } - - - "Syntax.combinatoryConditionParentheses" should "be valid" in { - val parseResult = new Syntax("[Filter1]||([Filter2]&&([Filter3]<3||[Filter4]>0))").QueryRule.run() - parseResult shouldBe a [Success[_]] - parseResult match { - case Success(ast) => { - ast.toString shouldEqual "OrExpr(IsTrueExpr(FieldReference(Filter1)),AndExpr(IsTrueExpr(FieldReference(Filter2))," + - "OrExpr(LessThanExpr(FieldReference(Filter3),3),GreaterThanExpr(FieldReference(Filter4),0))))" - } - } - } - - - "Syntax.combinatoryConditionParenthesesComplex" should "be valid" in { - val parseResult = new Syntax("[Filter1]&&(([Filter2]<3||[Filter2]>0)%%([Filter4]&&[Filter5]))").QueryRule.run() - parseResult shouldBe a [Success[_]] - parseResult match { - case Success(ast) => { - ast.toString shouldEqual "AndExpr(IsTrueExpr(FieldReference(Filter1)),XorExpr(OrExpr(LessThanExpr(FieldReference(Filter2),3)," + - "GreaterThanExpr(FieldReference(Filter2),0)),AndExpr(IsTrueExpr(FieldReference(Filter4)),IsTrueExpr(FieldReference(Filter5)))))" - } - } - } - - - "Syntax.combinatoryConditionNonMatchingParentheses" should "be valid" in { - val parseResult = new Syntax("[Filter1]&&([Filter2]<3||[Filter2]>0%%([Filter4])").QueryRule.run() - parseResult shouldBe a [Failure[_]] - } - - "Syntax.combinatoryConditionTypo" should "be valid" in { - val parseResult = new Syntax("[Filter1]&[Filter2]<3)").QueryRule.run() - parseResult shouldBe a [Failure[_]] - } - - "Syntax.combinatoryConditionLeftToRightPriority" should "be valid" in { - val parseResult = new Syntax("[Filter1]&&[Filter2]&&[Filter3]").QueryRule.run() - parseResult shouldBe a [Success[_]] - parseResult match { - case Success(ast) => { - ast.toString shouldEqual "AndExpr(AndExpr(IsTrueExpr(FieldReference(Filter1))," + - "IsTrueExpr(FieldReference(Filter2))),IsTrueExpr(FieldReference(Filter3)))" - } - } - } - - "Syntax.combinatoryConditionOperatorPriorities" should "be valid" in { - val parseResult = new Syntax("[Filter1]||[Filter2]%%![Filter3]&&[Filter4]").QueryRule.run() - parseResult shouldBe a [Success[_]] - parseResult match { - case Success(ast) => { - ast.toString shouldEqual "OrExpr(IsTrueExpr(FieldReference(Filter1)),AndExpr(XorExpr(" + - "IsTrueExpr(FieldReference(Filter2)),NotExpr(IsTrueExpr(FieldReference(Filter3)))),IsTrueExpr(FieldReference(Filter4))))" - } - } - } - - - "Syntax.combinatoryConditionOperatorPrioritiesParentheses" should "be valid" in { - val parseResult = new Syntax("([Filter1]||[Filter2])&&![Filter3]%%!([Filter4]&&[Filter5])").QueryRule.run() - parseResult shouldBe a [Success[_]] - parseResult match { - case Success(ast) => { - ast.toString shouldEqual "AndExpr(OrExpr(IsTrueExpr(FieldReference(Filter1)),IsTrueExpr(FieldReference(Filter2)))," + - "XorExpr(NotExpr(IsTrueExpr(FieldReference(Filter3))),NotExpr(AndExpr(IsTrueExpr(FieldReference(Filter4))," + - "IsTrueExpr(FieldReference(Filter5))))))" - } - } - } - - - "Syntax.notConditionSimple" should "be valid" in { - val parseResult = new Syntax("![Filter1]&&!([Filter2])").QueryRule.run() - parseResult shouldBe a [Success[_]] - parseResult match { - case Success(ast) => { - ast.toString shouldEqual "AndExpr(NotExpr(IsTrueExpr(FieldReference(Filter1)))," + - "NotExpr(IsTrueExpr(FieldReference(Filter2))))" - } - } - } - - "Syntax.notConditionSimpleParentheses" should "be valid" in { - val parseResult = new Syntax("!([Filter1]&&![Filter2])").QueryRule.run() - parseResult shouldBe a [Success[_]] - parseResult match { - case Success(ast) => { - ast.toString shouldEqual "NotExpr(AndExpr(IsTrueExpr(FieldReference(Filter1))," + - "NotExpr(IsTrueExpr(FieldReference(Filter2)))))" - } - } - } - - "Syntax.notConditionComplex" should "be valid" in { - val parseResult = new Syntax("!!([Filter1])&&!([Filter2]<=0||!([Filter3]&&![Filter4]%abc))").QueryRule.run() - parseResult shouldBe a [Success[_]] - parseResult match { - case Success(ast) => { - ast.toString shouldEqual "AndExpr(NotExpr(NotExpr(IsTrueExpr(FieldReference(Filter1))))," + - "NotExpr(OrExpr(LessOrEqualExpr(FieldReference(Filter2),0),NotExpr(AndExpr(IsTrueExpr(FieldReference(Filter3))," + - "NotExpr(LikeExpr(FieldReference(Filter4),abc)))))))" - } - } - } -} \ No newline at end of file