Skip to content

Commit efb75c1

Browse files
committed
add parameter to allow analyzing jsp/xhtml files for public code use
1 parent a55922b commit efb75c1

File tree

5 files changed

+81
-5
lines changed

5 files changed

+81
-5
lines changed

src/main/java/dcd/DcdHelper.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,9 @@ static File unzipIntoTempDirectory(File file) throws IOException {
153153
final Enumeration<? extends ZipEntry> entries = zipFile.entries();
154154
while (entries.hasMoreElements() && !Thread.currentThread().isInterrupted()) {
155155
final ZipEntry zipEntry = entries.nextElement();
156-
if (zipEntry.getName().endsWith(".class") && !zipEntry.isDirectory()) {
156+
final boolean toBeCopied = zipEntry.getName().endsWith(".class")
157+
|| isViewFile(zipEntry.getName());
158+
if (toBeCopied && !zipEntry.isDirectory()) {
157159
final File tmpFile = new File(tmpDirectory, zipEntry.getName());
158160
if (!tmpFile.getParentFile().exists() && !tmpFile.getParentFile().mkdirs()) {
159161
throw new IOException(tmpFile.getParentFile() + " can't be created");
@@ -175,6 +177,10 @@ static File unzipIntoTempDirectory(File file) throws IOException {
175177
return tmpDirectory;
176178
}
177179

180+
static boolean isViewFile(String fileName) {
181+
return fileName.endsWith(".xhtml") || fileName.endsWith(".jsp");
182+
}
183+
178184
private static void copy(byte[] buffer, InputStream input, OutputStream output)
179185
throws IOException {
180186
int read = input.read(buffer);

src/main/java/dcd/DeadCodeDetector.java

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@
1919

2020
import java.io.File;
2121
import java.io.IOException;
22+
import java.nio.charset.StandardCharsets;
23+
import java.nio.file.Files;
2224
import java.util.Collections;
2325
import java.util.HashMap;
2426
import java.util.Iterator;
2527
import java.util.LinkedHashSet;
2628
import java.util.List;
2729
import java.util.Map;
2830
import java.util.Set;
31+
import java.util.concurrent.ConcurrentHashMap;
32+
import java.util.regex.Pattern;
2933

3034
import javax.xml.stream.XMLStreamException;
3135

@@ -147,6 +151,29 @@ private void launchAnalyze(String dir) throws IOException, XMLStreamException {
147151
}
148152
}
149153

154+
private void analyzeViewFiles(File dir, Map<String, Pattern> patternsByMethod)
155+
throws IOException {
156+
for (final File file : DcdHelper.listFiles(dir)) {
157+
if (isInterrupted()) {
158+
break;
159+
}
160+
if (file.isDirectory()) {
161+
analyzeViewFiles(file, patternsByMethod);
162+
} else if (DcdHelper.isViewFile(file.getName())) {
163+
final byte[] bytes = Files.readAllBytes(file.toPath());
164+
final String string = new String(bytes, StandardCharsets.UTF_8);
165+
for (final Map.Entry<String, Pattern> entry : patternsByMethod.entrySet()) {
166+
final Pattern pattern = entry.getValue();
167+
if (pattern.matcher(string).matches()) {
168+
final String method = entry.getKey();
169+
result.methodCalled(method);
170+
patternsByMethod.remove(method);
171+
}
172+
}
173+
}
174+
}
175+
}
176+
150177
private void analyzeDirectory(String dir, String packageName)
151178
throws IOException, XMLStreamException {
152179
final Set<String> classNameList = listClassesAndAnalyzeSubDirectories(dir, packageName);
@@ -226,11 +253,11 @@ private Set<String> listClassesAndAnalyzeSubDirectories(String dir, String packa
226253
if (isInterrupted()) {
227254
break;
228255
}
229-
final String name = packageName != null ? packageName + '.' + file.getName()
230-
: file.getName();
231-
if (file.isDirectory() && file.getName().indexOf('.') == -1) {
256+
final String fileName = file.getName();
257+
final String name = packageName != null ? packageName + '.' + fileName : fileName;
258+
if (file.isDirectory() && fileName.indexOf('.') == -1) {
232259
analyzeDirectory(dir, name);
233-
} else if (file.getName().endsWith(".class")) {
260+
} else if (fileName.endsWith(".class")) {
234261
classNameList.add(name.substring(0, name.length() - ".class".length()));
235262
}
236263
}
@@ -542,6 +569,18 @@ private void launchAllAnalyses() throws IOException, XMLStreamException {
542569
// analyse des classes du répertoire WEB-INF/classes du war
543570
launchAnalyze(tmpDirectory.getPath() + webInfClasses);
544571
}
572+
if (parameters.includesViewFiles() && currentStep == Step.PUBLIC_ANALYSIS) {
573+
final Set<String> allMethods = result.getAllMethods();
574+
final Map<String, Pattern> patternsByMethod = new ConcurrentHashMap<>();
575+
for (final String method : allMethods) {
576+
// regex to search with word boundaries, for less false negatives in view files
577+
final String regex = ".*\\b" + DcdHelper.getMethodName(method)
578+
+ "\\b.*";
579+
final Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
580+
patternsByMethod.put(method, pattern);
581+
}
582+
analyzeViewFiles(tmpDirectory, patternsByMethod);
583+
}
545584
} else {
546585
// analyse des classes du jar
547586
launchAnalyze(tmpDirectory.getPath());

src/main/java/dcd/Parameters.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public class Parameters {
4747
private static final String LOCAL_DEAD_CODE_KEY = "localDeadCode";
4848
private static final String INIT_DEAD_CODE_KEY = "initDeadCode";
4949
private static final String XML_REPORT_FILE_KEY = "xmlReportFile";
50+
private static final String INCLUDE_VIEW_FILES_KEY = "includeViewFiles";
5051
private static final String SEPARATORS = "[;,]";
5152
private final List<File> directories;
5253
private final List<Pattern> excludedClasses;
@@ -56,6 +57,7 @@ public class Parameters {
5657
private final boolean localDeadCode;
5758
private final boolean initDeadCode;
5859
private File xmlReportFile; // can be null
60+
private final boolean includeViewFiles;
5961

6062
/**
6163
* Constructeur.
@@ -84,6 +86,8 @@ public Parameters(Properties properties) {
8486
xmlReportFile = properties.getProperty(XML_REPORT_FILE_KEY) == null
8587
|| properties.getProperty(XML_REPORT_FILE_KEY).trim().isEmpty() ? null
8688
: new File(properties.getProperty(XML_REPORT_FILE_KEY));
89+
includeViewFiles = Boolean.valueOf(properties.getProperty(INCLUDE_VIEW_FILES_KEY,
90+
System.getProperty(INCLUDE_VIEW_FILES_KEY)));
8791
}
8892

8993
/**
@@ -115,6 +119,7 @@ public Parameters(List<File> directories, boolean publicDeadCode, boolean privat
115119
: Collections.<Pattern> emptyList();
116120
this.excludedMethods = excludedMethods != null ? excludedMethods
117121
: Collections.<Pattern> emptyList();
122+
this.includeViewFiles = Boolean.valueOf(System.getProperty(INCLUDE_VIEW_FILES_KEY));
118123
}
119124

120125
/**
@@ -131,6 +136,7 @@ public static Parameters createFromSystemProperties() {
131136
properties.put(LOCAL_DEAD_CODE_KEY, System.getProperty(LOCAL_DEAD_CODE_KEY));
132137
properties.put(INIT_DEAD_CODE_KEY, System.getProperty(INIT_DEAD_CODE_KEY));
133138
properties.put(XML_REPORT_FILE_KEY, System.getProperty(XML_REPORT_FILE_KEY));
139+
properties.put(INCLUDE_VIEW_FILES_KEY, System.getProperty(INCLUDE_VIEW_FILES_KEY));
134140
return new Parameters(properties);
135141
}
136142

@@ -313,6 +319,13 @@ public void setXmlReportFile(File xmlReporFile) {
313319
this.xmlReportFile = xmlReporFile;
314320
}
315321

322+
/**
323+
* @return includes jsp/xhtml files for public dead code analysis
324+
*/
325+
public boolean includesViewFiles() {
326+
return includeViewFiles;
327+
}
328+
316329
/**
317330
* @param xmlReportFileName Nom du fichier pour export xml ou null sinon
318331
*/

src/main/java/dcd/Report.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ void close(long durationMillis, int suspectCount, int analyzedClassCount, File x
123123

124124
void reportDeadCodeSuspects(boolean publicDeadCode, String asmClassName, Set<String> descs)
125125
throws XMLStreamException {
126+
if (descs.isEmpty()) {
127+
// analyzeViewFiles peut avoir laisser des listes vides
128+
return;
129+
}
126130
final String type = publicDeadCode ? "publicDeadCode" : "privateDeadCode";
127131
final String className = Type.getObjectType(asmClassName).getClassName();
128132
final String msg = (publicDeadCode ? "Public suspects in class "

src/main/java/dcd/Result.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,20 @@ private Set<String> getJavaMethods(String asmClassName) {
331331
return methods;
332332
}
333333

334+
Set<String> getAllMethods() {
335+
final Set<String> result = new HashSet<>();
336+
for (final Set<String> methods : methodsByClassMap.values()) {
337+
result.addAll(methods);
338+
}
339+
return result;
340+
}
341+
342+
void methodCalled(String methodKey) {
343+
for (final Set<String> methods : methodsByClassMap.values()) {
344+
methods.remove(methodKey);
345+
}
346+
}
347+
334348
void methodCalled(String className, String name, String desc) {
335349
methodCalled(className, name, desc, methodsByClassMap);
336350
}

0 commit comments

Comments
 (0)