[AMQ-9485] Host activemq-protobuf modules for modernization

This commit is contained in:
Matt Pavlovich 2024-04-24 09:16:57 -05:00
parent 6e6caf7c60
commit f9cf7a3789
No known key found for this signature in database
54 changed files with 11786 additions and 0 deletions

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-parent</artifactId>
<version>6.1.3-SNAPSHOT</version>
</parent>
<groupId>org.apache.activemq.protobuf</groupId>
<artifactId>activemq-protobuf-test</artifactId>
<packaging>jar</packaging>
<name>ActiveMQ :: Protocol Buffers Tests</name>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.activemq.protobuf</groupId>
<artifactId>activemq-protobuf</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.activemq.protobuf</groupId>
<artifactId>activemq-protobuf</artifactId>
<version>${project.version}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.activemq.protobuf</groupId>
<artifactId>activemq-protobuf</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,40 @@
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.apache.activemq.protobuf;
option java_outer_classname = "DeferredUnmarshal";
option deferred_decode = true;
message Foo {
optional int32 field1 = 1;
optional int64 field2 = 2;
}
message Bar {
option base_type=Foo;
// These are the Foo fields.
optional int32 field1 = 1;
optional int64 field2 = 2;
optional Foo field3 = 3;
}

View File

@ -0,0 +1,53 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Author: kenton@google.com (Kenton Varda)
//
// A proto file which tests the java_multiple_files option.
import "unittest.proto";
package protobuf_unittest;
option java_multiple_files = true;
option java_outer_classname = "MultipleFilesTestProto";
message MessageWithNoOuter {
message NestedMessage {
optional int32 i = 1;
}
enum NestedEnum {
BAZ = 3;
}
optional NestedMessage nested = 1;
repeated TestAllTypes foreign = 2;
optional NestedEnum nested_enum = 3;
optional EnumWithNoOuter foreign_enum = 4;
}
enum EnumWithNoOuter {
FOO = 1;
BAR = 2;
}
service ServiceWithNoOuter {
rpc Foo(MessageWithNoOuter) returns(TestAllTypes);
}
extend TestAllExtensions {
optional int32 extension_with_outer = 1234567;
}

View File

@ -0,0 +1,452 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// A proto file we will use for unit testing.
import "unittest_import.proto";
// We don't put this in a package within proto2 because we need to make sure
// that the generated code doesn't depend on being in the proto2 namespace.
// In test_util.h we do "using namespace unittest = protobuf_unittest".
package protobuf_unittest;
// Protos optimized for SPEED use a strict superset of the generated code
// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
// tests for speed unless explicitly testing code size optimization.
option optimize_for = SPEED;
option java_outer_classname = "UnittestProto";
// This proto includes every type of field in both singular and repeated
// forms.
message TestAllTypes {
message NestedMessage {
// The field name "b" fails to compile in proto1 because it conflicts with
// a local variable named "b" in one of the generated methods. Doh.
// This file needs to compile in proto1 to test backwards-compatibility.
optional int32 bb = 1;
}
enum NestedEnum {
FOO = 1;
BAR = 2;
BAZ = 3;
}
// Singular
optional int32 optional_int32 = 1;
optional int64 optional_int64 = 2;
optional uint32 optional_uint32 = 3;
optional uint64 optional_uint64 = 4;
optional sint32 optional_sint32 = 5;
optional sint64 optional_sint64 = 6;
optional fixed32 optional_fixed32 = 7;
optional fixed64 optional_fixed64 = 8;
optional sfixed32 optional_sfixed32 = 9;
optional sfixed64 optional_sfixed64 = 10;
optional float optional_float = 11;
optional double optional_double = 12;
optional bool optional_bool = 13;
optional string optional_string = 14;
optional bytes optional_bytes = 15;
optional group OptionalGroup = 16 {
optional int32 a = 17;
}
optional NestedMessage optional_nested_message = 18;
optional ForeignMessage optional_foreign_message = 19;
optional protobuf_unittest_import.ImportMessage optional_import_message = 20;
optional NestedEnum optional_nested_enum = 21;
optional ForeignEnum optional_foreign_enum = 22;
optional protobuf_unittest_import.ImportEnum optional_import_enum = 23;
optional string optional_string_piece = 24 [ctype=STRING_PIECE];
optional string optional_cord = 25 [ctype=CORD];
// Repeated
repeated int32 repeated_int32 = 31;
repeated int64 repeated_int64 = 32;
repeated uint32 repeated_uint32 = 33;
repeated uint64 repeated_uint64 = 34;
repeated sint32 repeated_sint32 = 35;
repeated sint64 repeated_sint64 = 36;
repeated fixed32 repeated_fixed32 = 37;
repeated fixed64 repeated_fixed64 = 38;
repeated sfixed32 repeated_sfixed32 = 39;
repeated sfixed64 repeated_sfixed64 = 40;
repeated float repeated_float = 41;
repeated double repeated_double = 42;
repeated bool repeated_bool = 43;
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
repeated group RepeatedGroup = 46 {
optional int32 a = 47;
}
repeated NestedMessage repeated_nested_message = 48;
repeated ForeignMessage repeated_foreign_message = 49;
repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50;
repeated NestedEnum repeated_nested_enum = 51;
repeated ForeignEnum repeated_foreign_enum = 52;
repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53;
repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
repeated string repeated_cord = 55 [ctype=CORD];
// Singular with defaults
optional int32 default_int32 = 61 [default = 41 ];
optional int64 default_int64 = 62 [default = 42 ];
optional uint32 default_uint32 = 63 [default = 43 ];
optional uint64 default_uint64 = 64 [default = 44 ];
optional sint32 default_sint32 = 65 [default = -45 ];
optional sint64 default_sint64 = 66 [default = 46 ];
optional fixed32 default_fixed32 = 67 [default = 47 ];
optional fixed64 default_fixed64 = 68 [default = 48 ];
optional sfixed32 default_sfixed32 = 69 [default = 49 ];
optional sfixed64 default_sfixed64 = 70 [default = -50 ];
optional float default_float = 71 [default = 51.5 ];
optional double default_double = 72 [default = 52e3 ];
optional bool default_bool = 73 [default = true ];
optional string default_string = 74 [default = "hello"];
optional bytes default_bytes = 75 [default = "world"];
optional NestedEnum default_nested_enum = 81 [default = BAR ];
optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR];
optional protobuf_unittest_import.ImportEnum
default_import_enum = 83 [default = IMPORT_BAR];
optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
optional string default_cord = 85 [ctype=CORD,default="123"];
}
// Define these after TestAllTypes to make sure the compiler can handle
// that.
message ForeignMessage {
optional int32 c = 1;
}
enum ForeignEnum {
FOREIGN_FOO = 4;
FOREIGN_BAR = 5;
FOREIGN_BAZ = 6;
}
message TestAllExtensions {
extensions 1 to max;
}
extend TestAllExtensions {
// Singular
optional int32 optional_int32_extension = 1;
optional int64 optional_int64_extension = 2;
optional uint32 optional_uint32_extension = 3;
optional uint64 optional_uint64_extension = 4;
optional sint32 optional_sint32_extension = 5;
optional sint64 optional_sint64_extension = 6;
optional fixed32 optional_fixed32_extension = 7;
optional fixed64 optional_fixed64_extension = 8;
optional sfixed32 optional_sfixed32_extension = 9;
optional sfixed64 optional_sfixed64_extension = 10;
optional float optional_float_extension = 11;
optional double optional_double_extension = 12;
optional bool optional_bool_extension = 13;
optional string optional_string_extension = 14;
optional bytes optional_bytes_extension = 15;
optional group OptionalGroup_extension = 16 {
optional int32 a = 17;
}
optional TestAllTypes.NestedMessage optional_nested_message_extension = 18;
optional ForeignMessage optional_foreign_message_extension = 19;
optional protobuf_unittest_import.ImportMessage
optional_import_message_extension = 20;
optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21;
optional ForeignEnum optional_foreign_enum_extension = 22;
optional protobuf_unittest_import.ImportEnum
optional_import_enum_extension = 23;
optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
optional string optional_cord_extension = 25 [ctype=CORD];
// Repeated
repeated int32 repeated_int32_extension = 31;
repeated int64 repeated_int64_extension = 32;
repeated uint32 repeated_uint32_extension = 33;
repeated uint64 repeated_uint64_extension = 34;
repeated sint32 repeated_sint32_extension = 35;
repeated sint64 repeated_sint64_extension = 36;
repeated fixed32 repeated_fixed32_extension = 37;
repeated fixed64 repeated_fixed64_extension = 38;
repeated sfixed32 repeated_sfixed32_extension = 39;
repeated sfixed64 repeated_sfixed64_extension = 40;
repeated float repeated_float_extension = 41;
repeated double repeated_double_extension = 42;
repeated bool repeated_bool_extension = 43;
repeated string repeated_string_extension = 44;
repeated bytes repeated_bytes_extension = 45;
repeated group RepeatedGroup_extension = 46 {
optional int32 a = 47;
}
repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48;
repeated ForeignMessage repeated_foreign_message_extension = 49;
repeated protobuf_unittest_import.ImportMessage
repeated_import_message_extension = 50;
repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51;
repeated ForeignEnum repeated_foreign_enum_extension = 52;
repeated protobuf_unittest_import.ImportEnum
repeated_import_enum_extension = 53;
repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE];
repeated string repeated_cord_extension = 55 [ctype=CORD];
// Singular with defaults
optional int32 default_int32_extension = 61 [default = 41 ];
optional int64 default_int64_extension = 62 [default = 42 ];
optional uint32 default_uint32_extension = 63 [default = 43 ];
optional uint64 default_uint64_extension = 64 [default = 44 ];
optional sint32 default_sint32_extension = 65 [default = -45 ];
optional sint64 default_sint64_extension = 66 [default = 46 ];
optional fixed32 default_fixed32_extension = 67 [default = 47 ];
optional fixed64 default_fixed64_extension = 68 [default = 48 ];
optional sfixed32 default_sfixed32_extension = 69 [default = 49 ];
optional sfixed64 default_sfixed64_extension = 70 [default = -50 ];
optional float default_float_extension = 71 [default = 51.5 ];
optional double default_double_extension = 72 [default = 52e3 ];
optional bool default_bool_extension = 73 [default = true ];
optional string default_string_extension = 74 [default = "hello"];
optional bytes default_bytes_extension = 75 [default = "world"];
optional TestAllTypes.NestedEnum
default_nested_enum_extension = 81 [default = BAR];
optional ForeignEnum
default_foreign_enum_extension = 82 [default = FOREIGN_BAR];
optional protobuf_unittest_import.ImportEnum
default_import_enum_extension = 83 [default = IMPORT_BAR];
optional string default_string_piece_extension = 84 [ctype=STRING_PIECE,
default="abc"];
optional string default_cord_extension = 85 [ctype=CORD, default="123"];
}
// We have separate messages for testing required fields because it's
// annoying to have to fill in required fields in TestProto in order to
// do anything with it. Note that we don't need to test every type of
// required filed because the code output is basically identical to
// optional fields for all types.
message TestRequired {
required int32 a = 1;
optional int32 dummy2 = 2;
required int32 b = 3;
extend TestAllExtensions {
optional TestRequired single = 1000;
repeated TestRequired multi = 1001;
}
// Pad the field count to 32 so that we can test that IsInitialized()
// properly checks multiple elements of has_bits_.
optional int32 dummy4 = 4;
optional int32 dummy5 = 5;
optional int32 dummy6 = 6;
optional int32 dummy7 = 7;
optional int32 dummy8 = 8;
optional int32 dummy9 = 9;
optional int32 dummy10 = 10;
optional int32 dummy11 = 11;
optional int32 dummy12 = 12;
optional int32 dummy13 = 13;
optional int32 dummy14 = 14;
optional int32 dummy15 = 15;
optional int32 dummy16 = 16;
optional int32 dummy17 = 17;
optional int32 dummy18 = 18;
optional int32 dummy19 = 19;
optional int32 dummy20 = 20;
optional int32 dummy21 = 21;
optional int32 dummy22 = 22;
optional int32 dummy23 = 23;
optional int32 dummy24 = 24;
optional int32 dummy25 = 25;
optional int32 dummy26 = 26;
optional int32 dummy27 = 27;
optional int32 dummy28 = 28;
optional int32 dummy29 = 29;
optional int32 dummy30 = 30;
optional int32 dummy31 = 31;
optional int32 dummy32 = 32;
required int32 c = 33;
}
message TestRequiredForeign {
optional TestRequired optional_message = 1;
repeated TestRequired repeated_message = 2;
optional int32 dummy = 3;
}
// Test that we can use NestedMessage from outside TestAllTypes.
message TestForeignNested {
optional TestAllTypes.NestedMessage foreign_nested = 1;
}
// TestEmptyMessage is used to test unknown field support.
message TestEmptyMessage {
}
// Like above, but declare all field numbers as potential extensions. No
// actual extensions should ever be defined for this type.
message TestEmptyMessageWithExtensions {
extensions 1 to max;
}
// Test that really large tag numbers don't break anything.
message TestReallyLargeTagNumber {
// The largest possible tag number is 2^28 - 1, since the wire format uses
// three bits to communicate wire type.
optional int32 a = 1;
optional int32 bb = 268435455;
}
message TestRecursiveMessage {
optional TestRecursiveMessage a = 1;
optional int32 i = 2;
}
// Test that mutual recursion works.
message TestMutualRecursionA {
optional TestMutualRecursionB bb = 1;
}
message TestMutualRecursionB {
optional TestMutualRecursionA a = 1;
optional int32 optional_int32 = 2;
}
// Test that groups have disjoint field numbers from their siblings and
// parents. This is NOT possible in proto1; only proto2. When outputting
// proto1, the dup fields should be dropped.
message TestDupFieldNumber {
optional int32 a = 1;
optional group Foo = 2 { optional int32 a = 1; }
optional group Bar = 3 { optional int32 a = 1; }
}
// Needed for a Python test.
message TestNestedMessageHasBits {
message NestedMessage {
repeated int32 nestedmessage_repeated_int32 = 1;
repeated ForeignMessage nestedmessage_repeated_foreignmessage = 2;
}
optional NestedMessage optional_nested_message = 1;
}
// Test an enum that has multiple values with the same number.
enum TestEnumWithDupValue {
FOO1 = 1;
BAR1 = 2;
BAZ = 3;
FOO2 = 1;
BAR2 = 2;
}
// Test an enum with large, unordered values.
enum TestSparseEnum {
SPARSE_A = 123;
SPARSE_B = 62374;
SPARSE_C = 12589234;
SPARSE_D = -15;
SPARSE_E = -53452;
SPARSE_F = 0;
SPARSE_G = 2;
}
// Test message with CamelCase field names. This violates Protocol Buffer
// standard style.
message TestCamelCaseFieldNames {
optional int32 PrimitiveField = 1;
optional string StringField = 2;
optional ForeignEnum EnumField = 3;
optional ForeignMessage MessageField = 4;
optional string StringPieceField = 5 [ctype=STRING_PIECE];
optional string CordField = 6 [ctype=CORD];
repeated int32 RepeatedPrimitiveField = 7;
repeated string RepeatedStringField = 8;
repeated ForeignEnum RepeatedEnumField = 9;
repeated ForeignMessage RepeatedMessageField = 10;
repeated string RepeatedStringPieceField = 11 [ctype=STRING_PIECE];
repeated string RepeatedCordField = 12 [ctype=CORD];
}
// We list fields out of order, to ensure that we're using field number and not
// field index to determine serialization order.
message TestFieldOrderings {
optional string my_string = 11;
extensions 2 to 10;
optional int64 my_int = 1;
extensions 12 to 100;
optional float my_float = 101;
}
extend TestFieldOrderings {
optional string my_extension_string = 50;
optional int32 my_extension_int = 5;
}
message TestExtremeDefaultValues {
optional bytes escaped_bytes = 1 [default = "\0\001\a\b\f\n\r\t\v\\\'\"\xfe"];
optional uint32 large_uint32 = 2 [default = 0xFFFFFFFF];
optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF];
optional int32 small_int32 = 4 [default = -0x7FFFFFFF];
optional int64 small_int64 = 5 [default = -0x7FFFFFFFFFFFFFFF];
// The default value here is UTF-8 for "\u1234". (We could also just type
// the UTF-8 text directly into this text file rather than escape it, but
// lots of people use editors that would be confused by this.)
optional string utf8_string = 6 [default = "\341\210\264"];
}
// Test that RPC services work.
message FooRequest {}
message FooResponse {}
service TestService {
rpc Foo(FooRequest) returns (FooResponse);
rpc Bar(BarRequest) returns (BarResponse);
}
message BarRequest {}
message BarResponse {}

View File

@ -0,0 +1,36 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// A proto file which imports a proto file that uses optimize_for = CODE_SIZE.
import "unittest_optimize_for.proto";
package protobuf_unittest;
// We optimize for speed here, but we are importing a proto that is optimized
// for code size.
option optimize_for = SPEED;
message TestEmbedOptimizedForSize {
// Test that embedding a message which has optimize_for = CODE_SIZE into
// one optimized for speed works.
optional TestOptimizedForSize optional_message = 1;
repeated TestOptimizedForSize repeated_message = 2;
}

View File

@ -0,0 +1,47 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// A proto file which is imported by unittest.proto to test importing.
// We don't put this in a package within proto2 because we need to make sure
// that the generated code doesn't depend on being in the proto2 namespace.
// In test_util.h we do
// "using namespace unittest_import = protobuf_unittest_import".
package protobuf_unittest_import;
option optimize_for = SPEED;
// Excercise the java_package option.
option java_package = "com.google.protobuf.test";
// Do not set a java_outer_classname here to verify that Proto2 works without
// one.
message ImportMessage {
optional int32 d = 1;
}
enum ImportEnum {
IMPORT_FOO = 7;
IMPORT_BAR = 8;
IMPORT_BAZ = 9;
}

View File

@ -0,0 +1,58 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// This file contains messages for testing message_set_wire_format.
package protobuf_unittest;
option optimize_for = SPEED;
// A message with message_set_wire_format.
message TestMessageSet {
option message_set_wire_format = true;
extensions 4 to max;
}
message TestMessageSetContainer {
optional TestMessageSet message_set = 1;
}
message TestMessageSetExtension1 {
extend TestMessageSet {
optional TestMessageSetExtension1 message_set_extension = 1545008;
}
optional int32 i = 15;
}
message TestMessageSetExtension2 {
extend TestMessageSet {
optional TestMessageSetExtension2 message_set_extension = 1547769;
}
optional string str = 25;
}
// MessageSet wire format is equivalent to this.
message RawMessageSet {
repeated group Item = 1 {
required int32 type_id = 2;
required bytes message = 3;
}
}

View File

@ -0,0 +1,38 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// A proto file which uses optimize_for = CODE_SIZE.
import "unittest.proto";
package protobuf_unittest;
option optimize_for = CODE_SIZE;
message TestOptimizedForSize {
optional int32 i = 1;
optional ForeignMessage msg = 19;
extensions 1000 to max;
extend TestOptimizedForSize {
optional int32 test_extension = 1234;
}
}

View File

@ -0,0 +1,119 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.protobuf;
import java.util.Arrays;
import junit.framework.TestCase;
import protobuf_unittest.EnumWithNoOuter;
import protobuf_unittest.MessageWithNoOuter;
import protobuf_unittest.UnittestProto.ForeignEnum;
import protobuf_unittest.UnittestProto.ForeignMessage;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
/**
* Unit test for generated messages and generated code. See also
* {@link MessageTest}, which tests some generated message functionality.
*
* @author kenton@google.com Kenton Varda
*/
public class GeneratedMessageTest extends TestCase {
public void testAccessors() throws Exception {
TestAllTypes builder = new TestAllTypes();
TestUtil.setAllFields(builder);
TestAllTypes message = builder;
TestUtil.assertAllFieldsSet(message);
}
public void testRepeatedSetters() throws Exception {
TestAllTypes builder = new TestAllTypes();
TestUtil.setAllFields(builder);
TestUtil.modifyRepeatedFields(builder);
TestAllTypes message = builder;
TestUtil.assertRepeatedFieldsModified(message);
}
public void testRepeatedAppend() throws Exception {
TestAllTypes builder = new TestAllTypes();
builder.addAllRepeatedInt32(Arrays.asList(1, 2, 3, 4));
builder.addAllRepeatedForeignEnum(Arrays.asList(ForeignEnum.FOREIGN_BAZ));
ForeignMessage foreignMessage = new ForeignMessage().setC(12);
builder.addAllRepeatedForeignMessage(Arrays.asList(foreignMessage));
TestAllTypes message = builder;
assertEquals(message.getRepeatedInt32List(), Arrays.asList(1, 2, 3, 4));
assertEquals(message.getRepeatedForeignEnumList(),
Arrays.asList(ForeignEnum.FOREIGN_BAZ));
assertEquals(1, message.getRepeatedForeignMessageCount());
assertEquals(12, message.getRepeatedForeignMessage(0).getC());
}
public void testSettingForeignMessageUsingBuilder() throws Exception {
TestAllTypes message = new TestAllTypes()
// Pass builder for foreign message instance.
.setOptionalForeignMessage(new ForeignMessage().setC(123))
;
TestAllTypes expectedMessage = new TestAllTypes()
// Create expected version passing foreign message instance explicitly.
.setOptionalForeignMessage(new ForeignMessage().setC(123))
;
// TODO(ngd): Upgrade to using real #equals method once implemented
assertEquals(expectedMessage.toString(), message.toString());
}
public void testSettingRepeatedForeignMessageUsingBuilder() throws Exception {
TestAllTypes message = new TestAllTypes()
// Pass builder for foreign message instance.
.addRepeatedForeignMessage(new ForeignMessage().setC(456))
;
TestAllTypes expectedMessage = new TestAllTypes()
// Create expected version passing foreign message instance explicitly.
.addRepeatedForeignMessage(
new ForeignMessage().setC(456))
;
assertEquals(expectedMessage.toString(), message.toString());
}
public void testDefaults() throws Exception {
TestUtil.assertClear(new TestAllTypes());
assertEquals("\u1234", new TestExtremeDefaultValues().getUtf8String());
}
// =================================================================
// multiple_files_test
public void testMultipleFilesOption() throws Exception {
// We mostly just want to check that things compile.
MessageWithNoOuter message =
new MessageWithNoOuter()
.setNested(new MessageWithNoOuter.NestedMessage().setI(1))
.addForeign(new TestAllTypes().setOptionalInt32(1))
.setNestedEnum(MessageWithNoOuter.NestedEnum.BAZ)
.setForeignEnum(EnumWithNoOuter.BAR)
;
byte[] data = message.toUnframedByteArray();
MessageWithNoOuter newMessage = MessageWithNoOuter.parseUnframed(data);
assertEquals(message.toString(), newMessage.toString());
}
}

View File

