// NAnt - A .NET build tool
// Copyright (C) 2001-2003 Gerry Shaw
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Jaroslaw Kowalski (jkowalski@users.sourceforge.net)
using System;
using System.IO;
using System.Collections;
using System.Reflection;
using System.Globalization;
using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Util;
namespace NAnt.Core {
[FunctionSet("property", "NAnt")]
public class ExpressionEvaluator : ExpressionEvalBase {
#region Private Instance Fields
private PropertyDictionary _properties;
private Hashtable _state;
private Stack _visiting;
private Project _project;
#endregion Private Instance Fields
#region Public Instance Constructors
public ExpressionEvaluator(Project project, PropertyDictionary properties, Hashtable state, Stack visiting) {
_project = project;
_properties = properties;
_state = state;
_visiting = visiting;
}
#endregion Public Instance Constructors
#region Public Instance Properties
public Project Project {
get { return _project; }
}
#endregion Public Instance Properties
#region Override implementation of ExpressionEvalBase
protected override object EvaluateProperty(string propertyName) {
return GetPropertyValue(propertyName);
}
protected override ParameterInfo[] GetFunctionParameters(string functionName) {
MethodInfo methodInfo = TypeFactory.LookupFunction(functionName, Project);
if (methodInfo == null) {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1052"), functionName));
}
return methodInfo.GetParameters();
}
protected override object EvaluateFunction(string functionName, object[] args) {
MethodInfo methodInfo = TypeFactory.LookupFunction(functionName, Project);
if (methodInfo == null) {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1052"), functionName));
}
try {
if (methodInfo.IsStatic) {
return methodInfo.Invoke(null, args);
} else if (methodInfo.DeclaringType.IsAssignableFrom(typeof(ExpressionEvaluator))) {
return methodInfo.Invoke(this, args);
} else {
// create new instance.
ConstructorInfo constructor = methodInfo.DeclaringType.GetConstructor(new Type[] {typeof(Project), typeof(PropertyDictionary)});
object o = constructor.Invoke(new object[] {_project, _properties});
return methodInfo.Invoke(o, args);
}
} catch (TargetInvocationException ex) {
if (ex.InnerException != null) {
// throw actual exception
throw ex.InnerException;
}
// re-throw exception
throw;
}
}
#endregion Override implementation of ExpressionEvalBase
#region Public Instance Methods
///
/// Gets the value of the specified property.
///
/// The name of the property to get the value of.
///
/// The value of the specified property.
///
[Function("get-value")]
public string GetPropertyValue(string propertyName) {
if (_properties.IsDynamicProperty(propertyName)) {
string currentState = (string)_state[propertyName];
// check for circular references
if (currentState == PropertyDictionary.Visiting) {
// Currently visiting this node, so have a cycle
throw PropertyDictionary.CreateCircularException(propertyName, _visiting);
}
_visiting.Push(propertyName);
_state[propertyName] = PropertyDictionary.Visiting;
string propertyValue = _properties.GetPropertyValue(propertyName);
if (propertyValue == null) {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1053"), propertyName));
}
Location propertyLocation = Location.UnknownLocation;
// TODO - get the proper location of the property declaration
propertyValue = _properties.ExpandProperties(propertyValue,
propertyLocation, _state, _visiting);
_visiting.Pop();
_state[propertyName] = PropertyDictionary.Visited;
return propertyValue;
} else {
string propertyValue = _properties.GetPropertyValue(propertyName);
if (propertyValue == null) {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1053"), propertyName));
}
return propertyValue;
}
}
#endregion Public Instance Methods
}
}