From d9ad523709b5b2251df07770cd66afffc06b30db Mon Sep 17 00:00:00 2001 From: "Hiram R. Chirino" Date: Tue, 17 Feb 2009 14:49:52 +0000 Subject: [PATCH] Added a new alternative java generator which uses a different API style than the current one. The new API style should make it easier to work with deffered demarshalled messages. git-svn-id: https://svn.apache.org/repos/asf/activemq/activemq-protobuf/trunk@745108 13f79535-47bb-0310-9956-ffa450edef68 --- .../activemq/protobuf/CodedInputStream.java | 3 + .../activemq/protobuf/MessageBuffer.java | 28 + .../protobuf/MessageBufferSupport.java | 128 + .../protobuf/compiler/AltJavaGenerator.java | 2062 +++++++++++++++++ .../protobuf/compiler/CompilerException.java | 18 + .../protobuf/compiler/JavaGenerator.java | 13 - .../activemq/protobuf/compiler/ProtoMojo.java | 21 +- 7 files changed, 2256 insertions(+), 17 deletions(-) create mode 100644 activemq-protobuf/src/main/java/org/apache/activemq/protobuf/MessageBuffer.java create mode 100644 activemq-protobuf/src/main/java/org/apache/activemq/protobuf/MessageBufferSupport.java create mode 100644 activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/AltJavaGenerator.java create mode 100644 activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/CompilerException.java diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedInputStream.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedInputStream.java index 96dcf89..b8bb699 100644 --- a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedInputStream.java +++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedInputStream.java @@ -357,6 +357,9 @@ public byte readRawByte() throws IOException { * 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(); } diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/MessageBuffer.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/MessageBuffer.java new file mode 100644 index 0000000..9d553ba --- /dev/null +++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/MessageBuffer.java @@ -0,0 +1,28 @@ +package org.apache.activemq.protobuf; + +import java.io.IOException; +import java.io.OutputStream; + +public interface MessageBuffer { + + 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; + +} diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/MessageBufferSupport.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/MessageBufferSupport.java new file mode 100644 index 0000000..c5dba9e --- /dev/null +++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/MessageBufferSupport.java @@ -0,0 +1,128 @@ +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(); + 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); + } + } + + 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(); + 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 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 void addAll(Iterable values, Collection list) { + if (values instanceof Collection) { + @SuppressWarnings("unsafe") + Collection collection = (Collection) values; + list.addAll(collection); + } else { + for (T value : values) { + list.add(value); + } + } + } + + +} diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/AltJavaGenerator.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/AltJavaGenerator.java new file mode 100644 index 0000000..9b660c6 --- /dev/null +++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/AltJavaGenerator.java @@ -0,0 +1,2062 @@ +/** + * 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 static org.apache.activemq.protobuf.WireFormat.WIRETYPE_FIXED32; +import static org.apache.activemq.protobuf.WireFormat.WIRETYPE_FIXED64; +import static org.apache.activemq.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED; +import static org.apache.activemq.protobuf.WireFormat.WIRETYPE_VARINT; +import static org.apache.activemq.protobuf.WireFormat.makeTag; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.StringTokenizer; + +import org.apache.activemq.protobuf.compiler.parser.ParseException; +import org.apache.activemq.protobuf.compiler.parser.ProtoParser; + +public class AltJavaGenerator { + + private File out = new File("."); + private File[] path = new File[]{new File(".")}; + + private ProtoDescriptor proto; + private String javaPackage; + private String outerClassName; + private PrintWriter w; + private int indent; + private ArrayList errors = new ArrayList(); + private boolean multipleFiles; + private boolean auto_clear_optional_fields; + + public static void main(String[] args) { + + AltJavaGenerator generator = new AltJavaGenerator(); + args = CommandLineSupport.setOptions(generator, args); + + if (args.length == 0) { + System.out.println("No proto files specified."); + } + for (int i = 0; i < args.length; i++) { + try { + System.out.println("Compiling: "+args[i]); + generator.compile(new File(args[i])); + } catch (CompilerException e) { + System.out.println("Protocol Buffer Compiler failed with the following error(s):"); + for (String error : e.getErrors() ) { + System.out.println(""); + System.out.println(error); + } + System.out.println(""); + System.out.println("Compile failed. For more details see error messages listed above."); + return; + } + } + + } + + interface Closure { + void execute() throws CompilerException; + } + + public void compile(File file) throws CompilerException { + + // Parse the proto file + FileInputStream is=null; + try { + is = new FileInputStream(file); + ProtoParser parser = new ProtoParser(is); + proto = parser.ProtoDescriptor(); + proto.setName(file.getName()); + loadImports(proto, file.getParentFile()); + proto.validate(errors); + } catch (FileNotFoundException e) { + errors.add("Failed to open: "+file.getPath()+":"+e.getMessage()); + } catch (ParseException e) { + errors.add("Failed to parse: "+file.getPath()+":"+e.getMessage()); + } finally { + try { is.close(); } catch (Throwable ignore){} + } + + if (!errors.isEmpty()) { + throw new CompilerException(errors); + } + + // Load the options.. + javaPackage = javaPackage(proto); + outerClassName = javaClassName(proto); +// optimizeFor = getOption(proto.getOptions(), "optimize_for", "SPEED"); + multipleFiles = isMultipleFilesEnabled(proto); +// deferredDecode = Boolean.parseBoolean(getOption(proto.getOptions(), "deferred_decode", "false")); + auto_clear_optional_fields = Boolean.parseBoolean(getOption(proto.getOptions(), "auto_clear_optional_fields", "false")); + + if( multipleFiles ) { + generateProtoFile(); + } else { + writeFile(outerClassName, new Closure(){ + public void execute() throws CompilerException { + generateProtoFile(); + } + }); + } + + if (!errors.isEmpty()) { + throw new CompilerException(errors); + } + + } + + private void writeFile(String className, Closure closure) throws CompilerException { + PrintWriter oldWriter = w; + // Figure out the java file name.. + File outputFile = out; + if (javaPackage != null) { + String packagePath = javaPackage.replace('.', '/'); + outputFile = new File(outputFile, packagePath); + } + outputFile = new File(outputFile, className + ".java"); + + // Start writing the output file.. + outputFile.getParentFile().mkdirs(); + + FileOutputStream fos=null; + try { + fos = new FileOutputStream(outputFile); + w = new PrintWriter(fos); + closure.execute(); + w.flush(); + } catch (FileNotFoundException e) { + errors.add("Failed to write to: "+outputFile.getPath()+":"+e.getMessage()); + } finally { + try { fos.close(); } catch (Throwable ignore){} + w = oldWriter; + } + } + + private void loadImports(ProtoDescriptor proto, File protoDir) { + LinkedHashMap children = new LinkedHashMap(); + for (String imp : proto.getImports()) { + File file = new File(protoDir, imp); + for (int i = 0; i < path.length && !file.exists(); i++) { + file = new File(path[i], imp); + } + if ( !file.exists() ) { + errors.add("Cannot load import: "+imp); + } + + FileInputStream is=null; + try { + is = new FileInputStream(file); + ProtoParser parser = new ProtoParser(is); + ProtoDescriptor child = parser.ProtoDescriptor(); + child.setName(file.getName()); + loadImports(child, file.getParentFile()); + children.put(imp, child); + } catch (ParseException e) { + errors.add("Failed to parse: "+file.getPath()+":"+e.getMessage()); + } catch (FileNotFoundException e) { + errors.add("Failed to open: "+file.getPath()+":"+e.getMessage()); + } finally { + try { is.close(); } catch (Throwable ignore){} + } + } + proto.setImportProtoDescriptors(children); + } + + + private void generateProtoFile() throws CompilerException { + if( multipleFiles ) { + for (EnumDescriptor value : proto.getEnums().values()) { + final EnumDescriptor o = value; + String className = uCamel(o.getName()); + writeFile(className, new Closure(){ + public void execute() throws CompilerException { + generateFileHeader(); + generateEnum(o); + } + }); + } + for (MessageDescriptor value : proto.getMessages().values()) { + final MessageDescriptor o = value; + String className = uCamel(o.getName()); + writeFile(className, new Closure(){ + public void execute() throws CompilerException { + generateFileHeader(); + generateMessageBean(o); + } + }); + } + + } else { + generateFileHeader(); + + p("public class " + outerClassName + " {"); + indent(); + + for (EnumDescriptor enumType : proto.getEnums().values()) { + generateEnum(enumType); + } + for (MessageDescriptor m : proto.getMessages().values()) { + generateMessageBean(m); + } + + unindent(); + p("}"); + } + } + + private void generateFileHeader() { + p("//"); + p("// Generated by protoc, do not edit by hand."); + p("//"); + if (javaPackage != null) { + p("package " + javaPackage + ";"); + p(""); + } + } + + private void generateMessageBean(MessageDescriptor m) { + + String className = uCamel(m.getName()); + String beanClassName = className+"Bean"; + String bufferClassName = className+"Buffer"; + p(); + + String staticOption = "static "; + if( multipleFiles && m.getParent()==null ) { + staticOption=""; + } + + p(staticOption+"public interface " + className +" {"); + p(); + indent(); + + for (EnumDescriptor enumType : m.getEnums().values()) { + generateEnum(enumType); + } + + // Generate the Nested Messages. + for (MessageDescriptor subMessage : m.getMessages().values()) { + generateMessageBean(subMessage); + } + + // Generate the Group Messages + for (FieldDescriptor field : m.getFields().values()) { + if( field.isGroup() ) { + generateMessageBean(field.getGroup()); + } + } + + // Generate the field getters + for (FieldDescriptor field : m.getFields().values()) { + generateFieldGetterSignatures(field); + } + + p("public "+beanClassName+" copy();"); + p("public "+bufferClassName+" freeze();"); + p("public java.lang.StringBuilder toString(java.lang.StringBuilder sb, String prefix);"); + + + p(); + p("static public final class "+beanClassName+" implements "+className+" {"); + p(); + indent(); + + p(""+bufferClassName+" frozen;"); + p(""+beanClassName+" bean;"); + p(); + p("public "+beanClassName+"() {"); + indent(); + p("this.bean = this;"); + unindent(); + p("}"); + p(); + p("public "+beanClassName+"("+beanClassName+" copy) {"); + indent(); + p("this.bean = copy;"); + unindent(); + p("}"); + p(); + p("public "+beanClassName+" copy() {"); + indent(); + p("return new "+beanClassName+"(bean);"); + unindent(); + p("}"); + p(); + + generateMethodFreeze(m, bufferClassName); + + p("private void copyCheck() {"); + indent(); + p("assert frozen==null : org.apache.activemq.protobuf.MessageBufferSupport.FORZEN_ERROR_MESSAGE;"); + p("if (bean != this) {"); + indent(); + p("copy(bean);"); + unindent(); + p("}"); + unindent(); + p("}"); + p(); + + generateMethodCopyFromBean(m, beanClassName); + + // Generate the field accessors.. + for (FieldDescriptor field : m.getFields().values()) { + generateFieldAccessor(beanClassName, field); + } + + generateMethodToString(m); + + generateMethodMergeFromStream(m, beanClassName); + + generateBeanEquals(m, beanClassName); + + generateMethodMergeFromBean(m, className); + + generateMethodClear(m); + + unindent(); + p("}"); + p(); + + p("static public final class "+bufferClassName+" implements org.apache.activemq.protobuf.MessageBuffer, "+className+" {"); + p(); + indent(); + + p("private "+beanClassName+" bean;"); + p("private org.apache.activemq.protobuf.Buffer buffer;"); + p("private int size=-1;"); + p("private int hashCode;"); + p(); + p("private "+bufferClassName+"(org.apache.activemq.protobuf.Buffer buffer) {"); + indent(); + p("this.buffer = buffer;"); + unindent(); + p("}"); + p(); + p("private "+bufferClassName+"("+beanClassName+" bean) {"); + indent(); + p("this.bean = bean;"); + unindent(); + p("}"); + p(); + p("public "+beanClassName+" copy() {"); + indent(); + p("return bean().copy();"); + unindent(); + p("}"); + p(); + p("public "+bufferClassName+" freeze() {"); + indent(); + p("return this;"); + unindent(); + p("}"); + p(); + p("private "+beanClassName+" bean() {"); + indent(); + p("if (bean == null) {"); + indent(); + p("try {"); + indent(); + p("bean = new "+beanClassName+"().mergeUnframed(new org.apache.activemq.protobuf.CodedInputStream(buffer));"); + p("bean.frozen=this;"); + unindent(); + p("} catch (org.apache.activemq.protobuf.InvalidProtocolBufferException e) {"); + indent(); + p("throw new RuntimeException(e);"); + unindent(); + p("} catch (java.io.IOException e) {"); + indent(); + p("throw new RuntimeException(\"An IOException was thrown (should never happen in this method).\", e);"); + unindent(); + p("}"); + unindent(); + p("}"); + p("return bean;"); + unindent(); + p("}"); + p(); + + p("public String toString() {"); + indent(); + p("return bean().toString();"); + unindent(); + p("}"); + p(); + p("public java.lang.StringBuilder toString(java.lang.StringBuilder sb, String prefix) {"); + indent(); + p("return bean().toString(sb, prefix);"); + unindent(); + p("}"); + p(); + + for (FieldDescriptor field : m.getFields().values()) { + generateBufferGetters(field); + } + + generateMethodWrite(m); + + generateMethodSerializedSize(m); + + generateMethodParseFrom(m, bufferClassName, beanClassName); + + generateBufferEquals(m, bufferClassName); + + unindent(); + p("}"); + p(); + + +// generateMethodVisitor(m); +// generateMethodType(m, className); + + + unindent(); + p("}"); + p(); + + } + + private void generateMethodFreeze(MessageDescriptor m, String bufferClassName) { + p("public boolean frozen() {"); + indent(); + p("return frozen!=null;"); + unindent(); + p("}"); + p(); + p("public "+bufferClassName+" freeze() {"); + indent(); + p("if( frozen==null ) {"); + indent(); + p("frozen = new "+bufferClassName+"(bean);"); + p("frozen.serializedSizeUnframed();"); + unindent(); + p("}"); + p("return frozen;"); + unindent(); + p("}"); + p(); + } + + /** + * @param m + * @param className + */ + private void generateMethodCopyFromBean(MessageDescriptor m, String className) { + p("private void copy("+className+" other) {"); + indent(); + p("this.bean = this;"); + for (FieldDescriptor field : m.getFields().values()) { + String lname = lCamel(field.getName()); + String type = field.getRule()==FieldDescriptor.REPEATED_RULE ? javaCollectionType(field):javaType(field); + boolean primitive = field.getTypeDescriptor()==null || field.getTypeDescriptor().isEnum(); + if( field.isRepeated() ) { + if( primitive ) { + p("this.f_" + lname + " = other.f_" + lname + ";"); + p("if( this.f_" + lname + " !=null && !other.frozen()) {"); + indent(); + p("this.f_" + lname + " = new java.util.ArrayList<"+type+">(this.f_" + lname + ");"); + unindent(); + p("}"); + } else { + p("this.f_" + lname + " = other.f_" + lname + ";"); + p("if( this.f_" + lname + " !=null) {"); + indent(); + p("this.f_" + lname + " = new java.util.ArrayList<"+type+">(other.f_" + lname + ".size());"); + p("for( "+type+" e : other.f_" + lname + ") {"); + indent(); + p("this.f_" + lname + ".add(e.copy());"); + unindent(); + p("}"); + unindent(); + p("}"); + } + } else { + if( primitive ) { + p("this.f_" + lname + " = other.f_" + lname + ";"); + p("this.b_" + lname + " = other.b_" + lname + ";"); + } else { + p("this.f_" + lname + " = other.f_" + lname + ";"); + p("if( this.f_" + lname + " !=null ) {"); + indent(); + p("this.f_" + lname + " = this.f_" + lname + ".copy();"); + unindent(); + p("}"); + } + } + } + unindent(); + p("}"); + p(); + } + + + /** + * If the java_visitor message option is set, then this method generates a visitor method. The option + * speifiies the class name of the visitor and optionally the return value and exceptions thrown by the visitor. + * + * Examples: + * + * option java_visitor = "org.apache.kahadb.store.Visitor"; + * generates: + * public void visit(org.apache.kahadb.store.Visitor visitor) { + * visitor.visit(this); + * } + * + * option java_visitor = "org.apache.kahadb.store.Visitor:int:java.io.IOException"; + * generates: + * public int visit(org.apache.kahadb.store.Visitor visitor) throws java.io.IOException { + * return visitor.visit(this); + * } + * + * @param m + */ + private void generateMethodVisitor(MessageDescriptor m) { + String javaVisitor = getOption(m.getOptions(), "java_visitor", null); + if( javaVisitor!=null ) { + String returns = "void"; + String throwsException = null; + + StringTokenizer st = new StringTokenizer(javaVisitor, ":"); + String vistorClass = st.nextToken(); + if( st.hasMoreTokens() ) { + returns = st.nextToken(); + } + if( st.hasMoreTokens() ) { + throwsException = st.nextToken(); + } + + String throwsClause = ""; + if( throwsException!=null ) { + throwsClause = "throws "+throwsException+" "; + } + + p("public "+returns+" visit("+vistorClass+" visitor) "+throwsClause+ "{"); + indent(); + if( "void".equals(returns) ) { + p("visitor.visit(this);"); + } else { + p("return visitor.visit(this);"); + } + unindent(); + p("}"); + p(); + } + } + + private void generateMethodType(MessageDescriptor m, String className) { + String typeEnum = getOption(m.getOptions(), "java_type_method", null); + if( typeEnum!=null ) { + + TypeDescriptor typeDescriptor = m.getType(typeEnum); + if( typeDescriptor == null ) { + typeDescriptor = m.getProtoDescriptor().getType(typeEnum); + } + if( typeDescriptor == null || !typeDescriptor.isEnum() ) { + errors.add("The java_type_method option on the "+m.getName()+" message does not point to valid enum type"); + return; + } + + + String constant = constantCase(className); + EnumDescriptor enumDescriptor = (EnumDescriptor)typeDescriptor; + if( enumDescriptor.getFields().get(constant) == null ) { + errors.add("The java_type_method option on the "+m.getName()+" message does not points to the "+typeEnum+" enum but it does not have an entry for "+constant); + } + + String type = javaType(typeDescriptor); + + p("public "+type+" type() {"); + indent(); + p("return "+type+"."+constant+";"); + unindent(); + p("}"); + p(); + } + } + + private void generateMethodParseFrom(MessageDescriptor m, String bufferClassName, String beanClassName) { + p("public static "+beanClassName+" parseUnframed(org.apache.activemq.protobuf.CodedInputStream data) throws org.apache.activemq.protobuf.InvalidProtocolBufferException, java.io.IOException {"); + indent(); + p("return new "+beanClassName+"().mergeUnframed(data);"); + unindent(); + p("}"); + p(); + p("public static "+beanClassName+" parseUnframed(java.io.InputStream data) throws org.apache.activemq.protobuf.InvalidProtocolBufferException, java.io.IOException {"); + indent(); + p("return parseUnframed(new org.apache.activemq.protobuf.CodedInputStream(data));"); + unindent(); + p("}"); + p(); + p("public static "+bufferClassName+" parseUnframed(org.apache.activemq.protobuf.Buffer data) throws org.apache.activemq.protobuf.InvalidProtocolBufferException {"); + indent(); + p("return new "+bufferClassName+"(data);"); + unindent(); + p("}"); + p(); + p("public static "+bufferClassName+" parseUnframed(byte[] data) throws org.apache.activemq.protobuf.InvalidProtocolBufferException {"); + indent(); + p("return parseUnframed(new org.apache.activemq.protobuf.Buffer(data));"); + unindent(); + p("}"); + p(); + p("public static "+bufferClassName+" parseFramed(org.apache.activemq.protobuf.CodedInputStream data) throws org.apache.activemq.protobuf.InvalidProtocolBufferException, java.io.IOException {"); + indent(); + p("int length = data.readRawVarint32();"); + p("int oldLimit = data.pushLimit(length);"); + p(""+bufferClassName+" rc = parseUnframed(data.readRawBytes(length));"); + p("data.popLimit(oldLimit);"); + p("return rc;"); + unindent(); + p("}"); + p(); + p("public static "+bufferClassName+" parseFramed(org.apache.activemq.protobuf.Buffer data) throws org.apache.activemq.protobuf.InvalidProtocolBufferException {"); + indent(); + p("try {"); + indent(); + p("org.apache.activemq.protobuf.CodedInputStream input = new org.apache.activemq.protobuf.CodedInputStream(data);"); + p(""+bufferClassName+" rc = parseFramed(input);"); + p("input.checkLastTagWas(0);"); + p("return rc;"); + unindent(); + p("} catch (org.apache.activemq.protobuf.InvalidProtocolBufferException e) {"); + indent(); + p("throw e;"); + unindent(); + p("} catch (java.io.IOException e) {"); + indent(); + p("throw new RuntimeException(\"An IOException was thrown (should never happen in this method).\", e);"); + unindent(); + p("}"); + unindent(); + p("}"); + p(); + p("public static "+bufferClassName+" parseFramed(byte[] data) throws org.apache.activemq.protobuf.InvalidProtocolBufferException {"); + indent(); + p("return parseFramed(new org.apache.activemq.protobuf.Buffer(data));"); + unindent(); + p("}"); + p(); + p("public static "+bufferClassName+" parseFramed(java.io.InputStream data) throws org.apache.activemq.protobuf.InvalidProtocolBufferException, java.io.IOException {"); + indent(); + p("return parseUnframed(org.apache.activemq.protobuf.MessageBufferSupport.readFrame(data));"); + unindent(); + p("}"); + p(); + + } + + private void generateBeanEquals(MessageDescriptor m, String className) { + p("public boolean equals(Object obj) {"); + indent(); + p("if( obj==this )"); + p(" return true;"); + p(""); + p("if( obj==null || obj.getClass()!="+className+".class )"); + p(" return false;"); + p(""); + p("return equals(("+className+")obj);"); + unindent(); + p("}"); + p(""); + + p("public boolean equals("+className+" obj) {"); + indent(); + for (FieldDescriptor field : m.getFields().values()) { + String uname = uCamel(field.getName()); + String getterMethod="get"+uname+"()"; + String hasMethod = "has"+uname+"()"; + + if( field.getRule() == FieldDescriptor.REPEATED_RULE ) { + getterMethod = "get"+uname+"List()"; + } + + p("if ("+hasMethod+" ^ obj."+hasMethod+" ) "); + p(" return false;"); + + + + if( field.getRule() != FieldDescriptor.REPEATED_RULE && (field.isNumberType() || field.getType()==FieldDescriptor.BOOL_TYPE) ) { + p("if ("+hasMethod+" && ( "+getterMethod+"!=obj."+getterMethod+" ))"); + } else { + p("if ("+hasMethod+" && ( !"+getterMethod+".equals(obj."+getterMethod+") ))"); + } + p(" return false;"); + } + p("return true;"); + unindent(); + p("}"); + p(""); + p("public int hashCode() {"); + indent(); + int hc = className.hashCode(); + p("int rc="+hc+";"); + int counter=0; + for (FieldDescriptor field : m.getFields().values()) { + counter++; + + String uname = uCamel(field.getName()); + String getterMethod="get"+uname+"()"; + String hasMethod = "has"+uname+"()"; + + if( field.getRule() == FieldDescriptor.REPEATED_RULE ) { + getterMethod = "get"+uname+"List()"; + } + + p("if ("+hasMethod+") {"); + indent(); + + if( field.getRule() == FieldDescriptor.REPEATED_RULE ) { + p("rc ^= ( "+uname.hashCode()+"^"+getterMethod+".hashCode() );"); + } else if( field.isInteger32Type() ) { + p("rc ^= ( "+uname.hashCode()+"^"+getterMethod+" );"); + } else if( field.isInteger64Type() ) { + p("rc ^= ( "+uname.hashCode()+"^(new Long("+getterMethod+")).hashCode() );"); + } else if( field.getType()==FieldDescriptor.DOUBLE_TYPE ) { + p("rc ^= ( "+uname.hashCode()+"^(new Double("+getterMethod+")).hashCode() );"); + } else if( field.getType()==FieldDescriptor.FLOAT_TYPE ) { + p("rc ^= ( "+uname.hashCode()+"^(new Double("+getterMethod+")).hashCode() );"); + } else if( field.getType()==FieldDescriptor.BOOL_TYPE ) { + p("rc ^= ( "+uname.hashCode()+"^ ("+getterMethod+"? "+counter+":-"+counter+") );"); + } else { + p("rc ^= ( "+uname.hashCode()+"^"+getterMethod+".hashCode() );"); + } + unindent(); + p("}"); + } + p("return rc;"); + unindent(); + p("}"); + p(""); + } + + private void generateBufferEquals(MessageDescriptor m, String className) { + p("public boolean equals(Object obj) {"); + indent(); + p("if( obj==this )"); + p(" return true;"); + p(""); + p("if( obj==null || obj.getClass()!="+className+".class )"); + p(" return false;"); + p(""); + p("return equals(("+className+")obj);"); + unindent(); + p("}"); + p(""); + + p("public boolean equals("+className+" obj) {"); + indent(); + p("return toUnframedBuffer().equals(obj.toUnframedBuffer());"); + unindent(); + p("}"); + p(""); + p("public int hashCode() {"); + indent(); + int hc = className.hashCode(); + p("if( hashCode==0 ) {"); + p("hashCode="+hc+" ^ toUnframedBuffer().hashCode();"); + p("}"); + p("return hashCode;"); + unindent(); + p("}"); + p(""); + } + + /** + * @param m + */ + private void generateMethodSerializedSize(MessageDescriptor m) { + + p("public int serializedSizeFramed() {"); + indent(); + p("int t = serializedSizeUnframed();"); + p("return org.apache.activemq.protobuf.CodedOutputStream.computeRawVarint32Size(t) + t;"); + unindent(); + p("}"); + p(); + p("public int serializedSizeUnframed() {"); + indent(); + p("if (buffer != null) {"); + indent(); + p("return buffer.length;"); + unindent(); + p("}"); + p("if (size != -1)"); + p(" return size;"); + p(); + p("size = 0;"); + for (FieldDescriptor field : m.getFields().values()) { + + String uname = uCamel(field.getName()); + String getter="get"+uname+"()"; + String type = javaType(field); + + if( !field.isRequired() ) { + p("if (has"+uname+"()) {"); + indent(); + } + + if( field.getRule() == FieldDescriptor.REPEATED_RULE ) { + p("for ("+type+" i : get"+uname+"List()) {"); + indent(); + getter = "i"; + } + + if( field.getType()==FieldDescriptor.STRING_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeStringSize("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.BYTES_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeBytesSize("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.BOOL_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeBoolSize("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.DOUBLE_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeDoubleSize("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.FLOAT_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeFloatSize("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.INT32_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeInt32Size("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.INT64_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeInt64Size("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.SINT32_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeSInt32Size("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.SINT64_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeSInt64Size("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.UINT32_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeUInt32Size("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.UINT64_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeUInt64Size("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.FIXED32_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeFixed32Size("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.FIXED64_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeFixed64Size("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.SFIXED32_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeSFixed32Size("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.SFIXED64_TYPE ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeSFixed64Size("+field.getTag()+", "+getter+");"); + } else if( field.getTypeDescriptor().isEnum() ) { + p("size += org.apache.activemq.protobuf.CodedOutputStream.computeEnumSize("+field.getTag()+", "+getter+".getNumber());"); + } else if ( field.getGroup()!=null ) { + errors.add("This code generator does not support group fields."); +// p("size += org.apache.activemq.protobuf.MessageBufferSupport.computeGroupSize("+field.getTag()+", ("+type+"Buffer)"+getter+");"); + } else { + p("size += org.apache.activemq.protobuf.MessageBufferSupport.computeMessageSize("+field.getTag()+", "+getter+".freeze());"); + } + if( field.getRule() == FieldDescriptor.REPEATED_RULE ) { + unindent(); + p("}"); + } + + if( !field.isRequired() ) { + unindent(); + p("}"); + } + + } + // TODO: handle unknown fields + // size += getUnknownFields().getSerializedSize();"); + p("return size;"); + unindent(); + p("}"); + p(); + } + + /** + * @param m + */ + private void generateMethodWrite(MessageDescriptor m) { + + p("public org.apache.activemq.protobuf.Buffer toUnframedBuffer() {"); + indent(); + p("if( buffer !=null ) {"); + indent(); + p("return buffer;"); + unindent(); + p("}"); + p("return org.apache.activemq.protobuf.MessageBufferSupport.toUnframedBuffer(this);"); + unindent(); + p("}"); + p(); + p("public org.apache.activemq.protobuf.Buffer toFramedBuffer() {"); + indent(); + p("return org.apache.activemq.protobuf.MessageBufferSupport.toFramedBuffer(this);"); + unindent(); + p("}"); + p(); + p("public byte[] toUnframedByteArray() {"); + indent(); + p("return toUnframedBuffer().toByteArray();"); + unindent(); + p("}"); + p(); + p("public byte[] toFramedByteArray() {"); + indent(); + p("return toFramedBuffer().toByteArray();"); + unindent(); + p("}"); + p(); + p("public void writeFramed(org.apache.activemq.protobuf.CodedOutputStream output) throws java.io.IOException {"); + indent(); + p("output.writeRawVarint32(serializedSizeUnframed());"); + p("writeUnframed(output);"); + unindent(); + p("}"); + p(); + p("public void writeFramed(java.io.OutputStream output) throws java.io.IOException {"); + indent(); + p("org.apache.activemq.protobuf.CodedOutputStream codedOutput = new org.apache.activemq.protobuf.CodedOutputStream(output);"); + p("writeFramed(codedOutput);"); + p("codedOutput.flush();"); + unindent(); + p("}"); + p(); + + p("public void writeUnframed(java.io.OutputStream output) throws java.io.IOException {"); + indent(); + p("org.apache.activemq.protobuf.CodedOutputStream codedOutput = new org.apache.activemq.protobuf.CodedOutputStream(output);"); + p("writeUnframed(codedOutput);"); + p("codedOutput.flush();"); + unindent(); + p("}"); + p(); + + p("public void writeUnframed(org.apache.activemq.protobuf.CodedOutputStream output) throws java.io.IOException {"); + indent(); + + p("if (buffer == null) {"); + indent(); + p("int size = serializedSizeUnframed();"); + p("buffer = output.getNextBuffer(size);"); + p("org.apache.activemq.protobuf.CodedOutputStream original=null;"); + p("if( buffer == null ) {"); + indent(); + p("buffer = new org.apache.activemq.protobuf.Buffer(new byte[size]);"); + p("original = output;"); + p("output = new org.apache.activemq.protobuf.CodedOutputStream(buffer);"); + unindent(); + p("}"); + + for (FieldDescriptor field : m.getFields().values()) { + String uname = uCamel(field.getName()); + String getter="bean.get"+uname+"()"; + String type = javaType(field); + + if( !field.isRequired() ) { + p("if (bean.has"+uname+"()) {"); + indent(); + } + + if( field.getRule() == FieldDescriptor.REPEATED_RULE ) { + p("for ("+type+" i : bean.get"+uname+"List()) {"); + indent(); + getter = "i"; + } + + if( field.getType()==FieldDescriptor.STRING_TYPE ) { + p("output.writeString("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.BYTES_TYPE ) { + p("output.writeBytes("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.BOOL_TYPE ) { + p("output.writeBool("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.DOUBLE_TYPE ) { + p("output.writeDouble("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.FLOAT_TYPE ) { + p("output.writeFloat("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.INT32_TYPE ) { + p("output.writeInt32("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.INT64_TYPE ) { + p("output.writeInt64("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.SINT32_TYPE ) { + p("output.writeSInt32("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.SINT64_TYPE ) { + p("output.writeSInt64("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.UINT32_TYPE ) { + p("output.writeUInt32("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.UINT64_TYPE ) { + p("output.writeUInt64("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.FIXED32_TYPE ) { + p("output.writeFixed32("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.FIXED64_TYPE ) { + p("output.writeFixed64("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.SFIXED32_TYPE ) { + p("output.writeSFixed32("+field.getTag()+", "+getter+");"); + } else if( field.getType()==FieldDescriptor.SFIXED64_TYPE ) { + p("output.writeSFixed64("+field.getTag()+", "+getter+");"); + } else if( field.getTypeDescriptor().isEnum() ) { + p("output.writeEnum("+field.getTag()+", "+getter+".getNumber());"); + } else if ( field.getGroup()!=null ) { + errors.add("This code generator does not support group fields."); +// p("writeGroup(output, "+field.getTag()+", "+getter+");"); + } else { + p("org.apache.activemq.protobuf.MessageBufferSupport.writeMessage(output, "+field.getTag()+", "+getter+".freeze());"); + } + + if( field.getRule() == FieldDescriptor.REPEATED_RULE ) { + unindent(); + p("}"); + } + + if( !field.isRequired() ) { + unindent(); + p("}"); + } + } + + p("if( original !=null ) {"); + indent(); + p("output.checkNoSpaceLeft();"); + p("output = original;"); + p("output.writeRawBytes(buffer);"); + unindent(); + p("}"); + unindent(); + p("} else {"); + indent(); + p("output.writeRawBytes(buffer);"); + unindent(); + p("}"); + + unindent(); + p("}"); + p(); + } + + /** + * @param m + * @param className + */ + private void generateMethodMergeFromStream(MessageDescriptor m, String className) { + p("public "+className+" mergeUnframed(java.io.InputStream input) throws java.io.IOException {"); + indent(); + p("return mergeUnframed(new org.apache.activemq.protobuf.CodedInputStream(input));"); + unindent(); + p("}"); + p(); + p("public "+className+" mergeUnframed(org.apache.activemq.protobuf.CodedInputStream input) throws java.io.IOException {"); + indent(); + { + p("copyCheck();"); + p("while (true) {"); + indent(); + { + p("int tag = input.readTag();"); + p("if ((tag & 0x07) == 4) {"); + p(" return this;"); + p("}"); + + p("switch (tag) {"); + p("case 0:"); + p(" return this;"); + p("default: {"); + + p(" break;"); + p("}"); + + for (FieldDescriptor field : m.getFields().values()) { + String uname = uCamel(field.getName()); + String setter = "set" + uname; + boolean repeated = field.getRule() == FieldDescriptor.REPEATED_RULE; + if (repeated) { + setter = "create" + uname + "List().add"; + } + if (field.getType() == FieldDescriptor.STRING_TYPE) { + p("case " + + makeTag(field.getTag(), + WIRETYPE_LENGTH_DELIMITED) + ":"); + indent(); + p(setter + "(input.readString());"); + } else if (field.getType() == FieldDescriptor.BYTES_TYPE) { + p("case " + + makeTag(field.getTag(), + WIRETYPE_LENGTH_DELIMITED) + ":"); + indent(); + p(setter + "(input.readBytes());"); + } else if (field.getType() == FieldDescriptor.BOOL_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_VARINT) + + ":"); + indent(); + p(setter + "(input.readBool());"); + } else if (field.getType() == FieldDescriptor.DOUBLE_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_FIXED64) + + ":"); + indent(); + p(setter + "(input.readDouble());"); + } else if (field.getType() == FieldDescriptor.FLOAT_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_FIXED32) + + ":"); + indent(); + p(setter + "(input.readFloat());"); + } else if (field.getType() == FieldDescriptor.INT32_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_VARINT) + + ":"); + indent(); + p(setter + "(input.readInt32());"); + } else if (field.getType() == FieldDescriptor.INT64_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_VARINT) + + ":"); + indent(); + p(setter + "(input.readInt64());"); + } else if (field.getType() == FieldDescriptor.SINT32_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_VARINT) + + ":"); + indent(); + p(setter + "(input.readSInt32());"); + } else if (field.getType() == FieldDescriptor.SINT64_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_VARINT) + + ":"); + indent(); + p(setter + "(input.readSInt64());"); + } else if (field.getType() == FieldDescriptor.UINT32_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_VARINT) + + ":"); + indent(); + p(setter + "(input.readUInt32());"); + } else if (field.getType() == FieldDescriptor.UINT64_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_VARINT) + + ":"); + indent(); + p(setter + "(input.readUInt64());"); + } else if (field.getType() == FieldDescriptor.FIXED32_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_FIXED32) + + ":"); + indent(); + p(setter + "(input.readFixed32());"); + } else if (field.getType() == FieldDescriptor.FIXED64_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_FIXED64) + + ":"); + indent(); + p(setter + "(input.readFixed64());"); + } else if (field.getType() == FieldDescriptor.SFIXED32_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_FIXED32) + + ":"); + indent(); + p(setter + "(input.readSFixed32());"); + } else if (field.getType() == FieldDescriptor.SFIXED64_TYPE) { + p("case " + makeTag(field.getTag(), WIRETYPE_FIXED64) + + ":"); + indent(); + p(setter + "(input.readSFixed64());"); + } else if (field.getTypeDescriptor().isEnum()) { + p("case " + makeTag(field.getTag(), WIRETYPE_VARINT) + + ":"); + indent(); + String type = javaType(field); + p("{"); + indent(); + p("int t = input.readEnum();"); + p("" + type + " value = " + type + ".valueOf(t);"); + p("if( value !=null ) {"); + indent(); + p(setter + "(value);"); + unindent(); + p("}"); + // TODO: else store it as an known + + unindent(); + p("}"); + + } else if (field.getGroup() != null) { + errors.add("This code generator does not support group fields."); +// p("case "+ makeTag(field.getTag(), WIRETYPE_START_GROUP)+ ":"); +// indent(); +// String type = javaType(field); +// if (repeated) { +// p(setter + "(readGroup(input, " + field.getTag()+ ", new " + type + "()));"); +// } else { +// p("if (has" + uname + "()) {"); +// indent(); +// p("readGroup(input, " + field.getTag() + ", get" +// + uname + "());"); +// unindent(); +// p("} else {"); +// indent(); +// p(setter + "(readGroup(input, " + field.getTag() +// + ",new " + type + "()));"); +// unindent(); +// p("}"); +// } +// p(""); + } else { + p("case "+ makeTag(field.getTag(),WIRETYPE_LENGTH_DELIMITED) + ":"); + indent(); + String type = javaType(field); + if (repeated) { + p(setter + "("+type+"."+type+"Buffer.parseFramed(input));"); + } else { + p("if (has" + uname + "()) {"); + indent(); + p("set" + uname + "(get" + uname + "().copy().mergeFrom("+type+"."+type+"Buffer.parseFramed(input)));"); + unindent(); + p("} else {"); + indent(); + p(setter + "("+type+"."+type+"Buffer.parseFramed(input));"); + unindent(); + p("}"); + } + } + p("break;"); + unindent(); + } + p("}"); + } + unindent(); + p("}"); + } + unindent(); + p("}"); + } + + /** + * @param m + * @param className + */ + private void generateMethodMergeFromBean(MessageDescriptor m, String className) { + p("public "+className+"Bean mergeFrom("+className+" other) {"); + indent(); + p("copyCheck();"); + for (FieldDescriptor field : m.getFields().values()) { + String uname = uCamel(field.getName()); + p("if (other.has"+uname+"()) {"); + indent(); + + if( field.isScalarType() || field.getTypeDescriptor().isEnum() ) { + if( field.isRepeated() ) { + p("get"+uname+"List().addAll(other.get"+uname+"List());"); + } else { + p("set"+uname+"(other.get"+uname+"());"); + } + } else { + + String type = javaType(field); + // It's complex type... + if( field.isRepeated() ) { + p("for("+type+" element: other.get"+uname+"List() ) {"); + indent(); + p("get"+uname+"List().add(element.copy());"); + unindent(); + p("}"); + } else { + p("if (has"+uname+"()) {"); + indent(); + p("set"+uname+"(get"+uname+"().copy().mergeFrom(other.get"+uname+"()));"); + unindent(); + p("} else {"); + indent(); + p("set"+uname+"(other.get"+uname+"().copy());"); + unindent(); + p("}"); + } + } + unindent(); + p("}"); + } + p("return this;"); + unindent(); + p("}"); + p(); + } + + /** + * @param m + */ + private void generateMethodClear(MessageDescriptor m) { + p("public void clear() {"); + indent(); + for (FieldDescriptor field : m.getFields().values()) { + String uname = uCamel(field.getName()); + p("clear" + uname + "();"); + } + unindent(); + p("}"); + p(); + } + +// private void generateMethodAssertInitialized(MessageDescriptor m, String className) { +// +// p("public java.util.ArrayList missingFields() {"); +// indent(); +// p("java.util.ArrayList missingFields = super.missingFields();"); +// +// for (FieldDescriptor field : m.getFields().values()) { +// String uname = uCamel(field.getName()); +// if( field.isRequired() ) { +// p("if( !has" + uname + "() ) {"); +// indent(); +// p("missingFields.add(\""+field.getName()+"\");"); +// unindent(); +// p("}"); +// } +// } +// +// if( !deferredDecode ) { +// for (FieldDescriptor field : m.getFields().values()) { +// if( field.getTypeDescriptor()!=null && !field.getTypeDescriptor().isEnum()) { +// String uname = uCamel(field.getName()); +// p("if( has" + uname + "() ) {"); +// indent(); +// if( !field.isRepeated() ) { +// p("try {"); +// indent(); +// p("get" + uname + "().assertInitialized();"); +// unindent(); +// p("} catch (org.apache.activemq.protobuf.UninitializedMessageException e){"); +// indent(); +// p("missingFields.addAll(prefix(e.getMissingFields(),\""+field.getName()+".\"));"); +// unindent(); +// p("}"); +// } else { +// String type = javaCollectionType(field); +// p("java.util.List<"+type+"> l = get" + uname + "List();"); +// p("for( int i=0; i < l.size(); i++ ) {"); +// indent(); +// p("try {"); +// indent(); +// p("l.get(i).assertInitialized();"); +// unindent(); +// p("} catch (org.apache.activemq.protobuf.UninitializedMessageException e){"); +// indent(); +// p("missingFields.addAll(prefix(e.getMissingFields(),\""+field.getName()+"[\"+i+\"]\"));"); +// unindent(); +// p("}"); +// unindent(); +// p("}"); +// } +// unindent(); +// p("}"); +// } +// } +// } +// p("return missingFields;"); +// unindent(); +// p("}"); +// p(); +// } + + private void generateMethodToString(MessageDescriptor m) { + + p("public String toString() {"); + indent(); + p("return toString(new java.lang.StringBuilder(), \"\").toString();"); + unindent(); + p("}"); + p(); + + p("public java.lang.StringBuilder toString(java.lang.StringBuilder sb, String prefix) {"); + indent(); + for (FieldDescriptor field : m.getFields().values()) { + String uname = uCamel(field.getName()); + p("if( has" + uname + "() ) {"); + indent(); + if( field.isRepeated() ) { + String type = javaCollectionType(field); + p("java.util.List<"+type+"> l = get" + uname + "List();"); + p("for( int i=0; i < l.size(); i++ ) {"); + indent(); + if( field.getTypeDescriptor()!=null && !field.getTypeDescriptor().isEnum()) { + p("sb.append(prefix+\""+field.getName()+"[\"+i+\"] {\\n\");"); + p("l.get(i).toString(sb, prefix+\" \");"); + p("sb.append(prefix+\"}\\n\");"); + } else { + p("sb.append(prefix+\""+field.getName()+"[\"+i+\"]: \");"); + p("sb.append(l.get(i));"); + p("sb.append(\"\\n\");"); + } + unindent(); + p("}"); + } else { + if( field.getTypeDescriptor()!=null && !field.getTypeDescriptor().isEnum()) { + p("sb.append(prefix+\""+field.getName()+" {\\n\");"); + p("get" + uname + "().toString(sb, prefix+\" \");"); + p("sb.append(prefix+\"}\\n\");"); + } else { + p("sb.append(prefix+\""+field.getName()+": \");"); + p("sb.append(get" + uname + "());"); + p("sb.append(\"\\n\");"); + } + } + unindent(); + p("}"); + } + p("return sb;"); + unindent(); + p("}"); + p(); + + } + + /** + * @param field + * @param className + */ + private void generateBufferGetters(FieldDescriptor field) { + String uname = uCamel(field.getName()); + String type = field.getRule()==FieldDescriptor.REPEATED_RULE ? javaCollectionType(field):javaType(field); + boolean repeated = field.getRule()==FieldDescriptor.REPEATED_RULE; + + // Create the fields.. + p("// " + field.getRule() + " " + field.getType() + " " + field.getName() + " = " + field.getTag() + ";"); + if( repeated ) { + // Create the field accessors + p("public boolean has" + uname + "() {"); + indent(); + p("return bean().has" + uname + "();"); + unindent(); + p("}"); + p(); + p("public java.util.List<" + type + "> get" + uname + "List() {"); + indent(); + p("return bean().get" + uname + "List();"); + unindent(); + p("}"); + p(); + p("public int get" + uname + "Count() {"); + indent(); + p("return bean().get" + uname + "Count();"); + unindent(); + p("}"); + p(); + p("public " + type + " get" + uname + "(int index) {"); + indent(); + p("return bean().get" + uname + "(index);"); + unindent(); + p("}"); + p(); + } else { + // Create the field accessors + p("public boolean has" + uname + "() {"); + indent(); + p("return bean().has" + uname + "();"); + unindent(); + p("}"); + p(); + p("public " + type + " get" + uname + "() {"); + indent(); + p("return bean().get" + uname + "();"); + unindent(); + p("}"); + p(); + } + } + + /** + * @param field + * @param className + */ + private void generateFieldGetterSignatures(FieldDescriptor field) { + String uname = uCamel(field.getName()); + String type = field.getRule()==FieldDescriptor.REPEATED_RULE ? javaCollectionType(field):javaType(field); + boolean repeated = field.getRule()==FieldDescriptor.REPEATED_RULE; + + // Create the fields.. + p("// " + field.getRule() + " " + field.getType() + " " + field.getName() + " = " + field.getTag() + ";"); + if( repeated ) { + // Create the field accessors + p("public boolean has" + uname + "();"); + p("public java.util.List<" + type + "> get" + uname + "List();"); + p("public int get" + uname + "Count();"); + p("public " + type + " get" + uname + "(int index);"); + } else { + // Create the field accessors + p("public boolean has" + uname + "();"); + p("public " + type + " get" + uname + "();"); + } + } + + + /** + * @param field + * @param className + */ + private void generateFieldAccessor(String beanClassName, FieldDescriptor field) { + + String lname = lCamel(field.getName()); + String uname = uCamel(field.getName()); + String type = field.getRule()==FieldDescriptor.REPEATED_RULE ? javaCollectionType(field):javaType(field); + String typeDefault = javaTypeDefault(field); + boolean primitive = field.getTypeDescriptor()==null || field.getTypeDescriptor().isEnum(); + boolean repeated = field.getRule()==FieldDescriptor.REPEATED_RULE; + + // Create the fields.. + p("// " + field.getRule() + " " + field.getType() + " " + field.getName() + " = " + field.getTag() + ";"); + + if( repeated ) { + p("private java.util.List<" + type + "> f_" + lname + ";"); + p(); + + // Create the field accessors + p("public boolean has" + uname + "() {"); + indent(); + p("return bean.f_" + lname + "!=null && !bean.f_" + lname + ".isEmpty();"); + unindent(); + p("}"); + p(); + + p("public java.util.List<" + type + "> get" + uname + "List() {"); + indent(); + p("return bean.f_" + lname + ";"); + unindent(); + p("}"); + p(); + + p("public java.util.List<" + type + "> create" + uname + "List() {"); + indent(); + p("copyCheck();"); + p("if( this.f_" + lname + " == null ) {"); + indent(); + p("this.f_" + lname + " = new java.util.ArrayList<" + type + ">();"); + unindent(); + p("}"); + p("return bean.f_" + lname + ";"); + unindent(); + p("}"); + p(); + + p("public "+beanClassName+" set" + uname + "List(java.util.List<" + type + "> " + lname + ") {"); + indent(); + p("copyCheck();"); + p("this.f_" + lname + " = " + lname + ";"); + p("return this;"); + unindent(); + p("}"); + p(); + + p("public int get" + uname + "Count() {"); + indent(); + p("if( bean.f_" + lname + " == null ) {"); + indent(); + p("return 0;"); + unindent(); + p("}"); + p("return bean.f_" + lname + ".size();"); + unindent(); + p("}"); + p(); + + p("public " + type + " get" + uname + "(int index) {"); + indent(); + p("if( bean.f_" + lname + " == null ) {"); + indent(); + p("return null;"); + unindent(); + p("}"); + p("return bean.f_" + lname + ".get(index);"); + unindent(); + p("}"); + p(); + + p("public "+beanClassName+" set" + uname + "(int index, " + type + " value) {"); + indent(); + p("this.create" + uname + "List().set(index, value);"); + p("return this;"); + unindent(); + p("}"); + p(); + + p("public "+beanClassName+" add" + uname + "(" + type + " value) {"); + indent(); + p("this.create" + uname + "List().add(value);"); + p("return this;"); + unindent(); + p("}"); + p(); + + p("public "+beanClassName+" addAll" + uname + "(java.lang.Iterable collection) {"); + indent(); + p("org.apache.activemq.protobuf.MessageBufferSupport.addAll(collection, this.create" + uname + "List());"); + p("return this;"); + unindent(); + p("}"); + p(); + + p("public void clear" + uname + "() {"); + indent(); + p("copyCheck();"); + p("this.f_" + lname + " = null;"); + unindent(); + p("}"); + p(); + + } else { + + p("private " + type + " f_" + lname + " = "+typeDefault+";"); + if (primitive) { + p("private boolean b_" + lname + ";"); + } + p(); + + // Create the field accessors + p("public boolean has" + uname + "() {"); + indent(); + if (primitive) { + p("return bean.b_" + lname + ";"); + } else { + p("return bean.f_" + lname + "!=null;"); + } + unindent(); + p("}"); + p(); + + p("public " + type + " get" + uname + "() {"); + indent(); + p("return bean.f_" + lname + ";"); + unindent(); + p("}"); + p(); + + p("public "+beanClassName+" set" + uname + "(" + type + " " + lname + ") {"); + indent(); + p("copyCheck();"); + if (primitive) { + if( auto_clear_optional_fields && field.isOptional() ) { + if( field.isStringType() && !"null".equals(typeDefault)) { + p("this.b_" + lname + " = ("+lname+" != "+typeDefault+");"); + } else { + p("this.b_" + lname + " = ("+lname+" != "+typeDefault+");"); + } + } else { + p("this.b_" + lname + " = true;"); + } + } + p("this.f_" + lname + " = " + lname + ";"); + p("return this;"); + unindent(); + p("}"); + p(); + + p("public void clear" + uname + "() {"); + indent(); + p("copyCheck();"); + if (primitive) { + p("this.b_" + lname + " = false;"); + } + p("this.f_" + lname + " = " + typeDefault + ";"); + unindent(); + p("}"); + p(); + } + + } + + private String javaTypeDefault(FieldDescriptor field) { + OptionDescriptor defaultOption = field.getOptions().get("default"); + if( defaultOption!=null ) { + if( field.isStringType() ) { + return asJavaString(defaultOption.getValue()); + } else if( field.getType() == FieldDescriptor.BYTES_TYPE ) { + return "new org.apache.activemq.protobuf.Buffer("+asJavaString(defaultOption.getValue())+")"; + } else if( field.isInteger32Type() ) { + int v; + if( field.getType() == FieldDescriptor.UINT32_TYPE ) { + v = TextFormat.parseUInt32(defaultOption.getValue()); + } else { + v = TextFormat.parseInt32(defaultOption.getValue()); + } + return ""+v; + } else if( field.isInteger64Type() ) { + long v; + if( field.getType() == FieldDescriptor.UINT64_TYPE ) { + v = TextFormat.parseUInt64(defaultOption.getValue()); + } else { + v = TextFormat.parseInt64(defaultOption.getValue()); + } + return ""+v+"l"; + } else if( field.getType() == FieldDescriptor.DOUBLE_TYPE ) { + double v = Double.valueOf(defaultOption.getValue()); + return ""+v+"d"; + } else if( field.getType() == FieldDescriptor.FLOAT_TYPE ) { + float v = Float.valueOf(defaultOption.getValue()); + return ""+v+"f"; + } else if( field.getType() == FieldDescriptor.BOOL_TYPE ) { + boolean v = Boolean.valueOf(defaultOption.getValue()); + return ""+v; + } else if( field.getTypeDescriptor()!=null && field.getTypeDescriptor().isEnum() ) { + return javaType(field)+"."+defaultOption.getValue(); + } + return defaultOption.getValue(); + } else { + if( field.isNumberType() ) { + return "0"; + } + if( field.getType() == FieldDescriptor.BOOL_TYPE ) { + return "false"; + } + return "null"; + } + } + + static final char HEX_TABLE[] = new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + private String asJavaString(String value) { + StringBuilder sb = new StringBuilder(value.length()+2); + sb.append("\""); + for (int i = 0; i < value.length(); i++) { + + char b = value.charAt(i); + switch (b) { + // Java does not recognize \a or \v, apparently. + 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 '\\': sb.append("\\\\"); break; + case '\'': sb.append("\\\'"); break; + case '"' : sb.append("\\\""); break; + default: + if (b >= 0x20 && b <'Z') { + sb.append((char) b); + } else { + sb.append("\\u"); + sb.append(HEX_TABLE[(b >>> 12) & 0x0F] ); + sb.append(HEX_TABLE[(b >>> 8) & 0x0F] ); + sb.append(HEX_TABLE[(b >>> 4) & 0x0F] ); + sb.append(HEX_TABLE[b & 0x0F] ); + } + break; + } + + } + sb.append("\""); + return sb.toString(); + } + + private void generateEnum(EnumDescriptor ed) { + String uname = uCamel(ed.getName()); + + String staticOption = "static "; + if( multipleFiles && ed.getParent()==null ) { + staticOption=""; + } + + // TODO Auto-generated method stub + p(); + p("public "+staticOption+"enum " +uname + " {"); + indent(); + + + p(); + int counter=0; + for (EnumFieldDescriptor field : ed.getFields().values()) { + boolean last = counter+1 == ed.getFields().size(); + p(field.getName()+"(\""+field.getName()+"\", "+field.getValue()+")"+(last?";":",")); + counter++; + } + p(); + p("private final String name;"); + p("private final int value;"); + p(); + p("private "+uname+"(String name, int value) {"); + p(" this.name = name;"); + p(" this.value = value;"); + p("}"); + p(); + p("public final int getNumber() {"); + p(" return value;"); + p("}"); + p(); + p("public final String toString() {"); + p(" return name;"); + p("}"); + p(); + p("public static "+uname+" valueOf(int value) {"); + p(" switch (value) {"); + + // It's possible to define multiple ENUM fields with the same value.. + // we only want to put the first one into the switch statement. + HashSet values = new HashSet(); + for (EnumFieldDescriptor field : ed.getFields().values()) { + if( !values.contains(field.getValue()) ) { + p(" case "+field.getValue()+":"); + p(" return "+field.getName()+";"); + values.add(field.getValue()); + } + + } + p(" default:"); + p(" return null;"); + p(" }"); + p("}"); + p(); + + + String createMessage = getOption(ed.getOptions(), "java_create_message", null); + if( "true".equals(createMessage) ) { + + p("public Object createBean() {"); + indent(); + p("switch (this) {"); + indent(); + for (EnumFieldDescriptor field : ed.getFields().values()) { + p("case "+field.getName()+":"); + String type = constantToUCamelCase(field.getName()); + p(" return new "+type+"."+type+"Bean();"); + } + p("default:"); + p(" return null;"); + unindent(); + p("}"); + unindent(); + p("}"); + p(); + + generateParseDelegate(ed, "parseUnframed", "org.apache.activemq.protobuf.Buffer", "org.apache.activemq.protobuf.InvalidProtocolBufferException"); + generateParseDelegate(ed, "parseFramed", "org.apache.activemq.protobuf.Buffer", "org.apache.activemq.protobuf.InvalidProtocolBufferException"); + generateParseDelegate(ed, "parseUnframed", "byte[]", "org.apache.activemq.protobuf.InvalidProtocolBufferException"); + generateParseDelegate(ed, "parseFramed", "byte[]", "org.apache.activemq.protobuf.InvalidProtocolBufferException"); + generateParseDelegate(ed, "parseFramed", "org.apache.activemq.protobuf.CodedInputStream", "org.apache.activemq.protobuf.InvalidProtocolBufferException, java.io.IOException"); + generateParseDelegate(ed, "parseFramed", "java.io.InputStream", "org.apache.activemq.protobuf.InvalidProtocolBufferException, java.io.IOException"); + } + + unindent(); + p("}"); + p(); + } + + private void generateParseDelegate(EnumDescriptor descriptor, String methodName, String inputType, String exceptions) { + p("public org.apache.activemq.protobuf.MessageBuffer " + methodName + "(" + inputType + " data) throws " + exceptions + " {"); + indent(); + p("switch (this) {"); + indent(); + for (EnumFieldDescriptor field : descriptor.getFields().values()) { + p("case "+field.getName()+":"); + String type = constantToUCamelCase(field.getName()); + p(" return "+type+"."+type+"Buffer."+methodName+"(data);"); + } + p("default:"); + p(" return null;"); + unindent(); + p("}"); + unindent(); + p("}"); + p(); + } + + + + private String javaCollectionType(FieldDescriptor field) { + if( field.isInteger32Type() ) { + return "java.lang.Integer"; + } + if( field.isInteger64Type() ) { + return "java.lang.Long"; + } + if( field.getType() == FieldDescriptor.DOUBLE_TYPE ) { + return "java.lang.Double"; + } + if( field.getType() == FieldDescriptor.FLOAT_TYPE ) { + return "java.lang.Float"; + } + if( field.getType() == FieldDescriptor.STRING_TYPE ) { + return "java.lang.String"; + } + if( field.getType() == FieldDescriptor.BYTES_TYPE ) { + return "org.apache.activemq.protobuf.Buffer"; + } + if( field.getType() == FieldDescriptor.BOOL_TYPE ) { + return "java.lang.Boolean"; + } + + TypeDescriptor descriptor = field.getTypeDescriptor(); + return javaType(descriptor); + } + + private String javaType(FieldDescriptor field) { + if( field.isInteger32Type() ) { + return "int"; + } + if( field.isInteger64Type() ) { + return "long"; + } + if( field.getType() == FieldDescriptor.DOUBLE_TYPE ) { + return "double"; + } + if( field.getType() == FieldDescriptor.FLOAT_TYPE ) { + return "float"; + } + if( field.getType() == FieldDescriptor.STRING_TYPE ) { + return "java.lang.String"; + } + if( field.getType() == FieldDescriptor.BYTES_TYPE ) { + return "org.apache.activemq.protobuf.Buffer"; + } + if( field.getType() == FieldDescriptor.BOOL_TYPE ) { + return "boolean"; + } + + TypeDescriptor descriptor = field.getTypeDescriptor(); + return javaType(descriptor); + } + + private String javaType(TypeDescriptor descriptor) { + ProtoDescriptor p = descriptor.getProtoDescriptor(); + if( p != proto ) { + // Try to keep it short.. + String othePackage = javaPackage(p); + if( equals(othePackage,javaPackage(proto) ) ) { + return javaClassName(p)+"."+descriptor.getQName(); + } + // Use the fully qualified class name. + return othePackage+"."+javaClassName(p)+"."+descriptor.getQName(); + } + return descriptor.getQName(); + } + + private boolean equals(String o1, String o2) { + if( o1==o2 ) + return true; + if( o1==null || o2==null ) + return false; + return o1.equals(o2); + } + + private String javaClassName(ProtoDescriptor proto) { + return getOption(proto.getOptions(), "java_outer_classname", uCamel(removeFileExtension(proto.getName()))); + } + + private boolean isMultipleFilesEnabled(ProtoDescriptor proto) { + return "true".equals(getOption(proto.getOptions(), "java_multiple_files", "false")); + } + + + private String javaPackage(ProtoDescriptor proto) { + String name = proto.getPackageName(); + if( name!=null ) { + name = name.replace('-', '.'); + name = name.replace('/', '.'); + } + return getOption(proto.getOptions(), "java_package", name); + } + + + // ---------------------------------------------------------------- + // Internal Helper methods + // ---------------------------------------------------------------- + + private void indent() { + indent++; + } + + private void unindent() { + indent--; + } + + private void p(String line) { + // Indent... + for (int i = 0; i < indent; i++) { + w.print(" "); + } + // Then print. + w.println(line); + } + + private void p() { + w.println(); + } + + private String getOption(Map options, String optionName, String defaultValue) { + OptionDescriptor optionDescriptor = options.get(optionName); + if (optionDescriptor == null) { + return defaultValue; + } + return optionDescriptor.getValue(); + } + + static private String removeFileExtension(String name) { + return name.replaceAll("\\..*", ""); + } + + static private String uCamel(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; + } + sb.append(c); + } else { + upNext=true; + } + } + return sb.toString(); + } + + static private String lCamel(String name) { + if( name == null || name.length()<1 ) + return name; + String uCamel = uCamel(name); + return uCamel.substring(0,1).toLowerCase()+uCamel.substring(1); + } + + + 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(); + } + + + private String constantCase(String name) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if( i!=0 && Character.isUpperCase(c) ) { + sb.append("_"); + } + sb.append(Character.toUpperCase(c)); + } + return sb.toString(); + } + + public File getOut() { + return out; + } + + public void setOut(File outputDirectory) { + this.out = outputDirectory; + } + + public File[] getPath() { + return path; + } + + public void setPath(File[] path) { + this.path = path; + } + +} diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/CompilerException.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/CompilerException.java new file mode 100644 index 0000000..05d1b4f --- /dev/null +++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/CompilerException.java @@ -0,0 +1,18 @@ +/** + * + */ +package org.apache.activemq.protobuf.compiler; + +import java.util.List; + +public class CompilerException extends Exception { + private final List errors; + + public CompilerException(List errors) { + this.errors = errors; + } + + public List getErrors() { + return errors; + } +} \ No newline at end of file diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/JavaGenerator.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/JavaGenerator.java index 8eb4012..e33929f 100644 --- a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/JavaGenerator.java +++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/JavaGenerator.java @@ -31,7 +31,6 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.StringTokenizer; @@ -80,18 +79,6 @@ public static void main(String[] args) { } - static public class CompilerException extends Exception { - private final List errors; - - public CompilerException(List errors) { - this.errors = errors; - } - - public List getErrors() { - return errors; - } - } - interface Closure { void execute() throws CompilerException; } diff --git a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/ProtoMojo.java b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/ProtoMojo.java index f9d0242..c17365e 100644 --- a/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/ProtoMojo.java +++ b/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/ProtoMojo.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.List; -import org.apache.activemq.protobuf.compiler.JavaGenerator.CompilerException; import org.apache.activemq.protobuf.compiler.parser.ParseException; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; @@ -61,6 +60,14 @@ public class ProtoMojo extends AbstractMojo { */ 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() { @@ -78,9 +85,15 @@ public boolean accept(File pathname) { for (File file : recFiles) { try { getLog().info("Compiling: "+file.getPath()); - JavaGenerator generator = new JavaGenerator(); - generator.setOut(outputDirectory); - generator.compile(file); + 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() ) {