@ -0,0 +1,114 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.protobuf;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestRequired;
import protobuf_unittest.UnittestProto.TestRequiredForeign;
import protobuf_unittest.UnittestProto.ForeignMessage;
import junit.framework.TestCase;
/**
* Misc. unit tests for message operations that apply to both generated
* and dynamic messages.
*
* @author kenton@google.com Kenton Varda
*/
public class MessageTest extends TestCase {
// =================================================================
// Message-merging tests.
static final TestAllTypes MERGE_SOURCE =
new TestAllTypes()
.setOptionalInt32(1)
.setOptionalString("foo")
.setOptionalForeignMessage(new ForeignMessage())
.addRepeatedString("bar")
;
static final TestAllTypes MERGE_DEST =
new TestAllTypes()
.setOptionalInt64(2)
.setOptionalString("baz")
.setOptionalForeignMessage(new ForeignMessage().setC(3))
.addRepeatedString("qux")
;
static final String MERGE_RESULT_TEXT =
"optional_int32: 1\n" +
"optional_int64: 2\n" +
"optional_string: foo\n" +
"optional_foreign_message {\n" +
" c: 3\n" +
"}\n" +
"repeated_string[0]: qux\n" +
"repeated_string[1]: bar\n";
public void testMergeFrom() throws Exception {
TestAllTypes result =
new TestAllTypes().mergeFrom(MERGE_DEST)
.mergeFrom(MERGE_SOURCE);
assertEquals(MERGE_RESULT_TEXT, result.toString());
}
// =================================================================
// Required-field-related tests.
private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
new TestRequired();
private static final TestRequired TEST_REQUIRED_INITIALIZED =
new TestRequired().setA(1).setB(2).setC(3);
public void testRequired() throws Exception {
TestRequired builder = new TestRequired();
assertFalse(builder.isInitialized());
builder.setA(1);
assertFalse(builder.isInitialized());
builder.setB(1);
assertFalse(builder.isInitialized());
builder.setC(1);
assertTrue(builder.isInitialized());
}
public void testRequiredForeign() throws Exception {
TestRequiredForeign builder = new TestRequiredForeign();
assertTrue(builder.isInitialized());
builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
assertFalse(builder.isInitialized());
builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
assertTrue(builder.isInitialized());
builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
assertFalse(builder.isInitialized());
builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
assertTrue(builder.isInitialized());
}
public void testIsInitialized() throws Exception {
assertFalse(new TestRequired().isInitialized());
}
}

View File

@ -0,0 +1,791 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Note: This file contains many lines over 80 characters. It even contains
// many lines over 100 characters, which fails a presubmit test. However,
// given the extremely repetitive nature of the file, I (kenton) feel that
// having similar components of each statement line up is more important than
// avoiding horizontal scrolling. So, I am bypassing the presubmit check.
package com.google.protobuf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import org.apache.activemq.protobuf.Buffer;
import protobuf_unittest.UnittestProto.ForeignEnum;
import protobuf_unittest.UnittestProto.ForeignMessage;
import protobuf_unittest.UnittestProto.TestAllTypes;
import com.google.protobuf.test.UnittestImport.ImportEnum;
import com.google.protobuf.test.UnittestImport.ImportMessage;
/**
* Contains methods for setting all fields of {@code TestAllTypes} to
* some vaules as well as checking that all the fields are set to those values.
* These are useful for testing various protocol message features, e.g.
* set all fields of a message, serialize it, parse it, and check that all
* fields are set.
*
* @author kenton@google.com Kenton Varda
*/
class TestUtil {
private TestUtil() {}
/** Helper to convert a String to ByteSequence. */
private static Buffer toBytes(String str) {
try {
return new Buffer(str.getBytes("UTF-8"));
} catch(java.io.UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not supported.", e);
}
}
/**
* Get a {@code TestAllTypes} with all fields set as they would be by
* {@link #setAllFields(TestAllTypes.Builder)}.
*/
public static TestAllTypes getAllSet() {
TestAllTypes builder = new TestAllTypes();
setAllFields(builder);
return builder;
}
/**
* Set every field of {@code message} to the values expected by
* {@code assertAllFieldsSet()}.
*/
public static void setAllFields(protobuf_unittest.UnittestProto.TestAllTypes message) {
message.setOptionalInt32 (101);
message.setOptionalInt64 (102);
message.setOptionalUint32 (103);
message.setOptionalUint64 (104);
message.setOptionalSint32 (105);
message.setOptionalSint64 (106);
message.setOptionalFixed32 (107);
message.setOptionalFixed64 (108);
message.setOptionalSfixed32(109);
message.setOptionalSfixed64(110);
message.setOptionalFloat (111);
message.setOptionalDouble (112);
message.setOptionalBool (true);
message.setOptionalString ("115");
message.setOptionalBytes (toBytes("116"));
message.setOptionalGroup(
new TestAllTypes.OptionalGroup().setA(117));
message.setOptionalNestedMessage(
new TestAllTypes.NestedMessage().setBb(118));
message.setOptionalForeignMessage(
new ForeignMessage().setC(119));
message.setOptionalImportMessage(
new ImportMessage().setD(120));
message.setOptionalNestedEnum (TestAllTypes.NestedEnum.BAZ);
message.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ);
message.setOptionalImportEnum (ImportEnum.IMPORT_BAZ);
message.setOptionalStringPiece("124");
message.setOptionalCord("125");
// -----------------------------------------------------------------
message.getRepeatedInt32List().add(201);
message.getRepeatedInt64List().add(202L);
message.getRepeatedUint32List().add(203);
message.getRepeatedUint64List().add(204l);
message.getRepeatedSint32List().add(205);
message.getRepeatedSint64List().add (206l);
message.getRepeatedFixed32List().add (207);
message.getRepeatedFixed64List().add (208l);
message.getRepeatedSfixed32List().add(209);
message.getRepeatedSfixed64List().add(210l);
message.getRepeatedFloatList().add (211f);
message.getRepeatedDoubleList().add (212d);
message.getRepeatedBoolList().add (true);
message.getRepeatedStringList().add ("215");
message.getRepeatedBytesList().add (toBytes("216"));
message.getRepeatedGroupList().add(
new TestAllTypes.RepeatedGroup().setA(217));
message.getRepeatedNestedMessageList().add(
new TestAllTypes.NestedMessage().setBb(218));
message.getRepeatedForeignMessageList().add(
new ForeignMessage().setC(219));
message.getRepeatedImportMessageList().add(
new ImportMessage().setD(220));
message.getRepeatedNestedEnumList().add(TestAllTypes.NestedEnum.BAR);
message.getRepeatedForeignEnumList().add(ForeignEnum.FOREIGN_BAR);
message.getRepeatedImportEnumList().add(ImportEnum.IMPORT_BAR);
message.getRepeatedStringPieceList().add("224");
message.getRepeatedCordList().add("225");
// Add a second one of each field.
message.getRepeatedInt32List().add(301);
message.getRepeatedInt64List().add(302L);
message.getRepeatedUint32List().add(303);
message.getRepeatedUint64List().add(304l);
message.getRepeatedSint32List().add(305);
message.getRepeatedSint64List().add (306l);
message.getRepeatedFixed32List().add (307);
message.getRepeatedFixed64List().add (308l);
message.getRepeatedSfixed32List().add(309);
message.getRepeatedSfixed64List().add(310l);
message.getRepeatedFloatList().add (311f);
message.getRepeatedDoubleList().add (312d);
message.getRepeatedBoolList().add (false);
message.getRepeatedStringList().add ("315");
message.getRepeatedBytesList().add (toBytes("316"));
message.getRepeatedGroupList().add(
new TestAllTypes.RepeatedGroup().setA(317));
message.getRepeatedNestedMessageList().add(
new TestAllTypes.NestedMessage().setBb(318));
message.getRepeatedForeignMessageList().add(
new ForeignMessage().setC(319));
message.getRepeatedImportMessageList().add(
new ImportMessage().setD(320));
message.getRepeatedNestedEnumList().add(TestAllTypes.NestedEnum.BAZ);
message.getRepeatedForeignEnumList().add(ForeignEnum.FOREIGN_BAZ);
message.getRepeatedImportEnumList().add(ImportEnum.IMPORT_BAZ);
message.getRepeatedStringPieceList().add("324");
message.getRepeatedCordList().add("325");
// -----------------------------------------------------------------
message.setDefaultInt32 (401);
message.setDefaultInt64 (402);
message.setDefaultUint32 (403);
message.setDefaultUint64 (404);
message.setDefaultSint32 (405);
message.setDefaultSint64 (406);
message.setDefaultFixed32 (407);
message.setDefaultFixed64 (408);
message.setDefaultSfixed32(409);
message.setDefaultSfixed64(410);
message.setDefaultFloat (411);
message.setDefaultDouble (412);
message.setDefaultBool (false);
message.setDefaultString ("415");
message.setDefaultBytes (toBytes("416"));
message.setDefaultNestedEnum (TestAllTypes.NestedEnum.FOO);
message.setDefaultForeignEnum(ForeignEnum.FOREIGN_FOO);
message.setDefaultImportEnum (ImportEnum.IMPORT_FOO);
message.setDefaultStringPiece("424");
message.setDefaultCord("425");
}
// -------------------------------------------------------------------
/**
* Modify the repeated fields of {@code message} to contain the values
* expected by {@code assertRepeatedFieldsModified()}.
*/
public static void modifyRepeatedFields(TestAllTypes message) {
message.getRepeatedInt32List().set(1, 501);
message.getRepeatedInt64List().set (1, 502l);
message.getRepeatedUint32List().set (1, 503);
message.getRepeatedUint64List().set (1, 504l);
message.getRepeatedSint32List().set (1, 505);
message.getRepeatedSint64List().set (1, 506l);
message.getRepeatedFixed32List().set (1, 507);
message.getRepeatedFixed64List().set (1, 508l);
message.getRepeatedSfixed32List().set(1, 509);
message.getRepeatedSfixed64List().set(1, 510l);
message.getRepeatedFloatList().set (1, 511f);
message.getRepeatedDoubleList().set (1, 512d);
message.getRepeatedBoolList().set (1, true);
message.getRepeatedStringList().set (1, "515");
message.getRepeatedBytesList().set (1, toBytes("516"));
message.getRepeatedGroupList().set(1,
new TestAllTypes.RepeatedGroup().setA(517));
message.getRepeatedNestedMessageList().set(1,
new TestAllTypes.NestedMessage().setBb(518));
message.getRepeatedForeignMessageList().set(1,
new ForeignMessage().setC(519));
message.getRepeatedImportMessageList().set(1,
new ImportMessage().setD(520));
message.getRepeatedNestedEnumList().set (1, TestAllTypes.NestedEnum.FOO);
message.getRepeatedForeignEnumList().set(1, ForeignEnum.FOREIGN_FOO);
message.getRepeatedImportEnumList().set (1, ImportEnum.IMPORT_FOO);
message.getRepeatedStringPieceList().set(1, "524");
message.getRepeatedCordList().set(1, "525");
}
// -------------------------------------------------------------------
/**
* Assert (using {@code junit.framework.Assert}} that all fields of
* {@code message} are set to the values assigned by {@code setAllFields}.
*/
public static void assertAllFieldsSet(TestAllTypes message) {
assertTrue(message.hasOptionalInt32 ());
assertTrue(message.hasOptionalInt64 ());
assertTrue(message.hasOptionalUint32 ());
assertTrue(message.hasOptionalUint64 ());
assertTrue(message.hasOptionalSint32 ());
assertTrue(message.hasOptionalSint64 ());
assertTrue(message.hasOptionalFixed32 ());
assertTrue(message.hasOptionalFixed64 ());
assertTrue(message.hasOptionalSfixed32());
assertTrue(message.hasOptionalSfixed64());
assertTrue(message.hasOptionalFloat ());
assertTrue(message.hasOptionalDouble ());
assertTrue(message.hasOptionalBool ());
assertTrue(message.hasOptionalString ());
assertTrue(message.hasOptionalBytes ());
assertTrue(message.hasOptionalGroup ());
assertTrue(message.hasOptionalNestedMessage ());
assertTrue(message.hasOptionalForeignMessage());
assertTrue(message.hasOptionalImportMessage ());
assertTrue(message.getOptionalGroup ().hasA());
assertTrue(message.getOptionalNestedMessage ().hasBb());
assertTrue(message.getOptionalForeignMessage().hasC());
assertTrue(message.getOptionalImportMessage ().hasD());
assertTrue(message.hasOptionalNestedEnum ());
assertTrue(message.hasOptionalForeignEnum());
assertTrue(message.hasOptionalImportEnum ());
assertTrue(message.hasOptionalStringPiece());
assertTrue(message.hasOptionalCord());
assertEquals(101 , message.getOptionalInt32 ());
assertEquals(102 , message.getOptionalInt64 ());
assertEquals(103 , message.getOptionalUint32 ());
assertEquals(104 , message.getOptionalUint64 ());
assertEquals(105 , message.getOptionalSint32 ());
assertEquals(106 , message.getOptionalSint64 ());
assertEquals(107 , message.getOptionalFixed32 ());
assertEquals(108 , message.getOptionalFixed64 ());
assertEquals(109 , message.getOptionalSfixed32());
assertEquals(110 , message.getOptionalSfixed64());
assertEquals(111 , message.getOptionalFloat (), 0.0);
assertEquals(112 , message.getOptionalDouble (), 0.0);
assertEquals(true , message.getOptionalBool ());
assertEquals("115", message.getOptionalString ());
assertEquals(toBytes("116"), message.getOptionalBytes());
assertEquals(117, message.getOptionalGroup ().getA());
assertEquals(118, message.getOptionalNestedMessage ().getBb());
assertEquals(119, message.getOptionalForeignMessage().getC());
assertEquals(120, message.getOptionalImportMessage ().getD());
assertEquals(TestAllTypes.NestedEnum.BAZ, message.getOptionalNestedEnum());
assertEquals(ForeignEnum.FOREIGN_BAZ, message.getOptionalForeignEnum());
assertEquals(ImportEnum.IMPORT_BAZ, message.getOptionalImportEnum());
assertEquals("124", message.getOptionalStringPiece());
assertEquals("125", message.getOptionalCord());
// -----------------------------------------------------------------
assertEquals(2, message.getRepeatedInt32List().size ());
assertEquals(2, message.getRepeatedInt64List().size ());
assertEquals(2, message.getRepeatedUint32List().size ());
assertEquals(2, message.getRepeatedUint64List().size ());
assertEquals(2, message.getRepeatedSint32List().size ());
assertEquals(2, message.getRepeatedSint64List().size ());
assertEquals(2, message.getRepeatedFixed32List().size ());
assertEquals(2, message.getRepeatedFixed64List().size ());
assertEquals(2, message.getRepeatedSfixed32List().size());
assertEquals(2, message.getRepeatedSfixed64List().size());
assertEquals(2, message.getRepeatedFloatList().size ());
assertEquals(2, message.getRepeatedDoubleList().size ());
assertEquals(2, message.getRepeatedBoolList().size ());
assertEquals(2, message.getRepeatedStringList().size ());
assertEquals(2, message.getRepeatedBytesList().size ());
assertEquals(2, message.getRepeatedGroupList().size ());
assertEquals(2, message.getRepeatedNestedMessageList().size ());
assertEquals(2, message.getRepeatedForeignMessageList().size());
assertEquals(2, message.getRepeatedImportMessageList().size ());
assertEquals(2, message.getRepeatedNestedEnumList().size ());
assertEquals(2, message.getRepeatedForeignEnumList().size ());
assertEquals(2, message.getRepeatedImportEnumList().size ());
assertEquals(2, message.getRepeatedStringPieceList().size());
assertEquals(2, message.getRepeatedCordList().size());
assertEquals(201 , (int)message.getRepeatedInt32List().get(0));
assertEquals(202 , (long)message.getRepeatedInt64List().get (0));
assertEquals(203 , (int)message.getRepeatedUint32List().get (0));
assertEquals(204 , (long)message.getRepeatedUint64List().get (0));
assertEquals(205 , (int)message.getRepeatedSint32List().get (0));
assertEquals(206 , (long)message.getRepeatedSint64List().get (0));
assertEquals(207 , (int)message.getRepeatedFixed32List().get (0));
assertEquals(208 , (long)message.getRepeatedFixed64List().get (0));
assertEquals(209 , (int)message.getRepeatedSfixed32List().get(0));
assertEquals(210 , (long)message.getRepeatedSfixed64List().get(0));
assertEquals(211 , message.getRepeatedFloatList().get (0), 0.0);
assertEquals(212 , message.getRepeatedDoubleList().get (0), 0.0);
assertEquals(true , (boolean)message.getRepeatedBoolList().get (0));
assertEquals("215", message.getRepeatedStringList().get (0));
assertEquals(toBytes("216"), message.getRepeatedBytesList().get(0));
assertEquals(217, message.getRepeatedGroupList().get (0).getA());
assertEquals(218, message.getRepeatedNestedMessageList().get (0).getBb());
assertEquals(219, message.getRepeatedForeignMessageList().get(0).getC());
assertEquals(220, message.getRepeatedImportMessageList().get (0).getD());
assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnumList().get (0));
assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnumList().get(0));
assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnumList().get(0));
assertEquals("224", message.getRepeatedStringPieceList().get(0));
assertEquals("225", message.getRepeatedCordList().get(0));
assertEquals(301 , (int)message.getRepeatedInt32List().get (1));
assertEquals(302 , (long)message.getRepeatedInt64List().get (1));
assertEquals(303 , (int)message.getRepeatedUint32List().get (1));
assertEquals(304 , (long)message.getRepeatedUint64List().get (1));
assertEquals(305 , (int)message.getRepeatedSint32List().get (1));
assertEquals(306 , (long)message.getRepeatedSint64List().get (1));
assertEquals(307 , (int)message.getRepeatedFixed32List().get (1));
assertEquals(308 , (long)message.getRepeatedFixed64List().get (1));
assertEquals(309 , (int)message.getRepeatedSfixed32List().get(1));
assertEquals(310 , (long)message.getRepeatedSfixed64List().get(1));
assertEquals(311 , message.getRepeatedFloatList().get (1), 0.0);
assertEquals(312 , message.getRepeatedDoubleList().get (1), 0.0);
assertEquals(false, (boolean)message.getRepeatedBoolList().get (1));
assertEquals("315", message.getRepeatedStringList().get (1));
assertEquals(toBytes("316"), message.getRepeatedBytesList().get(1));
assertEquals(317, message.getRepeatedGroupList().get (1).getA());
assertEquals(318, message.getRepeatedNestedMessageList().get (1).getBb());
assertEquals(319, message.getRepeatedForeignMessageList().get(1).getC());
assertEquals(320, message.getRepeatedImportMessageList().get (1).getD());
assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnumList().get (1));
assertEquals(ForeignEnum.FOREIGN_BAZ, message.getRepeatedForeignEnumList().get(1));
assertEquals(ImportEnum.IMPORT_BAZ, message.getRepeatedImportEnumList().get(1));
assertEquals("324", message.getRepeatedStringPieceList().get(1));
assertEquals("325", message.getRepeatedCordList().get(1));
// -----------------------------------------------------------------
assertTrue(message.hasDefaultInt32 ());
assertTrue(message.hasDefaultInt64 ());
assertTrue(message.hasDefaultUint32 ());
assertTrue(message.hasDefaultUint64 ());
assertTrue(message.hasDefaultSint32 ());
assertTrue(message.hasDefaultSint64 ());
assertTrue(message.hasDefaultFixed32 ());
assertTrue(message.hasDefaultFixed64 ());
assertTrue(message.hasDefaultSfixed32());
assertTrue(message.hasDefaultSfixed64());
assertTrue(message.hasDefaultFloat ());
assertTrue(message.hasDefaultDouble ());
assertTrue(message.hasDefaultBool ());
assertTrue(message.hasDefaultString ());
assertTrue(message.hasDefaultBytes ());
assertTrue(message.hasDefaultNestedEnum ());
assertTrue(message.hasDefaultForeignEnum());
assertTrue(message.hasDefaultImportEnum ());
assertTrue(message.hasDefaultStringPiece());
assertTrue(message.hasDefaultCord());
assertEquals(401 , message.getDefaultInt32 ());
assertEquals(402 , message.getDefaultInt64 ());
assertEquals(403 , message.getDefaultUint32 ());
assertEquals(404 , message.getDefaultUint64 ());
assertEquals(405 , message.getDefaultSint32 ());
assertEquals(406 , message.getDefaultSint64 ());
assertEquals(407 , message.getDefaultFixed32 ());
assertEquals(408 , message.getDefaultFixed64 ());
assertEquals(409 , message.getDefaultSfixed32());
assertEquals(410 , message.getDefaultSfixed64());
assertEquals(411 , message.getDefaultFloat (), 0.0);
assertEquals(412 , message.getDefaultDouble (), 0.0);
assertEquals(false, message.getDefaultBool ());
assertEquals("415", message.getDefaultString ());
assertEquals(toBytes("416"), message.getDefaultBytes());
assertEquals(TestAllTypes.NestedEnum.FOO, message.getDefaultNestedEnum ());
assertEquals(ForeignEnum.FOREIGN_FOO, message.getDefaultForeignEnum());
assertEquals(ImportEnum.IMPORT_FOO, message.getDefaultImportEnum());
assertEquals("424", message.getDefaultStringPiece());
assertEquals("425", message.getDefaultCord());
}
// -------------------------------------------------------------------
/**
* Assert (using {@code junit.framework.Assert}} that all fields of
* {@code message} are cleared, and that getting the fields returns their
* default values.
*/
public static void assertClear(TestAllTypes message) {
// hasBlah() should initially be false for all optional fields.
assertFalse(message.hasOptionalInt32 ());
assertFalse(message.hasOptionalInt64 ());
assertFalse(message.hasOptionalUint32 ());
assertFalse(message.hasOptionalUint64 ());
assertFalse(message.hasOptionalSint32 ());
assertFalse(message.hasOptionalSint64 ());
assertFalse(message.hasOptionalFixed32 ());
assertFalse(message.hasOptionalFixed64 ());
assertFalse(message.hasOptionalSfixed32());
assertFalse(message.hasOptionalSfixed64());
assertFalse(message.hasOptionalFloat ());
assertFalse(message.hasOptionalDouble ());
assertFalse(message.hasOptionalBool ());
assertFalse(message.hasOptionalString ());
assertFalse(message.hasOptionalBytes ());
assertFalse(message.hasOptionalGroup ());
assertFalse(message.hasOptionalNestedMessage ());
assertFalse(message.hasOptionalForeignMessage());
assertFalse(message.hasOptionalImportMessage ());
assertFalse(message.hasOptionalNestedEnum ());
assertFalse(message.hasOptionalForeignEnum());
assertFalse(message.hasOptionalImportEnum ());
assertFalse(message.hasOptionalStringPiece());
assertFalse(message.hasOptionalCord());
// Optional fields without defaults are set to zero or something like it.
assertEquals(0 , message.getOptionalInt32 ());
assertEquals(0 , message.getOptionalInt64 ());
assertEquals(0 , message.getOptionalUint32 ());
assertEquals(0 , message.getOptionalUint64 ());
assertEquals(0 , message.getOptionalSint32 ());
assertEquals(0 , message.getOptionalSint64 ());
assertEquals(0 , message.getOptionalFixed32 ());
assertEquals(0 , message.getOptionalFixed64 ());
assertEquals(0 , message.getOptionalSfixed32());
assertEquals(0 , message.getOptionalSfixed64());
assertEquals(0 , message.getOptionalFloat (), 0.0);
assertEquals(0 , message.getOptionalDouble (), 0.0);
assertEquals(false, message.getOptionalBool ());
assertEquals(null , message.getOptionalString ());
assertEquals(null, message.getOptionalBytes());
assertEquals(null, message.getOptionalNestedEnum ());
assertEquals(null, message.getOptionalForeignEnum());
assertEquals(null, message.getOptionalImportEnum());
assertEquals(null, message.getOptionalStringPiece());
assertEquals(null, message.getOptionalCord());
// Embedded messages should also be clear.
assertFalse(message.getOptionalGroup ().hasA());
assertFalse(message.getOptionalNestedMessage ().hasBb());
assertFalse(message.getOptionalForeignMessage().hasC());
assertFalse(message.getOptionalImportMessage ().hasD());
assertEquals(0, message.getOptionalGroup ().getA());
assertEquals(0, message.getOptionalNestedMessage ().getBb());
assertEquals(0, message.getOptionalForeignMessage().getC());
assertEquals(0, message.getOptionalImportMessage ().getD());
// Repeated fields are empty.
assertEquals(0, message.getRepeatedInt32List().size ());
assertEquals(0, message.getRepeatedInt64List().size ());
assertEquals(0, message.getRepeatedUint32List().size ());
assertEquals(0, message.getRepeatedUint64List().size ());
assertEquals(0, message.getRepeatedSint32List().size ());
assertEquals(0, message.getRepeatedSint64List().size ());
assertEquals(0, message.getRepeatedFixed32List().size ());
assertEquals(0, message.getRepeatedFixed64List().size ());
assertEquals(0, message.getRepeatedSfixed32List().size());
assertEquals(0, message.getRepeatedSfixed64List().size());
assertEquals(0, message.getRepeatedFloatList().size ());
assertEquals(0, message.getRepeatedDoubleList().size ());
assertEquals(0, message.getRepeatedBoolList().size ());
assertEquals(0, message.getRepeatedStringList().size ());
assertEquals(0, message.getRepeatedBytesList().size ());
assertEquals(0, message.getRepeatedGroupList().size ());
assertEquals(0, message.getRepeatedNestedMessageList().size ());
assertEquals(0, message.getRepeatedForeignMessageList().size());
assertEquals(0, message.getRepeatedImportMessageList().size ());
assertEquals(0, message.getRepeatedNestedEnumList().size ());
assertEquals(0, message.getRepeatedForeignEnumList().size ());
assertEquals(0, message.getRepeatedImportEnumList().size ());
assertEquals(0, message.getRepeatedStringPieceList().size());
assertEquals(0, message.getRepeatedCordList().size());
// hasBlah() should also be false for all default fields.
assertFalse(message.hasDefaultInt32 ());
assertFalse(message.hasDefaultInt64 ());
assertFalse(message.hasDefaultUint32 ());
assertFalse(message.hasDefaultUint64 ());
assertFalse(message.hasDefaultSint32 ());
assertFalse(message.hasDefaultSint64 ());
assertFalse(message.hasDefaultFixed32 ());
assertFalse(message.hasDefaultFixed64 ());
assertFalse(message.hasDefaultSfixed32());
assertFalse(message.hasDefaultSfixed64());
assertFalse(message.hasDefaultFloat ());
assertFalse(message.hasDefaultDouble ());
assertFalse(message.hasDefaultBool ());
assertFalse(message.hasDefaultString ());
assertFalse(message.hasDefaultBytes ());
assertFalse(message.hasDefaultNestedEnum ());
assertFalse(message.hasDefaultForeignEnum());
assertFalse(message.hasDefaultImportEnum ());
assertFalse(message.hasDefaultStringPiece());
assertFalse(message.hasDefaultCord());
// Fields with defaults have their default values (duh).
assertEquals( 41 , message.getDefaultInt32 ());
assertEquals( 42 , message.getDefaultInt64 ());
assertEquals( 43 , message.getDefaultUint32 ());
assertEquals( 44 , message.getDefaultUint64 ());
assertEquals(-45 , message.getDefaultSint32 ());
assertEquals( 46 , message.getDefaultSint64 ());
assertEquals( 47 , message.getDefaultFixed32 ());
assertEquals( 48 , message.getDefaultFixed64 ());
assertEquals( 49 , message.getDefaultSfixed32());
assertEquals(-50 , message.getDefaultSfixed64());
assertEquals( 51.5 , message.getDefaultFloat (), 0.0);
assertEquals( 52e3 , message.getDefaultDouble (), 0.0);
assertEquals(true , message.getDefaultBool ());
assertEquals("hello", message.getDefaultString ());
assertEquals(toBytes("world"), message.getDefaultBytes());
assertEquals(TestAllTypes.NestedEnum.BAR, message.getDefaultNestedEnum ());
assertEquals(ForeignEnum.FOREIGN_BAR, message.getDefaultForeignEnum());
assertEquals(ImportEnum.IMPORT_BAR, message.getDefaultImportEnum());
assertEquals("abc", message.getDefaultStringPiece());
assertEquals("123", message.getDefaultCord());
}
// -------------------------------------------------------------------
/**
* Assert (using {@code junit.framework.Assert}} that all fields of
* {@code message} are set to the values assigned by {@code setAllFields}
* followed by {@code modifyRepeatedFields}.
*/
public static void assertRepeatedFieldsModified(TestAllTypes message) {
// ModifyRepeatedFields only sets the second repeated element of each
// field. In addition to verifying this, we also verify that the first
// element and size were *not* modified.
assertEquals(2, message.getRepeatedInt32List().size ());
assertEquals(2, message.getRepeatedInt64List().size ());
assertEquals(2, message.getRepeatedUint32List().size ());
assertEquals(2, message.getRepeatedUint64List().size ());
assertEquals(2, message.getRepeatedSint32List().size ());
assertEquals(2, message.getRepeatedSint64List().size ());
assertEquals(2, message.getRepeatedFixed32List().size ());
assertEquals(2, message.getRepeatedFixed64List().size ());
assertEquals(2, message.getRepeatedSfixed32List().size());
assertEquals(2, message.getRepeatedSfixed64List().size());
assertEquals(2, message.getRepeatedFloatList().size ());
assertEquals(2, message.getRepeatedDoubleList().size ());
assertEquals(2, message.getRepeatedBoolList().size ());
assertEquals(2, message.getRepeatedStringList().size ());
assertEquals(2, message.getRepeatedBytesList().size ());
assertEquals(2, message.getRepeatedGroupList().size ());
assertEquals(2, message.getRepeatedNestedMessageList().size ());
assertEquals(2, message.getRepeatedForeignMessageList().size());
assertEquals(2, message.getRepeatedImportMessageList().size ());
assertEquals(2, message.getRepeatedNestedEnumList().size ());
assertEquals(2, message.getRepeatedForeignEnumList().size ());
assertEquals(2, message.getRepeatedImportEnumList().size ());
assertEquals(2, message.getRepeatedStringPieceList().size());
assertEquals(2, message.getRepeatedCordList().size());
assertEquals(201 , (int)message.getRepeatedInt32List().get (0));
assertEquals(202L , (long)message.getRepeatedInt64List().get (0));
assertEquals(203 , (int)message.getRepeatedUint32List().get (0));
assertEquals(204L , (long)message.getRepeatedUint64List().get (0));
assertEquals(205 , (int)message.getRepeatedSint32List().get (0));
assertEquals(206L , (long)message.getRepeatedSint64List().get (0));
assertEquals(207 , (int)message.getRepeatedFixed32List().get (0));
assertEquals(208L , (long)message.getRepeatedFixed64List().get (0));
assertEquals(209 , (int)message.getRepeatedSfixed32List().get(0));
assertEquals(210L , (long)message.getRepeatedSfixed64List().get(0));
assertEquals(Float.valueOf(211F) , Float.valueOf(message.getRepeatedFloatList().get(0)));
assertEquals(Double.valueOf(212D), Double.valueOf(message.getRepeatedDoubleList().get(0)));
assertEquals(true , (boolean)message.getRepeatedBoolList().get (0));
assertEquals("215", message.getRepeatedStringList().get (0));
assertEquals(toBytes("216"), message.getRepeatedBytesList().get(0));
assertEquals(217, message.getRepeatedGroupList().get (0).getA());
assertEquals(218, message.getRepeatedNestedMessageList().get (0).getBb());
assertEquals(219, message.getRepeatedForeignMessageList().get(0).getC());
assertEquals(220, message.getRepeatedImportMessageList().get (0).getD());
assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnumList().get (0));
assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnumList().get(0));
assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnumList().get(0));
assertEquals("224", message.getRepeatedStringPieceList().get(0));
assertEquals("225", message.getRepeatedCordList().get(0));
// Actually verify the second (modified) elements now.
assertEquals(501 , (int)message.getRepeatedInt32List().get (1));
assertEquals(502L , (long)message.getRepeatedInt64List().get (1));
assertEquals(503 , (int)message.getRepeatedUint32List().get (1));
assertEquals(504L , (long)message.getRepeatedUint64List().get (1));
assertEquals(505 , (int)message.getRepeatedSint32List().get (1));
assertEquals(506L , (long)message.getRepeatedSint64List().get (1));
assertEquals(507 , (int)message.getRepeatedFixed32List().get (1));
assertEquals(508L , (long)message.getRepeatedFixed64List().get (1));
assertEquals(509 , (int)message.getRepeatedSfixed32List().get(1));
assertEquals(510L , (long)message.getRepeatedSfixed64List().get(1));
assertEquals(Float.valueOf(511F) , Float.valueOf(message.getRepeatedFloatList().get(1)));
assertEquals(Double.valueOf(512D) , Double.valueOf(message.getRepeatedDoubleList().get(1)));
assertEquals(true , (boolean)message.getRepeatedBoolList().get (1));
assertEquals("515", message.getRepeatedStringList().get (1));
assertEquals(toBytes("516"), message.getRepeatedBytesList().get(1));
assertEquals(517, message.getRepeatedGroupList().get (1).getA());
assertEquals(518, message.getRepeatedNestedMessageList().get (1).getBb());
assertEquals(519, message.getRepeatedForeignMessageList().get(1).getC());
assertEquals(520, message.getRepeatedImportMessageList().get (1).getD());
assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnumList().get (1));
assertEquals(ForeignEnum.FOREIGN_FOO, message.getRepeatedForeignEnumList().get(1));
assertEquals(ImportEnum.IMPORT_FOO, message.getRepeatedImportEnumList().get(1));
assertEquals("524", message.getRepeatedStringPieceList().get(1));
assertEquals("525", message.getRepeatedCordList().get(1));
}
// ===================================================================
// Like above, but for extensions
// Java gets confused with things like assertEquals(int, Integer): it can't
// decide whether to call assertEquals(int, int) or assertEquals(Object,
// Object). So we define these methods to help it.
private static void assertEqualsExactType(int a, int b) {
assertEquals(a, b);
}
private static void assertEqualsExactType(long a, long b) {
assertEquals(a, b);
}
private static void assertEqualsExactType(float a, float b) {
assertEquals(a, b, 0.0);
}
private static void assertEqualsExactType(double a, double b) {
assertEquals(a, b, 0.0);
}
private static void assertEqualsExactType(boolean a, boolean b) {
assertEquals(a, b);
}
private static void assertEqualsExactType(String a, String b) {
assertEquals(a, b);
}
private static void assertEqualsExactType(Buffer a, Buffer b) {
assertEquals(a, b);
}
private static void assertEqualsExactType(TestAllTypes.NestedEnum a,
TestAllTypes.NestedEnum b) {
assertEquals(a, b);
}
private static void assertEqualsExactType(ForeignEnum a, ForeignEnum b) {
assertEquals(a, b);
}
private static void assertEqualsExactType(ImportEnum a, ImportEnum b) {
assertEquals(a, b);
}
/**
* @param filePath The path relative to
* {@link com.google.testing.util.TestUtil#getDefaultSrcDir}.
*/
public static String readTextFromFile(String filePath) {
return readBytesFromFile(filePath).toStringUtf8();
}
private static File getTestDataDir() {
// Search each parent directory looking for "src/google/protobuf".
File ancestor = new File(".");
try {
ancestor = ancestor.getCanonicalFile();
} catch (IOException e) {
throw new RuntimeException(
"Couldn't get canonical name of working directory.", e);
}
while (ancestor != null && ancestor.exists()) {
if (new File(ancestor, "src/google/protobuf").exists()) {
return new File(ancestor, "src/google/protobuf/testdata");
}
ancestor = ancestor.getParentFile();
}
throw new RuntimeException(
"Could not find golden files. This test must be run from within the " +
"protobuf source package so that it can read test data files from the " +
"C++ source tree.");
}
/**
* @param filePath The path relative to
* {@link com.google.testing.util.TestUtil#getDefaultSrcDir}.
*/
public static Buffer readBytesFromFile(String filename) {
File fullPath = new File(getTestDataDir(), filename);
try(RandomAccessFile file = new RandomAccessFile(fullPath, "r")) {
byte[] content = new byte[(int) file.length()];
file.readFully(content);
return new Buffer(content);
} catch (IOException e) {
// Throw a RuntimeException here so that we can call this function from
// static initializers.
throw new IllegalArgumentException(
"Couldn't read file: " + fullPath.getPath(), e);
}
}
/**
* Get the bytes of the "golden message". This is a serialized TestAllTypes
* with all fields set as they would be by
* {@link setAllFields(TestAllTypes.Builder)}, but it is loaded from a file
* on disk rather than generated dynamically. The file is actually generated
* by C++ code, so testing against it verifies compatibility with C++.
*/
public static Buffer getGoldenMessage() {
if (goldenMessage == null) {
goldenMessage = readBytesFromFile("golden_message");
}
return goldenMessage;
}
private static Buffer goldenMessage = null;
}

