/// <summary> /// Writes an exception into one or more log entries, storing them in entries with a given prefix /// </summary> /// <param name="source">Log source</param> /// <param name="ex">Exception</param> /// <param name="entries">Log entry list</param> /// <param name="prefix">Entry string prefix</param> public static void ToLogEntries( Source source, Exception ex, IList< Entry > entries, string prefix ) { if ( ex == null ) { return; } StackTraceInfo info = new StackTraceInfo( ex.StackTrace ); Entry baseEntry = new Entry( source, prefix + ex.Message ); if ( info.HasMatch ) { baseEntry.Locate( info.File, int.Parse( info.Line ), 1, info.Method ); info.NextMatch( ); } entries.Add( baseEntry ); while ( info.HasMatch ) { entries.Add( new Entry( source, prefix + "(call stack)" ).Locate( info.File, int.Parse( info.Line ), 1, info.Method ) ); info.NextMatch( ); } ToLogEntries( source, ex.InnerException, entries, prefix + "\t" ); }
/// <summary> /// Loads component XML from a stream /// </summary> public object Load( Stream stream, ISource source, LoadParameters parameters ) { if ( !( parameters is ComponentLoadParameters ) ) { ComponentLoadParameters newParameters = new ComponentLoadParameters( parameters.Target ); foreach ( IDynamicProperty property in parameters.Properties ) { newParameters.Properties.Add( property ); } parameters = newParameters; } parameters.CanCache = false; ErrorCollection errors = new ErrorCollection( string.Copy( source.Path ) ); XmlTextReader reader = new XmlTextReader( stream ); reader.WhitespaceHandling = WhitespaceHandling.Significant; try { if ( reader.MoveToContent( ) == XmlNodeType.None ) { AssetsLog.Warning( "XML component asset \"{0}\" was empty - returning null", source.Name ); return null; } } catch ( XmlException ex ) { AssetsLog.Error( "Moving to XML component asset \"{0}\" content threw an exception", source.Name ); Entry entry = new Entry( AssetsLog.GetSource( Severity.Error ), ex.Message ); Source.HandleEntry( entry.Locate( source.Path, ex.LineNumber, ex.LinePosition, "" ) ); throw new ApplicationException( string.Format( "Failed to load component XML asset \"{0}\" (see log for details)", source.Name ) ); } string cacheable = reader.GetAttribute( "cacheable" ); parameters.CanCache = ( cacheable != null ) && ( ( cacheable == "yes" ) || ( cacheable == "true" ) ); RootBuilder builder = ( RootBuilder )BaseBuilder.CreateBuilderFromReader( null, ( ComponentLoadParameters )parameters, errors, reader ); if ( errors.Count == 0 ) { BaseBuilder.SafePostCreate( builder ); if ( errors.Count == 0 ) { BaseBuilder.SafeResolve( builder, true ); } } if ( ( builder.BuildObject == null ) && ( errors.Count == 0 ) ) { errors.Add( builder, "Empty components file" ); } if ( errors.Count > 0 ) { foreach ( Entry error in errors ) { Source.HandleEntry( error ); } throw new ApplicationException( string.Format( "Failed to load component XML asset \"{0}\" (see log for details)", source.Name ) ); } // TODO: AP: bit dubious... if there's more than one object, return a list if ( builder.Children.Count == 0 ) { throw new ApplicationException( string.Format( "Failed to load component XML asset \"{0}\" - did not contain any components", source.Name ) ); } if ( builder.Children.Count == 1 ) { return builder.Children[ 0 ]; } return builder.Children; }
/// <summary> /// Loads code from a source /// </summary> public override object Load( ISource source, LoadParameters parameters ) { string typeToInstance = DynamicProperties.GetProperty< string >( parameters.Properties, InstanceTypeName, null ); IEnumerable< string > assemblies = DynamicProperties.GetProperty< IEnumerable< string > >( parameters.Properties, ReferencesName, new string[] { } ); using ( Stream stream = OpenStream( source ) ) { StreamReader reader = new StreamReader( stream ); string allLines = reader.ReadToEnd( ); CodeDomProvider provider = new CSharpCodeProvider( ); CompilerParameters compilerParams = new CompilerParameters( ); compilerParams.GenerateInMemory = true; #if DEBUG compilerParams.IncludeDebugInformation = true; #endif // Add referenced assemblies to compiler parameters foreach ( string assembly in assemblies ) { compilerParams.ReferencedAssemblies.Add( assembly ); } CompilerResults results = provider.CompileAssemblyFromSource( compilerParams, allLines ); if ( results.Errors.Count > 0 ) { // Failed to compile assembly - dump foreach ( CompilerError error in results.Errors ) { Entry entry = new Entry( AssetsLog.GetSource( error.IsWarning ? Severity.Warning : Severity.Error ), error.ErrorText ); entry.Locate( error.FileName, error.Line, error.Column, "" ); Source.HandleEntry( entry ); } return null; } // If the caller requested the instance of a specific type, then find that type in the // compiled assembly, and create an instance of it if ( typeToInstance != null ) { Type instanceType = results.CompiledAssembly.GetType( typeToInstance ); return Activator.CreateInstance( instanceType ); } // Find a type that implements IBuilder, instance it, then use the IBuilder.CreateInstance() // to create our required type foreach ( Type type in results.CompiledAssembly.GetTypes( ) ) { if ( typeof( IBuilder ).IsAssignableFrom( type ) ) { IBuilder builder = ( IBuilder )Activator.CreateInstance( type ); return builder.CreateInstance( type ); } } } return null; }
/// <summary> /// Creates an array of Entry objects by parsing the contents of a log stream /// </summary> /// <param name="reader">Log text reader</param> /// <returns>Returns entry array</returns> public static Entry[] CreateEntriesFromLogText( TextReader reader ) { List< Entry > entries = new List< Entry >( ); string text = reader.ReadToEnd( ); MatchCollection matches = LogEntryRegex.Matches( text ); //int numMatches = matches.Count; foreach ( Match curMatch in matches ) { string file = curMatch.Groups[ "File" ].Value; string line = curMatch.Groups[ "Line" ].Value; string column = curMatch.Groups[ "Column" ].Value; string source = curMatch.Groups[ "Source" ].Value; string message = curMatch.Groups[ "Message" ].Value; string thread = curMatch.Groups[ "Thread" ].Value; string method = curMatch.Groups[ "Method" ].Value; // TODO: AP: Time not written/read Entry newEntry = new Entry( Log.Source.BuildFromString( source ), message, thread, DateTime.Now.TimeOfDay ); newEntry.Locate( file, int.Parse( line ), int.Parse( column ), method ); entries.Add( newEntry ); } return entries.ToArray( ); }