blob: e2a89b7deaa790dfd2b75c75dadc9614569dcb36 [file] [log] [blame]
Brian O'Connorbe95f682016-05-18 15:40:19 -07001/*
2 * Copyright 2016-present Open Networking Laboratory
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 */
16package org.onosproject.checkstyle;
17
18import com.google.common.io.ByteStreams;
19import com.puppycrawl.tools.checkstyle.Checker;
20import com.puppycrawl.tools.checkstyle.ConfigurationLoader;
21import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
22import com.puppycrawl.tools.checkstyle.PropertiesExpander;
23import com.puppycrawl.tools.checkstyle.api.AuditEvent;
24import com.puppycrawl.tools.checkstyle.api.AuditListener;
25import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
26import com.puppycrawl.tools.checkstyle.api.Configuration;
27
28import java.io.File;
29import java.io.IOException;
30import java.net.Socket;
31import java.util.List;
32import java.util.concurrent.CountDownLatch;
33import java.util.stream.Collectors;
34import java.util.stream.Stream;
35
Brian O'Connorfc247f42016-05-23 15:25:34 -070036import static com.google.common.base.Strings.isNullOrEmpty;
37
Brian O'Connorbe95f682016-05-18 15:40:19 -070038public class CheckstyleRunner {
39
40 private final Configuration config;
41
42 public CheckstyleRunner(String configLocation, String suppressionLocation)
43 throws CheckstyleException {
44 // create a configuration
45 DefaultConfiguration config = (DefaultConfiguration) ConfigurationLoader.loadConfiguration(
46 configLocation, new PropertiesExpander(System.getProperties()));
47
48 // add the suppression file to the configuration
49 DefaultConfiguration suppressions = new DefaultConfiguration("SuppressionFilter");
50 suppressions.addAttribute("file", suppressionLocation);
51 config.addChild(suppressions);
52
53 this.config = config;
54 }
55
56 public Runnable checkClass(Socket socket) {
57 return () -> {
58 try {
59 String input = new String(ByteStreams.toByteArray(socket.getInputStream()));
60 String output = checkClass(input);
61 socket.getOutputStream().write(output.getBytes());
62 socket.getOutputStream().flush();
63 socket.close();
64 } catch (IOException e) {
65 e.printStackTrace();
66 } catch (CheckstyleException e) {
67 e.printStackTrace();
68 } catch (InterruptedException e) {
69 e.printStackTrace();
70 }
71 };
72 }
73
74 public String checkClass(String input) throws CheckstyleException, InterruptedException {
Brian O'Connorfc247f42016-05-23 15:25:34 -070075 String[] split = input.split("\n", 3);
76 if (split.length < 3 || split[2].length() == 0) {
Brian O'Connorbe95f682016-05-18 15:40:19 -070077 return "";
78 }
Brian O'Connorfc247f42016-05-23 15:25:34 -070079 String project = split[0];
80 String baseDir = split[1];
81 String files = split[2];
Brian O'Connorbe95f682016-05-18 15:40:19 -070082
83 // create a listener for output
84 StringAuditor listener = new StringAuditor();
Brian O'Connorfc247f42016-05-23 15:25:34 -070085 listener.setProjectName(project);
86 listener.setBaseDir(baseDir);
Brian O'Connorbe95f682016-05-18 15:40:19 -070087
88 // create Checker object and run it
89 final Checker checker = new Checker();
90 final ClassLoader moduleClassLoader = Checker.class.getClassLoader();
91 checker.setModuleClassLoader(moduleClassLoader);
92
93 try {
94
95 checker.configure(config);
96 checker.addListener(listener);
97
98 // run Checker
99 List<File> fileList = Stream.of(files.split("\n"))
100 .map(File::new)
101 .collect(Collectors.toList());
102 int errorCounter = checker.process(fileList);
103 if (errorCounter > 0) {
104 listener.append("CHECKSTYLE ERROR\n");
105 }
106 } finally {
107 checker.destroy();
108 }
109
110 return listener.getAudit();
111 }
112}
113
114class StringAuditor implements AuditListener {
115
116 private CountDownLatch finishedLatch = new CountDownLatch(1);
117 private StringBuilder output = new StringBuilder();
Brian O'Connorfc247f42016-05-23 15:25:34 -0700118 private String baseDir = "";
119 private String project = "";
Brian O'Connorbe95f682016-05-18 15:40:19 -0700120
Brian O'Connorfc247f42016-05-23 15:25:34 -0700121 public void setBaseDir(String base) {
122 this.baseDir = base;
123 }
124
125 public void setProjectName(String projectName) {
126 this.project = projectName;
Brian O'Connorbe95f682016-05-18 15:40:19 -0700127 }
128
129 public void append(String s) {
130 output.append(s);
131 }
132
133 public String getAudit() throws InterruptedException {
134 finishedLatch.await();
135 return output.toString();
136 }
137
138 @Override
139 public void auditStarted(AuditEvent evt) {
140
141 }
142
143 @Override
144 public void auditFinished(AuditEvent evt) {
145 finishedLatch.countDown();
146 }
147
148 @Override
149 public void fileStarted(AuditEvent evt) {
150
151 }
152
153 @Override
154 public void fileFinished(AuditEvent evt) {
155
156 }
157
158 @Override
159 public void addError(AuditEvent evt) {
160 switch (evt.getSeverityLevel()) {
161 case ERROR:
162 String fileName = evt.getFileName();
Brian O'Connorfc247f42016-05-23 15:25:34 -0700163 if (!isNullOrEmpty(baseDir)) {
164 int index = fileName.indexOf(baseDir);
165 if (index >= 0) {
166 fileName = fileName.substring(index + baseDir.length() + 1);
167 if (!isNullOrEmpty(project)) {
168 output.append(project).append(':');
169 }
170 }
Brian O'Connorbe95f682016-05-18 15:40:19 -0700171 }
172 output.append(fileName).append(':').append(evt.getLine());
173 if (evt.getColumn() > 0) {
174 output.append(':').append(evt.getColumn());
175 }
176 output.append(": ").append(evt.getMessage());
177 output.append('\n');
178 break;
179 case IGNORE:
180 case INFO:
181 case WARNING:
182 default:
183 break;
184 }
185 }
186
187 @Override
188 public void addException(AuditEvent evt, Throwable throwable) {
189 addError(evt);
190 output.append(throwable.getMessage());
191 }
192}