/********************************************************************** * Copyright (c) 2005-2009 ant4eclipse project team. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Nils Hartmann, Daniel Kasmeroglu, Gerd Wuetherich **********************************************************************/ package org.ant4eclipse.ant.platform.core.delegate.helper; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import org.ant4eclipse.ant.platform.core.delegate.MacroExecutionDelegate; import org.ant4eclipse.lib.core.Assure; import org.apache.tools.ant.Project; /** * <p> * Helper class that provides access to some internal ant project fields. During macro execution with the * {@link MacroExecutionDelegate} several properties and references are (temporarily) set. Once the execution has * finished, all properties and references have to be reset. * </p> * * @author Gerd Wütherich (gerd@gerd-wuetherich.de) * * @param <V> */ public abstract class AbstractAntProjectRaper<V> { /** the ant project */ private Project _antProject; /** the prefix used for the scoped values */ private String _prefix; /** the scoped values */ private Map<String, V> _scopedValues; /** the overridden values */ private Map<String, V> _overriddenValues; /** the value accessor */ private AntProjectValueAccessor<V> _valueAccessor; /** - */ private Thread _currentThread; /** * <p> * Creates a new instance of type {@link AbstractAntProjectRaper}. * </p> * * @param antProject * the ant project */ public AbstractAntProjectRaper(Project antProject, Thread thread) { this._antProject = antProject; this._currentThread = thread; } /** * <p> * </p> * * @return */ public Thread getCurrentThread() { return this._currentThread; } /** * <p> * Returns the ant project. * </p> * * @return the ant project. */ public final Project getAntProject() { return this._antProject; } /** * <p> * Sets the specified scoped values. * </p> * * @param scopedValues * the scoped values. * @param prefix * the prefix used for the scoped values. */ public final void setScopedValues(Map<String, V> scopedValues, String prefix) { Assure.assertTrue(this._scopedValues == null, "Scoped values are already set!"); Assure.notNull("scopedValues", scopedValues); // set the scoped values this._scopedValues = scopedValues; this._overriddenValues = new HashMap<String, V>(); // set the prefix this._prefix = (prefix != null && prefix.trim().length() > 0) ? prefix + "." : ""; // iterate over all scoped properties Iterator<Entry<String, V>> iterator = this._scopedValues.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, V> entry = iterator.next(); String key = (this._prefix + entry.getKey()); // store the property if it already exists V existingValue = this._valueAccessor.getValue(key); if (existingValue != null) { this._overriddenValues.put(key, existingValue); } V newValue = entry.getValue(); this._valueAccessor.setValue(key, newValue); } } /** * <p> * Unsets all * </p> */ public final void unsetScopedValues() { Assure.assertTrue(this._scopedValues != null, "Scoped values must be set!"); // unset scopes value Iterator<String> keyIterator = this._scopedValues.keySet().iterator(); while (keyIterator.hasNext()) { String key = (this._prefix + keyIterator.next()); this._valueAccessor.unsetValue(key); // reset the property if it existed before executing the macro if (this._overriddenValues.containsKey(key)) { this._valueAccessor.setValue(key, this._overriddenValues.get(key)); } } this._scopedValues = null; } /** * Object rape: fondle the private parts of an object without it's permission. * * @param instance * the object instance * @param fieldName * the name of the field * @return an object representing the value of the field * @exception IllegalAccessException * foiled by the security manager * @exception NoSuchFieldException * Darn, nothing to fondle */ public static Object getValue(Object instance, String fieldName) throws IllegalAccessException, NoSuchFieldException { Field field = getField(instance.getClass(), fieldName); field.setAccessible(true); return field.get(instance); } /** * Object rape: fondle the private parts of an object without it's permission. * * @param thisClass * The class to rape. * @param fieldName * The field to fondle * @return The field value * @exception NoSuchFieldException * Darn, nothing to fondle. */ public static Field getField(Class<?> thisClass, String fieldName) throws NoSuchFieldException { if (thisClass == null) { throw new NoSuchFieldException("Invalid field : " + fieldName); } try { return thisClass.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { return getField(thisClass.getSuperclass(), fieldName); } } public void setValueAccessor(AntProjectValueAccessor<V> valueAccessor) { this._valueAccessor = valueAccessor; } /** * @author Gerd Wütherich (gerd@gerd-wuetherich.de) * * @param <V> */ public interface AntProjectValueAccessor<V> { /** * @param key * @return */ V getValue(String key); /** * @param key * @param value */ void setValue(String key, V value); /** * @param key */ void unsetValue(String key); } }