View File

@ -0,0 +1,60 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.protobuf;
import junit.framework.TestCase;
import org.apache.activemq.protobuf.Buffer;
import org.apache.activemq.protobuf.CodedInputStream;
import protobuf_unittest.UnittestProto.TestAllTypes;
/**
* Tests related to parsing and serialization.
*
* @author kenton@google.com (Kenton Varda)
*/
public class WireFormatTest extends TestCase {
public void testSerialization() throws Exception {
TestAllTypes message = TestUtil.getAllSet();
byte[] rawBytes = message.toUnframedByteArray();
assertEquals(rawBytes.length, message.serializedSizeUnframed());
TestAllTypes message2 = TestAllTypes.parseUnframed(rawBytes);
TestUtil.assertAllFieldsSet(message2);
}
private void assertFieldsInOrder(Buffer data) throws Exception {
try(CodedInputStream input = new CodedInputStream(data)) {
int previousTag = 0;
while (true) {
int tag = input.readTag();
if (tag == 0) {
break;
}
assertTrue(tag > previousTag);
input.skipField(tag);
}
}
}
}

View File

@ -0,0 +1,53 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Author: kenton@google.com (Kenton Varda)
//
// A proto file which tests the java_multiple_files option.
import "google/protobuf/unittest.proto";
package protobuf_unittest;
option java_multiple_files = true;
option java_outer_classname = "MultipleFilesTestProto";
message MessageWithNoOuter {
message NestedMessage {
optional int32 i = 1;
}
enum NestedEnum {
BAZ = 3;
}
optional NestedMessage nested = 1;
repeated TestAllTypes foreign = 2;
optional NestedEnum nested_enum = 3;
optional EnumWithNoOuter foreign_enum = 4;
}
enum EnumWithNoOuter {
FOO = 1;
BAR = 2;
}
service ServiceWithNoOuter {
rpc Foo(MessageWithNoOuter) returns(TestAllTypes);
}
extend TestAllExtensions {
optional int32 extension_with_outer = 1234567;
}

View File

@ -0,0 +1,75 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
import junit.framework.TestCase;
import org.apache.activemq.protobuf.DeferredUnmarshal.Bar;
import org.apache.activemq.protobuf.DeferredUnmarshal.Foo;
public class DeferredUnmarshalTest extends TestCase {
public void testDeferredDecoding() throws InvalidProtocolBufferException {
Foo foo = new Foo();
foo.setField1(5);
foo.setField2(20);
Bar bar = new Bar();
// There is no decoding pending so its' considered decoded.
assertTrue(bar.isDecoded());
bar.setField1(25);
bar.setField2(220);
bar.setField3(foo);
// The message should not be encoded yet.
assertFalse(bar.isEncoded());
// The message should be encoded now..
byte[] encodedForm = bar.toUnframedByteArray();
assertTrue(bar.isEncoded());
// Repeated encoding operations should just give back the same byte[]
assertTrue(encodedForm == bar.toUnframedByteArray());
// Decoding does not occur until a field is accessed. The new message should
// still be considered encoded.
Bar bar2 = Bar.parseUnframed(encodedForm);
assertTrue(bar2.isEncoded());
assertFalse(bar2.isDecoded());
// This should now decode the message.
assertEquals(25, bar2.getField1());
assertTrue(bar2.isDecoded());
// Since bar2 still has not been modified it should still spit out the same
// byte[]
assertTrue(encodedForm == bar2.toUnframedByteArray());
// Nested messages should remain un-decoded.
assertFalse(bar2.getField3().isDecoded());
// Changing a field should remove the encoding.
bar2.setField1(35);
assertFalse(bar2.isEncoded());
assertTrue(bar2.isDecoded());
}
}

View File

@ -0,0 +1,57 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
import org.apache.activemq.protobuf.DeferredUnmarshal.Bar;
import org.apache.activemq.protobuf.DeferredUnmarshal.Foo;
import junit.framework.TestCase;
public class EqualsTest extends TestCase {
public void testDeferredUnmarshal() {
Bar bar1 = createBar();
Bar bar2 = createBar();
// They should have the same hash and equal the same value.
assertTrue(bar1.hashCode() == bar2.hashCode());
assertTrue(bar1.equals(bar2));
// Change bar2 a little.
bar2.setField2(35);
assertFalse(bar1.hashCode() == bar2.hashCode());
assertFalse(bar1.equals(bar2));
}
private Bar createBar() {
Bar bar;
Foo foo = new Foo();
foo.setField1(5);
foo.setField2(20);
bar = new Bar();
bar.setField1(25);
bar.setField2(220);
bar.setField3(foo);
return bar;
}
}

View File

@ -0,0 +1,25 @@
=======================================================================
The AcitveMQ Protocol Buffers Java Implementation
=======================================================================
Protocol Buffers is a data interchange format developed by
Google. You can get more information about Protocol Buffers
at:
http://code.google.com/apis/protocolbuffers/
Unfortunately the the main Protocol Buffer's project made the
Java API cumbersome to use since the messages are immutable. They
Justify this decision by highlighting the fact it reduces end user
error that occur with Mutable messages.
This module brings you a slimmed down lean and mean API to accessing
Protocol Buffer data structures. It provides little protection
from end users 'hurting themselves', but it does give power user
and easier to use API.
In addition, this module provides a Java based code generator so
that it's easier to code generate your Protocol Buffer classes in
a java based build system like Ant or Maven.

90
activemq-protobuf/pom.xml Normal file
View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-parent</artifactId>
<version>6.1.3-SNAPSHOT</version>
</parent>
<groupId>org.apache.activemq.protobuf</groupId>
<artifactId>activemq-protobuf</artifactId>
<packaging>maven-plugin</packaging>
<name>ActiveMQ :: Protocol Buffers and Compiler</name>
<description>
A Simpler Protocol Buffer Java API. Includes a Proto to Java compiler.
</description>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven-core-version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven-core-version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<configuration>
<goalPrefix>amqprotobuf</goalPrefix>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>javacc-maven-plugin</artifactId>
<executions>
<execution>
<id>javacc</id>
<goals>
<goal>javacc</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,91 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
final public class AsciiBuffer extends Buffer {
private int hashCode;
public AsciiBuffer(Buffer other) {
super(other);
}
public AsciiBuffer(byte[] data, int offset, int length) {
super(data, offset, length);
}
public AsciiBuffer(byte[] data) {
super(data);
}
public AsciiBuffer(String input) {
super(encode(input));
}
public AsciiBuffer compact() {
if (length != data.length) {
return new AsciiBuffer(toByteArray());
}
return this;
}
public String toString()
{
return decode(this);
}
@Override
public boolean equals(Object obj) {
if( obj==this )
return true;
if( obj==null || obj.getClass()!=AsciiBuffer.class )
return false;
return equals((Buffer)obj);
}
@Override
public int hashCode() {
if( hashCode==0 ) {
hashCode = super.hashCode();;
}
return hashCode;
}
static public byte[] encode(String value)
{
int size = value.length();
byte rc[] = new byte[size];
for( int i=0; i < size; i++ ) {
rc[i] = (byte)(value.charAt(i)&0xFF);
}
return rc;
}
static public String decode(Buffer value)
{
int size = value.getLength();
char rc[] = new char[size];
for( int i=0; i < size; i++ ) {
rc[i] = (char)(value.byteAt(i) & 0xFF );
}
return new String(rc);
}
}

View File

