3 import iotchecker.qual.*;
5 import org.checkerframework.common.basetype.BaseTypeChecker;
6 import org.checkerframework.common.basetype.BaseTypeVisitor;
7 import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
8 import org.checkerframework.framework.source.Result;
9 import org.checkerframework.framework.type.AnnotatedTypeMirror;
10 import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
11 import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
12 import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
13 import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
14 import org.checkerframework.framework.type.AnnotatedTypeParameterBounds;
15 import org.checkerframework.framework.type.AnnotatedTypeFactory;
16 import org.checkerframework.framework.util.AnnotatedTypes;
17 import org.checkerframework.javacutil.AnnotationUtils;
18 import org.checkerframework.javacutil.ElementUtils;
19 import org.checkerframework.javacutil.Pair;
20 import org.checkerframework.javacutil.TreeUtils;
21 import org.checkerframework.javacutil.InternalUtils;
22 import org.checkerframework.dataflow.qual.Pure;
23 import org.checkerframework.dataflow.util.PurityChecker;
24 import org.checkerframework.dataflow.util.PurityChecker.PurityResult;
25 import org.checkerframework.dataflow.util.PurityUtils;
26 import org.checkerframework.framework.qual.FieldIsExpression;
28 import java.util.ArrayList;
29 import java.util.List;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.ArrayList;
34 import java.util.LinkedList;
36 import java.util.Iterator;
37 import java.util.HashSet;
38 import java.util.Arrays;
39 import java.util.Collection;
40 import java.lang.annotation.Annotation;
42 import javax.lang.model.element.AnnotationMirror;
43 import javax.lang.model.element.Element;
44 import javax.lang.model.element.ExecutableElement;
45 import javax.lang.model.element.TypeElement;
46 import javax.lang.model.type.DeclaredType;
47 import javax.lang.model.type.PrimitiveType;
48 import javax.lang.model.type.TypeKind;
49 import javax.lang.model.type.TypeMirror;
50 import javax.lang.model.util.SimpleElementVisitor7;
51 import javax.lang.model.util.SimpleTypeVisitor7;
52 import javax.lang.model.element.Modifier;
53 import javax.tools.Diagnostic.Kind;
55 import com.sun.source.tree.NewArrayTree;
56 import com.sun.source.tree.NewClassTree;
57 import com.sun.source.tree.MethodTree;
58 import com.sun.source.tree.AssignmentTree;
59 import com.sun.source.tree.ClassTree;
60 import com.sun.source.tree.ExpressionTree;
61 import com.sun.source.tree.MethodInvocationTree;
62 import com.sun.source.tree.Tree;
63 import com.sun.source.tree.TypeCastTree;
64 import com.sun.source.tree.VariableTree;
65 import com.sun.source.tree.LambdaExpressionTree;
66 import com.sun.source.tree.ReturnTree;
68 import java.io.Serializable;
69 import java.lang.reflect.*;
71 import java.rmi.Remote;
72 import java.rmi.server.UnicastRemoteObject;
74 /** Class IoTJavaVisitor is a class that extends
75 * BaseTypeVisitor. The purpose of this class is to
76 * annotate variables/objects with the right annotations,
77 * i.e. Normal, LocalRemote, NonLocalRemote, or CanBeRemote
79 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
80 * @author Bin Xu <xub3 @ uci.edu>
84 public final class IoTJavaVisitor extends BaseTypeVisitor<BaseAnnotatedTypeFactory> {
86 public IoTJavaVisitor(BaseTypeChecker checker) {
92 * This visitVariable() method is taken directly from BaseTypeVisitor
94 * We need to override the checkArguments() to not complain about the switch
95 * from @LocalRemote to @NonLocalRemote.
98 public Void visitVariable(VariableTree node, Void p) {
99 Pair<Tree, AnnotatedTypeMirror> preAssCtxt = visitorState.getAssignmentContext();
100 visitorState.setAssignmentContext(Pair.of((Tree) node, atypeFactory.getAnnotatedType(node)));
103 // Check and reject any existence/declaration of Java Reflection and Java Networking
104 checkIfJavaReflection(node);
105 checkIfJavaNetworking(node);
109 visitorState.setAssignmentContext(preAssCtxt);
115 * Return the AnnotatedTypeMirror of the node
116 * This handles normal variables and array type
118 protected AnnotatedTypeMirror getAnnotatedTypeUniversal(Tree treeNode) {
119 AnnotatedTypeMirror atmType = atypeFactory.getAnnotatedType(treeNode);
120 // Check the object annotation - an array type is treated differently
122 return (atmType.getKind() == TypeKind.ARRAY?((AnnotatedArrayType) atmType).getComponentType():atmType);
127 * Helper function to check if the variable is a part of Java Reflection
129 protected Void checkIfJavaReflection(VariableTree varTree) {
130 if (isJavaReflection(varTree)) {
131 checker.report(Result.failure("reflection.found", varTree), varTree);
139 * Helper function to check if the variable is a part of Java Networking
141 protected Void checkIfJavaNetworking(VariableTree varTree) {
142 if (isJavaNetworking(varTree)) {
143 checker.report(Result.failure("java.net.found", varTree), varTree);
151 * Helper function to check if the variable is a part of Java Networking library
153 * i.e. java.net.XXX classes
155 protected boolean isJavaNetworking(VariableTree varTree) {
156 AnnotatedTypeMirror typeVar = getAnnotatedTypeUniversal(varTree);
157 Class<?> varClass = typeMirrorToClass(typeVar.getUnderlyingType());
159 /* An alternative is to list down the class names
162 if ((varClass == InetAddress.class) ||
163 (varClass == DatagramSocket.class) ||
164 (varClass == DatagramPacket.class) ||
165 (varClass == URL.class) ||
166 (varClass == HttpURLConnection.class) ||
167 (varClass == Socket.class) ||
168 (varClass == ServerSocket.class)) {
171 // We still allow the java.net.*Exception classes
172 // to be allowed in a try { } catch { } structure
173 return ((varClass != null) &&
174 varClass.toString().contains("java.net") &&
175 !varClass.toString().contains("Exception"));
180 * Helper function to check if the variable is a part of Java Reflection
182 * i.e. java.lang.reflect.XXX classes
184 protected boolean isJavaReflection(VariableTree varTree) {
185 AnnotatedTypeMirror typeVar = getAnnotatedTypeUniversal(varTree);
186 Class<?> varClass = typeMirrorToClass(typeVar.getUnderlyingType());
188 /* An alternative is to list down the class names
191 if ((varClass == Class.class) ||
192 (varClass == Constructor.class) ||
193 (varClass == Method.class) ||
194 (varClass == Type.class)) {
197 return ((varClass != null) &&
198 (varClass.toString().contains("java.lang.reflect")));
203 * Helper method/function adapted from FormatterTreeUtil.java / I18nFormatterTreeUtil.java
204 * to find a basic type of a variable
206 protected final Class<?extends Object> typeMirrorToClass(final TypeMirror type) {
207 return type.accept(new SimpleTypeVisitor7<Class<?extends Object>, Class<Void> >() {
209 public Class<?extends Object> visitPrimitive(PrimitiveType t, Class<Void> v) {
210 switch (t.getKind()) {
212 return Boolean.class;
218 return Character.class;
224 return Integer.class;
241 public Class<?extends Object> visitDeclared(DeclaredType dt, Class<Void> v) {
242 return dt.asElement().accept(new SimpleElementVisitor7<Class<?extends Object>, Class<Void> >() {
244 public Class<?extends Object> visitType(TypeElement e, Class<Void> v) {
246 return Class.forName(e.getQualifiedName().toString());
247 } catch (ClassNotFoundException e1) {
248 return null; // the lookup should work for all the
249 // classes we care about