0001-special-rule-for-binary-attachements.patch
src/rsb/converter/XOPConverter.java | ||
---|---|---|
3 | 3 |
import com.google.protobuf.ByteString; |
4 | 4 |
import java.nio.ByteBuffer; |
5 | 5 |
import java.util.Iterator; |
6 |
import java.util.logging.Logger; |
|
6 | 7 |
import rsb.transport.XOP; |
7 | 8 |
import rsb.transport.XOP.SyntaxException; |
8 | 9 |
import rst.xml.XOPType; |
9 | 10 | |
10 | 11 |
/** |
11 |
* RSB converter for {@link rsb.xml.XOP} objects. |
|
12 |
* |
|
12 |
* RSB converter for {@link rsb.xml.XOP} objects. This converter is independent |
|
13 |
* of the data that is set to the XOP's attachment. Is is expected that the |
|
14 |
* attachment's data is convertible as well. |
|
15 |
* |
|
13 | 16 |
* @author lkettenb |
14 | 17 |
*/ |
15 | 18 |
public class XOPConverter implements Converter<ByteBuffer> { |
16 | 19 | |
20 |
private static final Logger LOG = Logger.getLogger(XOPConverter.class |
|
21 |
.getName()); |
|
22 | ||
17 | 23 |
private ConverterSignature signatur = new ConverterSignature(".rst.xml.XOP", XOP.class); |
18 | 24 | |
19 | 25 |
private ProtocolBufferConverter<XOPType.XOP> pbc; |
20 | 26 |
private ConverterSelectionStrategy<ByteBuffer> serializationConverters = null; |
21 | 27 |
private ConverterSelectionStrategy<ByteBuffer> deserializationConverters = null; |
22 | 28 | |
29 |
/** |
|
30 |
* Signature for binary attachments. |
|
31 |
*/ |
|
32 |
private final ConverterSignature byteSignature = new ConverterSignature( |
|
33 |
"bytes", ByteBuffer.class); |
|
34 | ||
23 | 35 |
public XOPConverter() { |
24 | 36 |
pbc = new ProtocolBufferConverter<XOPType.XOP> |
25 | 37 |
(XOPType.XOP.getDefaultInstance()); |
... | ... | |
38 | 50 |
} |
39 | 51 | |
40 | 52 |
@Override |
41 |
public UserData deserialize(String wireSchema, ByteBuffer buffer) |
|
42 |
throws ConversionException { |
|
53 |
public UserData<XOPType.XOP> deserialize(String wireSchema, ByteBuffer buffer) throws ConversionException { |
|
43 | 54 |
UserData<XOPType.XOP> result = pbc.deserialize(wireSchema, buffer); |
44 | 55 |
XOPType.XOP data = (XOPType.XOP) result.getData(); |
45 | 56 |
XOP xop = convertRSTtoRSB(data); |
... | ... | |
69 | 80 |
} |
70 | 81 | |
71 | 82 |
for (XOPType.Attachment attachment : data.getAttachmentsList()) { |
72 |
if (attachment.hasUrl() && attachment.hasData()) { |
|
83 |
if (!attachment.hasUrl() || !attachment.hasData()) { |
|
84 |
LOG.warning("received incomplete attachement!"); |
|
85 |
continue; |
|
86 |
} |
|
87 | ||
88 |
String wireSchema = attachment.getWireSchema().toStringUtf8(); |
|
89 |
ByteBuffer dataBuffer = ByteBuffer.wrap(attachment.getData() |
|
90 |
.toByteArray()); |
|
91 |
rsb.transport.Attachment att; |
|
92 | ||
93 |
if (wireSchema.equals(byteSignature.getSchema())) { |
|
94 |
att = new rsb.transport.Attachment(dataBuffer, |
|
95 |
byteSignature.getDataType()); |
|
96 |
} else { |
|
97 | ||
73 | 98 |
Converter<ByteBuffer> c = deserializationConverters |
74 |
.getConverter(attachment.getWireSchema().toStringUtf8());
|
|
99 |
.getConverter(wireSchema);
|
|
75 | 100 | |
76 |
ByteBuffer dataBuffer |
|
77 |
= ByteBuffer.wrap(attachment.getData().toByteArray()); |
|
78 |
UserData deserializedAttachment |
|
79 |
= c.deserialize(c.getSignature().getSchema(), dataBuffer); |
|
101 |
@SuppressWarnings("rawtypes") |
|
102 |
UserData deserializedAttachment = c.deserialize(c |
|
103 |
.getSignature().getSchema(), dataBuffer); |
|
80 | 104 | |
81 |
rsb.transport.Attachment att |
|
82 |
= new rsb.transport.Attachment(deserializedAttachment.getData(), |
|
83 |
deserializedAttachment.getTypeInfo()); |
|
84 |
xop.setAttachment(attachment.getUrl(), att); |
|
105 |
att = new rsb.transport.Attachment( |
|
106 |
deserializedAttachment.getData(), |
|
107 |
deserializedAttachment.getTypeInfo()); |
|
85 | 108 |
} |
109 |
xop.setAttachment(attachment.getUrl(), att); |
|
110 | ||
86 | 111 |
} |
87 | 112 |
return xop; |
88 | 113 |
} |
... | ... | |
117 | 142 |
XOPType.Attachment.Builder attachmentBuilder |
118 | 143 |
= XOPType.Attachment.newBuilder(); |
119 | 144 | |
120 |
Converter<ByteBuffer> c |
|
121 |
= serializationConverters |
|
122 |
.getConverter(attachment.getType().getName()); |
|
123 | ||
124 |
WireContents<ByteBuffer> result |
|
125 |
= c.serialize(attachment.getType(), attachment.getData()); |
|
126 |
attachmentBuilder.setWireSchema(ByteString.copyFrom(result.getWireSchema().getBytes())); |
|
127 |
attachmentBuilder.setData(ByteString.copyFrom(result.getSerialization().asReadOnlyBuffer())); |
|
145 |
if (attachment.getType().equals(byteSignature.getDataType())) { |
|
146 |
ByteBuffer bb = (ByteBuffer) attachment.getData(); |
|
147 |
attachmentBuilder.setWireSchema(ByteString |
|
148 |
.copyFrom(byteSignature.getSchema().getBytes())); |
|
149 |
attachmentBuilder.setData(ByteString.copyFrom(bb |
|
150 |
.asReadOnlyBuffer())); |
|
151 |
} else { |
|
152 |
Converter<ByteBuffer> c = serializationConverters |
|
153 |
.getConverter(attachment.getType().getName()); |
|
154 | ||
155 |
WireContents<ByteBuffer> result = c.serialize( |
|
156 |
attachment.getType(), attachment.getData()); |
|
157 |
attachmentBuilder.setWireSchema(ByteString.copyFrom(result |
|
158 |
.getWireSchema().getBytes())); |
|
159 |
attachmentBuilder.setData(ByteString.copyFrom(result |
|
160 |
.getSerialization().asReadOnlyBuffer())); |
|
161 |
} |
|
128 | 162 |
attachmentBuilder.setUrl(url); |
129 | 163 |
xopBuilder.addAttachments(attachmentBuilder.build()); |
130 | 164 |
} |
src/rsb/transport/Attachment.java | ||
---|---|---|
1 | 1 |
package rsb.transport; |
2 | 2 | |
3 |
import java.nio.ByteBuffer; |
|
3 | 4 |
import java.util.Arrays; |
4 | 5 |
import java.util.logging.Level; |
5 | 6 |
import java.util.logging.Logger; |
... | ... | |
25 | 26 |
private UserData data; |
26 | 27 | |
27 | 28 |
/** |
28 |
* Construct an {@link Attachment} containing the data.
|
|
29 |
* |
|
29 |
* Constructs an {@link Attachment} containing the data. Attention: For
|
|
30 |
* transferring binary data use {@link ByteBuffer}.
|
|
30 | 31 |
* |
31 | 32 |
* @param data The piece of data which should be stored in the attachment. |
32 | 33 |
* This can be any Java object, but the same restrictions as for event |
33 |
* payloads apply. |
|
34 |
* payloads apply. Use {@link ByteBuffer} for transferring binary data.
|
|
34 | 35 |
* @param type Data type which can be interpreted by RSB's event handling |
35 | 36 |
* machinery. |
36 | 37 |
* |
... | ... | |
46 | 47 |
* Copy constructor. |
47 | 48 |
* @param a |
48 | 49 |
*/ |
49 |
@SuppressWarnings("unchecked")
|
|
50 |
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
50 | 51 |
public Attachment(Attachment a) { |
51 | 52 |
data = new UserData(a.data.getData(), a.data.getTypeInfo()); |
52 | 53 |
} |
53 | 54 | |
54 | 55 |
/** |
55 | 56 |
* Returns the type of this attachment. Use {@link Class#getName()} when |
56 |
* looking for the appropirate converter of this attachment.
|
|
57 |
* looking for the appropriate converter of this attachment.
|
|
57 | 58 |
* |
58 | 59 |
* @return Type of this attachment. |
59 | 60 |
*/ |
test/rsb/transport/XOMXOPTest.java | ||
---|---|---|
90 | 90 |
} |
91 | 91 | |
92 | 92 |
@Test |
93 |
@SuppressWarnings("deprecation") |
|
94 | 93 |
public void testNonXML() { |
95 | 94 |
XOMXOP xop = new XOMXOP(); |
96 | 95 |
try { |
test/rsb/transport/XOPConverterTest.java | ||
---|---|---|
33 | 33 |
public void setUp() { |
34 | 34 |
// Register default converters (including String converter). |
35 | 35 |
DefaultConverters.register(); |
36 |
ConverterRepository rep = DefaultConverterRepository.getDefaultConverterRepository(); |
|
36 |
ConverterRepository<ByteBuffer> rep = DefaultConverterRepository.getDefaultConverterRepository();
|
|
37 | 37 |
rep.addConverter( |
38 | 38 |
new ProtocolBufferConverter<Gaussian1DType.Gaussian1D>( |
39 | 39 |
Gaussian1DType.Gaussian1D.getDefaultInstance())); |
... | ... | |
52 | 52 |
|
53 | 53 |
WireContents<ByteBuffer> serializedData = converter.serialize(XOP.class, xop1); |
54 | 54 | |
55 |
UserData<String> deserializedUserData =
|
|
55 |
UserData<rst.xml.XOPType.XOP> deserializedUserData =
|
|
56 | 56 |
converter.deserialize( |
57 | 57 |
serializedData.getWireSchema(), |
58 | 58 |
serializedData.getSerialization()); |
... | ... | |
76 | 76 |
} |
77 | 77 |
|
78 | 78 |
@Test |
79 |
public void testDeSerializeBinaryAttachment() throws ConversionException, SyntaxException { |
|
80 |
String xml1 = "<?xml version=\"1.0\"?>" + "<node1 attr1=\"val1\">" |
|
81 |
+ " <node2 attr2=\"val2\"/>" + " <node3 attr3=\"val3\"/>" |
|
82 |
+ "</node1>"; |
|
83 |
long id = 156546546; |
|
84 |
XOP xop1 = new XOP(xml1, id); |
|
85 |
|
|
86 |
// create data |
|
87 |
float[] floatData = {0.0f,1.0f,2.0f}; |
|
88 |
ByteBuffer bb = ByteBuffer.allocate(4 * floatData.length); |
|
89 |
for (int i = 0; i < floatData.length; i++) { |
|
90 |
bb.putFloat(floatData[i]); |
|
91 |
} |
|
92 |
|
|
93 |
rsb.transport.Attachment a1 = new rsb.transport.Attachment(bb, ByteBuffer.class); |
|
94 |
xop1.setAttachment("attachment", a1); |
|
95 |
|
|
96 |
WireContents<ByteBuffer> serializedData = converter.serialize(XOP.class, xop1); |
|
97 | ||
98 |
UserData<rst.xml.XOPType.XOP> deserializedUserData = |
|
99 |
converter.deserialize( |
|
100 |
serializedData.getWireSchema(), |
|
101 |
serializedData.getSerialization()); |
|
102 | ||
103 |
assertTrue(deserializedUserData.getTypeInfo().equals(xop1.getClass())); |
|
104 | ||
105 |
XOP deserializedXOP = (XOP) deserializedUserData.getData(); |
|
106 |
assertTrue(deserializedXOP.getID() == xop1.getID()); |
|
107 |
assertTrue(deserializedXOP.getID() != 156546545); |
|
108 |
assertTrue(deserializedXOP.hasID()); |
|
109 | ||
110 |
assertTrue(deserializedXOP.hasAttachment("attachment")); |
|
111 |
rsb.transport.Attachment a2 = deserializedXOP.getAttachment("attachment"); |
|
112 | ||
113 |
ByteBuffer a1bb = (ByteBuffer) a1.getData(); |
|
114 |
ByteBuffer a2bb = (ByteBuffer) a2.getData(); |
|
115 |
assertTrue(a1bb.equals(a2bb)); |
|
116 | ||
117 |
assertTrue(a1.equals(a2)); |
|
118 |
assertTrue(deserializedXOP.equals(xop1)); |
|
119 |
} |
|
120 |
|
|
121 |
@Test |
|
79 | 122 |
public void testDeSerializeUint64() throws ConversionException, SyntaxException { |
80 | 123 |
String xml1 = "<?xml version=\"1.0\"?>" + "<node1 attr1=\"val1\">" |
81 | 124 |
+ " <node2 attr2=\"val2\"/>" + " <node3 attr3=\"val3\"/>" |
... | ... | |
88 | 131 | |
89 | 132 |
WireContents<ByteBuffer> serializedData = converter.serialize(XOP.class, xop1); |
90 | 133 | |
91 |
UserData<String> deserializedUserData =
|
|
134 |
UserData<rst.xml.XOPType.XOP> deserializedUserData =
|
|
92 | 135 |
converter.deserialize( |
93 | 136 |
serializedData.getWireSchema(), |
94 | 137 |
serializedData.getSerialization()); |
... | ... | |
125 | 168 | |
126 | 169 |
WireContents<ByteBuffer> serializedData = converter.serialize(XOP.class, xop1); |
127 | 170 | |
128 |
UserData<String> deserializedUserData =
|
|
171 |
UserData<rst.xml.XOPType.XOP> deserializedUserData =
|
|
129 | 172 |
converter.deserialize( |
130 | 173 |
serializedData.getWireSchema(), |
131 | 174 |
serializedData.getSerialization()); |
... | ... | |
167 | 210 |
WireContents<ByteBuffer> serializedData = |
168 | 211 |
xopsConverter.serialize(XOPs.class, xops); |
169 | 212 |
|
170 |
UserData<String> deserializedUserData = |
|
213 |
@SuppressWarnings("rawtypes") |
|
214 |
UserData deserializedUserData = |
|
171 | 215 |
xopsConverter.deserialize( |
172 | 216 |
serializedData.getWireSchema(), |
173 | 217 |
serializedData.getSerialization()); |
test/rsb/transport/XOPTest.java | ||
---|---|---|
53 | 53 |
@Test |
54 | 54 |
public void testInValidDoc() { |
55 | 55 |
try { |
56 |
XOP xop = new XOP("test"); |
|
56 |
@SuppressWarnings("unused") |
|
57 |
XOP xop = new XOP("test"); |
|
57 | 58 |
} catch (SyntaxException ex) { |
58 | 59 |
assertTrue(true); |
59 | 60 |
} |
60 |
- |