@ -0,0 +1,334 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
import static org.apache.activemq.protobuf.WireFormat.WIRETYPE_END_GROUP;
import static org.apache.activemq.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED;
import static org.apache.activemq.protobuf.WireFormat.WIRETYPE_START_GROUP;
import static org.apache.activemq.protobuf.WireFormat.makeTag;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
abstract public class BaseMessage<T> implements Message<T> {
protected int memoizedSerializedSize = -1;
abstract public T clone() throws CloneNotSupportedException;
public void clear() {
memoizedSerializedSize = -1;
}
public boolean isInitialized() {
return missingFields().isEmpty();
}
@SuppressWarnings("unchecked")
public T assertInitialized() throws UninitializedMessageException {
java.util.ArrayList<String> missingFields = missingFields();
if (!missingFields.isEmpty()) {
throw new UninitializedMessageException(missingFields);
}
return getThis();
}
@SuppressWarnings("unchecked")
protected T checktInitialized() throws InvalidProtocolBufferException {
java.util.ArrayList<String> missingFields = missingFields();
if (!missingFields.isEmpty()) {
throw new UninitializedMessageException(missingFields).asInvalidProtocolBufferException();
}
return getThis();
}
public ArrayList<String> missingFields() {
load();
return new ArrayList<String>();
}
protected void loadAndClear() {
memoizedSerializedSize = -1;
}
protected void load() {
}
@SuppressWarnings("unchecked")
public T mergeFrom(T other) {
return getThis();
}
public void writeUnframed(CodedOutputStream output) throws java.io.IOException {
// if (encodedForm == null) {
// encodedForm = new byte[serializedSizeUnframed()];
// com.google.protobuf.CodedOutputStream original = output;
// output =
// com.google.protobuf.CodedOutputStream.newInstance(encodedForm);
// if (hasField1()) {
// output.writeInt32(1, getField1());
// }
// if (hasField2()) {
// output.writeInt64(2, getField2());
// }
// if (hasField3()) {
// writeMessage(output, 3, getField3());
// }
// output.checkNoSpaceLeft();
// output = original;
// }
// output.writeRawBytes(encodedForm);
}
// /////////////////////////////////////////////////////////////////
// Write related helpers.
// /////////////////////////////////////////////////////////////////
public void writeFramed(CodedOutputStream output) throws IOException {
output.writeRawVarint32(serializedSizeUnframed());
writeUnframed(output);
}
public Buffer toUnframedBuffer() {
try {
int size = serializedSizeUnframed();
BufferOutputStream baos = new BufferOutputStream(size);
CodedOutputStream output = new CodedOutputStream(baos);
writeUnframed(output);
Buffer rc = baos.toBuffer();
if( rc.length != size ) {
throw new IllegalStateException("Did not write as much data as expected.");
}
return rc;
} catch (IOException e) {
throw new RuntimeException("Serializing to a byte array threw an IOException " + "(should never happen).", e);
}
}
public Buffer toFramedBuffer() {
try {
int size = serializedSizeFramed();
BufferOutputStream baos = new BufferOutputStream(size);
CodedOutputStream output = new CodedOutputStream(baos);
writeFramed(output);
Buffer rc = baos.toBuffer();
if( rc.length != size ) {
throw new IllegalStateException("Did not write as much data as expected.");
}
return rc;
} catch (IOException e) {
throw new RuntimeException("Serializing to a byte array threw an IOException " + "(should never happen).", e);
}
}
public byte[] toUnframedByteArray() {
return toUnframedBuffer().toByteArray();
}
public byte[] toFramedByteArray() {
return toFramedBuffer().toByteArray();
}
public void writeFramed(OutputStream output) throws IOException {
CodedOutputStream codedOutput = new CodedOutputStream(output);
writeFramed(codedOutput);
codedOutput.flush();
}
public void writeUnframed(OutputStream output) throws IOException {
CodedOutputStream codedOutput = new CodedOutputStream(output);
writeUnframed(codedOutput);
codedOutput.flush();
}
public int serializedSizeFramed() {
int t = serializedSizeUnframed();
return CodedOutputStream.computeRawVarint32Size(t) + t;
}
// /////////////////////////////////////////////////////////////////
// Read related helpers.
// /////////////////////////////////////////////////////////////////
public T mergeFramed(CodedInputStream input) throws IOException {
int length = input.readRawVarint32();
int oldLimit = input.pushLimit(length);
T rc = mergeUnframed(input);
input.checkLastTagWas(0);
input.popLimit(oldLimit);
return rc;
}
public T mergeUnframed(Buffer data) throws InvalidProtocolBufferException {
try {
CodedInputStream input = new CodedInputStream(data);
mergeUnframed(input);
input.checkLastTagWas(0);
return getThis();
} catch (InvalidProtocolBufferException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException("An IOException was thrown (should never happen in this method).", e);
}
}
@SuppressWarnings("unchecked")
private T getThis() {
return (T) this;
}
public T mergeFramed(Buffer data) throws InvalidProtocolBufferException {
try {
CodedInputStream input = new CodedInputStream(data);
mergeFramed(input);
input.checkLastTagWas(0);
return getThis();
} catch (InvalidProtocolBufferException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException("An IOException was thrown (should never happen in this method).", e);
}
}
public T mergeUnframed(byte[] data) throws InvalidProtocolBufferException {
return mergeUnframed(new Buffer(data));
}
public T mergeFramed(byte[] data) throws InvalidProtocolBufferException {
return mergeFramed(new Buffer(data));
}
public T mergeUnframed(InputStream input) throws IOException {
CodedInputStream codedInput = new CodedInputStream(input);
mergeUnframed(codedInput);
return getThis();
}
public T mergeFramed(InputStream input) throws IOException {
int length = readRawVarint32(input);
byte[] data = new byte[length];
int pos = 0;
while (pos < length) {
int r = input.read(data, pos, length - pos);
if (r < 0) {
throw new InvalidProtocolBufferException("Input stream ended before a full message frame could be read.");
}
pos += r;
}
return mergeUnframed(data);
}
// /////////////////////////////////////////////////////////////////
// Internal implementation methods.
// /////////////////////////////////////////////////////////////////
static protected <T> void addAll(Iterable<T> values, Collection<? super T> list) {
if (values instanceof Collection) {
@SuppressWarnings("unsafe")
Collection<T> collection = (Collection<T>) values;
list.addAll(collection);
} else {
for (T value : values) {
list.add(value);
}
}
}
static protected void writeGroup(CodedOutputStream output, int tag, BaseMessage message) throws IOException {
output.writeTag(tag, WIRETYPE_START_GROUP);
message.writeUnframed(output);
output.writeTag(tag, WIRETYPE_END_GROUP);
}
static protected <T extends BaseMessage> T readGroup(CodedInputStream input, int tag, T group) throws IOException {
group.mergeUnframed(input);
input.checkLastTagWas(makeTag(tag, WIRETYPE_END_GROUP));
return group;
}
static protected int computeGroupSize(int tag, BaseMessage message) {
return CodedOutputStream.computeTagSize(tag) * 2 + message.serializedSizeUnframed();
}
static protected void writeMessage(CodedOutputStream output, int tag, BaseMessage message) throws IOException {
output.writeTag(tag, WIRETYPE_LENGTH_DELIMITED);
message.writeFramed(output);
}
static protected int computeMessageSize(int tag, BaseMessage message) {
return CodedOutputStream.computeTagSize(tag) + message.serializedSizeFramed();
}
protected List<String> prefix(List<String> missingFields, String prefix) {
ArrayList<String> rc = new ArrayList<String>(missingFields.size());
for (String v : missingFields) {
rc.add(prefix + v);
}
return rc;
}
/**
* Read a raw Varint from the stream. If larger than 32 bits, discard the
* upper bits.
*/
static public int readRawVarint32(InputStream is) throws IOException {
byte tmp = readRawByte(is);
if (tmp >= 0) {
return tmp;
}
int result = tmp & 0x7f;
if ((tmp = readRawByte(is)) >= 0) {
result |= tmp << 7;
} else {
result |= (tmp & 0x7f) << 7;
if ((tmp = readRawByte(is)) >= 0) {
result |= tmp << 14;
} else {
result |= (tmp & 0x7f) << 14;
if ((tmp = readRawByte(is)) >= 0) {
result |= tmp << 21;
} else {
result |= (tmp & 0x7f) << 21;
result |= (tmp = readRawByte(is)) << 28;
if (tmp < 0) {
// Discard upper 32 bits.
for (int i = 0; i < 5; i++) {
if (readRawByte(is) >= 0)
return result;
}
throw new InvalidProtocolBufferException("CodedInputStream encountered a malformed varint.");
}
}
}
}
return result;
}
static protected byte readRawByte(InputStream is) throws IOException {
int rc = is.read();
if (rc == -1) {
throw new InvalidProtocolBufferException("While parsing a protocol message, the input ended unexpectedly " + "in the middle of a field. This could mean either than the " + "input has been truncated or that an embedded message "
+ "misreported its own length.");
}
return (byte) rc;
}
}

View File

@ -0,0 +1,211 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
import java.util.List;
public class Buffer implements Comparable<Buffer> {
final public byte[] data;
final public int offset;
final public int length;
public Buffer(Buffer other) {
this(other.data, other.offset, other.length);
}
public Buffer(byte data[]) {
this(data, 0, data.length);
}
public Buffer(byte data[], int offset, int length) {
this.data = data;
this.offset = offset;
this.length = length;
}
@Deprecated
public Buffer(String value) {
this(UTF8Buffer.encode(value));
}
public final Buffer slice(int low, int high) {
int sz;
if (high < 0) {
sz = length + high;
} else {
sz = high - low;
}
if (sz < 0) {
sz = 0;
}
return new Buffer(data, offset + low, sz);
}
public final byte[] getData() {
return data;
}
public final int getLength() {
return length;
}
public final int getOffset() {
return offset;
}
public Buffer compact() {
if (length != data.length) {
return new Buffer(toByteArray());
}
return this;
}
final public byte[] toByteArray() {
byte[] data = this.data;
int length = this.length;
if (length != data.length) {
byte t[] = new byte[length];
System.arraycopy(data, offset, t, 0, length);
data = t;
}
return data;
}
public byte byteAt(int i) {
return data[offset + i];
}
@Override
public int hashCode() {
byte[] target = new byte[4];
for (int i = 0; i < length; i++) {
target[i % 4] ^= data[offset + i];
}
return target[0] << 24 | target[1] << 16 | target[2] << 8 | target[3];
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj == null || obj.getClass() != Buffer.class)
return false;
return equals((Buffer) obj);
}
final public boolean equals(Buffer obj) {
if (length != obj.length) {
return false;
}
for (int i = 0; i < length; i++) {
if (obj.data[obj.offset + i] != data[offset + i]) {
return false;
}
}
return true;
}
final public BufferInputStream newInput() {
return new BufferInputStream(this);
}
final public BufferOutputStream newOutput() {
return new BufferOutputStream(this);
}
final public boolean isEmpty() {
return length == 0;
}
final public boolean contains(byte value) {
return indexOf(value, 0) >= 0;
}
final public int indexOf(byte value, int pos) {
for (int i = pos; i < length; i++) {
if (data[offset + i] == value) {
return i;
}
}
return -1;
}
final public static Buffer join(List<Buffer> items, Buffer seperator) {
if (items.isEmpty())
return new Buffer(seperator.data, 0, 0);
int size = 0;
for (Buffer item : items) {
size += item.length;
}
size += seperator.length * (items.size() - 1);
int pos = 0;
byte data[] = new byte[size];
for (Buffer item : items) {
if (pos != 0) {
System.arraycopy(seperator.data, seperator.offset, data, pos, seperator.length);
pos += seperator.length;
}
System.arraycopy(item.data, item.offset, data, pos, item.length);
pos += item.length;
}
return new Buffer(data, 0, size);
}
@Deprecated
public String toStringUtf8() {
return UTF8Buffer.decode(this);
}
public int compareTo(Buffer o) {
int minLength = Math.min(length, o.length);
if (offset == o.offset) {
int pos = offset;
int limit = minLength + offset;
while (pos < limit) {
byte b1 = data[pos];
byte b2 = o.data[pos];
if (b1 != b2) {
return b1 - b2;
}
pos++;
}
} else {
int offset1 = offset;
int offset2 = o.offset;
while ( minLength-- != 0) {
byte b1 = data[offset1++];
byte b2 = o.data[offset2++];
if (b1 != b2) {
return b1 - b2;
}
}
}
return length - o.length;
}
}

View File

@ -0,0 +1,109 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
import java.io.IOException;
import java.io.InputStream;
/**
* Very similar to the java.io.ByteArrayInputStream but this version is not
* thread safe.
*/
final public class BufferInputStream extends InputStream {
byte buffer[];
int limit;
int pos;
int mark;
public BufferInputStream(byte data[]) {
this(data, 0, data.length);
}
public BufferInputStream(Buffer sequence) {
this(sequence.getData(), sequence.getOffset(), sequence.getLength());
}
public BufferInputStream(byte data[], int offset, int size) {
this.buffer = data;
this.mark = offset;
this.pos = offset;
this.limit = offset + size;
}
public int read() throws IOException {
if (pos < limit) {
return buffer[pos++] & 0xff;
} else {
return -1;
}
}
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) {
if (pos < limit) {
len = Math.min(len, limit - pos);
System.arraycopy(buffer, pos, b, off, len);
pos += len;
return len;
} else {
return -1;
}
}
public Buffer readBuffer(int len) {
Buffer rc=null;
if (pos < limit) {
len = Math.min(len, limit - pos);
rc = new Buffer(buffer, pos, len);
pos += len;
}
return rc;
}
public long skip(long len) throws IOException {
if (pos < limit) {
len = Math.min(len, limit - pos);
if (len > 0) {
pos += len;
}
return len;
} else {
return -1;
}
}
public int available() {
return limit - pos;
}
public boolean markSupported() {
return true;
}
public void mark(int markpos) {
mark = pos;
}
public void reset() {
pos = mark;
}
}

View File

@ -0,0 +1,101 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
import java.io.EOFException;
import java.io.IOException;
import java.io.OutputStream;
/**
* Very similar to the java.io.ByteArrayOutputStream but this version
* is not thread safe and the resulting data is returned in a Buffer
* to avoid an extra byte[] allocation. It also does not re-grow it's
* internal buffer.
*/
final public class BufferOutputStream extends OutputStream {
byte buffer[];
int offset;
int limit;
int pos;
public BufferOutputStream(int size) {
this(new byte[size]);
}
public BufferOutputStream(byte[] buffer) {
this.buffer = buffer;
this.limit = buffer.length;
}
public BufferOutputStream(Buffer data) {
this.buffer = data.data;
this.pos = this.offset = data.offset;
this.limit = data.offset+data.length;
}
public void write(int b) throws IOException {
int newPos = pos + 1;
checkCapacity(newPos);
buffer[pos] = (byte) b;
pos = newPos;
}
public void write(byte b[], int off, int len) throws IOException {
int newPos = pos + len;
checkCapacity(newPos);
System.arraycopy(b, off, buffer, pos, len);
pos = newPos;
}
public Buffer getNextBuffer(int len) throws IOException {
int newPos = pos + len;
checkCapacity(newPos);
return new Buffer(buffer, pos, len);
}
/**
* Ensures the the buffer has at least the minimumCapacity specified.
* @param i
* @throws EOFException
*/
private void checkCapacity(int minimumCapacity) throws IOException {
if( minimumCapacity > limit ) {
throw new EOFException("Buffer limit reached.");
}
}
public void reset() {
pos = offset;
}
public Buffer toBuffer() {
return new Buffer(buffer, offset, pos);
}
public byte[] toByteArray() {
return toBuffer().toByteArray();
}
public int size() {
return offset-pos;
}
}

View File

