Skip to content

Commit

Permalink
Server-side power API #179 (#429)
Browse files Browse the repository at this point in the history
  • Loading branch information
ctoomey authored and raboof committed Feb 25, 2019
1 parent 62a479c commit 4449442
Show file tree
Hide file tree
Showing 49 changed files with 1,026 additions and 420 deletions.
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ scalaVersion := scala212

val commonSettings = Seq(
organization := "com.lightbend.akka.grpc",

scalacOptions ++= List(
"-unchecked",
"-deprecation",
Expand Down Expand Up @@ -181,7 +180,7 @@ lazy val pluginTesterScala = Project(
.settings(commonSettings)
.enablePlugins(akka.grpc.NoPublish)
.settings(
ReflectiveCodeGen.codeGeneratorSettings ++= Seq("flat_package")
ReflectiveCodeGen.codeGeneratorSettings ++= Seq("flat_package", "server_power_apis")
)
.pluginTestingSettings

Expand All @@ -194,6 +193,7 @@ lazy val pluginTesterJava = Project(
.enablePlugins(akka.grpc.NoPublish)
.settings(
ReflectiveCodeGen.generatedLanguages := Seq("Java"),
ReflectiveCodeGen.codeGeneratorSettings ++= Seq("server_power_apis")
)
.pluginTestingSettings

Expand Down
90 changes: 39 additions & 51 deletions codegen/src/main/scala/akka/grpc/gen/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,14 @@ package akka.grpc.gen
import java.io.ByteArrayOutputStream

import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest
import akka.grpc.gen.javadsl.JavaBothCodeGenerator
import akka.grpc.gen.javadsl.JavaClientCodeGenerator
import akka.grpc.gen.javadsl.JavaServerCodeGenerator
import akka.grpc.gen.javadsl.{ JavaClientCodeGenerator, JavaInterfaceCodeGenerator, JavaPowerApiInterfaceCodeGenerator, JavaServerCodeGenerator }
import akka.grpc.gen.javadsl.play.{ PlayJavaClientCodeGenerator, PlayJavaServerCodeGenerator }
import akka.grpc.gen.scaladsl.ScalaBothCodeGenerator
import akka.grpc.gen.scaladsl.ScalaClientCodeGenerator
import akka.grpc.gen.scaladsl.ScalaServerCodeGenerator
import akka.grpc.gen.scaladsl.{ ScalaClientCodeGenerator, ScalaPowerApiTraitCodeGenerator, ScalaServerCodeGenerator, ScalaTraitCodeGenerator }
import akka.grpc.gen.scaladsl.play.{ PlayScalaClientCodeGenerator, PlayScalaServerCodeGenerator }

// This is the protoc plugin that the gradle plugin uses
object Main extends App {
// throw new RuntimeException(s"beginning of Main")

val inBytes: Array[Byte] = {
val baos = new ByteArrayOutputStream(math.max(64, System.in.available()))
Expand All @@ -42,71 +39,62 @@ object Main extends App {

private val generatePlay: Boolean = reqLowerCase.contains("generate_play=true")

private val serverPowerApis: Boolean = reqLowerCase.contains("server_power_apis=true")

val LogFileRegex = """(?:.*,)logfile=([^,]+)(?:,.*)?""".r
private val logger = req.getParameter match {
case LogFileRegex(path) => new FileLogger(path)
case _ => SilencedLogger
}

val out = {
val codeGenerator =
val codeGenerators =
if (!generatePlay) {
if (languageScala) {
// Scala
if (generateClient && generateServer) ScalaBothCodeGenerator
else if (generateClient) ScalaClientCodeGenerator
else if (generateServer) ScalaServerCodeGenerator
else throw new IllegalArgumentException("At least one of generateClient or generateServer must be enabled")
val base =
if (generateClient && generateServer) Seq(ScalaTraitCodeGenerator, ScalaClientCodeGenerator, ScalaServerCodeGenerator(serverPowerApis))
else if (generateClient) Seq(ScalaTraitCodeGenerator, ScalaClientCodeGenerator)
else if (generateServer) Seq(ScalaTraitCodeGenerator, ScalaServerCodeGenerator(serverPowerApis))
else throw new IllegalArgumentException("At least one of generateClient or generateServer must be enabled")
if (serverPowerApis) Seq(ScalaPowerApiTraitCodeGenerator) ++ base
else base
} else {
// Java
if (generateClient && generateServer) JavaBothCodeGenerator
else if (generateClient) JavaClientCodeGenerator
else if (generateServer) JavaServerCodeGenerator
else throw new IllegalArgumentException("At least one of generateClient or generateServer must be enabled")
val base =
if (generateClient && generateServer) Seq(JavaInterfaceCodeGenerator, JavaClientCodeGenerator, JavaServerCodeGenerator(serverPowerApis))
else if (generateClient) Seq(JavaInterfaceCodeGenerator, JavaClientCodeGenerator)
else if (generateServer) Seq(JavaInterfaceCodeGenerator, JavaServerCodeGenerator(serverPowerApis))
else throw new IllegalArgumentException("At least one of generateClient or generateServer must be enabled")
if (serverPowerApis) Seq(JavaPowerApiInterfaceCodeGenerator) ++ base
else base
}
} else {
if (languageScala) {
// Scala
if (generateClient && generateServer) CombinedPlayScalaBothCodeGenerator
else if (generateClient) CombinedPlayScalaClientCodeGenerator
else if (generateServer) CombinedPlayScalaServerCodeGenerator
else throw new IllegalArgumentException("At least one of generateClient or generateServer must be enabled")
val base =
if (generateClient && generateServer) Seq(ScalaTraitCodeGenerator, PlayScalaClientCodeGenerator, PlayScalaServerCodeGenerator(serverPowerApis))
else if (generateClient) Seq(ScalaTraitCodeGenerator, PlayScalaClientCodeGenerator)
else if (generateServer) Seq(ScalaTraitCodeGenerator, PlayScalaServerCodeGenerator(serverPowerApis))
else throw new IllegalArgumentException("At least one of generateClient or generateServer must be enabled")
if (serverPowerApis) Seq(ScalaPowerApiTraitCodeGenerator) ++ base
else base
} else {
// Java
if (generateClient && generateServer) CombinedPlayJavaBothCodeGenerator
else if (generateClient) CombinedPlayJavaClientCodeGenerator
else if (generateServer) CombinedPlayJavaServerCodeGenerator
else throw new IllegalArgumentException("At least one of generateClient or generateServer must be enabled")
val base =
if (generateClient && generateServer) Seq(JavaInterfaceCodeGenerator, JavaClientCodeGenerator, PlayJavaClientCodeGenerator, PlayJavaServerCodeGenerator(serverPowerApis))
else if (generateClient) Seq(JavaInterfaceCodeGenerator, JavaClientCodeGenerator, PlayJavaClientCodeGenerator)
else if (generateServer) Seq(JavaInterfaceCodeGenerator, PlayJavaServerCodeGenerator(serverPowerApis))
else throw new IllegalArgumentException("At least one of generateClient or generateServer must be enabled")
if (serverPowerApis) Seq(JavaPowerApiInterfaceCodeGenerator) ++ base
else base
}
}

codeGenerator.run(req, logger)
}

System.out.write(out.toByteArray)
System.out.flush()

/**
* Generators to generate both the 'plain' akka-grpc code and the play-specific code that depends on it.
* In other build tools (Maven and sbt) these are passed to protoc separately, but since Gradle does the
* akka-grpc code generation in a single protoc invocation we need to combine those here:
*/
object CombinedPlayJavaClientCodeGenerator extends PlayJavaClientCodeGenerator with JavaClientCodeGenerator {
override def name = "combined-play-java-client"
}
object CombinedPlayJavaServerCodeGenerator extends PlayJavaServerCodeGenerator with JavaServerCodeGenerator {
override def name = "combined-play-java-server"
}
object CombinedPlayJavaBothCodeGenerator extends PlayJavaClientCodeGenerator with JavaClientCodeGenerator with PlayJavaServerCodeGenerator with JavaServerCodeGenerator {
override def name = "combined-play-java-both"
}
object CombinedPlayScalaClientCodeGenerator extends PlayScalaClientCodeGenerator with ScalaClientCodeGenerator {
override def name = "combined-play-scala-client"
}
object CombinedPlayScalaServerCodeGenerator extends PlayScalaServerCodeGenerator with ScalaServerCodeGenerator {
override def name = "combined-play-scala-server"
}
object CombinedPlayScalaBothCodeGenerator extends PlayScalaClientCodeGenerator with ScalaClientCodeGenerator with PlayScalaServerCodeGenerator with ScalaServerCodeGenerator {
override def name = "combined-play-scala-both"
codeGenerators.foreach { g =>
val gout = g.run(req, logger)
System.out.write(gout.toByteArray)
System.out.flush()
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ trait JavaClientCodeGenerator extends JavaCodeGenerator {

override def perServiceContent: Set[(Logger, Service) CodeGeneratorResponse.File] =
super.perServiceContent +
JavaCodeGenerator.generateServiceFile +
generateInterface +
generateRaw

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,3 @@ abstract class JavaCodeGenerator extends CodeGenerator {
override val suggestedDependencies = (scalaBinaryVersion: CodeGenerator.ScalaBinaryVersion) => Seq(
Artifact(BuildInfo.organization, BuildInfo.runtimeArtifactName + "_" + scalaBinaryVersion.prefix, BuildInfo.version))
}

object JavaCodeGenerator {
val generateServiceFile: (Logger, Service) CodeGeneratorResponse.File = (logger, service) {
val b = CodeGeneratorResponse.File.newBuilder()
b.setContent(ApiInterface(service).body)
b.setName(s"${service.packageDir}/${service.name}.java")
logger.info(s"Generating Akka gRPC service interface for [${service.packageName}.${service.name}]")
b.build
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2018-2019 Lightbend Inc. <https://www.lightbend.com>
*/

package akka.grpc.gen.javadsl

import akka.grpc.gen.Logger
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse
import templates.JavaCommon.txt.ApiInterface

object JavaInterfaceCodeGenerator extends JavaCodeGenerator {
override def name = "akka-grpc-javadsl-interface"

override def perServiceContent: Set[(Logger, Service) CodeGeneratorResponse.File] = super.perServiceContent + generateServiceFile

val generateServiceFile: (Logger, Service) CodeGeneratorResponse.File = (logger, service) {
val b = CodeGeneratorResponse.File.newBuilder()
b.setContent(ApiInterface(service).body)
b.setName(s"${service.packageDir}/${service.name}.java")
logger.info(s"Generating Akka gRPC service interface for [${service.packageName}.${service.name}]")
b.build
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2018-2019 Lightbend Inc. <https://www.lightbend.com>
*/

package akka.grpc.gen.javadsl

import akka.grpc.gen.Logger
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse
import templates.JavaServer.txt.PowerApiInterface

object JavaPowerApiInterfaceCodeGenerator extends JavaCodeGenerator {
override def name = "akka-grpc-javadsl-power-api-interface"

override def perServiceContent: Set[(Logger, Service) CodeGeneratorResponse.File] = super.perServiceContent + generatePowerService

val generatePowerService: (Logger, Service) => CodeGeneratorResponse.File = (logger, service) => {
val b = CodeGeneratorResponse.File.newBuilder()
b.setContent(PowerApiInterface(service).body)
b.setName(s"${service.packageDir}/${service.name}PowerApi.java")
logger.info(s"Generating Akka gRPC service power interface for [${service.packageName}.${service.name}]")
b.build
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse
import protocbridge.Artifact
import templates.JavaServer.txt.Handler

trait JavaServerCodeGenerator extends JavaCodeGenerator {
case class JavaServerCodeGenerator(powerApis: Boolean = false) extends JavaCodeGenerator {
override def name = "akka-grpc-javadsl-server"

override def perServiceContent: Set[(Logger, Service) CodeGeneratorResponse.File] = super.perServiceContent +
JavaCodeGenerator.generateServiceFile + generateHandlerFactory
override def perServiceContent: Set[(Logger, Service) CodeGeneratorResponse.File] = super.perServiceContent + generateHandlerFactory() ++ (
if (powerApis) Set(generateHandlerFactory(powerApis))
else Set.empty
)

def generateHandlerFactory(logger: Logger, service: Service): CodeGeneratorResponse.File = {
val b = CodeGeneratorResponse.File.newBuilder()
b.setContent(Handler(service).body)
override val suggestedDependencies = (scalaBinaryVersion: CodeGenerator.ScalaBinaryVersion) => Seq(
Artifact(BuildInfo.organization, BuildInfo.runtimeArtifactName + "_" + scalaBinaryVersion.prefix, BuildInfo.version))

val serverPath = s"${service.packageDir}/${service.name}HandlerFactory.java"
def generateHandlerFactory(powerApis: Boolean = false): (Logger, Service) CodeGeneratorResponse.File = (logger, service) => {
val b = CodeGeneratorResponse.File.newBuilder()
b.setContent(Handler(service, powerApis).body)
val serverPath = s"${service.packageDir}/${service.name}${if (powerApis) "PowerApi" else ""}HandlerFactory.java"
b.setName(serverPath)
logger.info(s"Generating Akka gRPC service${if (powerApis) " power API" else ""} handler for ${service.packageName}.${service.name}")
b.build
}

override val suggestedDependencies = (scalaBinaryVersion: CodeGenerator.ScalaBinaryVersion) => Seq(
Artifact(BuildInfo.organization, BuildInfo.runtimeArtifactName + "_" + scalaBinaryVersion.prefix, BuildInfo.version))
}

object JavaServerCodeGenerator extends JavaServerCodeGenerator
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ trait PlayJavaClientCodeGenerator extends JavaCodeGenerator {
val b = CodeGeneratorResponse.File.newBuilder()
b.setContent(ClientProvider(service).body)
b.setName(s"${service.packageName.replace('.', '/')}/${service.name}ClientProvider.java")
logger.info(s"Generating Akka gRPC play client provider for ${service.packageName}.${service.name}")
b.build
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ import akka.grpc.gen.javadsl.{ JavaCodeGenerator, Service }
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse
import templates.PlayJavaServer.txt.Router

object PlayJavaServerCodeGenerator extends PlayJavaServerCodeGenerator

trait PlayJavaServerCodeGenerator extends JavaCodeGenerator {
case class PlayJavaServerCodeGenerator(powerApis: Boolean = false) extends JavaCodeGenerator {
override def name: String = "akka-grpc-play-server-java"

override def perServiceContent: Set[(Logger, Service) CodeGeneratorResponse.File] =
super.perServiceContent + generateRouter
override def perServiceContent = super.perServiceContent + generateRouter() ++ (
if (powerApis) Set(generateRouter(powerApis))
else Set.empty
)

private val generateRouter: (Logger, Service) => CodeGeneratorResponse.File = (logger, service) => {
private def generateRouter(powerApis: Boolean = false): (Logger, Service) => CodeGeneratorResponse.File = (logger, service) => {
val b = CodeGeneratorResponse.File.newBuilder()
b.setContent(Router(service).body)
b.setName(s"${service.packageDir}/Abstract${service.name}Router.java")
b.setContent(Router(service, powerApis).body)
b.setName(s"${service.packageDir}/Abstract${service.name}${if (powerApis) "PowerApi" else ""}Router.java")
logger.info(s"Generating Akka gRPC service${if (powerApis) " power API" else ""} play router for ${service.packageName}.${service.name}")
b.build
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import templates.ScalaClient.txt._
trait ScalaClientCodeGenerator extends ScalaCodeGenerator {
override def name = "akka-grpc-scaladsl-client"

override def perServiceContent = super.perServiceContent + ScalaCodeGenerator.generateServiceFile + generateStub
override def perServiceContent = super.perServiceContent + generateStub

def generateStub(logger: Logger, service: Service): CodeGeneratorResponse.File = {
val b = CodeGeneratorResponse.File.newBuilder()
b.setContent(Client(service).body)
b.setName(s"${service.packageDir}/${service.name}Client.scala")
logger.info(s"Generating Akka gRPC client ${service.packageName}.${service.name}")
logger.info(s"Generating Akka gRPC client for ${service.packageName}.${service.name}")
b.build
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,4 @@ abstract class ScalaCodeGenerator extends CodeGenerator {
}
}
}
object ScalaCodeGenerator {
val generateServiceFile: (Logger, Service) => CodeGeneratorResponse.File = (logger, service) => {
val b = CodeGeneratorResponse.File.newBuilder()
b.setContent(ApiTrait(service).body)
b.setName(s"${service.packageDir}/${service.name}.scala")
logger.info(s"Generating Akka gRPC service interface ${service.packageName}.${service.name}")
b.build
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
*/

package akka.grpc.gen.scaladsl

import akka.grpc.gen.Logger
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse
import templates.ScalaServer.txt.PowerApiTrait

object ScalaPowerApiTraitCodeGenerator extends ScalaCodeGenerator {
override def name = "akka-grpc-scaladsl-power-api-trait"

override def perServiceContent = super.perServiceContent + generatePowerApiTrait

val generatePowerApiTrait: (Logger, Service) => CodeGeneratorResponse.File = (logger, service) => {
val b = CodeGeneratorResponse.File.newBuilder()
b.setContent(PowerApiTrait(service).body)
b.setName(s"${service.packageDir}/${service.name}PowerApi.scala")
logger.info(s"Generating Akka gRPC service power API interface for ${service.packageName}.${service.name}")
b.build
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ import akka.grpc.gen.Logger
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse
import templates.ScalaServer.txt._

trait ScalaServerCodeGenerator extends ScalaCodeGenerator {
case class ScalaServerCodeGenerator(powerApis: Boolean = false) extends ScalaCodeGenerator {
override def name = "akka-grpc-scaladsl-server"

override def perServiceContent = super.perServiceContent + ScalaCodeGenerator.generateServiceFile + generateHandler
override def perServiceContent = super.perServiceContent + generateHandler() ++ (
if (powerApis) Set(generateHandler(powerApis))
else Set.empty
)

def generateHandler(logger: Logger, service: Service): CodeGeneratorResponse.File = {
def generateHandler(powerApis: Boolean = false): (Logger, Service) => CodeGeneratorResponse.File = (logger, service) => {
val b = CodeGeneratorResponse.File.newBuilder()
b.setContent(Handler(service).body)
b.setName(s"${service.packageDir}/${service.name}Handler.scala")
b.setContent(Handler(service, powerApis).body)
b.setName(s"${service.packageDir}/${service.name}${if (powerApis) "PowerApi" else ""}Handler.scala")
logger.info(s"Generating Akka gRPC service${if (powerApis) " power API" else ""} handler for ${service.packageName}.${service.name}")
b.build
}

}

object ScalaServerCodeGenerator extends ScalaServerCodeGenerator
Loading

0 comments on commit 4449442

Please sign in to comment.