Skip to content

Commit 9baf9bd

Browse files
author
Michal Lacko
committed
+cam akka#11214 add attachments to CamelMessage
add support for attachments in CamelMessage, taken from JCamelMessage add a extension class CamelMessageWithAttachments base on CamelMessage that contains attachments based on JCamelMessage add newline CamelMessageTest replace for-cycle attachment adding with one putAll remove CamelMessageWithAttachments and update CamelMessage to contain attachments fix the binary compatibility issues on CamelMessage add documentation for new methods in CamelMessage, add return type for method withBody
1 parent 81cba2e commit 9baf9bd

File tree

2 files changed

+129
-23
lines changed

2 files changed

+129
-23
lines changed

akka-camel/src/main/scala/akka/camel/CamelMessage.scala

Lines changed: 110 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,26 @@
55
package akka.camel
66

77
import java.util.{ Map JMap, Set JSet }
8+
import javax.activation.DataHandler
89
import org.apache.camel.{ CamelContext, Message JCamelMessage, StreamCache }
910
import akka.AkkaException
1011
import scala.reflect.ClassTag
12+
import scala.runtime.ScalaRunTime
1113
import scala.util.Try
1214
import scala.collection.JavaConversions._
1315
import akka.dispatch.Mapper
1416

1517
/**
1618
* An immutable representation of a Camel message.
1719
*/
18-
case class CamelMessage(body: Any, headers: Map[String, Any]) {
19-
def this(body: Any, headers: JMap[String, Any]) = this(body, headers.toMap) //for Java
20+
class CamelMessage(val body: Any, val headers: Map[String, Any], val attachments: Map[String, DataHandler]) extends Serializable with Product {
21+
def this(body: Any, headers: JMap[String, Any]) = this(body, headers.toMap, Map.empty[String, DataHandler]) //Java
22+
def this(body: Any, headers: JMap[String, Any], attachments: JMap[String, DataHandler]) = this(body, headers.toMap, attachments.toMap) //Java
23+
def this(body: Any, headers: Map[String, Any]) = this(body, headers.toMap, Map.empty[String, DataHandler])
2024

21-
override def toString: String = "CamelMessage(%s, %s)" format (body, headers)
25+
def copy(body: Any = this.body, headers: Map[String, Any] = this.headers): CamelMessage = CamelMessage(body, headers, this.attachments)
26+
27+
override def toString: String = "CamelMessage(%s, %s, %s)" format (body, headers, attachments)
2228

2329
/**
2430
* Returns those headers from this message whose name is contained in <code>names</code>.
@@ -112,7 +118,7 @@ case class CamelMessage(body: Any, headers: Map[String, Any]) {
112118
/**
113119
* Java API: Returns a new CamelMessage with a new body, while keeping the same headers.
114120
*/
115-
def withBody[T](body: T) = this.copy(body = body)
121+
def withBody[T](body: T): CamelMessage = copy(body = body)
116122
/**
117123
* Creates a CamelMessage with current <code>body</code> converted to type <code>T</code>.
118124
* The CamelContext is accessible in a [[akka.camel.javaapi.UntypedConsumerActor]] and [[akka.camel.javaapi.UntypedProducerActor]]
@@ -128,12 +134,95 @@ case class CamelMessage(body: Any, headers: Map[String, Any]) {
128134
*/
129135
def withBodyAs[T](clazz: Class[T])(implicit camelContext: CamelContext): CamelMessage = copy(body = getBodyAs(clazz, camelContext))
130136

137+
/**
138+
* Returns those attachments from this message whose name is contained in <code>names</code>.
139+
*/
140+
def attachments(names: Set[String]): Map[String, DataHandler] = attachments filterKeys names
141+
142+
/**
143+
* Java API: Returns those attachments from this message whose name is contained in <code>names</code>.
144+
* The returned headers map is backed up by an immutable headers map. Any attempt to modify
145+
* the returned map will throw an exception.
146+
*/
147+
def getAttachments(names: JSet[String]): JMap[String, DataHandler] = attachments(names.toSet)
148+
149+
/**
150+
* Java API: Returns all attachments from this message. The returned attachments map is backed up by this
151+
* message's immutable headers map. Any attempt to modify the returned map will throw an
152+
* exception.
153+
*/
154+
def getAttachments: JMap[String, DataHandler] = attachments
155+
156+
/**
157+
* Java API: Creates a new CamelMessage with given <code>attachments</code>. A copy of the attachments map is made.
158+
*/
159+
def withAttachments(attachments: JMap[String, DataHandler]): CamelMessage = CamelMessage(this.body, this.headers, attachments.toMap)
160+
161+
/**
162+
* SCALA API: Creates a new CamelMessage with given <code>attachments</code>.
163+
*/
164+
def withAttachments(attachments: Map[String, DataHandler]): CamelMessage = CamelMessage(this.body, this.headers, attachments)
165+
166+
/**
167+
* Indicates whether some other object is "equal to" this one.
168+
*/
169+
override def equals(that: Any): Boolean =
170+
that match {
171+
case that: CamelMessage if canEqual(that)
172+
this.body == that.body &&
173+
this.headers == that.headers &&
174+
this.attachments == that.attachments
175+
case _ false
176+
}
177+
178+
/**
179+
* Returns a hash code value for the object.
180+
*/
181+
override def hashCode(): Int = ScalaRunTime._hashCode(this)
182+
183+
/**
184+
* Returns the n-th element of this product, 0-based.
185+
*/
186+
override def productElement(n: Int): Any = n match {
187+
case 0 body
188+
case 1 headers
189+
case 2 attachments
190+
}
191+
192+
/**
193+
* Returns the size of this product.
194+
*/
195+
override def productArity: Int = 3
196+
197+
/**
198+
* Indicates if some other object can be compared (based on type).
199+
* This method should be called from every well-designed equals method that is open to be overridden in a subclass.
200+
*/
201+
override def canEqual(that: Any): Boolean = that match {
202+
case _: CamelMessage true
203+
case _ false
204+
}
131205
}
132206

133207
/**
134208
* Companion object of CamelMessage class.
135209
*/
136-
object CamelMessage {
210+
object CamelMessage extends ((Any, Map[String, Any]) CamelMessage) {
211+
212+
/**
213+
* Returns a new CamelMessage based on the <code>body</code> and <code>headers</code>.
214+
*/
215+
def apply(body: Any, headers: Map[String, Any]): CamelMessage = new CamelMessage(body, headers, Map.empty[String, DataHandler])
216+
217+
/**
218+
* Returns a new CamelMessage based on the <code>body</code>, <code>headers</code> and <code>attachments</code>.
219+
*/
220+
def apply(body: Any, headers: Map[String, Any], attachments: Map[String, DataHandler]): CamelMessage = new CamelMessage(body, headers, attachments)
221+
222+
/**
223+
* Returns <code>Some(body, headers)</code>.
224+
*/
225+
def unapply(camelMessage: CamelMessage): Option[(Any, Map[String, Any])] = Some((camelMessage.body, camelMessage.headers))
137226

138227
/**
139228
* CamelMessage header to correlate request with response messages. Applications that send
@@ -150,7 +239,7 @@ object CamelMessage {
150239
*/
151240
private[camel] def canonicalize(msg: Any) = msg match {
152241
case mobj: CamelMessage mobj
153-
case body CamelMessage(body, Map.empty)
242+
case body CamelMessage(body, Map.empty[String, Any])
154243
}
155244

156245
/**
@@ -159,15 +248,28 @@ object CamelMessage {
159248
* @param headers additional headers to set on the created CamelMessage in addition to those
160249
* in the Camel message.
161250
*/
162-
private[camel] def from(camelMessage: JCamelMessage, headers: Map[String, Any]): CamelMessage = CamelMessage(camelMessage.getBody, headers ++ camelMessage.getHeaders)
251+
private[camel] def from(camelMessage: JCamelMessage, headers: Map[String, Any]): CamelMessage =
252+
CamelMessage(camelMessage.getBody, headers ++ camelMessage.getHeaders, camelMessage.getAttachments.toMap)
253+
254+
/**
255+
* Creates a new CamelMessageWithAttachments object from the Camel message.
256+
*
257+
* @param headers additional headers to set on the created CamelMessageWithAttachments in addition to those
258+
* in the Camel message.
259+
* @param attachments additional attachments to set on the created CamelMessageWithAttachments in addition to those
260+
* in the Camel message.
261+
*/
262+
private[camel] def from(camelMessage: JCamelMessage, headers: Map[String, Any], attachments: Map[String, DataHandler]): CamelMessage =
263+
CamelMessage(camelMessage.getBody, headers ++ camelMessage.getHeaders, attachments ++ camelMessage.getAttachments)
163264

164265
/**
165266
* INTERNAL API
166-
* copies the content of this CamelMessage to an Apache Camel Message.
267+
* copies the content of this CamelMessageWithAttachments to an Apache Camel Message.
167268
*/
168269
private[camel] def copyContent(from: CamelMessage, to: JCamelMessage): Unit = {
169270
to.setBody(from.body)
170271
for ((name, value) from.headers) to.getHeaders.put(name, value.asInstanceOf[AnyRef])
272+
to.getAttachments.putAll(from.getAttachments)
171273
}
172274
}
173275

akka-camel/src/test/scala/akka/camel/CamelMessageTest.scala

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
package akka.camel
66

7+
import java.net.URL
8+
import javax.activation.DataHandler
9+
710
import org.apache.camel.impl.{ DefaultExchange, DefaultMessage }
811
import akka.camel.TestSupport.SharedCamelSystem
912
import org.scalatest.Matchers
@@ -12,22 +15,23 @@ import org.scalatest.WordSpecLike
1215
//TODO merge it with MessageScalaTest
1316
class CamelMessageTest extends Matchers with WordSpecLike with SharedCamelSystem {
1417

15-
"CamelMessage" must {
18+
"CamelMessage copyContent" must {
19+
"create a new CamelMessage with additional headers, attachments and new body" in {
20+
val attachment = new DataHandler(new URL("https://foo.bar"))
21+
val message = new DefaultMessage
22+
message.setBody("test")
23+
message.setHeader("foo", "bar")
24+
message.addAttachment("foo", attachment)
25+
message.setExchange(new DefaultExchange(camel.context))
1626

17-
"overwrite body and add header" in {
18-
val msg = sampleMessage
19-
CamelMessage.copyContent(CamelMessage("blah", Map("key" -> "baz")), msg)
20-
assert(msg.getBody === "blah")
21-
assert(msg.getHeader("foo") === "bar")
22-
assert(msg.getHeader("key") === "baz")
23-
}
24-
}
27+
val attachmentToAdd = new DataHandler(new URL("https://another.url"))
28+
CamelMessage.copyContent(new CamelMessage("body", Map("key" -> "baz"), Map("key" -> attachmentToAdd)), message)
2529

26-
private[camel] def sampleMessage = {
27-
val message = new DefaultMessage
28-
message.setBody("test")
29-
message.setHeader("foo", "bar")
30-
message.setExchange(new DefaultExchange(camel.context))
31-
message
30+
assert(message.getBody === "body")
31+
assert(message.getHeader("foo") === "bar")
32+
assert(message.getHeader("key") === "baz")
33+
assert(message.getAttachment("key") === attachmentToAdd)
34+
assert(message.getAttachment("foo") === attachment)
35+
}
3236
}
3337
}

0 commit comments

Comments
 (0)