001 package edu.rice.cs.cunit.threadCheck.predicates;
002
003 import java.awt.*;
004 import java.util.HashSet;
005
006 /**
007 * Class containing several common predicates.
008 * @author Mathias Ricken
009 */
010 public class ThreadCheckPredicates {
011 /**
012 * Return true if the current thread is the event thread.
013 * @param thisObject "this" at the time of the check, or null if not available; ignored by this method
014 * @return true if the current thread is the event thread
015 */
016 public static boolean checkEventThread(Object thisObject) {
017 return EventQueue.isDispatchThread();
018 }
019
020 /**
021 * Return true if the current thread is the event thread, or if thisObject is an instance of a subclass of
022 * java.awt.Component and that component has not been realized yet.
023 * @param thisObject "this" at the time of the check, or null if not available; ignored by this method
024 * @return true if the current thread is the event thread, or thisObject is a component that has not been realized
025 */
026 public static boolean checkEventThreadAfterRealized(Object thisObject) {
027 if (thisObject!=null) {
028 // non-static context
029 if (thisObject instanceof Component) {
030 // subclass of java.awt.Component
031 Component thisComponent = (Component)thisObject;
032 if (!thisComponent.isDisplayable()) {
033 // and not realized yet; any thread is ok
034 return true;
035 }
036 }
037 return EventQueue.isDispatchThread();
038 }
039 else {
040 // static context
041 return EventQueue.isDispatchThread();
042 }
043 }
044
045 /**
046 * Return true if the current thread's name equals the specified string
047 * @param thisObject "this" at the time of the check, or null if not available; ignored by this method
048 * @param value string to compare the current thread's name to
049 * @param regex true if value should be treated as a regular expression
050 * @return true if the current thread's name equals the specified string
051 */
052 public static boolean checkName(Object thisObject, String value, boolean regex) {
053 if (regex) {
054 return Thread.currentThread().getName().matches(value);
055 }
056 else {
057 return Thread.currentThread().getName().equals(value);
058 }
059 }
060
061 /**
062 * Return true if the current thread's group equals the specified string
063 * @param thisObject "this" at the time of the check, or null if not available; ignored by this method
064 * @param value string to compare the current thread's group to
065 * @param regex true if value should be treated as a regular expression
066 * @return true if the current thread's group equals the specified string
067 */
068 public static boolean checkGroup(Object thisObject, String value, boolean regex) {
069 if (regex) {
070 return Thread.currentThread().getThreadGroup().getName().matches(value);
071 }
072 else {
073 return Thread.currentThread().getThreadGroup().getName().equals(value);
074 }
075 }
076
077 /**
078 * Return true if the current thread owns the monitor of the object.
079 * If this method is directly used in a predicate annotation, then the object
080 * passed is "this".
081 * @param o object whose monitor should be checked; must be non-null
082 * @return true if the current thread owns the monitor (false if o is null)
083 */
084 public static boolean checkMonitorOwned(Object o) {
085 if (o==null) return false;
086 boolean interrupted = true;
087 while(interrupted) {
088 try {
089 o.wait(10);
090 interrupted = false;
091 }
092 catch(InterruptedException e) { /* ignore */ }
093 catch(IllegalMonitorStateException e) { return false; }
094 }
095 return true;
096 }
097
098 /**
099 * Return true if the current thread does not own the monitor of the object.
100 * If this method is directly used in a predicate annotation, then the object
101 * passed is "this".
102 * @param o object whose monitor should be checked; must be non-null
103 * @return true if the current thread does not own the monitor (false if o is null)
104 */
105 public static boolean checkMonitorNotOwned(Object o) {
106 return !checkMonitorOwned(o);
107 }
108
109 /**
110 * Return true if the current thread owns the monitor of the object
111 * with index value in the array of method arguments
112 * @param thisObject object that represents "this", or null if static
113 * @param args array of method arguments
114 * @param value index of the method argument that should be checked
115 * @return true if the current thread owns the monitor of the argument (false if value is out of range)
116 */
117 public static boolean checkMonitorOwnedArgument(Object thisObject, Object[] args, int value) {
118 if (value>=args.length) { return false; }
119 return checkMonitorOwned(args[value]);
120 }
121
122 /**
123 * Return true if the current thread does not own the monitor of the object
124 * with index value in the array of method arguments
125 * @param thisObject object that represents "this", or null if static
126 * @param args array of method arguments
127 * @param value index of the method argument that should be checked
128 * @return true if the current thread does not own the monitor of the argument (false if value is out of range)
129 */
130 public static boolean checkMonitorNotOwnedArgument(Object thisObject, Object[] args, int value) {
131 if (value>=args.length) { return false; }
132 return ThreadCheckPredicates.checkMonitorNotOwned(args[value]);
133 }
134
135 /**
136 * Return true if the any thread owns the monitor of the object.
137 * If this method is directly used in a predicate annotation, then the object
138 * passed is "this".
139 * @param o object whose monitor should be checked; must be non-null
140 * @return true if the any thread owns the monitor (false if o is null)
141 */
142 public static boolean checkMonitorOwnedByAnyThread(final Object o) {
143 if (o==null) return false;
144 final Boolean[] owned = new Boolean[] { null };
145 Thread inquirer = new Thread(new Runnable() {
146 public void run() {
147 final Thread inquirerThread = Thread.currentThread();
148 Thread acquirer = new Thread(new Runnable() {
149 public void run() {
150 synchronized(o) {
151 owned[0] = false;
152 inquirerThread.interrupt();
153 }
154 }
155 });
156 acquirer.start();
157 synchronized(this) {
158 while (owned[0]==null) {
159 try {
160 wait(10);
161 owned[0] = true;
162 return;
163 }
164 catch(InterruptedException e) {
165 if (!owned[0]) {
166 return;
167 }
168 }
169 }
170 }
171 }
172 });
173
174 inquirer.start();
175 try {
176 inquirer.join();
177 }
178 catch(InterruptedException e) { /* ignore */ }
179 return owned[0];
180 }
181
182 /**
183 * Return true if the no thread owns the monitor of the object.
184 * If this method is directly used in a predicate annotation, then the object
185 * passed is "this".
186 * @param o object whose monitor should be checked; must be non-null
187 * @return true if the no thread owns the monitor (false if o is null)
188 */
189 public static boolean checkMonitorNotOwnedByAnyThread(Object o) {
190 return !checkMonitorOwnedByAnyThread(o);
191 }
192
193 /**
194 * Return true if the any thread owns the monitor of the object
195 * with index value in the array of method arguments
196 * @param thisObject object that represents "this", or null if static
197 * @param args array of method arguments
198 * @param value index of the method argument that should be checked
199 * @return true if the any thread owns the monitor of the argument (false if value is out of range)
200 */
201 public static boolean checkMonitorOwnedArgumentByAnyThread(Object thisObject, Object[] args, int value) {
202 if (value>=args.length) { return false; }
203 return checkMonitorOwnedByAnyThread(args[value]);
204 }
205
206 /**
207 * Return true if the current thread does not own the monitor of the object
208 * with index value in the array of method arguments
209 * @param thisObject object that represents "this", or null if static
210 * @param args array of method arguments
211 * @param value index of the method argument that should be checked
212 * @return true if the current thread does not own the monitor of the argument (false if value is out of range)
213 */
214 public static boolean checkMonitorNotOwnedArgumentByAnyThread(Object thisObject, Object[] args, int value) {
215 if (value>=args.length) { return false; }
216 return ThreadCheckPredicates.checkMonitorNotOwnedByAnyThread(args[value]);
217 }
218
219 /**
220 * Return true if the object with index value in the array of method arguments is null.
221 * @param thisObject object that represents "this", or null if static
222 * @param args array of method arguments
223 * @param value index of the method argument that should be checked
224 * @return true if the argument is null (false if value is out of range)
225 */
226 public static boolean checkNullArgument(Object thisObject, Object[] args, int value) {
227 if (value>=args.length) { return false; }
228 return args[value]==null;
229 }
230
231 /**
232 * Return true if the object with index value in the array of method arguments is not null.
233 * @param thisObject object that represents "this", or null if static
234 * @param args array of method arguments
235 * @param value index of the method argument that should be checked
236 * @return true if the argument is not null (false if value is out of range)
237 */
238 public static boolean checkNotNullArgument(Object thisObject, Object[] args, int value) {
239 if (value>=args.length) { return false; }
240 return args[value]!=null;
241 }
242
243 /**
244 * Return true if the object with the specified index is a Number and meeds the bounds.
245 * @param thisObject object that represents "this", or null if static
246 * @param args array of method arguments
247 * @param mode bounding mode
248 * @param index index of the method argument that should be checked
249 * @param bound bound
250 * @param upperBound upper bound
251 * @return true if the number meets the bound, false otherwise, if index is out of range, or if the argument is not a Number
252 */
253 public static boolean checkNumberBoundedArgument(Object thisObject, Object[] args,
254 NumberBoundedArgument.Mode mode,
255 int index,
256 double bound,
257 double upperBound) {
258 if (index>=args.length) { return false; }
259 if (args[index]==null) { return false; }
260 if (!(args[index] instanceof Number)) {
261 return false;
262 }
263 Number n = ((Number)args[index]);
264 switch(mode) {
265 case LESS:
266 return n.doubleValue()<bound;
267 case LESS_EQ:
268 return n.doubleValue()<=bound;
269 case GREATER:
270 return n.doubleValue()>bound;
271 case GREATER_EQ:
272 return n.doubleValue()>=bound;
273 case IN_EQ:
274 return (n.doubleValue()<=upperBound) && (n.doubleValue()>=bound);
275 case IN:
276 return (n.doubleValue()<upperBound) && (n.doubleValue()>bound);
277 case OUT_EQ:
278 return (n.doubleValue()<=bound) || (n.doubleValue()>=upperBound);
279 case OUT:
280 return (n.doubleValue()<bound) || (n.doubleValue()>upperBound);
281 }
282 return false;
283 }
284
285 /**
286 * Return true if the object with the specified indices are all distinct.
287 * @param thisObject object that represents "this", or null if static
288 * @param args array of method arguments
289 * @param value array of indices of the method argument that should be checked
290 * @return true if the arguments are all distinct, false otherwise, if value is out of range, or if fewer than two indices are specified
291 */
292 public static boolean checkDistinctArguments(Object thisObject, Object[] args,
293 int[] value) {
294 if (value.length<2) { return false; }
295 HashSet<Object> found = new HashSet<Object>();
296 for (int i=0;i< value.length;++i) {
297 if (found.contains(args[i])) { return false; }
298 found.add(args[i]);
299 }
300 return true;
301 }
302
303 /**
304 * Return true if the object with the specified indices are all the same.
305 * @param thisObject object that represents "this", or null if static
306 * @param args array of method arguments
307 * @param value array of indices of the method argument that should be checked
308 * @return true if the arguments are all the same, false otherwise, if value is out of range, or if fewer than two indices are specified
309 */
310 public static boolean checkSameArguments(Object thisObject, Object[] args,
311 int[] value) {
312 if (value.length<2) { return false; }
313 for (int i=1;i< value.length;++i) {
314 if (!args[0].equals(args[i])) { return false; }
315 }
316 return true;
317 }
318 }