1 /*
2  * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation. Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package org.netbeans.jemmy.util;
26 
27 import java.lang.reflect.InvocationTargetException;
28 
29 import org.netbeans.jemmy.ClassReference;
30 import org.netbeans.jemmy.JemmyException;
31 import org.netbeans.jemmy.operators.Operator.StringComparator;
32 
33 /**
34  * Be executed under 1.4 uses {@code java.util.regex.Pattern}
35  * functionality. Otherwise understands only "." and "*" simbols, i.e. regexprs
36  * like ".*Ques.ion.*".
37  */
38 public class RegExComparator implements StringComparator {
39 
40     private static final int ANY_SIMBOL = -1;
41     private static final int IGNORE_SIMBOL = -999;
42 
43     @Override
equals(String caption, String match)44     public boolean equals(String caption, String match) {
45         if (match == null) {
46             return true;
47         }
48         if (caption == null) {
49             return false;
50         }
51         if (System.getProperty("java.specification.version").compareTo("1.3") > 0) {
52             try {
53                 Object result = new ClassReference("java.util.regex.Pattern").
54                         invokeMethod("matches",
55                                 new Object[]{match, caption},
56                                 new Class<?>[]{String.class, Class.forName("java.lang.CharSequence")});
57                 return ((Boolean) result).booleanValue();
58             } catch (InvocationTargetException e) {
59                 throw (new JemmyException("Exception during regexpr using",
60                         e));
61             } catch (ClassNotFoundException e) {
62                 throw (new JemmyException("Exception during regexpr using",
63                         e));
64             } catch (NoSuchMethodException e) {
65                 throw (new JemmyException("Exception during regexpr using",
66                         e));
67             } catch (IllegalAccessException e) {
68                 throw (new JemmyException("Exception during regexpr using",
69                         e));
70             }
71         } else {
72             return parse(caption, match);
73         }
74     }
75 
76     /**
77      * Checks that caption matshes the pattern. Understands only "." (any
78      * symbol) and "*" (repeat symbol). Used for 1.3 and earclier javas,
79      * starting from 1.4 {@code java.util.regex.Pattern} class is used.
80      *
81      * @param caption a caption to compare with the pattern.
82      * @param match a pattern
83      * @return true if the caption matches the pattern.
84      */
parse(String caption, String match)85     public boolean parse(String caption, String match) {
86         if (match.length() == 0
87                 && caption.length() == 0) {
88             return true;
89         } else if (match.length() == 0) {
90             return false;
91         }
92         int c0 = match.charAt(0);
93         int c1 = IGNORE_SIMBOL;
94         if (match.length() > 1) {
95             c1 = match.charAt(1);
96         }
97         int shift = 1;
98         switch (c0) {
99             case '\\':
100                 if (match.length() == 1) {
101                     throw (new RegExParsingException("\\ is not appropriate"));
102                 }
103                 c0 = match.charAt(1);
104                 if (match.length() > 2) {
105                     c1 = match.charAt(2);
106                 } else {
107                     c1 = IGNORE_SIMBOL;
108                 }
109                 shift = 2;
110                 break;
111             case '.':
112                 c0 = ANY_SIMBOL;
113                 break;
114             case '*':
115                 throw (new RegExParsingException("* is not appropriate"));
116         }
117         if (c1 == '*') {
118             shift = shift + 1;
119             int i = 0;
120             while (i <= caption.length()) {
121                 if (i == 0
122                         || checkOne(caption.substring(i - 1), c0)) {
123                     if (parse(caption.substring(i), match.substring(shift))) {
124                         return true;
125                     }
126                 } else {
127                     return false;
128                 }
129                 i++;
130             }
131             return false;
132         } else {
133             if (caption.length() == 0) {
134                 return false;
135             }
136             if (checkOne(caption, c0)) {
137                 return parse(caption.substring(1), match.substring(shift));
138             } else {
139                 return false;
140             }
141         }
142     }
143 
checkOne(String caption, int simbol)144     private boolean checkOne(String caption, int simbol) {
145         return (simbol == ANY_SIMBOL
146                 || simbol == caption.charAt(0));
147     }
148 
149     /**
150      * Thrown in case of parsing error.
151      */
152     public static class RegExParsingException extends JemmyException {
153 
154         private static final long serialVersionUID = 42L;
155 
156         /**
157          * Constructs a RegExComparator$RegExParsingException object.
158          *
159          * @param message an error message
160          */
RegExParsingException(String message)161         public RegExParsingException(String message) {
162             super(message);
163         }
164 
165         /**
166          * Constructs a RegExComparator$RegExParsingException object.
167          *
168          * @param message an error message
169          * @param innerException a parsing exception.
170          */
RegExParsingException(String message, Exception innerException)171         public RegExParsingException(String message, Exception innerException) {
172             super(message, innerException);
173         }
174     }
175 }
176