View Javadoc

1   /*
2    * Jour - bytecode instrumentation library
3    *
4    * Copyright (C) 2007 Vlad Skarzhevskyy
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Library General Public
8    * License as published by the Free Software Foundation; either
9    * version 2 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Library General Public License for more details.
15   *
16   * You should have received a copy of the GNU Library General Public
17   * License along with this library; if not, write to the
18   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19   * Boston, MA  02111-1307, USA.
20   * 
21   * @version $Id: Generator.java 67 2007-10-17 08:55:14Z vlads $
22   * 
23   */
24  package net.sf.jour.signature;
25  
26  import java.io.File;
27  import java.io.IOException;
28  import java.util.Collections;
29  import java.util.Comparator;
30  import java.util.Enumeration;
31  import java.util.HashSet;
32  import java.util.Iterator;
33  import java.util.List;
34  import java.util.Properties;
35  import java.util.Set;
36  import java.util.StringTokenizer;
37  import java.util.Vector;
38  
39  import javassist.ClassPool;
40  import javassist.CtClass;
41  import javassist.NotFoundException;
42  
43  import net.sf.jour.log.Logger;
44  import net.sf.jour.processor.DirectoryInputSource;
45  import net.sf.jour.processor.Entry;
46  import net.sf.jour.processor.EntryHelper;
47  import net.sf.jour.processor.InputSource;
48  import net.sf.jour.processor.JarFileInputSource;
49  
50  /**
51   * @author vlads
52   * 
53   */
54  public class Generator {
55  
56  	protected static final Logger log = Logger.getLogger();
57  
58  	private boolean useSystemClassPath = false;
59  
60  	private String supportingJars;
61  
62  	private String sources;
63  
64  	private String packages;
65  
66  	private String reportFile;
67  
68  	private String filterLevel;
69  
70  	private Set packageSet = new HashSet();
71  
72  	private List classNames = new Vector();
73  
74  	public Generator(Properties properties) {
75  		this(properties.getProperty("src"), properties.getProperty("packages"), properties.getProperty("dst"),
76  				properties.getProperty("level"));
77  		this.useSystemClassPath = "true".equals(properties.getProperty("systempath"));
78  		this.supportingJars = properties.getProperty("jars");
79  		this.filterLevel = properties.getProperty("level");
80  	}
81  
82  	public Generator(String sources, String packages, String reportFile, String filterLevel) {
83  		super();
84  		this.sources = sources;
85  		this.packages = packages;
86  		this.reportFile = reportFile;
87  		this.filterLevel = filterLevel;
88  
89  		if (reportFile == null) {
90  			this.reportFile = "api-signature.xml";
91  		}
92  		if (packages != null) {
93  			StringTokenizer st = new StringTokenizer(packages, ";");
94  			if (st.hasMoreTokens()) {
95  				while (st.hasMoreTokens()) {
96  					packageSet.add(st.nextToken());
97  				}
98  			} else {
99  				packageSet.add(packages);
100 			}
101 		}
102 	}
103 
104 	private boolean isSelectedPackage(String className) {
105 		if (packages == null) {
106 			return true;
107 		}
108 		StringBuffer packageName = new StringBuffer();
109 		StringTokenizer st = new StringTokenizer(className, ".");
110 		while (st.hasMoreTokens()) {
111 			if (packageName.length() > 0) {
112 				packageName.append(".");
113 			}
114 			packageName.append(st.nextToken());
115 			if (packageSet.contains(packageName.toString())) {
116 				return true;
117 			}
118 		}
119 		return false;
120 	}
121 
122 	public void process() throws IOException, NotFoundException {
123 
124 		File input = new File(sources).getCanonicalFile();
125 
126 		InputSource inputSource;
127 		if (input.isDirectory()) {
128 			inputSource = new DirectoryInputSource(input);
129 		} else {
130 			inputSource = new JarFileInputSource(input);
131 		}
132 
133 		ClassPool classPool = new ClassPool();
134 		classPool.appendPathList(input.getAbsolutePath());
135 		if (this.supportingJars != null) {
136 			classPool.appendPathList(this.supportingJars);
137 		}
138 		if (this.useSystemClassPath) {
139 			classPool.appendSystemPath();
140 		}
141 
142 		List classes = new Vector();
143 
144 		int countEntry = 0;
145 
146 		APIFilter filter = new APIFilter(filterLevel);
147 
148 		try {
149 
150 			for (Enumeration en = inputSource.getEntries(); en.hasMoreElements();) {
151 				Entry entry = (Entry) en.nextElement();
152 				if (!entry.isClass()) {
153 					continue;
154 				}
155 				String className = EntryHelper.getClassName(entry);
156 				if (!isSelectedPackage(className)) {
157 					continue;
158 				}
159 
160 				log.debug(entry.getName());
161 				countEntry++;
162 				CtClass klass = classPool.get(className);
163 				if (filter.isAPIClass(klass)) {
164 					classes.add(klass);
165 					classNames.add(className);
166 				}
167 			}
168 		} finally {
169 			inputSource.close();
170 		}
171 		log.debug("countEntry   " + countEntry);
172 
173 		Collections.sort(classes, new ClassSortComparator());
174 
175 		ExportXML.export(reportFile, classes, filter);
176 
177 	}
178 
179 	private static class ClassSortComparator implements Comparator {
180 
181 		public int compare(Object arg0, Object arg1) {
182 			return ((CtClass) (arg0)).getName().compareTo(((CtClass) (arg1)).getName());
183 		}
184 
185 	}
186 
187 	public void process(ClassPool classPool, List processClassNames) throws IOException, NotFoundException {
188 		APIFilter filter = new APIFilter(filterLevel);
189 		List classes = new Vector();
190 		for (Iterator iterator = processClassNames.iterator(); iterator.hasNext();) {
191 			String className = (String) iterator.next();
192 			CtClass klass = classPool.get(className);
193 			if (filter.isAPIClass(klass)) {
194 				classes.add(klass);
195 				classNames.add(className);
196 			}
197 		}
198 		ExportXML.export(reportFile, classes, filter);
199 	}
200 
201 	public List getClassNames() {
202 		return this.classNames;
203 	}
204 
205 	public String getReportFile() {
206 		return reportFile;
207 	}
208 
209 	/**
210 	 * @return the useSystemClassPath
211 	 */
212 	public boolean isUseSystemClassPath() {
213 		return useSystemClassPath;
214 	}
215 
216 	/**
217 	 * @param useSystemClassPath
218 	 *            the useSystemClassPath to set
219 	 */
220 	public void setUseSystemClassPath(boolean useSystemClassPath) {
221 		this.useSystemClassPath = useSystemClassPath;
222 	}
223 
224 }