@ -0,0 +1,418 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.apache.activemq.protobuf;
import java.io.EOFException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Reads and decodes protocol message fields.
*
* This class contains two kinds of methods: methods that read specific protocol
* message constructs and field types (e.g. {@link #readTag()} and
* {@link #readInt32()}) and methods that read low-level values (e.g.
* {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading
* encoded protocol messages, you should use the former methods, but if you are
* reading some other format of your own design, use the latter.
*
* @author kenton@google.com Kenton Varda
*/
public final class CodedInputStream extends FilterInputStream {
private int lastTag = 0;
private int limit = Integer.MAX_VALUE;
private int pos;
private BufferInputStream bis;
public CodedInputStream(InputStream in) {
super(in);
if( in.getClass() == BufferInputStream.class ) {
bis = (BufferInputStream)in;
}
}
public CodedInputStream(Buffer data) {
this(new BufferInputStream(data));
limit = data.length;
}
public CodedInputStream(byte[] data) {
this(new BufferInputStream(data));
limit = data.length;
}
/**
* Attempt to read a field tag, returning zero if we have reached EOF.
* Protocol message parsers use this to read tags, since a protocol message
* may legally end wherever a tag occurs, and zero is not a valid tag
* number.
*/
public int readTag() throws IOException {
if( pos >= limit ) {
lastTag=0;
return 0;
}
try {
lastTag = readRawVarint32();
if (lastTag == 0) {
// If we actually read zero, that's not a valid tag.
throw InvalidProtocolBufferException.invalidTag();
}
return lastTag;
} catch (EOFException e) {
lastTag=0;
return 0;
}
}
/**
* Verifies that the last call to readTag() returned the given tag value.
* This is used to verify that a nested group ended with the correct end
* tag.
*
* @throws InvalidProtocolBufferException
* {@code value} does not match the last tag.
*/
public void checkLastTagWas(int value) throws InvalidProtocolBufferException {
if (lastTag != value) {
throw InvalidProtocolBufferException.invalidEndTag();
}
}
/**
* Reads and discards a single field, given its tag value.
*
* @return {@code false} if the tag is an endgroup tag, in which case
* nothing is skipped. Otherwise, returns {@code true}.
*/
public boolean skipField(int tag) throws IOException {
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
readInt32();
return true;
case WireFormat.WIRETYPE_FIXED64:
readRawLittleEndian64();
return true;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
skipRawBytes(readRawVarint32());
return true;
case WireFormat.WIRETYPE_START_GROUP:
skipMessage();
checkLastTagWas(WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
return true;
case WireFormat.WIRETYPE_END_GROUP:
return false;
case WireFormat.WIRETYPE_FIXED32:
readRawLittleEndian32();
return true;
default:
throw InvalidProtocolBufferException.invalidWireType();
}
}
/**
* Reads and discards an entire message. This will read either until EOF or
* until an endgroup tag, whichever comes first.
*/
public void skipMessage() throws IOException {
while (true) {
int tag = readTag();
if (tag == 0 || !skipField(tag))
return;
}
}
// -----------------------------------------------------------------
/** Read a {@code double} field value from the stream. */
public double readDouble() throws IOException {
return Double.longBitsToDouble(readRawLittleEndian64());
}
/** Read a {@code float} field value from the stream. */
public float readFloat() throws IOException {
return Float.intBitsToFloat(readRawLittleEndian32());
}
/** Read a {@code uint64} field value from the stream. */
public long readUInt64() throws IOException {
return readRawVarint64();
}
/** Read an {@code int64} field value from the stream. */
public long readInt64() throws IOException {
return readRawVarint64();
}
/** Read an {@code int32} field value from the stream. */
public int readInt32() throws IOException {
return readRawVarint32();
}
/** Read a {@code fixed64} field value from the stream. */
public long readFixed64() throws IOException {
return readRawLittleEndian64();
}
/** Read a {@code fixed32} field value from the stream. */
public int readFixed32() throws IOException {
return readRawLittleEndian32();
}
/** Read a {@code bool} field value from the stream. */
public boolean readBool() throws IOException {
return readRawVarint32() != 0;
}
/** Read a {@code string} field value from the stream. */
public String readString() throws IOException {
int size = readRawVarint32();
Buffer data = readRawBytes(size);
return new String(data.data, data.offset, data.length, "UTF-8");
}
/** Read a {@code bytes} field value from the stream. */
public Buffer readBytes() throws IOException {
int size = readRawVarint32();
return readRawBytes(size);
}
/** Read a {@code uint32} field value from the stream. */
public int readUInt32() throws IOException {
return readRawVarint32();
}
/**
* Read an enum field value from the stream. Caller is responsible for
* converting the numeric value to an actual enum.
*/
public int readEnum() throws IOException {
return readRawVarint32();
}
/** Read an {@code sfixed32} field value from the stream. */
public int readSFixed32() throws IOException {
return readRawLittleEndian32();
}
/** Read an {@code sfixed64} field value from the stream. */
public long readSFixed64() throws IOException {
return readRawLittleEndian64();
}
/** Read an {@code sint32} field value from the stream. */
public int readSInt32() throws IOException {
return decodeZigZag32(readRawVarint32());
}
/** Read an {@code sint64} field value from the stream. */
public long readSInt64() throws IOException {
return decodeZigZag64(readRawVarint64());
}
// =================================================================
/**
* Read a raw Varint from the stream. If larger than 32 bits, discard the
* upper bits.
*/
public int readRawVarint32() throws IOException {
byte tmp = readRawByte();
if (tmp >= 0) {
return tmp;
}
int result = tmp & 0x7f;
if ((tmp = readRawByte()) >= 0) {
result |= tmp << 7;
} else {
result |= (tmp & 0x7f) << 7;
if ((tmp = readRawByte()) >= 0) {
result |= tmp << 14;
} else {
result |= (tmp & 0x7f) << 14;
if ((tmp = readRawByte()) >= 0) {
result |= tmp << 21;
} else {
result |= (tmp & 0x7f) << 21;
result |= (tmp = readRawByte()) << 28;
if (tmp < 0) {
// Discard upper 32 bits.
for (int i = 0; i < 5; i++) {
if (readRawByte() >= 0)
return result;
}
throw InvalidProtocolBufferException.malformedVarint();
}
}
}
}
return result;
}
/** Read a raw Varint from the stream. */
public long readRawVarint64() throws IOException {
int shift = 0;
long result = 0;
while (shift < 64) {
byte b = readRawByte();
result |= (long) (b & 0x7F) << shift;
if ((b & 0x80) == 0)
return result;
shift += 7;
}
throw InvalidProtocolBufferException.malformedVarint();
}
/** Read a 32-bit little-endian integer from the stream. */
public int readRawLittleEndian32() throws IOException {
byte b1 = readRawByte();
byte b2 = readRawByte();
byte b3 = readRawByte();
byte b4 = readRawByte();
return (((int) b1 & 0xff)) | (((int) b2 & 0xff) << 8) | (((int) b3 & 0xff) << 16) | (((int) b4 & 0xff) << 24);
}
/** Read a 64-bit little-endian integer from the stream. */
public long readRawLittleEndian64() throws IOException {
byte b1 = readRawByte();
byte b2 = readRawByte();
byte b3 = readRawByte();
byte b4 = readRawByte();
byte b5 = readRawByte();
byte b6 = readRawByte();
byte b7 = readRawByte();
byte b8 = readRawByte();
return (((long) b1 & 0xff)) | (((long) b2 & 0xff) << 8) | (((long) b3 & 0xff) << 16) | (((long) b4 & 0xff) << 24) | (((long) b5 & 0xff) << 32) | (((long) b6 & 0xff) << 40) | (((long) b7 & 0xff) << 48) | (((long) b8 & 0xff) << 56);
}
/**
* Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers into
* values that can be efficiently encoded with varint. (Otherwise, negative
* values must be sign-extended to 64 bits to be varint encoded, thus always
* taking 10 bytes on the wire.)
*
* @param n
* An unsigned 32-bit integer, stored in a signed int because
* Java has no explicit unsigned support.
* @return A signed 32-bit integer.
*/
public static int decodeZigZag32(int n) {
return (n >>> 1) ^ -(n & 1);
}
/**
* Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers into
* values that can be efficiently encoded with varint. (Otherwise, negative
* values must be sign-extended to 64 bits to be varint encoded, thus always
* taking 10 bytes on the wire.)
*
* @param n
* An unsigned 64-bit integer, stored in a signed int because
* Java has no explicit unsigned support.
* @return A signed 64-bit integer.
*/
public static long decodeZigZag64(long n) {
return (n >>> 1) ^ -(n & 1);
}
/**
* Read one byte from the input.
*
* @throws InvalidProtocolBufferException
* The end of the stream or the current limit was reached.
*/
public byte readRawByte() throws IOException {
if( pos >= limit ) {
throw new EOFException();
}
int rc = in.read();
if( rc < 0 ) {
throw new EOFException();
}
pos++;
return (byte)( rc & 0xFF);
}
/**
* Read a fixed size of bytes from the input.
*
* @throws InvalidProtocolBufferException
* The end of the stream or the current limit was reached.
*/
public Buffer readRawBytes(int size) throws IOException {
if( size == 0) {
return new Buffer(new byte[]{});
}
if( this.pos+size > limit ) {
throw new EOFException();
}
// If the underlying stream is a ByteArrayInputStream
// then we can avoid an array copy.
if( bis!=null ) {
Buffer rc = bis.readBuffer(size);
if( rc==null || rc.getLength() < size ) {
throw new EOFException();
}
this.pos += rc.getLength();
return rc;
}
// Otherwise we, have to do it the old fasioned way
byte[] rc = new byte[size];
int c;
int pos=0;
while( pos < size ) {
c = in.read(rc, pos, size-pos);
if( c < 0 ) {
throw new EOFException();
}
this.pos += c;
pos += c;
}
return new Buffer(rc);
}
/**
* Reads and discards {@code size} bytes.
*
* @throws InvalidProtocolBufferException
* The end of the stream or the current limit was reached.
*/
public void skipRawBytes(int size) throws IOException {
int pos = 0;
while (pos < size) {
int n = (int) in.skip(size - pos);
pos += n;
}
}
public int pushLimit(int limit) {
int rc = this.limit;
this.limit = pos+limit;
return rc;
}
public void popLimit(int limit) {
this.limit = limit;
}
}

View File

@ -0,0 +1,481 @@
//Protocol Buffers - Google's data interchange format
//Copyright 2008 Google Inc.
//http://code.google.com/p/protobuf/
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
package org.apache.activemq.protobuf;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Encodes and writes protocol message fields.
*
* <p>
* This class contains two kinds of methods: methods that write specific
* protocol message constructs and field types (e.g. {@link #writeTag} and
* {@link #writeInt32}) and methods that write low-level values (e.g.
* {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are writing
* encoded protocol messages, you should use the former methods, but if you are
* writing some other format of your own design, use the latter.
*
* <p>
* This class is totally unsynchronized.
*
* @author kneton@google.com Kenton Varda
*/
public final class CodedOutputStream extends FilterOutputStream {
private BufferOutputStream bos;
public CodedOutputStream(OutputStream os) {
super(os);
if( os instanceof BufferOutputStream ) {
bos = (BufferOutputStream)os;
}
}
public CodedOutputStream(byte[] data) {
super(new BufferOutputStream(data));
}
public CodedOutputStream(Buffer data) {
super(new BufferOutputStream(data));
}
// -----------------------------------------------------------------
/** Write a {@code double} field, including tag, to the stream. */
public void writeDouble(int fieldNumber, double value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
writeRawLittleEndian64(Double.doubleToRawLongBits(value));
}
/** Write a {@code float} field, including tag, to the stream. */
public void writeFloat(int fieldNumber, float value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
writeRawLittleEndian32(Float.floatToRawIntBits(value));
}
/** Write a {@code uint64} field, including tag, to the stream. */
public void writeUInt64(int fieldNumber, long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeRawVarint64(value);
}
/** Write an {@code int64} field, including tag, to the stream. */
public void writeInt64(int fieldNumber, long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeRawVarint64(value);
}
/** Write an {@code int32} field, including tag, to the stream. */
public void writeInt32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
if (value >= 0) {
writeRawVarint32(value);
} else {
// Must sign-extend.
writeRawVarint64(value);
}
}
/** Write a {@code fixed64} field, including tag, to the stream. */
public void writeFixed64(int fieldNumber, long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
writeRawLittleEndian64(value);
}
/** Write a {@code fixed32} field, including tag, to the stream. */
public void writeFixed32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
writeRawLittleEndian32(value);
}
/** Write a {@code bool} field, including tag, to the stream. */
public void writeBool(int fieldNumber, boolean value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeRawByte(value ? 1 : 0);
}
/** Write a {@code string} field, including tag, to the stream. */
public void writeString(int fieldNumber, String value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
// Unfortunately there does not appear to be any way to tell Java to
// encode
// UTF-8 directly into our buffer, so we have to let it create its own
// byte
// array and then copy.
byte[] bytes = value.getBytes("UTF-8");
writeRawVarint32(bytes.length);
writeRawBytes(bytes);
}
/** Write a {@code bytes} field, including tag, to the stream. */
public void writeBytes(int fieldNumber, Buffer value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeRawVarint32(value.length);
writeRawBytes(value.data, value.offset, value.length);
}
/** Write a {@code uint32} field, including tag, to the stream. */
public void writeUInt32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeRawVarint32(value);
}
/**
* Write an enum field, including tag, to the stream. Caller is responsible
* for converting the enum value to its numeric value.
*/
public void writeEnum(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeRawVarint32(value);
}
/** Write an {@code sfixed32} field, including tag, to the stream. */
public void writeSFixed32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
writeRawLittleEndian32(value);
}
/** Write an {@code sfixed64} field, including tag, to the stream. */
public void writeSFixed64(int fieldNumber, long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
writeRawLittleEndian64(value);
}
/** Write an {@code sint32} field, including tag, to the stream. */
public void writeSInt32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeRawVarint32(encodeZigZag32(value));
}
/** Write an {@code sint64} field, including tag, to the stream. */
public void writeSInt64(int fieldNumber, long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeRawVarint64(encodeZigZag64(value));
}
// =================================================================
/**
* Compute the number of bytes that would be needed to encode a {@code
* double} field, including tag.
*/
public static int computeDoubleSize(int fieldNumber, double value) {
return computeTagSize(fieldNumber) + LITTLE_ENDIAN_64_SIZE;
}
/**
* Compute the number of bytes that would be needed to encode a {@code
* float} field, including tag.
*/
public static int computeFloatSize(int fieldNumber, float value) {
return computeTagSize(fieldNumber) + LITTLE_ENDIAN_32_SIZE;
}
/**
* Compute the number of bytes that would be needed to encode a {@code
* uint64} field, including tag.
*/
public static int computeUInt64Size(int fieldNumber, long value) {
return computeTagSize(fieldNumber) + computeRawVarint64Size(value);
}
/**
* Compute the number of bytes that would be needed to encode an {@code
* int64} field, including tag.
*/
public static int computeInt64Size(int fieldNumber, long value) {
return computeTagSize(fieldNumber) + computeRawVarint64Size(value);
}
/**
* Compute the number of bytes that would be needed to encode an {@code
* int32} field, including tag.
*/
public static int computeInt32Size(int fieldNumber, int value) {
if (value >= 0) {
return computeTagSize(fieldNumber) + computeRawVarint32Size(value);
} else {
// Must sign-extend.
return computeTagSize(fieldNumber) + 10;
}
}
/**
* Compute the number of bytes that would be needed to encode a {@code
* fixed64} field, including tag.
*/
public static int computeFixed64Size(int fieldNumber, long value) {
return computeTagSize(fieldNumber) + LITTLE_ENDIAN_64_SIZE;
}
/**
* Compute the number of bytes that would be needed to encode a {@code
* fixed32} field, including tag.
*/
public static int computeFixed32Size(int fieldNumber, int value) {
return computeTagSize(fieldNumber) + LITTLE_ENDIAN_32_SIZE;
}
/**
* Compute the number of bytes that would be needed to encode a {@code bool}
* field, including tag.
*/
public static int computeBoolSize(int fieldNumber, boolean value) {
return computeTagSize(fieldNumber) + 1;
}
/**
* Compute the number of bytes that would be needed to encode a {@code
* string} field, including tag.
*/
public static int computeStringSize(int fieldNumber, String value) {
try {
byte[] bytes = value.getBytes("UTF-8");
return computeTagSize(fieldNumber) + computeRawVarint32Size(bytes.length) + bytes.length;
} catch (java.io.UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not supported.", e);
}
}
/**
* Compute the number of bytes that would be needed to encode a {@code
* bytes} field, including tag.
*/
public static int computeBytesSize(int fieldNumber, Buffer value) {
return computeTagSize(fieldNumber) + computeRawVarint32Size(value.length) + value.length;
}
/**
* Compute the number of bytes that would be needed to encode a {@code
* uint32} field, including tag.
*/
public static int computeUInt32Size(int fieldNumber, int value) {
return computeTagSize(fieldNumber) + computeRawVarint32Size(value);
}
/**
* Compute the number of bytes that would be needed to encode an enum field,
* including tag. Caller is responsible for converting the enum value to its
* numeric value.
*/
public static int computeEnumSize(int fieldNumber, int value) {
return computeTagSize(fieldNumber) + computeRawVarint32Size(value);
}
/**
* Compute the number of bytes that would be needed to encode an {@code
* sfixed32} field, including tag.
*/
public static int computeSFixed32Size(int fieldNumber, int value) {
return computeTagSize(fieldNumber) + LITTLE_ENDIAN_32_SIZE;
}
/**
* Compute the number of bytes that would be needed to encode an {@code
* sfixed64} field, including tag.
*/
public static int computeSFixed64Size(int fieldNumber, long value) {
return computeTagSize(fieldNumber) + LITTLE_ENDIAN_64_SIZE;
}
/**
* Compute the number of bytes that would be needed to encode an {@code
* sint32} field, including tag.
*/
public static int computeSInt32Size(int fieldNumber, int value) {
return computeTagSize(fieldNumber) + computeRawVarint32Size(encodeZigZag32(value));
}
/**
* Compute the number of bytes that would be needed to encode an {@code
* sint64} field, including tag.
*/
public static int computeSInt64Size(int fieldNumber, long value) {
return computeTagSize(fieldNumber) + computeRawVarint64Size(encodeZigZag64(value));
}
/** Write a single byte. */
public void writeRawByte(byte value) throws IOException {
out.write(value);
}
/** Write a single byte, represented by an integer value. */
public void writeRawByte(int value) throws IOException {
writeRawByte((byte) value);
}
/** Write an array of bytes. */
public void writeRawBytes(byte[] value) throws IOException {
writeRawBytes(value, 0, value.length);
}
/** Write part of an array of bytes. */
public void writeRawBytes(byte[] value, int offset, int length) throws IOException {
out.write(value, offset, length);
}
public void writeRawBytes(Buffer data) throws IOException {
out.write(data.data, data.offset, data.length);
}
/** Encode and write a tag. */
public void writeTag(int fieldNumber, int wireType) throws IOException {
writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType));
}
/** Compute the number of bytes that would be needed to encode a tag. */
public static int computeTagSize(int fieldNumber) {
return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0));
}
/**
* Encode and write a varint. {@code value} is treated as unsigned, so it
* won't be sign-extended if negative.
*/
public void writeRawVarint32(int value) throws IOException {
while (true) {
if ((value & ~0x7F) == 0) {
writeRawByte(value);
return;
} else {
writeRawByte((value & 0x7F) | 0x80);
value >>>= 7;
}
}
}
/**
* Compute the number of bytes that would be needed to encode a varint.
* {@code value} is treated as unsigned, so it won't be sign-extended if
* negative.
*/
public static int computeRawVarint32Size(int value) {
if ((value & (0xffffffff << 7)) == 0)
return 1;
if ((value & (0xffffffff << 14)) == 0)
return 2;
if ((value & (0xffffffff << 21)) == 0)
return 3;
if ((value & (0xffffffff << 28)) == 0)
return 4;
return 5;
}
/** Encode and write a varint. */
public void writeRawVarint64(long value) throws IOException {
while (true) {
if ((value & ~0x7FL) == 0) {
writeRawByte((int) value);
return;
} else {
writeRawByte(((int) value & 0x7F) | 0x80);
value >>>= 7;
}
}
}
/** Compute the number of bytes that would be needed to encode a varint. */
public static int computeRawVarint64Size(long value) {
if ((value & (0xffffffffffffffffL << 7)) == 0)
return 1;
if ((value & (0xffffffffffffffffL << 14)) == 0)
return 2;
if ((value & (0xffffffffffffffffL << 21)) == 0)
return 3;
if ((value & (0xffffffffffffffffL << 28)) == 0)
return 4;
if ((value & (0xffffffffffffffffL << 35)) == 0)
return 5;
if ((value & (0xffffffffffffffffL << 42)) == 0)
return 6;
if ((value & (0xffffffffffffffffL << 49)) == 0)
return 7;
if ((value & (0xffffffffffffffffL << 56)) == 0)
return 8;
if ((value & (0xffffffffffffffffL << 63)) == 0)
return 9;
return 10;
}
/** Write a little-endian 32-bit integer. */
public void writeRawLittleEndian32(int value) throws IOException {
writeRawByte((value) & 0xFF);
writeRawByte((value >> 8) & 0xFF);
writeRawByte((value >> 16) & 0xFF);
writeRawByte((value >> 24) & 0xFF);
}
public static final int LITTLE_ENDIAN_32_SIZE = 4;
/** Write a little-endian 64-bit integer. */
public void writeRawLittleEndian64(long value) throws IOException {
writeRawByte((int) (value) & 0xFF);
writeRawByte((int) (value >> 8) & 0xFF);
writeRawByte((int) (value >> 16) & 0xFF);
writeRawByte((int) (value >> 24) & 0xFF);
writeRawByte((int) (value >> 32) & 0xFF);
writeRawByte((int) (value >> 40) & 0xFF);
writeRawByte((int) (value >> 48) & 0xFF);
writeRawByte((int) (value >> 56) & 0xFF);
}
public static final int LITTLE_ENDIAN_64_SIZE = 8;
/**
* Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers into
* values that can be efficiently encoded with varint. (Otherwise, negative
* values must be sign-extended to 64 bits to be varint encoded, thus always
* taking 10 bytes on the wire.)
*
* @param n
* A signed 32-bit integer.
* @return An unsigned 32-bit integer, stored in a signed int because Java
* has no explicit unsigned support.
*/
public static int encodeZigZag32(int n) {
// Note: the right-shift must be arithmetic
return (n << 1) ^ (n >> 31);
}
/**
* Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers into
* values that can be efficiently encoded with varint. (Otherwise, negative
* values must be sign-extended to 64 bits to be varint encoded, thus always
* taking 10 bytes on the wire.)
*
* @param n
* A signed 64-bit integer.
* @return An unsigned 64-bit integer, stored in a signed int because Java
* has no explicit unsigned support.
*/
public static long encodeZigZag64(long n) {
// Note: the right-shift must be arithmetic
return (n << 1) ^ (n >> 63);
}
public void checkNoSpaceLeft() {
}
public Buffer getNextBuffer(int size) throws IOException {
if( bos==null ) {
return null;
}
return bos.getNextBuffer(size);
}
}

View File

@ -0,0 +1,90 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
import java.io.IOException;
abstract public class DeferredDecodeMessage<T> extends BaseMessage<T> {
protected Buffer encodedForm;
protected boolean decoded = true;
@Override
public T mergeFramed(CodedInputStream input) throws IOException {
int length = input.readRawVarint32();
int oldLimit = input.pushLimit(length);
T rc = mergeUnframed(input.readRawBytes(length));
input.popLimit(oldLimit);
return rc;
}
@SuppressWarnings("unchecked")
@Override
public T mergeUnframed(Buffer data) throws InvalidProtocolBufferException {
encodedForm = data;
decoded = false;
return (T) this;
}
@Override
public Buffer toUnframedBuffer() {
if (encodedForm == null) {
encodedForm = super.toUnframedBuffer();
}
return encodedForm;
}
protected void load() {
if (!decoded) {
decoded = true;
try {
Buffer originalForm = encodedForm;
encodedForm=null;
CodedInputStream input = new CodedInputStream(originalForm);
mergeUnframed(input);
input.checkLastTagWas(0);
// We need to reset the encoded form because the mergeUnframed
// from a stream clears it out.
encodedForm = originalForm;
checktInitialized();
} catch (Throwable e) {
throw new RuntimeException("Deferred message decoding failed: " + e.getMessage(), e);
}
}
}
protected void loadAndClear() {
super.loadAndClear();
load();
encodedForm = null;
}
public void clear() {
super.clear();
encodedForm = null;
decoded = true;
}
public boolean isDecoded() {
return decoded;
}
public boolean isEncoded() {
return encodedForm != null;
}
}

View File

@ -0,0 +1,66 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.apache.activemq.protobuf;
import java.io.IOException;
/**
* Thrown when a protocol message being parsed is invalid in some way, e.g. it
* contains a malformed varint or a negative byte length.
*
* @author kenton@google.com Kenton Varda
*/
public class InvalidProtocolBufferException extends IOException {
private static final long serialVersionUID = 5685337441004132240L;
public InvalidProtocolBufferException(String description) {
super(description);
}
static InvalidProtocolBufferException truncatedMessage() {
return new InvalidProtocolBufferException("While parsing a protocol message, the input ended unexpectedly " + "in the middle of a field. This could mean either than the " + "input has been truncated or that an embedded message "
+ "misreported its own length.");
}
static InvalidProtocolBufferException negativeSize() {
return new InvalidProtocolBufferException("CodedInputStream encountered an embedded string or message " + "which claimed to have negative size.");
}
static InvalidProtocolBufferException malformedVarint() {
return new InvalidProtocolBufferException("CodedInputStream encountered a malformed varint.");
}
static InvalidProtocolBufferException invalidTag() {
return new InvalidProtocolBufferException("Protocol message contained an invalid tag (zero).");
}
static InvalidProtocolBufferException invalidEndTag() {
return new InvalidProtocolBufferException("Protocol message end-group tag did not match expected tag.");
}
static InvalidProtocolBufferException invalidWireType() {
return new InvalidProtocolBufferException("Protocol message tag had invalid wire type.");
}
static InvalidProtocolBufferException recursionLimitExceeded() {
return new InvalidProtocolBufferException("Protocol message had too many levels of nesting. May be malicious. " + "Use CodedInputStream.setRecursionLimit() to increase the depth limit.");
}
static InvalidProtocolBufferException sizeLimitExceeded() {
return new InvalidProtocolBufferException("Protocol message was too large. May be malicious. " + "Use CodedInputStream.setSizeLimit() to increase the size limit.");
}
}

View File

@ -0,0 +1,72 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public interface Message<T> {
public T clone() throws CloneNotSupportedException;
public int serializedSizeUnframed();
public int serializedSizeFramed();
public void clear();
public T assertInitialized() throws UninitializedMessageException;
public T mergeFrom(T other);
public T mergeUnframed(byte[] data) throws InvalidProtocolBufferException;
public T mergeFramed(byte[] data) throws InvalidProtocolBufferException;
public T mergeUnframed(Buffer buffer) throws InvalidProtocolBufferException;
public T mergeFramed(Buffer buffer) throws InvalidProtocolBufferException;
public T mergeUnframed(InputStream input) throws IOException;
public T mergeFramed(InputStream input) throws IOException;
public T mergeUnframed(CodedInputStream input) throws IOException;
public T mergeFramed(CodedInputStream input) throws IOException;
public Buffer toUnframedBuffer();
public Buffer toFramedBuffer();
public byte[] toUnframedByteArray();
public byte[] toFramedByteArray();
public void writeUnframed(CodedOutputStream output) throws java.io.IOException;
public void writeFramed(CodedOutputStream output) throws java.io.IOException;
public void writeUnframed(OutputStream output) throws IOException;
public void writeFramed(OutputStream output) throws java.io.IOException;
}

View File

@ -0,0 +1,44 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
import java.io.IOException;
import java.io.OutputStream;
public interface MessageBuffer<B, MB extends MessageBuffer> extends PBMessage<B, MB> {
public int serializedSizeUnframed();
public int serializedSizeFramed();
public Buffer toUnframedBuffer();
public Buffer toFramedBuffer();
public byte[] toUnframedByteArray();
public byte[] toFramedByteArray();
public void writeUnframed(CodedOutputStream output) throws java.io.IOException;
public void writeFramed(CodedOutputStream output) throws java.io.IOException;
public void writeUnframed(OutputStream output) throws IOException;
public void writeFramed(OutputStream output) throws java.io.IOException;
}

View File

@ -0,0 +1,140 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
import static org.apache.activemq.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
final public class MessageBufferSupport {
public static final String FORZEN_ERROR_MESSAGE = "Modification not allowed after object has been fozen. Try modifying a copy of this object.";
static public Buffer toUnframedBuffer(MessageBuffer message) {
try {
int size = message.serializedSizeUnframed();
BufferOutputStream baos = new BufferOutputStream(size);
CodedOutputStream output = new CodedOutputStream(baos);
message.writeUnframed(output);
Buffer rc = baos.toBuffer();
assert rc.length == size : "Did not write as much data as expected.";
return rc;
} catch (IOException e) {
throw new RuntimeException("Serializing to a byte array threw an IOException " + "(should never happen).", e);
}
}
static public Buffer toFramedBuffer(MessageBuffer message) {
try {
int size = message.serializedSizeFramed();
BufferOutputStream baos = new BufferOutputStream(size);
CodedOutputStream output = new CodedOutputStream(baos);
message.writeFramed(output);
Buffer rc = baos.toBuffer();
assert rc.length==size : "Did not write as much data as expected.";
return rc;
} catch (IOException e) {
throw new RuntimeException("Serializing to a byte array threw an IOException " + "(should never happen).", e);
}
}
public static void writeMessage(CodedOutputStream output, int tag, MessageBuffer message) throws IOException {
output.writeTag(tag, WIRETYPE_LENGTH_DELIMITED);
message.writeFramed(output);
}
public static int computeMessageSize(int tag, MessageBuffer message) {
return CodedOutputStream.computeTagSize(tag) + message.serializedSizeFramed();
}
public static Buffer readFrame(java.io.InputStream input) throws IOException {
int length = readRawVarint32(input);
byte[] data = new byte[length];
int pos = 0;
while (pos < length) {
int r = input.read(data, pos, length - pos);
if (r < 0) {
throw new InvalidProtocolBufferException("Input stream ended before a full message frame could be read.");
}
pos += r;
}
return new Buffer(data);
}
/**
* Read a raw Varint from the stream. If larger than 32 bits, discard the
* upper bits.
*/
static public int readRawVarint32(InputStream is) throws IOException {
byte tmp = readRawByte(is);
if (tmp >= 0) {
return tmp;
}
int result = tmp & 0x7f;
if ((tmp = readRawByte(is)) >= 0) {
result |= tmp << 7;
} else {
result |= (tmp & 0x7f) << 7;
if ((tmp = readRawByte(is)) >= 0) {
result |= tmp << 14;
} else {
result |= (tmp & 0x7f) << 14;
if ((tmp = readRawByte(is)) >= 0) {
result |= tmp << 21;
} else {
result |= (tmp & 0x7f) << 21;
result |= (tmp = readRawByte(is)) << 28;
if (tmp < 0) {
// Discard upper 32 bits.
for (int i = 0; i < 5; i++) {
if (readRawByte(is) >= 0)
return result;
}
throw new InvalidProtocolBufferException("CodedInputStream encountered a malformed varint.");
}
}
}
}
return result;
}
static public byte readRawByte(InputStream is) throws IOException {
int rc = is.read();
if (rc == -1) {
throw new InvalidProtocolBufferException("While parsing a protocol message, the input ended unexpectedly " + "in the middle of a field. This could mean either than the " + "input has been truncated or that an embedded message "
+ "misreported its own length.");
}
return (byte) rc;
}
static public <T> void addAll(Iterable<T> values, Collection<? super T> list) {
if (values instanceof Collection) {
@SuppressWarnings("unsafe")
Collection<T> collection = (Collection<T>) values;
list.addAll(collection);
} else {
for (T value : values) {
list.add(value);
}
}
}
}

View File

@ -0,0 +1,23 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
public interface PBMessage <Bean, Buffer extends MessageBuffer>{
public Bean copy();
public boolean frozen();
public Buffer freeze();
}

View File

