Fixing a bug in IoTMaster (wrong variable for language flag check); adding LANGUAGE...
[iot2.git] / checker / iotchecker / IoTJavaVisitor.java
1 package iotchecker;
2
3 import iotchecker.qual.*;
4
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;
27
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.ArrayList;
34 import java.util.LinkedList;
35 import java.util.Set;
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;
41
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;
54
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;
67
68 import java.io.Serializable;
69 import java.lang.reflect.*;
70 import java.net.*;
71 import java.rmi.Remote;
72 import java.rmi.server.UnicastRemoteObject;
73
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
78  *
79  * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
80  * @author      Bin Xu <xub3 @ uci.edu>
81  * @version     1.0
82  * @since       2016-03-25
83  */
84 public final class IoTJavaVisitor extends BaseTypeVisitor<BaseAnnotatedTypeFactory> {
85
86         public IoTJavaVisitor(BaseTypeChecker checker) {
87                 super(checker);
88         }
89
90
91         /**
92          * This visitVariable() method is taken directly from BaseTypeVisitor
93          * <p>
94          * We need to override the checkArguments() to not complain about the switch
95          * from @LocalRemote to @NonLocalRemote.
96          */
97         @Override
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)));
101
102                 try {
103                         // Check and reject any existence/declaration of Java Reflection and Java Networking
104                         checkIfJavaReflection(node);
105                         checkIfJavaNetworking(node);
106
107                         return null;
108                 } finally {
109                         visitorState.setAssignmentContext(preAssCtxt);
110                 }
111         }
112
113
114         /**
115          * Return the AnnotatedTypeMirror of the node
116          * This handles normal variables and array type
117          */
118         protected AnnotatedTypeMirror getAnnotatedTypeUniversal(Tree treeNode) {
119                 AnnotatedTypeMirror atmType = atypeFactory.getAnnotatedType(treeNode);
120                 // Check the object annotation - an array type is treated differently
121
122                 return (atmType.getKind() == TypeKind.ARRAY?((AnnotatedArrayType) atmType).getComponentType():atmType);
123         }
124
125
126         /**
127          * Helper function to check if the variable is a part of Java Reflection
128          */
129         protected Void checkIfJavaReflection(VariableTree varTree) {
130                 if (isJavaReflection(varTree)) {
131                         checker.report(Result.failure("reflection.found", varTree), varTree);
132                 }
133
134                 return null;
135         }
136
137
138         /**
139          * Helper function to check if the variable is a part of Java Networking
140          */
141         protected Void checkIfJavaNetworking(VariableTree varTree) {
142                 if (isJavaNetworking(varTree)) {
143                         checker.report(Result.failure("java.net.found", varTree), varTree);
144                 }
145
146                 return null;
147         }
148
149
150         /**
151          * Helper function to check if the variable is a part of Java Networking library
152          * <p>
153          * i.e. java.net.XXX classes
154          */
155         protected boolean isJavaNetworking(VariableTree varTree) {
156                 AnnotatedTypeMirror typeVar = getAnnotatedTypeUniversal(varTree);
157                 Class<?> varClass = typeMirrorToClass(typeVar.getUnderlyingType());
158
159                 /* An alternative is to list down the class names
160                    like the following
161
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)) {
169                  */
170
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"));
176         }
177
178
179         /**
180          * Helper function to check if the variable is a part of Java Reflection
181          * <p>
182          * i.e. java.lang.reflect.XXX classes
183          */
184         protected boolean isJavaReflection(VariableTree varTree) {
185                 AnnotatedTypeMirror typeVar = getAnnotatedTypeUniversal(varTree);
186                 Class<?> varClass = typeMirrorToClass(typeVar.getUnderlyingType());
187
188                 /* An alternative is to list down the class names
189                    like the following
190
191                    if ((varClass == Class.class)       ||
192                     (varClass == Constructor.class) ||
193                     (varClass == Method.class)      ||
194                     (varClass == Type.class)) {
195                  */
196
197                 return ((varClass != null) &&
198                                                 (varClass.toString().contains("java.lang.reflect")));
199         }
200
201
202         /**
203          * Helper method/function adapted from FormatterTreeUtil.java / I18nFormatterTreeUtil.java
204          * to find a basic type of a variable
205          */
206         protected final Class<?extends Object> typeMirrorToClass(final TypeMirror type) {
207                 return type.accept(new SimpleTypeVisitor7<Class<?extends Object>, Class<Void> >() {
208                         @Override
209                         public Class<?extends Object> visitPrimitive(PrimitiveType t, Class<Void> v) {
210                                 switch (t.getKind()) {
211                                 case BOOLEAN:
212                                         return Boolean.class;
213
214                                 case BYTE:
215                                         return Byte.class;
216
217                                 case CHAR:
218                                         return Character.class;
219
220                                 case SHORT:
221                                         return Short.class;
222
223                                 case INT:
224                                         return Integer.class;
225
226                                 case LONG:
227                                         return Long.class;
228
229                                 case FLOAT:
230                                         return Float.class;
231
232                                 case DOUBLE:
233                                         return Double.class;
234
235                                 default:
236                                         return null;
237                                 }
238                         }
239
240                         @Override
241                         public Class<?extends Object> visitDeclared(DeclaredType dt, Class<Void> v) {
242                                 return dt.asElement().accept(new SimpleElementVisitor7<Class<?extends Object>, Class<Void> >() {
243                                         @Override
244                                         public Class<?extends Object> visitType(TypeElement e, Class<Void> v) {
245                                                 try {
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
250                                                 }
251                                         }
252                                 }, Void.TYPE);
253                         }
254                 }, Void.TYPE);
255         }
256 }