diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpConnector.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpConnector.scala index a4d3bec2c5..7aded4618c 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpConnector.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpConnector.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp import akka.stream.stage.GraphStageLogic diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpRpcFlowStage.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpRpcFlowStage.scala index c93a80b33d..a062e69095 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpRpcFlowStage.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpRpcFlowStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp import java.util.concurrent.atomic.AtomicInteger diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpSinkStage.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpSinkStage.scala index a77bef73bd..00aef22612 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpSinkStage.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpSinkStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp import java.util.Optional diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpSourceStage.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpSourceStage.scala index 2a72942e1d..c807083363 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpSourceStage.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/AmqpSourceStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp import java.util.concurrent.atomic.AtomicInteger diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/AmqpRpcFlow.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/AmqpRpcFlow.scala index 1bd4f1f966..65413533a7 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/AmqpRpcFlow.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/AmqpRpcFlow.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp.javadsl import java.util.concurrent.CompletionStage diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/AmqpSink.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/AmqpSink.scala index 865c0cda9f..503cb79a15 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/AmqpSink.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/AmqpSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp.javadsl import java.util.concurrent.CompletionStage diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/AmqpSource.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/AmqpSource.scala index 0fc91872a1..16a54344aa 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/AmqpSource.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/AmqpSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp.javadsl import akka.NotUsed diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/CommittableIncomingMessage.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/CommittableIncomingMessage.scala index 4477303664..e536987146 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/CommittableIncomingMessage.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/CommittableIncomingMessage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp.javadsl import java.util.concurrent.CompletionStage @@ -12,4 +13,4 @@ trait CommittableIncomingMessage { val message: IncomingMessage def ack(multiple: Boolean = false): CompletionStage[Done] def nack(multiple: Boolean = false, requeue: Boolean = true): CompletionStage[Done] -} \ No newline at end of file +} diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/package.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/package.scala index e93fdc7321..57b2e5daac 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/package.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/javadsl/package.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp import java.util.concurrent.CompletionStage diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/model.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/model.scala index af0bffe3e3..4be6dd0c79 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/model.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/model.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp import com.rabbitmq.client.ExceptionHandler diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/package.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/package.scala index 87d10a6068..68460e6b3c 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/package.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/package.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka package object amqp { diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/AmqpRpcFlow.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/AmqpRpcFlow.scala index b57da3c31e..2f65a52ca1 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/AmqpRpcFlow.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/AmqpRpcFlow.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp.scaladsl import akka.dispatch.ExecutionContexts diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/AmqpSink.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/AmqpSink.scala index 04dd5157a0..d18afb9991 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/AmqpSink.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/AmqpSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp.scaladsl import akka.Done diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/AmqpSource.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/AmqpSource.scala index 0d5c739416..6574829087 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/AmqpSource.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/AmqpSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp.scaladsl import akka.NotUsed diff --git a/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/CommittableIncomingMessage.scala b/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/CommittableIncomingMessage.scala index b23b108a87..a0fefc4e85 100644 --- a/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/CommittableIncomingMessage.scala +++ b/amqp/src/main/scala/akka/stream/alpakka/amqp/scaladsl/CommittableIncomingMessage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp.scaladsl import akka.Done diff --git a/amqp/src/test/java/akka/stream/alpakka/amqp/javadsl/AmqpConnectorsTest.java b/amqp/src/test/java/akka/stream/alpakka/amqp/javadsl/AmqpConnectorsTest.java index 44f6110595..894483d4f3 100644 --- a/amqp/src/test/java/akka/stream/alpakka/amqp/javadsl/AmqpConnectorsTest.java +++ b/amqp/src/test/java/akka/stream/alpakka/amqp/javadsl/AmqpConnectorsTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp.javadsl; import static org.junit.Assert.assertEquals; diff --git a/amqp/src/test/java/akka/stream/alpakka/amqp/javadsl/package.scala b/amqp/src/test/java/akka/stream/alpakka/amqp/javadsl/package.scala index 17080680ab..254f82ecce 100644 --- a/amqp/src/test/java/akka/stream/alpakka/amqp/javadsl/package.scala +++ b/amqp/src/test/java/akka/stream/alpakka/amqp/javadsl/package.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp import java.util.concurrent.CompletionStage diff --git a/amqp/src/test/scala/akka/stream/alpakka/amqp/AmqpSpec.scala b/amqp/src/test/scala/akka/stream/alpakka/amqp/AmqpSpec.scala index e558adbd1c..fcec20dc28 100644 --- a/amqp/src/test/scala/akka/stream/alpakka/amqp/AmqpSpec.scala +++ b/amqp/src/test/scala/akka/stream/alpakka/amqp/AmqpSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp import akka.actor.ActorSystem diff --git a/amqp/src/test/scala/akka/stream/alpakka/amqp/scaladsl/AmqpConnectorsSpec.scala b/amqp/src/test/scala/akka/stream/alpakka/amqp/scaladsl/AmqpConnectorsSpec.scala index 8cf7693ae9..15700da91b 100644 --- a/amqp/src/test/scala/akka/stream/alpakka/amqp/scaladsl/AmqpConnectorsSpec.scala +++ b/amqp/src/test/scala/akka/stream/alpakka/amqp/scaladsl/AmqpConnectorsSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.amqp.scaladsl import akka.Done diff --git a/awslambda/src/main/scala/akka/stream/alpakka/awslambda/AwsLambdaFlowStage.scala b/awslambda/src/main/scala/akka/stream/alpakka/awslambda/AwsLambdaFlowStage.scala index 8121465305..c059618b37 100644 --- a/awslambda/src/main/scala/akka/stream/alpakka/awslambda/AwsLambdaFlowStage.scala +++ b/awslambda/src/main/scala/akka/stream/alpakka/awslambda/AwsLambdaFlowStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.awslambda import akka.stream.stage.{GraphStage, GraphStageLogic, InHandler, OutHandler} diff --git a/awslambda/src/main/scala/akka/stream/alpakka/awslambda/javadsl/AwsLambdaFlow.scala b/awslambda/src/main/scala/akka/stream/alpakka/awslambda/javadsl/AwsLambdaFlow.scala index 5d31e2fa5c..9ee920c468 100644 --- a/awslambda/src/main/scala/akka/stream/alpakka/awslambda/javadsl/AwsLambdaFlow.scala +++ b/awslambda/src/main/scala/akka/stream/alpakka/awslambda/javadsl/AwsLambdaFlow.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.awslambda.javadsl import akka.NotUsed diff --git a/awslambda/src/main/scala/akka/stream/alpakka/awslambda/scaladsl/AwsLambdaFlow.scala b/awslambda/src/main/scala/akka/stream/alpakka/awslambda/scaladsl/AwsLambdaFlow.scala index 743ef5dd50..a24347dc09 100644 --- a/awslambda/src/main/scala/akka/stream/alpakka/awslambda/scaladsl/AwsLambdaFlow.scala +++ b/awslambda/src/main/scala/akka/stream/alpakka/awslambda/scaladsl/AwsLambdaFlow.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.awslambda.scaladsl import akka.NotUsed diff --git a/awslambda/src/test/java/akka/stream/alpakka/awslambda/javadsl/AwsLambdaFlowTest.java b/awslambda/src/test/java/akka/stream/alpakka/awslambda/javadsl/AwsLambdaFlowTest.java index 6505506597..11769a03c0 100644 --- a/awslambda/src/test/java/akka/stream/alpakka/awslambda/javadsl/AwsLambdaFlowTest.java +++ b/awslambda/src/test/java/akka/stream/alpakka/awslambda/javadsl/AwsLambdaFlowTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.awslambda.javadsl; import akka.NotUsed; diff --git a/awslambda/src/test/java/akka/stream/alpakka/awslambda/javadsl/Examples.java b/awslambda/src/test/java/akka/stream/alpakka/awslambda/javadsl/Examples.java index 9472d81618..45da597de5 100644 --- a/awslambda/src/test/java/akka/stream/alpakka/awslambda/javadsl/Examples.java +++ b/awslambda/src/test/java/akka/stream/alpakka/awslambda/javadsl/Examples.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.awslambda.javadsl; import akka.NotUsed; diff --git a/awslambda/src/test/scala/akka/stream/alpakka/awslambda/scaladsl/AwsLambdaFlowSpec.scala b/awslambda/src/test/scala/akka/stream/alpakka/awslambda/scaladsl/AwsLambdaFlowSpec.scala index 6295f63e3d..d6f49813a5 100644 --- a/awslambda/src/test/scala/akka/stream/alpakka/awslambda/scaladsl/AwsLambdaFlowSpec.scala +++ b/awslambda/src/test/scala/akka/stream/alpakka/awslambda/scaladsl/AwsLambdaFlowSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.awslambda.scaladsl import java.util.concurrent.{CompletableFuture, Future} diff --git a/awslambda/src/test/scala/akka/stream/alpakka/awslambda/scaladsl/Examples.scala b/awslambda/src/test/scala/akka/stream/alpakka/awslambda/scaladsl/Examples.scala index 0631ebd184..63ab4a8ca3 100644 --- a/awslambda/src/test/scala/akka/stream/alpakka/awslambda/scaladsl/Examples.scala +++ b/awslambda/src/test/scala/akka/stream/alpakka/awslambda/scaladsl/Examples.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.awslambda.scaladsl import java.util.concurrent.Executors diff --git a/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/AzureQueueSinkFunctions.scala b/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/AzureQueueSinkFunctions.scala index 249c75a2f9..e3436cfd1f 100644 --- a/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/AzureQueueSinkFunctions.scala +++ b/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/AzureQueueSinkFunctions.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.azure.storagequeue import com.microsoft.azure.storage.queue.{CloudQueue, CloudQueueMessage} diff --git a/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/AzureQueueSourceStage.scala b/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/AzureQueueSourceStage.scala index c1cb74957b..a278e983ce 100644 --- a/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/AzureQueueSourceStage.scala +++ b/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/AzureQueueSourceStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.azure.storagequeue import com.microsoft.azure.storage.queue.{CloudQueue, CloudQueueMessage} diff --git a/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/javadsl/AzureQueueSink.scala b/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/javadsl/AzureQueueSink.scala index a50c415eee..6870a7ac57 100644 --- a/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/javadsl/AzureQueueSink.scala +++ b/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/javadsl/AzureQueueSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.azure.storagequeue.javadsl import com.microsoft.azure.storage.queue.{CloudQueue, CloudQueueMessage} diff --git a/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/javadsl/AzureQueueSource.scala b/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/javadsl/AzureQueueSource.scala index 2f71f90a78..38c339e877 100644 --- a/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/javadsl/AzureQueueSource.scala +++ b/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/javadsl/AzureQueueSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.azure.storagequeue.javadsl import com.microsoft.azure.storage.queue.{CloudQueue, CloudQueueMessage} diff --git a/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/scaladsl/AzureQueueSink.scala b/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/scaladsl/AzureQueueSink.scala index aa61964e6b..bf0096051e 100644 --- a/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/scaladsl/AzureQueueSink.scala +++ b/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/scaladsl/AzureQueueSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.azure.storagequeue.scaladsl import com.microsoft.azure.storage.queue.{CloudQueue, CloudQueueMessage} diff --git a/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/scaladsl/AzureQueueSource.scala b/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/scaladsl/AzureQueueSource.scala index edd14f3bca..7c1b530add 100644 --- a/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/scaladsl/AzureQueueSource.scala +++ b/azure-storage-queue/src/main/scala/akka/stream/alpakka/azure/storagequeue/scaladsl/AzureQueueSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.azure.storagequeue.scaladsl import com.microsoft.azure.storage.queue.{CloudQueue, CloudQueueMessage} diff --git a/azure-storage-queue/src/test/java/akka/stream/alpakka/azure/storagequeue/javadsl/JavaDslTest.java b/azure-storage-queue/src/test/java/akka/stream/alpakka/azure/storagequeue/javadsl/JavaDslTest.java index 4041c29d55..8995cf4379 100644 --- a/azure-storage-queue/src/test/java/akka/stream/alpakka/azure/storagequeue/javadsl/JavaDslTest.java +++ b/azure-storage-queue/src/test/java/akka/stream/alpakka/azure/storagequeue/javadsl/JavaDslTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.azure.storagequeue.javadsl; import akka.Done; diff --git a/azure-storage-queue/src/test/scala/akka/stream/alpakka/azure/storagequeue/scaladsl/AzureQueueSpec.scala b/azure-storage-queue/src/test/scala/akka/stream/alpakka/azure/storagequeue/scaladsl/AzureQueueSpec.scala index 46d68f9f02..3a9629121c 100644 --- a/azure-storage-queue/src/test/scala/akka/stream/alpakka/azure/storagequeue/scaladsl/AzureQueueSpec.scala +++ b/azure-storage-queue/src/test/scala/akka/stream/alpakka/azure/storagequeue/scaladsl/AzureQueueSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.azure.storagequeue.scaladsl import org.scalatest._ diff --git a/build.sbt b/build.sbt index ebbe67877a..15185c5aec 100644 --- a/build.sbt +++ b/build.sbt @@ -159,10 +159,12 @@ lazy val docs = project paradoxGroups := Map("Language" -> Seq("Scala", "Java")), paradoxProperties in Local ++= Map( // point API doc links to locally generated API docs - "scaladoc.akka.stream.alpakka.base_url" -> rebase( - (baseDirectory in alpakka).value, - "../../../../../" - )((sbtunidoc.Plugin.UnidocKeys.unidoc in alpakka in Compile).value.head).get + "scaladoc.akka.stream.alpakka.base_url" -> sbt.io.Path + .rebase( + (baseDirectory in alpakka).value, + "../../../../../" + )((sbtunidoc.BaseUnidocPlugin.autoImport.unidoc in alpakka in Compile).value.head) + .get ) ) diff --git a/cassandra/src/main/scala/akka/stream/alpakka/cassandra/CassandraSourceStage.scala b/cassandra/src/main/scala/akka/stream/alpakka/cassandra/CassandraSourceStage.scala index 9e7cad5cdd..4b2b8abdbb 100644 --- a/cassandra/src/main/scala/akka/stream/alpakka/cassandra/CassandraSourceStage.scala +++ b/cassandra/src/main/scala/akka/stream/alpakka/cassandra/CassandraSourceStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.cassandra import akka.stream._ diff --git a/cassandra/src/main/scala/akka/stream/alpakka/cassandra/GuavaFutures.scala b/cassandra/src/main/scala/akka/stream/alpakka/cassandra/GuavaFutures.scala index 0198ff2223..62ddc167b5 100644 --- a/cassandra/src/main/scala/akka/stream/alpakka/cassandra/GuavaFutures.scala +++ b/cassandra/src/main/scala/akka/stream/alpakka/cassandra/GuavaFutures.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.cassandra import com.google.common.util.concurrent.{FutureCallback, Futures, ListenableFuture} diff --git a/cassandra/src/main/scala/akka/stream/alpakka/cassandra/javadsl/CassandraSink.scala b/cassandra/src/main/scala/akka/stream/alpakka/cassandra/javadsl/CassandraSink.scala index 10afab3bb9..b43cdf6a0d 100644 --- a/cassandra/src/main/scala/akka/stream/alpakka/cassandra/javadsl/CassandraSink.scala +++ b/cassandra/src/main/scala/akka/stream/alpakka/cassandra/javadsl/CassandraSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.cassandra.javadsl import java.util.concurrent.CompletionStage diff --git a/cassandra/src/main/scala/akka/stream/alpakka/cassandra/javadsl/CassandraSource.scala b/cassandra/src/main/scala/akka/stream/alpakka/cassandra/javadsl/CassandraSource.scala index cac8c842bc..ad0c122501 100644 --- a/cassandra/src/main/scala/akka/stream/alpakka/cassandra/javadsl/CassandraSource.scala +++ b/cassandra/src/main/scala/akka/stream/alpakka/cassandra/javadsl/CassandraSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.cassandra.javadsl import java.util.concurrent.CompletableFuture diff --git a/cassandra/src/main/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSink.scala b/cassandra/src/main/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSink.scala index 4204173dc9..6dbbbebbef 100644 --- a/cassandra/src/main/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSink.scala +++ b/cassandra/src/main/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.cassandra.scaladsl import akka.Done diff --git a/cassandra/src/main/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSource.scala b/cassandra/src/main/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSource.scala index 765a5e20e8..5349ac287f 100644 --- a/cassandra/src/main/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSource.scala +++ b/cassandra/src/main/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.cassandra.scaladsl import akka.NotUsed diff --git a/cassandra/src/test/java/akka/stream/alpakka/cassandra/javadsl/CassandraSourceTest.java b/cassandra/src/test/java/akka/stream/alpakka/cassandra/javadsl/CassandraSourceTest.java index 0bfaf25302..e67a253ecf 100644 --- a/cassandra/src/test/java/akka/stream/alpakka/cassandra/javadsl/CassandraSourceTest.java +++ b/cassandra/src/test/java/akka/stream/alpakka/cassandra/javadsl/CassandraSourceTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.cassandra.javadsl; import akka.Done; diff --git a/cassandra/src/test/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSourceSpec.scala b/cassandra/src/test/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSourceSpec.scala index ea7e4ba983..c962d569a3 100644 --- a/cassandra/src/test/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSourceSpec.scala +++ b/cassandra/src/test/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSourceSpec.scala @@ -1,12 +1,13 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.cassandra.scaladsl import akka.actor.ActorSystem import akka.stream.ActorMaterializer import akka.stream.scaladsl.{Sink, Source} -import com.datastax.driver.core.{Cluster, PreparedStatement, SimpleStatement, SocketOptions} +import com.datastax.driver.core.{Cluster, PreparedStatement, SimpleStatement} import org.scalatest._ import org.scalatest.concurrent.ScalaFutures @@ -33,10 +34,6 @@ class CassandraSourceSpec implicit val session = Cluster.builder .addContactPoint("127.0.0.1") .withPort(9042) - .withSocketOptions( - new SocketOptions() - .setConnectTimeoutMillis(20 * 1000) - ) .build .connect() //#init-session diff --git a/csv/src/main/java/akka/stream/alpakka/csv/javadsl/ByteOrderMark.java b/csv/src/main/java/akka/stream/alpakka/csv/javadsl/ByteOrderMark.java index 44e869de9a..92cb561455 100644 --- a/csv/src/main/java/akka/stream/alpakka/csv/javadsl/ByteOrderMark.java +++ b/csv/src/main/java/akka/stream/alpakka/csv/javadsl/ByteOrderMark.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.javadsl; import akka.util.ByteString; diff --git a/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvFormatting.java b/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvFormatting.java index 4608f2f4c0..25d9e84305 100644 --- a/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvFormatting.java +++ b/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvFormatting.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.javadsl; import akka.NotUsed; diff --git a/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvParsing.java b/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvParsing.java index d8f928b099..a0bec3b441 100644 --- a/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvParsing.java +++ b/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvParsing.java @@ -1,12 +1,13 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.javadsl; import akka.NotUsed; import akka.stream.javadsl.Flow; import akka.util.ByteString; -import scala.collection.JavaConversions; +import scala.collection.JavaConverters; import java.util.Collection; @@ -18,14 +19,19 @@ public class CsvParsing { public static final byte COLON = ':'; public static final byte TAB = '\t'; public static final byte DOUBLE_QUOTE = '"'; + public static final int MAXIMUM_LINE_LENGTH_DEFAULT = 10 * 1024; public static Flow, NotUsed> lineScanner() { - return lineScanner(COMMA, DOUBLE_QUOTE, BACKSLASH); + return lineScanner(COMMA, DOUBLE_QUOTE, BACKSLASH, MAXIMUM_LINE_LENGTH_DEFAULT); } public static Flow, NotUsed> lineScanner(byte delimiter, byte quoteChar, byte escapeChar) { + return lineScanner(delimiter, quoteChar, escapeChar, MAXIMUM_LINE_LENGTH_DEFAULT); + } + + public static Flow, NotUsed> lineScanner(byte delimiter, byte quoteChar, byte escapeChar, int maximumLineLength) { return akka.stream.alpakka.csv.scaladsl.CsvParsing - .lineScanner(delimiter, quoteChar, escapeChar).asJava() - .map(JavaConversions::asJavaCollection); + .lineScanner(delimiter, quoteChar, escapeChar, maximumLineLength).asJava() + .map(c -> JavaConverters.asJavaCollectionConverter(c).asJavaCollection()); } } diff --git a/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvQuotingStyle.java b/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvQuotingStyle.java index b90d3a519e..53e6f7c728 100644 --- a/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvQuotingStyle.java +++ b/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvQuotingStyle.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.javadsl; /** diff --git a/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvToMap.java b/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvToMap.java index 7202885d21..e7307cedc5 100644 --- a/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvToMap.java +++ b/csv/src/main/java/akka/stream/alpakka/csv/javadsl/CsvToMap.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.javadsl; diff --git a/csv/src/main/scala/akka/stream/alpakka/csv/CsvFormatter.scala b/csv/src/main/scala/akka/stream/alpakka/csv/CsvFormatter.scala index ab64463062..96a1928194 100644 --- a/csv/src/main/scala/akka/stream/alpakka/csv/CsvFormatter.scala +++ b/csv/src/main/scala/akka/stream/alpakka/csv/CsvFormatter.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv import java.nio.charset.{Charset, StandardCharsets} diff --git a/csv/src/main/scala/akka/stream/alpakka/csv/CsvParser.scala b/csv/src/main/scala/akka/stream/alpakka/csv/CsvParser.scala index 59316afe7b..3a4cf84945 100644 --- a/csv/src/main/scala/akka/stream/alpakka/csv/CsvParser.scala +++ b/csv/src/main/scala/akka/stream/alpakka/csv/CsvParser.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv import java.nio.charset.UnsupportedCharsetException @@ -31,7 +32,7 @@ private[csv] object CsvParser { /** * INTERNAL API: Use [[akka.stream.alpakka.csv.scaladsl.CsvParsing]] instead. */ -private[csv] final class CsvParser(delimiter: Byte, quoteChar: Byte, escapeChar: Byte) { +private[csv] final class CsvParser(delimiter: Byte, quoteChar: Byte, escapeChar: Byte, maximumLineLength: Int) { import CsvParser._ @@ -144,6 +145,10 @@ private[csv] final class CsvParser(delimiter: Byte, quoteChar: Byte, escapeChar: } while (state != LineEnd && pos < buf.length) { + if (pos >= maximumLineLength) + throw new MalformedCsvException( + s"no line end encountered within $maximumLineLength bytes on line $currentLineNo" + ) val byte = buf(pos) state match { case LineStart => diff --git a/csv/src/main/scala/akka/stream/alpakka/csv/CsvParsingStage.scala b/csv/src/main/scala/akka/stream/alpakka/csv/CsvParsingStage.scala index 392dbfe406..0fdaa37c27 100644 --- a/csv/src/main/scala/akka/stream/alpakka/csv/CsvParsingStage.scala +++ b/csv/src/main/scala/akka/stream/alpakka/csv/CsvParsingStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv import akka.event.Logging @@ -14,7 +15,7 @@ import scala.util.control.NonFatal /** * Internal API: Use [[akka.stream.alpakka.csv.scaladsl.CsvParsing]] instead. */ -private[csv] class CsvParsingStage(delimiter: Byte, quoteChar: Byte, escapeChar: Byte) +private[csv] class CsvParsingStage(delimiter: Byte, quoteChar: Byte, escapeChar: Byte, maximumLineLength: Int) extends GraphStage[FlowShape[ByteString, List[ByteString]]] { private val in = Inlet[ByteString](Logging.simpleName(this) + ".in") @@ -25,7 +26,7 @@ private[csv] class CsvParsingStage(delimiter: Byte, quoteChar: Byte, escapeChar: override def createLogic(inheritedAttributes: Attributes) = new GraphStageLogic(shape) with InHandler with OutHandler { - private[this] val buffer = new CsvParser(delimiter, quoteChar, escapeChar) + private[this] val buffer = new CsvParser(delimiter, quoteChar, escapeChar, maximumLineLength) setHandlers(in, out, this) diff --git a/csv/src/main/scala/akka/stream/alpakka/csv/CsvToMapJavaStage.scala b/csv/src/main/scala/akka/stream/alpakka/csv/CsvToMapJavaStage.scala index 2ae2cd72d6..18e1dc3558 100644 --- a/csv/src/main/scala/akka/stream/alpakka/csv/CsvToMapJavaStage.scala +++ b/csv/src/main/scala/akka/stream/alpakka/csv/CsvToMapJavaStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv import java.nio.charset.Charset diff --git a/csv/src/main/scala/akka/stream/alpakka/csv/CsvToMapStage.scala b/csv/src/main/scala/akka/stream/alpakka/csv/CsvToMapStage.scala index 4cc95c1d00..0a438c29ae 100644 --- a/csv/src/main/scala/akka/stream/alpakka/csv/CsvToMapStage.scala +++ b/csv/src/main/scala/akka/stream/alpakka/csv/CsvToMapStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv import java.nio.charset.Charset diff --git a/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/ByteOrderMark.scala b/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/ByteOrderMark.scala index 60ba492ec2..ef8e0d4d39 100644 --- a/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/ByteOrderMark.scala +++ b/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/ByteOrderMark.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.scaladsl import akka.util.ByteString diff --git a/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvFormatting.scala b/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvFormatting.scala index 4dba9c9beb..83f25e4dc7 100644 --- a/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvFormatting.scala +++ b/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvFormatting.scala @@ -1,12 +1,13 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.scaladsl import java.nio.charset.{Charset, StandardCharsets} import akka.NotUsed -import akka.stream.alpakka.csv.{javadsl, CsvFormatter} +import akka.stream.alpakka.csv.CsvFormatter import akka.stream.scaladsl.{Flow, Source} import akka.util.ByteString diff --git a/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvParsing.scala b/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvParsing.scala index cc15856f0f..e34e847057 100644 --- a/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvParsing.scala +++ b/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvParsing.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.scaladsl import akka.NotUsed @@ -16,12 +17,14 @@ object CsvParsing { val Colon: Byte = ':' val Tab: Byte = '\t' val DoubleQuote: Byte = '"' + val maximumLineLengthDefault: Int = 10 * 1024 /** Creates CSV parsing flow that reads CSV lines from incoming * [[akka.util.ByteString]] objects. */ def lineScanner(delimiter: Byte = Comma, quoteChar: Byte = DoubleQuote, - escapeChar: Byte = Backslash): Flow[ByteString, List[ByteString], NotUsed] = - Flow.fromGraph(new CsvParsingStage(delimiter, quoteChar, escapeChar)) + escapeChar: Byte = Backslash, + maximumLineLength: Int = maximumLineLengthDefault): Flow[ByteString, List[ByteString], NotUsed] = + Flow.fromGraph(new CsvParsingStage(delimiter, quoteChar, escapeChar, maximumLineLength)) } diff --git a/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvQuotingStyle.scala b/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvQuotingStyle.scala index 6b80651af0..7d8403cb4d 100644 --- a/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvQuotingStyle.scala +++ b/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvQuotingStyle.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.scaladsl import akka.stream.alpakka.csv.javadsl diff --git a/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvToMap.scala b/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvToMap.scala index 65a4cee027..0d1c2b263b 100644 --- a/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvToMap.scala +++ b/csv/src/main/scala/akka/stream/alpakka/csv/scaladsl/CsvToMap.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.scaladsl import java.nio.charset.{Charset, StandardCharsets} diff --git a/csv/src/test/java/akka/stream/alpakka/csv/javadsl/CsvFormattingTest.java b/csv/src/test/java/akka/stream/alpakka/csv/javadsl/CsvFormattingTest.java index 19284c3ba9..686d6fe364 100644 --- a/csv/src/test/java/akka/stream/alpakka/csv/javadsl/CsvFormattingTest.java +++ b/csv/src/test/java/akka/stream/alpakka/csv/javadsl/CsvFormattingTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.javadsl; import akka.actor.ActorSystem; diff --git a/csv/src/test/java/akka/stream/alpakka/csv/javadsl/CsvParsingTest.java b/csv/src/test/java/akka/stream/alpakka/csv/javadsl/CsvParsingTest.java index df00ebaed6..04252684e1 100644 --- a/csv/src/test/java/akka/stream/alpakka/csv/javadsl/CsvParsingTest.java +++ b/csv/src/test/java/akka/stream/alpakka/csv/javadsl/CsvParsingTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.javadsl; import akka.NotUsed; diff --git a/csv/src/test/java/akka/stream/alpakka/csv/javadsl/CsvToMapTest.java b/csv/src/test/java/akka/stream/alpakka/csv/javadsl/CsvToMapTest.java index 2e6fd15eef..0f4d5cbad8 100644 --- a/csv/src/test/java/akka/stream/alpakka/csv/javadsl/CsvToMapTest.java +++ b/csv/src/test/java/akka/stream/alpakka/csv/javadsl/CsvToMapTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.javadsl; import akka.actor.ActorSystem; diff --git a/csv/src/test/scala/akka/stream/alpakka/csv/CsvFormatterSpec.scala b/csv/src/test/scala/akka/stream/alpakka/csv/CsvFormatterSpec.scala index ccf118d7cb..dcbdd4dfd9 100644 --- a/csv/src/test/scala/akka/stream/alpakka/csv/CsvFormatterSpec.scala +++ b/csv/src/test/scala/akka/stream/alpakka/csv/CsvFormatterSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv import java.nio.charset.StandardCharsets diff --git a/csv/src/test/scala/akka/stream/alpakka/csv/CsvParserSpec.scala b/csv/src/test/scala/akka/stream/alpakka/csv/CsvParserSpec.scala index eed3c7ebda..7e9bbcf128 100644 --- a/csv/src/test/scala/akka/stream/alpakka/csv/CsvParserSpec.scala +++ b/csv/src/test/scala/akka/stream/alpakka/csv/CsvParserSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv import java.nio.charset.{StandardCharsets, UnsupportedCharsetException} @@ -12,6 +13,8 @@ import org.scalatest.{Matchers, OptionValues, WordSpec} class CsvParserSpec extends WordSpec with Matchers with OptionValues { + val maximumLineLength = 10 * 1024 + "CSV parser" should { "read comma separated values into a list" in { expectInOut("one,two,three\n", List("one", "two", "three")) @@ -31,7 +34,7 @@ class CsvParserSpec extends WordSpec with Matchers with OptionValues { "parse empty input to None" in { val in = ByteString.empty - val parser = new CsvParser(',', '-', '.') + val parser = new CsvParser(',', '-', '.', maximumLineLength) parser.offer(in) parser.poll(requireLineEnd = true) should be('empty) } @@ -87,7 +90,7 @@ class CsvParserSpec extends WordSpec with Matchers with OptionValues { "fail on escaped quote as quotes are escaped by doubled quote chars" in { val in = ByteString("a,\\\",c\n") - val parser = new CsvParser(',', '"', '\\') + val parser = new CsvParser(',', '"', '\\', maximumLineLength) parser.offer(in) val exception = the[MalformedCsvException] thrownBy { parser.poll(requireLineEnd = true) @@ -97,7 +100,7 @@ class CsvParserSpec extends WordSpec with Matchers with OptionValues { "fail on escape at line end" in { val in = ByteString("""a,\""") - val parser = new CsvParser(',', '"', '\\') + val parser = new CsvParser(',', '"', '\\', maximumLineLength) parser.offer(in) val exception = the[MalformedCsvException] thrownBy { parser.poll(requireLineEnd = true) @@ -107,7 +110,7 @@ class CsvParserSpec extends WordSpec with Matchers with OptionValues { "fail on escape within field at line end" in { val in = ByteString("""a,b\""") - val parser = new CsvParser(',', '"', '\\') + val parser = new CsvParser(',', '"', '\\', maximumLineLength) parser.offer(in) val exception = the[MalformedCsvException] thrownBy { parser.poll(requireLineEnd = true) @@ -117,7 +120,7 @@ class CsvParserSpec extends WordSpec with Matchers with OptionValues { "fail on escape within quoted field at line end" in { val in = ByteString("""a,"\""") - val parser = new CsvParser(',', '"', '\\') + val parser = new CsvParser(',', '"', '\\', maximumLineLength) parser.offer(in) val exception = the[MalformedCsvException] thrownBy { parser.poll(requireLineEnd = true) @@ -143,7 +146,7 @@ class CsvParserSpec extends WordSpec with Matchers with OptionValues { "allow Unicode L SEP 0x2028 as line separator" ignore { val in = ByteString("abc\u2028") - val parser = new CsvParser(',', '"', '\\') + val parser = new CsvParser(',', '"', '\\', maximumLineLength) parser.offer(in) val res = parser.poll(requireLineEnd = true) res.value.map(_.utf8String) should be(List("abc")) @@ -185,6 +188,18 @@ class CsvParserSpec extends WordSpec with Matchers with OptionValues { quoteChar = '$', escapeChar = '\\') } + + "fail on a very 'long' line" in { + val in = ByteString("a,b,c\n1,3,5,7,9,1\n") + val parser = new CsvParser(',', '"', '\\', 11) + parser.offer(in) + parser.poll(requireLineEnd = true) + val exception = the[MalformedCsvException] thrownBy { + parser.poll(requireLineEnd = true) + } + exception.getMessage should be("no line end encountered within 11 bytes on line 2") + } + } "CSV parsing with Byte Order Mark" should { @@ -226,7 +241,7 @@ class CsvParserSpec extends WordSpec with Matchers with OptionValues { quoteChar: Byte = '"', escapeChar: Byte = '\\', requireLineEnd: Boolean = true): Unit = { - val parser = new CsvParser(delimiter, quoteChar, escapeChar) + val parser = new CsvParser(delimiter, quoteChar, escapeChar, maximumLineLength) parser.offer(bsIn) expected.foreach { out => parser.poll(requireLineEnd).value.map(_.utf8String) should be(out) diff --git a/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvFormattingSpec.scala b/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvFormattingSpec.scala index b7b2f243b6..319dc66b5e 100644 --- a/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvFormattingSpec.scala +++ b/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvFormattingSpec.scala @@ -1,11 +1,11 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.scaladsl import java.nio.charset.StandardCharsets -import akka.NotUsed import akka.stream.scaladsl.{Flow, Sink, Source} import akka.util.ByteString diff --git a/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvParsingSpec.scala b/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvParsingSpec.scala index 679311dc3a..76eae75682 100644 --- a/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvParsingSpec.scala +++ b/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvParsingSpec.scala @@ -1,32 +1,20 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.scaladsl import java.nio.file.Paths import akka.NotUsed -import akka.actor.ActorSystem -import akka.stream.ActorMaterializer import akka.stream.scaladsl.{FileIO, Flow, Keep, Sink, Source} import akka.stream.testkit.scaladsl.{TestSink, TestSource} -import akka.testkit.TestKit import akka.util.ByteString -import org.scalatest.concurrent.ScalaFutures -import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach, Matchers, WordSpecLike} import scala.collection.immutable.Seq import scala.concurrent.duration.DurationInt -class CsvParsingSpec - extends TestKit(ActorSystem(classOf[CsvParsingSpec].getSimpleName)) - with WordSpecLike - with Matchers - with BeforeAndAfterAll - with BeforeAndAfterEach - with ScalaFutures { - - implicit val materializer = ActorMaterializer() +class CsvParsingSpec extends CsvSpec { def documentation(): Unit = { import CsvParsing._ diff --git a/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvSpec.scala b/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvSpec.scala index d3dc67d9a6..6d34fb618d 100644 --- a/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvSpec.scala +++ b/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.scaladsl import akka.actor.ActorSystem diff --git a/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvToMapSpec.scala b/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvToMapSpec.scala index 7dc2386b7d..ad9daae59b 100644 --- a/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvToMapSpec.scala +++ b/csv/src/test/scala/akka/stream/alpakka/csv/scaladsl/CsvToMapSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.csv.scaladsl import java.nio.charset.StandardCharsets diff --git a/docker-compose.yml b/docker-compose.yml index 2fabfda01f..cd3a2074b3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,7 +24,7 @@ services: - "8001:8000" geode: container_name: geode - image: apachegeode/geode:1.2.1 + image: apachegeode/geode:1.3.0 hostname: geode mem_limit: 2g expose: diff --git a/docs/src/main/paradox/data-transformations/xml.md b/docs/src/main/paradox/data-transformations/xml.md index 3f21ac6a12..adab112321 100644 --- a/docs/src/main/paradox/data-transformations/xml.md +++ b/docs/src/main/paradox/data-transformations/xml.md @@ -28,6 +28,24 @@ Scala Java : @@snip ($alpakka$/xml/src/test/java/akka/stream/alpakka/xml/javadsl/XmlParsingTest.java) { #parser-usage } +## XML writing + +XML processing pipeline ends with an @scaladoc[XmlWriting.writer](akka.stream.alpakka.xml.scaladsl.XmlWriting$) flow which writes a stream of XML parser events to @scaladoc[ByteString](akka.util.ByteString)s. + +Scala +: @@snip (../../../../../xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlWritingTest.scala) { #writer } + +Java +: @@snip (../../../../../xml/src/test/java/akka/stream/alpakka/xml/javadsl/XmlWritingTest.java) { #writer } + +To write an XML document run XML document source with this writer. + +Scala +: @@snip (../../../../../xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlWritingTest.scala) { #writer-usage } + +Java +: @@snip (../../../../../xml/src/test/java/akka/stream/alpakka/xml/javadsl/XmlWritingTest.java) { #writer-usage } + ## XML Subslice Use @scaladoc[XmlParsing.subslice](akka.stream.alpakka.xml.scaladsl.XmlParsing$) to filter out all elements not corresponding to a certain path. diff --git a/docs/src/main/paradox/file.md b/docs/src/main/paradox/file.md index 1ba7c0933f..0b7df3e140 100644 --- a/docs/src/main/paradox/file.md +++ b/docs/src/main/paradox/file.md @@ -68,6 +68,36 @@ Scala Java : @@snip ($alpakka$/file/src/test/java/akka/stream/alpakka/file/javadsl/DirectoryChangesSourceTest.java) { #minimal-sample } +### LogRotationSink + +The `LogRotationSink` will create and write to multiple files. +This sink will takes a function as parameter which returns a + `Bytestring => Option[Path]` function. If the generated function returns a path + the sink will rotate the file output to this new path and the actual `ByteString` will be + written to this new file too. + With this approach the user can define a custom stateful file generation implementation. + +The java implementation is a bit different. The inner function must return null or Path instead of the Option. + +A small snippet for the usage: + +Scala +: @@snip (../../../../file/src/test/scala/akka/stream/alpakka/file/scaladsl/LogRotatorSinkSpec.scala) { #LogRotationSink-sample } + +In this sample we create a size based rotation function: + +Scala +: @@snip (../../../../file/src/test/scala/akka/stream/alpakka/file/scaladsl/LogRotatorSinkSpec.scala) { #LogRotationSink-filesize-sample } +Java +: @@snip (../../../../file/src/test/java/akka/stream/alpakka/file/javadsl/LogRotatorSinkTest.java) { #LogRotationSink-filesize-sample } + +In this sample we create a time based rotation function: + +Scala +: @@snip (../../../../file/src/test/scala/akka/stream/alpakka/file/scaladsl/LogRotatorSinkSpec.scala) { #LogRotationSink-timebased-sample } +Java +: @@snip (../../../../file/src/test/java/akka/stream/alpakka/file/javadsl/LogRotatorSinkTest.java) { #LogRotationSink-timebased-sample } + ### Running the example code diff --git a/docs/src/main/paradox/jms.md b/docs/src/main/paradox/jms.md index e3e4392da9..4a3337751c 100644 --- a/docs/src/main/paradox/jms.md +++ b/docs/src/main/paradox/jms.md @@ -123,6 +123,26 @@ Scala Java : @@snip ($alpakka$/jms/src/test/java/akka/stream/alpakka/jms/javadsl/JmsConnectorsTest.java) { #run-jms-source } +### Receiving @extref[javax.jms.Message](javaee-api:javax.jms.Message)s messages from a JMS provider with Client Acknowledgement + +Create a @extref[javax.jms.Message](javaee-api:javax.jms.Message) source: + +Scala +: @@snip (../../../../jms/src/test/scala/akka/stream/alpakka/jms/scaladsl/JmsConnectorsSpec.scala) { #create-jms-source-client-ack } + +Java +: @@snip (../../../../jms/src/test/java/akka/stream/alpakka/jms/javadsl/JmsConnectorsTest.java) { #create-jms-source-client-ack } + +The `acknowledgeMode` parameter controls the JMS acknowledge mode parameter, see @extref[javax.jms.Connection#createSession](javaee-api:javax.jms.Connection#createSession). + +Run the source and take the same amount of messages as we previously sent to it acknowledging them. + +Scala +: @@snip (../../../../jms/src/test/scala/akka/stream/alpakka/jms/scaladsl/JmsConnectorsSpec.scala) { #run-jms-source-with-ack } + +Java +: @@snip (../../../../jms/src/test/java/akka/stream/alpakka/jms/javadsl/JmsConnectorsTest.java) { #run-jms-source-with-ack } + ### Receiving @extref[javax.jms.Message](javaee-api:javax.jms.Message)s from a JMS provider with a selector Create a @extref[javax.jms.Message](javaee-api:javax.jms.Message) source specifying a [JMS selector expression](https://docs.oracle.com/cd/E19798-01/821-1841/bncer/index.html): @@ -192,7 +212,7 @@ MQ settings for this image are shown here: https://github.com/ibm-messaging/mq-d #### Create a JmsSource to an IBM MQ Queue -The `MQQueueConnectionFactory` needs a queue manager name and a channel name, the docker command used in the previous section sets up a `QM1` queue manager and a `DEV.APP.SVRCONN` channel. The IBM MQ client makes it possible to +The `MQQueueConnectionFactory` needs a queue manager name and a channel name, the docker command used in the previous section sets up a `QM1` queue manager and a `DEV.APP.SVRCONN` channel. The IBM MQ client makes it possible to connect to the MQ server over TCP/IP or natively through JNI (when the client and server run on the same machine). In the examples below we have chosen to use TCP/IP, which is done by setting the transport type to `CommonConstants.WMQ_CM_CLIENT`. Scala diff --git a/docs/src/main/paradox/kinesis.md b/docs/src/main/paradox/kinesis.md index 2b9baf1995..874cc842dc 100644 --- a/docs/src/main/paradox/kinesis.md +++ b/docs/src/main/paradox/kinesis.md @@ -14,7 +14,7 @@ For more information about Kinesis please visit the [official documentation](htt ## Usage -Sources provided by this connector need a `AmazonKinesisAsync` instance to consume messages from a shard. +Sources and Flows provided by this connector need a `AmazonKinesisAsync` instance to consume messages from a shard. @@@ note The `AmazonKinesisAsync` instance you supply is thread-safe and can be shared amongst multiple `GraphStages`. As a result, individual `GraphStages` will not automatically shutdown the supplied client when they complete. @@ -39,10 +39,10 @@ Java The `KinesisSource` creates one `GraphStage` per shard. Reading from a shard requires an instance of `ShardSettings`. Scala -: @@snip ($alpakka$/kinesis/src/test/scala/akka/stream/alpakka/kinesis/scaladsl/Examples.scala) { #settings } +: @@snip ($alpakka$/kinesis/src/test/scala/akka/stream/alpakka/kinesis/scaladsl/Examples.scala) { #source-settings } Java -: @@snip ($alpakka$/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/Examples.java) { #settings } +: @@snip ($alpakka$/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/Examples.java) { #source-settings } You have the choice of reading from a single shard, or reading from multiple shards. In the case of multiple shards the results of running a separate `GraphStage` for each shard will be merged together. @@ -53,18 +53,50 @@ The `GraphStage` associated with a shard will remain open until the graph is sto For a single shard you simply provide the settings for a single shard. Scala -: @@snip ($alpakka$/kinesis/src/test/scala/akka/stream/alpakka/kinesis/scaladsl/Examples.scala) { #single } +: @@snip ($alpakka$/kinesis/src/test/scala/akka/stream/alpakka/kinesis/scaladsl/Examples.scala) { #source-single } Java -: @@snip ($alpakka$/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/Examples.java) { #single } +: @@snip ($alpakka$/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/Examples.java) { #source-single } You can merge multiple shards by providing a list settings. Scala -: @@snip ($alpakka$/kinesis/src/test/scala/akka/stream/alpakka/kinesis/scaladsl/Examples.scala) { #list } +: @@snip ($alpakka$/kinesis/src/test/scala/akka/stream/alpakka/kinesis/scaladsl/Examples.scala) { #source-list } Java -: @@snip ($alpakka$/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/Examples.java) { #list } +: @@snip ($alpakka$/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/Examples.java) { #source-list } The constructed `Source` will return [Record](http://docs.aws.amazon.com/kinesis/latest/APIReference/API_Record.html) + objects by calling [GetRecords](http://docs.aws.amazon.com/kinesis/latest/APIReference/API_GetRecords.html) at the specified interval and according to the downstream demand. + +### Using the Put Flow/Sink + +The `KinesisFlow` (or `KinesisSink`) publishes messages into a Kinesis stream using it's partition key and message body. It uses dynamic size batches, can perform several requests in parallel and retries failed records. These features are necessary to achieve the best possible write throughput to the stream. The Flow outputs the result of publishing each record. + +@@@ warning +Batching has a drawback: message order cannot be guaranteed, as some records within a single batch may fail to be published. That also means that the Flow output may not match the same input order. + +More information can be found [here](http://docs.aws.amazon.com/streams/latest/dev/developing-producers-with-sdk.html#kinesis-using-sdk-java-putrecords) and [here](http://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecords.html). +@@@ + +Publishing to a Kinesis stream requires an instance of `KinesisFlowSettings`, although a default instance with sane values and a method that returns settings based on the stream shard number are also available: + +Scala +: @@snip ($alpakka$/kinesis/src/test/scala/akka/stream/alpakka/kinesis/scaladsl/Examples.scala) { #flow-settings } + +Java +: @@snip ($alpakka$/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/Examples.java) { #flow-settings } + +@@@ warning +Note that throughput settings `maxRecordsPerSecond` and `maxBytesPerSecond` are vital to minimize server errors (like `ProvisionedThroughputExceededException`) and retries, and thus achieve a higher publication rate. +@@@ + +The Flow/Sink can now be created. + +Scala +: @@snip ($alpakka$/kinesis/src/test/scala/akka/stream/alpakka/kinesis/scaladsl/Examples.scala) { #flow-sink } + +Java +: @@snip ($alpakka$/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/Examples.java) { #flow-sink } + diff --git a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/AwsClient.scala b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/AwsClient.scala index cc4b8cf062..bb0778d435 100644 --- a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/AwsClient.scala +++ b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/AwsClient.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb.impl import java.io.{ByteArrayInputStream, InputStream} diff --git a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/ClientSettings.scala b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/ClientSettings.scala index 211c1c2b6a..1fa8e55e87 100644 --- a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/ClientSettings.scala +++ b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/ClientSettings.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb.impl abstract class ClientSettings { diff --git a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/DynamoClientImpl.scala b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/DynamoClientImpl.scala index e0c5e7a41d..1a78280f86 100644 --- a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/DynamoClientImpl.scala +++ b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/DynamoClientImpl.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb.impl import akka.actor.ActorSystem diff --git a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/DynamoProtocol.scala b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/DynamoProtocol.scala index 1d9c881e23..8f708b0170 100644 --- a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/DynamoProtocol.scala +++ b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/DynamoProtocol.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb.impl import com.amazonaws.AmazonServiceException diff --git a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/DynamoSettings.scala b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/DynamoSettings.scala index 445e516f05..30013e71ce 100644 --- a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/DynamoSettings.scala +++ b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/impl/DynamoSettings.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb.impl import akka.actor.ActorSystem diff --git a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/javadsl/DynamoClient.scala b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/javadsl/DynamoClient.scala index 661af21b5c..be8f929669 100644 --- a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/javadsl/DynamoClient.scala +++ b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/javadsl/DynamoClient.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb.javadsl import akka.NotUsed diff --git a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/package.scala b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/package.scala index 5550b4df93..e7337c366c 100644 --- a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/package.scala +++ b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/package.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka import com.amazonaws._ diff --git a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/scaladsl/DynamoClient.scala b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/scaladsl/DynamoClient.scala index 0bbab4dd4e..f4dacbec67 100644 --- a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/scaladsl/DynamoClient.scala +++ b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/scaladsl/DynamoClient.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb.scaladsl import akka.NotUsed diff --git a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/scaladsl/DynamoImplicits.scala b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/scaladsl/DynamoImplicits.scala index ab189ed98c..994f418e99 100644 --- a/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/scaladsl/DynamoImplicits.scala +++ b/dynamodb/src/main/scala/akka/stream/alpakka/dynamodb/scaladsl/DynamoImplicits.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb.scaladsl import akka.stream.alpakka.dynamodb.AwsOp diff --git a/dynamodb/src/test/java/akka/stream/alpakka/dynamodb/ExampleTest.java b/dynamodb/src/test/java/akka/stream/alpakka/dynamodb/ExampleTest.java index 4a12af3f5d..877ebb432e 100644 --- a/dynamodb/src/test/java/akka/stream/alpakka/dynamodb/ExampleTest.java +++ b/dynamodb/src/test/java/akka/stream/alpakka/dynamodb/ExampleTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb; import akka.NotUsed; diff --git a/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/ExampleSpec.scala b/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/ExampleSpec.scala index dbbca5d61d..bddf13c086 100644 --- a/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/ExampleSpec.scala +++ b/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/ExampleSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb import akka.actor.ActorSystem diff --git a/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/ItemSpec.scala b/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/ItemSpec.scala index b768e13c48..f52b9ed62f 100644 --- a/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/ItemSpec.scala +++ b/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/ItemSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb import akka.actor.ActorSystem diff --git a/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/TableSpec.scala b/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/TableSpec.scala index d9941ed471..b7226dddd8 100644 --- a/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/TableSpec.scala +++ b/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/TableSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb import akka.actor.ActorSystem diff --git a/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/TestOps.scala b/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/TestOps.scala index 15aa74b0f0..d925c0a4e6 100644 --- a/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/TestOps.scala +++ b/dynamodb/src/test/scala/akka/stream/alpakka/dynamodb/TestOps.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.dynamodb import com.amazonaws.services.dynamodbv2.model._ diff --git a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/ElasticsearchFlowStage.scala b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/ElasticsearchFlowStage.scala index 97af850072..3c2a57d882 100644 --- a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/ElasticsearchFlowStage.scala +++ b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/ElasticsearchFlowStage.scala @@ -1,8 +1,11 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch +import java.nio.charset.StandardCharsets + import akka.stream.{Attributes, FlowShape, Inlet, Outlet} import akka.stream.stage._ import org.apache.http.entity.StringEntity @@ -77,37 +80,42 @@ class ElasticsearchFlowStage[T, R]( completeStage() private def handleResponse(args: (Seq[IncomingMessage[T]], Response)): Unit = { - retryCount = 0 val (messages, response) = args val responseJson = EntityUtils.toString(response.getEntity).parseJson // If some commands in bulk request failed, pass failed messages to follows. val items = responseJson.asJsObject.fields("items").asInstanceOf[JsArray] - val failedMessages = items.elements.zip(messages).flatMap { + val failed = items.elements.zip(messages).flatMap { case (item, message) => - val result = item.asJsObject.fields("index").asJsObject.fields("result").asInstanceOf[JsString].value - if (result == "created" || result == "updated") { - None - } else { - Some(message) + item.asJsObject.fields("index").asJsObject.fields.get("error").map { _ => + message } } - // Fetch next messages from queue and send them - val nextMessages = (1 to settings.bufferSize).flatMap { _ => - queue.dequeueFirst(_ => true) - } + if (failed.nonEmpty && settings.retryPartialFailure && retryCount < settings.maxRetry) { + // Retry partial failed messages + retryCount = retryCount + 1 + failedMessages = failed + scheduleOnce(NotUsed, settings.retryInterval.millis) - if (nextMessages.isEmpty) { - state match { - case Finished => handleSuccess() - case _ => state = Idle - } } else { - sendBulkUpdateRequest(nextMessages) - } + retryCount = 0 + push(out, Future.successful(pusher(failed))) + + // Fetch next messages from queue and send them + val nextMessages = (1 to settings.bufferSize).flatMap { _ => + queue.dequeueFirst(_ => true) + } - push(out, Future.successful(pusher(failedMessages))) + if (nextMessages.isEmpty) { + state match { + case Finished => handleSuccess() + case _ => state = Idle + } + } else { + sendBulkUpdateRequest(nextMessages) + } + } } private def sendBulkUpdateRequest(messages: Seq[IncomingMessage[T]]): Unit = { @@ -131,7 +139,7 @@ class ElasticsearchFlowStage[T, R]( "POST", "/_bulk", Map[String, String]().asJava, - new StringEntity(json), + new StringEntity(json, StandardCharsets.UTF_8), new ResponseListener() { override def onFailure(exception: Exception): Unit = failureHandler.invoke((messages, exception)) diff --git a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/ElasticsearchSourceStage.scala b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/ElasticsearchSourceStage.scala index 14531d6388..99907431cf 100644 --- a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/ElasticsearchSourceStage.scala +++ b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/ElasticsearchSourceStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch import java.io.ByteArrayOutputStream diff --git a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchFlow.scala b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchFlow.scala index 331148b39e..1692f74b72 100644 --- a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchFlow.scala +++ b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchFlow.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch.javadsl import akka.NotUsed diff --git a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSink.scala b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSink.scala index 2d2c50f9a6..8a0093cb2d 100644 --- a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSink.scala +++ b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch.javadsl import java.util.concurrent.CompletionStage diff --git a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSinkSettings.scala b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSinkSettings.scala index 627d3cf84c..cc1e7e8489 100644 --- a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSinkSettings.scala +++ b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSinkSettings.scala @@ -1,29 +1,37 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch.javadsl import akka.stream.alpakka.elasticsearch._ import scaladsl.{ElasticsearchSinkSettings => ScalaElasticsearchSinkSettings} -final class ElasticsearchSinkSettings(val bufferSize: Int, val retryInterval: Int, val maxRetry: Int) { +final class ElasticsearchSinkSettings(val bufferSize: Int, + val retryInterval: Int, + val maxRetry: Int, + val retryPartialFailure: Boolean) { - def this() = this(10, 5000, 100) + def this() = this(10, 5000, 100, true) def withBufferSize(bufferSize: Int): ElasticsearchSinkSettings = - new ElasticsearchSinkSettings(bufferSize, this.retryInterval, this.maxRetry) + new ElasticsearchSinkSettings(bufferSize, this.retryInterval, this.maxRetry, this.retryPartialFailure) def withRetryInterval(retryInterval: Int): ElasticsearchSinkSettings = - new ElasticsearchSinkSettings(this.bufferSize, retryInterval, this.maxRetry) + new ElasticsearchSinkSettings(this.bufferSize, retryInterval, this.maxRetry, this.retryPartialFailure) def withMaxRetry(maxRetry: Int): ElasticsearchSinkSettings = - new ElasticsearchSinkSettings(this.bufferSize, this.retryInterval, maxRetry) + new ElasticsearchSinkSettings(this.bufferSize, this.retryInterval, maxRetry, this.retryPartialFailure) + + def withRetryPartialFailure(retryPartialFailure: Boolean): ElasticsearchSinkSettings = + new ElasticsearchSinkSettings(this.bufferSize, this.retryInterval, this.maxRetry, retryPartialFailure) private[javadsl] def asScala: ScalaElasticsearchSinkSettings = ScalaElasticsearchSinkSettings( bufferSize = this.bufferSize, retryInterval = this.retryInterval, - maxRetry = this.maxRetry + maxRetry = this.maxRetry, + retryPartialFailure = this.retryPartialFailure ) } diff --git a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSource.scala b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSource.scala index ffa449afb8..ffdb26e0db 100644 --- a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSource.scala +++ b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch.javadsl import akka.NotUsed diff --git a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSourceSettings.scala b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSourceSettings.scala index 1e56f995d0..14d41159b9 100644 --- a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSourceSettings.scala +++ b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/javadsl/ElasticsearchSourceSettings.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch.javadsl import akka.stream.alpakka.elasticsearch._ diff --git a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchFlow.scala b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchFlow.scala index 74d79352d1..e17f2b2f96 100644 --- a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchFlow.scala +++ b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchFlow.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch.scaladsl import akka.NotUsed diff --git a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSink.scala b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSink.scala index e878070efa..201f62e90a 100644 --- a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSink.scala +++ b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch.scaladsl import akka.Done diff --git a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSinkSettings.scala b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSinkSettings.scala index a14487baa4..a9a3d4fd1b 100644 --- a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSinkSettings.scala +++ b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSinkSettings.scala @@ -1,8 +1,12 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch.scaladsl //#sink-settings -final case class ElasticsearchSinkSettings(bufferSize: Int = 10, retryInterval: Int = 5000, maxRetry: Int = 100) +final case class ElasticsearchSinkSettings(bufferSize: Int = 10, + retryInterval: Int = 5000, + maxRetry: Int = 100, + retryPartialFailure: Boolean = true) //#sink-settings diff --git a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSource.scala b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSource.scala index f7cc2eaf51..8584657947 100644 --- a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSource.scala +++ b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch.scaladsl import akka.NotUsed diff --git a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSourceSettings.scala b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSourceSettings.scala index 1f77050f26..613a4e1e85 100644 --- a/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSourceSettings.scala +++ b/elasticsearch/src/main/scala/akka/stream/alpakka/elasticsearch/scaladsl/ElasticsearchSourceSettings.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch.scaladsl //#source-settings diff --git a/elasticsearch/src/test/java/akka/stream/alpakka/elasticsearch/ElasticsearchTest.java b/elasticsearch/src/test/java/akka/stream/alpakka/elasticsearch/ElasticsearchTest.java index 6866d770c4..5a9d3bb823 100644 --- a/elasticsearch/src/test/java/akka/stream/alpakka/elasticsearch/ElasticsearchTest.java +++ b/elasticsearch/src/test/java/akka/stream/alpakka/elasticsearch/ElasticsearchTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch; import akka.Done; @@ -214,9 +215,9 @@ public void flow() throws Exception { List>> result1 = f1.toCompletableFuture().get(); flush("sink3"); - assertEquals(2, result1.size()); - assertEquals(true, result1.get(0).isEmpty()); - assertEquals(true, result1.get(1).isEmpty()); + for(int i = 0; i < result1.size(); i ++){ + assertEquals(true, result1.get(i).isEmpty()); + } // Assert docs in sink3/book CompletionStage> f2 = ElasticsearchSource.typed( diff --git a/elasticsearch/src/test/scala/akka/stream/alpakka/elasticsearch/ElasticsearchSpec.scala b/elasticsearch/src/test/scala/akka/stream/alpakka/elasticsearch/ElasticsearchSpec.scala index dbf65b9dbe..1036b79349 100644 --- a/elasticsearch/src/test/scala/akka/stream/alpakka/elasticsearch/ElasticsearchSpec.scala +++ b/elasticsearch/src/test/scala/akka/stream/alpakka/elasticsearch/ElasticsearchSpec.scala @@ -1,12 +1,13 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.elasticsearch import akka.actor.ActorSystem import akka.stream.ActorMaterializer import akka.stream.alpakka.elasticsearch.scaladsl._ -import akka.stream.scaladsl.Sink +import akka.stream.scaladsl.{Sink, Source} import akka.testkit.TestKit import org.apache.http.HttpHost import org.apache.http.entity.StringEntity @@ -69,6 +70,24 @@ class ElasticsearchSpec extends WordSpec with Matchers with BeforeAndAfterAll { private def flush(indexName: String): Unit = client.performRequest("POST", s"$indexName/_flush") + private def createStrictMapping(indexName: String): Unit = + client.performRequest( + "PUT", + s"$indexName", + Map[String, String]().asJava, + new StringEntity(s"""{ + | "mappings": { + | "book": { + | "dynamic": "strict", + | "properties": { + | "title": { "type": "string"} + | } + | } + | } + |} + """.stripMargin) + ) + private def register(indexName: String, title: String): Unit = client.performRequest("POST", s"$indexName/book", @@ -181,7 +200,7 @@ class ElasticsearchSpec extends WordSpec with Matchers with BeforeAndAfterAll { } "ElasticsearchFlow" should { - "store documents and pass Responses" in { + "store documents and pass failed documents to downstream" in { // Copy source/book to sink3/book through typed stream //#run-flow val f1 = ElasticsearchSource @@ -237,4 +256,110 @@ class ElasticsearchSpec extends WordSpec with Matchers with BeforeAndAfterAll { } } + "ElasticsearchFlow" should { + "not post invalid encoded JSON" in { + + val books = Seq( + "Akka in Action", + "Akka \u00DF Concurrency" + ) + + val f1 = Source(books.zipWithIndex.toVector) + .map { + case (book: String, index: Int) => + IncomingMessage(Some(index.toString), Book(book)) + } + .via( + ElasticsearchFlow.typed[Book]( + "sink4", + "book", + ElasticsearchSinkSettings(5) + ) + ) + .runWith(Sink.seq) + + val result1 = Await.result(f1, Duration.Inf) + flush("sink4") + + // Assert no error + assert(result1.forall(_.isEmpty)) + + // Assert docs in sink4/book + val f2 = ElasticsearchSource + .typed[Book]( + "sink4", + "book", + """{"match_all": {}}""", + ElasticsearchSourceSettings() + ) + .map { message => + message.source.title + } + .runWith(Sink.seq) + + val result2 = Await.result(f2, Duration.Inf) + + result2.sorted shouldEqual Seq( + "Akka in Action", + "Akka \u00DF Concurrency" + ) + } + } + + "ElasticsearchFlow" should { + "retry a failed documents and pass retired documents to downstream" in { + // Create strict mapping to prevent invalid documents + createStrictMapping("sink5") + + val f1 = Source( + Seq( + Map("title" -> "Akka in Action").toJson, + Map("subject" -> "Akka Concurrency").toJson + ).zipWithIndex.toVector + ).map { + case (book: JsObject, index: Int) => + IncomingMessage(Some(index.toString), book) + } + .via( + ElasticsearchFlow( + "sink5", + "book", + ElasticsearchSinkSettings(maxRetry = 5, retryInterval = 100) + ) + ) + .runWith(Sink.seq) + + val start = System.currentTimeMillis() + val result1 = Await.result(f1, Duration.Inf) + val end = System.currentTimeMillis() + + // Assert retired documents + assert(result1.flatten == Seq(IncomingMessage(Some("1"), Map("subject" -> "Akka Concurrency").toJson))) + + // Assert retried 5 times by looking duration + assert(end - start > 5 * 100) + + flush("sink5") + + // Assert docs in sink5/book + val f2 = ElasticsearchSource + .typed[Book]( + "sink5", + "book", + """{"match_all": {}}""", + ElasticsearchSourceSettings() + ) + .map { message => + message.source.title + } + .runWith(Sink.seq) + + val result2 = Await.result(f2, Duration.Inf) + + result2.sorted shouldEqual Seq( + "Akka in Action" + ) + } + } + } diff --git a/file/src/main/java/akka/stream/alpakka/file/DirectoryChange.java b/file/src/main/java/akka/stream/alpakka/file/DirectoryChange.java index c434324d9f..e663040e7a 100644 --- a/file/src/main/java/akka/stream/alpakka/file/DirectoryChange.java +++ b/file/src/main/java/akka/stream/alpakka/file/DirectoryChange.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file; diff --git a/file/src/main/java/akka/stream/alpakka/file/javadsl/Directory.java b/file/src/main/java/akka/stream/alpakka/file/javadsl/Directory.java index b1380ac43c..06bc6ab5c1 100644 --- a/file/src/main/java/akka/stream/alpakka/file/javadsl/Directory.java +++ b/file/src/main/java/akka/stream/alpakka/file/javadsl/Directory.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file.javadsl; import akka.NotUsed; diff --git a/file/src/main/java/akka/stream/alpakka/file/javadsl/DirectoryChangesSource.java b/file/src/main/java/akka/stream/alpakka/file/javadsl/DirectoryChangesSource.java index 01f38cb71b..c94caf3aa8 100644 --- a/file/src/main/java/akka/stream/alpakka/file/javadsl/DirectoryChangesSource.java +++ b/file/src/main/java/akka/stream/alpakka/file/javadsl/DirectoryChangesSource.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file.javadsl; import akka.NotUsed; diff --git a/file/src/main/java/akka/stream/alpakka/file/javadsl/FileTailSource.java b/file/src/main/java/akka/stream/alpakka/file/javadsl/FileTailSource.java index 8ecb8f4b88..00f54ddc39 100644 --- a/file/src/main/java/akka/stream/alpakka/file/javadsl/FileTailSource.java +++ b/file/src/main/java/akka/stream/alpakka/file/javadsl/FileTailSource.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file.javadsl; import akka.NotUsed; diff --git a/file/src/main/scala/akka/stream/alpakka/file/javadsl/LogRotatorSink.scala b/file/src/main/scala/akka/stream/alpakka/file/javadsl/LogRotatorSink.scala new file mode 100644 index 0000000000..f2b60332fe --- /dev/null +++ b/file/src/main/scala/akka/stream/alpakka/file/javadsl/LogRotatorSink.scala @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.file.javadsl + +import java.nio.file.{Path, StandardOpenOption} +import java.util +import java.util.concurrent.CompletionStage + +import akka.Done +import akka.stream.javadsl +import akka.stream.javadsl.Sink +import akka.util.ByteString +import akka.japi.{function} + +import scala.collection.JavaConverters._ + +object LogRotatorSink { + def createFromFunction( + f: function.Creator[function.Function[ByteString, Path]] + ): javadsl.Sink[ByteString, CompletionStage[Done]] = + new Sink( + akka.stream.alpakka.file.scaladsl + .LogRotatorSink({ () => + val fun = f.create() + elem => + Option(fun(elem)) + }) + .toCompletionStage() + ) + + def createFromFunctionAndOptions[T]( + f: function.Creator[function.Function[ByteString, Path]], + options: util.Set[StandardOpenOption] + ): javadsl.Sink[ByteString, CompletionStage[Done]] = + new Sink( + akka.stream.alpakka.file.scaladsl + .LogRotatorSink({ () => + val fun = f.create() + elem => + Option(fun(elem)) + }, options.asScala.toSet) + .toCompletionStage() + ) +} diff --git a/file/src/main/scala/akka/stream/alpakka/file/scaladsl/Directory.scala b/file/src/main/scala/akka/stream/alpakka/file/scaladsl/Directory.scala index 22bed90eb4..acd579d552 100644 --- a/file/src/main/scala/akka/stream/alpakka/file/scaladsl/Directory.scala +++ b/file/src/main/scala/akka/stream/alpakka/file/scaladsl/Directory.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file.scaladsl import java.nio.file.{FileVisitOption, Files, Path} diff --git a/file/src/main/scala/akka/stream/alpakka/file/scaladsl/DirectoryChangesSource.scala b/file/src/main/scala/akka/stream/alpakka/file/scaladsl/DirectoryChangesSource.scala index cdb9f86d06..fd41bbd3ad 100644 --- a/file/src/main/scala/akka/stream/alpakka/file/scaladsl/DirectoryChangesSource.scala +++ b/file/src/main/scala/akka/stream/alpakka/file/scaladsl/DirectoryChangesSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file.scaladsl import java.nio.file.Path diff --git a/file/src/main/scala/akka/stream/alpakka/file/scaladsl/FileTailSource.scala b/file/src/main/scala/akka/stream/alpakka/file/scaladsl/FileTailSource.scala index 30d08fda45..ff2e90e4fd 100644 --- a/file/src/main/scala/akka/stream/alpakka/file/scaladsl/FileTailSource.scala +++ b/file/src/main/scala/akka/stream/alpakka/file/scaladsl/FileTailSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file.scaladsl import java.nio.charset.{Charset, StandardCharsets} diff --git a/file/src/main/scala/akka/stream/alpakka/file/scaladsl/LogRotatorSink.scala b/file/src/main/scala/akka/stream/alpakka/file/scaladsl/LogRotatorSink.scala new file mode 100644 index 0000000000..93662a85c6 --- /dev/null +++ b/file/src/main/scala/akka/stream/alpakka/file/scaladsl/LogRotatorSink.scala @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.file.scaladsl + +import java.nio.file.{OpenOption, Path, StandardOpenOption} + +import akka.Done +import akka.stream.ActorAttributes.SupervisionStrategy +import akka.stream._ +import akka.stream.impl.fusing.MapAsync.{Holder, NotYetThere} +import akka.stream.scaladsl.{FileIO, Sink, Source} +import akka.stream.stage._ +import akka.util.ByteString + +import scala.concurrent.{ExecutionContext, Future, Promise} +import scala.util.{Failure, Success} + +object LogRotatorSink { + def apply( + functionGeneratorFunction: () => ByteString => Option[Path], + fileOpenOptions: Set[OpenOption] = Set(StandardOpenOption.APPEND, StandardOpenOption.CREATE) + ): Sink[ByteString, Future[Done]] = + Sink.fromGraph(new LogRotatorSink(functionGeneratorFunction, fileOpenOptions)) +} + +final private[scaladsl] class LogRotatorSink(functionGeneratorFunction: () => ByteString => Option[Path], + fileOpenOptions: Set[OpenOption]) + extends GraphStageWithMaterializedValue[SinkShape[ByteString], Future[Done]] { + + val in = Inlet[ByteString]("FRotator.in") + override val shape = SinkShape.of(in) + + override def createLogicAndMaterializedValue(inheritedAttributes: Attributes): (GraphStageLogic, Future[Done]) = { + val promise = Promise[Done]() + val logic = new GraphStageLogic(shape) { + val pathGeneratorFunction: ByteString => Option[Path] = functionGeneratorFunction() + var sourceOut: SubSourceOutlet[ByteString] = _ + var fileSinkCompleted: Seq[Future[IOResult]] = Seq.empty + val decider = + inheritedAttributes.get[SupervisionStrategy].map(_.decider).getOrElse(Supervision.stoppingDecider) + + def failThisStage(ex: Throwable): Unit = + if (!promise.isCompleted) { + if (sourceOut != null) { + sourceOut.fail(ex) + } + cancel(in) + promise.failure(ex) + } + + def generatePathOrFailPeacefully(data: ByteString): Option[Path] = { + var ret = Option.empty[Path] + try { + ret = pathGeneratorFunction(data) + } catch { + case ex: Throwable => + failThisStage(ex) + } + ret + } + + def fileSinkFutureCallbackHandler(future: Future[IOResult])(h: Holder[IOResult]): Unit = + h.elem match { + case Success(IOResult(_, Failure(ex))) if decider(ex) == Supervision.Stop => + promise.failure(ex) + case Success(x) if fileSinkCompleted.size == 1 && fileSinkCompleted.head == future => + promise.trySuccess(Done) + completeStage() + case x: Success[IOResult] => + fileSinkCompleted = fileSinkCompleted.filter(_ != future) + case Failure(ex) => + failThisStage(ex) + case _ => + } + + //init stage where we are waiting for the first path + setHandler( + in, + new InHandler { + override def onPush(): Unit = { + val data = grab(in) + val pathO = generatePathOrFailPeacefully(data) + pathO.fold( + if (!isClosed(in)) pull(in) + )( + switchPath(_, data) + ) + } + + override def onUpstreamFinish(): Unit = + completeStage() + + override def onUpstreamFailure(ex: Throwable): Unit = + failThisStage(ex) + } + ) + + //we must pull the first element cos we are a sink + override def preStart(): Unit = { + super.preStart() + pull(in) + } + + def futureCB(newFuture: Future[IOResult]) = + getAsyncCallback[Holder[IOResult]](fileSinkFutureCallbackHandler(newFuture)) + + //we recreate the tail of the stream, and emit the data for the next req + def switchPath(path: Path, data: ByteString): Unit = { + val prevOut = Option(sourceOut) + + sourceOut = new SubSourceOutlet[ByteString]("FRotatorSource") + sourceOut.setHandler(new OutHandler { + override def onPull(): Unit = { + sourceOut.push(data) + switchToNormalMode() + } + }) + val newFuture = Source + .fromGraph(sourceOut.source) + .runWith(FileIO.toPath(path, fileOpenOptions))(interpreter.subFusingMaterializer) + + fileSinkCompleted = fileSinkCompleted :+ newFuture + + val holder = new Holder[IOResult](NotYetThere, futureCB(newFuture)) + + newFuture.onComplete(holder)( + akka.dispatch.ExecutionContexts.sameThreadExecutionContext + ) + + prevOut.foreach(_.complete()) + } + + //we change path if needed or push the grabbed data + def switchToNormalMode(): Unit = { + setHandler( + in, + new InHandler { + override def onPush(): Unit = { + val data = grab(in) + val pathO = generatePathOrFailPeacefully(data) + pathO.fold( + sourceOut.push(data) + )( + switchPath(_, data) + ) + } + + override def onUpstreamFinish(): Unit = { + implicit val executionContext: ExecutionContext = + akka.dispatch.ExecutionContexts.sameThreadExecutionContext + promise.completeWith(Future.sequence(fileSinkCompleted).map(_ => Done)) + sourceOut.complete() + } + + override def onUpstreamFailure(ex: Throwable): Unit = + failThisStage(ex) + } + ) + sourceOut.setHandler(new OutHandler { + override def onPull(): Unit = + pull(in) + }) + } + } + (logic, promise.future) + } + +} diff --git a/file/src/test/java/akka/stream/alpakka/file/javadsl/DirectoryChangesSourceTest.java b/file/src/test/java/akka/stream/alpakka/file/javadsl/DirectoryChangesSourceTest.java index 0cfedb1a4c..2cb2dbdfbf 100644 --- a/file/src/test/java/akka/stream/alpakka/file/javadsl/DirectoryChangesSourceTest.java +++ b/file/src/test/java/akka/stream/alpakka/file/javadsl/DirectoryChangesSourceTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file.javadsl; import akka.Done; diff --git a/file/src/test/java/akka/stream/alpakka/file/javadsl/DirectoryTest.java b/file/src/test/java/akka/stream/alpakka/file/javadsl/DirectoryTest.java index c0464a477c..c855f6eb9f 100644 --- a/file/src/test/java/akka/stream/alpakka/file/javadsl/DirectoryTest.java +++ b/file/src/test/java/akka/stream/alpakka/file/javadsl/DirectoryTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file.javadsl; import akka.NotUsed; diff --git a/file/src/test/java/akka/stream/alpakka/file/javadsl/FileTailSourceTest.java b/file/src/test/java/akka/stream/alpakka/file/javadsl/FileTailSourceTest.java index cf1f52814b..ae2fe1fb73 100644 --- a/file/src/test/java/akka/stream/alpakka/file/javadsl/FileTailSourceTest.java +++ b/file/src/test/java/akka/stream/alpakka/file/javadsl/FileTailSourceTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file.javadsl; import akka.NotUsed; diff --git a/file/src/test/java/akka/stream/alpakka/file/javadsl/LogRotatorSinkTest.java b/file/src/test/java/akka/stream/alpakka/file/javadsl/LogRotatorSinkTest.java new file mode 100644 index 0000000000..88ee23b859 --- /dev/null +++ b/file/src/test/java/akka/stream/alpakka/file/javadsl/LogRotatorSinkTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.file.javadsl; + +import akka.Done; +import akka.actor.ActorSystem; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.javadsl.Sink; +import akka.util.ByteString; +import scala.Function0; +import scala.Function1; + +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Objects; +import java.util.concurrent.CompletionStage; +import java.util.function.DoubleSupplier; +import java.util.function.IntSupplier; + + +public class LogRotatorSinkTest { + + public static void main(String... args) { + final ActorSystem system = ActorSystem.create(); + final Materializer materializer = ActorMaterializer.create(system); + + // #LogRotationSink-filesize-sample + final FileSystem fs = FileSystems.getDefault(); + + Sink> fileSizeBasedRotation = LogRotatorSink.createFromFunction( + () -> { + long max = 10 * 1024 * 1024; + final long[] size = new long[] {max}; + return (element) -> { + if (size[0] + element.size() > max) { + Path path = Files.createTempFile(fs.getPath("/"), "test", ".log"); + size[0] = element.size(); + return path; + } else { + size[0] += element.size(); + return null; + } + }; + }); + // #LogRotationSink-filesize-sample + + // #LogRotationSink-timebased-sample + Sink> timeBasedRotation = LogRotatorSink.createFromFunction( + () -> { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"); + final String[] lastFileName = new String[] {null}; + return (element) -> { + String newName = ZonedDateTime.now().format(formatter) + ".log"; + if (lastFileName[0] == null || !lastFileName[0].equals(newName)) { + lastFileName[0] = newName; + return fs.getPath(newName); + } else { + return null; + } + }; + }); + // #LogRotationSink-timebased-sample + + } +} diff --git a/file/src/test/scala/akka/stream/alpakka/file/scaladsl/DirectoryChangesSourceSpec.scala b/file/src/test/scala/akka/stream/alpakka/file/scaladsl/DirectoryChangesSourceSpec.scala index d221d2eaba..7beb7286cc 100644 --- a/file/src/test/scala/akka/stream/alpakka/file/scaladsl/DirectoryChangesSourceSpec.scala +++ b/file/src/test/scala/akka/stream/alpakka/file/scaladsl/DirectoryChangesSourceSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file.scaladsl import java.nio.file.FileSystems diff --git a/file/src/test/scala/akka/stream/alpakka/file/scaladsl/DirectorySpec.scala b/file/src/test/scala/akka/stream/alpakka/file/scaladsl/DirectorySpec.scala index 9bda4cfa3b..0c329b66fc 100644 --- a/file/src/test/scala/akka/stream/alpakka/file/scaladsl/DirectorySpec.scala +++ b/file/src/test/scala/akka/stream/alpakka/file/scaladsl/DirectorySpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file.scaladsl import java.nio.file.{Files, Path} diff --git a/file/src/test/scala/akka/stream/alpakka/file/scaladsl/FileTailSourceSpec.scala b/file/src/test/scala/akka/stream/alpakka/file/scaladsl/FileTailSourceSpec.scala index 8115f08808..dbe8db4661 100644 --- a/file/src/test/scala/akka/stream/alpakka/file/scaladsl/FileTailSourceSpec.scala +++ b/file/src/test/scala/akka/stream/alpakka/file/scaladsl/FileTailSourceSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.file.scaladsl import java.nio.file.FileSystems diff --git a/file/src/test/scala/akka/stream/alpakka/file/scaladsl/LogRotatorSinkSpec.scala b/file/src/test/scala/akka/stream/alpakka/file/scaladsl/LogRotatorSinkSpec.scala new file mode 100644 index 0000000000..3f003c2297 --- /dev/null +++ b/file/src/test/scala/akka/stream/alpakka/file/scaladsl/LogRotatorSinkSpec.scala @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.file.scaladsl + +import java.nio.channels.NonWritableChannelException +import java.nio.file._ +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter + +import akka.actor.ActorSystem +import akka.stream.scaladsl.{Keep, Source} +import akka.stream.testkit.scaladsl.TestSource +import akka.stream.{ActorMaterializer, ActorMaterializerSettings, Materializer} +import akka.testkit.TestKit +import akka.util.ByteString +import com.google.common.jimfs.{Configuration, Jimfs} +import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike} + +import scala.collection.mutable.ListBuffer +import scala.concurrent.Await +import scala.concurrent.duration._ + +object LogRotatorSinkSpec { + + def main(args: Array[String]): Unit = { + implicit val system: ActorSystem = ActorSystem() + implicit val materializer: Materializer = ActorMaterializer() + // #LogRotationSink-filesize-sample + val fs = FileSystems.getDefault + + val fileSizeRotationFunction = () => { + val max = 10 * 1024 * 1024 + var size: Long = max + (element: ByteString) => + { + if (size + element.size > max) { + val path = Files.createTempFile(fs.getPath("/"), "test", ".log") + println(path) + size = element.size + Some(path) + } else { + size += element.size + None + } + } + } + // #LogRotationSink-filesize-sample + + // #LogRotationSink-timebased-sample + val timeBasedRotationFunction = () => { + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss.SSS") + var lastFilename: Option[String] = None + (element: ByteString) => + { + val newName = ZonedDateTime.now().format(formatter) + ".log" + if (lastFilename.isEmpty || lastFilename.get != newName) { + lastFilename = Some(newName) + Some(fs.getPath(newName)) + } else { + None + } + } + } + // #LogRotationSink-timebased-sample + + val pathGeneratorFunction = timeBasedRotationFunction + + // #LogRotationSink-sample + val completion = Source(Seq("test1", "test2", "test3", "test4", "test5", "test6").toList) + .map(ByteString(_)) + .runWith(LogRotatorSink(pathGeneratorFunction)) + // #LogRotationSink-sample + + val completion2 = Source(Seq("test1", "test2", "test3", "test4", "test5", "test6").toList) + .map(ByteString(_)) + .runWith(LogRotatorSink(fileSizeRotationFunction)) + + Await.result(completion, 3.seconds) + Await.result(completion2, 3.seconds) + } + +} + +class LogRotatorSinkSpec + extends TestKit(ActorSystem("LogRotatorSinkSpec")) + with WordSpecLike + with Matchers + with BeforeAndAfterAll { + + override protected def afterAll(): Unit = { + TestKit.shutdownActorSystem(system) + fs.close() + } + + val settings = ActorMaterializerSettings(system).withDispatcher("akka.actor.default-dispatcher") + implicit val materializer = ActorMaterializer(settings) + val fs = Jimfs.newFileSystem("LogRotatorSinkSpec", Configuration.unix()) + + val TestLines = { + val buffer = ListBuffer[String]() + buffer.append("a" * 1000 + "\n") + buffer.append("b" * 1000 + "\n") + buffer.append("c" * 1000 + "\n") + buffer.append("d" * 1000 + "\n") + buffer.append("e" * 1000 + "\n") + buffer.append("f" * 1000 + "\n") + buffer.toList + } + + def fileLengthFunctionFactory(): (() => (ByteString) => Option[Path], () => Seq[Path]) = { + var files = Seq.empty[Path] + val testFunction = () => { + val max = 2002 + var size: Long = max + (element: ByteString) => + { + if (size + element.size > max) { + val path = Files.createTempFile(fs.getPath("/"), "test", ".log") + files :+= path + size = element.size + Option(path) + } else { + size += element.size + Option.empty[Path] + } + } + } + val listFiles = () => files + (testFunction, listFiles) + } + + val testByteStrings = TestLines.map(ByteString(_)) + + "LogRotatorSink" must { + "write lines to a single file" in { + var files = Seq.empty[Path] + val testFunction = () => { + var fileName: String = null + (element: ByteString) => + { + if (fileName == null) { + val path = Files.createTempFile(fs.getPath("/"), "test", ".log") + files :+= path + fileName = path.toString + Some(path) + } else { + None + } + } + } + val completion = Source(testByteStrings).runWith(LogRotatorSink(testFunction)) + Await.result(completion, 3.seconds) + + val (contents, sizes) = readUpFilesAndSizesThenClean(files) + sizes should contain theSameElementsAs Seq(6006L) + contents should contain theSameElementsAs Seq(TestLines.mkString("")) + } + "write lines to multiple files due to filesize" in { + val (testFunction, files) = fileLengthFunctionFactory() + val completion = + Source(testByteStrings).runWith(LogRotatorSink(testFunction)) + + Await.result(completion, 3.seconds) + + val (contents, sizes) = readUpFilesAndSizesThenClean(files()) + sizes should contain theSameElementsAs Seq(2002L, 2002L, 2002L) + contents should contain theSameElementsAs TestLines.sliding(2, 2).map(_.mkString("")).toList + } + "upstream fail before first file creation" in { + val (testFunction, files) = fileLengthFunctionFactory() + val (probe, completion) = + TestSource.probe[ByteString].toMat(LogRotatorSink(testFunction))(Keep.both).run() + + val ex = new Exception("my-exception") + probe.sendError(ex) + the[Exception] thrownBy Await.result(completion, 3.seconds) shouldBe ex + files() shouldBe empty + } + + "upstream fail after first file creation" in { + val (testFunction, files) = fileLengthFunctionFactory() + val (probe, completion) = + TestSource.probe[ByteString].toMat(LogRotatorSink(testFunction))(Keep.both).run() + + val ex = new Exception("my-exception") + probe.sendNext(ByteString("test")) + probe.sendError(ex) + the[Exception] thrownBy Await.result(completion, 3.seconds) shouldBe ex + files().size shouldBe 1 + readUpFilesAndSizesThenClean(files()) + } + "function fail on path creation" in { + val ex = new Exception("my-exception") + val testFunction = () => { (x: ByteString) => + { + throw ex + } + } + val (probe, completion) = + TestSource.probe[ByteString].toMat(LogRotatorSink(testFunction))(Keep.both).run() + probe.sendNext(ByteString("test")) + the[Exception] thrownBy Await.result(completion, 3.seconds) shouldBe ex + } + + "downstream fail on file write" in { + val path = Files.createTempFile(fs.getPath("/"), "test", ".log") + val testFunction = () => { (x: ByteString) => + { + Option(path) + } + } + val (probe, completion) = + TestSource.probe[ByteString].toMat(LogRotatorSink(testFunction, Set(StandardOpenOption.READ)))(Keep.both).run() + probe.sendNext(ByteString("test")) + probe.sendNext(ByteString("test")) + probe.expectCancellation() + the[Exception] thrownBy Await.result(completion, 3.seconds) shouldBe a[NonWritableChannelException] + } + + } + + def readUpFilesAndSizesThenClean(files: Seq[Path]): (Seq[String], Seq[Long]) = { + var sizes = Seq.empty[Long] + var data = Seq.empty[String] + files.foreach { path => + sizes = sizes :+ Files.size(path) + data = data :+ new String(Files.readAllBytes(path)) + Files.delete(path) + } + (data, sizes) + } +} diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpBrowserGraphStage.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpBrowserGraphStage.scala index 0dd2e53911..b10dd4c6c6 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpBrowserGraphStage.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpBrowserGraphStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp package impl diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpGraphStageLogic.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpGraphStageLogic.scala index 6b632e909e..8647684fb3 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpGraphStageLogic.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpGraphStageLogic.scala @@ -1,9 +1,12 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp package impl +import java.io.IOException + import akka.stream.Shape import akka.stream.stage.GraphStageLogic @@ -18,6 +21,7 @@ private[ftp] abstract class FtpGraphStageLogic[T, FtpClient, S <: RemoteFileSett protected[this] implicit val client = ftpClient() protected[this] var handler: Option[ftpLike.Handler] = Option.empty[ftpLike.Handler] + protected[this] var failed = false override def preStart(): Unit = { super.preStart() @@ -36,8 +40,19 @@ private[ftp] abstract class FtpGraphStageLogic[T, FtpClient, S <: RemoteFileSett } override def postStop(): Unit = { + try { + disconnect() + } catch { + case e: IOException => + matFailure(e) + // If we're failing, we might not be able to cleanly shut down the connection. + // So swallow any IO exceptions + if (!failed) throw e + case NonFatal(e) => + matFailure(e) + throw e + } matSuccess() - disconnect() super.postStop() } diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpIOGraphStage.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpIOGraphStage.scala index 2d90fa2c01..24c6e082e7 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpIOGraphStage.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpIOGraphStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp package impl @@ -9,8 +10,10 @@ import akka.stream.stage.{GraphStageWithMaterializedValue, InHandler, OutHandler import akka.stream.{Attributes, IOResult, Inlet, Outlet, Shape, SinkShape, SourceShape} import akka.util.ByteString import akka.util.ByteString.ByteString1C + import scala.concurrent.{Future, Promise} -import java.io.{InputStream, OutputStream} +import java.io.{IOException, InputStream, OutputStream} + import scala.util.control.NonFatal private[ftp] trait FtpIOGraphStage[FtpClient, S <: RemoteFileSettings, Sh <: Shape] @@ -53,33 +56,38 @@ private[ftp] trait FtpIOSourceStage[FtpClient, S <: RemoteFileSettings] out, new OutHandler { def onPull(): Unit = - readChunk() match { - case Some(bs) => - push(out, bs) - case None => - try { - isOpt.foreach(_.close()) - disconnect() - } finally { - matSuccess() - complete(out) - } - } - - override def onDownstreamFinish(): Unit = try { - isOpt.foreach(_.close()) - disconnect() - } finally { - matSuccess() - super.onDownstreamFinish() + readChunk() match { + case Some(bs) => + push(out, bs) + case None => + complete(out) + } + } catch { + case NonFatal(e) => + failed = true + matFailure(e) + failStage(e) } } ) // end of handler override def postStop(): Unit = try { - isOpt.foreach(_.close()) + isOpt.foreach { os => + try { + os.close() + } catch { + case e: IOException => + matFailure(e) + // If we failed, we have to expect the stream might already be dead + // so swallow the IOException + if (!failed) throw e + case NonFatal(e) => + matFailure(e) + throw e + } + } } finally { super.postStop() } @@ -138,40 +146,41 @@ private[ftp] trait FtpIOSinkStage[FtpClient, S <: RemoteFileSettings] setHandler( in, new InHandler { - override def onPush(): Unit = { + override def onPush(): Unit = try { write(grab(in)) + pull(in) } catch { case NonFatal(e) ⇒ + failed = true matFailure(e) - try osOpt.foreach(_.close()) - catch { - case NonFatal(_) ⇒ - } - osOpt = None - throw e - } - pull(in) - } - override def onUpstreamFinish(): Unit = - try { - osOpt.foreach(_.close()) - disconnect() - } finally { - matSuccess() - super.onUpstreamFinish() + failStage(e) } override def onUpstreamFailure(exception: Throwable): Unit = { matFailure(exception) - failStage(exception) + failed = true + super.onUpstreamFailure(exception) } } ) // end of handler override def postStop(): Unit = try { - osOpt.foreach(_.close()) + osOpt.foreach { os => + try { + os.close() + } catch { + case e: IOException => + matFailure(e) + // If we failed, we have to expect the stream might already be dead + // so swallow the IOException + if (!failed) throw e + case NonFatal(e) => + matFailure(e) + throw e + } + } } finally { super.postStop() } diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpLike.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpLike.scala index e88bfb013e..9fdc0ff0e6 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpLike.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpLike.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp package impl diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpOperations.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpOperations.scala index fc4c5984f7..1c6d6e07fb 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpOperations.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpOperations.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp package impl diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpSourceFactory.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpSourceFactory.scala index dd204fafec..9fe89715e7 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpSourceFactory.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpSourceFactory.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp.impl import akka.stream.alpakka.ftp.FtpCredentials.{AnonFtpCredentials, NonAnonFtpCredentials} diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/SftpOperations.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/SftpOperations.scala index 4718ad0816..9aacd21a02 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/SftpOperations.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/SftpOperations.scala @@ -1,20 +1,23 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp package impl +import java.io.{File, IOException, InputStream, OutputStream} +import java.nio.file.attribute.PosixFilePermission + import net.schmizz.sshj.SSHClient import net.schmizz.sshj.sftp.{OpenMode, RemoteResourceInfo, SFTPClient} import net.schmizz.sshj.transport.verification.PromiscuousVerifier import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile import net.schmizz.sshj.userauth.password.PasswordUtils import net.schmizz.sshj.xfer.FilePermission + +import scala.collection.JavaConverters._ import scala.collection.immutable import scala.util.Try -import scala.collection.JavaConverters._ -import java.nio.file.attribute.PosixFilePermission -import java.io.{File, IOException, InputStream, OutputStream} private[ftp] trait SftpOperations { _: FtpLike[SSHClient, SftpSettings] => @@ -59,7 +62,9 @@ private[ftp] trait SftpOperations { _: FtpLike[SSHClient, SftpSettings] => } private def getPosixFilePermissions(file: RemoteResourceInfo) = { - import FilePermission._, PosixFilePermission._ + import PosixFilePermission._ + + import FilePermission._ file.getAttributes.getPermissions.asScala.collect { case USR_R => OWNER_READ case USR_W => OWNER_WRITE @@ -77,16 +82,40 @@ private[ftp] trait SftpOperations { _: FtpLike[SSHClient, SftpSettings] => def retrieveFileInputStream(name: String, handler: Handler): Try[InputStream] = Try { val remoteFile = handler.open(name, Set(OpenMode.READ).asJava) - val is = new remoteFile.RemoteFileInputStream() - Option(is).getOrElse(throw new IOException(s"$name: No such file or directory")) + val is = new remoteFile.RemoteFileInputStream() { + + override def close(): Unit = + try { + super.close() + } finally { + remoteFile.close() + } + } + Option(is).getOrElse { + remoteFile.close() + throw new IOException(s"$name: No such file or directory") + } } def storeFileOutputStream(name: String, handler: Handler, append: Boolean): Try[OutputStream] = Try { import OpenMode._ val openModes = Set(WRITE, CREAT) ++ (if (append) Set(APPEND) else Set()) val remoteFile = handler.open(name, openModes.asJava) - val os = new remoteFile.RemoteFileOutputStream() - Option(os).getOrElse(throw new IOException(s"Could not write to $name")) + val os = new remoteFile.RemoteFileOutputStream() { + + override def close(): Unit = { + try { + remoteFile.close() + } catch { + case e: IOException => + } + super.close() + } + } + Option(os).getOrElse { + remoteFile.close() + throw new IOException(s"Could not write to $name") + } } private[this] def setIdentity(identity: SftpIdentity, username: String)(implicit ssh: SSHClient) = { diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/javadsl/FtpApi.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/javadsl/FtpApi.scala index 4d07a9f7a8..9c934d18bb 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/javadsl/FtpApi.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/javadsl/FtpApi.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp.javadsl import akka.NotUsed diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/model.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/model.scala index ce42d2c5b6..a94fedc003 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/model.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/model.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp import akka.stream.alpakka.ftp.FtpCredentials.AnonFtpCredentials diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/scaladsl/FtpApi.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/scaladsl/FtpApi.scala index 31a99932d7..cea33b1f35 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/scaladsl/FtpApi.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/scaladsl/FtpApi.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp.scaladsl import akka.NotUsed diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/AkkaSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/AkkaSupport.java index 65c1126430..9254c20473 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/AkkaSupport.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/AkkaSupport.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import akka.actor.ActorSystem; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/CommonFtpStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/CommonFtpStageTest.java index 605ea88697..fee8b3607c 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/CommonFtpStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/CommonFtpStageTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import akka.NotUsed; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpBaseSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpBaseSupport.java index d12ca576d8..54486bd9fb 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpBaseSupport.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpBaseSupport.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import akka.actor.ActorSystem; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java index 70fa8fd578..ea720aaa58 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import akka.NotUsed; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupport.java index 3252835b3e..92a26af620 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupport.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupport.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; interface FtpSupport { diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupportImpl.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupportImpl.java index 353b1893fb..da5c502173 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupportImpl.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupportImpl.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import org.apache.ftpserver.FtpServer; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsStageTest.java index 4a30e48b4f..db922fb544 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsStageTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import akka.NotUsed; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsSupportImpl.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsSupportImpl.java index 84a8d081e6..b18aa3b40e 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsSupportImpl.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsSupportImpl.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import org.apache.ftpserver.FtpServerFactory; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java index 27b6d161d6..05ce6c9698 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import akka.NotUsed; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/PlainFtpSupportImpl.java b/ftp/src/test/java/akka/stream/alpakka/ftp/PlainFtpSupportImpl.java index eeb42124c5..244043eb8a 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/PlainFtpSupportImpl.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/PlainFtpSupportImpl.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import com.google.common.jimfs.Configuration; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java index 4a10dd1739..13aa54c565 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import akka.NotUsed; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/SftpStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/SftpStageTest.java index 023f754a16..a15e611920 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/SftpStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/SftpStageTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import akka.NotUsed; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/SftpSupportImpl.java b/ftp/src/test/java/akka/stream/alpakka/ftp/SftpSupportImpl.java index 2fa4b7f3fa..a00a597d69 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/SftpSupportImpl.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/SftpSupportImpl.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import com.google.common.jimfs.Configuration; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java index ad33f77f0e..bda8ff048a 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp; import akka.NotUsed; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpRetrievingExample.java b/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpRetrievingExample.java index 68aa30451e..e1adfc0f76 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpRetrievingExample.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpRetrievingExample.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp.examples; //#retrieving diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpSettingsExample.java b/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpSettingsExample.java index 3bf7f0a438..c93619d139 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpSettingsExample.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpSettingsExample.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp.examples; //#create-settings diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpTraversingExample.java b/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpTraversingExample.java index 69040bc688..53de640b49 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpTraversingExample.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpTraversingExample.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp.examples; //#traversing diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpWritingExample.java b/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpWritingExample.java index c0f76a1b04..725df927cc 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpWritingExample.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/examples/FtpWritingExample.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp.examples; //#storing diff --git a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/JimfsFactory.java b/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/JimfsFactory.java index 05aba20585..c711cf1695 100644 --- a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/JimfsFactory.java +++ b/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/JimfsFactory.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package org.apache.ftpserver.filesystem.jimfs; import org.apache.ftpserver.filesystem.jimfs.impl.JimfsView; diff --git a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsFtpFile.java b/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsFtpFile.java index 47859b7d07..3b556626f0 100644 --- a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsFtpFile.java +++ b/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsFtpFile.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package org.apache.ftpserver.filesystem.jimfs.impl; import org.apache.ftpserver.ftplet.FtpFile; diff --git a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsView.java b/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsView.java index 85b6c6fc02..377aaf7530 100644 --- a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsView.java +++ b/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsView.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package org.apache.ftpserver.filesystem.jimfs.impl; import org.apache.ftpserver.ftplet.FileSystemView; diff --git a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/NameEqualsPathFilter.java b/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/NameEqualsPathFilter.java index d0fe503a28..e353bb5b82 100644 --- a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/NameEqualsPathFilter.java +++ b/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/NameEqualsPathFilter.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package org.apache.ftpserver.filesystem.jimfs.impl; import java.io.IOException; diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpSpec.scala index 7d160b7c95..2d9d26666a 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp import akka.NotUsed diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpsSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpsSpec.scala index 2fffcf5528..be4ddff306 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpsSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpsSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp import akka.NotUsed diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala index 7c6afa4abf..e9f864bdca 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp import akka.NotUsed diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSpec.scala index 80a4399245..86e141f1cc 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp import akka.NotUsed diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala index fcae10b397..1f46158544 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp import akka.stream.IOResult diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/scalaExamples.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/scalaExamples.scala index 95ee32adab..951aa0c35d 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/scalaExamples.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/scalaExamples.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ftp object scalaExamples { diff --git a/geode/scripts/geode.sh b/geode/scripts/geode.sh index ddc1af16ce..6fd388fa20 100755 --- a/geode/scripts/geode.sh +++ b/geode/scripts/geode.sh @@ -1,11 +1,13 @@ #!/bin/bash -rm -rf /geode -mkdir -p /geode/locator -mkdir -p /geode/server +GEODE_DATA=/geode-data +rm -rf $GEODE_DATA +mkdir -p $GEODE_DATA/locator +mkdir -p $GEODE_DATA/server -gfsh -e "start locator --name=$HOSTNAME-locator --dir=/geode/locator --mcast-port=0 --hostname-for-clients=0.0.0.0" -e "start server --name=$HOSTNAME-server --locators=localhost[10334] --dir=/geode/server --server-port=40404 --max-heap=1G --hostname-for-clients=0.0.0.0 --cache-xml-file=/scripts/cache.xml" + +gfsh -e "start locator --name=$HOSTNAME-locator --dir=$GEODE_DATA/locator --mcast-port=0 --hostname-for-clients=0.0.0.0" -e "start server --name=$HOSTNAME-server --locators=localhost[10334] --dir=$GEODE_DATA/server --server-port=40404 --max-heap=1G --hostname-for-clients=0.0.0.0 --cache-xml-file=/scripts/cache.xml" while true; do sleep 10 diff --git a/geode/src/main/java/akka/stream/alpakka/geode/javadsl/ReactiveGeode.java b/geode/src/main/java/akka/stream/alpakka/geode/javadsl/ReactiveGeode.java index a6bf588f60..eda69512bb 100644 --- a/geode/src/main/java/akka/stream/alpakka/geode/javadsl/ReactiveGeode.java +++ b/geode/src/main/java/akka/stream/alpakka/geode/javadsl/ReactiveGeode.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.javadsl; import akka.Done; diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/AkkaPdxSerializer.scala b/geode/src/main/scala/akka/stream/alpakka/geode/AkkaPdxSerializer.scala index f16bb62161..23db84cb45 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/AkkaPdxSerializer.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/AkkaPdxSerializer.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode import org.apache.geode.pdx.PdxSerializer diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/GeodeSettings.scala b/geode/src/main/scala/akka/stream/alpakka/geode/GeodeSettings.scala index c9b425d895..6952dee558 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/GeodeSettings.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/GeodeSettings.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode import org.apache.geode.cache.client.ClientCacheFactory diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/internal/GeodeCache.scala b/geode/src/main/scala/akka/stream/alpakka/geode/internal/GeodeCache.scala index 9dc2c6ded3..44fcf82829 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/internal/GeodeCache.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/internal/GeodeCache.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal import akka.stream.alpakka.geode.GeodeSettings diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/internal/GeodeCapabilities.scala b/geode/src/main/scala/akka/stream/alpakka/geode/internal/GeodeCapabilities.scala index 29914334aa..2700d34eb4 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/internal/GeodeCapabilities.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/internal/GeodeCapabilities.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal import akka.stream.alpakka.geode.RegionSettings diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/DelegatingPdxSerializer.scala b/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/DelegatingPdxSerializer.scala index bf4f6d27da..9616d461ef 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/DelegatingPdxSerializer.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/DelegatingPdxSerializer.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.pdx import java.util.Properties diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/PdxDecoder.scala b/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/PdxDecoder.scala index 56d05b2d3e..d60ee85bdb 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/PdxDecoder.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/PdxDecoder.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.pdx import java.util.{Date, UUID} diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/PdxEncoder.scala b/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/PdxEncoder.scala index 16441d39ea..93ef4ba445 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/PdxEncoder.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/PdxEncoder.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.pdx import java.util.{Date, UUID} diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/ShapelessPdxSerializer.scala b/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/ShapelessPdxSerializer.scala index c6844a1027..85ffa46ec5 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/ShapelessPdxSerializer.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/internal/pdx/ShapelessPdxSerializer.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.pdx import java.util.Properties diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeCQueryGraphLogic.scala b/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeCQueryGraphLogic.scala index 5a003284ee..3c96dd7012 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeCQueryGraphLogic.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeCQueryGraphLogic.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.stage import java.util diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeContinuousSourceStage.scala b/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeContinuousSourceStage.scala index afaeeab234..9781bf728b 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeContinuousSourceStage.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeContinuousSourceStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.stage import akka.Done diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeFiniteSourceStage.scala b/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeFiniteSourceStage.scala index e1792032a1..bc1eb59a7c 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeFiniteSourceStage.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeFiniteSourceStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.stage import akka.Done diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeFlowStage.scala b/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeFlowStage.scala index 373c0ee3c8..3df0337808 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeFlowStage.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeFlowStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.stage import akka.stream._ diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeQueryGraphLogic.scala b/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeQueryGraphLogic.scala index 1ced1896dc..7dbcbe13fa 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeQueryGraphLogic.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeQueryGraphLogic.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.stage import akka.stream.SourceShape diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeSourceStageLogic.scala b/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeSourceStageLogic.scala index 9ab64e1ef9..138db7a3d5 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeSourceStageLogic.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/internal/stage/GeodeSourceStageLogic.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.stage import akka.stream.SourceShape diff --git a/geode/src/main/scala/akka/stream/alpakka/geode/scaladsl/ReactiveGeode.scala b/geode/src/main/scala/akka/stream/alpakka/geode/scaladsl/ReactiveGeode.scala index 0b8da425bc..8736870ed5 100644 --- a/geode/src/main/scala/akka/stream/alpakka/geode/scaladsl/ReactiveGeode.scala +++ b/geode/src/main/scala/akka/stream/alpakka/geode/scaladsl/ReactiveGeode.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.scaladsl import akka.stream.alpakka.geode.internal._ diff --git a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/Animal.java b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/Animal.java index 9667572473..bece05cede 100644 --- a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/Animal.java +++ b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/Animal.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.javadsl; public class Animal { diff --git a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/AnimalPdxSerializer.java b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/AnimalPdxSerializer.java index d977752641..694615f86e 100644 --- a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/AnimalPdxSerializer.java +++ b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/AnimalPdxSerializer.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.javadsl; import akka.stream.alpakka.geode.AkkaPdxSerializer; diff --git a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeBaseTestCase.java b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeBaseTestCase.java index c685e070e8..a362549c11 100644 --- a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeBaseTestCase.java +++ b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeBaseTestCase.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.javadsl; import akka.NotUsed; diff --git a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeContinuousSourceTestCase.java b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeContinuousSourceTestCase.java index 27f64352ba..7975aca276 100644 --- a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeContinuousSourceTestCase.java +++ b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeContinuousSourceTestCase.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.javadsl; import akka.Done; diff --git a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeFiniteSourceTestCase.java b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeFiniteSourceTestCase.java index 946e20a054..83f1f7025b 100644 --- a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeFiniteSourceTestCase.java +++ b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeFiniteSourceTestCase.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.javadsl; import akka.Done; diff --git a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeFlowTestCase.java b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeFlowTestCase.java index 1fff0a9bab..c5b2cfad92 100644 --- a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeFlowTestCase.java +++ b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeFlowTestCase.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.javadsl; import akka.NotUsed; diff --git a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeSinkTestCase.java b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeSinkTestCase.java index 9dcbdb9cbb..5151689876 100644 --- a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeSinkTestCase.java +++ b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/GeodeSinkTestCase.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.javadsl; import akka.Done; diff --git a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/Person.java b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/Person.java index a4853f0bb2..4b10cc9d88 100644 --- a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/Person.java +++ b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/Person.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.javadsl; import java.util.Date; diff --git a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/PersonPdxSerializer.java b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/PersonPdxSerializer.java index 82c1456f10..8f854859af 100644 --- a/geode/src/test/java/akka/stream/alpakka/geode/javadsl/PersonPdxSerializer.java +++ b/geode/src/test/java/akka/stream/alpakka/geode/javadsl/PersonPdxSerializer.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.javadsl; import akka.stream.alpakka.geode.AkkaPdxSerializer; diff --git a/geode/src/test/scala/akka/stream/alpakka/geode/internal/pdx/PDXDecoderSpec.scala b/geode/src/test/scala/akka/stream/alpakka/geode/internal/pdx/PDXDecoderSpec.scala index 19d1205bb6..5648718936 100644 --- a/geode/src/test/scala/akka/stream/alpakka/geode/internal/pdx/PDXDecoderSpec.scala +++ b/geode/src/test/scala/akka/stream/alpakka/geode/internal/pdx/PDXDecoderSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.pdx import java.util.{Date, UUID} diff --git a/geode/src/test/scala/akka/stream/alpakka/geode/internal/pdx/PDXEncodeSpec.scala b/geode/src/test/scala/akka/stream/alpakka/geode/internal/pdx/PDXEncodeSpec.scala index 02d73dd637..9f53c75789 100644 --- a/geode/src/test/scala/akka/stream/alpakka/geode/internal/pdx/PDXEncodeSpec.scala +++ b/geode/src/test/scala/akka/stream/alpakka/geode/internal/pdx/PDXEncodeSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.pdx import java.util.{Date, UUID} diff --git a/geode/src/test/scala/akka/stream/alpakka/geode/internal/pdx/PdxWriterMock.scala b/geode/src/test/scala/akka/stream/alpakka/geode/internal/pdx/PdxWriterMock.scala index b1e88ccaae..cfcdc2aa03 100644 --- a/geode/src/test/scala/akka/stream/alpakka/geode/internal/pdx/PdxWriterMock.scala +++ b/geode/src/test/scala/akka/stream/alpakka/geode/internal/pdx/PdxWriterMock.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.internal.pdx import java.util.Date diff --git a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeBaseSpec.scala b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeBaseSpec.scala index 3590bd0dc3..1a9c19ef60 100644 --- a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeBaseSpec.scala +++ b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeBaseSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.scaladsl import java.util.{Date, UUID} diff --git a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeContinuousSourceSpec.scala b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeContinuousSourceSpec.scala index 805133ea87..f9ebed1c6e 100644 --- a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeContinuousSourceSpec.scala +++ b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeContinuousSourceSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.scaladsl import akka.NotUsed diff --git a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeFiniteSourceSpec.scala b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeFiniteSourceSpec.scala index b192dfb2db..146a829b6e 100644 --- a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeFiniteSourceSpec.scala +++ b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeFiniteSourceSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.scaladsl import akka.stream.scaladsl.Sink diff --git a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeFlowSpec.scala b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeFlowSpec.scala index 2276431cd4..831b65cd21 100644 --- a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeFlowSpec.scala +++ b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeFlowSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.scaladsl import akka.NotUsed diff --git a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeSinkSpec.scala b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeSinkSpec.scala index ba2576d444..65aaaae04f 100644 --- a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeSinkSpec.scala +++ b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/GeodeSinkSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.scaladsl import scala.concurrent.Await diff --git a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/Model.scala b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/Model.scala index 2783095e55..f75f4fca34 100644 --- a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/Model.scala +++ b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/Model.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.scaladsl import java.util.{Date, UUID} diff --git a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/PersonPdxSerializer.scala b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/PersonPdxSerializer.scala index 9b2d3945f1..3e3949513a 100644 --- a/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/PersonPdxSerializer.scala +++ b/geode/src/test/scala/akka/stream/alpakka/geode/scaladsl/PersonPdxSerializer.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.geode.scaladsl import java.util.Date diff --git a/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/GooglePubSubSource.scala b/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/GooglePubSubSource.scala index 8b24d0ebd1..5a0ea6e17f 100644 --- a/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/GooglePubSubSource.scala +++ b/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/GooglePubSubSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.googlecloud.pubsub import akka.actor.ActorSystem diff --git a/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/HttpApi.scala b/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/HttpApi.scala index 79ff444840..c040cc22c5 100644 --- a/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/HttpApi.scala +++ b/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/HttpApi.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.googlecloud.pubsub import java.security.{PrivateKey, Signature} diff --git a/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/Model.scala b/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/Model.scala index aebe074850..96dd8c6956 100644 --- a/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/Model.scala +++ b/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/Model.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.googlecloud.pubsub import scala.collection.immutable diff --git a/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/Session.scala b/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/Session.scala index 90aff7add0..8882bf3c19 100644 --- a/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/Session.scala +++ b/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/Session.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.googlecloud.pubsub import java.security.PrivateKey diff --git a/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/javadsl/GooglePubSub.scala b/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/javadsl/GooglePubSub.scala index 19159adc79..4b60ad9864 100644 --- a/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/javadsl/GooglePubSub.scala +++ b/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/javadsl/GooglePubSub.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.googlecloud.pubsub.javadsl import java.security.PrivateKey diff --git a/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/scaladsl/GooglePubSub.scala b/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/scaladsl/GooglePubSub.scala index 38f9950446..56c69eb84d 100644 --- a/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/scaladsl/GooglePubSub.scala +++ b/google-cloud-pub-sub/src/main/scala/akka/stream/alpakka/googlecloud/pubsub/scaladsl/GooglePubSub.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.googlecloud.pubsub.scaladsl import java.security.PrivateKey diff --git a/google-cloud-pub-sub/src/test/java/akka/stream/alpakka/googlecloud/pubsub/ExampleUsageJava.java b/google-cloud-pub-sub/src/test/java/akka/stream/alpakka/googlecloud/pubsub/ExampleUsageJava.java index 2037f64004..bc58291ff1 100644 --- a/google-cloud-pub-sub/src/test/java/akka/stream/alpakka/googlecloud/pubsub/ExampleUsageJava.java +++ b/google-cloud-pub-sub/src/test/java/akka/stream/alpakka/googlecloud/pubsub/ExampleUsageJava.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.googlecloud.pubsub; import akka.Done; diff --git a/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/ExampleUsage.scala b/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/ExampleUsage.scala index 8561f04697..593c634bad 100644 --- a/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/ExampleUsage.scala +++ b/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/ExampleUsage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.googlecloud.pubsub import java.security.{KeyFactory, PrivateKey} diff --git a/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/GooglePubSubSpec.scala b/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/GooglePubSubSpec.scala index 1111d6dddc..124851e5d6 100644 --- a/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/GooglePubSubSpec.scala +++ b/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/GooglePubSubSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.googlecloud.pubsub import java.security.PrivateKey diff --git a/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/HttpApiSpec.scala b/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/HttpApiSpec.scala index cbe6883b9e..3442258058 100644 --- a/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/HttpApiSpec.scala +++ b/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/HttpApiSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.googlecloud.pubsub import java.security.KeyFactory diff --git a/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/SessionSpec.scala b/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/SessionSpec.scala index 3d1d839659..cf478188d0 100644 --- a/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/SessionSpec.scala +++ b/google-cloud-pub-sub/src/test/scala/akka/stream/alpakka/googlecloud/pubsub/SessionSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.googlecloud.pubsub import java.time.Instant diff --git a/hbase/src/main/scala/akka/stream/alpakka/hbase/HBaseSettings.scala b/hbase/src/main/scala/akka/stream/alpakka/hbase/HBaseSettings.scala index eebdfd799a..ce4970f7ca 100644 --- a/hbase/src/main/scala/akka/stream/alpakka/hbase/HBaseSettings.scala +++ b/hbase/src/main/scala/akka/stream/alpakka/hbase/HBaseSettings.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.hbase import org.apache.hadoop.conf.Configuration diff --git a/hbase/src/main/scala/akka/stream/alpakka/hbase/internal/HBaseCapabilities.scala b/hbase/src/main/scala/akka/stream/alpakka/hbase/internal/HBaseCapabilities.scala index da7c9b9227..b8d5e3317d 100644 --- a/hbase/src/main/scala/akka/stream/alpakka/hbase/internal/HBaseCapabilities.scala +++ b/hbase/src/main/scala/akka/stream/alpakka/hbase/internal/HBaseCapabilities.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.hbase.internal import java.io.Closeable diff --git a/hbase/src/main/scala/akka/stream/alpakka/hbase/internal/HBaseFlowStage.scala b/hbase/src/main/scala/akka/stream/alpakka/hbase/internal/HBaseFlowStage.scala index 150408b30a..e5de8b0e7d 100644 --- a/hbase/src/main/scala/akka/stream/alpakka/hbase/internal/HBaseFlowStage.scala +++ b/hbase/src/main/scala/akka/stream/alpakka/hbase/internal/HBaseFlowStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.hbase.internal import akka.stream._ diff --git a/hbase/src/main/scala/akka/stream/alpakka/hbase/javadsl/HTableStage.scala b/hbase/src/main/scala/akka/stream/alpakka/hbase/javadsl/HTableStage.scala index 6cc3933d36..64f35234aa 100644 --- a/hbase/src/main/scala/akka/stream/alpakka/hbase/javadsl/HTableStage.scala +++ b/hbase/src/main/scala/akka/stream/alpakka/hbase/javadsl/HTableStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.hbase.javadsl import akka.stream.alpakka.hbase.HTableSettings diff --git a/hbase/src/main/scala/akka/stream/alpakka/hbase/scaladsl/HTableStage.scala b/hbase/src/main/scala/akka/stream/alpakka/hbase/scaladsl/HTableStage.scala index 1fd653663b..093c383895 100644 --- a/hbase/src/main/scala/akka/stream/alpakka/hbase/scaladsl/HTableStage.scala +++ b/hbase/src/main/scala/akka/stream/alpakka/hbase/scaladsl/HTableStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.hbase.scaladsl import akka.stream.alpakka.hbase.HTableSettings diff --git a/hbase/src/test/java/akka/stream/alpakka/hbase/javadsl/HBaseStageTest.java b/hbase/src/test/java/akka/stream/alpakka/hbase/javadsl/HBaseStageTest.java index 540a1a3303..af4c94593d 100644 --- a/hbase/src/test/java/akka/stream/alpakka/hbase/javadsl/HBaseStageTest.java +++ b/hbase/src/test/java/akka/stream/alpakka/hbase/javadsl/HBaseStageTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.hbase.javadsl; import akka.Done; diff --git a/hbase/src/test/scala/akka/stream/alpakka/hbase/scaladsl/HBaseStageSpec.scala b/hbase/src/test/scala/akka/stream/alpakka/hbase/scaladsl/HBaseStageSpec.scala index e4c2252161..7cbd608d4c 100644 --- a/hbase/src/test/scala/akka/stream/alpakka/hbase/scaladsl/HBaseStageSpec.scala +++ b/hbase/src/test/scala/akka/stream/alpakka/hbase/scaladsl/HBaseStageSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.hbase.scaladsl import akka.actor.ActorSystem diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/Codec.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/Codec.scala index fa865e3ff9..52c7f25753 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/Codec.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/Codec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import io.circe.{Decoder, Encoder, Json} diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqClient.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqClient.scala index 77466c3a1a..5f8337d48f 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqClient.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqClient.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import akka.actor.ActorSystem diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqPullStage.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqPullStage.scala index 262fa09250..f994d20bb1 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqPullStage.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqPullStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import akka.Done diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqPushStage.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqPushStage.scala index ddd3067759..ba48db946d 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqPushStage.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqPushStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import akka.stream._ diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqSettings.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqSettings.scala index c024b777eb..97924f3355 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqSettings.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/IronMqSettings.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import akka.actor.ActorSystem diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/domain.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/domain.scala index d81e7c57c2..c4f875e09b 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/domain.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/domain.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import java.util.concurrent.TimeUnit diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/CommittableMessage.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/CommittableMessage.scala index 223cfd3c8f..6cdd05aafd 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/CommittableMessage.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/CommittableMessage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq.javadsl import java.util.concurrent.CompletionStage diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/IronMqConsumer.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/IronMqConsumer.scala index 5f2c6bc551..0003893e2a 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/IronMqConsumer.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/IronMqConsumer.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq.javadsl import akka.NotUsed diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/IronMqProducer.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/IronMqProducer.scala index 9a87dbd8e6..1f987491b4 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/IronMqProducer.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/IronMqProducer.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq.javadsl import java.util.concurrent.CompletionStage diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/package.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/package.scala index 37ec4aa59b..43581b6712 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/package.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/javadsl/package.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import java.util.concurrent.CompletionStage diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/package.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/package.scala index f8c01fb3ac..e62dab2591 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/package.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/package.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka import java.time.{Duration => JDuration} import java.util.concurrent.TimeUnit diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/scaladsl/CommittableMessage.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/scaladsl/CommittableMessage.scala index 4be31c1424..ac20bcd9a9 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/scaladsl/CommittableMessage.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/scaladsl/CommittableMessage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq.scaladsl import akka.Done diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqConsumer.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqConsumer.scala index 4dfc374549..463c75d07f 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqConsumer.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqConsumer.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq.scaladsl import akka.NotUsed diff --git a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqProducer.scala b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqProducer.scala index 76fd77891b..ccd881a945 100644 --- a/ironmq/src/main/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqProducer.scala +++ b/ironmq/src/main/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqProducer.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq.scaladsl import akka.{Done, NotUsed} diff --git a/ironmq/src/test/java/akka/stream/alpakka/ironmq/UnitTest.java b/ironmq/src/test/java/akka/stream/alpakka/ironmq/UnitTest.java index 6cbc1b3af8..9f741e1901 100644 --- a/ironmq/src/test/java/akka/stream/alpakka/ironmq/UnitTest.java +++ b/ironmq/src/test/java/akka/stream/alpakka/ironmq/UnitTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq; import akka.actor.ActorSystem; diff --git a/ironmq/src/test/java/akka/stream/alpakka/ironmq/javadsl/IronMqConsumerTest.java b/ironmq/src/test/java/akka/stream/alpakka/ironmq/javadsl/IronMqConsumerTest.java index d5994ffe92..6348e3b8c3 100644 --- a/ironmq/src/test/java/akka/stream/alpakka/ironmq/javadsl/IronMqConsumerTest.java +++ b/ironmq/src/test/java/akka/stream/alpakka/ironmq/javadsl/IronMqConsumerTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq.javadsl; import akka.NotUsed; diff --git a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/AkkaFixture.scala b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/AkkaFixture.scala index 9c6fb90dae..ff3d09baae 100644 --- a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/AkkaFixture.scala +++ b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/AkkaFixture.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import akka.actor.ActorSystem diff --git a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/AkkaStreamFixture.scala b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/AkkaStreamFixture.scala index 213dfcf17d..1e4238f9e7 100644 --- a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/AkkaStreamFixture.scala +++ b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/AkkaStreamFixture.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import akka.stream.{ActorMaterializer, Materializer} diff --git a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/ConfigFixture.scala b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/ConfigFixture.scala index 37bc5dac1c..df963238d1 100644 --- a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/ConfigFixture.scala +++ b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/ConfigFixture.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import com.typesafe.config.{Config, ConfigFactory} diff --git a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqClientSpec.scala b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqClientSpec.scala index 0f44fabdd5..66b82db9d2 100644 --- a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqClientSpec.scala +++ b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqClientSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import org.scalatest.concurrent.Eventually diff --git a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqFixture.scala b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqFixture.scala index c71d179100..e6cb820cdb 100644 --- a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqFixture.scala +++ b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqFixture.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import java.util.UUID diff --git a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqPullStageSpec.scala b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqPullStageSpec.scala index 84e5db700b..1e9db6b385 100644 --- a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqPullStageSpec.scala +++ b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqPullStageSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import akka.stream.scaladsl.{Sink, Source} diff --git a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqPushStageSpec.scala b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqPushStageSpec.scala index e5970662ec..302570f3b5 100644 --- a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqPushStageSpec.scala +++ b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/IronMqPushStageSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import akka.dispatch.ExecutionContexts diff --git a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/UnitSpec.scala b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/UnitSpec.scala index fd91595920..e8816e8c0d 100644 --- a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/UnitSpec.scala +++ b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/UnitSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq import org.scalatest.concurrent.PatienceConfiguration.{Interval, Timeout} diff --git a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqConsumerSpec.scala b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqConsumerSpec.scala index b8b4abf482..1716956683 100644 --- a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqConsumerSpec.scala +++ b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqConsumerSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq.scaladsl import akka.NotUsed diff --git a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqProducerSpec.scala b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqProducerSpec.scala index de6742d576..c039d7a198 100644 --- a/ironmq/src/test/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqProducerSpec.scala +++ b/ironmq/src/test/scala/akka/stream/alpakka/ironmq/scaladsl/IronMqProducerSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.ironmq.scaladsl import akka.dispatch.ExecutionContexts diff --git a/jms/src/main/scala/akka/stream/alpakka/jms/Jms.scala b/jms/src/main/scala/akka/stream/alpakka/jms/Jms.scala index 0e8ff9c20d..66125f9dea 100644 --- a/jms/src/main/scala/akka/stream/alpakka/jms/Jms.scala +++ b/jms/src/main/scala/akka/stream/alpakka/jms/Jms.scala @@ -1,17 +1,21 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.jms -import scala.collection.JavaConversions._ import java.util import java.time.Duration +import javax.jms import javax.jms.ConnectionFactory +import scala.collection.JavaConverters._ + sealed trait JmsSettings { def connectionFactory: ConnectionFactory def destination: Option[Destination] def credentials: Option[Credentials] + def acknowledgeMode: AcknowledgeMode } sealed trait Destination @@ -84,19 +88,28 @@ object JmsTextMessage { * Java API: create [[JmsTextMessage]] */ def create(body: String, headers: util.Set[JmsHeader]) = - JmsTextMessage(body = body, headers = headers.toSet, properties = Map.empty) + JmsTextMessage(body = body, headers = headers.asScala.toSet, properties = Map.empty) /** * Java API: create [[JmsTextMessage]] */ def create(body: String, properties: util.Map[String, Any]) = - JmsTextMessage(body = body, headers = Set.empty, properties = properties.toMap) + JmsTextMessage(body = body, headers = Set.empty, properties = properties.asScala.toMap) /** * Java API: create [[JmsTextMessage]] */ def create(body: String, headers: util.Set[JmsHeader], properties: util.Map[String, Any]) = - JmsTextMessage(body = body, headers = headers.toSet, properties = properties.toMap) + JmsTextMessage(body = body, headers = headers.asScala.toSet, properties = properties.asScala.toMap) +} + +final class AcknowledgeMode(val mode: Int) + +object AcknowledgeMode { + val AutoAcknowledge: AcknowledgeMode = new AcknowledgeMode(jms.Session.AUTO_ACKNOWLEDGE) + val ClientAcknowledge: AcknowledgeMode = new AcknowledgeMode(jms.Session.CLIENT_ACKNOWLEDGE) + val DupsOkAcknowledge: AcknowledgeMode = new AcknowledgeMode(jms.Session.DUPS_OK_ACKNOWLEDGE) + val SessionTransacted: AcknowledgeMode = new AcknowledgeMode(jms.Session.SESSION_TRANSACTED) } object JmsSourceSettings { @@ -109,13 +122,15 @@ final case class JmsSourceSettings(connectionFactory: ConnectionFactory, destination: Option[Destination] = None, credentials: Option[Credentials] = None, bufferSize: Int = 100, - selector: Option[String] = None) + selector: Option[String] = None, + acknowledgeMode: AcknowledgeMode = AcknowledgeMode.AutoAcknowledge) extends JmsSettings { def withCredential(credentials: Credentials) = copy(credentials = Some(credentials)) def withBufferSize(size: Int) = copy(bufferSize = size) def withQueue(name: String) = copy(destination = Some(Queue(name))) def withTopic(name: String) = copy(destination = Some(Topic(name))) def withSelector(selector: String) = copy(selector = Some(selector)) + def withAcknowledgeMode(acknowledgeMode: AcknowledgeMode) = copy(acknowledgeMode = acknowledgeMode) } object JmsSinkSettings { @@ -127,12 +142,14 @@ object JmsSinkSettings { final case class JmsSinkSettings(connectionFactory: ConnectionFactory, destination: Option[Destination] = None, credentials: Option[Credentials] = None, - timeToLive: Option[Duration] = None) + timeToLive: Option[Duration] = None, + acknowledgeMode: AcknowledgeMode = AcknowledgeMode.AutoAcknowledge) extends JmsSettings { def withCredential(credentials: Credentials) = copy(credentials = Some(credentials)) def withQueue(name: String) = copy(destination = Some(Queue(name))) def withTopic(name: String) = copy(destination = Some(Topic(name))) def withTimeToLive(ttl: Duration) = copy(timeToLive = Some(ttl)) + def withAcknowledgeMode(acknowledgeMode: AcknowledgeMode) = copy(acknowledgeMode = acknowledgeMode) } final case class Credentials(username: String, password: String) diff --git a/jms/src/main/scala/akka/stream/alpakka/jms/JmsConnector.scala b/jms/src/main/scala/akka/stream/alpakka/jms/JmsConnector.scala index fa698d7d7d..44fd5ddf0c 100644 --- a/jms/src/main/scala/akka/stream/alpakka/jms/JmsConnector.scala +++ b/jms/src/main/scala/akka/stream/alpakka/jms/JmsConnector.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.jms import javax.jms @@ -57,7 +58,7 @@ private[jms] trait JmsConnector { this: GraphStageLogic => fail.invoke(exception) }) connection.start() - val session = connection.createSession(false, jms.Session.CLIENT_ACKNOWLEDGE) + val session = connection.createSession(false, jmsSettings.acknowledgeMode.mode) val dest = jmsSettings.destination match { case Some(Queue(name)) => session.createQueue(name) case Some(Topic(name)) => session.createTopic(name) diff --git a/jms/src/main/scala/akka/stream/alpakka/jms/JmsSinkStage.scala b/jms/src/main/scala/akka/stream/alpakka/jms/JmsSinkStage.scala index f8fabca5b8..799c9e1d86 100644 --- a/jms/src/main/scala/akka/stream/alpakka/jms/JmsSinkStage.scala +++ b/jms/src/main/scala/akka/stream/alpakka/jms/JmsSinkStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.jms import javax.jms.{MessageProducer, TextMessage} diff --git a/jms/src/main/scala/akka/stream/alpakka/jms/JmsSourceStage.scala b/jms/src/main/scala/akka/stream/alpakka/jms/JmsSourceStage.scala index 26d6dac6b8..9eb7c3c617 100644 --- a/jms/src/main/scala/akka/stream/alpakka/jms/JmsSourceStage.scala +++ b/jms/src/main/scala/akka/stream/alpakka/jms/JmsSourceStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.jms import java.util.concurrent.Semaphore @@ -63,14 +64,7 @@ final class JmsSourceStage(settings: JmsSourceSettings) extends GraphStage[Sourc consumer.setMessageListener(new MessageListener { override def onMessage(message: Message): Unit = { backpressure.acquire() - try { - message.acknowledge() - handleMessage.invoke(message) - } catch { - case e: JMSException => - backpressure.release() - handleError.invoke(e) - } + handleMessage.invoke(message) } }) case Failure(e) => diff --git a/jms/src/main/scala/akka/stream/alpakka/jms/javadsl/JmsSink.scala b/jms/src/main/scala/akka/stream/alpakka/jms/javadsl/JmsSink.scala index 2355821f8a..9df608b5f0 100644 --- a/jms/src/main/scala/akka/stream/alpakka/jms/javadsl/JmsSink.scala +++ b/jms/src/main/scala/akka/stream/alpakka/jms/javadsl/JmsSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.jms.javadsl import akka.NotUsed diff --git a/jms/src/main/scala/akka/stream/alpakka/jms/javadsl/JmsSource.scala b/jms/src/main/scala/akka/stream/alpakka/jms/javadsl/JmsSource.scala index a2f111fbfb..4c64e66ae0 100644 --- a/jms/src/main/scala/akka/stream/alpakka/jms/javadsl/JmsSource.scala +++ b/jms/src/main/scala/akka/stream/alpakka/jms/javadsl/JmsSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.jms.javadsl import javax.jms.Message diff --git a/jms/src/main/scala/akka/stream/alpakka/jms/scaladsl/JmsSink.scala b/jms/src/main/scala/akka/stream/alpakka/jms/scaladsl/JmsSink.scala index e24e686204..7928396e30 100644 --- a/jms/src/main/scala/akka/stream/alpakka/jms/scaladsl/JmsSink.scala +++ b/jms/src/main/scala/akka/stream/alpakka/jms/scaladsl/JmsSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.jms.scaladsl import akka.NotUsed diff --git a/jms/src/main/scala/akka/stream/alpakka/jms/scaladsl/JmsSource.scala b/jms/src/main/scala/akka/stream/alpakka/jms/scaladsl/JmsSource.scala index 80c5b719d5..6ed2a78934 100644 --- a/jms/src/main/scala/akka/stream/alpakka/jms/scaladsl/JmsSource.scala +++ b/jms/src/main/scala/akka/stream/alpakka/jms/scaladsl/JmsSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.jms.scaladsl import javax.jms.{Message, TextMessage} diff --git a/jms/src/test/java/akka/stream/alpakka/jms/javadsl/JmsConnectorsTest.java b/jms/src/test/java/akka/stream/alpakka/jms/javadsl/JmsConnectorsTest.java index c8f5e2ef05..4406be1140 100644 --- a/jms/src/test/java/akka/stream/alpakka/jms/javadsl/JmsConnectorsTest.java +++ b/jms/src/test/java/akka/stream/alpakka/jms/javadsl/JmsConnectorsTest.java @@ -1,12 +1,14 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.jms.javadsl; import akka.NotUsed; import akka.actor.ActorSystem; import akka.stream.ActorMaterializer; import akka.stream.Materializer; +import akka.stream.alpakka.jms.AcknowledgeMode; import akka.stream.alpakka.jms.JmsCorrelationId; import akka.stream.alpakka.jms.JmsReplyTo; import akka.stream.alpakka.jms.JmsSinkSettings; @@ -20,6 +22,7 @@ import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.broker.BrokerService; import org.apache.activemq.command.ActiveMQQueue; +import org.apache.activemq.command.ActiveMQTextMessage; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -299,6 +302,51 @@ public void publishAndConsumeTopic() throws Exception { }); } + @Test + public void publishAndConsumeJmsTextMessagesWithClientAcknowledgement() throws Exception { + withServer(ctx -> { + ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ctx.url); + + Sink jmsSink = JmsSink.create( + JmsSinkSettings + .create(connectionFactory) + .withQueue("test") + ); + List intsIn = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + List msgsIn = new ArrayList<>(); + for(Integer n: intsIn) { + msgsIn.add(JmsTextMessage.create(n.toString())); + } + + Source.from(msgsIn).runWith(jmsSink, materializer); + + //#create-jms-source-client-ack + Source jmsSource = JmsSource.create(JmsSourceSettings + .create(connectionFactory) + .withQueue("test") + .withAcknowledgeMode(AcknowledgeMode.ClientAcknowledge()) + ); + //#create-jms-source-client-ack + + //#run-jms-source-with-ack + CompletionStage> result = jmsSource + .take(msgsIn.size()) + .map(message -> { + String text = ((ActiveMQTextMessage)message).getText(); + message.acknowledge(); + return text; + }) + .runWith(Sink.seq(), materializer); + //#run-jms-source-with-ack + + List outMessages = result.toCompletableFuture().get(3, TimeUnit.SECONDS); + int msgIdx = 0; + for(String outMsg: outMessages) { + assertEquals(outMsg, msgsIn.get(msgIdx).body()); + msgIdx++; + } + }); + } private static ActorSystem system; private static Materializer materializer; diff --git a/jms/src/test/scala/akka/stream/alpakka/jms/JmsSpec.scala b/jms/src/test/scala/akka/stream/alpakka/jms/JmsSpec.scala index b9811ee204..7e41891a20 100644 --- a/jms/src/test/scala/akka/stream/alpakka/jms/JmsSpec.scala +++ b/jms/src/test/scala/akka/stream/alpakka/jms/JmsSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.jms import akka.actor.ActorSystem diff --git a/jms/src/test/scala/akka/stream/alpakka/jms/scaladsl/JmsConnectorsSpec.scala b/jms/src/test/scala/akka/stream/alpakka/jms/scaladsl/JmsConnectorsSpec.scala index b881e625c5..87ffcedab0 100644 --- a/jms/src/test/scala/akka/stream/alpakka/jms/scaladsl/JmsConnectorsSpec.scala +++ b/jms/src/test/scala/akka/stream/alpakka/jms/scaladsl/JmsConnectorsSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.jms.scaladsl import javax.jms.{JMSException, Message, TextMessage} @@ -8,11 +9,10 @@ import javax.jms.{JMSException, Message, TextMessage} import akka.NotUsed import akka.stream.ThrottleMode import akka.stream.alpakka.jms._ -import akka.stream.scaladsl.{Flow, Sink, Source} +import akka.stream.scaladsl.{Sink, Source} import org.apache.activemq.ActiveMQConnectionFactory import scala.concurrent.duration._ -import collection.JavaConverters._ class JmsConnectorsSpec extends JmsSpec { @@ -188,5 +188,85 @@ class JmsConnectorsSpec extends JmsSpec { result2.futureValue shouldEqual expectedList.sorted } + "publish and consume JMS text messages through a queue with client ack" in withServer() { ctx => + val url: String = ctx.url + val connectionFactory = new ActiveMQConnectionFactory(url) + + val jmsSink: Sink[JmsTextMessage, NotUsed] = JmsSink( + JmsSinkSettings(connectionFactory).withQueue("numbers") + ) + + val msgsIn = (1 to 10).toList.map { n => + JmsTextMessage(n.toString) + } + + Source(msgsIn).runWith(jmsSink) + + //#create-jms-source-client-ack + val jmsSource: Source[Message, NotUsed] = JmsSource( + JmsSourceSettings(connectionFactory) + .withQueue("numbers") + .withAcknowledgeMode(AcknowledgeMode.ClientAcknowledge) + ) + //#create-jms-source-client-ack + + //#run-jms-source-with-ack + val result = jmsSource + .take(msgsIn.size) + .map { + case textMessage: TextMessage => + val text = textMessage.getText + textMessage.acknowledge() + text + } + .runWith(Sink.seq) + //#run-jms-source-with-ack + + result.futureValue shouldEqual msgsIn.map(_.body) + + // all messages were acknowledged before + jmsSource + .takeWithin(5.seconds) + .runWith(Sink.seq) + .futureValue shouldBe empty + } + + "publish and consume JMS text messages through a queue without acknowledgingg them" in withServer() { ctx => + val url: String = ctx.url + val connectionFactory = new ActiveMQConnectionFactory(url) + + val jmsSink: Sink[JmsTextMessage, NotUsed] = JmsSink( + JmsSinkSettings(connectionFactory).withQueue("numbers") + ) + + val msgsIn = (1 to 10).toList.map { n => + JmsTextMessage(n.toString) + } + + Source(msgsIn).runWith(jmsSink) + + val jmsSource: Source[Message, NotUsed] = JmsSource( + JmsSourceSettings(connectionFactory) + .withBufferSize(10) + .withQueue("numbers") + .withAcknowledgeMode(AcknowledgeMode.ClientAcknowledge) + ) + + val result = jmsSource + .take(msgsIn.size) + .map { + case textMessage: TextMessage => + textMessage.getText + } + .runWith(Sink.seq) + + result.futureValue shouldEqual msgsIn.map(_.body) + + // messages were not acknowledged, may be delivered again + jmsSource + .takeWithin(5.seconds) + .runWith(Sink.seq) + .futureValue should not be empty + } } } diff --git a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisErrors.scala b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisErrors.scala new file mode 100644 index 0000000000..4c9a4ae07d --- /dev/null +++ b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisErrors.scala @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.kinesis + +import com.amazonaws.services.kinesis.model.PutRecordsResultEntry + +import scala.util.control.NoStackTrace + +object KinesisErrors { + + sealed trait KinesisSourceError extends NoStackTrace + case object NoShardsError extends KinesisSourceError + case object GetShardIteratorError extends KinesisSourceError + case object GetRecordsError extends KinesisSourceError + + sealed trait KinesisFlowErrors extends NoStackTrace + case class FailurePublishingRecords(e: Exception) extends RuntimeException(e) with KinesisFlowErrors + case class ErrorPublishingRecords(attempts: Int, records: Seq[PutRecordsResultEntry]) + extends RuntimeException(s"Unable to publish records after $attempts attempts") + with KinesisFlowErrors + +} diff --git a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisFlowSettings.scala b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisFlowSettings.scala new file mode 100644 index 0000000000..e456a37ed2 --- /dev/null +++ b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisFlowSettings.scala @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.kinesis + +import KinesisFlowSettings._ +import scala.concurrent.duration.FiniteDuration +import scala.concurrent.duration._ +import scala.language.postfixOps + +case class KinesisFlowSettings(parallelism: Int, + maxBatchSize: Int, + maxRecordsPerSecond: Int, + maxBytesPerSecond: Int, + maxRetries: Int, + backoffStrategy: RetryBackoffStrategy, + retryInitialTimeout: FiniteDuration) { + require( + maxBatchSize >= 1 && maxBatchSize <= 500, + "Limit must be between 1 and 500. See: http://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecords.html" + ) + require(maxRecordsPerSecond >= 1) + require(maxBytesPerSecond >= 1) + require(maxRetries >= 0) +} + +object KinesisFlowSettings { + + private val MAX_RECORDS_PER_REQUEST = 500 + private val MAX_RECORDS_PER_SHARD_PER_SECOND = 1000 + private val MAX_BYTES_PER_SHARD_PER_SECOND = 1000000 + + sealed trait RetryBackoffStrategy + case object Exponential extends RetryBackoffStrategy + case object Lineal extends RetryBackoffStrategy + + val exponential = Exponential + val lineal = Lineal + + val defaultInstance = byNumberOfShards(1) + + def byNumberOfShards(shards: Int): KinesisFlowSettings = + KinesisFlowSettings( + parallelism = shards * (MAX_RECORDS_PER_SHARD_PER_SECOND / MAX_RECORDS_PER_REQUEST), + maxBatchSize = MAX_RECORDS_PER_REQUEST, + maxRecordsPerSecond = shards * MAX_BYTES_PER_SHARD_PER_SECOND, + maxBytesPerSecond = shards * MAX_RECORDS_PER_SHARD_PER_SECOND, + maxRetries = 5, + backoffStrategy = Exponential, + retryInitialTimeout = 100 millis + ) +} diff --git a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisFlowStage.scala b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisFlowStage.scala new file mode 100644 index 0000000000..c1d58f286e --- /dev/null +++ b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisFlowStage.scala @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.kinesis + +import akka.stream.alpakka.kinesis.KinesisErrors.{ErrorPublishingRecords, FailurePublishingRecords} +import akka.stream.alpakka.kinesis.KinesisFlowSettings.{Exponential, Lineal, RetryBackoffStrategy} +import akka.stream.alpakka.kinesis.KinesisFlowStage._ +import akka.stream.stage._ +import akka.stream.{Attributes, FlowShape, Inlet, Outlet} +import com.amazonaws.handlers.AsyncHandler +import com.amazonaws.services.kinesis.AmazonKinesisAsync +import com.amazonaws.services.kinesis.model.{ + PutRecordsRequest, + PutRecordsRequestEntry, + PutRecordsResult, + PutRecordsResultEntry +} + +import scala.collection.JavaConverters._ +import scala.collection.mutable +import scala.concurrent.duration.FiniteDuration +import scala.concurrent.duration._ +import scala.concurrent.{Future, Promise} +import scala.util.{Failure, Success, Try} + +import scala.language.postfixOps + +private[kinesis] final class KinesisFlowStage( + streamName: String, + maxRetries: Int, + backoffStrategy: RetryBackoffStrategy, + retryInitialTimeout: FiniteDuration +)(implicit kinesisClient: AmazonKinesisAsync) + extends GraphStage[FlowShape[Seq[PutRecordsRequestEntry], Future[PutRecordsResult]]] { + + private val in = Inlet[Seq[PutRecordsRequestEntry]]("KinesisFlowStage.in") + private val out = Outlet[Future[PutRecordsResult]]("KinesisFlowStage.out") + override val shape = FlowShape(in, out) + + override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = + new TimerGraphStageLogic(shape) with StageLogging with InHandler with OutHandler { + + type Token = Int + type RetryCount = Int + + private val retryBaseInMillis = retryInitialTimeout.toMillis + + private var completionState: Option[Try[Unit]] = _ + + private val pendingRequests: mutable.Queue[Job] = mutable.Queue.empty + private var resultCallback: AsyncCallback[Result] = _ + private var inFlight: Int = _ + + private val waitingRetries: mutable.HashMap[Token, Job] = mutable.HashMap.empty + private var retryToken: Token = _ + + private def tryToExecute() = + if (pendingRequests.nonEmpty && isAvailable(out)) { + log.debug("Executing PutRecords call") + inFlight += 1 + val job = pendingRequests.dequeue() + push( + out, + putRecords( + streamName, + job.records, + recordsToRetry => resultCallback.invoke(Result(job.attempt, recordsToRetry)) + ) + ) + } + + private def handleResult(result: Result): Unit = result match { + case Result(_, Nil) => + log.debug("PutRecords call finished successfully") + inFlight -= 1 + tryToExecute() + if (!hasBeenPulled(in)) tryPull(in) + checkForCompletion() + case Result(attempt, errors) if attempt > maxRetries => + log.debug("PutRecords call finished with partial errors after {} attempts", attempt) + failStage(ErrorPublishingRecords(attempt, errors.map(_._1))) + case Result(attempt, errors) => + log.debug("PutRecords call finished with partial errors; scheduling retry") + inFlight -= 1 + waitingRetries.put(retryToken, Job(attempt + 1, errors.map(_._2))) + scheduleOnce(retryToken, backoffStrategy match { + case Exponential => scala.math.pow(retryBaseInMillis, attempt).toInt millis + case Lineal => retryInitialTimeout * attempt + }) + retryToken += 1 + } + + private def checkForCompletion() = + if (inFlight == 0 && pendingRequests.isEmpty && waitingRetries.isEmpty && isClosed(in)) { + completionState match { + case Some(Success(_)) => completeStage() + case Some(Failure(ex)) => failStage(ex) + case None => failStage(new IllegalStateException("Stage completed, but there is no info about status")) + } + } + + override protected def onTimer(timerKey: Any) = + waitingRetries.remove(timerKey.asInstanceOf[Token]) foreach { job => + log.debug("New PutRecords retry attempt available") + pendingRequests.enqueue(job) + tryToExecute() + } + + override def preStart() = { + completionState = None + inFlight = 0 + retryToken = 0 + resultCallback = getAsyncCallback[Result](handleResult) + pull(in) + } + + override def postStop(): Unit = { + pendingRequests.clear() + waitingRetries.clear() + } + + override def onUpstreamFinish(): Unit = { + completionState = Some(Success(())) + checkForCompletion() + } + + override def onUpstreamFailure(ex: Throwable): Unit = { + completionState = Some(Failure(ex)) + checkForCompletion() + } + + override def onPull(): Unit = { + tryToExecute() + if (waitingRetries.isEmpty && !hasBeenPulled(in)) tryPull(in) + } + + override def onPush(): Unit = { + log.debug("New PutRecords request available") + pendingRequests.enqueue(Job(1, grab(in))) + tryToExecute() + } + + setHandlers(in, out, this) + } + +} + +object KinesisFlowStage { + + private def putRecords( + streamName: String, + recordEntries: Seq[PutRecordsRequestEntry], + retryRecordsCallback: Seq[(PutRecordsResultEntry, PutRecordsRequestEntry)] => Unit + )(implicit kinesisClient: AmazonKinesisAsync): Future[PutRecordsResult] = { + + val p = Promise[PutRecordsResult] + + kinesisClient + .putRecordsAsync( + new PutRecordsRequest() + .withStreamName(streamName) + .withRecords(recordEntries.asJavaCollection), + new AsyncHandler[PutRecordsRequest, PutRecordsResult] { + + override def onError(exception: Exception): Unit = + p.failure(FailurePublishingRecords(exception)) + + override def onSuccess(request: PutRecordsRequest, result: PutRecordsResult): Unit = { + if (result.getFailedRecordCount > 0) { + retryRecordsCallback( + result.getRecords.asScala + .zip(request.getRecords.asScala) + .filter(_._1.getErrorCode != null) + ) + } else { + retryRecordsCallback(Nil) + } + p.success(result) + } + } + ) + + p.future + } + + private case class Result(attempt: Int, recordsToRetry: Seq[(PutRecordsResultEntry, PutRecordsRequestEntry)]) + private case class Job(attempt: Int, records: Seq[PutRecordsRequestEntry]) + +} diff --git a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisSourceErrors.scala b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisSourceErrors.scala deleted file mode 100644 index 94ba1b9556..0000000000 --- a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisSourceErrors.scala +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (C) 2016-2017 Lightbend Inc. - */ -package akka.stream.alpakka.kinesis - -import scala.util.control.NoStackTrace - -object KinesisSourceErrors { - sealed trait KinesisSourceError extends NoStackTrace - case object NoShardsError extends KinesisSourceError - case object GetShardIteratorError extends KinesisSourceError - case object GetRecordsError extends KinesisSourceError -} diff --git a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisSourceStage.scala b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisSourceStage.scala index 266711dda2..bccb7757b1 100644 --- a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisSourceStage.scala +++ b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/KinesisSourceStage.scala @@ -1,13 +1,14 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.kinesis import java.util.concurrent.Future import akka.actor.ActorRef import akka.stream.alpakka.kinesis.KinesisSourceStage._ -import akka.stream.alpakka.kinesis.{KinesisSourceErrors => Errors} +import akka.stream.alpakka.kinesis.{KinesisErrors => Errors} import akka.stream.stage.GraphStageLogic.StageActor import akka.stream.stage._ import akka.stream.{Attributes, Outlet, SourceShape} diff --git a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/ShardSettings.scala b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/ShardSettings.scala index 6617bff34f..d8b8f487d0 100644 --- a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/ShardSettings.scala +++ b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/ShardSettings.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.kinesis import java.util.Date diff --git a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/javadsl/KinesisFlow.scala b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/javadsl/KinesisFlow.scala new file mode 100644 index 0000000000..b4977bce0e --- /dev/null +++ b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/javadsl/KinesisFlow.scala @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.kinesis.javadsl + +import akka.NotUsed +import akka.stream.alpakka.kinesis.{scaladsl, KinesisFlowSettings} +import akka.stream.javadsl.Flow +import com.amazonaws.services.kinesis.AmazonKinesisAsync +import com.amazonaws.services.kinesis.model.{PutRecordsRequestEntry, PutRecordsResultEntry} + +object KinesisFlow { + + def apply(streamName: String, + kinesisClient: AmazonKinesisAsync): Flow[PutRecordsRequestEntry, PutRecordsResultEntry, NotUsed] = + apply(streamName, KinesisFlowSettings.defaultInstance, kinesisClient) + + def apply(streamName: String, + settings: KinesisFlowSettings, + kinesisClient: AmazonKinesisAsync): Flow[PutRecordsRequestEntry, PutRecordsResultEntry, NotUsed] = + (scaladsl.KinesisFlow.apply(streamName, settings)(kinesisClient)).asJava + +} diff --git a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/javadsl/KinesisSink.scala b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/javadsl/KinesisSink.scala new file mode 100644 index 0000000000..c2938b2bc7 --- /dev/null +++ b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/javadsl/KinesisSink.scala @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.kinesis.javadsl + +import akka.NotUsed +import akka.stream.alpakka.kinesis.{scaladsl, KinesisFlowSettings} +import akka.stream.javadsl.Sink +import com.amazonaws.services.kinesis.AmazonKinesisAsync +import com.amazonaws.services.kinesis.model.PutRecordsRequestEntry + +object KinesisSink { + + def apply(streamName: String, kinesisClient: AmazonKinesisAsync): Sink[PutRecordsRequestEntry, NotUsed] = + apply(streamName, KinesisFlowSettings.defaultInstance, kinesisClient) + + def apply(streamName: String, + settings: KinesisFlowSettings, + kinesisClient: AmazonKinesisAsync): Sink[PutRecordsRequestEntry, NotUsed] = + (scaladsl.KinesisSink.apply(streamName, settings)(kinesisClient)).asJava + +} diff --git a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/javadsl/KinesisSource.scala b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/javadsl/KinesisSource.scala index fbf1d221a5..bbd931f820 100644 --- a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/javadsl/KinesisSource.scala +++ b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/javadsl/KinesisSource.scala @@ -1,15 +1,14 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ -package akka.stream.alpakka.kinesis.javadsl -import java.util.concurrent.Future +package akka.stream.alpakka.kinesis.javadsl import akka.NotUsed import akka.stream.alpakka.kinesis.{scaladsl, ShardSettings} import akka.stream.javadsl.Source import com.amazonaws.services.kinesis.AmazonKinesisAsync -import com.amazonaws.services.kinesis.model.{DescribeStreamResult, Record} +import com.amazonaws.services.kinesis.model.Record import scala.collection.JavaConverters._ diff --git a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/scaladsl/KinesisFlow.scala b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/scaladsl/KinesisFlow.scala new file mode 100644 index 0000000000..d98e2033c6 --- /dev/null +++ b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/scaladsl/KinesisFlow.scala @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.kinesis.scaladsl + +import java.nio.ByteBuffer + +import akka.NotUsed +import akka.stream.ThrottleMode +import akka.stream.alpakka.kinesis.{KinesisFlowSettings, KinesisFlowStage} +import akka.stream.scaladsl.Flow +import akka.util.ByteString +import com.amazonaws.services.kinesis.AmazonKinesisAsync +import com.amazonaws.services.kinesis.model.{PutRecordsRequestEntry, PutRecordsResultEntry} + +import scala.collection.immutable.Queue +import scala.collection.JavaConverters._ +import scala.collection.immutable +import scala.concurrent.duration._ +import scala.language.postfixOps + +object KinesisFlow { + + def apply(streamName: String, settings: KinesisFlowSettings = KinesisFlowSettings.defaultInstance)( + implicit kinesisClient: AmazonKinesisAsync + ): Flow[PutRecordsRequestEntry, PutRecordsResultEntry, NotUsed] = + Flow[PutRecordsRequestEntry] + .throttle(settings.maxRecordsPerSecond, 1 second, settings.maxRecordsPerSecond, ThrottleMode.Shaping) + .throttle(settings.maxBytesPerSecond, 1 second, settings.maxBytesPerSecond, getByteSize, ThrottleMode.Shaping) + .batch(settings.maxBatchSize, Queue(_))(_ :+ _) + .via( + new KinesisFlowStage( + streamName, + settings.maxRetries, + settings.backoffStrategy, + settings.retryInitialTimeout + ) + ) + .mapAsync(settings.parallelism)(identity) + .mapConcat(_.getRecords.asScala.to[immutable.Iterable]) + .filter(_.getErrorCode == null) + + private def getByteSize(record: PutRecordsRequestEntry): Int = + record.getPartitionKey.length + record.getData.position + + def byPartitionAndData( + streamName: String, + settings: KinesisFlowSettings = KinesisFlowSettings.defaultInstance + )( + implicit kinesisClient: AmazonKinesisAsync + ): Flow[(String, ByteBuffer), PutRecordsResultEntry, NotUsed] = + Flow[(String, ByteBuffer)] + .map { + case (partitionKey, data) => + new PutRecordsRequestEntry() + .withPartitionKey(partitionKey) + .withData(data) + } + .via(apply(streamName, settings)) + + def byParititonAndBytes( + streamName: String, + settings: KinesisFlowSettings = KinesisFlowSettings.defaultInstance + )( + implicit kinesisClient: AmazonKinesisAsync + ): Flow[(String, ByteString), PutRecordsResultEntry, NotUsed] = + Flow[(String, ByteString)] + .map { + case (partitionKey, bytes) => + partitionKey -> bytes.toByteBuffer + } + .via(byPartitionAndData(streamName, settings)) + +} diff --git a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/scaladsl/KinesisSink.scala b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/scaladsl/KinesisSink.scala new file mode 100644 index 0000000000..0d67b059b4 --- /dev/null +++ b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/scaladsl/KinesisSink.scala @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.kinesis.scaladsl + +import java.nio.ByteBuffer + +import akka.NotUsed +import akka.stream.alpakka.kinesis.KinesisFlowSettings +import akka.stream.scaladsl.Sink +import akka.util.ByteString +import com.amazonaws.services.kinesis.AmazonKinesisAsync +import com.amazonaws.services.kinesis.model.PutRecordsRequestEntry + +object KinesisSink { + + def apply(streamName: String, settings: KinesisFlowSettings = KinesisFlowSettings.defaultInstance)( + implicit kinesisClient: AmazonKinesisAsync + ): Sink[PutRecordsRequestEntry, NotUsed] = + KinesisFlow(streamName, settings).to(Sink.ignore) + + def byPartitionAndData( + streamName: String, + settings: KinesisFlowSettings = KinesisFlowSettings.defaultInstance + )( + implicit kinesisClient: AmazonKinesisAsync + ): Sink[(String, ByteBuffer), NotUsed] = + KinesisFlow.byPartitionAndData(streamName, settings).to(Sink.ignore) + + def byParititonAndBytes( + streamName: String, + settings: KinesisFlowSettings = KinesisFlowSettings.defaultInstance + )( + implicit kinesisClient: AmazonKinesisAsync + ): Sink[(String, ByteString), NotUsed] = + KinesisFlow.byParititonAndBytes(streamName, settings).to(Sink.ignore) + +} diff --git a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/scaladsl/KinesisSource.scala b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/scaladsl/KinesisSource.scala index 2161708e18..c50a4652f4 100644 --- a/kinesis/src/main/scala/akka/stream/alpakka/kinesis/scaladsl/KinesisSource.scala +++ b/kinesis/src/main/scala/akka/stream/alpakka/kinesis/scaladsl/KinesisSource.scala @@ -1,10 +1,11 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.kinesis.scaladsl import akka.NotUsed -import akka.stream.alpakka.kinesis.KinesisSourceErrors.NoShardsError +import akka.stream.alpakka.kinesis.KinesisErrors.NoShardsError import akka.stream.alpakka.kinesis.{KinesisSourceStage, ShardSettings} import akka.stream.scaladsl.{Merge, Source} import com.amazonaws.services.kinesis.AmazonKinesisAsync diff --git a/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/ExampleSpec.java b/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/ExampleSpec.java index e09d3226fd..1de135d49e 100644 --- a/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/ExampleSpec.java +++ b/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/ExampleSpec.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.kinesis.javadsl; import akka.NotUsed; diff --git a/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/Examples.java b/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/Examples.java index e06a1a1eac..3e83f7e789 100644 --- a/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/Examples.java +++ b/kinesis/src/test/java/akka/stream/alpakka/kinesis/javadsl/Examples.java @@ -1,15 +1,21 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.kinesis.javadsl; import akka.NotUsed; import akka.actor.ActorSystem; import akka.stream.ActorMaterializer; +import akka.stream.alpakka.kinesis.KinesisFlowSettings; import akka.stream.alpakka.kinesis.ShardSettings; +import akka.stream.javadsl.Flow; +import akka.stream.javadsl.Sink; import akka.stream.javadsl.Source; import com.amazonaws.services.kinesis.AmazonKinesisAsync; import com.amazonaws.services.kinesis.AmazonKinesisAsyncClientBuilder; +import com.amazonaws.services.kinesis.model.PutRecordsRequestEntry; +import com.amazonaws.services.kinesis.model.PutRecordsResultEntry; import com.amazonaws.services.kinesis.model.Record; import com.amazonaws.services.kinesis.model.ShardIteratorType; import scala.concurrent.duration.FiniteDuration; @@ -28,16 +34,32 @@ public class Examples { final ActorMaterializer materializer = ActorMaterializer.create(system); //#init-system - //#settings + //#source-settings final ShardSettings settings = ShardSettings.create("streamName", "shard-id", ShardIteratorType.LATEST, FiniteDuration.apply(1L, TimeUnit.SECONDS), 500); - //#settings + //#source-settings - //#single + //#source-single final Source single = KinesisSource.basic(settings, amazonKinesisAsync); - //#single + //#source-single - //#list + //#source-list final Source two = KinesisSource.basicMerge(Arrays.asList(settings), amazonKinesisAsync); - //#list + //#source-list + + //#flow-settings + final KinesisFlowSettings flowSettings = KinesisFlowSettings.apply(1,500,1000,1000000,5, KinesisFlowSettings.exponential(), FiniteDuration.apply(100, TimeUnit.MILLISECONDS)); + + final KinesisFlowSettings defaultFlowSettings = KinesisFlowSettings.defaultInstance(); + + final KinesisFlowSettings fourShardFlowSettings = KinesisFlowSettings.byNumberOfShards(4); + //#flow-settings + + //#flow-sink + final Flow flow = KinesisFlow.apply("streamName", flowSettings, amazonKinesisAsync); + final Flow defaultSettingsFlow = KinesisFlow.apply("streamName", amazonKinesisAsync); + + final Sink sink = KinesisSink.apply("streamName", flowSettings, amazonKinesisAsync); + final Sink defaultSettingsSink = KinesisSink.apply("streamName", amazonKinesisAsync); + //#flow-sink } diff --git a/kinesis/src/test/scala/akka/stream/alpakka/kinesis/DefaultTestContext.scala b/kinesis/src/test/scala/akka/stream/alpakka/kinesis/DefaultTestContext.scala index 1d6bd295f0..b4f65402b1 100644 --- a/kinesis/src/test/scala/akka/stream/alpakka/kinesis/DefaultTestContext.scala +++ b/kinesis/src/test/scala/akka/stream/alpakka/kinesis/DefaultTestContext.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.kinesis import akka.actor.ActorSystem diff --git a/kinesis/src/test/scala/akka/stream/alpakka/kinesis/KinesisFlowSpec.scala b/kinesis/src/test/scala/akka/stream/alpakka/kinesis/KinesisFlowSpec.scala new file mode 100644 index 0000000000..10541e641f --- /dev/null +++ b/kinesis/src/test/scala/akka/stream/alpakka/kinesis/KinesisFlowSpec.scala @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.kinesis + +import java.util.concurrent.CompletableFuture + +import akka.stream.alpakka.kinesis.KinesisErrors.{ErrorPublishingRecords, FailurePublishingRecords} +import akka.stream.alpakka.kinesis.scaladsl.KinesisFlow +import akka.stream.scaladsl.Keep +import akka.stream.testkit.scaladsl.{TestSink, TestSource} +import akka.util.ByteString +import com.amazonaws.handlers.AsyncHandler +import com.amazonaws.services.kinesis.model._ +import org.mockito.ArgumentMatchers.any +import org.mockito.Mockito.when +import org.mockito.invocation.InvocationOnMock +import org.mockito.stubbing.Answer +import org.scalatest.{Matchers, WordSpecLike} + +import scala.collection.JavaConverters._ + +class KinesisFlowSpec extends WordSpecLike with Matchers with DefaultTestContext { + + "KinesisFlow" must { + + "publish records" in new DefaultSettings with KinesisFlowProbe with WithPutRecordsSuccess { + sourceProbe.sendNext(record) + sourceProbe.sendNext(record) + sourceProbe.sendNext(record) + sourceProbe.sendNext(record) + sourceProbe.sendNext(record) + + sinkProbe.requestNext() shouldBe publishedRecord + sinkProbe.requestNext() shouldBe publishedRecord + sinkProbe.requestNext() shouldBe publishedRecord + sinkProbe.requestNext() shouldBe publishedRecord + sinkProbe.requestNext() shouldBe publishedRecord + + sourceProbe.sendComplete() + sinkProbe.expectComplete() + } + "publish records with retries" in new DefaultSettings with KinesisFlowProbe { + when(amazonKinesisAsync.putRecordsAsync(any(), any())) + .thenAnswer(new Answer[AnyRef] { + override def answer(invocation: InvocationOnMock) = { + val request = invocation + .getArgument[PutRecordsRequest](0) + val result = new PutRecordsResult() + .withFailedRecordCount(request.getRecords.size()) + .withRecords( + request.getRecords.asScala + .map(_ => failingRecord) + .asJava + ) + invocation + .getArgument[AsyncHandler[PutRecordsRequest, PutRecordsResult]](1) + .onSuccess(request, result) + CompletableFuture.completedFuture(result) + } + }) + .thenAnswer(new Answer[AnyRef] { + override def answer(invocation: InvocationOnMock) = { + val request = invocation + .getArgument[PutRecordsRequest](0) + val result = new PutRecordsResult() + .withFailedRecordCount(0) + .withRecords(request.getRecords.asScala.map(_ => publishedRecord).asJava) + invocation + .getArgument[AsyncHandler[PutRecordsRequest, PutRecordsResult]](1) + .onSuccess(request, result) + CompletableFuture.completedFuture(result) + } + }) + + sourceProbe.sendNext(record) + + sinkProbe.requestNext(settings.retryInitialTimeout * 2) shouldBe publishedRecord + + sourceProbe.sendComplete() + sinkProbe.expectComplete() + } + "fail after trying to publish records with no retires" in new NoRetries with KinesisFlowProbe + with WithPutRecordsWithPartialErrors { + sourceProbe.sendNext(record) + + sinkProbe.request(1) + sinkProbe.expectError(ErrorPublishingRecords(1, Seq(failingRecord))) + } + "fail after trying to publish records with several retries" in new DefaultSettings with KinesisFlowProbe + with WithPutRecordsWithPartialErrors { + sourceProbe.sendNext(record) + + sinkProbe.request(1) + sinkProbe.expectError(ErrorPublishingRecords(settings.maxRetries + 1, Seq(failingRecord))) + } + "fails when request returns an error" in new DefaultSettings with KinesisFlowProbe with WithPutRecordsFailure { + sourceProbe.sendNext(record) + + sinkProbe.request(1) + sinkProbe.expectError(FailurePublishingRecords(requestError)) + } + } + + sealed trait Settings { + val settings: KinesisFlowSettings + } + trait DefaultSettings extends Settings { + val settings = KinesisFlowSettings.defaultInstance.copy(maxRetries = 1) + } + trait NoRetries extends Settings { + val settings = KinesisFlowSettings.defaultInstance.copy(maxRetries = 0) + } + + trait KinesisFlowProbe { self: Settings => + val streamName = "stream-name" + val record = + new PutRecordsRequestEntry().withPartitionKey("partition-key").withData(ByteString("data").asByteBuffer) + val publishedRecord = new PutRecordsResultEntry() + val failingRecord = new PutRecordsResultEntry().withErrorCode("error-code").withErrorMessage("error-message") + val requestError = new RuntimeException("kinesis-error") + + val (sourceProbe, sinkProbe) = + TestSource + .probe[PutRecordsRequestEntry] + .via(KinesisFlow(streamName, settings)) + .toMat(TestSink.probe)(Keep.both) + .run() + } + + trait WithPutRecordsSuccess { self: KinesisFlowProbe => + when(amazonKinesisAsync.putRecordsAsync(any(), any())).thenAnswer(new Answer[AnyRef] { + override def answer(invocation: InvocationOnMock) = { + val request = invocation + .getArgument[PutRecordsRequest](0) + val result = new PutRecordsResult() + .withFailedRecordCount(0) + .withRecords(request.getRecords.asScala.map(_ => publishedRecord).asJava) + invocation + .getArgument[AsyncHandler[PutRecordsRequest, PutRecordsResult]](1) + .onSuccess(request, result) + CompletableFuture.completedFuture(result) + } + }) + } + + trait WithPutRecordsWithPartialErrors { self: KinesisFlowProbe => + when(amazonKinesisAsync.putRecordsAsync(any(), any())) + .thenAnswer(new Answer[AnyRef] { + override def answer(invocation: InvocationOnMock) = { + val request = invocation + .getArgument[PutRecordsRequest](0) + val result = new PutRecordsResult() + .withFailedRecordCount(request.getRecords.size()) + .withRecords( + request.getRecords.asScala + .map(_ => failingRecord) + .asJava + ) + invocation + .getArgument[AsyncHandler[PutRecordsRequest, PutRecordsResult]](1) + .onSuccess(request, result) + CompletableFuture.completedFuture(result) + } + }) + } + + trait WithPutRecordsFailure { self: KinesisFlowProbe => + when(amazonKinesisAsync.putRecordsAsync(any(), any())).thenAnswer(new Answer[AnyRef] { + override def answer(invocation: InvocationOnMock) = { + invocation + .getArgument[AsyncHandler[PutRecordsRequest, PutRecordsResult]](1) + .onError(requestError) + val future = new CompletableFuture() + future.completeExceptionally(requestError) + future + } + }) + } + +} diff --git a/kinesis/src/test/scala/akka/stream/alpakka/kinesis/KinesisSourceSpec.scala b/kinesis/src/test/scala/akka/stream/alpakka/kinesis/KinesisSourceSpec.scala index 5be3acca7d..429579b09a 100644 --- a/kinesis/src/test/scala/akka/stream/alpakka/kinesis/KinesisSourceSpec.scala +++ b/kinesis/src/test/scala/akka/stream/alpakka/kinesis/KinesisSourceSpec.scala @@ -1,13 +1,13 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.kinesis import java.util import java.util.concurrent.CompletableFuture import java.util.concurrent.atomic.AtomicReference -import akka.stream.alpakka.kinesis.KinesisSourceErrors.NoShardsError import akka.stream.alpakka.kinesis.scaladsl.KinesisSource import akka.stream.testkit.scaladsl.TestSink import akka.util.ByteString @@ -130,7 +130,7 @@ class KinesisSourceSpec extends WordSpecLike with Matchers with DefaultTestConte with WithGetRecordsFailure { val probe = KinesisSource.basic(shardSettings, amazonKinesisAsync).runWith(TestSink.probe) probe.request(1) - probe.expectError() shouldBe an[KinesisSourceErrors.GetRecordsError.type] + probe.expectError() shouldBe an[KinesisErrors.GetRecordsError.type] } } diff --git a/kinesis/src/test/scala/akka/stream/alpakka/kinesis/ShardSettingsSpec.scala b/kinesis/src/test/scala/akka/stream/alpakka/kinesis/ShardSettingsSpec.scala index 0a92b3d13a..11ffa57319 100644 --- a/kinesis/src/test/scala/akka/stream/alpakka/kinesis/ShardSettingsSpec.scala +++ b/kinesis/src/test/scala/akka/stream/alpakka/kinesis/ShardSettingsSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.kinesis import java.util.Date diff --git a/kinesis/src/test/scala/akka/stream/alpakka/kinesis/scaladsl/Examples.scala b/kinesis/src/test/scala/akka/stream/alpakka/kinesis/scaladsl/Examples.scala index c764df5a8c..2702bde9b9 100644 --- a/kinesis/src/test/scala/akka/stream/alpakka/kinesis/scaladsl/Examples.scala +++ b/kinesis/src/test/scala/akka/stream/alpakka/kinesis/scaladsl/Examples.scala @@ -1,17 +1,22 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.kinesis.scaladsl +import java.nio.ByteBuffer import java.util.Date import akka.actor.ActorSystem -import akka.stream.alpakka.kinesis.ShardSettings +import akka.stream.alpakka.kinesis.{KinesisFlowSettings, ShardSettings} +import akka.stream.scaladsl.{Sink, Source} import akka.stream.{ActorMaterializer, Materializer} -import com.amazonaws.services.kinesis.model.ShardIteratorType +import akka.util.ByteString +import com.amazonaws.services.kinesis.model.{PutRecordsRequestEntry, ShardIteratorType} import com.amazonaws.services.kinesis.{AmazonKinesisAsync, AmazonKinesisAsyncClientBuilder} import scala.concurrent.duration._ +import scala.language.postfixOps object Examples { @@ -24,19 +29,19 @@ object Examples { val amazonKinesisAsync: AmazonKinesisAsync = AmazonKinesisAsyncClientBuilder.defaultClient() //#init-client - //#settings + //#source-settings val settings = ShardSettings(streamName = "myStreamName", shardId = "shard-id", shardIteratorType = ShardIteratorType.TRIM_HORIZON, refreshInterval = 1.second, limit = 500) - //#settings + //#source-settings - //#single + //#source-single KinesisSource.basic(settings, amazonKinesisAsync) - //#single + //#source-single - //#list + //#source-list val mergeSettings = List( ShardSettings("myStreamName", "shard-id-1", @@ -52,6 +57,36 @@ object Examples { limit = 500) ) KinesisSource.basicMerge(mergeSettings, amazonKinesisAsync) - //#list + //#source-list + + //#flow-settings + val flowSettings = KinesisFlowSettings( + parallelism = 1, + maxBatchSize = 500, + maxRecordsPerSecond = 1000, + maxBytesPerSecond = 1000000, + maxRetries = 5, + backoffStrategy = KinesisFlowSettings.Exponential, + retryInitialTimeout = 100 millis + ) + + val defaultFlowSettings = KinesisFlowSettings.defaultInstance + + val fourShardFlowSettings = KinesisFlowSettings.byNumberOfShards(4) + //#flow-settings + + //#flow-sink + implicit val _: AmazonKinesisAsync = amazonKinesisAsync + + Source.empty[PutRecordsRequestEntry].via(KinesisFlow("myStreamName")).to(Sink.ignore) + Source.empty[PutRecordsRequestEntry].via(KinesisFlow("myStreamName", flowSettings)).to(Sink.ignore) + Source.empty[(String, ByteString)].via(KinesisFlow.byParititonAndBytes("myStreamName")).to(Sink.ignore) + Source.empty[(String, ByteBuffer)].via(KinesisFlow.byPartitionAndData("myStreamName")).to(Sink.ignore) + + Source.empty[PutRecordsRequestEntry].to(KinesisSink("myStreamName")) + Source.empty[PutRecordsRequestEntry].to(KinesisSink("myStreamName", flowSettings)) + Source.empty[(String, ByteString)].to(KinesisSink.byParititonAndBytes("myStreamName")) + Source.empty[(String, ByteBuffer)].to(KinesisSink.byPartitionAndData("myStreamName")) + //#flow-sink } diff --git a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/Mqtt.scala b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/Mqtt.scala index c31ae16b64..b0b874b223 100644 --- a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/Mqtt.scala +++ b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/Mqtt.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.mqtt import javax.net.ssl.SSLSocketFactory diff --git a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/MqttProducerStage.scala b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/MqttProducerStage.scala index a96b21569c..8531ff7c41 100644 --- a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/MqttProducerStage.scala +++ b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/MqttProducerStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.mqtt import akka.stream._ diff --git a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/MqttSourceStage.scala b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/MqttSourceStage.scala index 6dcb33bf3d..5a1d0d75d2 100644 --- a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/MqttSourceStage.scala +++ b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/MqttSourceStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.mqtt import java.util.concurrent.Semaphore diff --git a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/javadsl/MqttSink.scala b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/javadsl/MqttSink.scala index 04bdf307c2..274dc8f43b 100644 --- a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/javadsl/MqttSink.scala +++ b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/javadsl/MqttSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.mqtt.javadsl import java.util.concurrent.CompletionStage diff --git a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/javadsl/MqttSource.scala b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/javadsl/MqttSource.scala index 7d052bc233..85717b1812 100644 --- a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/javadsl/MqttSource.scala +++ b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/javadsl/MqttSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.mqtt.javadsl import java.util.concurrent.CompletionStage diff --git a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSink.scala b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSink.scala index 58ba13486f..be37f8b526 100644 --- a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSink.scala +++ b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.mqtt.scaladsl import akka.Done diff --git a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSource.scala b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSource.scala index 4d8946bc6e..3d7774e667 100644 --- a/mqtt/src/main/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSource.scala +++ b/mqtt/src/main/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.mqtt.scaladsl import akka.Done diff --git a/mqtt/src/test/java/akka/stream/alpakka/mqtt/javadsl/MqttSourceTest.java b/mqtt/src/test/java/akka/stream/alpakka/mqtt/javadsl/MqttSourceTest.java index fc7e39da74..8acfce02d5 100644 --- a/mqtt/src/test/java/akka/stream/alpakka/mqtt/javadsl/MqttSourceTest.java +++ b/mqtt/src/test/java/akka/stream/alpakka/mqtt/javadsl/MqttSourceTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.mqtt.javadsl; import akka.stream.alpakka.mqtt.*; diff --git a/mqtt/src/test/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSinkSpec.scala b/mqtt/src/test/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSinkSpec.scala index 26a7766994..e0c89b9691 100644 --- a/mqtt/src/test/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSinkSpec.scala +++ b/mqtt/src/test/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSinkSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.mqtt.scaladsl import akka.Done diff --git a/mqtt/src/test/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSourceSpec.scala b/mqtt/src/test/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSourceSpec.scala index cd6a1e61fe..f86c6de472 100644 --- a/mqtt/src/test/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSourceSpec.scala +++ b/mqtt/src/test/scala/akka/stream/alpakka/mqtt/scaladsl/MqttSourceSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.mqtt.scaladsl import akka.actor.ActorSystem diff --git a/project/AutomateScalafmtPlugin.scala b/project/AutomateScalafmtPlugin.scala deleted file mode 100644 index 9cf0ede222..0000000000 --- a/project/AutomateScalafmtPlugin.scala +++ /dev/null @@ -1,65 +0,0 @@ -import org.scalafmt.bootstrap.ScalafmtBootstrap -import org.scalafmt.sbt.ScalafmtPlugin -import sbt._ -import sbt.Keys._ -import sbt.inc.Analysis - -object AutomateScalafmtPlugin extends AutoPlugin { - - object autoImport { - def automateScalafmtFor(configurations: Configuration*): Seq[Setting[_]] = - configurations.flatMap { c => - inConfig(c)( - Seq( - compileInputs.in(compile) := { - scalafmtInc.value - compileInputs.in(compile).value - }, - sourceDirectories.in(scalafmtInc) := Seq(scalaSource.value), - scalafmtInc := { - val cache = streams.value.cacheDirectory / "scalafmt" - val include = includeFilter.in(scalafmtInc).value - val exclude = excludeFilter.in(scalafmtInc).value - val sources = - sourceDirectories - .in(scalafmtInc) - .value - .descendantsExcept(include, exclude) - .get - .toSet - def format(handler: Set[File] => Unit, msg: String) = { - def update(handler: Set[File] => Unit, msg: String)(in: ChangeReport[File], out: ChangeReport[File]) = { - val label = Reference.display(thisProjectRef.value) - val files = in.modified -- in.removed - Analysis - .counted("Scala source", "", "s", files.size) - .foreach(count => streams.value.log.info(s"$msg $count in $label ...")) - handler(files) - files - } - FileFunction.cached(cache)(FilesInfo.hash, FilesInfo.exists)(update(handler, msg))( - sources - ) - } - def formattingHandler(files: Set[File]) = - if (files.nonEmpty) { - val filesArg = files.map(_.getAbsolutePath).mkString(",") - ScalafmtBootstrap.main(List("--quiet", "-i", "-f", filesArg)) - } - format(formattingHandler, "Formatting") - format(_ => (), "Reformatted") // Recalculate the cache - } - ) - ) - } - } - - private val scalafmtInc = taskKey[Unit]("Incrementally format modified sources") - - override def requires = ScalafmtPlugin - - override def trigger = allRequirements - - override def projectSettings = - (includeFilter.in(scalafmtInc) := "*.scala") +: autoImport.automateScalafmtFor(Compile, Test) -} diff --git a/project/Common.scala b/project/Common.scala index 8e74141dad..41ed0515e2 100644 --- a/project/Common.scala +++ b/project/Common.scala @@ -1,17 +1,13 @@ import sbt._ import sbt.Keys._ import sbt.plugins.JvmPlugin +import com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin.autoImport._ import de.heikoseeberger.sbtheader._ import de.heikoseeberger.sbtheader.HeaderPlugin.autoImport._ +import sbtunidoc.BaseUnidocPlugin.autoImport._ object Common extends AutoPlugin { - val FileHeader = - (HeaderPattern.cStyleBlockComment, """|/* - | * Copyright (C) 2016-2017 Lightbend Inc. - | */ - |""".stripMargin) - override def trigger = allRequirements override def requires = JvmPlugin && HeaderPlugin @@ -50,9 +46,7 @@ object Common extends AutoPlugin { // -v Log "test run started" / "test started" / "test run finished" events on log level "info" instead of "debug". // -a Show stack traces and exception class name for AssertionErrors. testOptions += Tests.Argument(TestFrameworks.JUnit, "-v", "-a"), - headers := headers.value ++ Map( - "scala" -> FileHeader, - "java" -> FileHeader - ) + scalafmtOnCompile := true, + headerLicense := Some(HeaderLicense.Custom("Copyright (C) 2016-2017 Lightbend Inc. ")) ) } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 762d8ad532..92674da419 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -6,7 +6,7 @@ object Dependencies { case Some("2.5") => "2.5.6" case _ => "2.4.19" } - val AkkaHttpVersion = "10.0.9" + val AkkaHttpVersion = "10.0.10" val Common = Seq( libraryDependencies ++= Seq( @@ -83,7 +83,7 @@ object Dependencies { ) val Geode = { - val geodeVersion = "1.2.1" + val geodeVersion = "1.3.0" val slf4jVersion = "1.7.25" val logbackVersion = "1.2.3" Seq( diff --git a/project/Publish.scala b/project/Publish.scala index 218df45fc2..3b262ee2b4 100644 --- a/project/Publish.scala +++ b/project/Publish.scala @@ -27,17 +27,18 @@ object Publish extends AutoPlugin { } object PublishUnidoc extends AutoPlugin { - import sbtunidoc.Plugin._ - import sbtunidoc.Plugin.UnidocKeys._ + import sbtunidoc.BaseUnidocPlugin._ + import sbtunidoc.BaseUnidocPlugin.autoImport._ + import sbtunidoc.ScalaUnidocPlugin.autoImport.ScalaUnidoc - override def requires = plugins.JvmPlugin + override def requires = sbtunidoc.ScalaUnidocPlugin def publishOnly(artifactType: String)(config: PublishConfiguration) = { - val newArts = config.artifacts.filterKeys(_.`type` == artifactType) - new PublishConfiguration(config.ivyFile, config.resolverName, newArts, config.checksums, config.logging) + val newArts = config.artifacts.filter(_._1.`type` == artifactType) + config.withArtifacts(newArts) } - override def projectSettings = unidocSettings ++ Seq( + override def projectSettings = Seq( doc in Compile := (doc in ScalaUnidoc).value, target in unidoc in ScalaUnidoc := crossTarget.value / "api", publishConfiguration ~= publishOnly(Artifact.DocType), diff --git a/project/TestChanged.scala b/project/TestChanged.scala index 200ff342a5..cbb47b0373 100644 --- a/project/TestChanged.scala +++ b/project/TestChanged.scala @@ -1,6 +1,7 @@ package akka.stream.alpakka import scala.collection.immutable +import scala.sys.process._ import sbt._ import sbt.Keys._ @@ -34,7 +35,7 @@ object TestChanged extends AutoPlugin { override lazy val projectSettings = Seq( testChanged := Def.taskDyn { - val skip = Def.setting { task() } + val skip = Def.setting { task(()) } if (shouldBuild(name.value, changedDirectories.value)) test in Test else skip }.value diff --git a/project/build.properties b/project/build.properties index c091b86ca4..9abea1294a 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.16 +sbt.version=1.0.3 diff --git a/project/plugins.sbt b/project/plugins.sbt index 97658d5437..3311c5ad29 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,10 +1,10 @@ -addSbtPlugin("de.heikoseeberger" % "sbt-header" % "1.6.0") -addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "0.6.6") +addSbtPlugin("de.heikoseeberger" % "sbt-header" % "3.0.2") +addSbtPlugin("com.lucidchart" % "sbt-scalafmt-coursier" % "1.12") addSbtPlugin("com.dwijnand" % "sbt-dynver" % "2.0.0") addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.9.3") -addSbtPlugin("com.dwijnand" % "sbt-travisci" % "1.1.0") +addSbtPlugin("com.dwijnand" % "sbt-travisci" % "1.1.1") addSbtPlugin("com.lightbend.paradox" % "sbt-paradox" % "0.3.1") -addSbtPlugin("com.eed3si9n" % "sbt-unidoc" % "0.3.3") -addSbtPlugin("com.thoughtworks.sbt-api-mappings" % "sbt-api-mappings" % "1.0.0") +addSbtPlugin("com.eed3si9n" % "sbt-unidoc" % "0.4.1") +addSbtPlugin("com.thoughtworks.sbt-api-mappings" % "sbt-api-mappings" % "2.0.0") addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.1") -addSbtPlugin("com.lightbend" % "sbt-whitesource" % "0.1.3") +addSbtPlugin("com.lightbend" % "sbt-whitesource" % "0.1.6") diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/S3Exception.scala b/s3/src/main/scala/akka/stream/alpakka/s3/S3Exception.scala index 0899ce7dc3..af72afa684 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/S3Exception.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/S3Exception.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3 import scala.xml.{Elem, XML} diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/S3Settings.scala b/s3/src/main/scala/akka/stream/alpakka/s3/S3Settings.scala index 00b554ad70..e6484a6017 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/S3Settings.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/S3Settings.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3 import java.nio.file.{Path, Paths} diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/acl/CannedAcl.scala b/s3/src/main/scala/akka/stream/alpakka/s3/acl/CannedAcl.scala index 3ed41a76fe..bbd1e56fa9 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/acl/CannedAcl.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/acl/CannedAcl.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.acl import akka.http.scaladsl.model.HttpHeader diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/auth/AWSCredentials.scala b/s3/src/main/scala/akka/stream/alpakka/s3/auth/AWSCredentials.scala index 16b7157be0..7ed5225164 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/auth/AWSCredentials.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/auth/AWSCredentials.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.auth import com.amazonaws.auth diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/auth/CanonicalRequest.scala b/s3/src/main/scala/akka/stream/alpakka/s3/auth/CanonicalRequest.scala index 43fe5d32dd..a71bc7906e 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/auth/CanonicalRequest.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/auth/CanonicalRequest.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.auth import java.net.URLEncoder diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/auth/Signer.scala b/s3/src/main/scala/akka/stream/alpakka/s3/auth/Signer.scala index 34e8dc72b6..31801e80ce 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/auth/Signer.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/auth/Signer.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.auth import java.security.MessageDigest @@ -34,12 +35,9 @@ private[alpakka] object Signer { private[this] def sessionHeader(creds: AWSCredentialsProvider): Option[HttpHeader] = creds.getCredentials match { - case _: BasicAWSCredentials => - None - case _: AnonymousAWSCredentials ⇒ - None case sessCreds: auth.AWSSessionCredentials => Some(RawHeader("X-Amz-Security-Token", sessCreds.getSessionToken)) + case _ => None } private[this] def authorizationHeader(algorithm: String, diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/auth/SigningKey.scala b/s3/src/main/scala/akka/stream/alpakka/s3/auth/SigningKey.scala index 5426ed5a67..9038da9959 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/auth/SigningKey.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/auth/SigningKey.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.auth import java.time.LocalDate diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/auth/package.scala b/s3/src/main/scala/akka/stream/alpakka/s3/auth/package.scala index 7afb7f7a25..727e654b28 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/auth/package.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/auth/package.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3 import java.security.MessageDigest diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/impl/Chunk.scala b/s3/src/main/scala/akka/stream/alpakka/s3/impl/Chunk.scala index 79c6f6df06..14b581282a 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/impl/Chunk.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/impl/Chunk.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import akka.stream.scaladsl.Source diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/impl/DiskBuffer.scala b/s3/src/main/scala/akka/stream/alpakka/s3/impl/DiskBuffer.scala index 781421aac1..0769d2277d 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/impl/DiskBuffer.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/impl/DiskBuffer.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import java.io.{File, FileOutputStream, RandomAccessFile} diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/impl/HttpRequests.scala b/s3/src/main/scala/akka/stream/alpakka/s3/impl/HttpRequests.scala index 050e9fbc7a..4bd5f7404b 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/impl/HttpRequests.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/impl/HttpRequests.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._ diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/impl/Marshalling.scala b/s3/src/main/scala/akka/stream/alpakka/s3/impl/Marshalling.scala index 50b904e349..e61f98b54e 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/impl/Marshalling.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/impl/Marshalling.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import java.time.Instant diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/impl/MemoryBuffer.scala b/s3/src/main/scala/akka/stream/alpakka/s3/impl/MemoryBuffer.scala index 612a2031a3..44898f4242 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/impl/MemoryBuffer.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/impl/MemoryBuffer.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import akka.stream.{Attributes, FlowShape, Inlet, Outlet} diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/impl/S3Headers.scala b/s3/src/main/scala/akka/stream/alpakka/s3/impl/S3Headers.scala index bb40756d02..dafce45618 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/impl/S3Headers.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/impl/S3Headers.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import akka.http.scaladsl.model.HttpHeader diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/impl/S3Stream.scala b/s3/src/main/scala/akka/stream/alpakka/s3/impl/S3Stream.scala index 45fb56eb5e..6306fe8cb8 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/impl/S3Stream.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/impl/S3Stream.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import java.time.LocalDate @@ -57,7 +58,8 @@ private[alpakka] final class S3Stream(settings: S3Settings)(implicit system: Act implicit val conf = settings val MinChunkSize = 5242880 //in bytes - val signingKey = SigningKey(settings.credentialsProvider, CredentialScope(LocalDate.now(), settings.s3Region, "s3")) + // def because tokens can expire + def signingKey = SigningKey(settings.credentialsProvider, CredentialScope(LocalDate.now(), settings.s3Region, "s3")) def download(s3Location: S3Location, range: Option[ByteRange] = None): Source[ByteString, NotUsed] = { import mat.executionContext @@ -171,6 +173,9 @@ private[alpakka] final class S3Stream(settings: S3Settings)(implicit system: Act val requestInfo: Source[(MultipartUpload, Int), NotUsed] = initiateUpload(s3Location, contentType, s3Headers) + // use the same key for all sub-requests (chunks) + val key: SigningKey = signingKey + SplitAfterSize(chunkSize)(Flow.apply[ByteString]) .via(getChunkBuffer(chunkSize)) //creates the chunks .concatSubstreams @@ -181,7 +186,7 @@ private[alpakka] final class S3Stream(settings: S3Settings)(implicit system: Act uploadPartRequest(uploadInfo, chunkIndex, chunkedPayload.data, chunkedPayload.size) (partRequest, (uploadInfo, chunkIndex)) } - .mapAsync(parallelism) { case (req, info) => Signer.signedRequest(req, signingKey).zip(Future.successful(info)) } + .mapAsync(parallelism) { case (req, info) => Signer.signedRequest(req, key).zip(Future.successful(info)) } } private def getChunkBuffer(chunkSize: Int) = settings.bufferType match { diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/impl/SplitAfterSize.scala b/s3/src/main/scala/akka/stream/alpakka/s3/impl/SplitAfterSize.scala index 4fd22939c0..77af95401a 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/impl/SplitAfterSize.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/impl/SplitAfterSize.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import akka.stream.scaladsl.SubFlow diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/javadsl/S3Client.scala b/s3/src/main/scala/akka/stream/alpakka/s3/javadsl/S3Client.scala index 6950a71980..42839010ba 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/javadsl/S3Client.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/javadsl/S3Client.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.javadsl import java.time.Instant diff --git a/s3/src/main/scala/akka/stream/alpakka/s3/scaladsl/S3Client.scala b/s3/src/main/scala/akka/stream/alpakka/s3/scaladsl/S3Client.scala index 3c62227af4..e2918bff39 100644 --- a/s3/src/main/scala/akka/stream/alpakka/s3/scaladsl/S3Client.scala +++ b/s3/src/main/scala/akka/stream/alpakka/s3/scaladsl/S3Client.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.scaladsl import java.time.Instant diff --git a/s3/src/test/java/akka/stream/alpakka/s3/javadsl/DocSnippets.java b/s3/src/test/java/akka/stream/alpakka/s3/javadsl/DocSnippets.java index 8188051866..90d56d50dd 100644 --- a/s3/src/test/java/akka/stream/alpakka/s3/javadsl/DocSnippets.java +++ b/s3/src/test/java/akka/stream/alpakka/s3/javadsl/DocSnippets.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.javadsl; import akka.stream.ActorMaterializer; diff --git a/s3/src/test/java/akka/stream/alpakka/s3/javadsl/S3ClientTest.java b/s3/src/test/java/akka/stream/alpakka/s3/javadsl/S3ClientTest.java index bae4fbac43..c6c2e11d33 100644 --- a/s3/src/test/java/akka/stream/alpakka/s3/javadsl/S3ClientTest.java +++ b/s3/src/test/java/akka/stream/alpakka/s3/javadsl/S3ClientTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.javadsl; import java.util.Arrays; diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/S3SettingsSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/S3SettingsSpec.scala index b8a5d1db46..5fac6510c9 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/S3SettingsSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/S3SettingsSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3 import akka.stream.alpakka.s3.scaladsl.{S3ClientIntegrationSpec, S3WireMockBase} diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/auth/CanonicalRequestSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/auth/CanonicalRequestSpec.scala index c84be3de95..5383a885db 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/auth/CanonicalRequestSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/auth/CanonicalRequestSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.auth import akka.http.scaladsl.model.Uri.Query diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/auth/SignerSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/auth/SignerSpec.scala index 5452e273d6..2f5b134753 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/auth/SignerSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/auth/SignerSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.auth import java.time.{LocalDate, LocalDateTime, ZoneOffset} diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/auth/SigningKeySpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/auth/SigningKeySpec.scala index 317eb910c2..062f40e62b 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/auth/SigningKeySpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/auth/SigningKeySpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.auth import java.time.LocalDate diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/auth/StreamUtilsSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/auth/StreamUtilsSpec.scala index 79027ebbea..43cb0e7da1 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/auth/StreamUtilsSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/auth/StreamUtilsSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.auth import java.nio.charset.StandardCharsets._ diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/impl/DiskBufferSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/impl/DiskBufferSpec.scala index a2081337e7..1df1663e4c 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/impl/DiskBufferSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/impl/DiskBufferSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import java.nio.BufferOverflowException diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/impl/HttpRequestsSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/impl/HttpRequestsSpec.scala index 5f7e9f2091..def293b1e4 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/impl/HttpRequestsSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/impl/HttpRequestsSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import akka.http.scaladsl.model.Uri.Query diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/impl/MarshallingSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/impl/MarshallingSpec.scala index ccc6853ed2..14e593f89a 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/impl/MarshallingSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/impl/MarshallingSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import java.time.Instant diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/impl/MemoryBufferSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/impl/MemoryBufferSpec.scala index 25aea43a1b..dcd9274cc1 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/impl/MemoryBufferSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/impl/MemoryBufferSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import akka.actor.ActorSystem diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/impl/S3HeadersSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/impl/S3HeadersSpec.scala index 119ec9c9c9..f7c8d59966 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/impl/S3HeadersSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/impl/S3HeadersSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import akka.http.scaladsl.model.headers.RawHeader diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/impl/S3StreamSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/impl/S3StreamSpec.scala index fc572658c5..fcb8649440 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/impl/S3StreamSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/impl/S3StreamSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import akka.actor.ActorSystem diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/impl/SplitAfterSizeSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/impl/SplitAfterSizeSpec.scala index 0ab90e154d..f49c814fce 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/impl/SplitAfterSizeSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/impl/SplitAfterSizeSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.impl import akka.actor.ActorSystem diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/DocSnippets.scala b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/DocSnippets.scala index 7df2e27ae4..248b7370b5 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/DocSnippets.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/DocSnippets.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.scaladsl import akka.actor.ActorSystem diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3ClientIntegrationSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3ClientIntegrationSpec.scala index 8f1424e824..a07633ac01 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3ClientIntegrationSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3ClientIntegrationSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.scaladsl import akka.actor.ActorSystem diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3ClientSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3ClientSpec.scala index dfaa2f5a75..81745f5341 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3ClientSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3ClientSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.scaladsl import akka.actor.ActorSystem diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3NoMock.scala b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3NoMock.scala index f1beac70ec..1f410eebc2 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3NoMock.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3NoMock.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.scaladsl import scala.concurrent.Await diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3SinkSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3SinkSpec.scala index 659d99b254..b1a2d695b9 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3SinkSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3SinkSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.scaladsl import akka.stream.alpakka.s3.{MemoryBufferType, Proxy, S3Settings} diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3SourceSpec.scala b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3SourceSpec.scala index ffba94f8d9..3aa7dd44b0 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3SourceSpec.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3SourceSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.scaladsl import akka.NotUsed diff --git a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3WireMockBase.scala b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3WireMockBase.scala index fb0ad14973..a3022ccd87 100644 --- a/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3WireMockBase.scala +++ b/s3/src/test/scala/akka/stream/alpakka/s3/scaladsl/S3WireMockBase.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.s3.scaladsl import akka.actor.ActorSystem diff --git a/simple-codecs/src/main/scala/akka/stream/alpakka/recordio/javadsl/RecordIOFraming.scala b/simple-codecs/src/main/scala/akka/stream/alpakka/recordio/javadsl/RecordIOFraming.scala index e50b35c84f..97fdd55859 100755 --- a/simple-codecs/src/main/scala/akka/stream/alpakka/recordio/javadsl/RecordIOFraming.scala +++ b/simple-codecs/src/main/scala/akka/stream/alpakka/recordio/javadsl/RecordIOFraming.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.recordio.javadsl import akka.NotUsed diff --git a/simple-codecs/src/main/scala/akka/stream/alpakka/recordio/scaladsl/RecordIOFraming.scala b/simple-codecs/src/main/scala/akka/stream/alpakka/recordio/scaladsl/RecordIOFraming.scala index bfb9e38c9d..b884057722 100644 --- a/simple-codecs/src/main/scala/akka/stream/alpakka/recordio/scaladsl/RecordIOFraming.scala +++ b/simple-codecs/src/main/scala/akka/stream/alpakka/recordio/scaladsl/RecordIOFraming.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.recordio.scaladsl import akka.NotUsed diff --git a/simple-codecs/src/test/scala/akka/stream/alpakka/recordio/RecordIOFramingSpec.scala b/simple-codecs/src/test/scala/akka/stream/alpakka/recordio/RecordIOFramingSpec.scala index 1059100503..cef4f72ffe 100644 --- a/simple-codecs/src/test/scala/akka/stream/alpakka/recordio/RecordIOFramingSpec.scala +++ b/simple-codecs/src/test/scala/akka/stream/alpakka/recordio/RecordIOFramingSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.recordio import akka.actor.ActorSystem diff --git a/slick/src/main/scala/akka/stream/alpakka/slick/javadsl/Slick.scala b/slick/src/main/scala/akka/stream/alpakka/slick/javadsl/Slick.scala index e03ecf9908..5e59cde6ca 100644 --- a/slick/src/main/scala/akka/stream/alpakka/slick/javadsl/Slick.scala +++ b/slick/src/main/scala/akka/stream/alpakka/slick/javadsl/Slick.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.slick.javadsl import java.util.concurrent.CompletionStage diff --git a/slick/src/main/scala/akka/stream/alpakka/slick/javadsl/package.scala b/slick/src/main/scala/akka/stream/alpakka/slick/javadsl/package.scala index cc5d3b2e25..adbf82bcea 100644 --- a/slick/src/main/scala/akka/stream/alpakka/slick/javadsl/package.scala +++ b/slick/src/main/scala/akka/stream/alpakka/slick/javadsl/package.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.slick.javadsl import slick.basic.DatabaseConfig diff --git a/slick/src/main/scala/akka/stream/alpakka/slick/scaladsl/Slick.scala b/slick/src/main/scala/akka/stream/alpakka/slick/scaladsl/Slick.scala index 955f8113b0..e839596de7 100644 --- a/slick/src/main/scala/akka/stream/alpakka/slick/scaladsl/Slick.scala +++ b/slick/src/main/scala/akka/stream/alpakka/slick/scaladsl/Slick.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.slick.scaladsl import scala.concurrent.Future diff --git a/slick/src/main/scala/akka/stream/alpakka/slick/scaladsl/package.scala b/slick/src/main/scala/akka/stream/alpakka/slick/scaladsl/package.scala index 65a48a81f3..06b9a2ee5c 100644 --- a/slick/src/main/scala/akka/stream/alpakka/slick/scaladsl/package.scala +++ b/slick/src/main/scala/akka/stream/alpakka/slick/scaladsl/package.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.slick package object scaladsl { diff --git a/slick/src/test/java/akka/stream/alpakka/slick/javadsl/DocSnippetFlow.java b/slick/src/test/java/akka/stream/alpakka/slick/javadsl/DocSnippetFlow.java index 4a7e11d37f..5ccf70dd8d 100644 --- a/slick/src/test/java/akka/stream/alpakka/slick/javadsl/DocSnippetFlow.java +++ b/slick/src/test/java/akka/stream/alpakka/slick/javadsl/DocSnippetFlow.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package example; //#flow-example diff --git a/slick/src/test/java/akka/stream/alpakka/slick/javadsl/DocSnippetSink.java b/slick/src/test/java/akka/stream/alpakka/slick/javadsl/DocSnippetSink.java index 334b7ddd46..404c3d914f 100644 --- a/slick/src/test/java/akka/stream/alpakka/slick/javadsl/DocSnippetSink.java +++ b/slick/src/test/java/akka/stream/alpakka/slick/javadsl/DocSnippetSink.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package example; //#sink-example diff --git a/slick/src/test/java/akka/stream/alpakka/slick/javadsl/DocSnippetSource.java b/slick/src/test/java/akka/stream/alpakka/slick/javadsl/DocSnippetSource.java index 65abf3d131..457a9d0d7f 100644 --- a/slick/src/test/java/akka/stream/alpakka/slick/javadsl/DocSnippetSource.java +++ b/slick/src/test/java/akka/stream/alpakka/slick/javadsl/DocSnippetSource.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package example; //#important-imports diff --git a/slick/src/test/java/akka/stream/alpakka/slick/javadsl/SlickTest.java b/slick/src/test/java/akka/stream/alpakka/slick/javadsl/SlickTest.java index d8251bd4f7..39f42df169 100644 --- a/slick/src/test/java/akka/stream/alpakka/slick/javadsl/SlickTest.java +++ b/slick/src/test/java/akka/stream/alpakka/slick/javadsl/SlickTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.slick.javadsl; import java.util.Arrays; diff --git a/slick/src/test/java/akka/stream/alpakka/slick/javadsl/User.java b/slick/src/test/java/akka/stream/alpakka/slick/javadsl/User.java index a14e494a94..4deb31f53b 100644 --- a/slick/src/test/java/akka/stream/alpakka/slick/javadsl/User.java +++ b/slick/src/test/java/akka/stream/alpakka/slick/javadsl/User.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.slick.javadsl; public class User { diff --git a/slick/src/test/scala/akka/stream/alpakka/slick/scaladsl/DocSnippets.scala b/slick/src/test/scala/akka/stream/alpakka/slick/scaladsl/DocSnippets.scala index 838c99912a..0ce11775cf 100644 --- a/slick/src/test/scala/akka/stream/alpakka/slick/scaladsl/DocSnippets.scala +++ b/slick/src/test/scala/akka/stream/alpakka/slick/scaladsl/DocSnippets.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package example //#important-imports diff --git a/slick/src/test/scala/akka/stream/alpakka/slick/scaladsl/SlickSpec.scala b/slick/src/test/scala/akka/stream/alpakka/slick/scaladsl/SlickSpec.scala index 7966ba41ff..ec499ef199 100644 --- a/slick/src/test/scala/akka/stream/alpakka/slick/scaladsl/SlickSpec.scala +++ b/slick/src/test/scala/akka/stream/alpakka/slick/scaladsl/SlickSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.slick.scaladsl import scala.concurrent.Future diff --git a/sns/src/main/scala/akka/stream/alpakka/sns/SnsPublishFlowStage.scala b/sns/src/main/scala/akka/stream/alpakka/sns/SnsPublishFlowStage.scala index 9b18a68812..fe77870636 100644 --- a/sns/src/main/scala/akka/stream/alpakka/sns/SnsPublishFlowStage.scala +++ b/sns/src/main/scala/akka/stream/alpakka/sns/SnsPublishFlowStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sns import akka.stream._ diff --git a/sns/src/main/scala/akka/stream/alpakka/sns/javadsl/SnsPublisher.scala b/sns/src/main/scala/akka/stream/alpakka/sns/javadsl/SnsPublisher.scala index 95691a09eb..e587301629 100644 --- a/sns/src/main/scala/akka/stream/alpakka/sns/javadsl/SnsPublisher.scala +++ b/sns/src/main/scala/akka/stream/alpakka/sns/javadsl/SnsPublisher.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sns.javadsl import java.util.concurrent.CompletionStage diff --git a/sns/src/main/scala/akka/stream/alpakka/sns/scaladsl/SnsPublisher.scala b/sns/src/main/scala/akka/stream/alpakka/sns/scaladsl/SnsPublisher.scala index b4b0f07250..3acdfc13a8 100644 --- a/sns/src/main/scala/akka/stream/alpakka/sns/scaladsl/SnsPublisher.scala +++ b/sns/src/main/scala/akka/stream/alpakka/sns/scaladsl/SnsPublisher.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sns.scaladsl import akka.stream.alpakka.sns.SnsPublishFlowStage diff --git a/sns/src/test/java/akka/stream/alpakka/sns/javadsl/Examples.java b/sns/src/test/java/akka/stream/alpakka/sns/javadsl/Examples.java index c88a6b93e8..282c4b7641 100644 --- a/sns/src/test/java/akka/stream/alpakka/sns/javadsl/Examples.java +++ b/sns/src/test/java/akka/stream/alpakka/sns/javadsl/Examples.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sns.javadsl; import akka.Done; diff --git a/sns/src/test/scala/akka/stream/alpakka/sns/DefaultTestContext.scala b/sns/src/test/scala/akka/stream/alpakka/sns/DefaultTestContext.scala index ef87d47e14..6070e39c20 100644 --- a/sns/src/test/scala/akka/stream/alpakka/sns/DefaultTestContext.scala +++ b/sns/src/test/scala/akka/stream/alpakka/sns/DefaultTestContext.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sns import akka.actor.ActorSystem diff --git a/sns/src/test/scala/akka/stream/alpakka/sns/SnsPublishFlowSpec.scala b/sns/src/test/scala/akka/stream/alpakka/sns/SnsPublishFlowSpec.scala index 580078d70c..6bf387eae6 100644 --- a/sns/src/test/scala/akka/stream/alpakka/sns/SnsPublishFlowSpec.scala +++ b/sns/src/test/scala/akka/stream/alpakka/sns/SnsPublishFlowSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sns import java.util.concurrent.{CompletableFuture, Future} diff --git a/sns/src/test/scala/akka/stream/alpakka/sns/scaladsl/Examples.scala b/sns/src/test/scala/akka/stream/alpakka/sns/scaladsl/Examples.scala index 04c5205736..1e155e3e1b 100644 --- a/sns/src/test/scala/akka/stream/alpakka/sns/scaladsl/Examples.scala +++ b/sns/src/test/scala/akka/stream/alpakka/sns/scaladsl/Examples.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sns.scaladsl import akka.Done diff --git a/spring-web/src/main/java/akka/stream/alpakka/spring/web/AkkaStreamsRegistrar.java b/spring-web/src/main/java/akka/stream/alpakka/spring/web/AkkaStreamsRegistrar.java index 654f2ca7a0..af72156813 100644 --- a/spring-web/src/main/java/akka/stream/alpakka/spring/web/AkkaStreamsRegistrar.java +++ b/spring-web/src/main/java/akka/stream/alpakka/spring/web/AkkaStreamsRegistrar.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.spring.web; import akka.stream.Materializer; diff --git a/spring-web/src/main/java/akka/stream/alpakka/spring/web/SpringWebAkkaStreamsConfiguration.java b/spring-web/src/main/java/akka/stream/alpakka/spring/web/SpringWebAkkaStreamsConfiguration.java index 180c21a2f0..6822fe119d 100644 --- a/spring-web/src/main/java/akka/stream/alpakka/spring/web/SpringWebAkkaStreamsConfiguration.java +++ b/spring-web/src/main/java/akka/stream/alpakka/spring/web/SpringWebAkkaStreamsConfiguration.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.spring.web; //#configure diff --git a/spring-web/src/test/java/akka/stream/alpakka/spring/web/DemoApplication.java b/spring-web/src/test/java/akka/stream/alpakka/spring/web/DemoApplication.java index 4b966ba92f..14075ee2e3 100644 --- a/spring-web/src/test/java/akka/stream/alpakka/spring/web/DemoApplication.java +++ b/spring-web/src/test/java/akka/stream/alpakka/spring/web/DemoApplication.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.spring.web; //#use diff --git a/spring-web/src/test/java/akka/stream/alpakka/spring/web/SampleController.java b/spring-web/src/test/java/akka/stream/alpakka/spring/web/SampleController.java index a9132fbe06..71ecdf11ae 100644 --- a/spring-web/src/test/java/akka/stream/alpakka/spring/web/SampleController.java +++ b/spring-web/src/test/java/akka/stream/alpakka/spring/web/SampleController.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.spring.web; //#use diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsAckFlowStage.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsAckFlowStage.scala index 8e9e15e386..54ac48c60b 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsAckFlowStage.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsAckFlowStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs import akka.stream.alpakka.sqs.scaladsl.AckResult diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsAckSinkSettings.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsAckSinkSettings.scala index 30b7570321..82b830a2a9 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsAckSinkSettings.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsAckSinkSettings.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs object SqsAckSinkSettings { diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsFlowStage.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsFlowStage.scala index f1e185435d..898d08525b 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsFlowStage.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsFlowStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs import akka.stream.alpakka.sqs.scaladsl.Result diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsSinkSettings.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsSinkSettings.scala index 00916f7a88..5fc498b30a 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsSinkSettings.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsSinkSettings.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs object SqsSinkSettings { diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsSourceSettings.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsSourceSettings.scala index 4a9f989eca..395f303fa0 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsSourceSettings.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsSourceSettings.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs import java.util diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsSourceStage.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsSourceStage.scala index 288df5099a..8e16cf12ee 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsSourceStage.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/SqsSourceStage.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs import java.util diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsAckFlow.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsAckFlow.scala index ed6ffdf94a..66e2f801ac 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsAckFlow.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsAckFlow.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.javadsl import akka.NotUsed diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsAckSink.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsAckSink.scala index d0f72e054f..1e765bcbe9 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsAckSink.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsAckSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.javadsl import java.util.concurrent.CompletionStage diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsFlow.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsFlow.scala index e56e88671e..dbaaa4cd92 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsFlow.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsFlow.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.javadsl import akka.NotUsed diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsSink.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsSink.scala index c734b04c05..ec79993460 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsSink.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.javadsl import java.util.concurrent.CompletionStage diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsSource.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsSource.scala index ee7de3589f..3fec97c233 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsSource.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/javadsl/SqsSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.javadsl import akka.NotUsed diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/package.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/package.scala index a2011808a9..3a42d4fe46 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/package.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/package.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka import com.amazonaws.services.sqs.model.Message diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsAckFlow.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsAckFlow.scala index 5db179b308..bce7dc99dc 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsAckFlow.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsAckFlow.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import akka.NotUsed diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsAckSink.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsAckSink.scala index 07dbe217ca..86d13079f5 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsAckSink.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsAckSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import akka.Done diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsFlow.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsFlow.scala index 6cbe8893c7..0de110c41e 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsFlow.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsFlow.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import akka.NotUsed diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsSink.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsSink.scala index 0bf17e5919..43f4ed27b7 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsSink.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsSink.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import akka.Done diff --git a/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsSource.scala b/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsSource.scala index 97939188e6..dbf1e6d96c 100644 --- a/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsSource.scala +++ b/sqs/src/main/scala/akka/stream/alpakka/sqs/scaladsl/SqsSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import akka.NotUsed diff --git a/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/BaseSqsTest.java b/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/BaseSqsTest.java index 13e88389d5..f51044533b 100644 --- a/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/BaseSqsTest.java +++ b/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/BaseSqsTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.javadsl; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.AWSCredentialsProvider; diff --git a/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/SqsAckSinkTest.java b/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/SqsAckSinkTest.java index 9991d5bc27..1f2bdd3e19 100644 --- a/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/SqsAckSinkTest.java +++ b/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/SqsAckSinkTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.javadsl; import akka.Done; diff --git a/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/SqsSinkTest.java b/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/SqsSinkTest.java index ca93c8252d..76cb3bd212 100644 --- a/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/SqsSinkTest.java +++ b/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/SqsSinkTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.javadsl; import akka.Done; diff --git a/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/SqsSourceTest.java b/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/SqsSourceTest.java index d4ea43c96f..7dfd732291 100644 --- a/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/SqsSourceTest.java +++ b/sqs/src/test/java/akka/stream/alpakka/sqs/javadsl/SqsSourceTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.javadsl; import akka.actor.ActorSystem; diff --git a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/ChangeMessageVisibilitySpec.scala b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/ChangeMessageVisibilitySpec.scala index d3d42e0ca0..7a86befc65 100644 --- a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/ChangeMessageVisibilitySpec.scala +++ b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/ChangeMessageVisibilitySpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import akka.stream.alpakka.sqs.ChangeMessageVisibility diff --git a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/DefaultTestContext.scala b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/DefaultTestContext.scala index 535865e215..38922ebc25 100644 --- a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/DefaultTestContext.scala +++ b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/DefaultTestContext.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import akka.actor.ActorSystem diff --git a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/MessageAttributeNameSpec.scala b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/MessageAttributeNameSpec.scala index be10f54af8..294ec38b29 100644 --- a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/MessageAttributeNameSpec.scala +++ b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/MessageAttributeNameSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import akka.stream.alpakka.sqs.{MessageAttributeName, SqsSourceSettings} diff --git a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsAckSinkSettingsSpec.scala b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsAckSinkSettingsSpec.scala index bb5aca688f..f22beff14a 100644 --- a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsAckSinkSettingsSpec.scala +++ b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsAckSinkSettingsSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import akka.stream.alpakka.sqs.SqsAckSinkSettings diff --git a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSinkSettingsSpec.scala b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSinkSettingsSpec.scala index b43670440e..b69f94710b 100644 --- a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSinkSettingsSpec.scala +++ b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSinkSettingsSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import akka.stream.alpakka.sqs.SqsSinkSettings diff --git a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSinkSpec.scala b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSinkSpec.scala index b0b4a2243b..94338af266 100644 --- a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSinkSpec.scala +++ b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSinkSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import java.util.concurrent.{CompletableFuture, Future} diff --git a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSourceSettingsSpec.scala b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSourceSettingsSpec.scala index 4d8bb8f0b0..1c76963519 100644 --- a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSourceSettingsSpec.scala +++ b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSourceSettingsSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import akka.stream.alpakka.sqs.{All, SqsSourceSettings} diff --git a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSourceSpec.scala b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSourceSpec.scala index 46dca871b7..3e9c2719c8 100644 --- a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSourceSpec.scala +++ b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSourceSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import java.util.concurrent.Executors diff --git a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSpec.scala b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSpec.scala index 915c338201..d9e404f4a4 100644 --- a/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSpec.scala +++ b/sqs/src/test/scala/akka/stream/alpakka/sqs/scaladsl/SqsSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sqs.scaladsl import akka.Done diff --git a/sse/src/main/scala/akka/stream/alpakka/sse/javadsl/EventSource.scala b/sse/src/main/scala/akka/stream/alpakka/sse/javadsl/EventSource.scala index c5da5029db..1ae937c9d7 100644 --- a/sse/src/main/scala/akka/stream/alpakka/sse/javadsl/EventSource.scala +++ b/sse/src/main/scala/akka/stream/alpakka/sse/javadsl/EventSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sse package javadsl diff --git a/sse/src/main/scala/akka/stream/alpakka/sse/scaladsl/EventSource.scala b/sse/src/main/scala/akka/stream/alpakka/sse/scaladsl/EventSource.scala index cc9c37f9e7..92baac38e3 100644 --- a/sse/src/main/scala/akka/stream/alpakka/sse/scaladsl/EventSource.scala +++ b/sse/src/main/scala/akka/stream/alpakka/sse/scaladsl/EventSource.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sse package scaladsl diff --git a/sse/src/test/scala/akka/stream/alpakka/sse/scaladsl/EventSourceSpec.scala b/sse/src/test/scala/akka/stream/alpakka/sse/scaladsl/EventSourceSpec.scala index 7c8640c6c3..b681330f44 100644 --- a/sse/src/test/scala/akka/stream/alpakka/sse/scaladsl/EventSourceSpec.scala +++ b/sse/src/test/scala/akka/stream/alpakka/sse/scaladsl/EventSourceSpec.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.sse package scaladsl diff --git a/xml/src/main/scala/akka/stream/alpakka/xml/Xml.scala b/xml/src/main/scala/akka/stream/alpakka/xml/Xml.scala index fca6b5536e..d51bb8283c 100644 --- a/xml/src/main/scala/akka/stream/alpakka/xml/Xml.scala +++ b/xml/src/main/scala/akka/stream/alpakka/xml/Xml.scala @@ -1,13 +1,16 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.xml +import java.nio.charset.Charset import java.util.Optional +import javax.xml.stream.XMLOutputFactory import akka.stream.stage.{GraphStage, GraphStageLogic, InHandler, OutHandler} import akka.stream.{Attributes, FlowShape, Inlet, Outlet} -import akka.util.ByteString +import akka.util.{ByteString, ByteStringBuilder} import com.fasterxml.aalto.stax.InputFactoryImpl import com.fasterxml.aalto.{AsyncByteArrayFeeder, AsyncXMLInputFactory, AsyncXMLStreamReader} @@ -175,6 +178,65 @@ object Xml { } } + /** + * Internal API + */ + private[xml] class StreamingXmlWriter(charset: Charset) extends GraphStage[FlowShape[ParseEvent, ByteString]] { + val in: Inlet[ParseEvent] = Inlet("XMLWriter.in") + val out: Outlet[ByteString] = Outlet("XMLWriter.out") + override val shape: FlowShape[ParseEvent, ByteString] = FlowShape(in, out) + + private val xMLOutputFactory = XMLOutputFactory.newInstance() + + override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = + new GraphStageLogic(shape) with InHandler with OutHandler { + val byteStringBuilder = new ByteStringBuilder() + + val output = xMLOutputFactory.createXMLStreamWriter(byteStringBuilder.asOutputStream, charset.name()) + + setHandlers(in, out, this) + + override def onPush(): Unit = { + val ev: ParseEvent = grab(in) + ev match { + case StartDocument => + output.writeStartDocument() + + case EndDocument => + output.writeEndDocument() + + case StartElement(localName, attributes) => + output.writeStartElement(localName) + attributes.foreach(t => output.writeAttribute(t._1, t._2)) + + case EndElement(_) => + output.writeEndElement() + + case Characters(text) => + output.writeCharacters(text) + case ProcessingInstruction(Some(target), Some(data)) => + output.writeProcessingInstruction(target, data) + + case ProcessingInstruction(Some(target), None) => + output.writeProcessingInstruction(target) + + case ProcessingInstruction(None, Some(data)) => + output.writeProcessingInstruction(None.orNull, data) + case ProcessingInstruction(None, None) => + case Comment(text) => + output.writeComment(text) + + case CData(text) => + output.writeCData(text) + } + push(out, byteStringBuilder.result().compact) + byteStringBuilder.clear() + } + + override def onPull(): Unit = pull(in) + } + } + /** * Internal API */ diff --git a/xml/src/main/scala/akka/stream/alpakka/xml/javadsl/XmlParsing.scala b/xml/src/main/scala/akka/stream/alpakka/xml/javadsl/XmlParsing.scala index 0d2b3a9032..e883f269eb 100644 --- a/xml/src/main/scala/akka/stream/alpakka/xml/javadsl/XmlParsing.scala +++ b/xml/src/main/scala/akka/stream/alpakka/xml/javadsl/XmlParsing.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.xml.javadsl import akka.NotUsed diff --git a/xml/src/main/scala/akka/stream/alpakka/xml/javadsl/XmlWriting.scala b/xml/src/main/scala/akka/stream/alpakka/xml/javadsl/XmlWriting.scala new file mode 100644 index 0000000000..c7910a52af --- /dev/null +++ b/xml/src/main/scala/akka/stream/alpakka/xml/javadsl/XmlWriting.scala @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.xml.javadsl + +import java.nio.charset.{Charset, StandardCharsets} + +import akka.NotUsed +import akka.stream.alpakka.xml.ParseEvent +import akka.stream.alpakka.xml.Xml.StreamingXmlWriter +import akka.stream.scaladsl.Flow +import akka.util.ByteString + +object XmlWriting { + + /** + * Writer Flow that takes a stream of XML events similar to SAX and write ByteStrings. + * encoding UTF-8 + */ + def writer(): akka.stream.javadsl.Flow[ParseEvent, ByteString, NotUsed] = + Flow.fromGraph(new StreamingXmlWriter(StandardCharsets.UTF_8)).asJava + + /** + * Writer Flow that takes a stream of XML events similar to SAX and write ByteStrings. + * @param strEncoding encoding of the stream + */ + def writer(charset: Charset): akka.stream.javadsl.Flow[ParseEvent, ByteString, NotUsed] = + Flow.fromGraph(new StreamingXmlWriter(charset)).asJava + +} diff --git a/xml/src/main/scala/akka/stream/alpakka/xml/scaladsl/XmlParsing.scala b/xml/src/main/scala/akka/stream/alpakka/xml/scaladsl/XmlParsing.scala index c80cbf76a8..6ca891fd5f 100644 --- a/xml/src/main/scala/akka/stream/alpakka/xml/scaladsl/XmlParsing.scala +++ b/xml/src/main/scala/akka/stream/alpakka/xml/scaladsl/XmlParsing.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.xml.scaladsl import akka.NotUsed diff --git a/xml/src/main/scala/akka/stream/alpakka/xml/scaladsl/XmlWriting.scala b/xml/src/main/scala/akka/stream/alpakka/xml/scaladsl/XmlWriting.scala new file mode 100644 index 0000000000..9f497b546a --- /dev/null +++ b/xml/src/main/scala/akka/stream/alpakka/xml/scaladsl/XmlWriting.scala @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.xml.scaladsl + +import java.nio.charset.{Charset, StandardCharsets} + +import akka.NotUsed +import akka.stream.alpakka.xml.ParseEvent +import akka.stream.alpakka.xml.Xml.StreamingXmlWriter +import akka.stream.scaladsl.Flow +import akka.util.ByteString + +object XmlWriting { + + /** + * Writer Flow that takes a stream of XML events similar to SAX and write ByteStrings. + * @param charset charset of encoding + */ + def writer(charset: Charset): Flow[ParseEvent, ByteString, NotUsed] = + Flow.fromGraph(new StreamingXmlWriter(charset)) + + /** + * Writer Flow that takes a stream of XML events similar to SAX and write ByteStrings. + * encoding UTF-8 + */ + val writer: Flow[ParseEvent, ByteString, NotUsed] = writer(StandardCharsets.UTF_8) +} diff --git a/xml/src/test/java/akka/stream/alpakka/xml/javadsl/XmlParsingTest.java b/xml/src/test/java/akka/stream/alpakka/xml/javadsl/XmlParsingTest.java index ec5db1ce74..f0ccf996c1 100644 --- a/xml/src/test/java/akka/stream/alpakka/xml/javadsl/XmlParsingTest.java +++ b/xml/src/test/java/akka/stream/alpakka/xml/javadsl/XmlParsingTest.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.xml.javadsl; import akka.actor.ActorSystem; diff --git a/xml/src/test/java/akka/stream/alpakka/xml/javadsl/XmlWritingTest.java b/xml/src/test/java/akka/stream/alpakka/xml/javadsl/XmlWritingTest.java new file mode 100644 index 0000000000..90d027fec1 --- /dev/null +++ b/xml/src/test/java/akka/stream/alpakka/xml/javadsl/XmlWritingTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.xml.javadsl; + +import akka.actor.ActorSystem; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.alpakka.xml.*; +import akka.stream.javadsl.Flow; +import akka.stream.javadsl.Keep; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.testkit.JavaTestKit; +import akka.util.ByteString; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static org.junit.Assert.assertEquals; + +public class XmlWritingTest { + private static ActorSystem system; + private static Materializer materializer; + + @Test + public void xmlWriter() throws InterruptedException, ExecutionException, TimeoutException { + + // #writer + final Sink> write = Flow.of(ParseEvent.class) + .via(XmlWriting.writer()) + .map((ByteString bs) -> bs.utf8String()) + .toMat(Sink.fold("", (acc, el) -> acc + el), Keep.right()); + // #writer + + // #writer-usage + final String doc = "elem1elem2"; + final List docList= new ArrayList(); + docList.add(StartDocument.getInstance()); + docList.add(StartElement.create("doc", Collections.emptyMap())); + docList.add(StartElement.create("elem", Collections.emptyMap())); + docList.add(Characters.create("elem1")); + docList.add(EndElement.create("elem")); + docList.add(StartElement.create("elem", Collections.emptyMap())); + docList.add(Characters.create("elem2")); + docList.add(EndElement.create("elem")); + docList.add(EndElement.create("doc")); + docList.add(EndDocument.getInstance()); + + + final CompletionStage resultStage = Source.from(docList).runWith(write, materializer); + // #writer-usage + + resultStage.thenAccept((str) -> { + assertEquals(doc,str); + }).toCompletableFuture().get(5, TimeUnit.SECONDS); + } + + @BeforeClass + public static void setup() throws Exception { + system = ActorSystem.create(); + materializer = ActorMaterializer.create(system); + } + + @AfterClass + public static void teardown() throws Exception { + JavaTestKit.shutdownActorSystem(system); + } +} diff --git a/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlCoalesceTest.scala b/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlCoalesceTest.scala index 78fe4cd3fd..db9cbe90d7 100644 --- a/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlCoalesceTest.scala +++ b/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlCoalesceTest.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.xml.scaladsl import akka.actor.ActorSystem diff --git a/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlProcessingTest.scala b/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlProcessingTest.scala index 6177ab70e9..f61c5dde9b 100644 --- a/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlProcessingTest.scala +++ b/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlProcessingTest.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.xml.scaladsl import akka.actor.ActorSystem diff --git a/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlSubsliceTest.scala b/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlSubsliceTest.scala index e5b69b5e0a..13504a7d3f 100644 --- a/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlSubsliceTest.scala +++ b/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlSubsliceTest.scala @@ -1,6 +1,7 @@ /* * Copyright (C) 2016-2017 Lightbend Inc. */ + package akka.stream.alpakka.xml.scaladsl import akka.actor.ActorSystem diff --git a/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlWritingTest.scala b/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlWritingTest.scala new file mode 100644 index 0000000000..f6defbbed7 --- /dev/null +++ b/xml/src/test/scala/akka/stream/alpakka/xml/scaladsl/XmlWritingTest.scala @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2016-2017 Lightbend Inc. + */ + +package akka.stream.alpakka.xml.scaladsl + +import akka.actor.ActorSystem +import akka.stream.ActorMaterializer +import akka.stream.alpakka.xml._ +import akka.stream.scaladsl.{Flow, Keep, Sink, Source} +import org.scalatest.concurrent.PatienceConfiguration.Timeout +import org.scalatest.concurrent.ScalaFutures +import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpec} + +import scala.concurrent.Future +import scala.concurrent.duration._ + +class XmlWritingTest extends WordSpec with Matchers with BeforeAndAfterAll with ScalaFutures { + implicit val system = ActorSystem("Test") + implicit val mat = ActorMaterializer() + + // #writer + val writer: Sink[ParseEvent, Future[String]] = Flow[ParseEvent] + .via(XmlWriting.writer) + .map[String](_.utf8String) + .toMat(Sink.fold[String, String]("")((t, u) => t + u))(Keep.right) + // #writer + + "XML Writer" must { + + "properly write simple XML" in { + // #writer-usage + val listEl: List[ParseEvent] = List( + StartDocument, + StartElement("doc", Map.empty), + StartElement("elem", Map.empty), + Characters("elem1"), + EndElement("elem"), + StartElement("elem", Map.empty), + Characters("elem2"), + EndElement("elem"), + EndElement("doc"), + EndDocument + ) + + val doc = "elem1elem2" + val resultFuture: Future[String] = Source.fromIterator[ParseEvent](() => listEl.iterator).runWith(writer) + // #writer-usage + + resultFuture.futureValue(Timeout(20.seconds)) should ===(doc) + } + + "properly process a comment" in { + val doc = "" + val listEl = List( + StartDocument, + StartElement("doc", Map.empty), + Comment("comment"), + EndElement("doc"), + EndDocument + ) + + val resultFuture: Future[String] = Source.fromIterator[ParseEvent](() => listEl.iterator).runWith(writer) + + resultFuture.futureValue(Timeout(20.seconds)) should ===(doc) + } + + "properly process parse instructions" in { + val doc = """""" + val listEl = List( + StartDocument, + ProcessingInstruction(Some("target"), Some("content")), + StartElement("doc", Map.empty), + EndElement("doc"), + EndDocument + ) + + val resultFuture: Future[String] = Source.fromIterator[ParseEvent](() => listEl.iterator).runWith(writer) + + resultFuture.futureValue(Timeout(20.seconds)) should ===(doc) + + } + + "properly process attributes" in { + val doc = + """elem1""" + val listEl = List( + StartDocument, + StartElement("doc", Map("good" -> "yes")), + StartElement("elem", Map("nice" -> "yes", "very" -> "true")), + Characters("elem1"), + EndElement("elem"), + EndElement("doc"), + EndDocument + ) + + val resultFuture: Future[String] = Source.fromIterator[ParseEvent](() => listEl.iterator).runWith(writer) + + resultFuture.futureValue(Timeout(3.seconds)) should ===(doc) + } + + "properly process CData blocks" in { + val doc = """even]]>""" + + val listEl = List( + StartDocument, + StartElement("doc", Map.empty), + CData("even"), + EndElement("doc"), + EndDocument + ) + val resultFuture: Future[String] = Source.fromIterator[ParseEvent](() => listEl.iterator).runWith(writer) + + resultFuture.futureValue(Timeout(3.seconds)) should ===(doc) + } + + } + + override protected def afterAll(): Unit = system.terminate() +}