1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.weaver.privilizer;
20
21 import java.io.InputStream;
22 import java.lang.annotation.ElementType;
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import org.apache.commons.weaver.model.ScanRequest;
27 import org.apache.commons.weaver.model.Scanner;
28 import org.apache.commons.weaver.model.WeavableClass;
29 import org.apache.commons.weaver.model.WeaveEnvironment;
30 import org.apache.commons.weaver.model.WeaveInterest;
31 import org.apache.commons.weaver.spi.Cleaner;
32 import org.objectweb.asm.ClassReader;
33 import org.objectweb.asm.ClassVisitor;
34
35
36
37
38 public class PrivilizerCleaner implements Cleaner {
39
40 @Override
41 public boolean clean(final WeaveEnvironment environment, final Scanner scanner) {
42 final Privilizer privilizer = new Privilizer(environment);
43
44 final List<String> toDelete = new ArrayList<>();
45
46 final ScanRequest scanRequest = new ScanRequest().add(WeaveInterest.of(Privilized.class, ElementType.TYPE));
47
48 environment.debug("Cleaning classes privilized with policy other than %s", privilizer.policy);
49 for (final WeavableClass<?> weavableClass : scanner.scan(scanRequest).getClasses().with(Privilized.class)) {
50 final Policy privilizedPolicy = Policy.valueOf(weavableClass.getAnnotation(Privilized.class).value());
51 if (privilizedPolicy == privilizer.policy) {
52 continue;
53 }
54 final String className = weavableClass.getTarget().getName();
55 environment.debug("Class %s privilized with %s; deleting.", className, privilizedPolicy);
56
57 try (InputStream bytecode = privilizer.env.getClassfile(className).getInputStream()) {
58 final ClassReader classReader = new ClassReader(bytecode);
59 classReader.accept(new ClassVisitor(Privilizer.ASM_VERSION) {
60 @Override
61 @SuppressWarnings("PMD.UseVarargs")
62 public void visit(final int version, final int access, final String name, final String signature,
63 final String superName, final String[] interfaces) {
64 toDelete.add(name);
65 }
66
67 @Override
68 public void visitInnerClass(final String name, final String outerName, final String innerName,
69 final int access) {
70 if (toDelete.contains(outerName)) {
71 toDelete.add(name);
72 }
73 }
74 }, ClassReader.SKIP_CODE + ClassReader.SKIP_DEBUG + ClassReader.SKIP_FRAMES);
75 } catch (final Exception e) {
76 throw new IllegalStateException(e);
77 }
78 }
79 boolean result = false;
80 for (final String className : toDelete) {
81 final String resourcePath = toResourcePath(className);
82 final boolean success = environment.deleteResource(resourcePath);
83 environment.debug("Deletion of resource %s was %ssuccessful.", resourcePath, success ? "" : "un");
84 result |= success;
85 }
86 return result;
87 }
88
89 private static String toResourcePath(final String className) {
90 return className.replace('.', '/') + ".class";
91 }
92
93 }