1 17 package org.apache.tools.ant.taskdefs.optional.metamata; 18 19 20 import java.io.BufferedReader ; 21 import java.io.IOException ; 22 import java.io.InputStream ; 23 import java.io.InputStreamReader ; 24 import java.io.OutputStream ; 25 import java.io.OutputStreamWriter ; 26 import java.text.DecimalFormat ; 27 import java.text.NumberFormat ; 28 import java.text.ParseException ; 29 import java.util.Date ; 30 import java.util.EmptyStackException ; 31 import java.util.Enumeration ; 32 import java.util.Stack ; 33 import java.util.Vector ; 34 import javax.xml.transform.OutputKeys ; 35 import javax.xml.transform.Transformer ; 36 import javax.xml.transform.TransformerFactory ; 37 import javax.xml.transform.sax.SAXTransformerFactory ; 38 import javax.xml.transform.sax.TransformerHandler ; 39 import javax.xml.transform.stream.StreamResult ; 40 import org.apache.tools.ant.BuildException; 41 import org.apache.tools.ant.Project; 42 import org.apache.tools.ant.Task; 43 import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; 44 import org.apache.tools.ant.util.DateUtils; 45 import org.xml.sax.Attributes ; 46 import org.xml.sax.SAXException ; 47 import org.xml.sax.helpers.AttributesImpl ; 48 49 59 public class MMetricsStreamHandler implements ExecuteStreamHandler { 60 61 62 private static final String CLASS = "class"; 63 64 65 private static final String PACKAGE = "package"; 66 67 68 private static final String FILE = "file"; 69 70 71 private static final String METHOD = "method"; 72 73 private static final String [] ATTRIBUTES = { 74 "name", "vg", "loc", "dit", "noa", "nrm", "nlm", "wmc", 75 "rfc", "dac", "fanout", "cbo", "lcom", "nocl"}; 76 77 78 private InputStream metricsOutput; 79 80 84 private OutputStream xmlOutputStream; 85 86 87 private TransformerHandler metricsHandler; 88 89 90 private Task task; 91 92 96 private Stack stack = new Stack (); 97 98 99 MMetricsStreamHandler(Task task, OutputStream xmlOut) { 100 this.task = task; 101 this.xmlOutputStream = xmlOut; 102 } 103 104 105 public void setProcessInputStream(OutputStream p1) throws IOException { 106 } 107 108 109 public void setProcessErrorStream(InputStream p1) throws IOException { 110 } 111 112 113 public void setProcessOutputStream(InputStream is) throws IOException { 114 metricsOutput = is; 115 } 116 117 public void start() throws IOException { 118 TransformerFactory factory = TransformerFactory.newInstance(); 121 if (!factory.getFeature(SAXTransformerFactory.FEATURE)) { 122 throw new IllegalStateException ("Invalid Transformer factory feature"); 123 } 124 try { 125 metricsHandler = ((SAXTransformerFactory ) factory).newTransformerHandler(); 126 metricsHandler.setResult(new StreamResult (new OutputStreamWriter (xmlOutputStream, "UTF-8"))); 127 Transformer transformer = metricsHandler.getTransformer(); 128 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 129 130 final Date now = new Date (); 132 metricsHandler.startDocument(); 133 AttributesImpl attr = new AttributesImpl (); 134 attr.addAttribute("", "company", "company", "CDATA", "metamata"); 135 attr.addAttribute("", "snapshot_created", "snapshot_created", "CDATA", 136 DateUtils.format(now, DateUtils.ISO8601_DATETIME_PATTERN)); 137 attr.addAttribute("", "program_start", "program_start", "CDATA", 140 DateUtils.format(new Date (), DateUtils.ISO8601_DATETIME_PATTERN)); 141 metricsHandler.startElement("", "metrics", "metrics", attr); 142 143 parseOutput(); 145 146 } catch (Exception e) { 147 throw new BuildException(e); 148 } 149 } 150 151 154 public void stop() { 155 try { 156 while (stack.size() > 0) { 159 ElementEntry elem = (ElementEntry) stack.pop(); 160 metricsHandler.endElement("", elem.getType(), elem.getType()); 161 } 162 metricsHandler.endElement("", "metrics", "metrics"); 164 metricsHandler.endDocument(); 166 } catch (SAXException e) { 167 e.printStackTrace(); 168 throw new IllegalStateException (e.getMessage()); 169 } 170 } 171 172 173 protected void parseOutput() throws IOException , SAXException { 174 BufferedReader br = new BufferedReader (new InputStreamReader (metricsOutput)); 175 String line = null; 176 while ((line = br.readLine()) != null) { 177 processLine(line); 178 } 179 } 180 181 186 protected void processLine(String line) throws SAXException { 187 if (line.startsWith("Construct\tV(G)\tLOC\tDIT\tNOA\tNRM\tNLM\tWMC\tRFC\tDAC\tFANOUT\tCBO\tLCOM\tNOCL")) { 188 return; 189 } 190 try { 191 MetricsElement elem = MetricsElement.parse(line); 192 startElement(elem); 193 } catch (ParseException e) { 194 task.log(line, Project.MSG_INFO); 197 } 198 } 199 200 207 protected void startElement(MetricsElement elem) throws SAXException { 208 int indent = elem.getIndent(); 211 if (stack.size() > 0) { 212 ElementEntry previous = (ElementEntry) stack.peek(); 213 try { 215 while (indent <= previous.getIndent() && stack.size() > 0) { 216 stack.pop(); 217 metricsHandler.endElement("", previous.getType(), previous.getType()); 218 previous = (ElementEntry) stack.peek(); 219 } 220 } catch (EmptyStackException ignored) { 221 } 222 } 223 224 String type = getConstructType(elem); 226 Attributes attrs = createAttributes(elem); 227 metricsHandler.startElement("", type, type, attrs); 228 229 stack.push(new ElementEntry(type, indent)); 231 } 232 233 241 protected String getConstructType(MetricsElement elem) { 242 if (elem.isCompilationUnit()) { 244 return FILE; 245 } 246 247 if (elem.isMethod()) { 249 return METHOD; 250 } 251 252 if (stack.size() == 0) { 254 return PACKAGE; 255 } 256 257 final ElementEntry previous = (ElementEntry) stack.peek(); 260 final String prevType = previous.getType(); 261 final int prevIndent = previous.getIndent(); 262 final int indent = elem.getIndent(); 263 if (prevType.equals(FILE) && indent > prevIndent) { 265 return CLASS; 266 } 267 268 if (prevType.equals(CLASS) && indent >= prevIndent) { 271 return CLASS; 272 } 273 274 return PACKAGE; 276 } 277 278 279 283 protected Attributes createAttributes(MetricsElement elem) { 284 AttributesImpl impl = new AttributesImpl (); 285 int i = 0; 286 String name = ATTRIBUTES[i++]; 287 impl.addAttribute("", name, name, "CDATA", elem.getName()); 288 Enumeration metrics = elem.getMetrics(); 289 for (; metrics.hasMoreElements(); i++) { 290 String value = (String ) metrics.nextElement(); 291 if (value.length() > 0) { 292 name = ATTRIBUTES[i]; 293 impl.addAttribute("", name, name, "CDATA", value); 294 } 295 } 296 return impl; 297 } 298 299 303 private static final class ElementEntry { 304 private String type; 305 private int indent; 306 307 ElementEntry(String type, int indent) { 308 this.type = type; 309 this.indent = indent; 310 } 311 312 public String getType() { 313 return type; 314 } 315 316 public int getIndent() { 317 return indent; 318 } 319 } 320 } 321 322 class MetricsElement { 323 324 private static final NumberFormat METAMATA_NF; 325 326 private static final NumberFormat NEUTRAL_NF; 327 328 static { 329 METAMATA_NF = NumberFormat.getInstance(); 330 METAMATA_NF.setMaximumFractionDigits(1); 331 NEUTRAL_NF = NumberFormat.getInstance(); 332 if (NEUTRAL_NF instanceof DecimalFormat ) { 333 ((DecimalFormat ) NEUTRAL_NF).applyPattern("###0.###;-###0.###"); 334 } 335 NEUTRAL_NF.setMaximumFractionDigits(1); 336 } 337 338 private int indent; 339 340 private String construct; 341 342 private Vector metrics; 343 344 MetricsElement(int indent, String construct, Vector metrics) { 345 this.indent = indent; 346 this.construct = construct; 347 this.metrics = metrics; 348 } 349 350 public int getIndent() { 351 return indent; 352 } 353 354 public String getName() { 355 return construct; 356 } 357 358 public Enumeration getMetrics() { 359 return metrics.elements(); 360 } 361 362 public boolean isCompilationUnit() { 363 return (construct.endsWith(".java") || construct.endsWith(".class")); 364 } 365 366 public boolean isMethod() { 367 return (construct.endsWith("(...)") || construct.endsWith("()")); 368 } 369 370 public static MetricsElement parse(String line) throws ParseException { 371 final Vector metrics = new Vector (); 372 int pos; 373 374 while ((pos = line.indexOf('\t')) != -1) { 377 String token = line.substring(0, pos); 378 383 metrics.addElement(token); 384 line = line.substring(pos + 1); 385 } 386 metrics.addElement(line); 387 388 if (metrics.size() != 14) { 390 throw new ParseException ("Could not parse the following line as " 391 + "a metrics: -->" + line + "<--", -1); 392 } 393 394 String name = (String ) metrics.elementAt(0); 399 metrics.removeElementAt(0); 400 int indent = 0; 401 pos = name.lastIndexOf('/'); 402 if (pos != -1) { 403 name = name.substring(pos + 1); 404 indent = pos + 1; } 406 return new MetricsElement(indent, name, metrics); 407 } 408 } 409 410 | Popular Tags |