001 /*
002 * $Id: TestOn.java,v 1.15 2011/11/21 20:46:43 oboehm Exp $
003 *
004 * Copyright (c) 2010 by Oliver Boehm
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 *
018 * (c)reated 23.04.2010 by oliver (ob@oasd.de)
019 */
020
021 package patterntesting.runtime.junit.internal;
022
023 import java.net.*;
024
025 import org.apache.commons.lang.*;
026 import org.slf4j.*;
027
028 import patterntesting.runtime.net.Localhost;
029 import patterntesting.runtime.util.*;
030
031 /**
032 * This is a local helper class for the RunTestOn and SkipTestOn annotation.
033 * So most of the methods are package default because there is no need to
034 * access from somewhere else.
035 *
036 * @author oliver
037 * @since 1.0 (23.04.2010)
038 */
039 public final class TestOn {
040
041 private static final Logger log = LoggerFactory.getLogger(TestOn.class);
042 private String osName = Environment.OS_NAME;
043 private String osArch = Environment.OS_ARCH;
044 private String userName = Environment.USER_NAME;
045 /** Contains the reason of the last match. */
046 private transient String reason;
047
048 /**
049 * For testing you can set the OS name.
050 *
051 * @param name the new os name
052 */
053 public void setOsName(final String name) {
054 this.osName = name;
055 }
056
057 /**
058 * For testing you can set the OS architector.
059 *
060 * @param arch the new os architector
061 */
062 public void setOsArch(final String arch) {
063 this.osArch = arch;
064 }
065
066 /**
067 * For testing you can set the user name.
068 *
069 * @param name the new user name
070 */
071 public void setUserName(final String name) {
072 this.userName = name;
073 }
074
075 /**
076 * Gets the reason.
077 *
078 * @return the reason
079 */
080 public String getReason() {
081 return this.reason;
082 }
083
084 /**
085 * Checks for reason.
086 *
087 * @return true, if reason is set
088 */
089 public boolean hasReason() {
090 return this.reason != null;
091 }
092
093 /**
094 * If the operating system(s) match and one of the other parameters (if
095 * they contain values) this method will return true.
096 *
097 * @param value same as os parameter
098 * @param os the operating system(s) which should match
099 * @param arch the architectures
100 * @param version the version(s) of the operating systems
101 * @param host the host(s)
102 * @param javaVersions the java version(s)
103 * @param javaVendors the java vendor(s)
104 * @param users the user(s)
105 * @param systemProps the system properties
106 * @return true if the parameter matches
107 */
108 public boolean matches(final String[] value, final String[] os,
109 final String[] arch, final String[] version, final String[] host,
110 final String[] javaVersions, final String[] javaVendors,
111 final String[] users, final String[] systemProps) {
112 String[] osValue = StringUtils.isEmpty(os[0]) ? value : os;
113 return matches(osValue, arch, version, host, javaVersions, javaVendors, users, systemProps);
114 }
115
116 /**
117 * If the operating system(s) match and one of the other parameters (if
118 * they contain values) this method will return true.
119 *
120 * @param os the operating system(s) which should match
121 * @param arch the architectures
122 * @param version the version(s) of the operating systems
123 * @param host the host(s)
124 * @param javaVersions the java version(s)
125 * @param javaVendors the java vendor(s)
126 * @param users the user(s)
127 * @param systemProps the system properties
128 * @return true if the parameter matches
129 */
130 public boolean matches(final String[] os,
131 final String[] arch, final String[] version, final String[] host,
132 final String[] javaVersions, final String[] javaVendors,
133 final String[] users, final String[] systemProps) {
134 boolean valueGiven = false;
135 if (!StringUtils.isEmpty(os[0])) {
136 if (!matches(os, osName)) {
137 return false;
138 }
139 valueGiven = true;
140 }
141 if (!StringUtils.isEmpty(arch[0])) {
142 if (!matches(arch, osArch)) {
143 return false;
144 }
145 valueGiven = true;
146 }
147 if (!StringUtils.isEmpty(version[0])) {
148 if (!matches(version, Environment.OS_VERSION)) {
149 return false;
150 }
151 valueGiven = true;
152 }
153 if (!StringUtils.isEmpty(javaVersions[0])) {
154 if (!matches(javaVersions, Environment.JAVA_VERSION)) {
155 return false;
156 }
157 valueGiven = true;
158 }
159 if (!StringUtils.isEmpty(javaVendors[0])) {
160 if (!matches(javaVendors, Environment.JAVA_VENDOR)) {
161 return false;
162 }
163 valueGiven = true;
164 }
165 if (!StringUtils.isEmpty(users[0])) {
166 if (!matches(users, userName)) {
167 return false;
168 }
169 valueGiven = true;
170 }
171 if (!StringUtils.isEmpty(systemProps[0])) {
172 if (!Environment.matchesOneOf(systemProps)) {
173 return false;
174 }
175 valueGiven = true;
176 }
177 // this call is expensive so we shift it to the end
178 if (!StringUtils.isEmpty(host[0])) {
179 if (!runsOn(host)) {
180 return false;
181 }
182 valueGiven = true;
183 }
184 if (!valueGiven) {
185 throw new IllegalArgumentException("no value(s) given");
186 //return true;
187 }
188 reason = (StringUtils.isEmpty(os[0]) ? "" : osName)
189 + (StringUtils.isEmpty(arch[0]) ? "" : osArch)
190 + (StringUtils.isEmpty(version[0]) ? "" : Environment.OS_VERSION)
191 + (StringUtils.isEmpty(javaVersions[0]) ? "" : "JDK " + Environment.JAVA_VERSION)
192 + (StringUtils.isEmpty(javaVendors[0]) ? "" : Environment.JAVA_VENDOR + " as vendor")
193 + (StringUtils.isEmpty(users[0]) ? "" : Environment.JAVA_VENDOR + " as user")
194 + (StringUtils.isEmpty(systemProps[0]) ? "" : Converter.toString(systemProps))
195 + (StringUtils.isEmpty(host[0]) ? "" : "host " + Converter.toString(host))
196 + " detected";
197 return true;
198 }
199
200 private static boolean matches(final String[] names, final String name) {
201 for (int i = 0; i < names.length; i++) {
202 if (matches(names[i], name)) {
203 return true;
204 }
205 }
206 return false;
207 }
208
209 /**
210 * If the given pattern parameter contains an asterisk ("*") it is
211 * considered as pattern. Otherwise only the beginning with name
212 * must match.
213 *
214 * @param pattern the pattern
215 * @param name the name
216 * @return true, if successful
217 * @since 1.1
218 */
219 private static boolean matches(final String pattern, final String name) {
220 if (name.startsWith(pattern)) {
221 return true;
222 }
223 if (pattern.contains("*") || (pattern.contains("?"))) {
224 String regex = wildcardToRegex(pattern);
225 return name.matches(regex);
226 }
227 return false;
228 }
229
230 private static boolean runsOn(final String[] hosts) {
231 try {
232 InetAddress localhost = InetAddress.getLocalHost();
233 if (ArrayUtils.contains(hosts, localhost.getHostAddress())
234 || matches(hosts, localhost.getHostName())) {
235 return true;
236 }
237 return Localhost.matches(hosts);
238 } catch (UnknownHostException e) {
239 log.debug("can't get local InetAddress - using localhost", e);
240 return runsOnLocalhost(hosts);
241 }
242 }
243
244 private static boolean runsOnLocalhost(final String[] hosts) {
245 return ArrayUtils.contains(hosts, "127.0.0.1")
246 || StringHelper.containsIgnoreCase(hosts, "localhost"); //NOPMD
247 }
248
249 /**
250 * Wildcard to regex.
251 *
252 * @param wildcard the wildcard
253 * @return the string
254 * @see "http://www.rgagnon.com/javadetails/java-0515.html"
255 */
256 private static String wildcardToRegex(final String wildcard) {
257 StringBuffer s = new StringBuffer(wildcard.length());
258 s.append('^');
259 for (int i = 0, is = wildcard.length(); i < is; i++) {
260 char c = wildcard.charAt(i);
261 switch(c) {
262 case '*':
263 s.append(".*");
264 break;
265 case '?':
266 s.append(".");
267 break;
268 // escape special regexp-characters
269 case '(': case ')': case '[': case ']': case '$':
270 case '^': case '.': case '{': case '}': case '|':
271 case '\\':
272 s.append("\\");
273 s.append(c);
274 break;
275 default:
276 s.append(c);
277 break;
278 }
279 }
280 s.append('$');
281 return(s.toString());
282 }
283
284 }
285