/* * Copyright 2005,2009 Ivan SZKIBA * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ini4j.spi; import java.beans.Introspector; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.beans.PropertyVetoException; import java.beans.VetoableChangeListener; import java.beans.VetoableChangeSupport; import java.lang.reflect.Array; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public abstract class AbstractBeanInvocationHandler implements InvocationHandler { private static final String PROPERTY_CHANGE_LISTENER = "PropertyChangeListener"; private static final String VETOABLE_CHANGE_LISTENER = "VetoableChangeListener"; private static final String ADD_PREFIX = "add"; private static final String READ_PREFIX = "get"; private static final String REMOVE_PREFIX = "remove"; private static final String READ_BOOLEAN_PREFIX = "is"; private static final String WRITE_PREFIX = "set"; private static final String HAS_PREFIX = "has"; private static enum Prefix { READ(READ_PREFIX), READ_BOOLEAN(READ_BOOLEAN_PREFIX), WRITE(WRITE_PREFIX), ADD_CHANGE(ADD_PREFIX + PROPERTY_CHANGE_LISTENER), ADD_VETO(ADD_PREFIX + VETOABLE_CHANGE_LISTENER), REMOVE_CHANGE(REMOVE_PREFIX + PROPERTY_CHANGE_LISTENER), REMOVE_VETO(REMOVE_PREFIX + VETOABLE_CHANGE_LISTENER), HAS(HAS_PREFIX); private int _len; private String _value; private Prefix(String value) { _value = value; _len = value.length(); } public static Prefix parse(String str) { Prefix ret = null; for (Prefix p : values()) { if (str.startsWith(p.getValue())) { ret = p; break; } } return ret; } public String getTail(String input) { return Introspector.decapitalize(input.substring(_len)); } public String getValue() { return _value; } } private PropertyChangeSupport _pcSupport; private Object _proxy; private VetoableChangeSupport _vcSupport; @Override public Object invoke(Object proxy, Method method, Object[] args) throws PropertyVetoException { Object ret = null; Prefix prefix = Prefix.parse(method.getName()); if (prefix != null) { String tail = prefix.getTail(method.getName()); updateProxy(proxy); switch (prefix) { case READ: ret = getProperty(prefix.getTail(method.getName()), method.getReturnType()); break; case READ_BOOLEAN: ret = getProperty(prefix.getTail(method.getName()), method.getReturnType()); break; case WRITE: setProperty(tail, args[0], method.getParameterTypes()[0]); break; case HAS: ret = Boolean.valueOf(hasProperty(prefix.getTail(method.getName()))); break; case ADD_CHANGE: addPropertyChangeListener((String) args[0], (PropertyChangeListener) args[1]); break; case ADD_VETO: addVetoableChangeListener((String) args[0], (VetoableChangeListener) args[1]); break; case REMOVE_CHANGE: removePropertyChangeListener((String) args[0], (PropertyChangeListener) args[1]); break; case REMOVE_VETO: removeVetoableChangeListener((String) args[0], (VetoableChangeListener) args[1]); break; default: break; } } return ret; } protected abstract Object getPropertySpi(String property, Class<?> clazz); protected abstract void setPropertySpi(String property, Object value, Class<?> clazz); protected abstract boolean hasPropertySpi(String property); protected synchronized Object getProperty(String property, Class<?> clazz) { Object o; try { o = getPropertySpi(property, clazz); if (o == null) { o = zero(clazz); } else if (clazz.isArray() && (o instanceof String[]) && !clazz.equals(String[].class)) { String[] str = (String[]) o; o = Array.newInstance(clazz.getComponentType(), str.length); for (int i = 0; i < str.length; i++) { Array.set(o, i, parse(str[i], clazz.getComponentType())); } } else if ((o instanceof String) && !clazz.equals(String.class)) { o = parse((String) o, clazz); } } catch (Exception x) { o = zero(clazz); } return o; } protected synchronized void setProperty(String property, Object value, Class<?> clazz) throws PropertyVetoException { boolean pc = (_pcSupport != null) && _pcSupport.hasListeners(property); boolean vc = (_vcSupport != null) && _vcSupport.hasListeners(property); Object oldVal = null; Object newVal = ((value != null) && clazz.equals(String.class) && !(value instanceof String)) ? value.toString() : value; if (pc || vc) { oldVal = getProperty(property, clazz); } if (vc) { fireVetoableChange(property, oldVal, value); } setPropertySpi(property, newVal, clazz); if (pc) { firePropertyChange(property, oldVal, value); } } protected synchronized Object getProxy() { return _proxy; } protected synchronized void addPropertyChangeListener(String property, PropertyChangeListener listener) { if (_pcSupport == null) { _pcSupport = new PropertyChangeSupport(_proxy); } _pcSupport.addPropertyChangeListener(property, listener); } protected synchronized void addVetoableChangeListener(String property, VetoableChangeListener listener) { if (_vcSupport == null) { _vcSupport = new VetoableChangeSupport(_proxy); } _vcSupport.addVetoableChangeListener(property, listener); } protected synchronized void firePropertyChange(String property, Object oldValue, Object newValue) { if (_pcSupport != null) { _pcSupport.firePropertyChange(property, oldValue, newValue); } } protected synchronized void fireVetoableChange(String property, Object oldValue, Object newValue) throws PropertyVetoException { if (_vcSupport != null) { _vcSupport.fireVetoableChange(property, oldValue, newValue); } } protected synchronized boolean hasProperty(String property) { boolean ret; try { ret = hasPropertySpi(property); } catch (Exception x) { ret = false; } return ret; } protected Object parse(String value, Class<?> clazz) throws IllegalArgumentException { return BeanTool.getInstance().parse(value, clazz); } protected synchronized void removePropertyChangeListener(String property, PropertyChangeListener listener) { if (_pcSupport != null) { _pcSupport.removePropertyChangeListener(property, listener); } } protected synchronized void removeVetoableChangeListener(String property, VetoableChangeListener listener) { if (_vcSupport != null) { _vcSupport.removeVetoableChangeListener(property, listener); } } protected Object zero(Class<?> clazz) { return BeanTool.getInstance().zero(clazz); } private synchronized void updateProxy(Object value) { if (_proxy == null) { _proxy = value; } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 8023 | Sven Erik Knop |
Complete rewrite of the configuration file, now based on an ini-file format. The ini file has a general [reader] section for settings like verbose, outputFile, case-sensitivity and so on. It also allows to set up a range of Actions and Filters. The section name here is the fully classified class name, followed by settings for the particular actions. An example will make this clearer: ================================================================ [reader] verbose=true [journal.action.UserRenamer] fileName=user.txt patch=True outputFile=user.out [journal.action.ClientRenamer] fileName=client.txt outputFile=client.out patch=true ================================================================ I will provide more example set-ups in the near future. Filters are classes implementing journal.action.Filter (soon to be journal.filter.Filter) which can be chained together and are all executed before the actions. Actions are applied in order that they are given in the config file. |