/// <summary> returns an Iterator to the collection in the #foreach() /// /// </summary> /// <param name="context"> current context /// </param> /// <param name="node"> AST node /// </param> /// <returns>Iterator to do the dataset /// /// </returns> private IEnumerator getIterator(InternalContextAdapter context, INode node) { /* * get our list object, and punt if it's null. */ Object listObject = node.jjtGetChild(2).value_Renamed(context); if (listObject == null) { return(null); } /* * See if we already know what type this is. * Use the introspection cache */ int type = UNKNOWN; IntrospectionCacheData icd = context.ICacheGet(this); System.Type c = listObject.GetType(); /* * if we have an entry in the cache, and the Class we have * cached is the same as the Class of the data object * then we are ok */ if (icd != null && icd.contextData == c) { /* dig the type out of the cata object */ type = ((System.Int32)icd.thingy); } /* * If we still don't know what this is, * figure out what type of object the list * element is, and get the iterator for it */ if (type == UNKNOWN) { if (listObject.GetType().IsArray) { type = INFO_ARRAY; } // NOTE: IDictionary needs to come before ICollection as it support ICollection else if (listObject is IDictionary) { type = INFO_MAP; } else if (listObject is ICollection) { type = INFO_COLLECTION; } else if (listObject is IEnumerable) { type = INFO_ENUMERABLE; } else if (listObject is IEnumerator) { type = INFO_ENUMERATION; } /* * if we did figure it out, cache it */ if (type != UNKNOWN) { icd = new IntrospectionCacheData(); icd.thingy = type; icd.contextData = c; context.ICachePut(this, icd); } } /* * now based on the type from either cache or examination... */ switch (type) { case INFO_COLLECTION: return(((ICollection)listObject).GetEnumerator()); case INFO_ENUMERABLE: return(((IEnumerable)listObject).GetEnumerator()); case INFO_ENUMERATION: rsvc.warn("Warning! The reference " + node.jjtGetChild(2).FirstToken.image + " is an Enumeration in the #foreach() loop at [" + Line + "," + Column + "]" + " in template " + context.CurrentTemplateName + ". Because it's not resetable," + " if used in more than once, this may lead to" + " unexpected results."); return((IEnumerator)listObject); case INFO_ARRAY: return(((Array)listObject).GetEnumerator()); case INFO_MAP: return(((IDictionary)listObject).GetEnumerator()); default: /* we have no clue what this is */ rsvc.warn("Could not determine type of enumerator (" + listObject.GetType().Name + ") in " + "#foreach loop for " + node.jjtGetChild(2).FirstToken.image + " at [" + Line + "," + Column + "]" + " in template " + context.CurrentTemplateName); return(null); } }
public void ICachePut(System.Object key, IntrospectionCacheData o) { icb.ICachePut(key, o); }
/// <seealso cref=" IntrospectionCacheData) /// element in the cache for specified key /// * /// "/> /// <param name="key"> key /// </param> /// <param name="o"> IntrospectionCacheData object to place in cache /// /// </param> public virtual void ICachePut(System.Object key, IntrospectionCacheData o) { introspectionCache[key] = o; }
/// <summary> invokes the method on the object passed in /// </summary> public override System.Object execute(System.Object o, InternalContextAdapter context) { AbstractExecutor executor = null; try { System.Type c = o.GetType(); /* * first, see if we have this information cached. */ IntrospectionCacheData icd = context.ICacheGet(this); /* * if we have the cache data and the class of the object we are * invoked with is the same as that in the cache, then we must * be allright. The last 'variable' is the method name, and * that is fixed in the template :) */ if (icd != null && icd.contextData == c) { executor = (AbstractExecutor) icd.thingy; } else { /* * otherwise, do the introspection, and cache it */ executor = doIntrospection(c); if (executor != null) { icd = new IntrospectionCacheData(); icd.contextData = c; icd.thingy = executor; context.ICachePut(this, icd); } } } catch (System.Exception e) { rsvc.error("ASTIdentifier.execute() : identifier = " + identifier + " : " + e); } /* * we have no executor... punt... */ if (executor == null) { return null; } /* * now try and execute. If we get a MIE, throw that * as the app wants to get these. If not, log and punt. */ try { return executor.execute(o, context); } catch (MethodInvocationException mie) { throw mie; } catch (System.Exception e) { rsvc.error("ASTIdentifier() : exception invoking method for identifier '" + identifier + "' in " + o.GetType() + " : " + e); } return null; }
/// <summary> /// invokes the method. Returns null if a problem, the /// actual return if the method returns something, or /// an empty string "" if the method returns void /// </summary> public override System.Object execute(System.Object o, InternalContextAdapter context) { /* * new strategy (strategery!) for introspection. Since we want * to be thread- as well as context-safe, we *must* do it now, * at execution time. There can be no in-node caching, * but if we are careful, we can do it in the context. */ MethodInfo method = null; PropertyInfo property = null; try { /* * check the cache */ IntrospectionCacheData icd = context.ICacheGet(this); System.Type c = o.GetType(); /* * like ASTIdentifier, if we have cache information, and the * Class of Object o is the same as that in the cache, we are * safe. */ if (icd != null && icd.contextData == c) { /* * sadly, we do need recalc the values of the args, as this can * change from visit to visit */ for (int j = 0; j < paramCount; j++) { params_Renamed[j] = jjtGetChild(j + 1).value_Renamed(context); } /* * and get the method from the cache */ if (icd.thingy is MethodInfo) { method = (MethodInfo)icd.thingy; } if (icd.thingy is PropertyInfo) { property = (PropertyInfo)icd.thingy; } } else { /* * otherwise, do the introspection, and then * cache it */ Object obj = doIntrospection(context, c); if (obj is MethodInfo) { method = (MethodInfo)obj; } if (obj is PropertyInfo) { property = (PropertyInfo)obj; } if (obj != null) { icd = new IntrospectionCacheData(); icd.contextData = c; icd.thingy = obj; context.ICachePut(this, icd); } } /* * if we still haven't gotten the method, either we are calling * a method that doesn't exist (which is fine...) or I screwed * it up. */ if (method == null && property == null) { return(null); } } catch (MethodInvocationException mie) { /* * this can come from the doIntrospection(), as the arg values * are evaluated to find the right method signature. We just * want to propogate it here, not do anything fancy */ throw mie; } catch (System.Exception e) { /* * can come from the doIntropection() also, from Introspector */ rsvc.error("ASTMethod.execute() : exception from introspection : " + e); return(null); } try { /* * get the returned object. It may be null, and that is * valid for something declared with a void return type. * Since the caller is expecting something to be returned, * as long as things are peachy, we can return an empty * String so ASTReference() correctly figures out that * all is well. */ Object obj = null; if (method != null) { obj = method.Invoke(o, (System.Object[])params_Renamed); if (obj == null && method.ReturnType == System.Type.GetType("System.Void")) { obj = String.Empty; } } else { obj = property.GetValue(o, null); } return(obj); } catch (System.Reflection.TargetInvocationException ite) { /* * In the event that the invocation of the method * itself throws an exception, we want to catch that * wrap it, and throw. We don't log here as we want to figure * out which reference threw the exception, so do that * above */ EventCartridge ec = context.EventCartridge; /* * if we have an event cartridge, see if it wants to veto * also, let non-Exception Throwables go... */ if (ec != null && ite.GetBaseException() is System.Exception) { try { return(ec.methodException(o.GetType(), methodName, (System.Exception)ite.GetBaseException())); } catch (System.Exception e) { throw new MethodInvocationException("Invocation of method '" + methodName + "' in " + o.GetType() + " threw exception " + e.GetType() + " : " + e.Message, e, methodName); } } else { /* * no event cartridge to override. Just throw */ throw new MethodInvocationException("Invocation of method '" + methodName + "' in " + o.GetType() + " threw exception " + ite.GetBaseException().GetType() + " : " + ite.GetBaseException().Message, ite.GetBaseException(), methodName); } } catch (System.Exception e) { rsvc.error("ASTMethod.execute() : exception invoking method '" + methodName + "' in " + o.GetType() + " : " + e); return(null); } }
/// <summary> invokes the method on the object passed in /// </summary> public override System.Object execute(System.Object o, InternalContextAdapter context) { AbstractExecutor executor = null; try { System.Type c = o.GetType(); /* * first, see if we have this information cached. */ IntrospectionCacheData icd = context.ICacheGet(this); /* * if we have the cache data and the class of the object we are * invoked with is the same as that in the cache, then we must * be allright. The last 'variable' is the method name, and * that is fixed in the template :) */ if (icd != null && icd.contextData == c) { executor = (AbstractExecutor)icd.thingy; } else { /* * otherwise, do the introspection, and cache it */ executor = doIntrospection(c); if (executor != null) { icd = new IntrospectionCacheData(); icd.contextData = c; icd.thingy = executor; context.ICachePut(this, icd); } } } catch (System.Exception e) { rsvc.error("ASTIdentifier.execute() : identifier = " + identifier + " : " + e); } /* * we have no executor... punt... */ if (executor == null) { return(null); } /* * now try and execute. If we get a MIE, throw that * as the app wants to get these. If not, log and punt. */ try { return(executor.execute(o, context)); } catch (MethodInvocationException mie) { throw mie; } catch (System.Exception e) { rsvc.error("ASTIdentifier() : exception invoking method for identifier '" + identifier + "' in " + o.GetType() + " : " + e); } return(null); }
/// <summary> /// invokes the method. Returns null if a problem, the /// actual return if the method returns something, or /// an empty string "" if the method returns void /// </summary> public override System.Object execute(System.Object o, InternalContextAdapter context) { /* * new strategy (strategery!) for introspection. Since we want * to be thread- as well as context-safe, we *must* do it now, * at execution time. There can be no in-node caching, * but if we are careful, we can do it in the context. */ MethodInfo method = null; PropertyInfo property = null; try { /* * check the cache */ IntrospectionCacheData icd = context.ICacheGet(this); System.Type c = o.GetType(); /* * like ASTIdentifier, if we have cache information, and the * Class of Object o is the same as that in the cache, we are * safe. */ if (icd != null && icd.contextData == c) { /* * sadly, we do need recalc the values of the args, as this can * change from visit to visit */ for (int j = 0; j < paramCount; j++) params_Renamed[j] = jjtGetChild(j + 1).value_Renamed(context); /* * and get the method from the cache */ if (icd.thingy is MethodInfo) { method = (MethodInfo) icd.thingy; } if (icd.thingy is PropertyInfo) { property = (PropertyInfo) icd.thingy; } } else { /* * otherwise, do the introspection, and then * cache it */ Object obj = doIntrospection(context, c); if (obj is MethodInfo) { method = (MethodInfo)obj; } if (obj is PropertyInfo) { property = (PropertyInfo)obj; } if (obj != null) { icd = new IntrospectionCacheData(); icd.contextData = c; icd.thingy = obj; context.ICachePut(this, icd); } } /* * if we still haven't gotten the method, either we are calling * a method that doesn't exist (which is fine...) or I screwed * it up. */ if (method == null && property == null) { return null; } } catch (MethodInvocationException mie) { /* * this can come from the doIntrospection(), as the arg values * are evaluated to find the right method signature. We just * want to propogate it here, not do anything fancy */ throw mie; } catch (System.Exception e) { /* * can come from the doIntropection() also, from Introspector */ rsvc.error("ASTMethod.execute() : exception from introspection : " + e); return null; } try { /* * get the returned object. It may be null, and that is * valid for something declared with a void return type. * Since the caller is expecting something to be returned, * as long as things are peachy, we can return an empty * String so ASTReference() correctly figures out that * all is well. */ Object obj = null; if (method != null) { obj = method.Invoke(o, (System.Object[]) params_Renamed); if (obj == null && method.ReturnType == System.Type.GetType("System.Void")) { obj = String.Empty; } } else { obj = property.GetValue(o, null); } return obj; } catch (System.Reflection.TargetInvocationException ite) { /* * In the event that the invocation of the method * itself throws an exception, we want to catch that * wrap it, and throw. We don't log here as we want to figure * out which reference threw the exception, so do that * above */ EventCartridge ec = context.EventCartridge; /* * if we have an event cartridge, see if it wants to veto * also, let non-Exception Throwables go... */ if (ec != null && ite.GetBaseException() is System.Exception) { try { return ec.methodException(o.GetType(), methodName, (System.Exception) ite.GetBaseException()); } catch (System.Exception e) { throw new MethodInvocationException("Invocation of method '" + methodName + "' in " + o.GetType() + " threw exception " + e.GetType() + " : " + e.Message, e, methodName); } } else { /* * no event cartridge to override. Just throw */ throw new MethodInvocationException("Invocation of method '" + methodName + "' in " + o.GetType() + " threw exception " + ite.GetBaseException().GetType() + " : " + ite.GetBaseException().Message, ite.GetBaseException(), methodName); } } catch (System.Exception e) { rsvc.error("ASTMethod.execute() : exception invoking method '" + methodName + "' in " + o.GetType() + " : " + e); return null; } }