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 */
017package org.apache.activemq.openwire.tool;
018
019import java.io.File;
020import java.io.FileWriter;
021import java.io.PrintWriter;
022import java.util.ArrayList;
023import java.util.HashSet;
024import java.util.List;
025import java.util.Set;
026import org.apache.tools.ant.Project;
027import org.apache.tools.ant.taskdefs.FixCRLF;
028import org.codehaus.jam.JClass;
029import org.codehaus.jam.JProperty;
030import org.codehaus.jam.JamClassIterator;
031
032/**
033 * 
034 */
035public abstract class MultiSourceGenerator extends OpenWireGenerator {
036    protected Set<String> manuallyMaintainedClasses = new HashSet<String>();
037    protected File destDir;
038    protected File destFile;
039
040    protected JClass jclass;
041    protected JClass superclass;
042    protected String simpleName;
043    protected String className;
044    protected String baseClass;
045    protected StringBuffer buffer;
046
047    public MultiSourceGenerator() {
048        initialiseManuallyMaintainedClasses();
049    }
050
051    public Object run() {
052        if (destDir == null) {
053            throw new IllegalArgumentException("No destDir defined!");
054        }
055        System.out.println(getClass().getName() + " generating files in: " + destDir);
056        destDir.mkdirs();
057        buffer = new StringBuffer();
058
059        JamClassIterator iter = getClasses();
060        while (iter.hasNext()) {
061            try {
062                jclass = iter.nextClass();
063                if (isValidClass(jclass)) {
064                    processClass(jclass);
065                }
066            } catch (Exception e) {
067                System.err.println("Unable to process: " + jclass);
068                e.printStackTrace();
069            }
070        }
071        return null;
072    }
073
074    /**
075     * Returns all the valid properties available on the current class
076     */
077    public List<JProperty> getProperties() {
078        List<JProperty> answer = new ArrayList<JProperty>();
079        JProperty[] properties = jclass.getDeclaredProperties();
080        for (int i = 0; i < properties.length; i++) {
081            JProperty property = properties[i];
082            if (isValidProperty(property)) {
083                answer.add(property);
084            }
085        }
086        return answer;
087    }
088
089    protected boolean isValidClass(JClass jclass) {
090        if (jclass.getAnnotation("openwire:marshaller") == null) {
091            return false;
092        }
093        return !manuallyMaintainedClasses.contains(jclass.getSimpleName());
094    }
095
096    protected void processClass(JClass jclass) {
097        simpleName = jclass.getSimpleName();
098        superclass = jclass.getSuperclass();
099
100        System.out.println(getClass().getName() + " processing class: " + simpleName);
101
102        className = getClassName(jclass);
103
104        destFile = new File(destDir, className + filePostFix);
105
106        baseClass = getBaseClassName(jclass);
107
108        PrintWriter out = null;
109        try {
110            out = new PrintWriter(new FileWriter(destFile));
111            generateFile(out);
112        } catch (Exception e) {
113            throw new RuntimeException(e);
114        } finally {
115            if (out != null) {
116                out.close();
117            }
118        }
119
120        // Use the FixCRLF Ant Task to make sure the file has consistent
121        // newlines
122        // so that SVN does not complain on checkin.
123        Project project = new Project();
124        project.init();
125        FixCRLF fixCRLF = new FixCRLF();
126        fixCRLF.setProject(project);
127        fixCRLF.setSrcdir(destFile.getParentFile());
128        fixCRLF.setIncludes(destFile.getName());
129        fixCRLF.execute();
130    }
131
132    protected abstract void generateFile(PrintWriter out) throws Exception;
133
134    protected String getBaseClassName(JClass jclass) {
135        String answer = "BaseDataStructure";
136        if (superclass != null) {
137            String name = superclass.getSimpleName();
138            if (name != null && !name.equals("Object")) {
139                answer = name;
140            }
141        }
142        return answer;
143    }
144
145    protected String getClassName(JClass jclass) {
146        return jclass.getSimpleName();
147    }
148
149    public boolean isAbstractClass() {
150        return jclass != null && jclass.isAbstract();
151    }
152
153    public String getAbstractClassText() {
154        return isAbstractClass() ? "abstract " : "";
155    }
156
157    public boolean isMarshallerAware() {
158        return isMarshallAware(jclass);
159    }
160
161    protected void initialiseManuallyMaintainedClasses() {
162        String[] names = {
163            "ActiveMQDestination", "ActiveMQTempDestination", "ActiveMQQueue", "ActiveMQTopic", "ActiveMQTempQueue", "ActiveMQTempTopic", "BaseCommand", "ActiveMQMessage", "ActiveMQTextMessage",
164            "ActiveMQMapMessage", "ActiveMQBytesMessage", "ActiveMQStreamMessage", "ActiveMQBlobMessage", "DataStructureSupport", "WireFormatInfo", "ActiveMQObjectMessage"
165        };
166
167        for (int i = 0; i < names.length; i++) {
168            manuallyMaintainedClasses.add(names[i]);
169        }
170    }
171
172    public String getBaseClass() {
173        return baseClass;
174    }
175
176    public void setBaseClass(String baseClass) {
177        this.baseClass = baseClass;
178    }
179
180    public String getClassName() {
181        return className;
182    }
183
184    public void setClassName(String className) {
185        this.className = className;
186    }
187
188    public File getDestDir() {
189        return destDir;
190    }
191
192    public void setDestDir(File destDir) {
193        this.destDir = destDir;
194    }
195
196    public File getDestFile() {
197        return destFile;
198    }
199
200    public void setDestFile(File destFile) {
201        this.destFile = destFile;
202    }
203
204    public JClass getJclass() {
205        return jclass;
206    }
207
208    public void setJclass(JClass jclass) {
209        this.jclass = jclass;
210    }
211
212    public Set<String> getManuallyMaintainedClasses() {
213        return manuallyMaintainedClasses;
214    }
215
216    public void setManuallyMaintainedClasses(Set<String> manuallyMaintainedClasses) {
217        this.manuallyMaintainedClasses = manuallyMaintainedClasses;
218    }
219
220    public String getSimpleName() {
221        return simpleName;
222    }
223
224    public void setSimpleName(String simpleName) {
225        this.simpleName = simpleName;
226    }
227
228    public JClass getSuperclass() {
229        return superclass;
230    }
231
232    public void setSuperclass(JClass superclass) {
233        this.superclass = superclass;
234    }
235
236}