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     * 
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    }