001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.activemq.openwire.tool;
018
019 import java.io.File;
020 import java.io.PrintWriter;
021 import java.util.ArrayList;
022 import java.util.Collections;
023 import java.util.Comparator;
024 import java.util.HashMap;
025 import java.util.Iterator;
026 import java.util.LinkedHashMap;
027 import java.util.List;
028
029 import org.codehaus.jam.JAnnotation;
030 import org.codehaus.jam.JAnnotationValue;
031 import org.codehaus.jam.JClass;
032 import org.codehaus.jam.JProperty;
033
034 /**
035 * @version $Revision: 383749 $
036 */
037 public class CHeadersGenerator extends SingleSourceGenerator {
038
039 protected String targetDir = "./src/lib/openwire";
040
041 public Object run() {
042 filePostFix = ".h";
043 if (destFile == null) {
044 destFile = new File(targetDir + "/ow_commands_v" + getOpenwireVersion() + ".h");
045 }
046 return super.run();
047 }
048
049 public String getTargetDir() {
050 return targetDir;
051 }
052
053 public void setTargetDir(String targetDir) {
054 this.targetDir = targetDir;
055 }
056
057 protected void generateLicence(PrintWriter out) {
058 out.println("/**");
059 out.println(" * Licensed to the Apache Software Foundation (ASF) under one or more");
060 out.println(" * contributor license agreements. See the NOTICE file distributed with");
061 out.println(" * this work for additional information regarding copyright ownership.");
062 out.println(" * The ASF licenses this file to You under the Apache License, Version 2.0");
063 out.println(" * (the \"License\"); you may not use this file except in compliance with");
064 out.println(" * the License. You may obtain a copy of the License at");
065 out.println(" *");
066 out.println(" * http://www.apache.org/licenses/LICENSE-2.0");
067 out.println(" *");
068 out.println(" * Unless required by applicable law or agreed to in writing, software");
069 out.println(" * distributed under the License is distributed on an \"AS IS\" BASIS,");
070 out.println(" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.");
071 out.println(" * See the License for the specific language governing permissions and");
072 out.println(" * limitations under the License.");
073 out.println(" */");
074 }
075
076 String changeCase(String value) {
077 StringBuffer b = new StringBuffer();
078 char[] cs = value.toCharArray();
079 for (int i = 0; i < cs.length; i++) {
080 char c = cs[i];
081 if (Character.isUpperCase((char)c)) {
082 b.append('_');
083 b.append(Character.toLowerCase((char)c));
084 } else {
085 b.append(c);
086 }
087 }
088 return b.toString();
089 }
090
091 String toPropertyCase(String value) {
092 return value.substring(0, 1).toLowerCase() + value.substring(1);
093 }
094
095 /**
096 * Sort the class list so that base classes come up first.
097 */
098 protected List<JClass> sort(List source) {
099 LinkedHashMap<JClass, JClass> rc = new LinkedHashMap<JClass, JClass>();
100 ArrayList classes = new ArrayList(source);
101 Collections.sort(classes, new Comparator() {
102 public int compare(Object o1, Object o2) {
103 JClass c1 = (JClass)o1;
104 JClass c2 = (JClass)o2;
105 return c1.getSimpleName().compareTo(c2.getSimpleName());
106 }
107 });
108
109 // lets make a map of all the class names
110 HashMap<JClass, JClass> classNames = new HashMap<JClass, JClass>();
111 for (Iterator iter = classes.iterator(); iter.hasNext();) {
112 JClass c = (JClass)iter.next();
113 classNames.put(c, c);
114 }
115
116 // Add all classes that have no parent first
117 for (Iterator iter = classes.iterator(); iter.hasNext();) {
118 JClass c = (JClass)iter.next();
119 if (!classNames.containsKey(c.getSuperclass())) {
120 rc.put(c, c);
121 }
122 }
123
124 // now lets add the rest
125 for (Iterator iter = classes.iterator(); iter.hasNext();) {
126 JClass c = (JClass)iter.next();
127 if (!rc.containsKey(c)) {
128 rc.put(c, c);
129 }
130 }
131
132 return new ArrayList<JClass>(rc.keySet());
133 }
134
135 void generateFields(PrintWriter out, JClass jclass) {
136
137 if (jclass.getSuperclass() == null || jclass.getSuperclass().getSimpleName().equals("Object")) {
138 out.println("");
139 out.println(" ow_byte structType;");
140 } else {
141 generateFields(out, jclass.getSuperclass());
142 }
143
144 ArrayList<JProperty> properties = new ArrayList<JProperty>();
145 jclass.getDeclaredProperties();
146 for (int i = 0; i < jclass.getDeclaredProperties().length; i++) {
147 JProperty p = jclass.getDeclaredProperties()[i];
148 if (isValidProperty(p)) {
149 properties.add(p);
150 }
151 }
152 for (Iterator<JProperty> iter = properties.iterator(); iter.hasNext();) {
153 JProperty property = iter.next();
154 JAnnotation annotation = property.getGetter().getAnnotation("openwire:property");
155 // JAnnotationValue size = annotation.getValue("size");
156 String name = toPropertyCase(property.getSimpleName());
157 // boolean cached = isCachedProperty(property);
158
159 String type = property.getType().getQualifiedName();
160 if (type.equals("boolean")) {
161 out.println(" ow_" + type + " " + name + ";");
162 } else if (type.equals("byte")) {
163 out.println(" ow_" + type + " " + name + ";");
164 } else if (type.equals("char")) {
165 out.println(" ow_" + type + " " + name + ";");
166 } else if (type.equals("short")) {
167 out.println(" ow_" + type + " " + name + ";");
168 } else if (type.equals("int")) {
169 out.println(" ow_" + type + " " + name + ";");
170 } else if (type.equals("long")) {
171 out.println(" ow_" + type + " " + name + ";");
172 } else if (type.equals("byte[]")) {
173 out.println(" ow_byte_array *" + name + ";");
174 } else if (type.equals("org.apache.activeio.packet.ByteSequence")) {
175 out.println(" ow_byte_array *" + name + ";");
176 } else if (type.equals("org.apache.activeio.packet.ByteSequence")) {
177 out.println(" ow_byte_array *" + name + ";");
178 } else if (type.equals("java.lang.String")) {
179 out.println(" ow_string *" + name + ";");
180 } else {
181 if (property.getType().isArrayType()) {
182 out.println(" ow_DataStructure_array *" + name + ";");
183 } else if (isThrowable(property.getType())) {
184 out.println(" ow_throwable *" + name + ";");
185 } else {
186 out.println(" struct ow_" + property.getType().getSimpleName() + " *" + name + ";");
187 }
188 }
189 }
190 }
191
192 protected void generateSetup(PrintWriter out) {
193 generateLicence(out);
194 out.println("");
195 out.println("/*****************************************************************************************");
196 out.println(" * ");
197 out.println(" * NOTE!: This file is auto generated - do not modify!");
198 out.println(" * if you need to make a change, please see the modify the groovy scripts in the");
199 out.println(" * under src/gram/script and then use maven openwire:generate to regenerate ");
200 out.println(" * this file.");
201 out.println(" * ");
202 out.println(" *****************************************************************************************/");
203 out.println(" ");
204 out.println("#ifndef OW_COMMANDS_V" + openwireVersion + "_H");
205 out.println("#define OW_COMMANDS_V" + openwireVersion + "_H");
206 out.println("");
207 out.println("#include \"ow.h\"");
208 out.println("");
209 out.println("#ifdef __cplusplus");
210 out.println("extern \"C\" {");
211 out.println("#endif /* __cplusplus */");
212 out.println(" ");
213 out.println("#define OW_WIREFORMAT_VERSION " + openwireVersion + "");
214
215 out.println("#define OW_WIREFORMAT_STACK_TRACE_MASK 0x00000001;");
216 out.println("#define OW_WIREFORMAT_TCP_NO_DELAY_MASK 0x00000002;");
217 out.println("#define OW_WIREFORMAT_CACHE_MASK 0x00000004;");
218 out.println("#define OW_WIREFORMAT_COMPRESSION_MASK 0x00000008;");
219
220 for (Iterator iterator = sortedClasses.iterator(); iterator.hasNext();) {
221 JClass jclass = (JClass)iterator.next();
222 String name = jclass.getSimpleName();
223 String type = ("ow_" + name).toUpperCase() + "_TYPE";
224 if (!isAbstract(jclass)) {
225 out.println("#define " + type + " " + getOpenWireOpCode(jclass));
226 }
227 }
228
229 out.println(" ");
230 out.println("apr_status_t ow_bitmarshall(ow_bit_buffer *buffer, ow_DataStructure *object);");
231 out.println("apr_status_t ow_marshall(ow_byte_buffer *buffer, ow_DataStructure *object);");
232 }
233
234 protected void generateFile(PrintWriter out) throws Exception {
235
236 String structName = jclass.getSimpleName();
237
238 out.println("");
239 out.println("typedef struct ow_" + structName + " {");
240
241 // This recusivly generates the field definitions of the class and it's
242 // supper classes.
243 generateFields(out, jclass);
244
245 out.println("");
246 out.println("} ow_" + structName + ";");
247 out.println("ow_" + structName + " *ow_" + structName + "_create(apr_pool_t *pool);");
248 out.println("ow_boolean ow_is_a_" + structName + "(ow_DataStructure *object);");
249
250 }
251
252 protected void generateTearDown(PrintWriter out) {
253 out.println("");
254 out.println("#ifdef __cplusplus");
255 out.println("}");
256 out.println("#endif");
257 out.println("");
258 out.println("#endif /* ! OW_COMMANDS_V" + openwireVersion + "_H */");
259 }
260 }