@ -0,0 +1,101 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf;
import java.io.UnsupportedEncodingException;
final public class UTF8Buffer extends Buffer {
int hashCode;
String value;
public UTF8Buffer(Buffer other) {
super(other);
}
public UTF8Buffer(byte[] data, int offset, int length) {
super(data, offset, length);
}
public UTF8Buffer(byte[] data) {
super(data);
}
public UTF8Buffer(String input) {
super(encode(input));
}
public UTF8Buffer compact() {
if (length != data.length) {
return new UTF8Buffer(toByteArray());
}
return this;
}
public String toString()
{
if( value==null ) {
value = decode(this);
}
return value;
}
@Override
public int compareTo(Buffer other) {
// Do a char comparison.. not a byte for byte comparison.
return toString().compareTo(other.toString());
}
@Override
public boolean equals(Object obj) {
if( obj==this )
return true;
if( obj==null || obj.getClass()!=UTF8Buffer.class )
return false;
return equals((Buffer)obj);
}
@Override
public int hashCode() {
if( hashCode==0 ) {
hashCode = super.hashCode();;
}
return hashCode;
}
static public byte[] encode(String value)
{
try {
return value.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("A UnsupportedEncodingException was thrown for teh UTF-8 encoding. (This should never happen)");
}
}
static public String decode(Buffer buffer)
{
try {
return new String(buffer.getData(), buffer.getOffset(), buffer.getLength(), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("A UnsupportedEncodingException was thrown for teh UTF-8 encoding. (This should never happen)");
}
}
}

View File

@ -0,0 +1,76 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.apache.activemq.protobuf;
import java.util.Collections;
import java.util.List;
/**
* Thrown when attempting to build a protocol message that is missing required
* fields. This is a {@code RuntimeException} because it normally represents a
* programming error: it happens when some code which constructs a message fails
* to set all the fields. {@code parseFrom()} methods <b>do not</b> throw this;
* they throw an {@link InvalidProtocolBufferException} if required fields are
* missing, because it is not a programming error to receive an incomplete
* message. In other words, {@code UninitializedMessageException} should never
* be thrown by correct code, but {@code InvalidProtocolBufferException} might
* be.
*
* @author kenton@google.com Kenton Varda
*/
public class UninitializedMessageException extends RuntimeException {
public UninitializedMessageException(List<String> missingFields) {
super(buildDescription(missingFields));
this.missingFields = missingFields;
}
private final List<String> missingFields;
/**
* Get a list of human-readable names of required fields missing from this
* message. Each name is a full path to a field, e.g. "foo.bar[5].baz".
*/
public List<String> getMissingFields() {
return Collections.unmodifiableList(missingFields);
}
/**
* Converts this exception to an {@link InvalidProtocolBufferException}.
* When a parsed message is missing required fields, this should be thrown
* instead of {@code UninitializedMessageException}.
*/
public InvalidProtocolBufferException asInvalidProtocolBufferException() {
return new InvalidProtocolBufferException(getMessage());
}
/** Construct the description string for this exception. */
private static String buildDescription(List<String> missingFields) {
StringBuilder description = new StringBuilder("Message missing required fields: ");
boolean first = true;
for (String field : missingFields) {
if (first) {
first = false;
} else {
description.append(", ");
}
description.append(field);
}
return description.toString();
}
}

View File

@ -0,0 +1,70 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.apache.activemq.protobuf;
/**
* This class is used internally by the Protocol Buffer library and generated
* message implementations. It is public only because those generated messages
* do not reside in the {@code protocol2} package. Others should not use this
* class directly.
*
* This class contains constants and helper functions useful for dealing with
* the Protocol Buffer wire format.
*
* @author kenton@google.com Kenton Varda
*/
public final class WireFormat {
// Do not allow instantiation.
private WireFormat() {
}
public static final int WIRETYPE_VARINT = 0;
public static final int WIRETYPE_FIXED64 = 1;
public static final int WIRETYPE_LENGTH_DELIMITED = 2;
public static final int WIRETYPE_START_GROUP = 3;
public static final int WIRETYPE_END_GROUP = 4;
public static final int WIRETYPE_FIXED32 = 5;
public static final int TAG_TYPE_BITS = 3;
public static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
/** Given a tag value, determines the wire type (the lower 3 bits). */
public static int getTagWireType(int tag) {
return tag & TAG_TYPE_MASK;
}
/** Given a tag value, determines the field number (the upper 29 bits). */
public static int getTagFieldNumber(int tag) {
return tag >>> TAG_TYPE_BITS;
}
/** Makes a tag value given a field number and wire type. */
public static int makeTag(int fieldNumber, int wireType) {
return (fieldNumber << TAG_TYPE_BITS) | wireType;
}
// Field numbers for feilds in MessageSet wire format.
public static final int MESSAGE_SET_ITEM = 1;
public static final int MESSAGE_SET_TYPE_ID = 2;
public static final int MESSAGE_SET_MESSAGE = 3;
// Tag numbers.
public static final int MESSAGE_SET_ITEM_TAG = makeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP);
public static final int MESSAGE_SET_ITEM_END_TAG = makeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP);
public static final int MESSAGE_SET_TYPE_ID_TAG = makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT);
public static final int MESSAGE_SET_MESSAGE_TAG = makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED);
}

View File

@ -0,0 +1,115 @@
/**
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
import java.util.ArrayList;
/**
* Support utility that can be used to set the properties on any object
* using command line arguments.
*
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
*/
public class CommandLineSupport {
/**
* Sets the properties of an object given the command line args.
*
* if args contains: --ack-mode=AUTO --url=tcp://localhost:61616 --persistent
*
* then it will try to call the following setters on the target object.
*
* target.setAckMode("AUTO");
* target.setURL(new URI("tcp://localhost:61616") );
* target.setPersistent(true);
*
* Notice the the proper conversion for the argument is determined by examining the
* setter argument type.
*
* @param target the object that will have it's properties set
* @param args the command line options
* @return any arguments that are not valid options for the target
*/
static public String[] setOptions(Object target, String []args) {
ArrayList rc = new ArrayList();
for (int i = 0; i < args.length; i++) {
if( args[i] == null )
continue;
if( args[i].startsWith("--") ) {
// --options without a specified value are considered boolean flags that are enabled.
String value="true";
String name = args[i].substring(2);
// if --option=value case
int p = name.indexOf("=");
if( p > 0 ) {
value = name.substring(p+1);
name = name.substring(0,p);
}
// name not set, then it's an unrecognized option
if( name.length()==0 ) {
rc.add(args[i]);
continue;
}
String propName = convertOptionToPropertyName(name);
if( !IntrospectionSupport.setProperty(target, propName, value) ) {
rc.add(args[i]);
continue;
}
} else {
rc.add(args[i]);
}
}
String r[] = new String[rc.size()];
rc.toArray(r);
return r;
}
/**
* converts strings like: test-enabled to testEnabled
* @param name
* @return
*/
private static String convertOptionToPropertyName(String name) {
String rc="";
// Look for '-' and strip and then convert the subsequent char to uppercase
int p = name.indexOf("-");
while( p > 0 ) {
// strip
rc += name.substring(0, p);
name = name.substring(p+1);
// can I convert the next char to upper?
if( name.length() >0 ) {
rc += name.substring(0,1).toUpperCase();
name = name.substring(1);
}
p = name.indexOf("-");
}
return rc+name;
}
}

View File

@ -0,0 +1,31 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
import java.util.List;
public class CompilerException extends Exception {
private final List<String> errors;
public CompilerException(List<String> errors) {
this.errors = errors;
}
public List<String> getErrors() {
return errors;
}
}

View File

@ -0,0 +1,136 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class EnumDescriptor implements TypeDescriptor {
private String name;
private Map<String,EnumFieldDescriptor> fields= new LinkedHashMap<String, EnumFieldDescriptor>();
private final ProtoDescriptor protoDescriptor;
private final MessageDescriptor parent;
private Map<String, OptionDescriptor> options = new LinkedHashMap<String, OptionDescriptor>();
public EnumDescriptor(ProtoDescriptor protoDescriptor, MessageDescriptor parent) {
this.protoDescriptor = protoDescriptor;
this.parent = parent;
}
public String getName() {
return name;
}
public Map<String,EnumFieldDescriptor> getFields() {
return fields;
}
public void setName(String name) {
this.name = name;
}
public void setFields(Map<String,EnumFieldDescriptor> fields) {
this.fields = fields;
}
public ProtoDescriptor getProtoDescriptor() {
return protoDescriptor;
}
private String getOption(Map<String, OptionDescriptor> options, String optionName, String defaultValue) {
OptionDescriptor optionDescriptor = options.get(optionName);
if (optionDescriptor == null) {
return defaultValue;
}
return optionDescriptor.getValue();
}
private String constantToUCamelCase(String name) {
boolean upNext=true;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if( Character.isJavaIdentifierPart(c) && Character.isLetterOrDigit(c)) {
if( upNext ) {
c = Character.toUpperCase(c);
upNext=false;
} else {
c = Character.toLowerCase(c);
}
sb.append(c);
} else {
upNext=true;
}
}
return sb.toString();
}
public void validate(List<String> errors) {
String createMessage = getOption(getOptions(), "java_create_message", null);
if( "true".equals(createMessage) ) {
for (EnumFieldDescriptor field : getFields().values()) {
String type = constantToUCamelCase(field.getName());
TypeDescriptor typeDescriptor=null;
// Find the type def for that guy..
if( parent!=null ) {
typeDescriptor = parent.getType(type);
}
if( typeDescriptor == null ) {
typeDescriptor = protoDescriptor.getType(type);
}
if( typeDescriptor == null ) {
errors.add("ENUM constant '"+field.getName()+"' did not find expected associated message: "+type);
} else {
field.associate(typeDescriptor);
typeDescriptor.associate(field);
}
}
}
}
public MessageDescriptor getParent() {
return parent;
}
public String getQName() {
if( parent==null ) {
return name;
} else {
return parent.getQName()+"."+name;
}
}
public boolean isEnum() {
return true;
}
public Map<String, OptionDescriptor> getOptions() {
return options;
}
public void setOptions(Map<String, OptionDescriptor> options) {
this.options = options;
}
public void associate(EnumFieldDescriptor desc) {
throw new RuntimeException("not supported.");
}
}

View File

@ -0,0 +1,58 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
public class EnumFieldDescriptor {
private String name;
private int value;
private final EnumDescriptor parent;
private TypeDescriptor associatedType;
public EnumFieldDescriptor(EnumDescriptor parent) {
this.parent = parent;
}
public void setName(String name) {
this.name = name;
}
public void setValue(int value) {
this.value = value;
}
public String getName() {
return name;
}
public int getValue() {
return value;
}
public EnumDescriptor getParent() {
return parent;
}
public TypeDescriptor getAssociatedType() {
return associatedType;
}
public void associate(TypeDescriptor associatedType) {
this.associatedType = associatedType;
}
}

View File

@ -0,0 +1,50 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
public class ExtensionsDescriptor {
private int first;
private int last;
private final MessageDescriptor parent;
public ExtensionsDescriptor(MessageDescriptor parent) {
this.parent = parent;
}
public void setFirst(int first) {
this.first = first;
}
public void setLast(int last) {
this.last = last;
}
public int getFirst() {
return first;
}
public int getLast() {
return last;
}
public MessageDescriptor getParent() {
return parent;
}
}

View File

