source: other-projects/trunk/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/optional/metamata/MAuditStreamHandler.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 8.5 KB
Line 
1/*
2 * Copyright 2001-2002,2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17package org.apache.tools.ant.taskdefs.optional.metamata;
18
19import java.io.BufferedReader;
20import java.io.IOException;
21import java.io.InputStream;
22import java.io.InputStreamReader;
23import java.io.OutputStream;
24import java.util.Date;
25import java.util.Enumeration;
26import java.util.Hashtable;
27import java.util.Vector;
28import javax.xml.parsers.DocumentBuilder;
29import javax.xml.parsers.DocumentBuilderFactory;
30import org.apache.tools.ant.BuildException;
31import org.apache.tools.ant.Project;
32import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
33import org.apache.tools.ant.taskdefs.LogOutputStream;
34import org.apache.tools.ant.taskdefs.StreamPumper;
35import org.apache.tools.ant.util.DOMElementWriter;
36import org.apache.tools.ant.util.DateUtils;
37import org.w3c.dom.Document;
38import org.w3c.dom.Element;
39
40/**
41 * This is a very bad stream handler for the MAudit task.
42 * All report to stdout that does not match a specific report pattern is dumped
43 * to the Ant output as warn level. The report that match the pattern is stored
44 * in a map with the key being the filepath that caused the error report.
45 * <p>
46 * The limitation with the choosen implementation is clear:
47 * <ul>
48 * <li>it does not handle multiline report( message that has \n ). the part until
49 * the \n will be stored and the other part (which will not match the pattern)
50 * will go to Ant output in Warn level.
51 * <li>it does not report error that goes to stderr.
52 * </ul>
53 *
54 */
55class MAuditStreamHandler implements ExecuteStreamHandler {
56
57 /** parent task */
58 private MAudit task;
59
60 /** reader for stdout */
61 private BufferedReader br;
62
63 /**
64 * this is where the XML output will go, should mostly be a file
65 * the caller is responsible for flushing and closing this stream
66 */
67 private OutputStream xmlOut = null;
68
69 /** error stream, might be useful to spit out error messages */
70 private OutputStream errStream;
71
72 /** thread pumping out error stream */
73 private Thread errThread;
74
75 /**
76 * the multimap. The key in the map is the filepath that caused the audit
77 * error and the value is a vector of MAudit.Violation entries.
78 */
79 private Hashtable auditedFiles = new Hashtable();
80
81 /** program start timestamp for reporting purpose */
82 private Date program_start;
83
84 MAuditStreamHandler(MAudit task, OutputStream xmlOut) {
85 this.task = task;
86 this.xmlOut = xmlOut;
87 }
88
89 /** Ignore. */
90 public void setProcessInputStream(OutputStream os) {
91 }
92
93 /** Ignore. */
94 public void setProcessErrorStream(InputStream is) {
95 errStream = new LogOutputStream(task, Project.MSG_ERR);
96 errThread = createPump(is, errStream);
97 }
98
99 /** Set the inputstream */
100 public void setProcessOutputStream(InputStream is) throws IOException {
101 br = new BufferedReader(new InputStreamReader(is));
102 }
103
104 /** Invokes parseOutput. This will block until the end :-(*/
105 public void start() throws IOException {
106 program_start = new Date();
107 errThread.start();
108 parseOutput(br);
109 }
110
111 /**
112 * Pretty dangerous business here. It serializes what was extracted from
113 * the MAudit output and write it to the output.
114 */
115 public void stop() {
116 // make sure to flush err stream
117 try {
118 errThread.join();
119 } catch (InterruptedException e) {
120 }
121 try {
122 errStream.flush();
123 } catch (IOException e) {
124 }
125 // serialize the content as XML, move this to another method
126 // this is the only code that could be needed to be overriden
127 Document doc = getDocumentBuilder().newDocument();
128 Element rootElement = doc.createElement("classes");
129 Enumeration keys = auditedFiles.keys();
130 Hashtable filemapping = task.getFileMapping();
131 final Date now = new Date();
132 rootElement.setAttribute("snapshot_created",
133 DateUtils.format(now, DateUtils.ISO8601_DATETIME_PATTERN));
134 rootElement.setAttribute("elapsed_time",
135 String.valueOf(now.getTime() - program_start.getTime()));
136 rootElement.setAttribute("program_start",
137 DateUtils.format(now, DateUtils.ISO8601_DATETIME_PATTERN));
138 rootElement.setAttribute("audited",
139 String.valueOf(filemapping.size()));
140 rootElement.setAttribute("reported",
141 String.valueOf(auditedFiles.size()));
142 int errors = 0;
143 while (keys.hasMoreElements()) {
144 String filepath = (String) keys.nextElement();
145 Vector v = (Vector) auditedFiles.get(filepath);
146 String fullclassname = (String) filemapping.get(filepath);
147 if (fullclassname == null) {
148 task.getProject().log("Could not find class mapping for "
149 + filepath, Project.MSG_WARN);
150 continue;
151 }
152 int pos = fullclassname.lastIndexOf('.');
153 String pkg = (pos == -1) ? "" : fullclassname.substring(0, pos);
154 String clazzname = (pos == -1) ? fullclassname : fullclassname.substring(pos + 1);
155 Element clazz = doc.createElement("class");
156 clazz.setAttribute("package", pkg);
157 clazz.setAttribute("name", clazzname);
158 final int violationCount = v.size();
159 clazz.setAttribute("violations", String.valueOf(violationCount));
160 errors += violationCount;
161 for (int i = 0; i < violationCount; i++) {
162 MAuditParser.Violation violation = (MAuditParser.Violation) v.elementAt(i);
163 Element error = doc.createElement("violation");
164 error.setAttribute("line", violation.line);
165 error.setAttribute("message", violation.error);
166 clazz.appendChild(error);
167 }
168 rootElement.appendChild(clazz);
169 }
170 rootElement.setAttribute("violations", String.valueOf(errors));
171
172 // now write it to the outputstream, not very nice code
173 DOMElementWriter domWriter = new DOMElementWriter();
174 try {
175 domWriter.write(rootElement, xmlOut);
176 } catch (IOException e) {
177 throw new BuildException(e);
178 }
179 }
180
181 protected static DocumentBuilder getDocumentBuilder() {
182 try {
183 return DocumentBuilderFactory.newInstance().newDocumentBuilder();
184 } catch (Exception exc) {
185 throw new ExceptionInInitializerError(exc);
186 }
187 }
188
189 /**
190 * Creates a stream pumper to copy the given input stream to the given output stream.
191 */
192 protected Thread createPump(InputStream is, OutputStream os) {
193 final Thread result = new Thread(new StreamPumper(is, os));
194 result.setDaemon(true);
195 return result;
196 }
197
198
199 /** read each line and process it */
200 protected void parseOutput(BufferedReader br) throws IOException {
201 String line = null;
202 final MAuditParser parser = new MAuditParser();
203 while ((line = br.readLine()) != null) {
204 final MAuditParser.Violation violation = parser.parseLine(line);
205 if (violation != null) {
206 addViolation(violation.file, violation);
207 } else {
208 // this doesn't match..report it as info, it could be
209 // either the copyright, summary or a multiline message (damn !)
210 task.log(line, Project.MSG_INFO);
211 }
212 }
213 }
214
215 /** add a violation entry for the file */
216 private void addViolation(String file, MAuditParser.Violation entry) {
217 Vector violations = (Vector) auditedFiles.get(file);
218 // if there is no decl for this file yet, create it.
219 if (violations == null) {
220 violations = new Vector();
221 auditedFiles.put(file, violations);
222 }
223 violations.addElement(entry);
224 }
225
226}
Note: See TracBrowser for help on using the repository browser.