/******************************************************************************* * Copyright (c) 2006-2013, Cloudsmith Inc. * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the copyright holder * listed above, as the Initial Contributor under such license. The text or * such license is available at www.eclipse.org. ******************************************************************************/ package org.eclipse.buckminster.osgi.filter.impl; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Map; class StringFilterImpl extends FilterImpl { private static class SetAccessibleAction implements PrivilegedAction<Object> { private final AccessibleObject accessible; SetAccessibleAction(AccessibleObject accessible) { this.accessible = accessible; } @Override public Object run() { accessible.setAccessible(true); return null; } } private static final Class<?>[] constructorType = new Class<?>[] { String.class }; private final String stringValue; StringFilterImpl(int operation, String attr, String value) { super(operation, attr); this.stringValue = value; } @Override public int compareTo(FilterImpl filter) { int cmp = internalCompareTo(filter); if (cmp == 0) cmp = stringValue.compareTo(((StringFilterImpl) filter).stringValue); return cmp; } @Override String getValueAsString() { return stringValue; } @SuppressWarnings("unchecked") @Override boolean internalCompare(Object value) { if (value instanceof String) return compare((String) value); Class<?> clazz = value.getClass(); if (clazz.isArray()) return compare(clazz.getComponentType(), value); if (value instanceof Integer) return compare(((Integer) value).intValue()); if (value instanceof Boolean) return compare(((Boolean) value).booleanValue()); if (value instanceof Long) return compare(((Long) value).longValue()); if (value instanceof Byte) return compare(((Byte) value).byteValue()); if (value instanceof Short) return compare(((Short) value).shortValue()); if (value instanceof Character) return compare(((Character) value).charValue()); if (value instanceof Float) return compare(((Float) value).floatValue()); if (value instanceof Double) return compare(((Double) value).doubleValue()); if (value instanceof Comparable<?>) return compareAsComparable((Comparable<Object>) value); return compareUnknown(value); // RFC 59 } @Override boolean match0(Map<String, ? extends Object> properties) { Object prop = (properties == null) ? null : properties.get(getAttr()); return compare(prop); } @Override void toString(StringBuilder sb) { sb.append('('); sb.append(getAttr()); switch (getOp()) { case EQUAL: sb.append('='); sb.append(encodeValue(stringValue)); break; case GREATER: sb.append(">="); //$NON-NLS-1$ sb.append(encodeValue(stringValue)); break; case LESS: sb.append("<="); //$NON-NLS-1$ sb.append(encodeValue(stringValue)); break; case APPROX: sb.append("~="); //$NON-NLS-1$ sb.append(encodeValue(approxString(stringValue.toString()))); break; } sb.append(')'); } private boolean compare(boolean boolval) { boolean boolval2 = Boolean.parseBoolean(stringValue.trim()); switch (getOp()) { case EQUAL: return boolval == boolval2; case APPROX: return boolval == boolval2; case GREATER: return boolval == boolval2; default: return boolval == boolval2; } } private boolean compare(byte byteval) { byte byteval2; try { byteval2 = Byte.parseByte(stringValue.trim()); } catch (NumberFormatException e) { return false; } switch (getOp()) { case EQUAL: return byteval == byteval2; case APPROX: return byteval == byteval2; case GREATER: return byteval >= byteval2; default: return byteval <= byteval2; } } private boolean compare(char charval) { // Find first non whitespace character int end = stringValue.length(); int idx = 0; char charval2 = 0; for (; idx < end; ++idx) { charval2 = stringValue.charAt(idx); if (charval2 > ' ') break; } if (idx == end) return false; switch (getOp()) { case EQUAL: return charval == charval2; case APPROX: return (charval == charval2) || (Character.toUpperCase(charval) == Character.toUpperCase(charval2)) || (Character.toLowerCase(charval) == Character.toLowerCase(charval2)); case GREATER: return charval >= charval2; default: return charval <= charval2; } } private boolean compare(Class<?> type, Object primarray) { if (Integer.TYPE.isAssignableFrom(type)) { int[] array = (int[]) primarray; for (int i = 0, size = array.length; i < size; i++) if (compare(array[i])) return true; return false; } if (Long.TYPE.isAssignableFrom(type)) { long[] array = (long[]) primarray; for (int i = 0, size = array.length; i < size; i++) if (compare(array[i])) return true; return false; } if (Byte.TYPE.isAssignableFrom(type)) { byte[] array = (byte[]) primarray; for (int i = 0, size = array.length; i < size; i++) if (compare(array[i])) return true; return false; } if (Short.TYPE.isAssignableFrom(type)) { short[] array = (short[]) primarray; for (int i = 0, size = array.length; i < size; i++) if (compare(array[i])) return true; return false; } if (Character.TYPE.isAssignableFrom(type)) { char[] array = (char[]) primarray; for (int i = 0, size = array.length; i < size; i++) if (compare(array[i])) return true; return false; } if (Float.TYPE.isAssignableFrom(type)) { float[] array = (float[]) primarray; for (int i = 0, size = array.length; i < size; i++) if (compare(array[i])) return true; return false; } if (Double.TYPE.isAssignableFrom(type)) { double[] array = (double[]) primarray; for (int i = 0, size = array.length; i < size; i++) if (compare(array[i])) return true; return false; } if (Boolean.TYPE.isAssignableFrom(type)) { boolean[] array = (boolean[]) primarray; for (int i = 0, size = array.length; i < size; i++) if (compare(array[i])) return true; return false; } return false; } private boolean compare(double doubleval) { double doubleval2; try { doubleval2 = Double.parseDouble(stringValue.trim()); } catch (NumberFormatException e) { return false; } switch (getOp()) { case EQUAL: return Double.compare(doubleval, doubleval2) == 0; case APPROX: return Double.compare(doubleval, doubleval2) == 0; case GREATER: return Double.compare(doubleval, doubleval2) >= 0; default: return Double.compare(doubleval, doubleval2) <= 0; } } private boolean compare(float floatval) { float floatval2; try { floatval2 = Float.parseFloat(stringValue.trim()); } catch (NumberFormatException e) { return false; } switch (getOp()) { case EQUAL: return Float.compare(floatval, floatval2) == 0; case APPROX: return Float.compare(floatval, floatval2) == 0; case GREATER: return Float.compare(floatval, floatval2) >= 0; default: return Float.compare(floatval, floatval2) <= 0; } } private boolean compare(int intval) { int intval2; try { intval2 = Integer.parseInt(stringValue.trim()); } catch (NumberFormatException e) { return false; } switch (getOp()) { case EQUAL: return intval == intval2; case APPROX: return intval == intval2; case GREATER: return intval >= intval2; default: return intval <= intval2; } } private boolean compare(long longval) { long longval2; try { longval2 = Long.parseLong(stringValue.trim()); } catch (NumberFormatException e) { return false; } switch (getOp()) { case EQUAL: return longval == longval2; case APPROX: return longval == longval2; case GREATER: return longval >= longval2; default: return longval <= longval2; } } private boolean compare(short shortval) { short shortval2; try { shortval2 = Short.parseShort(stringValue.trim()); } catch (NumberFormatException e) { return false; } switch (getOp()) { case EQUAL: return shortval == shortval2; case APPROX: return shortval == shortval2; case GREATER: return shortval >= shortval2; default: return shortval <= shortval2; } } private boolean compare(String string) { switch (getOp()) { case EQUAL: return string.equals(stringValue); case APPROX: string = approxString(string); String string2 = approxString(stringValue); return string.equalsIgnoreCase(string2); case GREATER: return string.compareTo(stringValue) >= 0; default: return string.compareTo(stringValue) <= 0; } } private boolean compareAsComparable(Comparable<Object> value1) { try { Constructor<?> constructor = value1.getClass().getConstructor(constructorType); if (!constructor.isAccessible()) AccessController.doPrivileged(new SetAccessibleAction(constructor)); Object value2 = constructor.newInstance(new Object[] { stringValue.trim() }); switch (getOp()) { case EQUAL: case APPROX: return value1.compareTo(value2) == 0; case GREATER: return value1.compareTo(value2) >= 0; default: return value1.compareTo(value2) <= 0; } } catch (NoSuchMethodException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } catch (InstantiationException e) { } return false; } private boolean compareUnknown(Object value1) { // RFC 59 try { Constructor<?> constructor = value1.getClass().getConstructor(constructorType); if (!constructor.isAccessible()) AccessController.doPrivileged(new SetAccessibleAction(constructor)); Object value2 = constructor.newInstance(new Object[] { stringValue.trim() }); return value1.equals(value2); } catch (NoSuchMethodException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } catch (InstantiationException e) { } return false; } }