@ -0,0 +1,207 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class FieldDescriptor {
public static final String STRING_TYPE = "string".intern();
public static final String BOOL_TYPE = "bool".intern();
public static final String BYTES_TYPE = "bytes".intern();
public static final String DOUBLE_TYPE = "double".intern();
public static final String FLOAT_TYPE = "float".intern();
public static final String INT32_TYPE = "int32".intern();
public static final String INT64_TYPE = "int64".intern();
public static final String UINT32_TYPE = "uint32".intern();
public static final String UINT64_TYPE = "uint64".intern();
public static final String SINT32_TYPE = "sint32".intern();
public static final String SINT64_TYPE = "sint64".intern();
public static final String FIXED32_TYPE = "fixed32".intern();
public static final String FIXED64_TYPE = "fixed64".intern();
public static final String SFIXED32_TYPE = "sfixed32".intern();
public static final String SFIXED64_TYPE = "sfixed64".intern();
public static final String REQUIRED_RULE = "required".intern();
public static final String OPTIONAL_RULE= "optional".intern();
public static final String REPEATED_RULE = "repeated".intern();
public static final Set<String> INT32_TYPES = new HashSet<String>();
public static final Set<String> INT64_TYPES = new HashSet<String>();
public static final Set<String> INTEGER_TYPES = new HashSet<String>();
public static final Set<String> NUMBER_TYPES = new HashSet<String>();
public static final Set<String> SCALAR_TYPES = new HashSet<String>();
public static final Set<String> SIGNED_TYPES = new HashSet<String>();
public static final Set<String> UNSIGNED_TYPES = new HashSet<String>();
static {
INT32_TYPES.add(INT32_TYPE);
INT32_TYPES.add(UINT32_TYPE);
INT32_TYPES.add(SINT32_TYPE);
INT32_TYPES.add(FIXED32_TYPE);
INT32_TYPES.add(SFIXED32_TYPE);
INT64_TYPES.add(INT64_TYPE);
INT64_TYPES.add(UINT64_TYPE);
INT64_TYPES.add(SINT64_TYPE);
INT64_TYPES.add(FIXED64_TYPE);
INT64_TYPES.add(SFIXED64_TYPE);
INTEGER_TYPES.addAll(INT32_TYPES);
INTEGER_TYPES.addAll(INT64_TYPES);
NUMBER_TYPES.addAll(INTEGER_TYPES);
NUMBER_TYPES.add(DOUBLE_TYPE);
NUMBER_TYPES.add(FLOAT_TYPE);
SCALAR_TYPES.addAll(NUMBER_TYPES);
SCALAR_TYPES.add(STRING_TYPE);
SCALAR_TYPES.add(BOOL_TYPE);
SCALAR_TYPES.add(BYTES_TYPE);
}
private String name;
private String type;
private String rule;
private int tag;
private Map<String,OptionDescriptor> options;
private TypeDescriptor typeDescriptor;
private final MessageDescriptor parent;
private MessageDescriptor group;
public FieldDescriptor(MessageDescriptor parent) {
this.parent = parent;
}
public void validate(List<String> errors) {
if( group!=null ) {
typeDescriptor=group;
}
if( !SCALAR_TYPES.contains(type) ) {
// Find the type def for that guy..
if( typeDescriptor==null ) {
typeDescriptor = parent.getType(type);
}
if( typeDescriptor == null ) {
typeDescriptor = parent.getProtoDescriptor().getType(type);
}
if( typeDescriptor == null ) {
errors.add("Field type not found: "+type);
}
}
}
public boolean isGroup() {
return group!=null;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRule() {
return rule;
}
public void setRule(String rule) {
this.rule = rule.intern();
}
public boolean isOptional() {
return this.rule == OPTIONAL_RULE;
}
public boolean isRequired() {
return this.rule == REQUIRED_RULE;
}
public boolean isRepeated() {
return this.rule == REPEATED_RULE;
}
public int getTag() {
return tag;
}
public void setTag(int tag) {
this.tag = tag;
}
public Map<String,OptionDescriptor> getOptions() {
return options;
}
public void setOptions(Map<String,OptionDescriptor> options) {
this.options = options;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type.intern();
}
public boolean isMessageType() {
return !SCALAR_TYPES.contains(type);
}
public boolean isScalarType() {
return SCALAR_TYPES.contains(type);
}
public boolean isNumberType() {
return NUMBER_TYPES.contains(type);
}
public boolean isIntegerType() {
return INTEGER_TYPES.contains(type);
}
public boolean isInteger32Type() {
return INT32_TYPES.contains(type);
}
public boolean isInteger64Type() {
return INT64_TYPES.contains(type);
}
public boolean isStringType() {
return type==STRING_TYPE;
}
public TypeDescriptor getTypeDescriptor() {
return typeDescriptor;
}
public void setTypeDescriptor(TypeDescriptor typeDescriptor) {
this.typeDescriptor = typeDescriptor;
}
public MessageDescriptor getGroup() {
return group;
}
public void setGroup(MessageDescriptor group) {
this.group = group;
}
}

View File

@ -0,0 +1,324 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Map.Entry;
/**
* Support class used to do introspection/reflection based setting and getting of properties on a Java Bean.
*
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
*/
public final class IntrospectionSupport {
private IntrospectionSupport() {
}
public static boolean getProperties(Object target, Map props, String optionPrefix) {
boolean rc = false;
if (target == null) {
throw new IllegalArgumentException("target was null.");
}
if (props == null) {
throw new IllegalArgumentException("props was null.");
}
if (optionPrefix == null) {
optionPrefix = "";
}
Class clazz = target.getClass();
Method[] methods = clazz.getMethods();
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
String name = method.getName();
Class type = method.getReturnType();
Class params[] = method.getParameterTypes();
if (name.startsWith("get") && params.length == 0 && type != null && isSettableType(type)) {
try {
Object value = method.invoke(target, new Object[] {});
if (value == null) {
continue;
}
String strValue = convertToString(value, type);
if (strValue == null) {
continue;
}
name = name.substring(3, 4).toLowerCase() + name.substring(4);
props.put(optionPrefix + name, strValue);
rc = true;
} catch (Throwable ignore) {
}
}
}
return rc;
}
public static boolean setProperties(Object target, Map<String, ?> props, String optionPrefix) {
boolean rc = false;
if (target == null) {
throw new IllegalArgumentException("target was null.");
}
if (props == null) {
throw new IllegalArgumentException("props was null.");
}
for (Iterator<String> iter = props.keySet().iterator(); iter.hasNext();) {
String name = iter.next();
if (name.startsWith(optionPrefix)) {
Object value = props.get(name);
name = name.substring(optionPrefix.length());
if (setProperty(target, name, value)) {
iter.remove();
rc = true;
}
}
}
return rc;
}
public static Map<String, Object> extractProperties(Map props, String optionPrefix) {
if (props == null) {
throw new IllegalArgumentException("props was null.");
}
HashMap<String, Object> rc = new HashMap<String, Object>(props.size());
for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
String name = (String)iter.next();
if (name.startsWith(optionPrefix)) {
Object value = props.get(name);
name = name.substring(optionPrefix.length());
rc.put(name, value);
iter.remove();
}
}
return rc;
}
public static boolean setProperties(Object target, Map props) {
boolean rc = false;
if (target == null) {
throw new IllegalArgumentException("target was null.");
}
if (props == null) {
throw new IllegalArgumentException("props was null.");
}
for (Iterator iter = props.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Entry)iter.next();
if (setProperty(target, (String)entry.getKey(), entry.getValue())) {
iter.remove();
rc = true;
}
}
return rc;
}
public static boolean setProperty(Object target, String name, Object value) {
try {
Class clazz = target.getClass();
Method setter = findSetterMethod(clazz, name);
if (setter == null) {
return false;
}
// If the type is null or it matches the needed type, just use the
// value directly
if (value == null || value.getClass() == setter.getParameterTypes()[0]) {
setter.invoke(target, new Object[] {value});
} else {
// We need to convert it
setter.invoke(target, new Object[] {convert(value, setter.getParameterTypes()[0])});
}
return true;
} catch (Throwable ignore) {
return false;
}
}
private static Object convert(Object value, Class type) throws URISyntaxException {
PropertyEditor editor = PropertyEditorManager.findEditor(type);
if (editor != null) {
editor.setAsText(value.toString());
return editor.getValue();
}
if (type == URI.class) {
return new URI(value.toString());
}
if (type == File.class) {
return new File(value.toString());
}
if (type == File[].class) {
ArrayList<File> files = new ArrayList<File>();
StringTokenizer st = new StringTokenizer(value.toString(), ":");
while(st.hasMoreTokens()) {
String t = st.nextToken();
if( t!=null && t.trim().length()>0 ) {
files.add(new File(t.trim()));
}
}
File rc[] = new File[files.size()];
files.toArray(rc);
return rc;
}
return null;
}
private static String convertToString(Object value, Class type) throws URISyntaxException {
PropertyEditor editor = PropertyEditorManager.findEditor(type);
if (editor != null) {
editor.setValue(value);
return editor.getAsText();
}
if (type == URI.class) {
return ((URI)value).toString();
}
return null;
}
private static Method findSetterMethod(Class clazz, String name) {
// Build the method name.
name = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
Method[] methods = clazz.getMethods();
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
Class params[] = method.getParameterTypes();
if (method.getName().equals(name) && params.length == 1 && isSettableType(params[0])) {
return method;
}
}
return null;
}
private static boolean isSettableType(Class clazz) {
if (PropertyEditorManager.findEditor(clazz) != null) {
return true;
}
if (clazz == URI.class) {
return true;
}
if (clazz == File.class) {
return true;
}
if (clazz == File[].class) {
return true;
}
if (clazz == Boolean.class) {
return true;
}
return false;
}
public static String toString(Object target) {
return toString(target, Object.class);
}
public static String toString(Object target, Class stopClass) {
LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
addFields(target, target.getClass(), stopClass, map);
StringBuffer buffer = new StringBuffer(simpleName(target.getClass()));
buffer.append(" {");
Set entrySet = map.entrySet();
boolean first = true;
for (Iterator iter = entrySet.iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry)iter.next();
if (first) {
first = false;
} else {
buffer.append(", ");
}
buffer.append(entry.getKey());
buffer.append(" = ");
appendToString(buffer, entry.getValue());
}
buffer.append("}");
return buffer.toString();
}
protected static void appendToString(StringBuffer buffer, Object value) {
buffer.append(value);
}
public static String simpleName(Class clazz) {
String name = clazz.getName();
int p = name.lastIndexOf(".");
if (p >= 0) {
name = name.substring(p + 1);
}
return name;
}
private static void addFields(Object target, Class startClass, Class<Object> stopClass, LinkedHashMap<String, Object> map) {
if (startClass != stopClass) {
addFields(target, startClass.getSuperclass(), stopClass, map);
}
Field[] fields = startClass.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers())
|| Modifier.isPrivate(field.getModifiers())) {
continue;
}
try {
field.setAccessible(true);
Object o = field.get(target);
if (o != null && o.getClass().isArray()) {
try {
o = Arrays.asList((Object[])o);
} catch (Throwable e) {
}
}
map.put(field.getName(), o);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,194 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class MessageDescriptor implements TypeDescriptor {
private String name;
private ExtensionsDescriptor extensions;
private Map<String,FieldDescriptor> fields = new LinkedHashMap<String, FieldDescriptor>();
private Map<String,MessageDescriptor> messages = new LinkedHashMap<String,MessageDescriptor>();
private Map<String,EnumDescriptor> enums = new LinkedHashMap<String, EnumDescriptor>();
private final ProtoDescriptor protoDescriptor;
private List<MessageDescriptor> extendsList = new ArrayList<MessageDescriptor>();
private Map<String, OptionDescriptor> options = new LinkedHashMap<String, OptionDescriptor>();
private List<EnumFieldDescriptor> associatedEnumFieldDescriptors = new ArrayList<EnumFieldDescriptor>();
private final MessageDescriptor parent;
private MessageDescriptor baseType;
public MessageDescriptor(ProtoDescriptor protoDescriptor, MessageDescriptor parent) {
this.protoDescriptor = protoDescriptor;
this.parent = parent;
}
public void validate(List<String> errors) {
String baseName = getOption(getOptions(), "base_type", null);
if( baseName!=null ) {
if( baseType==null ) {
baseType = (MessageDescriptor) getType(baseName);
}
if( baseType == null ) {
baseType = (MessageDescriptor) getProtoDescriptor().getType(baseName);
}
if( baseType == null ) {
errors.add("base_type option not valid, type not found: "+baseName);
}
// Assert that all the fields in the base type are defined in this message defintion too.
HashSet<String> baseFieldNames = new HashSet<String>(baseType.getFields().keySet());
baseFieldNames.removeAll(getFields().keySet());
// Some fields were not defined in the sub class..
if( !baseFieldNames.isEmpty() ) {
for (String fieldName : baseFieldNames) {
errors.add("base_type "+baseName+" field "+fieldName+" not defined in "+getName());
}
}
}
for (FieldDescriptor field : fields.values()) {
field.validate(errors);
}
for (EnumDescriptor o : enums.values()) {
o.validate(errors);
}
for (MessageDescriptor o : messages.values()) {
o.validate(errors);
}
}
public String getOption(Map<String, OptionDescriptor> options, String optionName, String defaultValue) {
OptionDescriptor optionDescriptor = options.get(optionName);
if (optionDescriptor == null) {
return defaultValue;
}
return optionDescriptor.getValue();
}
public void setName(String name) {
this.name = name;
}
public void setExtensions(ExtensionsDescriptor extensions) {
this.extensions = extensions;
}
public void setExtends(List<MessageDescriptor> extendsList) {
this.extendsList = extendsList;
}
public List<MessageDescriptor> getExtends() {
return extendsList;
}
public void setFields(Map<String,FieldDescriptor> fields) {
this.fields = fields;
}
public void setMessages(Map<String,MessageDescriptor> messages) {
this.messages = messages;
}
public void setEnums(Map<String,EnumDescriptor> enums) {
this.enums = enums;
}
public String getName() {
return name;
}
public String getQName() {
if( parent==null ) {
return name;
} else {
return parent.getQName()+"."+name;
}
}
public ExtensionsDescriptor getExtensions() {
return extensions;
}
public Map<String,FieldDescriptor> getFields() {
return fields;
}
public Map<String,MessageDescriptor> getMessages() {
return messages;
}
public Map<String,EnumDescriptor> getEnums() {
return enums;
}
public ProtoDescriptor getProtoDescriptor() {
return protoDescriptor;
}
public Map<String, OptionDescriptor> getOptions() {
return options;
}
public void setOptions(Map<String, OptionDescriptor> options) {
this.options = options;
}
public MessageDescriptor getParent() {
return parent;
}
public TypeDescriptor getType(String t) {
for (MessageDescriptor o : messages.values()) {
if( t.equals(o.getName()) ) {
return o;
}
if( t.startsWith(o.getName()+".") ) {
return o.getType( t.substring(o.getName().length()+1) );
}
}
for (EnumDescriptor o : enums.values()) {
if( t.equals(o.getName()) ) {
return o;
}
}
return null;
}
public boolean isEnum() {
return false;
}
public MessageDescriptor getBaseType() {
return baseType;
}
public void associate(EnumFieldDescriptor desc) {
associatedEnumFieldDescriptors.add(desc);
}
public List<EnumFieldDescriptor> getAssociatedEnumFieldDescriptors() {
return associatedEnumFieldDescriptors;
}
}

View File

@ -0,0 +1,58 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
public class MethodDescriptor {
private final ProtoDescriptor protoDescriptor;
private String name;
private String parameter;
private String returns;
public MethodDescriptor(ProtoDescriptor protoDescriptor) {
this.protoDescriptor = protoDescriptor;
}
public void setName(String name) {
this.name = name;
}
public void setParameter(String parameter) {
this.parameter = parameter;
}
public void setReturns(String returns) {
this.returns = returns;
}
public ProtoDescriptor getProtoDescriptor() {
return protoDescriptor;
}
public String getName() {
return name;
}
public String getParameter() {
return parameter;
}
public String getReturns() {
return returns;
}
}

View File

@ -0,0 +1,50 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
import java.util.List;
public class OptionDescriptor {
private String name;
private String value;
public OptionDescriptor() {
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
public void setName(String name) {
this.name = name;
}
public void setValue(String value) {
this.value = value;
}
public void validate(List<String> errors) {
// TODO Auto-generated method stub
}
}

View File

@ -0,0 +1,83 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
import org.apache.activemq.protobuf.compiler.TextFormat.InvalidEscapeSequence;
import org.apache.activemq.protobuf.compiler.parser.ParseException;
import org.apache.activemq.protobuf.compiler.parser.Token;
public class ParserSupport {
public static String decodeString(Token token) throws ParseException {
// StringBuilder sb = new StringBuilder();
// for (int i = 1; i < value.length() - 1; i++) {
// char c = value.charAt(i);
// if (c == '\'') {
// if( i+1 < (value.length() - 1) ) {
// char e = value.charAt(i+1);
// switch(e) {
// case 'a':
// sb.append((char)0x07);
// break;
// case 'b':
// sb.append("\b");
// break;
// case 'f':
// sb.append("\f");
// break;
// case 'n':
// sb.append("\n");
// break;
// case 'r':
// sb.append("\r");
// break;
// case 't':
// sb.append("\t");
// break;
// case 'v':
// sb.append((char)0x0b);
// break;
// case '\\':
// sb.append("\\");
// break;
// case '\'':
// sb.append("'");
// break;
// case '\"':
// sb.append("\"");
// break;
// default:
// sb.append(e);
// break;
// }
// } else {
// throw new RuntimeException("Invalid string litteral: "+value);
// }
// }
// sb.append(c);
// }
// return sb.toString();
try {
return TextFormat.unescapeText(token.image.substring(1, token.image.length()-1));
} catch (InvalidEscapeSequence e) {
throw new ParseException("Invalid string litteral at line " + token.next.beginLine + ", column " + token.next.beginColumn+": "+e.getMessage());
}
}
}

View File

@ -0,0 +1,164 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class ProtoDescriptor {
private String packageName;
private Map<String, OptionDescriptor> options = new LinkedHashMap<String, OptionDescriptor>();
private Map<String, MessageDescriptor> messages = new LinkedHashMap<String, MessageDescriptor>();
private Map<String, EnumDescriptor> enums = new LinkedHashMap<String, EnumDescriptor>();
private List<MessageDescriptor> extendsList = new ArrayList<MessageDescriptor>();
private Map<String, ServiceDescriptor> services = new LinkedHashMap<String, ServiceDescriptor>();
List<String> imports = new ArrayList<String>();
Map<String,ProtoDescriptor> importProtoDescriptors = new LinkedHashMap<String, ProtoDescriptor>();
private String name;
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setOptions(Map<String,OptionDescriptor> options) {
this.options = options;
}
public void setMessages(Map<String,MessageDescriptor> messages) {
this.messages = messages;
}
public void setEnums(Map<String,EnumDescriptor> enums) {
this.enums = enums;
}
public void setExtends(List<MessageDescriptor> extendsList) {
this.extendsList = extendsList;
}
public List<MessageDescriptor> getExtends() {
return extendsList;
}
public String getPackageName() {
return packageName;
}
public Map<String, OptionDescriptor> getOptions() {
return options;
}
public Map<String,MessageDescriptor> getMessages() {
return messages;
}
public Map<String,EnumDescriptor> getEnums() {
return enums;
}
public void setServices(Map<String,ServiceDescriptor> services) {
this.services = services;
}
public Map<String,ServiceDescriptor> getServices() {
return services;
}
/**
* Checks for validation errors in the proto definition and fills them
* into the errors list.
*
* @return
*/
public void validate(List<String> errors) {
for (ProtoDescriptor o : importProtoDescriptors.values()) {
o.validate(errors);
}
for (OptionDescriptor o : options.values()) {
o.validate(errors);
}
for (MessageDescriptor o : messages.values()) {
o.validate(errors);
}
for (EnumDescriptor o : enums.values()) {
o.validate(errors);
}
for (MessageDescriptor o : extendsList) {
o.validate(errors);
}
for (ServiceDescriptor o : services.values()) {
o.validate(errors);
}
}
public List<String> getImports() {
return imports;
}
public void setImports(List<String> imports) {
this.imports = imports;
}
public Map<String, ProtoDescriptor> getImportProtoDescriptors() {
return importProtoDescriptors;
}
public void setImportProtoDescriptors(Map<String, ProtoDescriptor> importProtoDescriptors) {
this.importProtoDescriptors = importProtoDescriptors;
}
public TypeDescriptor getType(String type) {
for (MessageDescriptor o : messages.values()) {
if( type.equals(o.getName()) ) {
return o;
}
if( type.startsWith(o.getName()+".") ) {
return o.getType( type.substring(o.getName().length()+1) );
}
}
for (EnumDescriptor o : enums.values()) {
if( type.equals(o.getName()) ) {
return o;
}
}
// Check to see if the type was qualified with the package name...
for (ProtoDescriptor o : importProtoDescriptors.values()) {
if( o.getPackageName()!=null && type.startsWith(o.getPackageName()+".") ) {
return o.getType( type.substring(o.getPackageName().length()+1) );
}
}
for (ProtoDescriptor o : importProtoDescriptors.values()) {
TypeDescriptor rc = o.getType(type);
if (rc != null) {
return rc;
}
}
return null;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,110 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import org.apache.activemq.protobuf.compiler.parser.ParseException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
/**
* A Maven Mojo so that the Proto compiler can be used with maven.
*
* @goal compile
* @phase process-sources
*/
public class ProtoMojo extends AbstractMojo {
/**
* The maven project.
*
* @parameter expression="${project}"
* @required
* @readonly
*/
protected MavenProject project;
/**
* The directory where the proto files (<code>*.proto</code>) are
* located.
*
* @parameter expression="${sourceDirectory}" default-value="${basedir}/src/main/proto"
*/
private File sourceDirectory;
/**
* The directory where the output files will be located.
*
* @parameter expression="${outputDirectory}" default-value="${project.build.directory}/generated-sources/proto"
*/
private File outputDirectory;
/**
* The type of generator to run.
*
* @parameter default-value="default"
*/
private String type;
public void execute() throws MojoExecutionException {
File[] files = sourceDirectory.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.getName().endsWith(".proto");
}
});
if (files==null || files.length==0) {
getLog().warn("No proto files found in directory: " + sourceDirectory.getPath());
return;
}
List<File> recFiles = Arrays.asList(files);
for (File file : recFiles) {
try {
getLog().info("Compiling: "+file.getPath());
if( "default".equals(type) ) {
JavaGenerator generator = new JavaGenerator();
generator.setOut(outputDirectory);
generator.compile(file);
} else if( "alt".equals(type) ) {
AltJavaGenerator generator = new AltJavaGenerator();
generator.setOut(outputDirectory);
generator.compile(file);
}
} catch (CompilerException e) {
getLog().error("Protocol Buffer Compiler failed with the following error(s):");
for (String error : e.getErrors() ) {
getLog().error("");
getLog().error(error);
}
getLog().error("");
throw new MojoExecutionException("Compile failed. For more details see error messages listed above.", e);
}
}
this.project.addCompileSourceRoot(outputDirectory.getAbsolutePath());
}
}

View File

@ -0,0 +1,55 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
import java.util.ArrayList;
import java.util.List;
public class ServiceDescriptor {
private final ProtoDescriptor protoDescriptor;
private List<MethodDescriptor> methods=new ArrayList<MethodDescriptor>();
private String name;
public ServiceDescriptor(ProtoDescriptor protoDescriptor) {
this.protoDescriptor = protoDescriptor;
}
public void setName(String name) {
this.name = name;
}
public void setMethods(List<MethodDescriptor> methods) {
this.methods = methods;
}
public ProtoDescriptor getProtoDescriptor() {
return protoDescriptor;
}
public List<MethodDescriptor> getMethods() {
return methods;
}
public String getName() {
return name;
}
public void validate(List<String> errors) {
}
}

View File

@ -0,0 +1,767 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.apache.activemq.protobuf.compiler;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.CharBuffer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.activemq.protobuf.Buffer;
import org.apache.activemq.protobuf.UTF8Buffer;
/**
* Provide ascii text parsing and formatting support for proto2 instances.
* The implementation largely follows google/protobuf/text_format.cc.
*
* HRC: I wish the original class was not package protected so we did not need
* to copy this file over. We need to request that the protobuf folks open
* this class up amoung a few others.
*
* @author wenboz@google.com Wenbo Zhu
* @author kenton@google.com Kenton Varda
*/
public final class TextFormat {
/** Convert an unsigned 32-bit integer to a string. */
private static String unsignedToString(int value) {
if (value >= 0) {
return Integer.toString(value);
} else {
return Long.toString(((long) value) & 0x00000000FFFFFFFFL);
}
}
/** Convert an unsigned 64-bit integer to a string. */
private static String unsignedToString(long value) {
if (value >= 0) {
return Long.toString(value);
} else {
// Pull off the most-significant bit so that BigInteger doesn't think
// the number is negative, then set it again using setBit().
return BigInteger.valueOf(value & 0x7FFFFFFFFFFFFFFFL)
.setBit(63).toString();
}
}
// =================================================================
// Parsing
/**
* Represents a stream of tokens parsed from a {@code String}.
*
* <p>The Java standard library provides many classes that you might think
* would be useful for implementing this, but aren't. For example:
*
* <ul>
* <li>{@code java.io.StreamTokenizer}: This almost does what we want -- or,
* at least, something that would get us close to what we want -- except
* for one fatal flaw: It automatically un-escapes strings using Java
* escape sequences, which do not include all the escape sequences we
* need to support (e.g. '\x').
* <li>{@code java.util.Scanner}: This seems like a great way at least to
* parse regular expressions out of a stream (so we wouldn't have to load
* the entire input into a single string before parsing). Sadly,
* {@code Scanner} requires that tokens be delimited with some delimiter.
* Thus, although the text "foo:" should parse to two tokens ("foo" and
* ":"), {@code Scanner} would recognize it only as a single token.
* Furthermore, {@code Scanner} provides no way to inspect the contents
* of delimiters, making it impossible to keep track of line and column
* numbers.
* </ul>
*
* <p>Luckily, Java's regular expression support does manage to be useful to
* us. (Barely: We need {@code Matcher.usePattern()}, which is new in
* Java 1.5.) So, we can use that, at least. Unfortunately, this implies
* that we need to have the entire input in one contiguous string.
*/
private static final class Tokenizer {
private final CharSequence text;
private final Matcher matcher;
private String currentToken;
// The character index within this.text at which the current token begins.
private int pos = 0;
// The line and column numbers of the current token.
private int line = 0;
private int column = 0;
// The line and column numbers of the previous token (allows throwing
// errors *after* consuming).
private int previousLine = 0;
private int previousColumn = 0;
private static Pattern WHITESPACE =
Pattern.compile("(\\s|(#.*$))+", Pattern.MULTILINE);
private static Pattern TOKEN = Pattern.compile(
"[a-zA-Z_][0-9a-zA-Z_+-]*|" + // an identifier
"[0-9+-][0-9a-zA-Z_.+-]*|" + // a number
"\"([^\"\n\\\\]|\\\\.)*(\"|\\\\?$)|" + // a double-quoted string
"\'([^\"\n\\\\]|\\\\.)*(\'|\\\\?$)", // a single-quoted string
Pattern.MULTILINE);
private static Pattern DOUBLE_INFINITY = Pattern.compile(
"-?inf(inity)?",
Pattern.CASE_INSENSITIVE);
private static Pattern FLOAT_INFINITY = Pattern.compile(
"-?inf(inity)?f?",
Pattern.CASE_INSENSITIVE);
private static Pattern FLOAT_NAN = Pattern.compile(
"nanf?",
Pattern.CASE_INSENSITIVE);
/** Construct a tokenizer that parses tokens from the given text. */
public Tokenizer(CharSequence text) {
this.text = text;
this.matcher = WHITESPACE.matcher(text);
skipWhitespace();
nextToken();
}
/** Are we at the end of the input? */
public boolean atEnd() {
return currentToken.length() == 0;
}
/** Advance to the next token. */
public void nextToken() {
previousLine = line;
previousColumn = column;
// Advance the line counter to the current position.
while (pos < matcher.regionStart()) {
if (text.charAt(pos) == '\n') {
++line;
column = 0;
} else {
++column;
}
++pos;
}
// Match the next token.
if (matcher.regionStart() == matcher.regionEnd()) {
// EOF
currentToken = "";
} else {
matcher.usePattern(TOKEN);
if (matcher.lookingAt()) {
currentToken = matcher.group();
matcher.region(matcher.end(), matcher.regionEnd());
} else {
// Take one character.
currentToken = String.valueOf(text.charAt(pos));
matcher.region(pos + 1, matcher.regionEnd());
}
skipWhitespace();
}
}
/**
* Skip over any whitespace so that the matcher region starts at the next
* token.
*/
private void skipWhitespace() {
matcher.usePattern(WHITESPACE);
if (matcher.lookingAt()) {
matcher.region(matcher.end(), matcher.regionEnd());
}
}
/**
* If the next token exactly matches {@code token}, consume it and return
* {@code true}. Otherwise, return {@code false} without doing anything.
*/
public boolean tryConsume(String token) {
if (currentToken.equals(token)) {
nextToken();
return true;
} else {
return false;
}
}
/**
* If the next token exactly matches {@code token}, consume it. Otherwise,
* throw a {@link ParseException}.
*/
public void consume(String token) throws ParseException {
if (!tryConsume(token)) {
throw parseException("Expected \"" + token + "\".");
}
}
/**
* Returns {@code true} if the next token is an integer, but does
* not consume it.
*/
public boolean lookingAtInteger() {
if (currentToken.length() == 0) {
return false;
}
char c = currentToken.charAt(0);
return ('0' <= c && c <= '9') ||
c == '-' || c == '+';
}
/**
* If the next token is an identifier, consume it and return its value.
* Otherwise, throw a {@link ParseException}.
*/
public String consumeIdentifier() throws ParseException {
for (int i = 0; i < currentToken.length(); i++) {
char c = currentToken.charAt(i);
if (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z') ||
('0' <= c && c <= '9') ||
(c == '_') || (c == '.')) {
// OK
} else {
throw parseException("Expected identifier.");
}
}
String result = currentToken;
nextToken();
return result;
}
/**
* If the next token is a 32-bit signed integer, consume it and return its
* value. Otherwise, throw a {@link ParseException}.
*/
public int consumeInt32() throws ParseException {
try {
int result = parseInt32(currentToken);
nextToken();
return result;
} catch (NumberFormatException e) {
throw integerParseException(e);
}
}
/**
* If the next token is a 32-bit unsigned integer, consume it and return its
* value. Otherwise, throw a {@link ParseException}.
*/
public int consumeUInt32() throws ParseException {
try {
int result = parseUInt32(currentToken);
nextToken();
return result;
} catch (NumberFormatException e) {
throw integerParseException(e);
}
}
/**
* If the next token is a 64-bit signed integer, consume it and return its
* value. Otherwise, throw a {@link ParseException}.
*/
public long consumeInt64() throws ParseException {
try {
long result = parseInt64(currentToken);
nextToken();
return result;
} catch (NumberFormatException e) {
throw integerParseException(e);
}
}
/**
* If the next token is a 64-bit unsigned integer, consume it and return its
* value. Otherwise, throw a {@link ParseException}.
*/
public long consumeUInt64() throws ParseException {
try {
long result = parseUInt64(currentToken);
nextToken();
return result;
} catch (NumberFormatException e) {
throw integerParseException(e);
}
}
/**
* If the next token is a double, consume it and return its value.
* Otherwise, throw a {@link ParseException}.
*/
public double consumeDouble() throws ParseException {
// We need to parse infinity and nan separately because
// Double.parseDouble() does not accept "inf", "infinity", or "nan".
if (DOUBLE_INFINITY.matcher(currentToken).matches()) {
boolean negative = currentToken.startsWith("-");
nextToken();
return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
}
if (currentToken.equalsIgnoreCase("nan")) {
nextToken();
return Double.NaN;
}
try {
double result = Double.parseDouble(currentToken);
nextToken();
return result;
} catch (NumberFormatException e) {
throw floatParseException(e);
}
}
/**
* If the next token is a float, consume it and return its value.
* Otherwise, throw a {@link ParseException}.
*/
public float consumeFloat() throws ParseException {
// We need to parse infinity and nan separately because
// Float.parseFloat() does not accept "inf", "infinity", or "nan".
if (FLOAT_INFINITY.matcher(currentToken).matches()) {
boolean negative = currentToken.startsWith("-");
nextToken();
return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
}
if (FLOAT_NAN.matcher(currentToken).matches()) {
nextToken();
return Float.NaN;
}
try {
float result = Float.parseFloat(currentToken);
nextToken();
return result;
} catch (NumberFormatException e) {
throw floatParseException(e);
}
}
/**
* If the next token is a boolean, consume it and return its value.
* Otherwise, throw a {@link ParseException}.
*/
public boolean consumeBoolean() throws ParseException {
if (currentToken.equals("true")) {
nextToken();
return true;
} else if (currentToken.equals("false")) {
nextToken();
return false;
} else {
throw parseException("Expected \"true\" or \"false\".");
}
}
/**
* If the next token is a string, consume it and return its (unescaped)
* value. Otherwise, throw a {@link ParseException}.
*/
public String consumeString() throws ParseException {
return new UTF8Buffer(consumeBuffer()).toString();
}
/**
* If the next token is a string, consume it, unescape it as a
* {@link Buffer}, and return it. Otherwise, throw a
* {@link ParseException}.
*/
public Buffer consumeBuffer() throws ParseException {
char quote = currentToken.length() > 0 ? currentToken.charAt(0) : '\0';
if (quote != '\"' && quote != '\'') {
throw parseException("Expected string.");
}
if (currentToken.length() < 2 ||
currentToken.charAt(currentToken.length() - 1) != quote) {
throw parseException("String missing ending quote.");
}
try {
String escaped = currentToken.substring(1, currentToken.length() - 1);
Buffer result = unescapeBytes(escaped);
nextToken();
return result;
} catch (InvalidEscapeSequence e) {
throw parseException(e.getMessage());
}
}
/**
* Returns a {@link ParseException} with the current line and column
* numbers in the description, suitable for throwing.
*/
public ParseException parseException(String description) {
// Note: People generally prefer one-based line and column numbers.
return new ParseException(
(line + 1) + ":" + (column + 1) + ": " + description);
}
/**
* Returns a {@link ParseException} with the line and column numbers of
* the previous token in the description, suitable for throwing.
*/
public ParseException parseExceptionPreviousToken(String description) {
// Note: People generally prefer one-based line and column numbers.
return new ParseException(
(previousLine + 1) + ":" + (previousColumn + 1) + ": " + description);
}
/**
* Constructs an appropriate {@link ParseException} for the given
* {@code NumberFormatException} when trying to parse an integer.
*/
private ParseException integerParseException(NumberFormatException e) {
return parseException("Couldn't parse integer: " + e.getMessage());
}
/**
* Constructs an appropriate {@link ParseException} for the given
* {@code NumberFormatException} when trying to parse a float or double.
*/
private ParseException floatParseException(NumberFormatException e) {
return parseException("Couldn't parse number: " + e.getMessage());
}
}
/** Thrown when parsing an invalid text format message. */
public static class ParseException extends IOException {
public ParseException(String message) {
super(message);
}
}
private static final int BUFFER_SIZE = 4096;
// TODO(chrisn): See if working around java.io.Reader#read(CharBuffer)
// overhead is worthwhile
private static StringBuilder toStringBuilder(Readable input)
throws IOException {
StringBuilder text = new StringBuilder();
CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE);
while (true) {
int n = input.read(buffer);
if (n == -1) {
break;
}
buffer.flip();
text.append(buffer, 0, n);
}
return text;
}
// =================================================================
// Utility functions
//
// Some of these methods are package-private because Descriptors.java uses
// them.
/**
* Escapes bytes in the format used in protocol buffer text format, which
* is the same as the format used for C string literals. All bytes
* that are not printable 7-bit ASCII characters are escaped, as well as
* backslash, single-quote, and double-quote characters. Characters for
* which no defined short-hand escape sequence is defined will be escaped
* using 3-digit octal sequences.
*/
static String escapeBytes(Buffer input) {
StringBuilder builder = new StringBuilder(input.getLength());
for (int i = 0; i < input.getLength(); i++) {
byte b = input.byteAt(i);
switch (b) {
// Java does not recognize \a or \v, apparently.
case 0x07: builder.append("\\a" ); break;
case '\b': builder.append("\\b" ); break;
case '\f': builder.append("\\f" ); break;
case '\n': builder.append("\\n" ); break;
case '\r': builder.append("\\r" ); break;
case '\t': builder.append("\\t" ); break;
case 0x0b: builder.append("\\v" ); break;
case '\\': builder.append("\\\\"); break;
case '\'': builder.append("\\\'"); break;
case '"' : builder.append("\\\""); break;
default:
if (b >= 0x20) {
builder.append((char) b);
} else {
builder.append('\\');
builder.append((char) ('0' + ((b >>> 6) & 3)));
builder.append((char) ('0' + ((b >>> 3) & 7)));
builder.append((char) ('0' + (b & 7)));
}
break;
}
}
return builder.toString();
}
/**
* Un-escape a byte sequence as escaped using
* {@link #escapeBytes(Buffer)}. Two-digit hex escapes (starting with
* "\x") are also recognized.
*/
static Buffer unescapeBytes(CharSequence input)
throws InvalidEscapeSequence {
byte[] result = new byte[input.length()];
int pos = 0;
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c == '\\') {
if (i + 1 < input.length()) {
++i;
c = input.charAt(i);
if (isOctal(c)) {
// Octal escape.
int code = digitValue(c);
if (i + 1 < input.length() && isOctal(input.charAt(i + 1))) {
++i;
code = code * 8 + digitValue(input.charAt(i));
}
if (i + 1 < input.length() && isOctal(input.charAt(i + 1))) {
++i;
code = code * 8 + digitValue(input.charAt(i));
}
result[pos++] = (byte)code;
} else {
switch (c) {
case 'a' : result[pos++] = 0x07; break;
case 'b' : result[pos++] = '\b'; break;
case 'f' : result[pos++] = '\f'; break;
case 'n' : result[pos++] = '\n'; break;
case 'r' : result[pos++] = '\r'; break;
case 't' : result[pos++] = '\t'; break;
case 'v' : result[pos++] = 0x0b; break;
case '\\': result[pos++] = '\\'; break;
case '\'': result[pos++] = '\''; break;
case '"' : result[pos++] = '\"'; break;
case 'x':
// hex escape
int code = 0;
if (i + 1 < input.length() && isHex(input.charAt(i + 1))) {
++i;
code = digitValue(input.charAt(i));
} else {
throw new InvalidEscapeSequence(
"Invalid escape sequence: '\\x' with no digits");
}
if (i + 1 < input.length() && isHex(input.charAt(i + 1))) {
++i;
code = code * 16 + digitValue(input.charAt(i));
}
result[pos++] = (byte)code;
break;
default:
throw new InvalidEscapeSequence(
"Invalid escape sequence: '\\" + c + "'");
}
}
} else {
throw new InvalidEscapeSequence(
"Invalid escape sequence: '\\' at end of string.");
}
} else {
result[pos++] = (byte)c;
}
}
return new Buffer(result, 0, pos);
}
/**
* Thrown by {@link TextFormat#unescapeBytes} and
* {@link TextFormat#unescapeText} when an invalid escape sequence is seen.
*/
static class InvalidEscapeSequence extends IOException {
public InvalidEscapeSequence(String description) {
super(description);
}
}
/**
* Like {@link #escapeBytes(Buffer)}, but escapes a text string.
* Non-ASCII characters are first encoded as UTF-8, then each byte is escaped
* individually as a 3-digit octal escape. Yes, it's weird.
*/
static String escapeText(String input) {
return escapeBytes(new UTF8Buffer(input));
}
/**
* Un-escape a text string as escaped using {@link #escapeText(String)}.
* Two-digit hex escapes (starting with "\x") are also recognized.
*/
static String unescapeText(String input) throws InvalidEscapeSequence {
return new UTF8Buffer(unescapeBytes(input)).toString();
}
/** Is this an octal digit? */
private static boolean isOctal(char c) {
return '0' <= c && c <= '7';
}
/** Is this a hex digit? */
private static boolean isHex(char c) {
return ('0' <= c && c <= '9') ||
('a' <= c && c <= 'f') ||
('A' <= c && c <= 'F');
}
/**
* Interpret a character as a digit (in any base up to 36) and return the
* numeric value. This is like {@code Character.digit()} but we don't accept
* non-ASCII digits.
*/
private static int digitValue(char c) {
if ('0' <= c && c <= '9') {
return c - '0';
} else if ('a' <= c && c <= 'z') {
return c - 'a' + 10;
} else {
return c - 'A' + 10;
}
}
/**
* Parse a 32-bit signed integer from the text. Unlike the Java standard
* {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
* and "0" to signify hexidecimal and octal numbers, respectively.
*/
static int parseInt32(String text) throws NumberFormatException {
return (int) parseInteger(text, true, false);
}
/**
* Parse a 32-bit unsigned integer from the text. Unlike the Java standard
* {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
* and "0" to signify hexidecimal and octal numbers, respectively. The
* result is coerced to a (signed) {@code int} when returned since Java has
* no unsigned integer type.
*/
static int parseUInt32(String text) throws NumberFormatException {
return (int) parseInteger(text, false, false);
}
/**
* Parse a 64-bit signed integer from the text. Unlike the Java standard
* {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
* and "0" to signify hexidecimal and octal numbers, respectively.
*/
static long parseInt64(String text) throws NumberFormatException {
return parseInteger(text, true, true);
}
/**
* Parse a 64-bit unsigned integer from the text. Unlike the Java standard
* {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
* and "0" to signify hexidecimal and octal numbers, respectively. The
* result is coerced to a (signed) {@code long} when returned since Java has
* no unsigned long type.
*/
static long parseUInt64(String text) throws NumberFormatException {
return parseInteger(text, false, true);
}
private static long parseInteger(String text,
boolean isSigned,
boolean isLong)
throws NumberFormatException {
int pos = 0;
boolean negative = false;
if (text.startsWith("-", pos)) {
if (!isSigned) {
throw new NumberFormatException("Number must be positive: " + text);
}
++pos;
negative = true;
}
int radix = 10;
if (text.startsWith("0x", pos)) {
pos += 2;
radix = 16;
} else if (text.startsWith("0", pos)) {
radix = 8;
}
String numberText = text.substring(pos);
long result = 0;
if (numberText.length() < 16) {
// Can safely assume no overflow.
result = Long.parseLong(numberText, radix);
if (negative) {
result = -result;
}
// Check bounds.
// No need to check for 64-bit numbers since they'd have to be 16 chars
// or longer to overflow.
if (!isLong) {
if (isSigned) {
if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
throw new NumberFormatException(
"Number out of range for 32-bit signed integer: " + text);
}
} else {
if (result >= (1L << 32) || result < 0) {
throw new NumberFormatException(
"Number out of range for 32-bit unsigned integer: " + text);
}
}
}
} else {
BigInteger bigValue = new BigInteger(numberText, radix);
if (negative) {
bigValue = bigValue.negate();
}
// Check bounds.
if (!isLong) {
if (isSigned) {
if (bigValue.bitLength() > 31) {
throw new NumberFormatException(
"Number out of range for 32-bit signed integer: " + text);
}
} else {
if (bigValue.bitLength() > 32) {
throw new NumberFormatException(
"Number out of range for 32-bit unsigned integer: " + text);
}
}
} else {
if (isSigned) {
if (bigValue.bitLength() > 63) {
throw new NumberFormatException(
"Number out of range for 64-bit signed integer: " + text);
}
} else {
if (bigValue.bitLength() > 64) {
throw new NumberFormatException(
"Number out of range for 64-bit unsigned integer: " + text);
}
}
}
result = bigValue.longValue();
}
return result;
}
}

