blob: 1768e16df9713a31e1a6d87e5d471a5c49a643e0 [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
36public class CheckstyleRunner {
37
38 private final Configuration config;
39
40 public CheckstyleRunner(String configLocation, String suppressionLocation)
41 throws CheckstyleException {
42 // create a configuration
43 DefaultConfiguration config = (DefaultConfiguration) ConfigurationLoader.loadConfiguration(
44 configLocation, new PropertiesExpander(System.getProperties()));
45
46 // add the suppression file to the configuration
47 DefaultConfiguration suppressions = new DefaultConfiguration("SuppressionFilter");
48 suppressions.addAttribute("file", suppressionLocation);
49 config.addChild(suppressions);
50
51 this.config = config;
52 }
53
54 public Runnable checkClass(Socket socket) {
55 return () -> {
56 try {
57 String input = new String(ByteStreams.toByteArray(socket.getInputStream()));
58 String output = checkClass(input);
59 socket.getOutputStream().write(output.getBytes());
60 socket.getOutputStream().flush();
61 socket.close();
62 } catch (IOException e) {
63 e.printStackTrace();
64 } catch (CheckstyleException e) {
65 e.printStackTrace();
66 } catch (InterruptedException e) {
67 e.printStackTrace();
68 }
69 };
70 }
71
72 public String checkClass(String input) throws CheckstyleException, InterruptedException {
73 String[] split = input.split("\n", 2);
74 if (split.length < 2 || split[1].length() == 0) {
75 return "";
76 }
77 String base = split[0];
78 String files = split[1];
79
80 // create a listener for output
81 StringAuditor listener = new StringAuditor();
82 listener.setBase(base);
83
84 // create Checker object and run it
85 final Checker checker = new Checker();
86 final ClassLoader moduleClassLoader = Checker.class.getClassLoader();
87 checker.setModuleClassLoader(moduleClassLoader);
88
89 try {
90
91 checker.configure(config);
92 checker.addListener(listener);
93
94 // run Checker
95 List<File> fileList = Stream.of(files.split("\n"))
96 .map(File::new)
97 .collect(Collectors.toList());
98 int errorCounter = checker.process(fileList);
99 if (errorCounter > 0) {
100 listener.append("CHECKSTYLE ERROR\n");
101 }
102 } finally {
103 checker.destroy();
104 }
105
106 return listener.getAudit();
107 }
108}
109
110class StringAuditor implements AuditListener {
111
112 private CountDownLatch finishedLatch = new CountDownLatch(1);
113 private StringBuilder output = new StringBuilder();
114 private String base = "";
115
116 public void setBase(String base) {
117 this.base = base;
118 }
119
120 public void append(String s) {
121 output.append(s);
122 }
123
124 public String getAudit() throws InterruptedException {
125 finishedLatch.await();
126 return output.toString();
127 }
128
129 @Override
130 public void auditStarted(AuditEvent evt) {
131
132 }
133
134 @Override
135 public void auditFinished(AuditEvent evt) {
136 finishedLatch.countDown();
137 }
138
139 @Override
140 public void fileStarted(AuditEvent evt) {
141
142 }
143
144 @Override
145 public void fileFinished(AuditEvent evt) {
146
147 }
148
149 @Override
150 public void addError(AuditEvent evt) {
151 switch (evt.getSeverityLevel()) {
152 case ERROR:
153 String fileName = evt.getFileName();
154 int index = fileName.indexOf(base);
155 if (index >= 0) {
156 fileName = fileName.substring(index + base.length() + 1);
157 }
158 output.append(fileName).append(':').append(evt.getLine());
159 if (evt.getColumn() > 0) {
160 output.append(':').append(evt.getColumn());
161 }
162 output.append(": ").append(evt.getMessage());
163 output.append('\n');
164 break;
165 case IGNORE:
166 case INFO:
167 case WARNING:
168 default:
169 break;
170 }
171 }
172
173 @Override
174 public void addException(AuditEvent evt, Throwable throwable) {
175 addError(evt);
176 output.append(throwable.getMessage());
177 }
178}