├── src ├── test │ ├── resources │ │ ├── helloscala.txt │ │ ├── error404.html │ │ ├── langs.properties │ │ └── log4j.properties │ ├── keystores │ │ ├── client-keystore.jks │ │ ├── server-keystore.jks │ │ ├── client-truststore.jks │ │ ├── server-truststore.jks │ │ └── ssl.txt │ ├── scripts │ │ ├── VerticleScript.scala │ │ └── ScriptingTest.scala │ └── scala │ │ └── org │ │ └── vertx │ │ └── scala │ │ └── tests │ │ ├── core │ │ ├── http │ │ │ ├── HttpTest.scala │ │ │ ├── Compression.scala │ │ │ ├── HttpConfigurationTest.scala │ │ │ ├── HttpCompressionTest.scala │ │ │ └── WebSocketsTest.scala │ │ ├── eventbus │ │ │ └── EventBusBridgeTest.scala │ │ └── streams │ │ │ └── PumpTest.scala │ │ ├── lang │ │ ├── ScalaScriptingTest.scala │ │ ├── VerticleClass.scala │ │ ├── UnsupportedVerticleClass.scala │ │ └── ScalaInterpreterTest.scala │ │ ├── router │ │ ├── AuthRouter.scala │ │ ├── JsonRouter.scala │ │ ├── RouterTestHelper.scala │ │ ├── RouterAuthTest.scala │ │ └── JsonRouterTest.scala │ │ ├── plattform │ │ └── impl │ │ │ ├── ScalaVerticleFactoryTest.scala │ │ │ └── SystemPropertyDefaultLangOverrideTest.scala │ │ ├── util │ │ └── TestUtils.scala │ │ └── mods │ │ └── TestBusMod.scala └── main │ ├── scala │ └── org │ │ └── vertx │ │ └── scala │ │ ├── router │ │ ├── RouterException.scala │ │ └── routing │ │ │ └── routing.scala │ │ ├── core │ │ ├── VertxAccess.scala │ │ ├── dns │ │ │ ├── DnsException.scala │ │ │ ├── MxRecord.scala │ │ │ ├── SrvRecord.scala │ │ │ └── DnsResponseCode.scala │ │ ├── datagram │ │ │ ├── package.scala │ │ │ ├── InternetProtocolFamily.scala │ │ │ └── DatagramPacket.scala │ │ ├── streams │ │ │ ├── ReadSupport.scala │ │ │ ├── ExceptionSupport.scala │ │ │ ├── ReadStream.scala │ │ │ ├── DrainSupport.scala │ │ │ ├── WriteStream.scala │ │ │ └── Pump.scala │ │ ├── eventbus │ │ │ ├── SendOrPublish.scala │ │ │ ├── RegisteredHandler.scala │ │ │ └── Message.scala │ │ ├── json │ │ │ └── package.scala │ │ ├── package.scala │ │ ├── http │ │ │ ├── WebSocket.scala │ │ │ ├── HttpServerFileUpload.scala │ │ │ ├── ServerWebSocket.scala │ │ │ ├── WebSocketBase.scala │ │ │ ├── package.scala │ │ │ ├── HttpClientResponse.scala │ │ │ └── RouteMatcher.scala │ │ ├── ServerTCPSupport.scala │ │ ├── Closeable.scala │ │ ├── ClientSSLSupport.scala │ │ ├── ServerSSLSupport.scala │ │ ├── file │ │ │ ├── FileSystemProps.scala │ │ │ ├── FileProps.scala │ │ │ └── AsyncFile.scala │ │ ├── VertxExecutionContext.scala │ │ ├── logging │ │ │ └── Logger.scala │ │ ├── NetworkSupport.scala │ │ ├── SSLSupport.scala │ │ ├── TCPSupport.scala │ │ ├── buffer │ │ │ └── package.scala │ │ ├── sockjs │ │ │ ├── SockJSSocket.scala │ │ │ └── EventBusBridgeHook.scala │ │ ├── FunctionConverters.scala │ │ ├── parsetools │ │ │ └── RecordParser.scala │ │ ├── shareddata │ │ │ └── SharedData.scala │ │ └── net │ │ │ ├── NetServer.scala │ │ │ ├── NetSocket.scala │ │ │ └── NetClient.scala │ │ ├── mods │ │ ├── UnknownActionException.scala │ │ ├── BusModException.scala │ │ └── replies │ │ │ └── busmodreplies.scala │ │ ├── FutureOps.scala │ │ ├── Self.scala │ │ ├── AsJava.scala │ │ ├── lang │ │ ├── ClassLoaders.scala │ │ └── ScalaInterpreter.scala │ │ ├── testtools │ │ ├── ScalaClassRunner.java │ │ └── TestVerticle.scala │ │ └── platform │ │ ├── impl │ │ └── ScalaVerticle.scala │ │ ├── Verticle.scala │ │ └── Container.scala │ └── resources │ └── mod.json ├── .travis.yml ├── .gitignore ├── README.asciidoc └── ADMIN.md /src/test/resources/helloscala.txt: -------------------------------------------------------------------------------- 1 | Hello Scala (sendFile)! -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk7 4 | - openjdk7 5 | -------------------------------------------------------------------------------- /src/test/keystores/client-keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vert-x/mod-lang-scala/HEAD/src/test/keystores/client-keystore.jks -------------------------------------------------------------------------------- /src/test/keystores/server-keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vert-x/mod-lang-scala/HEAD/src/test/keystores/server-keystore.jks -------------------------------------------------------------------------------- /src/test/keystores/client-truststore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vert-x/mod-lang-scala/HEAD/src/test/keystores/client-truststore.jks -------------------------------------------------------------------------------- /src/test/keystores/server-truststore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vert-x/mod-lang-scala/HEAD/src/test/keystores/server-truststore.jks -------------------------------------------------------------------------------- /src/test/resources/error404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
24 | * Instances of this class are not thread-safe
25 | *
26 | * @author Tim Fox
27 | * @author swilliams
28 | * @author Galder Zamarreño
29 | * @author Joern Bernhardt
30 | */
31 | final class WebSocket private[scala] (val asJava: JWebSocket) extends Self
32 | with WebSocketBase {
33 |
34 | override type J = JWebSocket
35 |
36 | }
37 |
38 | /** Factory for [[org.vertx.scala.core.http.WebSocket]] instances. */
39 | object WebSocket {
40 | def apply(jsocket: JWebSocket) = new WebSocket(jsocket)
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/ServerTCPSupport.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core
17 |
18 | import org.vertx.java.core.{ ServerTCPSupport => JServerTCPSupport }
19 | import org.vertx.scala.Self
20 |
21 | /**
22 | * Supports [[org.vertx.java.core.ServerTCPSupport]] functionality.
23 | *
24 | * @author Joern Bernhardt
25 | * @author Galder Zamarreño
26 | */
27 | trait ServerTCPSupport extends Self
28 | with TCPSupport {
29 |
30 | override type J <: JServerTCPSupport[_]
31 |
32 | /**
33 | * Set the accept backlog
34 | * @return a reference to this so multiple method calls can be chained together
35 | */
36 | def setAcceptBacklog(backlog: Int): this.type = wrap(asJava.setAcceptBacklog(backlog))
37 |
38 | /**
39 | *
40 | * @return The accept backlog
41 | */
42 | def getAcceptBacklog: Int = asJava.getAcceptBacklog
43 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/lang/ClassLoaders.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.lang
17 |
18 | import scala.util.Try
19 |
20 | /**
21 | * Class loading utility class.
22 | *
23 | * @author Galder Zamarreño
24 | */
25 | object ClassLoaders {
26 |
27 | /**
28 | * Instantiates the given class name using the classloader provided
29 | * @param className String containing the class name to instantiate
30 | * @param classLoader where to find the given class name
31 | * @tparam T type of instance expected back
32 | * @return [[scala.util.Success]] containing a new instance of the given
33 | * class or [[scala.util.Failure]] with any errors reported
34 | */
35 | def newInstance[T](className: String, classLoader: ClassLoader): Try[T] = {
36 | Try {
37 | val clazz = classLoader.loadClass(className)
38 | clazz.newInstance().asInstanceOf[T]
39 | }
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/dns/MxRecord.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.dns
17 |
18 | import org.vertx.java.core.dns.{ MxRecord => JMxRecord }
19 |
20 | /**
21 | * Represent a Mail-Exchange-Record (MX) which was resolved for a domain.
22 | *
23 | * @author Norman Maurer
24 | * @author Joern Bernhardt
25 | * @author Galder Zamarreño
26 | */
27 | final class MxRecord private[scala] (val asJava: JMxRecord) extends AnyVal {
28 |
29 | /**
30 | * The priority of the MX record.
31 | */
32 | def priority(): Int = asJava.priority()
33 |
34 | /**
35 | * The name of the MX record
36 | */
37 | def name(): String = asJava.name()
38 |
39 | }
40 |
41 | /** Factory for [[org.vertx.scala.core.dns.MxRecord]] instances. */
42 | object MxRecord {
43 | def apply(internal: JMxRecord) = new MxRecord(internal)
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/testtools/ScalaClassRunner.java:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.testtools;
2 |
3 | import org.junit.runners.model.FrameworkMethod;
4 | import org.junit.runners.model.InitializationError;
5 | import org.junit.runners.model.TestClass;
6 | import org.vertx.testtools.JavaClassRunner;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * Scala class runner. This class used to be a Scala class, but due to the lack
12 | * of support for SBT project detection in JavaClassRunner, a static
13 | * initialization is needed to set the correct value for -Dvertx.mods system
14 | * property before super() constructor executes.
15 | */
16 | public class ScalaClassRunner extends JavaClassRunner {
17 |
18 | static {
19 | if (System.getProperty("vertx.mods") == null) {
20 | // JavaClassRunner can currently only detect gradle/maven projects,
21 | // so force SBT expectations when it comes to modules location
22 | // if not pre-configured.
23 | System.setProperty("vertx.mods", "target/mods");
24 | }
25 | }
26 |
27 | public ScalaClassRunner(Class> clazz) throws InitializationError {
28 | super(clazz);
29 | }
30 |
31 | @Override
32 | protected List
41 | * Use this with caution as you may be exposed to "main in the middle" attacks
42 | * @param trustAll Set to true if you want to trust all server certificates
43 | */
44 | def setTrustAll(trustAll: Boolean): this.type = wrap(asJava.setTrustAll(trustAll))
45 |
46 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/ServerSSLSupport.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core
17 |
18 | import org.vertx.java.core.{ ServerSSLSupport => JServerSSLSupport }
19 | import org.vertx.scala.Self
20 |
21 | /**
22 | * Supports [[org.vertx.java.core.ServerSSLSupport]] functionality.
23 | *
24 | * @author Joern Bernhardt
25 | * @author Galder Zamarreño
26 | */
27 | trait ServerSSLSupport extends Self
28 | with SSLSupport {
29 |
30 | override type J <: JServerSSLSupport[_]
31 |
32 | /**
33 | * Is client auth required?
34 | */
35 | def isClientAuthRequired: Boolean = asJava.isClientAuthRequired
36 |
37 | /**
38 | * Set `required` to true if you want the server to request client authentication from any connecting clients. This
39 | * is an extra level of security in SSL, and requires clients to provide client certificates. Those certificates must be added
40 | * to the server trust store.
41 | * @return A reference to this, so multiple invocations can be chained together.
42 | */
43 | def setClientAuthRequired(required: Boolean): this.type = wrap(asJava.setClientAuthRequired(required))
44 |
45 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/datagram/DatagramPacket.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.datagram
17 |
18 | import org.vertx.java.core.datagram.{ DatagramPacket => JDatagramPacket }
19 | import java.net.InetSocketAddress
20 | import org.vertx.scala.core.buffer.Buffer
21 |
22 | /**
23 | * A received Datagram packet (UDP) which contains the data and information about the sender of the data itself.
24 | *
25 | * @author Norman Maurer
26 | * @author Galder Zamarreño
27 | */
28 | final class DatagramPacket private[scala] (val asJava: JDatagramPacket) extends AnyVal {
29 |
30 | /**
31 | * Returns the [[java.net.InetSocketAddress]] of the sender that send this
32 | * [[org.vertx.scala.core.datagram.DatagramPacket]].
33 | */
34 | def sender(): InetSocketAddress = asJava.sender()
35 |
36 | /**
37 | * Returns the data of the [[org.vertx.scala.core.datagram.DatagramPacket]]
38 | */
39 | def data(): Buffer = Buffer(asJava.data())
40 |
41 | }
42 |
43 | /** Factory for [[org.vertx.scala.core.datagram.DatagramPacket]] instances. */
44 | object DatagramPacket {
45 | def apply(actual: JDatagramPacket) = new DatagramPacket(actual)
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/router/JsonRouter.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.tests.router
2 |
3 | import org.vertx.scala.router.{RouterException, Router}
4 | import org.vertx.scala.core.http.{HttpServer, HttpServerRequest}
5 | import org.vertx.scala.core.FunctionConverters._
6 | import org.vertx.scala.router.routing._
7 | import org.vertx.scala.platform.Verticle
8 | import scala.concurrent.Promise
9 | import scala.util.{Try, Failure, Success}
10 | import org.vertx.scala.core.json.Json
11 | import scala.util.matching.Regex
12 |
13 | /**
14 | * @author Joern Bernhardt
15 | */
16 | class JsonRouter extends Verticle with Router {
17 |
18 | override def start(p: Promise[Unit]) = {
19 | vertx.createHttpServer().requestHandler(this).listen(8080, {
20 | case Success(s) => p.success()
21 | case Failure(x) => p.failure(x)
22 | }: Try[HttpServer] => Unit)
23 | }
24 |
25 | override def notFoundFile = "error404.html"
26 |
27 | val IdMatcher = "/get/(\\d+)".r
28 |
29 | override def routes(implicit req: HttpServerRequest): Routing = {
30 | case Get("/") => SendFile("helloscala.txt")
31 | case Get("/test.txt") => SendFile("helloscala.txt")
32 | case Get("/not-found") => SendFile("not-existing.txt")
33 | case Get("/cookies1") => SetCookie("a", "1", Ok(Json.obj()))
34 | case Get("/cookies2") => SetCookie("a", "1", SetCookie("b", "2", Ok(Json.obj())))
35 | case Get(IdMatcher(id)) => Ok(Json.obj("result" -> id))
36 | case Post("/") => Ok(Json.obj("status" -> "ok"))
37 | case Post("/post-ok") => Ok(Json.obj("status" -> "ok"))
38 | case Head("/head") => Header("x-custom-head", "hello", NoBody)
39 | case Delete("/forbidden") => Error(RouterException(message = "not authorized", statusCode = 403))
40 | case All("/all-test") => SendFile("helloscala.txt")
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/file/FileSystemProps.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.file
17 |
18 | import org.vertx.java.core.file.{ FileSystemProps => JFileSystemProps }
19 |
20 | /**
21 | * Represents properties of the file system.
22 | * Instances of FileSystemProps are thread-safe.
23 | *
24 | * @author Tim Fox
25 | * @author Joern Bernhardt
26 | * @author Galder Zamarreño
27 | */
28 | final class FileSystemProps private[scala] (val asJava: JFileSystemProps) extends AnyVal {
29 |
30 | /**
31 | * The total space on the file system, in bytes
32 | */
33 | def totalSpace(): Long = asJava.totalSpace()
34 |
35 | /**
36 | * The total un-allocated space on the file system, in bytes
37 | */
38 | def unallocatedSpace(): Long = asJava.unallocatedSpace()
39 |
40 | /**
41 | * The total usable space on the file system, in bytes
42 | */
43 | def usableSpace(): Long = asJava.usableSpace()
44 |
45 | }
46 |
47 | /** Factory for [[org.vertx.scala.core.file.FileSystemProps]] instances. */
48 | object FileSystemProps {
49 | def apply(internal: JFileSystemProps) = new FileSystemProps(internal)
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/mods/replies/busmodreplies.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.mods.replies
17 |
18 | import org.vertx.scala.core.json._
19 | import scala.concurrent.Future
20 | import org.vertx.scala.mods.ScalaBusMod._
21 |
22 | sealed trait BusModReceiveEnd
23 | sealed trait BusModReply extends BusModReceiveEnd
24 |
25 | case class AsyncReply(replyWhenDone: Future[BusModReply]) extends BusModReply
26 |
27 | sealed trait ReplyReceiver {
28 | val handler: Receive
29 | }
30 | case class Receiver(handler: Receive) extends ReplyReceiver
31 | case class ReceiverWithTimeout(handler: Receive, timeout: Long, timeoutHandler: () => Unit) extends ReplyReceiver
32 |
33 | sealed trait SyncReply extends BusModReply {
34 | val replyHandler: Option[ReplyReceiver]
35 | def toJson: JsonObject
36 | }
37 | case class Ok(x: JsonObject = Json.obj(), replyHandler: Option[ReplyReceiver] = None) extends SyncReply {
38 | def toJson = x.putString("status", "ok")
39 | }
40 |
41 | case class Error(message: String, id: String = "MODULE_EXCEPTION", obj: JsonObject = Json.obj(), replyHandler: Option[ReplyReceiver] = None) extends SyncReply {
42 | def toJson = Json.obj("status" -> "error", "message" -> message, "error" -> id).mergeIn(obj)
43 | }
44 |
45 | case object NoReply extends BusModReceiveEnd
46 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/VertxExecutionContext.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core
17 |
18 | import scala.concurrent.ExecutionContext
19 | import org.vertx.scala.core.logging.Logger
20 |
21 | /**
22 | * Vert.x Scala execution context
23 | *
24 | * @author Joern Bernhardt
25 | * @author Galder Zamarreño
26 | */
27 | object VertxExecutionContext {
28 |
29 | /**
30 | * Vert.x execution context for use in verticles extending [[VertxAccess]]
31 | * trait. Scala verticles do extend this trait to facilitate access to
32 | * internal components.
33 | */
34 | def fromVertxAccess(vertxAccess: VertxAccess): ExecutionContext =
35 | new VertxExecutionContextImpl(vertxAccess.vertx, vertxAccess.logger)
36 |
37 | /**
38 | * Vert.x execution context for situations where verticles are written in
39 | * other languages except Scala, where there's no access to [[VertxAccess]],
40 | * but access to [[Logger]] and [[Vertx]] class instances are available.
41 | */
42 | def fromVertx(vertx: => Vertx, logger: => Logger): ExecutionContext =
43 | new VertxExecutionContextImpl(vertx, logger)
44 |
45 | private final class VertxExecutionContextImpl(vertx: => Vertx, logger: => Logger) extends ExecutionContext {
46 | override def reportFailure(t: Throwable): Unit =
47 | logger.error("Error executing Future in VertxExecutionContext", t)
48 | override def execute(runnable: Runnable): Unit =
49 | runnable.run()
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/router/RouterTestHelper.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.tests.router
2 |
3 | import org.vertx.scala.FutureOps
4 | import org.vertx.scala.core.http.{HttpClientRequest, HttpClientResponse}
5 | import org.vertx.testtools.VertxAssert._
6 | import scala.concurrent.{Promise, Future}
7 | import FutureOps._
8 | import org.vertx.scala.testtools.TestVerticle
9 |
10 | /**
11 | * @author Joern Bernhardt
12 | */
13 | trait RouterTestHelper extends TestVerticle {
14 |
15 | protected def error404FileContents(): String =
16 | vertx.fileSystem.readFileSync("error404.html").toString("UTF-8")
17 |
18 | protected def testFileContents(): String =
19 | vertx.fileSystem.readFileSync("helloscala.txt").toString("UTF-8")
20 |
21 | protected def bodyOkCompleter[B](fn: String => B): HttpClientResponse => Unit = { res: HttpClientResponse =>
22 | assertEquals(200, res.statusCode())
23 | checkBody(fn)(res)
24 | }
25 |
26 | protected def checkBody[B](fn: String => B): HttpClientResponse => Unit = { res: HttpClientResponse =>
27 | res.bodyHandler { body =>
28 | logger.info("in checkBody test")
29 | fn(body.toString("UTF-8"))
30 | testComplete()
31 | }
32 | logger.info("set checkBody test")
33 | }
34 |
35 | protected def doHttp(method: String, uri: String): Future[HttpClientResponse] = {
36 | doHttpInternal(method, uri) { _ =>}
37 | }
38 |
39 | protected def doAuthedHttp(method: String, uri: String): Future[HttpClientResponse] = {
40 | doHttpInternal(method, uri) { request =>
41 | request.putHeader("X-XSRF-TOKEN", "secret")
42 | }
43 | }
44 |
45 | protected def doHttpInternal(method: String, uri: String)(fn: HttpClientRequest => Unit):
46 | Future[HttpClientResponse] = futurify {
47 | p: Promise[HttpClientResponse] =>
48 | val request = vertx.createHttpClient()
49 | .setPort(8080)
50 | .request(method, uri, { res =>
51 | p.success(res)
52 | })
53 | fn(request)
54 | request.end()
55 | }
56 |
57 | }
58 |
59 | object RouterTestHelper {
60 | def customAuthExceptionMessage(): String = "i'm a teapot."
61 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/dns/SrvRecord.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.dns
17 |
18 | import org.vertx.java.core.dns.{ SrvRecord => JSrvRecord }
19 |
20 | /**
21 | * Represent a Service-Record (SRV) which was resolved for a domain.
22 | *
23 | * @author Norman Maurer
24 | * @author Joern Bernhardt
25 | */
26 | final class SrvRecord private[scala] (val asJava: JSrvRecord) extends AnyVal {
27 |
28 | /**
29 | * Returns the priority for this service record.
30 | */
31 | def priority(): Int = asJava.priority()
32 |
33 | /**
34 | * Returns the weight of this service record.
35 | */
36 | def weight(): Int = asJava.weight()
37 |
38 | /**
39 | * Returns the port the service is running on.
40 | */
41 | def port(): Int = asJava.port()
42 |
43 | /**
44 | * Returns the name for the server being queried.
45 | */
46 | def name(): String = asJava.name()
47 |
48 | /**
49 | * Returns the protocol for the service being queried (i.e. "_tcp").
50 | */
51 | def protocol(): String = asJava.protocol()
52 |
53 | /**
54 | * Returns the service's name (i.e. "_http").
55 | */
56 | def service(): String = asJava.service()
57 |
58 | /**
59 | * Returns the name of the host for the service.
60 | */
61 | def target(): String = asJava.target()
62 | }
63 |
64 | /** Factory for [[org.vertx.scala.core.dns.SrvRecord]] instances. */
65 | object SrvRecord {
66 | def apply(internal: JSrvRecord) = new SrvRecord(internal)
67 | }
68 |
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/core/eventbus/EventBusBridgeTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.tests.core.eventbus
17 |
18 | import org.vertx.scala.testtools.TestVerticle
19 | import org.vertx.scala.core.json.Json
20 | import org.vertx.testtools.VertxAssert._
21 | import org.junit.Test
22 |
23 | class EventBusBridgeTest extends TestVerticle {
24 |
25 | @Test
26 | def letAllThroughBridge(): Unit = {
27 | val server = vertx.createHttpServer()
28 |
29 | val permitted = Json.arr()
30 | permitted.add(Json.obj()) // Let everything through
31 |
32 | val sockJSServer = vertx.createSockJSServer(server)
33 | sockJSServer.bridge(Json.obj("prefix" -> "/eventbus"), permitted, permitted)
34 |
35 | server.listen(8080, result => {
36 | assertThread()
37 | def client = vertx.createHttpClient().setPort(8080)
38 | // We use rawwebsocket transport
39 | client.connectWebsocket("/eventbus/websocket", websocket => {
40 | assertThread()
41 | // Register
42 | val msg = Json.obj("type" -> "register", "address" -> "someaddress")
43 | websocket.writeTextFrame(msg.encode())
44 |
45 | // Send
46 | val msg2 = Json.obj("type" -> "send", "address" -> "someaddress", "body" -> "hello world")
47 | websocket.writeTextFrame(msg2.encode())
48 |
49 | websocket.dataHandler { buffer =>
50 | assertThread()
51 | val msg = buffer.toString()
52 | val received = Json.fromObjectString(msg)
53 | assert(received.getString("body").equals("hello world"))
54 | testComplete()
55 | }
56 | })
57 | })
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/streams/ReadStream.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.core.streams
18 |
19 | import org.vertx.java.core.streams.{ ReadStream => JReadStream }
20 | import org.vertx.java.core.streams.{ ExceptionSupport => JExceptionSupport }
21 | import org.vertx.scala.core.buffer._
22 | import org.vertx.scala.{Self, AsJava}
23 | import org.vertx.scala.core.FunctionConverters._
24 |
25 | /**
26 | * Represents a stream of data that can be read from.
27 | * Any class that implements this interface can be used by a [[org.vertx.scala.core.streams.Pump]]
28 | * to pump data from it to a [[org.vertx.scala.core.streams.WriteStream]].
29 | * This interface exposes a fluent api and the type T represents the type of the object that implements
30 | * the interface to allow method chaining
31 | *
32 | * @author Tim Fox
33 | * @author swilliams
34 | * @author Joern Bernhardt
35 | * @author Galder Zamarreño
36 | */
37 | trait ReadStream extends Self
38 | with ReadSupport[Buffer]
39 | with AsJava {
40 |
41 | override type J <: JReadStream[_] with JExceptionSupport[_]
42 |
43 | /**
44 | * Set an end handler. Once the stream has ended, and there is no more data
45 | * to be read, this handler will be called.
46 | */
47 | def endHandler(handler: => Unit): this.type = wrap(asJava.endHandler(lazyToVoidHandler(handler)))
48 |
49 | /**
50 | * Set a data handler. As data is read, the handler will be called with the data.
51 | */
52 | override def dataHandler(handler: Buffer => Unit): this.type = wrap(asJava.dataHandler(bufferHandlerToJava(handler)))
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/http/HttpServerFileUpload.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.http
17 |
18 | import org.vertx.java.core.http.{ HttpServerFileUpload => JHttpServerFileUpload }
19 | import java.nio.charset.Charset
20 | import org.vertx.scala.Self
21 | import org.vertx.scala.core.streams.ReadStream
22 |
23 | /**
24 | * @author Galder Zamarreño
25 | */
26 | final class HttpServerFileUpload private[scala] (val asJava: JHttpServerFileUpload) extends Self
27 | with ReadStream {
28 |
29 | override type J = JHttpServerFileUpload
30 |
31 | /**
32 | * Stream the content of this upload to the given filename.
33 | */
34 | def streamToFileSystem(filename: String): HttpServerFileUpload =
35 | wrap(asJava.streamToFileSystem(filename))
36 |
37 | /**
38 | * Returns the filename which was used when upload the file.
39 | */
40 | def filename(): String = asJava.filename()
41 |
42 | /**
43 | * Returns the name of the attribute
44 | */
45 | def name(): String = asJava.name()
46 |
47 | /**
48 | * Returns the contentType for the upload
49 | */
50 | def contentType(): String = asJava.contentType()
51 |
52 | /**
53 | * Returns the contentTransferEncoding for the upload
54 | */
55 | def contentTransferEncoding(): String = asJava.contentTransferEncoding()
56 |
57 | /**
58 | * Returns the charset for the upload
59 | */
60 | def charset(): Charset = asJava.charset()
61 |
62 | /**
63 | * Returns the size of the upload (in bytes)
64 | */
65 | def size(): Long = asJava.size()
66 |
67 | }
68 |
69 | object HttpServerFileUpload {
70 | def apply(internal: JHttpServerFileUpload) = new HttpServerFileUpload(internal)
71 | }
72 |
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/router/RouterAuthTest.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.tests.router
2 |
3 | import org.vertx.scala.FutureOps
4 |
5 | import scala.concurrent.{ExecutionContext, Promise, Future}
6 | import FutureOps._
7 | import org.vertx.scala.core.FunctionConverters._
8 | import scala.util.Try
9 | import org.junit.Test
10 | import org.vertx.testtools.VertxAssert._
11 | import scala.util.Failure
12 | import scala.util.Success
13 | import org.vertx.scala.core.http.HttpClientResponse
14 |
15 | /**
16 | * @author Joern Bernhardt
17 | */
18 | class RouterAuthTest extends RouterTestHelper {
19 | override def asyncBefore(): Future[Unit] = futurify { p: Promise[Unit] =>
20 | container.deployVerticle("scala:org.vertx.scala.tests.router.AuthRouter", handler = {
21 | case Success(deployId) => p.success()
22 | case Failure(ex) => p.failure(ex)
23 | }: Try[String] => Unit)
24 | }
25 |
26 | @Test def unauthorizedGet(): Unit = doHttp("GET", "/member") map { res =>
27 | assertEquals("Should get a 401-UNAUTHORIZED status code", 401, res.statusCode())
28 | testComplete()
29 | }
30 |
31 | @Test def authorizedGet(): Unit = doAuthedHttp("GET", "/member") map bodyOkCompleter({ body =>
32 | assertEquals("Should receive the real test file contents", testFileContents(), body)
33 | })
34 |
35 | @Test def wrongAuthTokenGet(): Unit = doHttpInternal("GET", "/member") { req =>
36 | req.putHeader("X-XSRF-TOKEN", "wrong")
37 | } map { res: HttpClientResponse =>
38 | assertEquals("Should get a 401-UNAUTHORIZED status code", 401, res.statusCode())
39 | testComplete()
40 | }
41 |
42 | @Test def shouldGetOwnException(): Unit = doHttpInternal("GET", "/teapot") { req =>
43 | req.putHeader("X-XSRF-TOKEN", "whatever")
44 | } map { res =>
45 | res.bodyHandler { buffer =>
46 | assertEquals("Should get the customized auth message", RouterTestHelper.customAuthExceptionMessage(), buffer.toString("UTF-8"))
47 | logger.info("got right body")
48 | testComplete()
49 | }
50 | assertEquals("Should get a 418 status code", 418, res.statusCode())
51 | assertEquals("Should get a TEAPOT status message", "TEAPOT", res.statusMessage())
52 | vertx.setTimer(2000, { id =>
53 | fail("Test didn't handle the body -> broken!")
54 | })
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/core/http/HttpCompressionTest.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.tests.core.http
2 |
3 | import org.junit.Test
4 | import org.vertx.scala.tests.util.TestUtils._
5 | import org.vertx.testtools.VertxAssert._
6 |
7 | final class HttpCompressionTest extends HttpTestBase {
8 |
9 | val compression: Compression = Compressed
10 |
11 | @Test override def sendFile(): Unit = {
12 | val (file, content) = generateRandomContentFile("test-send-file.html", 10000)
13 | withClient(vertx.createHttpServer(), _.response().sendFile(file.getAbsolutePath)) { c =>
14 | c.getNow("some-uri", { res =>
15 | assertEquals(200, res.statusCode())
16 | assertTrue(res.headers().entryExists("content-type", _ == "text/html"))
17 | res.bodyHandler { buff =>
18 | assertEquals(content, buff.toString())
19 | file.delete()
20 | testComplete()
21 | }
22 | })
23 | }
24 | }
25 |
26 | @Test override def sendFileWithHandler(): Unit = {
27 | val (file, content) = generateRandomContentFile("test-send-file.html", 10000)
28 | var sendComplete = false
29 | withClient(vertx.createHttpServer(), _.response().sendFile(file.getAbsolutePath, { res =>
30 | sendComplete = true
31 | } )) { c =>
32 | c.getNow("some-uri", { res =>
33 | assertEquals(200, res.statusCode())
34 | assertTrue(res.headers().entryExists("content-type", _ == "text/html"))
35 | res.bodyHandler { buff =>
36 | assertEquals(content, buff.toString())
37 | file.delete()
38 | assertTrue(sendComplete)
39 | testComplete()
40 | }
41 | })
42 | }
43 | }
44 |
45 | @Test override def sendFileOverrideHeaders(): Unit = {
46 | val (file, content) = generateRandomContentFile("test-send-file.html", 10000)
47 | withClient(vertx.createHttpServer(),
48 | _.response().putHeader("Content-Type", "wibble").sendFile(file.getAbsolutePath)
49 | ) { c =>
50 | c.getNow("some-uri", { res =>
51 | assertEquals(200, res.statusCode())
52 | assertTrue(res.headers().entryExists("content-type", _ == "wibble"))
53 | res.bodyHandler { buff =>
54 | assertEquals(content, buff.toString())
55 | file.delete()
56 | testComplete()
57 | }
58 | })
59 | }
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/lang/ScalaInterpreterTest.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.tests.lang
2 |
3 | import java.io.{File, PrintWriter, StringWriter, Writer}
4 |
5 | import org.junit.Assert.fail
6 | import org.junit.Test
7 | import org.vertx.scala.lang.{ClassLoaders, ScalaInterpreter}
8 | import org.vertx.scala.platform.Verticle
9 | import org.vertx.scala.platform.impl.ScalaVerticle
10 | import org.vertx.scala.testtools.TestVerticle
11 | import org.vertx.testtools.VertxAssert._
12 |
13 | import scala.tools.nsc.Settings
14 | import scala.util.{Failure, Success}
15 |
16 | class ScalaInterpreterTest extends TestVerticle {
17 |
18 | @Test
19 | def runScriptTest(): Unit = {
20 | val path = new File("src/test/scripts/VerticleScript.scala").toURI.toURL
21 | val out = new StringWriter()
22 | val interpreter = createInterpreter(out)
23 | interpreter.runScript(path) match {
24 | case Success(s) =>
25 | assertHttpClientGetNow("Hello verticle script!")
26 | case Failure(ex) =>
27 | println(out.toString)
28 | fail(ex.toString)
29 | }
30 | }
31 |
32 | @Test
33 | def runClassTest(): Unit = {
34 | val filePath = "src/test/scala/org/vertx/scala/tests/lang/VerticleClass.scala"
35 | val out = new StringWriter()
36 | val interpreter = createInterpreter(out)
37 | val classLoader = interpreter.compileClass(new File(filePath))
38 | val className = "org.vertx.scala.tests.lang.VerticleClass"
39 | val delegate = ClassLoaders.newInstance[Verticle](className, classLoader.get)
40 | val verticle = ScalaVerticle.newVerticle(delegate.get, vertx, container)
41 | verticle.start()
42 | assertHttpClientGetNow("Hello verticle class!")
43 | }
44 |
45 | private def createInterpreter(out: Writer): ScalaInterpreter = {
46 | val settings = new Settings()
47 | settings.usejavacp.value = true
48 | settings.verbose.value = ScalaInterpreter.isVerbose
49 | new ScalaInterpreter(settings, vertx, container, new PrintWriter(out))
50 | }
51 |
52 | private def assertHttpClientGetNow(expected: String) {
53 | val client = vertx.createHttpClient().setPort(8080)
54 | client.getNow("/", { h =>
55 | assertThread()
56 | h.bodyHandler { data => {
57 | assertThread()
58 | assertEquals(expected, data.toString())
59 | testComplete()
60 | }
61 | }
62 | })
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/streams/DrainSupport.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.streams
17 |
18 | import org.vertx.java.core.streams.{ DrainSupport => JDrainSupport }
19 | import org.vertx.scala.{Self, AsJava}
20 | import org.vertx.scala.core.FunctionConverters._
21 |
22 | /**
23 | * Allows to set a `Handler` which is notified once the write queue is
24 | * drained again. This way you can stop writing once the write queue consumes
25 | * to much memory and so prevent an OutOfMemoryError.
26 | *
27 | * @author Norman Maurer
28 | * @author Galder Zamarreño
29 | */
30 | trait DrainSupport extends Self
31 | with AsJava {
32 |
33 | override type J <: JDrainSupport[_]
34 |
35 | /**
36 | * Set the maximum size of the write queue to `maxSize`. You will still be
37 | * able to write to the stream even if there is more than `maxSize` bytes in
38 | * the write queue. This is used as an indicator by classes such as `Pump`
39 | * to provide flow control.
40 | */
41 | def setWriteQueueMaxSize(maxSize: Int): this.type = wrap(asJava.setWriteQueueMaxSize(maxSize))
42 |
43 | /**
44 | * This will return `true` if there are more bytes in the write queue than
45 | * the value set using [[org.vertx.scala.core.streams.DrainSupport.setWriteQueueMaxSize]]
46 | */
47 | def writeQueueFull: Boolean = asJava.writeQueueFull()
48 |
49 | /**
50 | * Set a drain handler on the stream. If the write queue is full, then the
51 | * handler will be called when the write queue has been reduced to
52 | * maxSize / 2. See `Pump` for an example of this being used.
53 | */
54 | def drainHandler(handler: => Unit): this.type = wrap(asJava.drainHandler(lazyToVoidHandler(handler)))
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/file/FileProps.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.file
17 |
18 | import org.vertx.java.core.file.{ FileProps => JFileProps }
19 | import java.util.Date
20 |
21 | /**
22 | * Represents properties of a file on the file system
23 | * Instances of FileProps are thread-safe
24 | *
25 | * @author Tim Fox
26 | * @author Joern Bernhardt
27 | * @author Galder Zamarreño
28 | */
29 | final class FileProps private[scala] (val asJava: JFileProps) extends AnyVal {
30 |
31 | /**
32 | * The date the file was created
33 | */
34 | def creationTime(): Date = asJava.creationTime()
35 |
36 | /**
37 | * The date the file was last accessed
38 | */
39 | def lastAccessTime(): Date = asJava.lastAccessTime()
40 |
41 | /**
42 | * The date the file was last modified
43 | */
44 | def lastModifiedTime(): Date = asJava.lastModifiedTime()
45 |
46 | /**
47 | * Is the file a directory?
48 | */
49 | def isDirectory: Boolean = asJava.isDirectory
50 |
51 | /**
52 | * Is the file some other type? (I.e. not a directory, regular file or symbolic link)
53 | */
54 | def isOther: Boolean = asJava.isOther
55 |
56 | /**
57 | * Is the file a regular file?
58 | */
59 | def isRegularFile: Boolean = asJava.isRegularFile
60 |
61 | /**
62 | * Is the file a symbolic link?
63 | */
64 | def isSymbolicLink: Boolean = asJava.isSymbolicLink
65 |
66 | /**
67 | * The size of the file, in bytes
68 | */
69 | def size(): Long = asJava.size()
70 | }
71 |
72 | /** Factory for [[org.vertx.scala.core.file.FileProps]] instances. */
73 | object FileProps {
74 | def apply(internal: JFileProps) = new FileProps(internal)
75 | }
76 |
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/plattform/impl/ScalaVerticleFactoryTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.tests.plattform.impl
17 |
18 | import org.junit.Test
19 | import org.vertx.scala.testtools.TestVerticle
20 | import org.vertx.scala.platform.impl.ScalaVerticleFactory
21 | import org.vertx.testtools.VertxAssert._
22 |
23 | /**
24 | * Scala verticle factory tests.
25 | *
26 | * @author Galder Zamarreño
27 | */
28 | class ScalaVerticleFactoryTest extends TestVerticle {
29 |
30 | @Test
31 | def createVerticleWithSystemPath(): Unit = {
32 | val factory = createScalaVerticleFactory()
33 | val path = "src/test/scala/org/vertx/scala/tests/lang/VerticleClass.scala"
34 | val verticle = factory.createVerticle(path)
35 | verticle.start()
36 | assertHttpClientGetNow("Hello verticle class!")
37 | }
38 |
39 | @Test
40 | def createVerticleWithUnmatchingPathAndClassName(): Unit = {
41 | val factory = createScalaVerticleFactory()
42 | val path = "src/test/scala/org/vertx/scala/tests/lang/UnsupportedVerticleClass.scala"
43 | try {
44 | factory.createVerticle(path)
45 | fail("Should have failed with an exception")
46 | } catch {
47 | case e: ClassNotFoundException => testComplete() // expected
48 | }
49 | }
50 |
51 | private def createScalaVerticleFactory(): ScalaVerticleFactory = {
52 | val factory = new ScalaVerticleFactory
53 | factory.init(vertx.asJava, container.asJava, this.getClass.getClassLoader)
54 | factory
55 | }
56 |
57 | private def assertHttpClientGetNow(expected: String) {
58 | val client = vertx.createHttpClient().setPort(8080)
59 | client.getNow("/", {h =>
60 | assertThread()
61 | h.bodyHandler { data => {
62 | assertThread()
63 | assertEquals(expected, data.toString())
64 | testComplete()
65 | }
66 | }
67 | })
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/platform/impl/ScalaVerticle.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.platform.impl
18 |
19 | import org.vertx.java.core.Future
20 | import org.vertx.java.core.{ Vertx => JVertx }
21 | import org.vertx.java.platform.{ Container => JContainer }
22 | import org.vertx.java.platform.{ Verticle => JVerticle }
23 | import org.vertx.scala.core.Vertx
24 | import org.vertx.scala.core.VertxExecutionContext
25 | import org.vertx.scala.platform.Container
26 | import org.vertx.scala.platform.Verticle
27 | import scala.concurrent.Promise
28 | import scala.util.Failure
29 | import scala.util.Success
30 |
31 | /**
32 | * @author swilliams
33 | * @author Joern Bernhardt
34 | */
35 | object ScalaVerticle {
36 | def newVerticle(delegate: Verticle, vertx: Vertx, container: Container): ScalaVerticle = {
37 | val verticle = new ScalaVerticle(delegate)
38 | verticle.setVertx(vertx.asJava)
39 | verticle.setContainer(container.asJava)
40 | verticle
41 | }
42 | }
43 |
44 | final private[platform] class ScalaVerticle(delegate: Verticle) extends JVerticle {
45 |
46 | implicit val executionContext = VertxExecutionContext.fromVertxAccess(delegate)
47 |
48 | override def setContainer(jcontainer: JContainer) = {
49 | delegate.setContainer(new Container(jcontainer))
50 | super.setContainer(jcontainer)
51 | }
52 |
53 | override def setVertx(jvertx: JVertx) = {
54 | delegate.setVertx(new Vertx(jvertx))
55 | super.setVertx(jvertx)
56 | }
57 |
58 | override def start(): Unit = {
59 | delegate.start()
60 | }
61 |
62 | override def start(future: Future[Void]): Unit = {
63 | val p = Promise[Unit]()
64 | delegate.start()
65 | delegate.start(p)
66 | p.future onComplete {
67 | case Success(_) =>
68 | future.setResult(null)
69 | case Failure(x) =>
70 | future.setFailure(x)
71 | }
72 | }
73 |
74 | override def stop(): Unit = delegate.stop()
75 |
76 | }
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/plattform/impl/SystemPropertyDefaultLangOverrideTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.tests.plattform.impl
17 |
18 | import java.net.{URLClassLoader, URL}
19 | import org.hamcrest.Matchers.startsWith
20 | import org.junit.Assert._
21 | import org.junit.{After, Before, Test}
22 | import org.vertx.java.platform.{PlatformManager, PlatformLocator}
23 | import org.vertx.scala.core.AsyncResult
24 | import org.vertx.scala.core.FunctionConverters._
25 | import org.vertx.scala.tests.lang.VerticleClass
26 | import scala.collection.mutable
27 | import scala.concurrent.duration._
28 | import scala.concurrent.{Await, Promise}
29 |
30 | /**
31 | * @author Galder Zamarreño
32 | */
33 | class SystemPropertyDefaultLangOverrideTest {
34 |
35 | var mgr: PlatformManager = _
36 |
37 | @Before def beforeTest() {
38 | System.setProperty("vertx.langs..", "scala") // override default via system property
39 | mgr = PlatformLocator.factory.createPlatformManager
40 | }
41 |
42 | @After def afterTest() {
43 | System.clearProperty("vertx.langs..")
44 | mgr.stop()
45 | }
46 |
47 | @Test def testDeployVerticle(): Unit = {
48 | val p = Promise[String]()
49 |
50 | val handler: AsyncResult[String] => Unit = { res =>
51 | if (res.succeeded()) p.success(res.result()) else p.failure(res.cause())
52 | }
53 |
54 | mgr.deployVerticle(classOf[VerticleClass].getName, null, findURLs().orNull, 1, null, handler)
55 | assertThat(Await.result(p.future, 10 second), startsWith("deployment-"))
56 | }
57 |
58 | private def findURLs(): Option[Array[URL]] = {
59 | val urls = mutable.ListBuffer[URL]()
60 | val pcl = Thread.currentThread.getContextClassLoader
61 | pcl match {
62 | case u: URLClassLoader =>
63 | for (url <- u.getURLs) {
64 | val stringUrl = url.toString
65 | if (!stringUrl.endsWith(".jar") && !stringUrl.endsWith(".zip"))
66 | urls += url
67 | }
68 | Some(urls.toArray)
69 | case _ => None
70 | }
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/logging/Logger.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.logging
17 |
18 | import org.vertx.java.core.logging.{ Logger => JLogger }
19 |
20 | /**
21 | * Small helper class to check for log level and delegate it to the real logger if enabled.
22 | *
23 | * @author Joern Bernhardt
24 | */
25 | // constructor is private because users should use apply in companion
26 | // extends AnyVal to avoid object allocation and improve performance
27 | final class Logger private[scala] (val asJava: JLogger) extends AnyVal {
28 |
29 | def isInfoEnabled: Boolean = asJava.isInfoEnabled
30 | def isDebugEnabled: Boolean = asJava.isDebugEnabled
31 | def isTraceEnabled: Boolean = asJava.isTraceEnabled
32 |
33 | def trace(message: => AnyRef) = withTrace(asJava.trace(message))
34 | def trace(message: => AnyRef, t: => Throwable) = withTrace(asJava.trace(message, t))
35 | def debug(message: => AnyRef) = withDebug(asJava.debug(message))
36 | def debug(message: => AnyRef, t: => Throwable) = withDebug(asJava.debug(message, t))
37 | def info(message: => AnyRef) = withInfo(asJava.info(message))
38 | def info(message: => AnyRef, t: => Throwable) = withInfo(asJava.info(message, t))
39 |
40 | def warn(message: => AnyRef) = asJava.warn(message)
41 | def warn(message: => AnyRef, t: => Throwable) = asJava.warn(message, t)
42 | def error(message: => AnyRef) = asJava.error(message)
43 | def error(message: => AnyRef, t: => Throwable) = asJava.error(message, t)
44 | def fatal(message: => AnyRef) = asJava.fatal(message)
45 | def fatal(message: => AnyRef, t: => Throwable) = asJava.fatal(message, t)
46 |
47 | private def withTrace(fn: => Unit) = if (asJava.isTraceEnabled) { fn }
48 | private def withDebug(fn: => Unit) = if (asJava.isDebugEnabled) { fn }
49 | private def withInfo(fn: => Unit) = if (asJava.isInfoEnabled) { fn }
50 |
51 | }
52 |
53 | /** Factory for [[org.vertx.scala.core.logging.Logger]] instances. */
54 | object Logger {
55 | def apply(internal: JLogger): Logger = new Logger(internal)
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/http/ServerWebSocket.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.core.http
18 |
19 | import org.vertx.java.core.http.{ ServerWebSocket => JServerWebSocket }
20 | import org.vertx.scala.Self
21 | import org.vertx.scala.core.MultiMap
22 |
23 | /**
24 | * Represents a server side WebSocket that is passed into a the websocketHandler of an [[org.vertx.scala.core.http.HttpServer]]
25 | * Instances of this class are not thread-safe
26 | *
27 | * @author Tim Fox
28 | * @author swilliams
29 | * @author Galder Zamarreño
30 | * @author Joern Bernhardt
31 | */
32 | final class ServerWebSocket private[scala] (val asJava: JServerWebSocket) extends Self
33 | with WebSocketBase {
34 |
35 | override type J = JServerWebSocket
36 |
37 | /**
38 | * The uri the websocket handshake occurred at
39 | */
40 | def uri(): String = asJava.uri()
41 |
42 | /**
43 | * The path the websocket is attempting to connect at
44 | */
45 | def path(): String = asJava.path()
46 |
47 | /**
48 | * The query string passed on the websocket uri
49 | */
50 | def query(): String = asJava.query()
51 |
52 | /**
53 | * A map of all headers in the request to upgrade to websocket
54 | */
55 | def headers(): MultiMap = multiMapToScalaMultiMap(asJava.headers())
56 |
57 | /**
58 | * Reject the WebSocket
59 | * Calling this method from the websocketHandler gives you the opportunity to reject
60 | * the websocket, which will cause the websocket handshake to fail by returning
61 | * a 404 response code.
62 | * You might use this method, if for example you only want to accept websockets
63 | * with a particular path.
64 | */
65 | def reject(): ServerWebSocket = wrap(asJava.reject())
66 | }
67 |
68 | /** Factory for [[org.vertx.scala.core.http.ServerWebSocket]] instances. */
69 | object ServerWebSocket {
70 | def apply(socket: JServerWebSocket) = new ServerWebSocket(socket)
71 | def unapply(socket: ServerWebSocket): JServerWebSocket = socket.asJava
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/NetworkSupport.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core
17 |
18 | import org.vertx.java.core.{NetworkSupport => JNetworkSupport}
19 | import org.vertx.scala.{Self, AsJava}
20 |
21 | /**
22 | * Offers methods that can be used to configure a service that provide network services.
23 | *
24 | * @author Norman Maurer
25 | * @author Joern Bernhardt
26 | * @author Galder Zamarreño
27 | */
28 | trait NetworkSupport extends Self with AsJava {
29 |
30 | override type J <: JNetworkSupport[_]
31 |
32 | /**
33 | * Set the send buffer size for connections created by this instance to `size` in bytes.
34 | * @return a reference to this so multiple method calls can be chained together
35 | */
36 | def setSendBufferSize(size: Int): this.type = wrap(asJava.setSendBufferSize(size))
37 |
38 | /**
39 | * Set the receive buffer size for connections created by this instance to `size` in bytes.
40 | * @return a reference to this so multiple method calls can be chained together
41 | */
42 | def setReceiveBufferSize(size: Int): this.type = wrap(asJava.setReceiveBufferSize(size))
43 |
44 | /**
45 | * Set the reuseAddress setting for connections created by this instance to `reuse`.
46 | * @return a reference to this so multiple method calls can be chained together
47 | */
48 | def setReuseAddress(reuse: Boolean): this.type = wrap(asJava.setReuseAddress(reuse))
49 |
50 | /**
51 | * Set the trafficClass setting for connections created by this instance to `trafficClass`.
52 | * @return a reference to this so multiple method calls can be chained together
53 | */
54 | def setTrafficClass(trafficClass: Int): this.type = wrap(asJava.setTrafficClass(trafficClass))
55 |
56 | /**
57 | * @return The send buffer size
58 | */
59 | def getSendBufferSize: Int = asJava.getSendBufferSize
60 |
61 | /**
62 | * @return The receive buffer size
63 | */
64 | def getReceiveBufferSize: Int = asJava.getReceiveBufferSize
65 |
66 | /**
67 | * @return The value of reuse address
68 | */
69 | def isReuseAddress: Boolean = asJava.isReuseAddress
70 |
71 | /**
72 | * @return the value of traffic class
73 | */
74 | def getTrafficClass: Int = asJava.getTrafficClass
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/platform/Verticle.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.platform
18 |
19 | import org.vertx.scala.core.Vertx
20 | import org.vertx.scala.core.VertxAccess
21 | import org.vertx.scala.core.logging.Logger
22 | import scala.concurrent.Promise
23 |
24 | /**
25 | * A verticle is the unit of execution in the Vert.x platform
26 | * Vert.x code is packaged into Verticle's and then deployed and executed by the Vert.x platform.
27 | * Verticles can be written in different languages.
28 | *
29 | * @author Tim Fox
30 | * @author swilliams
31 | * @author Joern Bernhardt
32 | */
33 | trait Verticle extends VertxAccess {
34 |
35 | private var _vertx: Vertx = _
36 | private var _container: Container = _
37 |
38 | /**
39 | * A reference to the Vert.x runtime.
40 | * @return A reference to a Vertx.
41 | */
42 | lazy val vertx: Vertx = _vertx
43 |
44 | /**
45 | * A reference to the Vert.x container.
46 | * @return A reference to the Container.
47 | */
48 | lazy val container: Container = _container
49 |
50 | /**
51 | *
52 | */
53 | lazy val logger: Logger = container.logger()
54 |
55 | /**
56 | * Injects the vertx.
57 | */
58 | private[platform] def setVertx(newVertx: Vertx): Unit = _vertx = newVertx
59 |
60 | /**
61 | * Injects the container.
62 | */
63 | private[platform] def setContainer(newContainer: Container): Unit = _container = newContainer
64 |
65 | /**
66 | * Vert.x calls the start method when the verticle is deployed.
67 | */
68 | def start(): Unit = {}
69 |
70 | /**
71 | * Override this method to signify that start is complete sometime _after_ the start() method has returned.
72 | * This is useful if your verticle deploys other verticles or modules and you don't want this verticle to
73 | * be considered started until the other modules and verticles have been started.
74 | *
75 | * @param promise When you are happy your verticle is started set the result.
76 | */
77 | def start(promise: Promise[Unit]): Unit = promise.success()
78 |
79 | /**
80 | * Vert.x calls the stop method when the verticle is undeployed.
81 | * Put any cleanup code for your verticle in here
82 | */
83 | def stop(): Unit = {}
84 |
85 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/testtools/TestVerticle.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.testtools
2 |
3 | import java.lang.reflect.{Method, InvocationTargetException}
4 | import org.junit.runner.RunWith
5 | import org.vertx.scala.platform.Verticle
6 | import org.vertx.testtools.VertxAssert
7 | import scala.concurrent.{ExecutionContext, Future}
8 | import org.vertx.java.core.impl.{WorkerContext, DefaultContext, VertxInternal}
9 | import org.vertx.scala.core.VertxExecutionContext
10 |
11 | @RunWith(classOf[ScalaClassRunner])
12 | abstract class TestVerticle extends Verticle {
13 |
14 | override final def start() {
15 | initialize()
16 | before()
17 | asyncBefore() map { _ =>
18 | startTests()
19 | } recover {
20 | case ex: Throwable =>
21 | VertxAssert.handleThrowable(ex)
22 | }
23 | }
24 |
25 | /**
26 | * Override this method if you want to do things synchronously before starting the tests.
27 | */
28 | def before(): Unit = {}
29 |
30 | /**
31 | * Override this method if you want to do things asynchronously before starting the tests.
32 | */
33 | def asyncBefore(): Future[Unit] = Future.successful()
34 |
35 | /**
36 | * Expected thread
37 | */
38 | var th: Thread = _
39 |
40 | /**
41 | * Vertx internal context
42 | */
43 | var context: DefaultContext = _
44 |
45 | protected final def initialize(): Unit = {
46 | VertxAssert.initialize(vertx.asJava)
47 | th = Thread.currentThread
48 | context = vertx.asJava.asInstanceOf[VertxInternal].getContext
49 | }
50 |
51 | protected final def startTests() {
52 | val methodName = container.config().getString("methodName")
53 | try {
54 | val m = findMethod(getClass, methodName)
55 | m.invoke(this)
56 | } catch {
57 | case e: InvocationTargetException =>
58 | val targetEx = e.getTargetException
59 | VertxAssert.handleThrowable(targetEx)
60 | case t: Throwable =>
61 | // Problem with invoking
62 | VertxAssert.handleThrowable(t)
63 | }
64 | }
65 |
66 | protected final def assertThread() {
67 | if (!context.isInstanceOf[WorkerContext] && th != Thread.currentThread)
68 | throw new IllegalStateException(
69 | s"Expected: $th Actual: ${Thread.currentThread}")
70 |
71 | if (context != vertx.asJava.asInstanceOf[VertxInternal].getContext)
72 | throw new IllegalStateException(
73 | s"Wrong context: Expected: $context Actual: ${vertx.asInstanceOf[VertxInternal].getContext}")
74 | }
75 |
76 | def findMethod(clazz: Class[_], methodName: String): Method = {
77 | try {
78 | clazz.getDeclaredMethod(methodName)
79 | } catch {
80 | case e: NoSuchMethodException =>
81 | if ((clazz == classOf[AnyRef]) || clazz.isInterface)
82 | throw e
83 |
84 | val superclass = clazz.getSuperclass
85 | logger.info(s"Method not found, try super-class $superclass")
86 | findMethod(superclass, methodName)
87 | }
88 | }
89 |
90 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/SSLSupport.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.core
2 |
3 | import org.vertx.java.core.{ SSLSupport => JSSLSupport }
4 | import org.vertx.scala.{Self, AsJava}
5 |
6 | trait SSLSupport extends Self
7 | with AsJava {
8 |
9 | override type J <: JSSLSupport[_]
10 |
11 | /**
12 | * If `ssl` is `true`, this signifies that any connections will be SSL connections.
13 | * @return A reference to this, so multiple invocations can be chained together.
14 | */
15 | def setSSL(ssl: Boolean): this.type = wrap(asJava.setSSL(ssl))
16 |
17 | /**
18 | *
19 | * @return Is SSL enabled?
20 | */
21 | def isSSL: Boolean = asJava.isSSL
22 |
23 | /**
24 | * Set the path to the SSL key store. This method should only be used in SSL
25 | * mode, i.e. after [[org.vertx.scala.core.SSLSupport.setSSL(boolean)]] has been set to `true`.
26 | * The SSL key store is a standard Java Key Store, and will contain the client certificate. Client certificates are
27 | * only required if the server requests client authentication.
28 | * @return A reference to this, so multiple invocations can be chained together.
29 | */
30 | def setKeyStorePath(path: String): this.type = wrap(asJava.setKeyStorePath(path))
31 |
32 | /**
33 | *
34 | * @return Get the key store path
35 | */
36 | def getKeyStorePath: String = asJava.getKeyStorePath
37 |
38 | /**
39 | * Set the password for the SSL key store. This method should only be used in SSL mode, i.e. after
40 | * [[org.vertx.scala.core.SSLSupport.setSSL(boolean)]] has been set to `true`.
41 | * @return A reference to this, so multiple invocations can be chained together.
42 | */
43 | def setKeyStorePassword(pwd: String): this.type = wrap(asJava.setKeyStorePassword(pwd))
44 |
45 | /**
46 | *
47 | * @return Get the key store password
48 | */
49 | def getKeyStorePassword: String = asJava.getKeyStorePassword
50 |
51 | /**
52 | * Set the path to the SSL trust store. This method should only be used in SSL mode, i.e. after
53 | * [[org.vertx.scala.core.SSLSupport.setSSL(boolean)]] has been set to `true`.
54 | * The trust store is a standard Java Key Store, and should contain the certificates of any servers that the client trusts.
55 | * @return A reference to this, so multiple invocations can be chained together.
56 | */
57 | def setTrustStorePath(path: String): this.type = wrap(asJava.setTrustStorePath(path))
58 |
59 | /**
60 | *
61 | * @return Get the trust store path
62 | */
63 | def getTrustStorePath: String = asJava.getTrustStorePath
64 |
65 | /**
66 | * Set the password for the SSL trust store. This method should only be used in SSL mode, i.e. after
67 | * [[org.vertx.scala.core.SSLSupport.setSSL(boolean)]] has been set to `true`.
68 | * @return A reference to this, so multiple invocations can be chained together.
69 | */
70 | def setTrustStorePassword(pwd: String): this.type = wrap(asJava.setTrustStorePassword(pwd))
71 |
72 | /**
73 | *
74 | * @return Get trust store password
75 | */
76 | def getTrustStorePassword: String = asJava.getTrustStorePassword
77 | }
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/util/TestUtils.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.tests.util
2 |
3 | import org.vertx.scala.core.AsyncResult
4 | import org.vertx.testtools.VertxAssert._
5 | import org.vertx.scala.platform.Container
6 | import org.vertx.scala.core.buffer.Buffer
7 | import scala.annotation.tailrec
8 | import java.io.{FileOutputStream, OutputStreamWriter, BufferedWriter, File}
9 |
10 | /**
11 | * Port of some of the original TestUtils Helper methods.
12 | *
13 | * @author Edgar Chan
14 | * @author Galder Zamarreño
15 | */
16 | object TestUtils {
17 |
18 | def completeWithArFailed[T]: AsyncResult[T] => Unit = { ar =>
19 | assertTrue(ar.failed())
20 | assertTrue(ar.cause() != null)
21 | testComplete()
22 | }
23 |
24 | def startTests(script: AnyRef, container: Container): Unit = {
25 | val methodName = container.config().getString("methodName")
26 | script.getClass.getMethod(methodName).invoke(script)
27 | }
28 |
29 | def generateRandomBuffer(length: Int): Buffer =
30 | generateRandomBuffer(length, avoid = false, 0.toByte)
31 |
32 | def generateRandomBuffer(length: Int, avoid: Boolean, avoidByte: Byte): Buffer =
33 | Buffer(generateRandomByteArray(length, avoid, avoidByte))
34 |
35 | def generateRandomByteArray(length: Int): Array[Byte] =
36 | generateRandomByteArray(length, avoid = false, 0.toByte)
37 |
38 | def generateRandomByteArray(length: Int, avoid: Boolean, avoidByte: Byte): Array[Byte] = {
39 | val line = new Array[Byte](length)
40 | var i = 0
41 | do {
42 | var rand:Byte = 0.toByte
43 | do {
44 | rand = ((Math.random() * 255) - 128).toByte
45 | } while(avoid && rand == avoidByte)
46 | line(i) = rand
47 | i += 1
48 | } while(i < length)
49 | line
50 | }
51 |
52 | def generateRandomUnicodeString(length: Int): String = {
53 | val builder = new StringBuilder(length)
54 | for (i <- 0 until length) {
55 | @tailrec def generateChar(): Char = {
56 | val c = (0xFFFF * Math.random()).toChar
57 | // Skip illegal chars
58 | if ((c >= 0xFFFE && c <= 0xFFFF) || (c >= 0xD800 && c <= 0xDFFF))
59 | generateChar()
60 | else
61 | c
62 | }
63 |
64 | builder.append(generateChar())
65 | }
66 | builder.toString()
67 | }
68 |
69 | def generateRandomContentFile(filename: String, len: Int): (File, String) = {
70 | val content = TestUtils.generateRandomUnicodeString(len)
71 | val file = createFile(filename, content)
72 | (file, content)
73 | }
74 |
75 | def generateFile(filename: String, content: String): (File, String) = {
76 | val file = createFile(filename, content)
77 | (file, content)
78 | }
79 |
80 | private def createFile(filename: String, content: String): File = {
81 | val file = new File(System.getProperty("java.io.tmpdir"), filename)
82 | if (file.exists())
83 | file.delete()
84 |
85 | val out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"))
86 | try {
87 | out.write(content)
88 | } finally {
89 | out.close()
90 | }
91 |
92 | file
93 | }
94 |
95 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/TCPSupport.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core
17 |
18 | import org.vertx.java.core.{ TCPSupport => JTCPSupport }
19 | import org.vertx.scala.Self
20 |
21 | /**
22 | * Supports [[org.vertx.java.core.TCPSupport]] functionality.
23 | *
24 | * @author Joern Bernhardt
25 | * @author Galder Zamarreño
26 | */
27 | trait TCPSupport extends Self
28 | with NetworkSupport {
29 |
30 | override type J <: JTCPSupport[_]
31 |
32 | /**
33 | *
34 | * @return the value of TCP so linger
35 | */
36 | def getSoLinger: Int = asJava.getSoLinger
37 |
38 | /**
39 | *
40 | * @return true if TCP keep alive is enabled
41 | */
42 | def isTCPKeepAlive: Boolean = asJava.isTCPKeepAlive
43 |
44 | /**
45 | * @return true if Nagle's algorithm is disabled.
46 | */
47 | def isTCPNoDelay: Boolean = asJava.isTCPNoDelay
48 |
49 | /**
50 | * @return `true` if pooled buffers are used
51 | */
52 | def isUsePooledBuffers: Boolean = asJava.isUsePooledBuffers
53 |
54 | /**
55 | * Set the TCP soLinger setting for connections created by this instance to `linger`.
56 | * Using a negative value will disable soLinger.
57 | * @return a reference to this so multiple method calls can be chained together
58 | *
59 | */
60 | def setSoLinger(linger: Int): this.type = wrap(asJava.setSoLinger(linger))
61 |
62 | /**
63 | * Set the TCP keepAlive setting for connections created by this instance to `keepAlive`.
64 | * @return a reference to this so multiple method calls can be chained together
65 | */
66 | def setTCPKeepAlive(keepAlive: Boolean): this.type = wrap(asJava.setTCPKeepAlive(keepAlive))
67 |
68 | /**
69 | * If `tcpNoDelay` is set to `true` then Nagle's algorithm
70 | * will turned off for the TCP connections created by this instance.
71 | * @return a reference to this so multiple method calls can be chained together
72 | */
73 | def setTCPNoDelay(tcpNoDelay: Boolean): this.type = wrap(asJava.setTCPNoDelay(tcpNoDelay))
74 |
75 | /**
76 | * Set if vertx should use pooled buffers for performance reasons. Doing so will give the best throughput but
77 | * may need a bit higher memory footprint.
78 | * @return a reference to this so multiple method calls can be chained together
79 | */
80 | def setUsePooledBuffers(pooledBuffers: Boolean): this.type = wrap(asJava.setUsePooledBuffers(pooledBuffers))
81 | }
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/router/JsonRouterTest.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.tests.router
2 |
3 | import org.junit.Test
4 | import org.vertx.scala.FutureOps
5 | import org.vertx.testtools.VertxAssert._
6 | import FutureOps._
7 | import org.vertx.scala.core.FunctionConverters._
8 | import scala.concurrent.{ExecutionContext, Promise, Future}
9 | import scala.util.{Try, Failure, Success}
10 | import org.vertx.scala.core.json.Json
11 | import org.vertx.scala.core.http.HttpClientResponse
12 |
13 | /**
14 | * @author Joern Bernhardt
15 | */
16 | class JsonRouterTest extends RouterTestHelper {
17 |
18 | override def asyncBefore(): Future[Unit] = futurify { p: Promise[Unit] =>
19 | container.deployVerticle("scala:org.vertx.scala.tests.router.JsonRouter", handler = {
20 | case Success(deployId) => p.success()
21 | case Failure(ex) => p.failure(ex)
22 | }: Try[String] => Unit)
23 | }
24 |
25 | @Test def indexGet(): Unit = doHttp("GET", "/") map bodyOkCompleter { body =>
26 | assertEquals(testFileContents(), body)
27 | }
28 |
29 | @Test def pathGet(): Unit = doHttp("GET", "/test.txt") map bodyOkCompleter { body =>
30 | assertEquals(testFileContents(), body)
31 | }
32 |
33 | @Test def missingFileSend(): Unit = doHttp("GET", "/not-found") map { res: HttpClientResponse =>
34 | assertEquals(404, res.statusCode())
35 | checkBody { body =>
36 | assertEquals(error404FileContents(), body)
37 | }(res)
38 | }
39 |
40 | @Test def singleCookie(): Unit = doHttp("GET", "/cookies1") map { res =>
41 | assertEquals(200, res.statusCode())
42 | assertEquals(Set("a=1"), res.headers().get("Set-Cookie").get)
43 | res.endHandler(testComplete())
44 | }
45 |
46 | @Test def multipleCookies(): Unit = doHttp("GET", "/cookies2") map { res =>
47 | assertEquals(200, res.statusCode())
48 | assertEquals(Set("a=1", "b=2"), res.headers().get("Set-Cookie").get)
49 | res.endHandler(testComplete())
50 | }
51 |
52 | @Test def indexPost(): Unit = doHttp("POST", "/") map bodyOkCompleter({ body =>
53 | assertEquals("ok", Json.fromObjectString(body).getString("status"))
54 | })
55 |
56 | @Test def pathPost(): Unit = doHttp("POST", "/post-ok") map bodyOkCompleter({ body =>
57 | assertEquals("ok", Json.fromObjectString(body).getString("status"))
58 | })
59 |
60 | @Test def patchNotFound(): Unit = doHttp("PATCH", "/not-found") map { res =>
61 | assertEquals(404, res.statusCode())
62 | testComplete()
63 | }
64 |
65 | @Test def deleteForbidden(): Unit = doHttp("DELETE", "/forbidden") map { res =>
66 | assertEquals(403, res.statusCode())
67 | testComplete()
68 | }
69 |
70 | @Test def customHead(): Unit = doHttp("HEAD", "/head") map { res =>
71 | assertEquals(200, res.statusCode())
72 | assertTrue(res.headers().entryExists("x-custom-head", _ == "hello"))
73 | testComplete()
74 | }
75 |
76 | @Test def allMatchesGet(): Unit = doHttp("GET", "/all-test") map bodyOkCompleter { body =>
77 | assertEquals(testFileContents(), body)
78 | }
79 |
80 | @Test def allMatchesPost(): Unit = doHttp("POST", "/all-test") map bodyOkCompleter { body =>
81 | assertEquals(testFileContents(), body)
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/streams/WriteStream.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.core.streams
18 |
19 | import org.vertx.java.core.streams.{ WriteStream => JWriteStream }
20 | import org.vertx.scala.core.buffer.Buffer
21 | import org.vertx.scala.{Self, AsJava}
22 | import org.vertx.scala.core.FunctionConverters._
23 |
24 | /**
25 | * Represents a stream of data that can be written to
26 | * Any class that implements this interface can be used by a [[org.vertx.scala.core.streams.Pump]]
27 | * to pump data from a [[org.vertx.scala.core.streams.ReadStream]]
28 | * to it.
29 | * This interface exposes a fluent api and the type T represents the type of
30 | * the object that implements the interface to allow method chaining
31 | *
32 | * @author Tim Fox
33 | * @author swilliams
34 | * @author Joern Bernhardt
35 | * @author Galder Zamarreño
36 | */
37 | trait WriteStream extends Self
38 | with ExceptionSupport
39 | with AsJava {
40 |
41 | override type J <: JWriteStream[_]
42 |
43 | /**
44 | * Write some data to the stream. The data is put on an internal write queue, and the write actually happens
45 | * asynchronously. To avoid running out of memory by putting too much on the write queue,
46 | * check the [[org.vertx.scala.core.streams.WriteStream.writeQueueFull()]]
47 | * method before writing. This is done automatically if using a [[org.vertx.scala.core.streams.Pump]].
48 | */
49 | def write(data: Buffer): this.type = wrap(asJava.write(data.asJava))
50 |
51 | /**
52 | * Set the maximum size of the write queue to `maxSize`. You will still be able to write to the stream even
53 | * if there is more than `maxSize` bytes in the write queue. This is used as an indicator by classes such as
54 | * `Pump` to provide flow control.
55 | */
56 | def setWriteQueueMaxSize(maxSize: Int): this.type = wrap(asJava.setWriteQueueMaxSize(maxSize))
57 |
58 | /**
59 | * This will return `true` if there are more bytes in the write queue than the value set using
60 | * [[org.vertx.scala.core.streams.WriteStream.setWriteQueueMaxSize()]]
61 | */
62 | def writeQueueFull(): Boolean = asJava.writeQueueFull()
63 |
64 | /**
65 | * Set a drain handler on the stream. If the write queue is full, then the handler will be called when the write
66 | * queue has been reduced to maxSize / 2. See [[org.vertx.scala.core.streams.Pump]] for an example of this being used.
67 | */
68 | def drainHandler(handler: => Unit): this.type = wrap(asJava.drainHandler(lazyToVoidHandler(handler)))
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/http/WebSocketBase.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.core.http
2 |
3 | import org.vertx.java.core.http.{ WebSocketBase => JWebSocketBase }
4 | import org.vertx.scala.core.streams.{ WriteStream, ReadStream }
5 | import org.vertx.scala.core.FunctionConverters._
6 | import org.vertx.scala.core.buffer.Buffer
7 | import org.vertx.scala.Self
8 | import java.net.InetSocketAddress
9 |
10 | /**
11 | * Represents an HTML 5 Websocket
12 | * Instances of this class are created and provided to the handler of an
13 | * [[org.vertx.scala.core.http.HttpClient]] when a successful websocket connect attempt occurs.
14 | * On the server side, the subclass [[org.vertx.scala.core.http.ServerWebSocket]] is used instead.
15 | * It implements both [[org.vertx.scala.core.streams.ReadStream]] and [[org.vertx.scala.core.streams.WriteStream]] so it can be used with
16 | * [[org.vertx.scala.core.streams.Pump]] to pump data with flow control.
17 | * Instances of this class are not thread-safe
18 | *
19 | * @author Tim Fox
20 | * @author Joern Bernhardt
21 | * @author Galder Zamarreño
22 | */
23 | trait WebSocketBase extends Self
24 | with ReadStream
25 | with WriteStream {
26 |
27 | override type J <: JWebSocketBase[J]
28 |
29 | /**
30 | * When a `Websocket` is created it automatically registers an event handler with the eventbus, the ID of that
31 | * handler is given by `binaryHandlerID`.
32 | * Given this ID, a different event loop can send a binary frame to that event handler using the event bus and
33 | * that buffer will be received by this instance in its own event loop and written to the underlying connection. This
34 | * allows you to write data to other websockets which are owned by different event loops.
35 | */
36 | def binaryHandlerID(): String = asJava.binaryHandlerID()
37 |
38 | /**
39 | * Close the websocket
40 | */
41 | def close(): Unit = asJava.close()
42 |
43 | /**
44 | * Set a closed handler on the connection
45 | */
46 | def closeHandler(handler: => Unit): this.type = wrap(asJava.closeHandler(handler))
47 |
48 | /**
49 | * When a `Websocket} is created it automatically registers an event handler with the eventbus, the ID of that
50 | * handler is given by `textHandlerID}.
51 | * Given this ID, a different event loop can send a text frame to that event handler using the event bus and
52 | * that buffer will be received by this instance in its own event loop and written to the underlying connection. This
53 | * allows you to write data to other websockets which are owned by different event loops.
54 | */
55 | def textHandlerID(): String = asJava.textHandlerID()
56 |
57 | /**
58 | * Write `data` to the websocket as a binary frame
59 | */
60 | def writeBinaryFrame(data: Buffer): this.type = wrap(asJava.writeBinaryFrame(data.asJava))
61 |
62 | /**
63 | * Write `str` to the websocket as a text frame
64 | */
65 | def writeTextFrame(str: String): this.type = wrap(asJava.writeTextFrame(str))
66 |
67 | /**
68 | * Return the remote address for this socket
69 | */
70 | def remoteAddress(): InetSocketAddress = asJava.remoteAddress()
71 |
72 | /**
73 | * Return the local address for this socket
74 | */
75 | def localAddress(): InetSocketAddress = asJava.localAddress()
76 |
77 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/buffer/package.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core
17 |
18 | import org.vertx.java.core.buffer.{ Buffer => JBuffer }
19 | import org.vertx.scala.core.FunctionConverters._
20 |
21 | /**
22 | * @author swilliams
23 | * @author Edgar Chan
24 | * @author Joern Bernhardt
25 | */
26 | package object buffer {
27 |
28 | trait BufferType[T] {
29 | def appendToBuffer(buffer: JBuffer, value: T): JBuffer
30 | }
31 | implicit object BufferElem extends BufferType[Buffer] {
32 | override def appendToBuffer(buffer: JBuffer, value: Buffer) = buffer.appendBuffer(value.asJava)
33 | }
34 | implicit object ByteElem extends BufferType[Byte] {
35 | override def appendToBuffer(buffer: JBuffer, value: Byte) = buffer.appendByte(value)
36 | }
37 | implicit object BytesElem extends BufferType[Array[Byte]] {
38 | override def appendToBuffer(buffer: JBuffer, value: Array[Byte]) = buffer.appendBytes(value)
39 | }
40 | implicit object DoubleElem extends BufferType[Double] {
41 | override def appendToBuffer(buffer: JBuffer, value: Double) = buffer.appendDouble(value)
42 | }
43 | implicit object FloatElem extends BufferType[Float] {
44 | override def appendToBuffer(buffer: JBuffer, value: Float) = buffer.appendFloat(value)
45 | }
46 | implicit object IntElem extends BufferType[Int] {
47 | override def appendToBuffer(buffer: JBuffer, value: Int) = buffer.appendInt(value)
48 | }
49 | implicit object LongElem extends BufferType[Long] {
50 | override def appendToBuffer(buffer: JBuffer, value: Long) = buffer.appendLong(value)
51 | }
52 | implicit object ShortElem extends BufferType[Short] {
53 | override def appendToBuffer(buffer: JBuffer, value: Short) = buffer.appendShort(value)
54 | }
55 | implicit object StringElem extends BufferType[String] {
56 | override def appendToBuffer(buffer: JBuffer, value: String) = buffer.appendString(value)
57 | }
58 | implicit object StringWithEncodingElem extends BufferType[(String, String)] {
59 | override def appendToBuffer(buffer: JBuffer, value: (String, String)) = buffer.appendString(value._1, value._2)
60 | }
61 |
62 | trait BufferSeekType[T] {
63 | def appendToBuffer(buffer: JBuffer, value: T, offset: Int, len: Int): JBuffer
64 | }
65 | implicit object BufferSeekElem extends BufferSeekType[Buffer] {
66 | override def appendToBuffer(buffer: JBuffer, value: Buffer, offset: Int, len: Int) =
67 | buffer.appendBuffer(value.asJava, offset, len)
68 | }
69 | implicit object BytesSeekElem extends BufferSeekType[Array[Byte]] {
70 | override def appendToBuffer(buffer: JBuffer, value: Array[Byte], offset: Int, len: Int) =
71 | buffer.appendBytes(value, offset, len)
72 | }
73 |
74 | def bufferHandlerToJava(handler: Buffer => Unit) = fnToHandler(handler.compose { jbuffer: JBuffer => Buffer.apply(jbuffer) })
75 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/sockjs/SockJSSocket.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.core.sockjs
18 |
19 | import org.vertx.java.core.sockjs.{ SockJSSocket => JSockJSSocket }
20 | import org.vertx.scala.core.streams.{WriteStream, ReadStream}
21 | import org.vertx.scala.core.http._
22 | import org.vertx.scala.Self
23 | import java.net.InetSocketAddress
24 | import org.vertx.scala.core.MultiMap
25 |
26 | /**
27 | * You interact with SockJS clients through instances of SockJS socket.
28 | * The API is very similar to [[org.vertx.scala.core.http.WebSocket]]. It implements both
29 | * [[org.vertx.scala.core.streams.ReadStream]] and [[org.vertx.scala.core.streams.WriteStream]] so it can be used with
30 | * [[org.vertx.scala.core.streams.Pump]] to pump data with flow control.
31 | * Instances of this class are not thread-safe.
32 | *
33 | * @author Tim Fox
34 | * @author swilliams
35 | * @author Joern Bernhardt
36 | */
37 | final class SockJSSocket private[scala] (val asJava: JSockJSSocket) extends Self
38 | with ReadStream
39 | with WriteStream {
40 |
41 | override type J = JSockJSSocket
42 |
43 | /**
44 | * When a `SockJSSocket` is created it automatically registers an event handler with the event bus, the ID of that
45 | * handler is given by `writeHandlerID`.
46 | * Given this ID, a different event loop can send a buffer to that event handler using the event bus and
47 | * that buffer will be received by this instance in its own event loop and written to the underlying socket. This
48 | * allows you to write data to other sockets which are owned by different event loops.
49 | */
50 | def writeHandlerID(): String = asJava.writeHandlerID()
51 |
52 | /**
53 | * Close it
54 | */
55 | def close(): Unit = asJava.close()
56 |
57 | /**
58 | * Return the remote address for this socket
59 | */
60 | def remoteAddress(): InetSocketAddress = asJava.remoteAddress()
61 |
62 | /**
63 | * Return the local address for this socket
64 | */
65 | def localAddress(): InetSocketAddress = asJava.localAddress()
66 |
67 | /**
68 | * Return the headers corresponding to the last request for this socket or the websocket handshake
69 | * Any cookie headers will be removed for security reasons
70 | *
71 | * This method converts a Java collection into a Scala collection every
72 | * time it gets called, so use it sensibly.
73 | */
74 | def headers: MultiMap = multiMapToScalaMultiMap(asJava.headers())
75 |
76 | /**
77 | * Return the URI corresponding to the last request for this socket or the websocket handshake
78 | */
79 | def uri: String = asJava.uri()
80 |
81 | }
82 |
83 | /** Factory for [[org.vertx.scala.core.sockjs.SockJSSocket]] instances. */
84 | object SockJSSocket {
85 | def apply(internal: JSockJSSocket) = new SockJSSocket(internal)
86 | }
87 |
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/mods/TestBusMod.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.tests.mods
2 |
3 | import org.vertx.scala.platform.Verticle
4 | import org.vertx.scala.mods.ScalaBusMod
5 | import org.vertx.scala.core.eventbus.Message
6 | import org.vertx.scala.core.json._
7 | import org.vertx.scala.core.FunctionConverters._
8 | import org.vertx.scala.mods.replies._
9 | import scala.concurrent.Promise
10 | import scala.util.Try
11 | import scala.util.Success
12 | import scala.util.Failure
13 | import org.vertx.scala.mods.BusModException
14 | import scala.concurrent.Future
15 | import org.vertx.testtools.VertxAssert
16 |
17 | class TestBusMod extends Verticle with ScalaBusMod {
18 | override def start(promise: Promise[Unit]): Unit = {
19 | vertx.eventBus.registerHandler("test-bus-mod", this, {
20 | case Success(_) => promise.success()
21 | case Failure(ex) => promise.failure(ex)
22 | }: Try[Void] => Unit)
23 | }
24 |
25 | override def receive = (msg: Message[JsonObject]) => {
26 | case "sync-hello" => Ok(Json.obj("result" -> "sync-hello-result"))
27 | case "sync-error" => throw new RuntimeException("sync-error-result")
28 | case "sync-echo" =>
29 | Option(msg.body.getString("echo")) match {
30 | case Some(echo) => Ok(Json.obj("echo" -> echo))
31 | case None => Error("No echo argument given!", "NO_ECHO_GIVEN")
32 | }
33 | case "async-hello" => AsyncReply {
34 | val p = Promise[BusModReply]
35 | vertx.setTimer(10, { timerId => p.success(Ok(Json.obj("result" -> "async-hello-result"))) })
36 | p.future
37 | }
38 | case "async-cascade" => AsyncReply {
39 | val p = Promise[BusModReply]
40 | vertx.setTimer(10, { timerId =>
41 | p.success(AsyncReply {
42 | val p2 = Promise[BusModReply]
43 | vertx.setTimer(10, { timerId2 =>
44 | p2.success(Ok(Json.obj("result" -> "async-cascade-result")))
45 | })
46 | p2.future
47 | })
48 | })
49 | p.future
50 | }
51 | case "async-cascade-uncaught" => AsyncReply {
52 | val p = Promise[BusModReply]
53 | vertx.setTimer(10, { timerId =>
54 | p.failure(new RuntimeException("async-uncaught-exception"))
55 | })
56 | p.future
57 | }
58 | case "async-error-1" => AsyncReply {
59 | throw new RuntimeException("uncaught-exception")
60 | }
61 | case "async-error-2" => AsyncReply {
62 | Future.failed(new BusModException("caught-exception", id = "CAUGHT_EXCEPTION"))
63 | }
64 | case "reply-notimeout" =>
65 | Ok(Json.obj("echo" -> msg.body.getString("echo")), Some(Receiver(msg => {
66 | case "reply-notimeout-reply" => Ok(Json.obj("echo" -> msg.body.getString("echo")))
67 | })))
68 | case "reply-timeout" =>
69 | val clientAddress = msg.body().getString("address")
70 | Ok(Json.obj("state" -> "waitForTimeout"), Some(ReceiverWithTimeout(msg => {
71 | case x =>
72 | vertx.eventBus.send(clientAddress, Json.obj("state" -> "error:should-not-get-reply"))
73 | Error("should not receive message")
74 | }, 500L, { () =>
75 | vertx.eventBus.send(clientAddress, Json.obj("state" -> "timeout"))
76 | })))
77 | case "reply-error-ok" =>
78 | Error("no.", replyHandler = Some(Receiver(msg => {
79 | case "please" => Ok(Json.obj("echo" -> msg.body.getString("echo")))
80 | })))
81 | case "no-direct-reply" =>
82 | val clientAddress = msg.body.getString("address")
83 | vertx.eventBus.send(clientAddress, Json.obj("echo" -> msg.body.getString("echo")))
84 | NoReply
85 | }
86 |
87 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/dns/DnsResponseCode.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.dns
17 |
18 | import org.vertx.java.core.dns.{ DnsResponseCode => JDnsResponseCode }
19 |
20 | abstract sealed class DnsResponseCode(code: Int, message: String) {
21 | override def toString: String = getClass.getName + ": type " + code + ", " + message
22 | def toJava: JDnsResponseCode = JDnsResponseCode.valueOf(code)
23 | }
24 |
25 | object DnsResponseCode {
26 | def fromJava(x: JDnsResponseCode) = x.code() match {
27 | case 0 => NOERROR
28 | case 1 => FORMERROR
29 | case 2 => SERVFAIL
30 | case 3 => NXDOMAIN
31 | case 4 => NOTIMPL
32 | case 5 => REFUSED
33 | case 6 => YXDOMAIN
34 | case 7 => YXRRSET
35 | case 8 => NXRRSET
36 | case 9 => NOTAUTH
37 | case 10 => NOTZONE
38 | case 11 => BADVERS
39 | case 12 => BADSIG
40 | case 13 => BADKEY
41 | case 14 => BADTIME
42 | }
43 | }
44 |
45 | /**
46 | * ID 0, no error
47 | */
48 | case object NOERROR extends DnsResponseCode(0, "no error")
49 |
50 | /**
51 | * ID 1, format error
52 | */
53 | case object FORMERROR extends DnsResponseCode(1, "format error")
54 |
55 | /**
56 | * ID 2, server failure
57 | */
58 | case object SERVFAIL extends DnsResponseCode(2, "server failure")
59 |
60 | /**
61 | * ID 3, name error
62 | */
63 | case object NXDOMAIN extends DnsResponseCode(3, "name error")
64 |
65 | /**
66 | * ID 4, not implemented
67 | */
68 | case object NOTIMPL extends DnsResponseCode(4, "not implemented")
69 |
70 | /**
71 | * ID 5, operation refused
72 | */
73 | case object REFUSED extends DnsResponseCode(5, "operation refused")
74 |
75 | /**
76 | * ID 6, domain name should not exist
77 | */
78 | case object YXDOMAIN extends DnsResponseCode(6, "domain name should not exist")
79 |
80 | /**
81 | * ID 7, resource record set should not exist
82 | */
83 | case object YXRRSET extends DnsResponseCode(7, "resource record set should not exist")
84 |
85 | /**
86 | * ID 8, rrset does not exist
87 | */
88 | case object NXRRSET extends DnsResponseCode(8, "rrset does not exist")
89 |
90 | /**
91 | * ID 9, not authoritative for zone
92 | */
93 | case object NOTAUTH extends DnsResponseCode(9, "not authoritative for zone")
94 |
95 | /**
96 | * ID 10, name not in zone
97 | */
98 | case object NOTZONE extends DnsResponseCode(10, "name not in zone")
99 |
100 | /**
101 | * ID 11, bad extension mechanism for version
102 | */
103 | case object BADVERS extends DnsResponseCode(11, "bad extension mechanism for version")
104 |
105 | /**
106 | * ID 12, bad signature
107 | */
108 | case object BADSIG extends DnsResponseCode(12, "bad signature")
109 |
110 | /**
111 | * ID 13, bad key
112 | */
113 | case object BADKEY extends DnsResponseCode(13, "bad key")
114 |
115 | /**
116 | * ID 14, bad timestamp
117 | */
118 | case object BADTIME extends DnsResponseCode(14, "bad timestamp")
119 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/FunctionConverters.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core
17 |
18 | import scala.language.implicitConversions
19 | import org.vertx.java.core.AsyncResultHandler
20 | import org.vertx.java.core.eventbus.{ Message => JMessage }
21 | import org.vertx.scala.core.eventbus.Message
22 | import org.vertx.java.core.impl.DefaultFutureResult
23 | import scala.util.Try
24 | import scala.util.Success
25 | import scala.util.Failure
26 |
27 | /**
28 | * @author swilliams
29 | * @author Joern Bernhardt
30 | * @author Galder Zamarreño
31 | */
32 | trait FunctionConverters {
33 |
34 | implicit def lazyToVoidHandler(func: => Unit): Handler[Void] = new Handler[Void]() {
35 | override def handle(event: Void) = func
36 | }
37 |
38 | implicit def fnToHandler[T](func: T => Unit): Handler[T] = new Handler[T]() {
39 | override def handle(event: T) = func(event)
40 | }
41 |
42 | implicit def messageFnToJMessageHandler[T](func: Message[T] => Unit): Handler[JMessage[T]] = new Handler[JMessage[T]]() {
43 | override def handle(event: JMessage[T]) = func.compose(Message.apply).apply(event)
44 | }
45 |
46 | implicit def handlerToFn[T](handler: Handler[T]): T => Unit = (event: T) => handler.handle(event)
47 |
48 | implicit def convertFunctionToVoidAsyncHandler(func: () => Unit): AsyncResultHandler[Void] = new AsyncResultHandler[Void]() {
49 | override def handle(event: AsyncResult[Void]) = func()
50 | }
51 |
52 | implicit def convertFunctionToParameterisedAsyncHandler[T](func: AsyncResult[T] => Unit): AsyncResultHandler[T] = new AsyncResultHandler[T]() {
53 | override def handle(event: AsyncResult[T]) = func(event)
54 | }
55 |
56 | implicit def tryToAsyncResultHandler[X](tryHandler: Try[X] => Unit): AsyncResult[X] => Unit = {
57 | tryHandler.compose { ar: AsyncResult[X] =>
58 | if (ar.succeeded()) {
59 | Success(ar.result())
60 | } else {
61 | Failure(ar.cause())
62 | }
63 | }
64 | }
65 |
66 | def asyncResultConverter[ST, JT](mapFn: JT => ST)(handler: AsyncResult[ST] => Unit): Handler[AsyncResult[JT]] = {
67 | new Handler[AsyncResult[JT]]() {
68 | def handle(ar: AsyncResult[JT]) = {
69 | val scalaAr = new AsyncResult[ST]() {
70 | override def result(): ST = mapFn(ar.result())
71 | override def cause() = ar.cause()
72 | override def succeeded() = ar.succeeded()
73 | override def failed() = ar.failed()
74 | }
75 | handler(scalaAr)
76 | }
77 | }
78 | }
79 |
80 | def asyncHandler[A, B, C](handler: AsyncResult[A] => B, f: C => A): Handler[AsyncResult[C]] = {
81 | new Handler[AsyncResult[C]] {
82 | def handle(rst: AsyncResult[C]) {
83 | handler(
84 | new DefaultFutureResult[A](f(rst.result)))
85 | }
86 | }
87 | }
88 |
89 | def voidAsyncHandler(handler: AsyncResult[Unit] => Unit): Handler[AsyncResult[Void]] = {
90 | new Handler[AsyncResult[Void]] {
91 | def handle(rst: AsyncResult[Void]) {
92 | handler(rst.asInstanceOf[AsyncResult[Unit]])
93 | }
94 | }
95 | }
96 |
97 | }
98 |
99 | object FunctionConverters extends FunctionConverters
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/http/package.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.core
18 |
19 | import org.vertx.java.core.{ MultiMap => JMultiMap }
20 | import scala.collection.mutable
21 | import org.vertx.java.core.http.CaseInsensitiveMultiMap
22 |
23 | package object http {
24 |
25 | type HttpVersion = org.vertx.java.core.http.HttpVersion
26 | type WebSocketVersion = org.vertx.java.core.http.WebSocketVersion
27 |
28 | import scala.language.implicitConversions
29 |
30 | /**
31 | * Implicit conversion for [[org.vertx.java.core.MultiMap]] to [[scala.collection.mutable.MultiMap]].
32 | */
33 | implicit def multiMapToScalaMultiMap(n: JMultiMap): mutable.MultiMap[String, String] = {
34 | new JMultiMapWrapper(n)
35 | }
36 |
37 | /**
38 | * Implicit conversion for [[scala.collection.mutable.MultiMap]] to [[org.vertx.java.core.MultiMap]].
39 | */
40 | implicit def scalaMultiMapToMultiMap(n: mutable.MultiMap[String, String]): JMultiMap = {
41 | val jmultiMap = new CaseInsensitiveMultiMap
42 | n.foreach { entry => jmultiMap.put(entry._1, entry._2)}
43 | jmultiMap
44 | }
45 |
46 | private class JMultiMapWrapper(val underlying: JMultiMap) extends mutable.MultiMap[String, String] {
47 |
48 | override def addBinding(key: String, value: String): this.type = {
49 | underlying.add(key, value)
50 | this
51 | }
52 |
53 | override def removeBinding(key: String, value: String): this.type = {
54 | val it = underlying.iterator()
55 | while (it.hasNext) {
56 | val next = it.next()
57 | if (next.getKey.equalsIgnoreCase(key) && next.getValue == value)
58 | it.remove()
59 | }
60 | this
61 | }
62 |
63 | override def entryExists(key: String, p: (String) => Boolean): Boolean = {
64 | val it = underlying.iterator()
65 | while (it.hasNext) {
66 | val next = it.next()
67 | if (next.getKey.equalsIgnoreCase(key) && p(next.getValue))
68 | return true
69 | }
70 | false
71 | }
72 |
73 | override def iterator: Iterator[(String, mutable.Set[String])] = {
74 | val mm = new mutable.HashMap[String, mutable.Set[String]] with MultiMap
75 | val it = underlying.iterator()
76 | while (it.hasNext) {
77 | val next = it.next()
78 | mm.addBinding(next.getKey, next.getValue)
79 | }
80 | mm.iterator
81 | }
82 |
83 | override def get(key: String): Option[mutable.Set[String]] = {
84 | val set = mutable.HashSet[String]()
85 | val it = underlying.iterator()
86 | while (it.hasNext) {
87 | val next = it.next()
88 | if (next.getKey.equalsIgnoreCase(key))
89 | set.add(next.getValue)
90 | }
91 | if (seq.isEmpty) None else Some(set)
92 | }
93 |
94 | override def -=(key: String): this.type = {
95 | underlying.remove(key)
96 | this
97 | }
98 |
99 | override def +=(kv: (String, mutable.Set[String])): this.type = {
100 | kv._2.foreach { v =>
101 | underlying.add(kv._1, v)
102 | }
103 | this
104 | }
105 |
106 | }
107 |
108 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/parsetools/RecordParser.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2012 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.core.parsetools
18 |
19 | import org.vertx.java.core.parsetools.{ RecordParser => JRecordParser }
20 | import org.vertx.scala.core.buffer._
21 | import scala.language.implicitConversions
22 |
23 |
24 | /**
25 | * A helper class which allows you to easily parse protocols which are delimited by a sequence of bytes, or fixed
26 | * size records.
27 | * Instances of this class take as input [[org.vertx.scala.core.buffer.Buffer]] instances containing raw bytes, and output records.
28 | * For example, if I had a simple ASCII text protocol delimited by '\n' and the input was the following:
29 | *
36 | *
45 | * Instances of this class can't currently be used for protocols where the text is encoded with something other than
46 | * a 1-1 byte-char mapping. TODO extend this class to cope with arbitrary character encodings
47 | *
48 | * @author Tim Fox
49 | */
50 | object RecordParser {
51 | /**
52 | * Helper method to convert a latin-1 String to an array of bytes for use as a delimiter
53 | * Please do not use this for non latin-1 characters
54 | *
55 | * @param str string to convert
56 | * @return The byte[] form of the string
57 | */
58 | def latin1StringToBytes(str: String): Array[Byte] = JRecordParser.latin1StringToBytes(str)
59 |
60 | /**
61 | * Create a new `RecordParser` instance, initially in delimited mode, and where the delimiter can be represented
62 | * by the String delim endcoded in latin-1 . Don't use this if your String contains other than latin-1 characters.
63 | * `output` Will receive whole records which have been parsed.
64 | */
65 | def newDelimited(delim: String, handler: Buffer => Unit) = JRecordParser.newDelimited(delim, bufferHandlerToJava(handler))
66 |
67 | /**
68 | * Create a new `RecordParser` instance, initially in delimited mode, and where the delimiter can be represented
69 | * by the `byte[]` delim.
70 | * `output` Will receive whole records which have been parsed.
71 | */
72 | def newDelimited(delim: Array[Byte], handler: Buffer => Unit) = JRecordParser.newDelimited(delim, bufferHandlerToJava(handler))
73 |
74 | /**
75 | * Create a new `RecordParser` instance, initially in fixed size mode, and where the record size is specified
76 | * by the `size` parameter.
77 | * `output` Will receive whole records which have been parsed.
78 | */
79 | def newFixed(size: Int, handler: Buffer => Unit) = JRecordParser.newFixed(size, bufferHandlerToJava(handler))
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/shareddata/SharedData.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.shareddata
17 |
18 | import org.vertx.java.core.shareddata.{ SharedData => JSharedData }
19 | import scala.collection.concurrent
20 | import scala.collection.mutable
21 | import scala.collection.JavaConversions._
22 |
23 | /**
24 | * Sometimes it is desirable to share immutable data between different event loops, for example to implement a
25 | * cache of data.
26 | * This class allows instances of shared data structures to be looked up and used from different event loops.
27 | * The data structures themselves will only allow certain data types to be stored into them. This shields you from
28 | * worrying about any thread safety issues might occur if mutable objects were shared between event loops.
29 | * The following types can be stored in a shareddata data structure:
30 | *
44 | *
45 | * Instances of this class are thread-safe.
46 | *
47 | * @author Tim Fox
48 | * @author Joern Bernhardt
49 | * @author Galder Zamarreño
50 | */
51 | final class SharedData private[scala] (val asJava: JSharedData) extends AnyVal {
52 |
53 | /**
54 | * Return a [[scala.collection.concurrent.Map]] facade for the internal map
55 | * with the specific `name`. All invocations of this method with the same
56 | * value of `name` are guaranteed to return the same underlying internal
57 | * map instance.
58 | *
59 | * This method converts a Java collection into a Scala collection every
60 | * time it gets called, so use it sensibly.
61 | */
62 | def getMap[K, V](name: String): concurrent.Map[K, V] = mapAsScalaConcurrentMap(asJava.getMap(name))
63 |
64 | /**
65 | * Return a [[scala.collection.mutable.Set]] facade for the internal set
66 | * with the specific `name`. All invocations of this method with the same
67 | * value of `name` are guaranteed to return the same underlying internal
68 | * set instance.
69 | *
70 | * This method converts a Java collection into a Scala collection every
71 | * time it gets called, so use it sensibly.
72 | */
73 | def getSet[E](name: String): mutable.Set[E] = asScalaSet(asJava.getSet(name))
74 |
75 | /**
76 | * Remove the `Map` with the specific `name`.
77 | */
78 | def removeMap(name: String): Boolean = asJava.removeMap(name)
79 |
80 | /**
81 | * Remove the `Set` with the specific `name`.
82 | */
83 | def removeSet(name: String): Boolean = asJava.removeSet(name)
84 |
85 | }
86 |
87 | /** Factory for [[org.vertx.scala.core.shareddata.SharedData]] instances. */
88 | object SharedData {
89 | def apply(actual: JSharedData) = new SharedData(actual)
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/sockjs/EventBusBridgeHook.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.sockjs
17 |
18 | import org.vertx.java.core.sockjs.{EventBusBridgeHook => JEventBusBridgeHook}
19 | import org.vertx.scala.core.json.JsonObject
20 | import org.vertx.scala.core._
21 | import org.vertx.scala.core.FunctionConverters._
22 |
23 | /**
24 | * A hook that you can use to receive various events on the EventBusBridge.
25 | *
26 | * @author Galder Zamarreño
27 | */
28 | final class EventBusBridgeHook private[scala] (val asJava: JEventBusBridgeHook) extends AnyVal {
29 |
30 | /**
31 | * Called when a new socket is created
32 | * You can override this method to do things like check the origin header of a socket before
33 | * accepting it
34 | * @param sock The socket
35 | * @return true to accept the socket, false to reject it
36 | */
37 | def handleSocketCreated(sock: SockJSSocket): Boolean =
38 | asJava.handleSocketCreated(sock.asJava)
39 |
40 | /**
41 | * The socket has been closed
42 | * @param sock The socket
43 | */
44 | def handleSocketClosed(sock: SockJSSocket): Unit =
45 | asJava.handleSocketClosed(sock.asJava)
46 |
47 | /**
48 | * Client is sending or publishing on the socket
49 | * @param sock The sock
50 | * @param send if true it's a send else it's a publish
51 | * @param msg The message
52 | * @param address The address the message is being sent/published to
53 | * @return true To allow the send/publish to occur, false otherwise
54 | */
55 | def handleSendOrPub(sock: SockJSSocket, send: Boolean, msg: JsonObject, address: String): Boolean =
56 | asJava.handleSendOrPub(sock.asJava, send, msg, address)
57 |
58 | /**
59 | * Called before client registers a handler
60 | * @param sock The socket
61 | * @param address The address
62 | * @return true to let the registration occur, false otherwise
63 | */
64 | def handlePreRegister(sock: SockJSSocket, address: String): Boolean =
65 | asJava.handlePreRegister(sock.asJava, address)
66 |
67 | /**
68 | * Called after client registers a handler
69 | * @param sock The socket
70 | * @param address The address
71 | */
72 | def handlePostRegister(sock: SockJSSocket, address: String): Unit =
73 | asJava.handlePostRegister(sock.asJava, address)
74 |
75 | /**
76 | * Client is unregistering a handler
77 | * @param sock The socket
78 | * @param address The address
79 | */
80 | def handleUnregister(sock: SockJSSocket, address: String): Boolean =
81 | asJava.handleUnregister(sock.asJava, address)
82 |
83 | /**
84 | * Called before authorisation - you can override authorisation here if you don't want the default
85 | * @param message The auth message
86 | * @param sessionID The session ID
87 | * @param handler Handler - call this when authorisation is complete
88 | * @return true if you wish to override authorisation
89 | */
90 | def handleAuthorise(message: JsonObject, sessionID: String, handler: AsyncResult[Boolean] => Unit): Boolean =
91 | asJava.handleAuthorise(message, sessionID, asyncResultConverter((x: java.lang.Boolean) => x.booleanValue)(handler))
92 |
93 | }
94 |
95 | object EventBusBridgeHook {
96 | def apply(internal: JEventBusBridgeHook) = new EventBusBridgeHook(internal)
97 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/file/AsyncFile.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.file
17 |
18 | import org.vertx.java.core.file.{ AsyncFile => JAsyncFile }
19 | import org.vertx.scala.core.buffer._
20 | import org.vertx.java.core.buffer.{ Buffer => JBuffer }
21 | import org.vertx.scala.core.{Closeable, AsyncResult}
22 | import org.vertx.scala.core.FunctionConverters._
23 | import org.vertx.scala.core.streams.{WriteStream, ReadStream}
24 | import org.vertx.scala.Self
25 |
26 | /**
27 | * Represents a file on the file-system which can be read from, or written to asynchronously.
28 | * This class also implements [[org.vertx.scala.core.streams.ReadStream]] and
29 | * [[org.vertx.scala.core.streams.WriteStream]]. This allows the data to be pumped to and from
30 | * other streams, e.g. an [[org.vertx.scala.core.http.HttpClientRequest]] instance,
31 | * using the [[org.vertx.scala.core.streams.Pump]] class
32 | * Instances of AsyncFile are not thread-safe
33 | *
34 | * @author Tim Fox
35 | * @author Edgar Chan
36 | * @author swilliams
37 | * @author Joern Bernhardt
38 | * @author Galder Zamarreño
39 | */
40 | final class AsyncFile private[scala] (val asJava: JAsyncFile) extends Self
41 | with ReadStream
42 | with WriteStream
43 | with Closeable {
44 |
45 | override type J = JAsyncFile
46 |
47 | /**
48 | * Write a [[org.vertx.scala.core.buffer.Buffer]] to the file at position `position` in the file, asynchronously.
49 | * If `position` lies outside of the current size
50 | * of the file, the file will be enlarged to encompass it.
51 | * When multiple writes are invoked on the same file
52 | * there are no guarantees as to order in which those writes actually occur.
53 | * The handler will be called when the write is complete, or if an error occurs.
54 | */
55 | def write(buffer: Buffer, position: Int, handler: AsyncResult[Void] => Unit): AsyncFile =
56 | wrap(asJava.write(buffer.asJava, position, handler))
57 |
58 | /**
59 | * Reads `length} bytes of data from the file at position `position` in the file, asynchronously.
60 | * The read data will be written into the specified `Buffer buffer} at position `offset`.
61 | * If data is read past the end of the file then zero bytes will be read.
62 | * When multiple reads are invoked on the same file there are no guarantees as to order in which those reads actually occur.
63 | * The handler will be called when the close is complete, or if an error occurs.
64 | */
65 | def read(buffer: Buffer, offset: Int, position: Int, length: Int, handler: AsyncResult[Buffer] => Unit): AsyncFile =
66 | wrap(asJava.read(buffer.asJava, offset, position, length, asyncResultConverter { jbuf: JBuffer => Buffer.apply(jbuf) }(handler)))
67 |
68 | /**
69 | * Flush any writes made to this file to underlying persistent storage.
70 | * If the file was opened with `flush` set to `true` then calling this method will have no effect.
71 | * The actual flush will happen asynchronously.
72 | */
73 | def flush(): AsyncFile = wrap(asJava.flush())
74 |
75 | /**
76 | * Same as [[org.vertx.scala.core.file.AsyncFile.flush]] but the handler will be called when the flush is complete or if an error occurs
77 | */
78 | def flush(handler: AsyncResult[Void] => Unit): AsyncFile = wrap(asJava.flush(handler))
79 |
80 | }
81 |
82 | /** Factory for [[org.vertx.scala.core.file.AsyncFile]] instances. */
83 | object AsyncFile {
84 | def apply(internal: JAsyncFile) = new AsyncFile(internal)
85 | }
86 |
--------------------------------------------------------------------------------
/README.asciidoc:
--------------------------------------------------------------------------------
1 | = Vert.x 2.x is **deprecated** - use instead https://github.com/vert-x3/vertx-lang-scala
2 |
3 | == Scala Module for Vert.x
4 |
5 | Scala language implementation for Vert.x.
6 |
7 | === Versions
8 |
9 | Vert.x Scala 1.0.x is designed for Vert.x 2.1 and works with Scala 2.10
10 |
11 | === Quickstart
12 |
13 | To use it, we've added a first "Hello World"-like example to the
14 | https://github.com/vert-x/vertx-examples/blob/master/src/raw/scala[Vert.x Examples repository]
15 | which can be run like this:
16 |
17 | 1. Clone or download the https://github.com/vert-x/vertx-examples[Vert.x Examples Git repository]
18 | 2. Change directory to `src/raw/scala` and type:
19 | +
20 | ...............................................................................
21 | [VERTX_HOME]/bin/vertx run http/Server.scala
22 | ...............................................................................
23 | +
24 |
25 | 5. Go to http://localhost:8080/ and you should see the message: ""This is a Verticle script!"
26 |
27 | === Using the Vert.x Scala API
28 |
29 | The best places to look for examples on how to use the Vert.x Scala API are
30 | the https://github.com/vert-x/vertx-examples/blob/master/src/raw/scala[Vert.x Examples repository]
31 | and the https://github.com/vert-x/mod-lang-scala/tree/master/src/test/scala/org/vertx/scala/tests[Vert.x Scala testsuite].
32 | Please inspect those if you have any doubts. The following sub sections explain
33 | some of the items to bear in mind when using this API.
34 |
35 | ==== Type annotations for handlers in for overloaded methods
36 |
37 | In some cases, the Scala compiler can fail to detect the type of a particular
38 | handler, for example:
39 |
40 | +
41 | ...............................................................................
42 | val datagramSocket = vertx.createDatagramSocket()
43 | datagramSocket.send("hello", "127.0.0.1", 1234, { h: AsyncResult[DatagramSocket] =>
44 | ...
45 | }
46 | ...............................................................................
47 | +
48 |
49 | In this example, `send` method call explicitly needs to define the type
50 | annotation for the async result handler. This is because there's an overloaded
51 | method that sends a `org.vertx.scala.core.buffer.Buffer` instead of a String.
52 |
53 | A possible workaround would have been to use function currying, but doing so
54 | would limit the API capability to add `scala.concurrent.Future` based methods,
55 | which are better suited for implementing handlers.
56 |
57 | === Plugging Vert.x Scala language extension
58 |
59 | Vert.x 2.1 comes with Vert.x Scala language support embedded within it, but if
60 | you want to test a different version of the Vert.x Scala language
61 | implementation, follow these instructions:
62 |
63 | 1. Download a Vert.x distribution.
64 | 2. Open `[VERTX_HOME]/conf/langs.properties` file and modify this line to match
65 | the Vert.x Scala version to test:
66 | +
67 | ...............................................................................
68 | scala=io.vertx~lang-scala~X.Y.Z:org.vertx.scala.platform.impl.ScalaVerticleFactory
69 | ...............................................................................
70 | +
71 |
72 | Optionally, if you're testing a locally built Vert.x Scala extension, you'll
73 | need to do the following steps additionally:
74 |
75 | 1. Download latest http://www.scala-sbt.org/download.html[SBT release]
76 | 2. Put `[SBT_HOME]/bin/sbt` or `[SBT_HOME]/bin/sbt.bar` into your path
77 | 3. Clone the Vert.x Scala source repository
78 | 4a. If you want build plugin with the base Scala version used (e.g. 2.10), execute:
79 | +
80 | ...............................................................................
81 | $ sbt clean publishM2
82 | $ [VERTX_HOME]/bin/vertx install io.vertx~lang-scala_2.10~X.Y.Z
83 | ...............................................................................
84 | +
85 | 4b. On the other hand, if you want build plugin with a cross compiled Scala version (e.g. 2.11), execute:
86 | +
87 | ...............................................................................
88 | $ sbt clean +publishM2
89 | $ [VERTX_HOME]/bin/vertx install io.vertx~lang-scala_2.11~X.Y.Z
90 | ...............................................................................
91 | +
92 |
93 | For more information on building Vert.x Scala, check the contributing guide.
94 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/net/NetServer.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.core.net
18 |
19 | import org.vertx.scala.core.FunctionConverters._
20 | import org.vertx.java.core.net.{ NetServer => JNetServer }
21 | import org.vertx.java.core.AsyncResult
22 | import org.vertx.scala.core.ServerSSLSupport
23 | import org.vertx.scala.core.ServerTCPSupport
24 | import org.vertx.scala.core.Closeable
25 | import org.vertx.scala.Self
26 |
27 | /**
28 | * Represents a TCP or SSL server
29 | * If an instance is instantiated from an event loop then the handlers
30 | * of the instance will always be called on that same event loop.
31 | * If an instance is instantiated from some other arbitrary Java thread (i.e. when running embedded) then
32 | * and event loop will be assigned to the instance and used when any of its handlers
33 | * are called.
34 | * Instances of this class are thread-safe.
35 | *
36 | * @author Tim Fox
37 | * @author swilliams
38 | * @author Joern Bernhardt
39 | * @author Galder Zamarreño
40 | */
41 | final class NetServer private[scala] (val asJava: JNetServer) extends Self
42 | with ServerSSLSupport
43 | with ServerTCPSupport
44 | with Closeable {
45 |
46 | override type J = JNetServer
47 |
48 | /**
49 | * Supply a connect handler for this server. The server can only have at most one connect handler at any one time.
50 | * As the server accepts TCP or SSL connections it creates an instance of [[org.vertx.scala.core.net.NetSocket]] and passes it to the
51 | * connect handler.
52 | * @return a reference to this so multiple method calls can be chained together
53 | */
54 | def connectHandler(connectHandler: NetSocket => Unit): NetServer =
55 | wrap(asJava.connectHandler(connectHandler.compose(NetSocket.apply)))
56 |
57 | /**
58 | * Tell the server to start listening on all available interfaces and port `port`. Be aware this is an
59 | * async operation and the server may not bound on return of the method.
60 | */
61 | def listen(port: Int): NetServer = wrap(asJava.listen(port))
62 |
63 | /**
64 | * Instruct the server to listen for incoming connections on the specified `port` and all available interfaces.
65 | */
66 | def listen(port: Int, listenHandler: AsyncResult[NetServer] => Unit): NetServer =
67 | wrap(asJava.listen(port, arNetServer(listenHandler)))
68 |
69 | /**
70 | * Tell the server to start listening on port `port` and hostname or ip address given by `host`. Be aware this is an
71 | * async operation and the server may not bound on return of the method.
72 | *
73 | */
74 | def listen(port: Int, host: String): NetServer = wrap(asJava.listen(port, host))
75 |
76 | /**
77 | * Instruct the server to listen for incoming connections on the specified `port` and `host`. `host` can
78 | * be a host name or an IP address.
79 | */
80 | def listen(port: Int, host: String, listenHandler: AsyncResult[NetServer] => Unit): NetServer =
81 | wrap(asJava.listen(port, host, arNetServer(listenHandler)))
82 |
83 | /**
84 | * The actual port the server is listening on. This is useful if you bound the server specifying 0 as port number
85 | * signifying an ephemeral port
86 | */
87 | def port(): Int = asJava.port()
88 |
89 | /**
90 | * The host.
91 | */
92 | def host(): String = asJava.host()
93 |
94 | private def arNetServer = asyncResultConverter(NetServer.apply) _
95 |
96 | }
97 |
98 | /** Factory for [[org.vertx.scala.core.net.NetServer]] instances. */
99 | object NetServer {
100 | def apply(actual: JNetServer) = new NetServer(actual)
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/streams/Pump.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.streams
17 |
18 | import org.vertx.java.core.streams.{ Pump => JPump }
19 | import org.vertx.scala.Self
20 |
21 | /**
22 | * Pumps data from a [[org.vertx.scala.core.streams.ReadStream]] to a
23 | * [[org.vertx.scala.core.streams.WriteStream]] and performs flow control where necessary to
24 | * prevent the write stream buffer from getting overfull.
25 | * Instances of this class read bytes from a [[org.vertx.scala.core.streams.ReadStream]]
26 | * and write them to a [[org.vertx.scala.core.streams.WriteStream]]. If data
27 | * can be read faster than it can be written this could result in the write
28 | * queue of the [[org.vertx.scala.core.streams.WriteStream]] growing
29 | * without bound, eventually causing it to exhaust all available RAM.
30 | * To prevent this, after each write, instances of this class check whether the write queue of the
31 | * [[org.vertx.scala.core.streams.WriteStream]] is full, and if so, the
32 | * [[org.vertx.scala.core.streams.ReadStream]] is paused, and a `drainHandler` is set on the
33 | * [[org.vertx.scala.core.streams.WriteStream]]. When the [[org.vertx.scala.core.streams.WriteStream]]
34 | * has processed half of its backlog, the `drainHandler` will be
35 | * called, which results in the pump resuming the [[org.vertx.scala.core.streams.ReadStream]].
36 | * This class can be used to pump from any [[org.vertx.scala.core.streams.ReadStream]]
37 | * to any [[org.vertx.scala.core.streams.WriteStream]], e.g. from an
38 | * [[org.vertx.scala.core.http.HttpServerRequest]] to an [[org.vertx.scala.core.file.AsyncFile]],
39 | * or from [[org.vertx.scala.core.net.NetSocket]] to a [[org.vertx.scala.core.http.WebSocket]].
40 | *
41 | * Instances of this class are not thread-safe.
42 | *
43 | * @author Tim Fox
44 | * @author swilliams
45 | * @author Joern Bernhardt
46 | */
47 | final class Pump private[scala] (val asJava: JPump) extends Self {
48 |
49 | /**
50 | * Set the write queue max size to `maxSize`
51 | */
52 | def setWriteQueueMaxSize(maxSize: Int): Pump = wrap(asJava.setWriteQueueMaxSize(maxSize))
53 |
54 | /**
55 | * Start the Pump. The Pump can be started and stopped multiple times.
56 | */
57 | def start(): Pump = wrap(asJava.start())
58 |
59 | /**
60 | * Stop the Pump. The Pump can be started and stopped multiple times.
61 | */
62 | def stop(): Pump = wrap(asJava.stop())
63 |
64 | /**
65 | * Return the total number of bytes pumped by this pump.
66 | */
67 | def bytesPumped(): Int = asJava.bytesPumped()
68 |
69 | }
70 |
71 | object Pump {
72 |
73 | /**
74 | * Create a new `Pump` with the given `ReadStream` and `WriteStream`
75 | */
76 | def apply[A <: ReadStream, B <: WriteStream](rs: ReadStream, ws: WriteStream) = createPump(rs, ws)
77 |
78 | /**
79 | * Create a new `Pump` with the given `ReadStream` and `WriteStream` and
80 | * `writeQueueMaxSize`
81 | */
82 | def apply[A <: ReadStream, B <: WriteStream](rs: ReadStream, ws: WriteStream, writeQueueMaxSize: Int) =
83 | createPump(rs, ws, writeQueueMaxSize)
84 |
85 | /**
86 | * Create a new `Pump` with the given `ReadStream` and `WriteStream`
87 | */
88 | def createPump[A <: ReadStream, B <: WriteStream](rs: ReadStream, ws: WriteStream) =
89 | new Pump(JPump.createPump(rs.asJava, ws.asJava))
90 |
91 | /**
92 | * Create a new `Pump` with the given `ReadStream` and `WriteStream` and
93 | * `writeQueueMaxSize`
94 | */
95 | def createPump[A <: ReadStream, B <: WriteStream](rs: ReadStream, ws: WriteStream, writeQueueMaxSize: Int) =
96 | new Pump(JPump.createPump(rs.asJava, ws.asJava, writeQueueMaxSize))
97 |
98 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/lang/ScalaInterpreter.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.lang
2 |
3 | import java.io.{ File, PrintWriter }
4 | import scala.annotation.tailrec
5 | import scala.io.Source
6 | import scala.reflect.internal.util.BatchSourceFile
7 | import scala.reflect.io.PlainFile
8 | import scala.tools.nsc.Settings
9 | import scala.tools.nsc.interpreter.{NamedParamClass, IMain}
10 | import scala.tools.nsc.interpreter.Results.Result
11 | import scala.tools.nsc.interpreter.Results.{ Error => InterpreterError }
12 | import scala.tools.nsc.interpreter.Results.{ Incomplete => InterpreterIncomplete}
13 | import scala.tools.nsc.interpreter.Results.{ Success => InterpreterSuccess }
14 | import org.vertx.scala.core.Vertx
15 | import scala.tools.nsc.NewLinePrintWriter
16 | import scala.tools.nsc.ConsoleWriter
17 | import java.net.URL
18 | import org.vertx.scala.platform.Container
19 | import scala.util.{Success, Failure, Try}
20 |
21 | /**
22 | * Scala interpreter
23 | *
24 | * @author Galder Zamarreño
25 | */
26 | class ScalaInterpreter(
27 | settings: Settings,
28 | vertx: Vertx,
29 | container: Container,
30 | out: PrintWriter = new NewLinePrintWriter(new ConsoleWriter, true)) {
31 |
32 | private val interpreter = new IMain(settings, out)
33 | interpreter.setContextClassLoader()
34 |
35 | def addBootClasspathJar(path: String): Unit =
36 | settings.bootclasspath.append(path)
37 |
38 | def close(): Unit = interpreter.close()
39 |
40 | def runScript(script: URL): Try[Unit] = {
41 | val content = Source.fromURL(script).mkString
42 | val ops = List(
43 | () => addImport("org.vertx.scala._"),
44 | () => addImport("org.vertx.scala.core._"),
45 | () => addImport("org.vertx.scala.core.buffer._"),
46 | () => addImport("org.vertx.scala.core.dns._"),
47 | () => addImport("org.vertx.scala.core.eventbus._"),
48 | () => addImport("org.vertx.scala.core.file._"),
49 | () => addImport("org.vertx.scala.core.http._"),
50 | () => addImport("org.vertx.scala.core.json._"),
51 | () => addImport("org.vertx.scala.core.net._"),
52 | () => addImport("org.vertx.scala.core.streams._"),
53 | () => bind("vertx", "org.vertx.scala.core.Vertx", vertx),
54 | () => bind("container", "org.vertx.scala.platform.Container", container),
55 | () => interpret(content)
56 | )
57 | val result = interpret(ops, InterpreterIncomplete)
58 | result match {
59 | case InterpreterError => Failure(new ScalaCompilerError(s"Interpreter error running $script"))
60 | case InterpreterIncomplete => Failure(new ScalaCompilerError(s"Incomplete script $script"))
61 | case InterpreterSuccess => Success()
62 | }
63 | }
64 |
65 | private def addImport(id: String): Result =
66 | interpret("import " + id)
67 |
68 | private def bind(name: String, boundType: String, value: Any): Result =
69 | verboseOrQuiet(
70 | interpreter.bind(name, boundType, value),
71 | interpreter.quietBind(NamedParamClass(name, boundType, value)))
72 |
73 | private def interpret(content: String): Result =
74 | verboseOrQuiet(
75 | interpreter.interpret(content),
76 | interpreter.beQuietDuring(interpreter.interpret(content)))
77 |
78 | private def verboseOrQuiet(verbose: => Result, quiet: => Result): Result = {
79 | if (ScalaInterpreter.isVerbose) verbose else quiet
80 | }
81 |
82 | def compileClass(classFile: File): Try[ClassLoader] = {
83 | val source = new BatchSourceFile(new PlainFile(classFile))
84 | val result = interpreter.compileSources(source)
85 | if (result)
86 | Success(interpreter.classLoader)
87 | else
88 | Failure(new IllegalArgumentException(s"Unable to compile $classFile"))
89 | }
90 |
91 | @tailrec
92 | private def interpret(ops: List[() => Result], accumulate: Result): Result = {
93 | ops match {
94 | case List() => accumulate
95 | case x :: xs =>
96 | val result = x()
97 | result match {
98 | case InterpreterError | InterpreterIncomplete => result
99 | case InterpreterSuccess => interpret(xs, result)
100 | }
101 | }
102 | }
103 |
104 | private class ScalaCompilerError(message: String) extends Exception(message)
105 | }
106 |
107 | object ScalaInterpreter {
108 |
109 | def isVerbose: Boolean =
110 | System.getProperty("vertx.scala.interpreter.verbose", "false").toBoolean
111 |
112 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/http/HttpClientResponse.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.core.http
18 |
19 | import org.vertx.java.core.http.{ HttpClientResponse => JHttpClientResponse }
20 | import org.vertx.scala.core.MultiMap
21 | import org.vertx.scala.core.buffer._
22 | import org.vertx.scala.core.net.NetSocket
23 | import org.vertx.scala.core.streams.ReadStream
24 | import org.vertx.scala.Self
25 | import scala.collection.JavaConverters._
26 |
27 | /**
28 | * Represents a client-side HTTP response.
29 | * An instance is provided to the user via a [[org.vertx.java.core.Handler]]
30 | * instance that was specified when one of the HTTP method operations, or the
31 | * generic [[org.vertx.scala.core.http.HttpClient.request(String, String, org.vertx.java.core.Handler)]]
32 | * method was called on an instance of [[org.vertx.scala.core.http.HttpClient]].
33 | * It implements [[org.vertx.scala.core.streams.ReadStream]] so it can be used with
34 | * [[org.vertx.scala.core.streams.Pump]] to pump data with flow control.
35 | * Instances of this class are not thread-safe.
36 | *
37 | * @author Tim Fox
38 | * @author swilliams
39 | * @author Joern Bernhardt
40 | */
41 | class HttpClientResponse private[scala] (val asJava: JHttpClientResponse) extends Self
42 | with ReadStream {
43 |
44 | override type J = JHttpClientResponse
45 |
46 | /**
47 | * Returns the HTTP status code of the response.
48 | *
49 | * @return The HTTP status code of the response.
50 | */
51 | def statusCode(): Int = asJava.statusCode
52 |
53 | /**
54 | * Returns the HTTP status message of the response.
55 | *
56 | * @return The HTTP status message of the response.
57 | */
58 | def statusMessage(): String = asJava.statusMessage
59 |
60 | /**
61 | * Returns the HTTP headers.
62 | *
63 | * This method converts a Java collection into a Scala collection every
64 | * time it gets called, so use it sensibly.
65 | *
66 | * @return The HTTP headers.
67 | */
68 | def headers(): MultiMap = multiMapToScalaMultiMap(asJava.headers)
69 |
70 | /**
71 | * Returns the HTTP trailers.
72 | *
73 | * This method converts a Java collection into a Scala collection every
74 | * time it gets called, so call it sensibly.
75 | *
76 | * @return The HTTP trailers.
77 | */
78 | def trailers(): MultiMap = multiMapToScalaMultiMap(asJava.trailers)
79 |
80 | /**
81 | * Returns the Set-Cookie headers (including trailers).
82 | *
83 | * @return The Set-Cookie headers (including trailers).
84 | */
85 | def cookies(): List[String] = asJava.cookies().asScala.toList
86 |
87 | /**
88 | * Convenience method for receiving the entire request body in one piece. This saves the user having to manually
89 | * set a data and end handler and append the chunks of the body until the whole body received.
90 | * Don't use this if your request body is large - you could potentially run out of RAM.
91 | *
92 | * @param handler This handler will be called after all the body has been received.
93 | */
94 | def bodyHandler(handler: Buffer => Unit): HttpClientResponse =
95 | wrap(asJava.bodyHandler(bufferHandlerToJava(handler)))
96 |
97 | /**
98 | * Get a net socket for the underlying connection of this request. USE THIS WITH CAUTION!
99 | * Writing to the socket directly if you don't know what you're doing can easily break the HTTP protocol.
100 | *
101 | * One valid use-case for calling this is to receive the [[NetSocket]] after a HTTP CONNECT was issued to the
102 | * remote peer and it responded with a status code of 200.
103 | *
104 | * @return the net socket
105 | */
106 | def netSocket(): NetSocket = NetSocket(asJava.netSocket())
107 |
108 | }
109 |
110 | /** Factory for [[org.vertx.scala.core.http.HttpClient]] instances by wrapping a Java instance. */
111 | object HttpClientResponse {
112 | def apply(internal: JHttpClientResponse) = new HttpClientResponse(internal)
113 | }
114 |
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/core/http/WebSocketsTest.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.tests.core.http
2 |
3 | import org.vertx.scala.testtools.TestVerticle
4 | import org.vertx.testtools.VertxAssert._
5 | import org.junit.Test
6 | import org.vertx.scala.core.AsyncResult
7 | import org.vertx.scala.core.http.HttpServer
8 | import org.vertx.scala.core.http.HttpClient
9 | import org.vertx.scala.core.http.HttpClientResponse
10 | import org.vertx.scala.core.http.ServerWebSocket
11 | import org.vertx.scala.core.http.WebSocket
12 | import org.vertx.scala.core.buffer.Buffer
13 | import org.vertx.scala.tests.util.TestUtils._
14 |
15 | class WebSocketsTest extends TestVerticle {
16 | val testPort = 8844
17 |
18 | val html =
19 |
29 | * Instances of this class are created on the client side by an [[org.vertx.scala.core.net.NetClient]]
30 | * when a connection to a server is made, or on the server side by a [[org.vertx.scala.core.net.NetServer]]
31 | * when a server accepts a connection.
32 | * It implements both [[org.vertx.scala.core.streams.ReadStream]] and [[org.vertx.scala.core.streams.WriteStream]] so it can be used with
33 | * [[org.vertx.java.core.streams.Pump]] to pump data with flow control.
34 | * Instances of this class are not thread-safe.
35 | *
36 | * @author Tim Fox
37 | * @author swilliams
38 | * @author Joern Bernhardt
39 | * @author Galder Zamarreño
40 | */
41 | final class NetSocket private[scala] (val asJava: JNetSocket) extends Self
42 | with ReadStream
43 | with WriteStream {
44 |
45 | override type J = JNetSocket
46 |
47 | /**
48 | * When a `NetSocket` is created it automatically registers an event handler with the event bus, the ID of that
49 | * handler is given by `writeHandlerID`.
50 | * Given this ID, a different event loop can send a buffer to that event handler using the event bus and
51 | * that buffer will be received by this instance in its own event loop and written to the underlying connection. This
52 | * allows you to write data to other connections which are owned by different event loops.
53 | */
54 | def writeHandlerID(): String = asJava.writeHandlerID
55 |
56 | /**
57 | * Write a [[java.lang.String]] to the connection, encoded in UTF-8.
58 | * @return A reference to this, so multiple method calls can be chained.
59 | */
60 | def write(data: String): NetSocket = wrap(asJava.write(data))
61 |
62 | /**
63 | * Write a [[java.lang.String]] to the connection, encoded using the encoding `enc`.
64 | * @return A reference to this, so multiple method calls can be chained.
65 | */
66 | def write(data: String, enc: String): NetSocket = wrap(asJava.write(data, enc))
67 |
68 | /**
69 | * Tell the kernel to stream a file as specified by `filename` directly from disk to the outgoing connection,
70 | * bypassing userspace altogether (where supported by the underlying operating system. This is a very efficient way to stream files.
71 | */
72 | def sendFile(filename: String): NetSocket = wrap(asJava.sendFile(filename))
73 |
74 | /**
75 | * Same as [[NetSocket.sendFile()]] but also takes a handler that will be
76 | * called when the send has completed or a failure has occurred
77 | */
78 | def sendFile(filename: String, handler: AsyncResult[Void] => Unit): NetSocket =
79 | wrap(asJava.sendFile(filename, fnToHandler(handler)))
80 |
81 | /**
82 | * Return the remote address for this socket
83 | */
84 | def remoteAddress(): InetSocketAddress = asJava.remoteAddress()
85 |
86 | /**
87 | * Return the local address for this socket
88 | */
89 | def localAddress(): InetSocketAddress = asJava.localAddress()
90 |
91 | /**
92 | * Close the NetSocket
93 | */
94 | def close(): Unit = asJava.close()
95 |
96 | /**
97 | * Set a handler that will be called when the NetSocket is closed
98 | */
99 | def closeHandler(handler: => Unit): NetSocket = wrap(asJava.closeHandler(handler))
100 |
101 | /**
102 | * Upgrade channel to use SSL/TLS. Be aware that for this to work SSL must be configured.
103 | */
104 | def ssl(handler: => Unit): NetSocket = wrap(asJava.ssl(handler))
105 |
106 | /**
107 | * Returns `true` if this [[org.vertx.scala.core.net.NetSocket]] is encrypted via SSL/TLS.
108 | */
109 | def isSsl: Boolean = asJava.isSsl
110 | }
111 |
112 | object NetSocket {
113 | def apply(socket: JNetSocket) = new NetSocket(socket)
114 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/http/RouteMatcher.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.core.http
18 |
19 | import org.vertx.java.core.Handler
20 | import org.vertx.java.core.http.{ RouteMatcher => JRouteMatcher }
21 | import org.vertx.scala.core.FunctionConverters._
22 | import org.vertx.scala.Self
23 |
24 | /**
25 | * Not sure whether this kind of RouteMatcher should stay in Scala...
26 | *
27 | * @author swilliams
28 | * @author Joern Bernhardt
29 | * @author Galder Zamarreño
30 | */
31 | class RouteMatcher private[scala] (val asJava: JRouteMatcher = new JRouteMatcher()) extends Handler[HttpServerRequest]
32 | with (HttpServerRequest => Unit)
33 | with Self {
34 |
35 | def all(uri: String, handler: HttpServerRequest => Unit): RouteMatcher =
36 | wrap(asJava.all(uri, wrapHandler(handler)))
37 |
38 | def allWithRegEx(regex: String, handler: HttpServerRequest => Unit): RouteMatcher =
39 | wrap(asJava.allWithRegEx(regex, wrapHandler(handler)))
40 |
41 | def apply(request: HttpServerRequest): Unit = handle(request)
42 |
43 | def connect(uri: String, handler: HttpServerRequest => Unit): RouteMatcher =
44 | wrap(asJava.connect(uri, wrapHandler(handler)))
45 |
46 | def connectWithRegEx(regex: String, handler: HttpServerRequest => Unit): RouteMatcher =
47 | wrap(asJava.connectWithRegEx(regex, wrapHandler(handler)))
48 |
49 | def delete(uri: String, handler: HttpServerRequest => Unit): RouteMatcher =
50 | wrap(asJava.delete(uri, wrapHandler(handler)))
51 |
52 | def deleteWithRegEx(regex: String, handler: HttpServerRequest => Unit): RouteMatcher =
53 | wrap(asJava.deleteWithRegEx(regex, wrapHandler(handler)))
54 |
55 | def get(uri: String, handler: HttpServerRequest => Unit): RouteMatcher =
56 | wrap(asJava.get(uri, wrapHandler(handler)))
57 |
58 | def getWithRegEx(regex: String, handler: HttpServerRequest => Unit): RouteMatcher =
59 | wrap(asJava.getWithRegEx(regex, wrapHandler(handler)))
60 |
61 | def handle(request: HttpServerRequest): Unit = asJava.handle(request.asJava)
62 |
63 | def head(uri: String, handler: HttpServerRequest => Unit): RouteMatcher =
64 | wrap(asJava.head(uri, wrapHandler(handler)))
65 |
66 | def headWithRegEx(regex: String, handler: HttpServerRequest => Unit): RouteMatcher =
67 | wrap(asJava.headWithRegEx(regex, wrapHandler(handler)))
68 |
69 | def options(uri: String, handler: HttpServerRequest => Unit): RouteMatcher =
70 | wrap(asJava.options(uri, wrapHandler(handler)))
71 |
72 | def optionsWithRegEx(regex: String, handler: HttpServerRequest => Unit): RouteMatcher =
73 | wrap(asJava.optionsWithRegEx(regex, wrapHandler(handler)))
74 |
75 | def patch(uri: String, handler: HttpServerRequest => Unit): RouteMatcher =
76 | wrap(asJava.patch(uri, wrapHandler(handler)))
77 |
78 | def patchWithRegEx(regex: String, handler: HttpServerRequest => Unit): RouteMatcher =
79 | wrap(asJava.patchWithRegEx(regex, wrapHandler(handler)))
80 |
81 | def post(uri: String, handler: HttpServerRequest => Unit): RouteMatcher =
82 | wrap(asJava.post(uri, wrapHandler(handler)))
83 |
84 | def postWithRegEx(regex: String, handler: HttpServerRequest => Unit): RouteMatcher =
85 | wrap(asJava.postWithRegEx(regex, wrapHandler(handler)))
86 |
87 | def put(uri: String, handler: HttpServerRequest => Unit): RouteMatcher =
88 | wrap(asJava.put(uri, wrapHandler(handler)))
89 |
90 | def putWithRegEx(regex: String, handler: HttpServerRequest => Unit): RouteMatcher =
91 | wrap(asJava.putWithRegEx(regex, wrapHandler(handler)))
92 |
93 | def trace(uri: String, handler: HttpServerRequest => Unit): RouteMatcher =
94 | wrap(asJava.trace(uri, wrapHandler(handler)))
95 |
96 | def traceWithRegEx(regex: String, handler: HttpServerRequest => Unit): RouteMatcher =
97 | wrap(asJava.traceWithRegEx(regex, wrapHandler(handler)))
98 |
99 | private def wrapHandler(handler: HttpServerRequest => Unit) =
100 | fnToHandler(handler.compose(HttpServerRequest.apply))
101 |
102 | }
103 |
104 | /** Factory for [[org.vertx.scala.core.http.RouteMatcher]] instances. */
105 | object RouteMatcher {
106 | def apply(actual: JRouteMatcher): RouteMatcher = new RouteMatcher(actual)
107 | def apply(): RouteMatcher = new RouteMatcher()
108 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/net/NetClient.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.core.net
18 |
19 | import org.vertx.java.core.net.{ NetClient => JNetClient }
20 | import org.vertx.scala.core.FunctionConverters._
21 | import org.vertx.scala.core.TCPSupport
22 | import org.vertx.scala.core.ClientSSLSupport
23 | import org.vertx.scala.core.AsyncResult
24 | import org.vertx.scala.Self
25 |
26 | /**
27 | * A TCP/SSL client.
28 | * Multiple connections to different servers can be made using the same instance.
29 | * This client supports a configurable number of connection attempts and a configurable delay
30 | * between attempts.
31 | * If an instance is instantiated from an event loop then the handlers of the instance will always
32 | * be called on that same event loop. If an instance is instantiated from some other arbitrary Java
33 | * thread (i.e. when using embedded) then an event loop will be assigned to the instance and used
34 | * when any of its handlers are called.
35 | * Instances of this class are thread-safe.
36 | *
37 | * @author Tim Fox
38 | * @author swilliams
39 | * @author Edgar Chan
40 | * @author Joern Bernhardt
41 | * @author Galder Zamarreño
42 | */
43 | final class NetClient private[scala] (val asJava: JNetClient) extends Self
44 | with TCPSupport
45 | with ClientSSLSupport {
46 |
47 | override type J = JNetClient
48 |
49 | /**
50 | * Attempt to open a connection to a server at the specific `port` and host `localhost`
51 | * The connect is done asynchronously and on success, a
52 | * [[org.vertx.scala.core.net.NetSocket]] instance is supplied via the `connectHandler` instance.
53 | *
54 | * @return A reference to this so multiple method calls can be chained together.
55 | */
56 | def connect(port: Int, connectCallback: AsyncResult[NetSocket] => Unit): NetClient =
57 | wrap(asJava.connect(port, arNetSocket(connectCallback)))
58 |
59 | /**
60 | * Attempt to open a connection to a server at the specific `port` and `host`.
61 | * `host` can be a valid host name or IP address. The connect is done asynchronously and on success, a
62 | * [[org.vertx.scala.core.net.NetSocket]] instance is supplied via the `connectHandler` instance.
63 | *
64 | * @return a reference to this so multiple method calls can be chained together
65 | */
66 | def connect(port: Int, host: String, connectHandler: AsyncResult[NetSocket] => Unit): NetClient =
67 | wrap(asJava.connect(port, host, arNetSocket(connectHandler)))
68 |
69 | /**
70 | * Set the number of reconnection attempts. In the event a connection attempt fails, the client will attempt
71 | * to connect a further number of times, before it fails. Default value is zero.
72 | */
73 | def setReconnectAttempts(attempts: Int): NetClient =
74 | wrap(asJava.setReconnectAttempts(attempts))
75 |
76 | /**
77 | * Get the number of reconnect attempts.
78 | *
79 | * @return The number of reconnect attempts.
80 | */
81 | def getReconnectAttempts: Int = asJava.getReconnectAttempts
82 |
83 | /**
84 | * Set the reconnect interval, in milliseconds.
85 | */
86 | def setReconnectInterval(interval: Long): NetClient =
87 | wrap(asJava.setReconnectInterval(interval))
88 |
89 | /**
90 | * Get the reconnect interval, in milliseconds.
91 | *
92 | * @return The reconnect interval in milliseconds.
93 | */
94 | def getReconnectInterval: Long = asJava.getReconnectInterval
95 |
96 | /**
97 | * Set the connect timeout in milliseconds.
98 | *
99 | * @return a reference to this so multiple method calls can be chained together
100 | */
101 | def setConnectTimeout(timeout: Int): NetClient =
102 | wrap(asJava.setConnectTimeout(timeout))
103 |
104 | /**
105 | * Returns the connect timeout in milliseconds.
106 | *
107 | * @return The connect timeout in milliseconds.
108 | */
109 | def getConnectTimeout: Int = asJava.getConnectTimeout
110 |
111 | /**
112 | * Close the client. Any sockets which have not been closed manually will be closed here.
113 | */
114 | def close(): Unit = asJava.close()
115 |
116 | private def arNetSocket = asyncResultConverter(NetSocket.apply) _
117 | }
118 |
119 | /** Factory for [[org.vertx.scala.core.net.NetClient]] instances. */
120 | object NetClient {
121 | def apply(actual: JNetClient) = new NetClient(actual)
122 | }
123 |
--------------------------------------------------------------------------------
/ADMIN.md:
--------------------------------------------------------------------------------
1 | This guide walks through the basics on administrating the mod-lang-scala repository.
2 | Make sure you read the contribution guidelines in `CONTRIBUTE.md` before reading
3 | this file.
4 |
5 | # Source control - Git
6 | mod-lang-scala uses git, hosted on GitHub, for version control. In this section,
7 | we'll review the tasks and responsibilities of a mod-lang-scala repository
8 | Project Admin.
9 |
10 | ## Project Admin
11 | Project Admins have a very limited role. Only Project Admins are allowed to
12 | push to upstream, and Project Admins never write any code directly on the
13 | upstream repository. All Project Admins do is pull in and merge changes from
14 | contributors (even if the "contributor" happens to be themselves) into
15 | upstream, perform code reviews and either commit or reject such changes.
16 |
17 | > All Contributors who are also Project Admins are encouraged to not merge
18 | their own changes, to ensure that all changes are reviewed.
19 |
20 | This approach ensures mod-lang-scala maintains quality on the main code source
21 | tree, and allows for important code reviews to take place again ensuring
22 | quality. Further, it ensures clean and easily traceable code history and makes
23 | sure that more than one person knows about the changes being performed.
24 |
25 | ### Merging in patches
26 |
27 | ![Figure 2-1]
28 | (https://docs.jboss.org/author/download/attachments/4784485/git_wf_3.png "Merging patch")
29 |
30 | Patches submitted via JIRA are audited and promoted to the upstream repository
31 | as detailed above. A Project Admin would typically create a working branch to
32 | which the patch is applied and tested. The patch can be further modified,
33 | cleaned up, and commit messages made clearer if necessary. The branch should
34 | then be merged to the master or one of the maintenance branches before being
35 | pushed.
36 |
37 | More information on applying patches can be found in
38 | [Chapter 5, Section 3 of Pro Git](http://progit.org/book/ch5-3.html), under
39 | **Applying Patches From Email**.
40 |
41 | ### Handling pull requests
42 |
43 | ![Figure 2-2]
44 | (https://docs.jboss.org/author/download/attachments/4784485/git_wf_4.png "Handling pull request")
45 |
46 | Project Admins are also responsible for responding to pull requests. The
47 | process is similar to applying a patch directly, except that when pulling in
48 | changes from a forked repository, more than a single commit may be pulled in.
49 | Again, this should be done on a newly created working branch, code reviewed,
50 | tested and cleaned up as necessary.
51 |
52 | If commits need to be altered - e.g., rebasing to squash or split commits, or
53 | to alter commit messages - it is often better to contact the Contributor and
54 | ask the Contributor to do so and re-issue the pull request, since doing so on
55 | the upstream repo could cause update issues for contributors later on. If
56 | commits were altered or three-way merge was performed during a merge instead
57 | of fast-forward, it's also a good idea to check the log to make sure that the
58 | resulting repository history looks OK:
59 |
60 | $ git log --pretty=oneline --graph --abbrev-commit # History messed up due to a bad merge
61 | * 3005020 Merge branch 'ISPN-786' of git://github.com/Sanne/infinispan
62 | |\
63 | | * e757265 ISPN-786 Make dependency to log4j optional <-- Same with cb4e5d6 - unnecessary
64 | * | cb4e5d6 ISPN-786 Make dependency to log4j optional <-- Cherry-picked commit by other admin
65 | |/
66 | * ...
67 |
68 | $ git reset cb4e5d6 # revert the bad merge
69 |
70 | It is therefore strongly recommended that you use the [handle_pull_request]
71 | (https://github.com/maniksurtani/githelpers/blob/master/project_admins/handle_pull_request)
72 | script that ensures a clean merge. If you still wish to do this manually,
73 | please consider reading through the script first to get an idea of what needs
74 | to happen.
75 |
76 | More information on pulling changes from remote, forked repos can be found in
77 | [Chapter 5, Section 3 of Pro Git](http://progit.org/book/ch5-3.html), under
78 | **Checking Out Remote Branches**.
79 |
80 | #### Possible trouble handling pull requests
81 | If you have warnings about "Merge made by recursive" you have to fix it rebasing.
82 | If you have warnings about "non-fast-forward" you have to rebase. If you see
83 | "non-fast-forward updates were rejected" you shall never use "force" on upstream!
84 | It means that another patch was merged before you and you have to update your
85 | master again, and rebase again. "force" is allowed only in special maintenance
86 | circumstances. If you find you're needing it to handle a pull request, then
87 | you're doing it wrong, and the mistake might be a dangerous one! It's like the
88 | good rule of never commit when you're drunk (coding is allowed).
89 |
90 | > **Never use force on git push!** Using -f while pushing on a shared repository
91 | such as upstream you could effectively erase other committed patches. Noone
92 | shall ever use this option unless unanimously approved on the public mailing
93 | list: the most dangerous aspect of it is that nobody gets any notification if
94 | this happens, and we might think issues are solved but you silently removed
95 | the fix and it's history from the repository.
96 |
97 | ### Cutting releases
98 | Releases can only me cut by Project Admins... TBD.
99 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/platform/Container.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.platform
17 |
18 | import scala.language.implicitConversions
19 | import scala.collection.JavaConverters._
20 | import org.vertx.java.platform.{ Container => JContainer }
21 | import org.vertx.scala.core.AsyncResult
22 | import org.vertx.scala.core.json._
23 | import org.vertx.scala.core.FunctionConverters._
24 | import org.vertx.scala.core.logging.Logger
25 |
26 | /**
27 | * This class represents a Verticle's view of the container in which it is running.
28 | * An instance of this class will be created by the system and made available to
29 | * a running Verticle.
30 | * It contains methods to programmatically deploy other verticles, undeploy
31 | * verticles, deploy modules, get the configuration for a verticle and get the logger for a
32 | * verticle, amongst other things.
33 | *
34 | * @author Tim Fox
35 | * @author swilliams
36 | * @author Joern Bernhardt
37 | * @author Galder Zamarreño
38 | */
39 | final class Container private[scala] (val asJava: JContainer) extends AnyVal {
40 |
41 | /**
42 | * Deploy a module programmatically
43 | * @param name The main of the module to deploy
44 | * @param config JSON config to provide to the module
45 | * @param instances The number of instances to deploy (defaults to 1)
46 | * @param handler The handler will be called passing in the unique deployment id when deployment is complete
47 | */
48 | def deployModule(name: String, config: JsonObject = Json.emptyObj(), instances: Int = 1, handler: AsyncResult[String] => Unit = { ar: AsyncResult[String] => }): Unit =
49 | asJava.deployModule(name, config, instances, handler)
50 |
51 | /**
52 | * Deploy a verticle programmatically
53 | * @param name The main of the verticle
54 | * @param config JSON config to provide to the verticle
55 | * @param instances The number of instances to deploy (defaults to 1)
56 | * @param handler The handler will be called passing in the unique deployment id when deployment is complete
57 | */
58 | def deployVerticle(name: String, config: JsonObject = Json.emptyObj(), instances: Int = 1, handler: AsyncResult[String] => Unit = { ar: AsyncResult[String] => }): Unit =
59 | asJava.deployVerticle(name, config, instances, handler)
60 |
61 | /**
62 | * Deploy a worker verticle programmatically
63 | * @param name The main of the verticle
64 | * @param config JSON config to provide to the verticle (defaults to empty JSON)
65 | * @param instances The number of instances to deploy (defaults to 1)
66 | * @param multiThreaded if true then the verticle will be deployed as a multi-threaded worker (default is false)
67 | * @param handler The handler will be called passing in the unique deployment id when deployment is complete
68 | */
69 | def deployWorkerVerticle(name: String, config: JsonObject = Json.emptyObj(), instances: Int = 1, multiThreaded: Boolean = false, handler: AsyncResult[String] => Unit = { ar: AsyncResult[String] => }): Unit =
70 | asJava.deployWorkerVerticle(name, config, instances, multiThreaded, handler)
71 |
72 | /**
73 | * Get the verticle configuration
74 | * @return a JSON object representing the configuration
75 | */
76 | def config(): JsonObject = asJava.config()
77 |
78 | /**
79 | * Get an umodifiable map of system, environment variables.
80 | * @return The map
81 | */
82 | def env(): Map[String, String] = mapAsScalaMapConverter(asJava.env()).asScala.toMap
83 |
84 | /**
85 | * Cause the container to exit
86 | */
87 | def exit(): Unit = asJava.exit()
88 |
89 | /**
90 | * Get the verticle logger
91 | * @return The logger
92 | */
93 | def logger(): Logger = new Logger(asJava.logger())
94 |
95 | /**
96 | * Undeploy a module
97 | * @param deploymentID The deployment ID
98 | * @param handler The handler will be called when undeployment is complete
99 | */
100 | def undeployModule(deploymentID: String, handler: () => Unit): Unit = asJava.undeployModule(deploymentID, handler)
101 |
102 | /**
103 | * Undeploy a module
104 | * @param deploymentID The deployment ID
105 | * @param handler The handler will be called when undeployment is complete
106 | */
107 | def undeployVerticle(deploymentID: String, handler: () => Unit): Unit = asJava.undeployVerticle(deploymentID, handler)
108 |
109 | }
110 |
111 | /** Factory for [[org.vertx.scala.platform.Container]] instances. */
112 | object Container {
113 | def apply(actual: JContainer) = new Container(actual)
114 | }
115 |
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/eventbus/Message.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.vertx.scala.core.eventbus
17 |
18 | import org.vertx.java.core.eventbus.{ Message => JMessage }
19 | import org.vertx.scala.core.FunctionConverters._
20 | import org.vertx.scala.core.AsyncResult
21 | import org.vertx.scala.core.Handler
22 |
23 | /**
24 | * Represents a message on the event bus.
25 | *
26 | * Instances of this class are not thread-safe
27 | *
28 | * @author Tim Fox
29 | * @author Joern Bernhardt
30 | * @author Galder Zamarreño
31 | */
32 | final class Message[T <% MessageData] private[scala] (val asJava: JMessage[T]) {
33 |
34 | /**
35 | * The address the message was sent to
36 | */
37 | def address(): String = asJava.address()
38 |
39 | /**
40 | * The body of the message.
41 | */
42 | def body(): T = anyToMessageData(asJava.body()).data.asInstanceOf[T]
43 |
44 | /**
45 | * The reply address (if any).
46 | *
47 | * @return An optional String containing the reply address.
48 | */
49 | def replyAddress(): Option[String] = Option(asJava.replyAddress())
50 |
51 | /**
52 | * Reply to this message. If the message was sent specifying a reply handler, that handler will be
53 | * called when it has received a reply. If the message wasn't sent specifying a receipt handler
54 | * this method does nothing.
55 | */
56 | def reply(): Unit = asJava.reply()
57 |
58 | /**
59 | * Reply to this message. If the message was sent specifying a reply handler, that handler will be
60 | * called when it has received a reply. If the message wasn't sent specifying a receipt handler
61 | * this method does nothing.
62 | *
63 | * @param value The data to send with the reply.
64 | */
65 | def reply(value: MessageData): Unit = value.reply(asJava)
66 |
67 | /**
68 | * The same as [[org.vertx.scala.core.eventbus.Message.reply(MessageData)]] but you can specify handler for the reply - i.e.
69 | * to receive the reply to the reply.
70 | *
71 | * @param value The value to send.
72 | * @param handler Handling the reply.
73 | */
74 | def reply[B <% MessageData](value: MessageData, handler: Message[B] => Unit): Unit = value.reply(asJava, fnToHandler(handler.compose(Message.apply)))
75 |
76 | /**
77 | * The same as {@code reply()} but you can specify handler for the reply - i.e.
78 | * to receive the reply to the reply.
79 | *
80 | * @param handler Handling the reply.
81 | */
82 | def reply[B <% MessageData](handler: Message[B] => Unit): Unit = asJava.reply(messageFnToJMessageHandler(handler))
83 |
84 | /**
85 | * Reply to this message. Specifying a timeout and a reply handler.
86 | *
87 | * @param timeout The timeout in ms to wait for an answer.
88 | * @param replyHandler Handling the reply (success) or the timeout (failed).
89 | */
90 | def replyWithTimeout[T <% MessageData](timeout: Long, replyHandler: AsyncResult[Message[T]] => Unit): Unit =
91 | asJava.replyWithTimeout(timeout, asyncResultConverter({ x: JMessage[T] => Message.apply(x) })(replyHandler))
92 |
93 | /**
94 | * Reply to this message with data. Specifying a timeout and a reply handler.
95 | *
96 | * @param value The value to send.
97 | * @param timeout The timeout in ms to wait for an answer.
98 | * @param replyHandler Handling the reply (success) or the timeout (failed).
99 | */
100 | def replyWithTimeout[T <% MessageData](value: MessageData, timeout: Long, replyHandler: AsyncResult[Message[T]] => Unit): Unit =
101 | value.replyWithTimeout(asJava, timeout, convertArHandler(replyHandler))
102 |
103 | /**
104 | * Signal that processing of this message failed. If the message was sent specifying a result handler
105 | * the handler will be called with a failure corresponding to the failure code and message specified here
106 | * @param failureCode A failure code to pass back to the sender
107 | * @param message A message to pass back to the sender
108 | */
109 | def fail(failureCode: Int, message: String): Unit = asJava.fail(failureCode, message)
110 |
111 | private def convertArHandler[T <% MessageData](handler: AsyncResult[Message[T]] => Unit): Handler[AsyncResult[JMessage[T]]] = {
112 | asyncResultConverter({x: JMessage[T] => Message.apply(x)})(handler)
113 | }
114 | }
115 |
116 | /**
117 | * Companion object for Message.
118 | *
119 | * @author pidster
120 | * @author Joern Bernhardt
121 | */
122 | object Message {
123 | def apply[X <% MessageData](jmessage: JMessage[X]): Message[X] = new Message(jmessage)
124 | }
125 |
--------------------------------------------------------------------------------
/src/test/scala/org/vertx/scala/tests/core/streams/PumpTest.scala:
--------------------------------------------------------------------------------
1 | package org.vertx.scala.tests.core.streams
2 |
3 | import java.nio.file.{Paths, Files}
4 | import org.junit.Test
5 | import org.vertx.scala.core.AsyncResult
6 | import org.vertx.scala.core.buffer.{ Buffer, BufferElem }
7 | import org.vertx.scala.core.file.AsyncFile
8 | import org.vertx.scala.core.http.{ HttpClient, HttpClientResponse, HttpServer, HttpServerRequest }
9 | import org.vertx.scala.core.streams.Pump
10 | import org.vertx.scala.testtools.TestVerticle
11 | import org.vertx.testtools.VertxAssert._
12 |
13 | class PumpTest extends TestVerticle {
14 |
15 | val testPort = 8844
16 |
17 | val html =
18 |
30 | * buffer1:HELLO\nHOW ARE Y
31 | * buffer2:OU?\nI AM
32 | * buffer3: DOING OK
33 | * buffer4:\n
34 | *
35 | * Then the output would be:
37 | * buffer1:HELLO
38 | * buffer2:HOW ARE YOU?
39 | * buffer3:I AM DOING OK
40 | *
41 | * Instances of this class can be changed between delimited mode and fixed size record mode on the fly as
42 | * individual records are read, this allows you to parse protocols where, for example, the first 5 records might
43 | * all be fixed size (of potentially different sizes), followed by some delimited records, followed by more fixed
44 | * size records.
31 | * [[java.lang.String]]
32 | * [[java.lang.Integer]]
33 | * [[java.lang.Long]]
34 | * [[java.lang.Double]]
35 | * [[java.lang.Float]]
36 | * [[java.lang.Short]]
37 | * [[java.lang.Byte]]
38 | * [[java.lang.Character]]
39 | * `byte[]` - this will be automatically copied, and the copy will be stored in the structure.
40 | * [[org.vertx.scala.core.buffer.Buffer]] - this will be automatically copied, and the copy will be stored in the
41 | * structure.
42 | *
43 | * Hello world!
24 |
25 | .toString()
26 |
27 | @Test def websocketServer(): Unit = {
28 | vertx.createHttpServer.websocketHandler(regularRequestHandler).listen(testPort, checkServer({ c =>
29 | assertThread()
30 | c.connectWebsocket("/", correctBodyHandler(testComplete))
31 | }))
32 | }
33 |
34 | @Test def secureWebsocketServer(): Unit = {
35 | val server = vertx.createHttpServer.setSSL(true)
36 |
37 | server.setKeyStorePath("./src/test/keystores/server-keystore.jks").setKeyStorePassword("wibble")
38 | server.setTrustStorePath("./src/test/keystores/server-truststore.jks").setTrustStorePassword("wibble")
39 |
40 | server.websocketHandler(regularRequestHandler).listen(testPort, checkServer({ c =>
41 | assertThread()
42 | c.setSSL(true)
43 | c.setKeyStorePath("./src/test/keystores/client-keystore.jks").setKeyStorePassword("wibble")
44 | c.setTrustStorePath("./src/test/keystores/client-truststore.jks").setTrustStorePassword("wibble")
45 | c.exceptionHandler(ex => fail("Should not get exception but got " + ex)) connectWebsocket ("/", correctBodyHandler(testComplete))
46 | }))
47 | }
48 |
49 | @Test def pingPongMessages(): Unit = {
50 | vertx.createHttpServer.websocketHandler({ ws: ServerWebSocket =>
51 | ws.dataHandler({ buf =>
52 | assertThread()
53 | if (buf.toString() == "ping") {
54 | ws.write(Buffer("pong"))
55 | } else if (buf.toString() == "ping2") {
56 | ws.write(Buffer("pong2"))
57 | }
58 | })
59 | }).listen(testPort, checkServer({ c =>
60 | assertThread()
61 | c.connectWebsocket("/", { resp: WebSocket =>
62 | assertThread()
63 | resp.dataHandler({ buf =>
64 | assertThread()
65 | assertEquals("pong", buf.toString)
66 | resp.dataHandler({ buf =>
67 | assertThread()
68 | assertEquals("pong2", buf.toString)
69 | testComplete()
70 | })
71 | resp.write(Buffer("ping2"))
72 | })
73 | resp.write(Buffer("ping"))
74 | })
75 | }))
76 | }
77 |
78 | @Test def websocketAddresses(): Unit = {
79 | vertx.createHttpServer.websocketHandler({ ws: ServerWebSocket =>
80 | assertNotNull(ws.remoteAddress())
81 | assertNotNull(ws.localAddress())
82 | ws.dataHandler({ buf =>
83 | assertThread()
84 | val addresses = buf.toString().split("\n")
85 | assertEquals(ws.remoteAddress().getAddress().getHostAddress().toString(), addresses(1))
86 | assertEquals(ws.localAddress().getAddress().getHostAddress().toString(), addresses(0))
87 | testComplete()
88 | })
89 | }).listen(testPort, checkServer({ c =>
90 | c.connectWebsocket("/", { ws: WebSocket =>
91 | assertThread()
92 | ws.write(Buffer(ws.remoteAddress().getAddress().getHostAddress().toString() + "\n"
93 | + ws.localAddress().getAddress().getHostAddress().toString()))
94 | })
95 | }))
96 | }
97 |
98 | private def regularRequestHandler: ServerWebSocket => Unit = { ws =>
99 | ws.write(Buffer(html))
100 |
101 | ws.dataHandler({ buf =>
102 | assertThread()
103 | assertEquals(html, buf.toString)
104 | testComplete()
105 | }): Unit
106 | }
107 |
108 | private def correctBodyHandler(fn: () => Unit) = { resp: WebSocket =>
109 | resp.dataHandler({ buf =>
110 | assertThread()
111 | assertEquals(html, buf.toString)
112 | fn()
113 | }): Unit
114 | }
115 |
116 | private def checkServer(clientFn: HttpClient => Unit) = { ar: AsyncResult[HttpServer] =>
117 | assertThread()
118 | if (ar.succeeded()) {
119 | val httpClient = vertx.createHttpClient.setPort(testPort)
120 | clientFn(httpClient)
121 | } else {
122 | fail("listening did not succeed: " + ar.cause().getMessage())
123 | }
124 | }
125 | }
--------------------------------------------------------------------------------
/src/main/scala/org/vertx/scala/core/net/NetSocket.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.vertx.scala.core.net
18 |
19 | import org.vertx.java.core.net.{ NetSocket => JNetSocket }
20 | import java.net.InetSocketAddress
21 | import org.vertx.scala.core.FunctionConverters._
22 | import org.vertx.scala.core.streams.{WriteStream, ReadStream}
23 | import org.vertx.scala.Self
24 | import org.vertx.scala.core._
25 |
26 | /**
27 | * Represents a socket-like interface to a TCP/SSL connection on either the
28 | * client or the server side.Hello world!
23 |
24 | .toString()
25 |
26 | @Test
27 | def pumpingHttp(): Unit = {
28 | vertx.createHttpServer.requestHandler(regularRequestHandler).listen(testPort, checkServer({ c =>
29 | assertThread()
30 | val chunk = Buffer("hello pump")
31 | val req = c.post("/", { resp =>
32 | assertEquals(200, resp.statusCode)
33 | val buffer = Buffer()
34 | resp.dataHandler { buff =>
35 | assertThread()
36 | buffer.append(buff)
37 | }
38 | resp.endHandler {
39 | assertThread()
40 | assertEquals(chunk.length(), buffer.length())
41 | assertEquals(chunk, buffer)
42 | testComplete()
43 | }
44 | })
45 | req.setChunked(true)
46 | req.write(chunk)
47 | req.end()
48 | }))
49 | }
50 |
51 | @Test
52 | def pumpingFile(): Unit = withPumpFiles { (filename, oldFile, newFile) =>
53 | oldFile.endHandler({
54 | assertThread()
55 | oldFile.close { readCloseResult =>
56 | if (readCloseResult.failed())
57 | fail("Fail to close read file")
58 | else {
59 | newFile.close { writeCloseResult =>
60 | if (writeCloseResult.failed())
61 | fail("Fail to close write file")
62 | else {
63 | val readFileSize = vertx.fileSystem.propsSync(filename).size()
64 | val writtenBytes = Files.readAllBytes(Paths.get(filename + ".copy"))
65 | assertEquals(readFileSize, writtenBytes.length)
66 | vertx.fileSystem.deleteSync(filename + ".copy")
67 | testComplete()
68 | }
69 | }
70 | }
71 | }
72 | })
73 |
74 | Pump.createPump(oldFile, newFile).start()
75 | }
76 |
77 | @Test
78 | def pumpStopAndResume(): Unit = withPumpFiles { (filename, oldFile, newFile) =>
79 | val filesize = vertx.fileSystem.propsSync(filename).size
80 | val pump = Pump.createPump(oldFile, newFile)
81 | pump.setWriteQueueMaxSize((filesize / 10).intValue)
82 |
83 | for (i <- 0 to 9) {
84 | pump.start
85 | pump.stop
86 | }
87 |
88 | oldFile.endHandler({
89 | assertThread()
90 | val filesizeNew = vertx.fileSystem.propsSync(filename + ".copy").size
91 | val oldContents = vertx.fileSystem.readFileSync(filename)
92 | val newContents = vertx.fileSystem.readFileSync(filename + ".copy")
93 | assertEquals("Filesize should match", filesize, filesizeNew)
94 | assertEquals("Filesize should match pumped bytes", filesize, pump.bytesPumped)
95 | assertEquals("Contents should match", oldContents, newContents)
96 | testComplete
97 | })
98 | pump.start
99 | }
100 |
101 | private def withPumpFiles(fn: (String, AsyncFile, AsyncFile) => Unit): Unit = {
102 | val file = "src/test/resources/pumpfile.txt"
103 | if (vertx.fileSystem.existsSync(file + ".copy")) {
104 | vertx.fileSystem.deleteSync(file + ".copy")
105 | }
106 | vertx.fileSystem.createFileSync(file + ".copy")
107 | vertx.fileSystem.open(file, { ar1: AsyncResult[AsyncFile] =>
108 | assertThread()
109 | assertTrue("Should be able to open " + file, ar1.succeeded())
110 | val oldFile = ar1.result()
111 | vertx.fileSystem.open(file + ".copy", { ar2: AsyncResult[AsyncFile] =>
112 | assertThread()
113 | assertTrue("Should be able to open " + file + ".copy", ar2.succeeded())
114 | val newFile = ar2.result()
115 | fn(file, oldFile, newFile)
116 | })
117 | })
118 | }
119 |
120 | private def regularRequestHandler: HttpServerRequest => Unit = { req =>
121 | req.response.setChunked(true)
122 | req.endHandler({ req.response.end })
123 | Pump.createPump(req, req.response).start
124 | }
125 |
126 | private def checkServer(clientFn: HttpClient => Unit) = { ar: AsyncResult[HttpServer] =>
127 | assertThread()
128 | if (ar.succeeded()) {
129 | val httpClient = vertx.createHttpClient.setPort(testPort)
130 | clientFn(httpClient)
131 | } else {
132 | fail("listening did not succeed: " + ar.cause().getMessage())
133 | }
134 | }
135 |
136 | private def correctHandler(fn: () => Unit) = { resp: HttpClientResponse =>
137 | resp.bodyHandler({ buf =>
138 | assertThread()
139 | assertEquals(html, buf.toString)
140 | fn()
141 | }): Unit
142 | }
143 |
144 | }
--------------------------------------------------------------------------------