View File

@ -0,0 +1,30 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler;
public interface TypeDescriptor {
public String getName();
public String getQName();
public ProtoDescriptor getProtoDescriptor();
public boolean isEnum();
public void associate(EnumFieldDescriptor desc);
}

View File

@ -0,0 +1,599 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
options {
STATIC=false;
}
PARSER_BEGIN(ProtoParser)
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.protobuf.compiler.parser;
import org.apache.activemq.protobuf.compiler.*;
import java.util.LinkedHashMap;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* This class is generated with JavaCC. Do not modify manually.
*/
public class ProtoParser {
}
PARSER_END(ProtoParser)
SKIP :
{
" "
| "\t"
| "\n"
| "\r"
}
SPECIAL_TOKEN :
{
"//" : COMMENT
}
<COMMENT> SPECIAL_TOKEN :
{
<("\n" | "\r" | "\r\n" | "|")> : DEFAULT
}
<COMMENT> MORE :
{
<~[]>
}
TOKEN :
{
<IMPORT:"import">
| <PACKAGE:"package">
| <SERVICE:"service">
| <RPC:"rpc">
| <OPTION:"option">
| <MESSAGE:"message">
| <EXTENSIONS:"extensions">
| <EXTEND:"extend">
| <ENUM:"enum">
| <GROUP:"group">
| <REQURIED:"required">
| <OPTIONAL:"optional">
| <REPEATED:"repeated">
| <RETURNS:"returns">
| <TO:"to">
| <MAX:"max">
| <LBRACE: "{">
| <RBRACE: "}">
| <EQUALS: "=">
| <SEMICOLON: ";">
| <LBRACKET: "[">
| <RBRACKET: "]">
| <LPAREN: "(">
| <RPAREN: ")">
| <PERIOD: ".">
| <COMMA: ",">
| < INTEGER: ("-")? (
<DECIMAL_LITERAL> (["l","L"])?
| <HEX_LITERAL> (["l","L"])?
| <OCTAL_LITERAL> (["l","L"])?
) >
| < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
| < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
| < #OCTAL_LITERAL: "0" (["0"-"7"])* >
| < FLOAT: ("-")? (
(["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?
| "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?
| (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?
| (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]
)>
| < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
| <STRING:
"\""
( (~["\"","\\","\n","\r"])
| ("\\"
( ["a","v","n","t","b","r","f","\\","'","\""]
| ["x","X"]["0"-"9","A"-"F","a"-"f"]["0"-"9","A"-"F","a"-"f"]
| ["0"-"7"] ( ["0"-"7"] )?
| ["0"-"3"] ["0"-"7"] ["0"-"7"]
)
)
)*
"\"">
| <ID: ["A"-"Z","a"-"z"] (["a"-"z","A"-"Z","0"-"9","_"])*>
}
ProtoDescriptor ProtoDescriptor() :
{
ProtoDescriptor proto = new ProtoDescriptor();
String packageName=null;
LinkedHashMap<String,OptionDescriptor> opts = new LinkedHashMap<String,OptionDescriptor>();
LinkedHashMap<String,MessageDescriptor> messages = new LinkedHashMap<String,MessageDescriptor>();
LinkedHashMap<String,EnumDescriptor> enums = new LinkedHashMap<String,EnumDescriptor>();
ArrayList<MessageDescriptor> extendsList = new ArrayList<MessageDescriptor>();
LinkedHashMap<String,ServiceDescriptor> services = new LinkedHashMap<String,ServiceDescriptor>();
ArrayList<String> imports = new ArrayList<String>();
OptionDescriptor optionD;
MessageDescriptor messageD;
EnumDescriptor enumD;
ServiceDescriptor serviceD;
MessageDescriptor extendD;
String o;
}
{
(
<PACKAGE> packageName=PackageID() <SEMICOLON>
|
<OPTION> optionD = OptionDescriptor() <SEMICOLON>
{ opts.put(optionD.getName(),optionD); }
|
<IMPORT>
o = StringLitteral()
<SEMICOLON>
{ imports.add((String)o); }
|
messageD = MessageDescriptor(proto, null) (<SEMICOLON>)?
{ messages.put(messageD.getName(),messageD); }
|
enumD = EnumDescriptor(proto, null) (<SEMICOLON>)?
{ enums.put(enumD.getName(),enumD); }
|
serviceD = ServiceDescriptor(proto) (<SEMICOLON>)?
{ services.put(serviceD.getName(),serviceD); }
|
extendD = ExtendDescriptor(proto, null) (<SEMICOLON>)?
{ extendsList.add(extendD); }
)+
<EOF>
{
proto.setPackageName(packageName);
proto.setImports(imports);
proto.setOptions(opts);
proto.setMessages(messages);
proto.setEnums(enums);
proto.setServices(services);
proto.setExtends(extendsList);
return proto;
}
}
MessageDescriptor MessageDescriptor(ProtoDescriptor proto, MessageDescriptor parent) :
{
String name;
LinkedHashMap<String,FieldDescriptor> fields = new LinkedHashMap<String,FieldDescriptor>();
LinkedHashMap<String,MessageDescriptor> messages = new LinkedHashMap<String,MessageDescriptor>();
LinkedHashMap<String,EnumDescriptor> enums = new LinkedHashMap<String,EnumDescriptor>();
ArrayList<MessageDescriptor> extendsList = new ArrayList<MessageDescriptor>();
LinkedHashMap<String,OptionDescriptor> opts = new LinkedHashMap<String,OptionDescriptor>();
MessageDescriptor rc = new MessageDescriptor(proto, parent);
OptionDescriptor optionD;
ExtensionsDescriptor extensionsD=null;
FieldDescriptor fieldD;
MessageDescriptor messageD;
EnumDescriptor enumD;
MessageDescriptor extendD;
}
{
<MESSAGE> name = ID() <LBRACE>
(
<OPTION> optionD = OptionDescriptor() <SEMICOLON>
{ opts.put(optionD.getName(),optionD); }
|
fieldD = FieldDescriptor(rc)
{ fields.put(fieldD.getName(), fieldD); }
|
messageD = MessageDescriptor(proto, rc) (<SEMICOLON>)?
{ messages.put(messageD.getName(),messageD); }
|
enumD = EnumDescriptor(proto, rc) (<SEMICOLON>)?
{ enums.put(enumD.getName(), enumD); }
|
extensionsD = ExtensionsDescriptor(rc) <SEMICOLON>
|
extendD = ExtendDescriptor(proto, rc) (<SEMICOLON>)?
{ extendsList.add(extendD); }
)*
<RBRACE>
{
rc.setName(name);
rc.setFields(fields);
rc.setMessages(messages);
rc.setEnums(enums);
rc.setExtensions(extensionsD);
rc.setOptions(opts);
return rc;
}
}
/**
* Parses something like:
* optional string foo = 1;
*/
FieldDescriptor FieldDescriptor(MessageDescriptor parent) :
{
String rule;
String type;
String name;
int tag;
LinkedHashMap<String,OptionDescriptor> opts = new LinkedHashMap<String,OptionDescriptor>();
LinkedHashMap<String,FieldDescriptor> fields = new LinkedHashMap<String,FieldDescriptor>();
OptionDescriptor optionD;
FieldDescriptor fieldD;
FieldDescriptor rc = new FieldDescriptor(parent);
MessageDescriptor group = new MessageDescriptor(parent.getProtoDescriptor(), parent);
}
{
rule = Rule()
(
// We have to go through the look ahead trouble because based on if 'type' is 'group'
// we need to look ahead to see if it looks like a group declaration instead it being
// message type called group.
LOOKAHEAD(5)
type = PackageID()
name = ID()
<EQUALS>
tag = Integer()
(
<LBRACKET>
optionD = OptionDescriptor()
{
opts.put(optionD.getName(), optionD);
}
(
<COMMA>
optionD = OptionDescriptor()
{
opts.put(optionD.getName(), optionD);
}
)*
<RBRACKET>
)?
<SEMICOLON>
|
{
}
<GROUP>
name = ID()
<EQUALS>
tag = Integer()
<LBRACE>
(
fieldD = FieldDescriptor(group)
{
fields.put(fieldD.getName(), fieldD);
}
)*
<RBRACE>
( <SEMICOLON> )?
{
type = name;
group.setName(name);
group.setFields(fields);
rc.setGroup(group);
}
)
{
rc.setName(name);
rc.setType(type);
rc.setRule(rule);
rc.setTag(tag);
rc.setOptions(opts);
return rc;
}
}
ServiceDescriptor ServiceDescriptor(ProtoDescriptor proto) :
{
String name;
ArrayList<MethodDescriptor> methods = new ArrayList<MethodDescriptor>();
MethodDescriptor method;
}
{
<SERVICE> name = ID() <LBRACE>
(
method = MethodDescriptor(proto) <SEMICOLON>
{
methods.add(method);
}
)*
<RBRACE>
{
ServiceDescriptor rc = new ServiceDescriptor(proto);
rc.setName(name);
rc.setMethods(methods);
return rc;
}
}
MethodDescriptor MethodDescriptor(ProtoDescriptor proto) :
{
String name;
String input;
String output;
}
{
<RPC> name = ID() <LPAREN> input = PackageID() <RPAREN> <RETURNS> <LPAREN> output = PackageID() <RPAREN>
{
MethodDescriptor rc = new MethodDescriptor(proto);
rc.setName(name);
rc.setParameter(input);
rc.setReturns(output);
return rc;
}
}
OptionDescriptor OptionDescriptor() :
{
String name;
String value;
}
{
name = ID()
<EQUALS>
value=Value()
{
OptionDescriptor rc = new OptionDescriptor();
rc.setName(name);
rc.setValue(value);
return rc;
}
}
MessageDescriptor ExtendDescriptor(ProtoDescriptor proto, MessageDescriptor parent) :
{
String name;
LinkedHashMap<String, FieldDescriptor> fields = new LinkedHashMap<String,FieldDescriptor>();
MessageDescriptor rc = new MessageDescriptor(proto, parent);
FieldDescriptor fieldD;
}
{
<EXTEND> name = ID() <LBRACE>
(
fieldD = FieldDescriptor(rc)
{ fields.put(fieldD.getName(), fieldD); }
)*
<RBRACE>
{
rc.setName(name);
rc.setFields(fields);
return rc;
}
}
ExtensionsDescriptor ExtensionsDescriptor(MessageDescriptor parent) :
{
int first;
int last;
}
{
<EXTENSIONS>
first = Integer()
<TO>
(
last = Integer()
|
<MAX>
{
last=536870911;
}
)
{
ExtensionsDescriptor rc = new ExtensionsDescriptor(parent);
rc.setFirst(first);
rc.setLast(last);
return rc;
}
}
EnumDescriptor EnumDescriptor(ProtoDescriptor proto, MessageDescriptor parent) :
{
Token name;
LinkedHashMap<String,EnumFieldDescriptor> fields = new LinkedHashMap<String,EnumFieldDescriptor>();
EnumDescriptor rc = new EnumDescriptor(proto, parent);
LinkedHashMap<String,OptionDescriptor> opts = new LinkedHashMap<String,OptionDescriptor>();
EnumFieldDescriptor enumD;
OptionDescriptor optionD;
}
{
<ENUM> name = <ID> <LBRACE>
(
LOOKAHEAD(2)
<OPTION> optionD = OptionDescriptor() <SEMICOLON>
{ opts.put(optionD.getName(),optionD); }
|
enumD = EnumFieldDescriptor(rc) <SEMICOLON>
{ fields.put(enumD.getName(),enumD); }
)*
<RBRACE>
{
rc.setName(name.image);
rc.setFields(fields);
rc.setOptions(opts);
return rc;
}
}
/**
* Parses something like:
* optional string foo = 1;
*/
EnumFieldDescriptor EnumFieldDescriptor(EnumDescriptor parent) :
{
String name;
int value=0;
}
{
name = ID()
<EQUALS>
value = Integer()
{
EnumFieldDescriptor rc = new EnumFieldDescriptor(parent);
rc.setName(name);
rc.setValue(value);
return rc;
}
}
int Integer() :
{
Token t;
}
{
t = <INTEGER>
{
return Integer.parseInt(t.image);
}
}
String Rule() :
{
Token t;
}
{
(
t = <REQURIED>
|
t = <OPTIONAL>
|
t = <REPEATED>
)
{
return t.image;
}
}
String Value() :
{
Token t;
String value=null;
}
{
(
value = StringLitteral()
|
value = ID()
|
t = <INTEGER>
{
value = t.image;
}
|
t = <FLOAT>
{
value = t.image;
}
)
{
return value;
}
}
String ID() :
{
Token t;
}
{
(
t = <ID>
| t = <GROUP>
| t = <IMPORT>
| t = <PACKAGE>
| t = <SERVICE>
| t = <RPC>
| t = <OPTION>
| t = <MESSAGE>
| t = <EXTENSIONS>
| t = <EXTEND>
| t = <ENUM>
| t = <REQURIED>
| t = <OPTIONAL>
| t = <REPEATED>
| t = <RETURNS>
| t = <TO>
| t = <MAX>
)
{
return t.image;
}
}
String PackageID() :
{
String t;
StringBuffer sb = new StringBuffer();
}
{
(
t = ID()
{
sb.append(t);
}
(
<PERIOD>
t=ID()
{
sb.append(".");
sb.append(t);
}
)*
)
{
return sb.toString();
}
}
String StringLitteral() :
{
Token t;
}
{
t = <STRING>
{
return ParserSupport.decodeString(t);
}
}

View File

@ -0,0 +1,17 @@
=========================================================================
== Apache Notice ==
=========================================================================
Apache ActiveMQ
Copyright 2005-2008 The Apache Software Foundation
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
=========================================================================
== Protocol Buffers Notice ==
=========================================================================
This product includes software developed by the Protocol Buffers
project (http://code.google.com/apis/protocolbuffers).

View File

@ -203,6 +203,8 @@
<modules>
<module>activemq-openwire-generator</module>
<module>activemq-protobuf</module>
<module>activemq-protobuf-test</module>
<module>activemq-client</module>
<module>activemq-openwire-legacy</module>
<module>activemq-broker</module>