//
// Copyright (C) 2007 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* simple utility that can be used to check for string matches in
* sets with '*' wildcards, e.g. to check for class name lists like
*
* vm.halt_on_throw=java.lang.reflect.*:my.own.Exception
*
* Only meta chars in patterns are '*', i.e. '.' is a regular char to match
*/
public class StringSetMatcher {
boolean hasAnyPattern; // do we have a universal '*' pattern?
Pattern[] pattern;
Matcher[] matcher;
/**
* convenience method for matcher pairs containing of explicit excludes and
* includes
*/
public static boolean isMatch (String s, StringSetMatcher includes, StringSetMatcher excludes){
if (excludes != null) {
if (excludes.matchesAny(s)){
return false;
}
}
if (includes != null) {
if (!includes.matchesAny(s)){
return false;
}
}
return true;
}
public static StringSetMatcher getNonEmpty(String[] set){
if (set != null && set.length > 0){
return new StringSetMatcher(set);
} else {
return null;
}
}
public StringSetMatcher (String... set){
int n = set.length;
pattern = new Pattern[n];
matcher = new Matcher[n];
for (int i=0; i<n; i++){
String s = set[i];
if (s.equals("*")) {
hasAnyPattern = true;
// no need to compile this
} else {
Pattern p = createPattern(s);
pattern[i] = p;
matcher[i] = p.matcher(""); // gets reset upon use
}
}
}
public String toString() {
int n=0;
StringBuilder sb = new StringBuilder(64);
sb.append("StringSetMatcher [regex_patterns=");
if (hasAnyPattern) {
sb.append(".*");
n++;
}
for (int i=0; i<pattern.length; i++) {
if (pattern[i] != null) {
if (n++>0) {
sb.append(',');
}
sb.append(pattern[i]);
}
}
sb.append(']');
return sb.toString();
}
public void addPattern (String s){
if (s.equals("*")) { // no need to compile
hasAnyPattern = true;
} else {
int n = pattern.length;
Pattern[] pNew = new Pattern[n+1];
System.arraycopy(pattern, 0, pNew, 0, n);
pNew[n] = createPattern(s);
Matcher[] mNew = new Matcher[pNew.length];
System.arraycopy(matcher, 0, mNew, 0, n);
mNew[n] = pNew[n].matcher("");
pattern = pNew;
matcher = mNew;
}
}
Pattern createPattern (String s){
Pattern p;
StringBuilder sb = new StringBuilder();
int len = s.length();
for (int j=0; j<len; j++){
char c = s.charAt(j);
switch (c){
case '.' : sb.append("\\."); break;
case '$' : sb.append("\\$"); break;
case '[' : sb.append("\\["); break;
case ']' : sb.append("\\]"); break;
case '*' : sb.append(".*"); break;
case '(' : sb.append("\\("); break;
case ')' : sb.append("\\)"); break;
// <2do> and probably more..
default: sb.append(c);
}
}
p = Pattern.compile(sb.toString());
return p;
}
/**
* does 's' match at least one of our patterns
*/
public boolean matchesAny (String s){
if (s != null) {
if (hasAnyPattern) {
return true; // no need to check
}
for (int i=0; i<matcher.length; i++){
Matcher m = matcher[i];
m.reset(s);
if (m.matches()){
return true;
}
}
}
return false;
}
/**
* does 's' match ALL of our patterns
*/
public boolean matchesAll (String s){
if (s != null) {
if (hasAnyPattern && pattern.length == 1) {
return true; // no need to check
}
for (int i=0; i<pattern.length; i++){
// Pattern p = pattern[i];
Matcher m = matcher[i];
m.reset(s);
if (!m.matches()){
return false;
}
}
return true;
} else {
return false;
}
}
/**
* do all elements of 'set' match at least one of our patterns?
*/
public boolean allMatch (String[] set){
if (hasAnyPattern) {
return true;
}
for (int i=0; i<set.length; i++){
if (!matchesAny(set[i])){
return false;
}
}
return true;
}
public static void main (String[] args){
String[] p = args[0].split(":");
String[] s = args[1].split(":");
StringSetMatcher sm = new StringSetMatcher(p);
if (sm.matchesAny(s[0])){
System.out.println("Bingo, \"" + s[0] + "\" matches " + sm);
} else {
System.out.println("nope, \"" + s[0] + "\" doesn't match " + sm);
}
}
}