3
3
import com .google .common .collect .ImmutableMap ;
4
4
import com .tngtech .archunit .base .DescribedPredicate ;
5
5
import com .tngtech .archunit .core .domain .JavaAccess ;
6
+ import com .tngtech .archunit .core .domain .JavaClass ;
6
7
import com .tngtech .archunit .lang .ArchRule ;
7
8
import com .tngtech .archunit .lang .syntax .ArchRuleDefinition ;
9
+ import de .tum .cit .ase .ares .api .architecturetest .java .FileHandlerConstants ;
10
+ import de .tum .cit .ase .ares .api .architecturetest .java .JavaSupportedArchitectureTestCase ;
8
11
9
12
import java .io .IOException ;
10
13
import java .nio .file .Files ;
11
14
import java .nio .file .Path ;
15
+ import java .nio .file .Paths ;
12
16
import java .util .HashSet ;
13
- import java .util .List ;
14
- import java .util .Optional ;
15
17
import java .util .Set ;
16
18
17
19
import static de .tum .cit .ase .ares .api .architecturetest .java .JavaSupportedArchitectureTestCase .FILESYSTEM_INTERACTION ;
20
+ import static de .tum .cit .ase .ares .api .architecturetest .java .JavaSupportedArchitectureTestCase .NETWORK_CONNECTION ;
18
21
19
22
/**
20
23
* This class runs the security rules on the architecture for the post-compile mode.
@@ -25,29 +28,12 @@ private JavaArchitectureTestCaseCollection() {
25
28
throw new IllegalArgumentException ("This class should not be instantiated" );
26
29
}
27
30
31
+ public static final String LOAD_FORBIDDEN_METHODS_FROM_FILE_FAILED = "Could not load the architecture rule file content" ;
28
32
/**
29
33
* Map to store the forbidden methods for the supported architectural test cases
30
34
*/
31
35
private static final ImmutableMap .Builder <String , Set <String >> FORBIDDEN_METHODS_FOR_SUPPORTED_ARCHITECTURAL_TEST_CASE = ImmutableMap .builder ();
32
36
33
- /**
34
- * Map to store the content of the architecture test case files
35
- */
36
- private static final ImmutableMap .Builder <String , String > ARCHITECTURAL_RULES_CONTENT_MAP = ImmutableMap .builder ();
37
-
38
- /**
39
- * The packages that should not be accessed by the student submission.
40
- */
41
- private static final List <String > BANNED_FILESYSTEM_ACCESS_PACKAGES = List .of (
42
- "java.nio.file" ,
43
- "java.util.prefs" ,
44
- "sun.print" ,
45
- "java.util.jar" ,
46
- "java.util.zip" ,
47
- "sun.awt.X11" ,
48
- "javax.imageio" ,
49
- "javax.sound.midi" ,
50
- "javax.swing.filechooser" );
51
37
52
38
/**
53
39
* Load pre file contents
@@ -57,14 +43,6 @@ public static void loadForbiddenMethodsFromFile(Path filePath, String key) throw
57
43
FORBIDDEN_METHODS_FOR_SUPPORTED_ARCHITECTURAL_TEST_CASE .put (key , content );
58
44
}
59
45
60
- /**
61
- * Load the content of the architecture test case files
62
- */
63
- public static void loadArchitectureRuleFileContent (Path filePath , String key ) throws IOException {
64
- String content = Files .readString (filePath );
65
- ARCHITECTURAL_RULES_CONTENT_MAP .put (key , content );
66
- }
67
-
68
46
/**
69
47
* Get the content of a file from the architectural rules storage
70
48
*/
@@ -75,23 +53,99 @@ public static Set<String> getForbiddenMethods(String key) {
75
53
/**
76
54
* Get the content of a file from the architectural rules storage
77
55
*/
78
- public static String getArchitectureRuleFileContent (String key ) {
79
- return ARCHITECTURAL_RULES_CONTENT_MAP . build () .get (key );
56
+ public static String getArchitectureRuleFileContent (String key ) throws IOException {
57
+ return Files . readString ( Paths .get ("src" , "main" , "resources" , "archunit" , "files" , "java" , "rules" , "%s.txt" . formatted ( key )) );
80
58
}
81
59
82
60
/**
83
61
* This method checks if any class in the given package accesses the file system.
84
62
*/
85
63
public static final ArchRule NO_CLASS_SHOULD_ACCESS_FILE_SYSTEM = ArchRuleDefinition .noClasses ()
86
64
.should (new TransitivelyAccessesMethodsCondition (new DescribedPredicate <>("accesses file system" ) {
65
+ private Set <String > forbiddenMethods ;
66
+
67
+ @ Override
68
+ public boolean test (JavaAccess <?> javaAccess ) {
69
+ if (forbiddenMethods == null ) {
70
+ try {
71
+ loadForbiddenMethodsFromFile (FileHandlerConstants .JAVA_FILESYSTEM_INTERACTION_METHODS , JavaSupportedArchitectureTestCase .FILESYSTEM_INTERACTION .name ());
72
+ } catch (IOException e ) {
73
+ throw new IllegalStateException (LOAD_FORBIDDEN_METHODS_FROM_FILE_FAILED , e );
74
+ }
75
+ forbiddenMethods = getForbiddenMethods (FILESYSTEM_INTERACTION .name ());
76
+ }
77
+
78
+ return forbiddenMethods .stream ().anyMatch (method -> javaAccess .getTarget ().getFullName ().startsWith (method ));
79
+ }
80
+ }));
81
+
82
+ /**
83
+ * This method checks if any class in the given package accesses the network.
84
+ */
85
+ public static final ArchRule NO_CLASSES_SHOULD_ACCESS_NETWORK = ArchRuleDefinition .noClasses ()
86
+ .should (new TransitivelyAccessesMethodsCondition (new DescribedPredicate <>("accesses network" ) {
87
+ private Set <String > forbiddenMethods ;
88
+
89
+ @ Override
90
+ public boolean test (JavaAccess <?> javaAccess ) {
91
+ if (forbiddenMethods == null ) {
92
+ try {
93
+ loadForbiddenMethodsFromFile (FileHandlerConstants .JAVA_NETWORK_ACCESS_METHODS , JavaSupportedArchitectureTestCase .NETWORK_CONNECTION .name ());
94
+ } catch (IOException e ) {
95
+ throw new IllegalStateException (LOAD_FORBIDDEN_METHODS_FROM_FILE_FAILED , e );
96
+ }
97
+ forbiddenMethods = getForbiddenMethods (NETWORK_CONNECTION .name ());
98
+ }
99
+
100
+ return forbiddenMethods .stream ().anyMatch (method -> javaAccess .getTarget ().getFullName ().startsWith (method ));
101
+ }
102
+ }));
103
+
104
+ /**
105
+ * This method checks if any class in the given package imports forbidden packages.
106
+ */
107
+ public static ArchRule noClassesShouldImportForbiddenPackages (Set <String > allowedPackages ) {
108
+ return ArchRuleDefinition .noClasses ()
109
+ .should ()
110
+ .transitivelyDependOnClassesThat (new DescribedPredicate <>("imports package" ) {
111
+ @ Override
112
+ public boolean test (JavaClass javaClass ) {
113
+ return !allowedPackages .contains (javaClass .getPackageName ());
114
+ }
115
+ });
116
+ }
117
+
118
+ /**
119
+ * This method checks if any class in the given package uses reflection.
120
+ */
121
+ public static final ArchRule NO_CLASSES_SHOULD_USE_REFLECTION = ArchRuleDefinition .noClasses ()
122
+ .should (new TransitivelyAccessesMethodsCondition (new DescribedPredicate <>("uses reflection" ) {
123
+ @ Override
124
+ public boolean test (JavaAccess <?> javaAccess ) {
125
+ return javaAccess .getTarget ().getFullName ().startsWith ("java.lang.reflect" )
126
+ || javaAccess .getTarget ().getFullName ().startsWith ("sun.reflect.misc" );
127
+ }
128
+ }));
129
+
130
+ /**
131
+ * This method checks if any class in the given package uses the command line.
132
+ */
133
+ public static final ArchRule NO_CLASSES_SHOULD_TERMINATE_JVM = ArchRuleDefinition .noClasses ()
134
+ .should (new TransitivelyAccessesMethodsCondition ((new DescribedPredicate <>("terminates JVM" ) {
135
+ private Set <String > forbiddenMethods ;
136
+
87
137
@ Override
88
138
public boolean test (JavaAccess <?> javaAccess ) {
89
- if (BANNED_FILESYSTEM_ACCESS_PACKAGES .stream ().anyMatch (p -> javaAccess .getTarget ().getFullName ().startsWith (p ))) {
90
- return true ;
139
+ if (forbiddenMethods == null ) {
140
+ try {
141
+ loadForbiddenMethodsFromFile (FileHandlerConstants .JAVA_JVM_TERMINATION_METHODS , "JVM_TERMINATION" );
142
+ } catch (IOException e ) {
143
+ throw new IllegalStateException (LOAD_FORBIDDEN_METHODS_FROM_FILE_FAILED , e );
144
+ }
145
+ forbiddenMethods = getForbiddenMethods ("JVM_TERMINATION" );
91
146
}
92
147
93
- Optional <Set <String >> bannedMethods = Optional .ofNullable (JavaArchitectureTestCaseCollection .getForbiddenMethods (FILESYSTEM_INTERACTION .name ()));
94
- return bannedMethods .map (strings -> strings .contains (javaAccess .getTarget ().getName ())).orElse (false );
148
+ return forbiddenMethods .stream ().anyMatch (method -> javaAccess .getTarget ().getFullName ().startsWith (method ));
95
149
}
96
- }, FILESYSTEM_INTERACTION ));
150
+ }) ));
97
151
}
0 commit comments