/[xmltv_parser]/trunk/libxmltv/Core/XMLTVRuntimeInstance.cs
ViewVC logotype

Annotation of /trunk/libxmltv/Core/XMLTVRuntimeInstance.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 189 - (hide annotations) (download)
Sat Mar 16 19:56:47 2013 UTC (7 years, 8 months ago) by william
File size: 23742 byte(s)

1 william 36 using System;
2     using System.Collections.Generic;
3     using System.Linq;
4     using System.Text;
5     using libxmltv.Interfaces;
6 william 46 using System.ComponentModel;
7 william 54 using System.Windows.Forms;
8     using System.Threading;
9 william 56 using System.Reflection;
10     using System.Globalization;
11     using System.Diagnostics;
12 william 73 using System.Xml.Linq;
13 william 167 using Enterprise.Logging;
14     using System.IO;
15 william 36
16     namespace libxmltv.Core
17     {
18 william 49 [Serializable]
19 william 56 internal class XMLTVRuntimeInstance : MarshalByRefObject,
20     IXMLTVRuntimeInstance,
21     ISerializer<XMLTVRuntimeInstance>,
22     IGetCreatedInstanceEvent,
23     ISetCreatedInstanceEvent,
24     IDestroyInstance,
25     IRuntimeInstanceLoader<XMLTVRuntimeInstance>
26 william 36 {
27 william 56 [NonSerialized]
28 william 54 Thread worker;
29 william 72 public XMLTVRuntimeInstance() { init(); }
30     public XMLTVRuntimeInstance(string xmlfile) : this(xmlfile, null) { }
31     public XMLTVRuntimeInstance(string xmlfile, EventHandler<EventArgs> handler)
32     : this()
33 william 56 {
34 william 72 this.OnInstanceCreated += handler;
35     worker = new Thread(new ParameterizedThreadStart(CreateInstance)); worker.Start(xmlfile);
36 william 56 }
37 william 72 private void CreateInstance(object xmlfile)
38 william 54 {
39 william 72 using (XMLTVInstance instance = new XMLTVInstance(xmlfile.ToString()))
40 william 45 {
41 william 72 this.LoadFromInstance(instance.GetInstance());
42     OnCreatedInstance(this, new EventArgs());
43 william 45 }
44     }
45 william 72
46     private void OnCreatedInstance(object sender, EventArgs e)
47     {
48     if (OnInstanceCreated != null) { OnInstanceCreated.Invoke(sender, e); }
49     }
50 william 36
51 william 72 private void init()
52     {
53 william 77 this.Source = new XMLTVSource();
54 william 120 this.Channels = new ChannelList();
55     this.Programs = new ProgramList();
56 william 72 this.XmlFile_Name = string.Empty;
57     this.XmlFile_FullName = string.Empty;
58     this.XmlDoc = string.Empty;
59     this.OnInstanceCreated = null;
60 william 120 this.ExtraEntries = new ExtraList();
61 william 72 }
62    
63     #region IXMLTVRuntimeInstance members
64     private bool _IsAborting;
65     public bool IsAborting { get { return _IsAborting; } private set { _IsAborting = value; } }
66    
67    
68     private string _XmlFile_Name;
69     public string XmlFile_Name { get { return _XmlFile_Name; } set { _XmlFile_Name = value; } }
70     private string _XmlFile_FullName;
71     public string XmlFile_FullName { get { return _XmlFile_FullName; } set { _XmlFile_FullName = value; } }
72    
73 william 56 private string _XmlDoc;
74 william 73 public string XmlDoc { get { return _XmlDoc; } set { _XmlDoc = value; } }
75 william 77 private IXMLTVSource _Source;
76     public IXMLTVSource Source { get { return _Source; } set { _Source = value; } }
77 william 120 private ChannelList _Channels;
78     public ChannelList Channels { get { return _Channels; } set { _Channels = value; } }
79     private ProgramList _Programs;
80     public ProgramList Programs { get { return _Programs; } set { _Programs = value; } }
81 william 107
82 william 120 private ExtraList _ExtraEntries;
83     public ExtraList ExtraEntries { get { return _ExtraEntries; } set { _ExtraEntries = value; } }
84 william 72 #endregion
85     #region IOnInstanceCreated members
86 william 56 [NonSerialized]
87     private EventHandler<EventArgs> _OnInstanceCreated;
88     public EventHandler<EventArgs> OnInstanceCreated { get { return _OnInstanceCreated; } set { _OnInstanceCreated = value; } }
89 william 72 #endregion
90     #region IGetCreatedInstanceEvent members
91 william 54 public EventHandler<EventArgs> GetOnInstanceCreated() { return OnInstanceCreated; }
92 william 72 #endregion
93     #region ISetCreatedInstanceEvent members
94 william 54 public void SetOnInstanceCreated(EventHandler<EventArgs> event_instance) { OnInstanceCreated = event_instance; }
95 william 72 #endregion
96     #region ISerializer<XMLTVRuntimeInstance> members
97     public IXMLTVSerializer<XMLTVRuntimeInstance> Serializer { get { return new XMLTVSerializer<XMLTVRuntimeInstance>(this); } }
98     #endregion
99     #region IDestroyInstance member
100 william 54 public void DestroyInstance()
101 william 46 {
102 william 55 xmltv_logger.Debug.WriteLine("Destoying Instance of: '{0}'", this.GetType().Name);
103 william 54 this.IsAborting = true;
104     if (worker == null)
105 william 46 {
106 william 55 xmltv_logger.Debug.WriteLine("Unable to destroy instance of: '{0}' - worker thread is null", this.GetType().Name);
107 william 54 return;
108 william 46 }
109 william 54 else
110     {
111     if (worker.IsAlive)
112     {
113 william 55 xmltv_logger.Verbose.Debug.WriteLine("Requesting Instance to Abort...");
114 william 72 while (worker.IsAlive) { worker.Abort(); Application.DoEvents(); }
115 william 54 }
116 william 72 else { xmltv_logger.Debug.WriteLine("Instance of: '{0}'- already destroyed.", this.GetType().Name); }
117 william 54 }
118 william 46 }
119 william 72 #endregion
120     #region IRuntimeInstanceLoader<XMLTVRuntimeInstance> member
121 william 56 public XMLTVRuntimeInstance LoadFromInstance(XMLTVRuntimeInstance instance)
122     {
123     if (instance == null)
124     {
125     throw new NullReferenceException("Failed to load from instance because the instance is null.");
126     }
127 william 72 xmltv_logger.Debug.WriteLine("Loading from instance...");
128 william 76 CloneFromInstance(ref instance);
129     xmltv_logger.Debug.WriteLine("Loaded from instance...");
130 william 72 if (this.Source != null)
131 william 56 {
132 william 77 xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Created by '{1}' - original source file: '{2}'", this.Source.SourceName, this.Source.GeneratorName, this.XmlFile_FullName);
133 william 56 }
134     else
135     {
136 william 72 xmltv_logger.Error.WriteLine("Source Property is null.");
137     throw new NullReferenceException("Source Property is null.");
138 william 56 }
139 william 72 if (this.Channels != null)
140 william 56 {
141 william 189 this.Channels.TrimExcess();
142 william 77 xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Channels from source '{1}'", this.Channels.Count, this.Source.SourceName);
143 william 56 }
144     else
145     {
146 william 72 xmltv_logger.Error.WriteLine("Channels Property is null.");
147     throw new NullReferenceException("Channels Property is null.");
148 william 56 }
149 william 72 if (this.Programs != null)
150 william 56 {
151 william 189 this.Programs.TrimExcess();
152 william 77 xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Programs from source '{1}'", this.Programs.Count, this.Source.SourceName);
153 william 56 }
154     else
155     {
156 william 72 xmltv_logger.Error.WriteLine("Programs Property is null.");
157     throw new NullReferenceException("Programs Property is null.");
158 william 76 }
159 william 56 return instance;
160     }
161 william 72 #endregion
162     #region CloneFromInstance
163 william 56 private void CloneFromInstance(ref XMLTVRuntimeInstance instance)
164     {
165 william 72 xmltv_logger.Debug.WriteLine("Cloning from instance...");
166 william 56 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
167     CultureInfo culture = CultureInfo.CurrentCulture;
168     Type t = typeof(XMLTVRuntimeInstance);
169     foreach (var field in t.GetFields(flags))
170     {
171     try
172     {
173 william 72 if (field.IsNotSerialized) { continue; }
174     var f = instance.GetType().GetField(field.Name, flags);
175     var v = f.GetValue(instance);
176     if (v != null)
177 william 56 {
178 william 72 field.SetValue(this, v);
179     }
180     else
181     {
182     xmltv_logger.Debug.WriteLine("Attempted to set field: '{0}' with a null value. The operation was aborted.", f.Name);
183 william 56 continue;
184     }
185     }
186     catch (Exception ex)
187     {
188     throw new Exception(string.Format("Unable to copy value for field: '{0}' from instance", field.Name), ex);
189     }
190     }
191     foreach (var property in t.GetProperties(flags))
192     {
193     try
194     {
195     var f = instance.GetType().GetProperty(property.Name);
196     object value = null;
197     try
198     {
199     value = f.GetValue(instance, null);
200     }
201     catch (ArgumentException ex) { if (ex.Message == "Property get method not found.") { Debug.WriteLine(ex.ToString()); } else { throw ex; } }
202     try
203     {
204 william 72 if (value != null)
205     {
206     property.SetValue(this, value, null);
207     }
208     else
209     {
210     xmltv_logger.Debug.WriteLine("Attempted to set property: '{0}' with a null value. The operation was aborted.", f.Name);
211     continue;
212     }
213 william 56 }
214     catch (ArgumentException ex) { if (ex.Message == "Property set method not found.") { Debug.WriteLine(ex.ToString()); } else { throw ex; } }
215    
216     }
217     catch (Exception ex)
218     {
219     throw new Exception(string.Format("Unable to copy value for property: '{0}' from instance", property.Name), ex);
220     }
221     }
222 william 72 xmltv_logger.Debug.WriteLine("Cloned from instance...");
223 william 56 }
224 william 72 #endregion
225 william 36 }
226    
227 william 72 internal class XMLTVInstance : IGetInstance<XMLTVRuntimeInstance>, IDisposable
228 william 36 {
229 william 73 public void Dispose()
230     {
231     //throw new NotImplementedException();
232     }
233    
234 william 72 private XMLTVRuntimeInstance gInstance;
235     public XMLTVRuntimeInstance GetInstance() { return gInstance; }
236     public XMLTVInstance(string xmlfile)
237     {
238     try
239     {
240     CreateLoader(xmlfile);
241 william 73 CreateParser();
242 william 72 }
243 william 79 catch (ThreadAbortException ex) { Debug.WriteLine(ex.ToString()); }
244 william 72 catch (Exception ex)
245     {
246     xmltv_logger.Error.WriteLine(ex.ToString());
247     }
248 william 36 }
249    
250 william 72 private void CreateLoader(string xml_file)
251 william 36 {
252 william 81 xmltv_logger.Verbose.Debug.WriteLine("Creating loader handle");
253 william 72 gInstance = new XMLTVRuntimeInstance();
254     object raw_instance = null;
255 william 81 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
256     CultureInfo culture = CultureInfo.CurrentCulture;
257 william 72 Assembly asm = Assembly.GetExecutingAssembly();
258     var types = asm.GetTypes();
259 william 81 Type handler_type = null;
260 william 72 foreach (var type in types)
261     {
262     if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
263     {
264 william 81 //xmltv_logger.Verbose.Debug.WriteLine("Type: '{0}' Base: '{1}'", type.Name, type.BaseType == null ? "none" : type.BaseType.Name);
265 william 72 object[] args = new object[] { xml_file, gInstance };
266 william 81 var iface = type.GetInterface("IXMLTVHandler", true);
267     if (iface != null)
268 william 72 {
269 william 81 var handler_prop = type.GetProperty("Handler");
270     if (handler_prop != null)
271     {
272     var ctors = type.GetConstructors(flags);
273     bool has_string_ctor = false;
274     foreach (var ctor in ctors) { if (ctor.GetParameters().Count() == 1 && ctor.GetParameters()[0].ParameterType == typeof(string)) { has_string_ctor = true; } }
275     if (!has_string_ctor) { continue; }
276     raw_instance = Activator.CreateInstance(type, flags, null, new object[] { xml_file}, culture);
277     if (raw_instance != null)
278     {
279     object handler_value = handler_prop.GetValue(raw_instance, null);
280     if (handler_value != null && handler_value.ToString() == xml_file)
281     {
282     handler_type = type;
283     break;
284     }
285     }
286     }
287 william 72 }
288     }
289     }
290 william 81 if (handler_type == null) { throw new Exception("Unable to find a compatible XMLTV Data Loader."); }
291     xmltv_logger.Verbose.Debug.WriteLine("Created loader handle");
292     raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] {xml_file , gInstance }, culture);
293 william 72 if (raw_instance == null) { throw new NullReferenceException("Found a compatible XMLTV Data Loader, but it returned invalid data."); }
294     IGetInstance<XMLTVRuntimeInstance> getter_instance = (raw_instance as IGetInstance<XMLTVRuntimeInstance>);
295     if (getter_instance != null) { gInstance = getter_instance.GetInstance(); }
296     else { throw new Exception("Found a compatible XMLTV Data Loader, but was unable to obtain the instance holding the data"); }
297 william 36 }
298 william 73 private void CreateParser()
299 william 36 {
300 william 73 var doc = XDocument.Parse(this.GetInstance().XmlDoc);
301 william 76 var root_element = doc.Root;
302 william 74 CreateHandlerForRootNode(root_element);
303 william 76 var nodes = doc.Root.Elements().ToList();
304 william 72
305 william 76 double total_nodes = nodes.Count;
306     double node_index = 0;
307     double progress = 0;
308 william 74 foreach(var node in nodes)
309     {
310 william 78 if (this.GetInstance().IsAborting)
311     {
312     break;
313     }
314 william 76 if (!CreateHandlerForNode(node)) { xmltv_logger.Verbose.Debug.WriteLine("Unable to create handler for node: '{0}'", node.Name.ToString()); }
315     node_index++;
316     progress = 100.0 * (node_index / total_nodes);
317 william 167 xmltv_logger.ReportProgress(this, new ReportProgressEventArgs((int)progress, string.Format("Loading {0} ==> {1:00}%", this.gInstance.XmlFile_Name, (int)progress)));
318 william 76 Application.DoEvents();
319 william 74 }
320 william 36 }
321 william 44
322 william 73
323 william 74 private void CreateHandlerForRootNode(XElement root)
324     {
325     if (root == null) { throw new NullReferenceException("Root element is null"); }
326     if (root.Name == null) { throw new NullReferenceException("Root element's Name is null"); }
327     var root_name = root.Name.ToString();
328     xmltv_logger.Verbose.Debug.WriteLine("Creating handler for root: '{0}'", root_name.ToString());
329 william 73 object raw_instance = null;
330     BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
331     CultureInfo culture = CultureInfo.CurrentCulture;
332     Assembly asm = Assembly.GetExecutingAssembly();
333     var types = asm.GetTypes();
334     Type handler_type = null;
335     foreach (var type in types)
336     {
337     if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
338 william 81 {
339     var iface = type.GetInterface("IXMLTVHandler", true);
340     if (iface != null)
341 william 73 {
342     var handler_prop = type.GetProperty("Handler");
343     if (handler_prop != null)
344     {
345 william 81 var ctors = type.GetConstructors(flags);
346     bool has_default_ctor = false;
347     foreach (var ctor in ctors) { if (ctor.GetParameters().Count() == 0) { has_default_ctor = true; } }
348 william 111 ctors = null;
349 william 81 if (!has_default_ctor) { continue; }
350 william 73 raw_instance = Activator.CreateInstance(type, flags, null, new object[0], culture);
351     if (raw_instance != null)
352     {
353     object handler_value = handler_prop.GetValue(raw_instance, null);
354 william 74 if (handler_value != null && handler_value.ToString() == root_name)
355 william 73 {
356     handler_type = type;
357 william 111 handler_value = null;
358     raw_instance = null;
359     handler_prop = null;
360     iface = null;
361 william 73 break;
362     }
363 william 111 handler_value = null;
364 william 81 }
365 william 111 raw_instance = null;
366 william 73 }
367 william 111 handler_prop = null;
368 william 73 }
369 william 111 iface = null;
370 william 73 }
371     }
372 william 111 asm = null;
373     types = null;
374 william 82 if (handler_type == null)
375     {
376     StringBuilder node_builder = new StringBuilder();
377     node_builder.AppendFormat("<{0} ", root.Name);
378 william 83 if (root.HasAttributes) { foreach (var attribute in root.Attributes()) { node_builder.AppendFormat("{0}=\"{1}\" ", attribute.Name, attribute.Value); } }
379 william 82 string node_text = string.Format("{0}>", node_builder.ToString().TrimEnd(new char[] { ' ' }));
380 william 83 throw new Exception(string.Format("Unable to find a compatible handler to parse node: {0}", node_text));
381 william 82 }
382 william 74 xmltv_logger.Verbose.Debug.WriteLine("Created handler for root: '{0}'", root_name.ToString());
383 william 73 raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { gInstance }, culture);
384 william 111 raw_instance = null;
385     flags = 0;
386     culture = null;
387 william 44 }
388 william 72
389 william 74 private bool CreateHandlerForNode(XElement node)
390     {
391     if (node == null) { throw new NullReferenceException("Node element is null"); }
392     if (node.Name == null) { throw new NullReferenceException("Node element's Name is null"); }
393 william 111 //var node_name = node.Name.ToString();
394 william 74
395 william 111 xmltv_logger.Verbose.Debug.WriteLine("Creating handler for node: '{0}'", node.Name.ToString());
396 william 74 object raw_instance = null;
397     BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
398     CultureInfo culture = CultureInfo.CurrentCulture;
399     Assembly asm = Assembly.GetExecutingAssembly();
400     var types = asm.GetTypes();
401     Type handler_type = null;
402     foreach (var type in types)
403     {
404     if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
405     {
406 william 81 var iface = type.GetInterface("IXMLTVHandler", true);
407     if (iface != null)
408 william 74 {
409     var handler_prop = type.GetProperty("Handler");
410     if (handler_prop != null)
411     {
412 william 81 var ctors = type.GetConstructors(flags);
413     bool has_default_ctor = false;
414     foreach (var ctor in ctors) { if (ctor.GetParameters().Count() == 0) { has_default_ctor = true; } }
415 william 111 ctors = null;
416 william 81 if (!has_default_ctor) { continue; }
417 william 74 raw_instance = Activator.CreateInstance(type, flags, null, new object[0], culture);
418     if (raw_instance != null)
419     {
420     object handler_value = handler_prop.GetValue(raw_instance, null);
421 william 111 if (handler_value != null && handler_value.ToString() == node.Name.ToString())
422 william 74 {
423     handler_type = type;
424 william 111 handler_value = null;
425     raw_instance = null;
426     handler_prop = null;
427     iface = null;
428 william 74 break;
429     }
430 william 111 handler_value = null;
431 william 74 }
432 william 111 raw_instance = null;
433 william 74 }
434 william 111 handler_prop = null;
435 william 74 }
436 william 111 iface = null;
437 william 74 }
438     }
439 william 111 asm = null;
440     types = null;
441 william 107 if (handler_type == null)
442 william 82 {
443 william 107 try
444     {
445     raw_instance = Activator.CreateInstance(typeof(UnhandledNodeData), flags, null, new object[] { gInstance, node }, culture);
446     }
447     catch (Exception ex) { throw ex; }
448    
449     if (raw_instance == null)
450     {
451     StringBuilder node_builder = new StringBuilder();
452     node_builder.AppendFormat("<{0} ", node.Name);
453     if (node.HasAttributes) { foreach (var attribute in node.Attributes()) { node_builder.AppendFormat("{0}=\"{1}\" ", attribute.Name, attribute.Value); } }
454     string node_text = string.Format("{0}>", node_builder.ToString().TrimEnd(new char[] { ' ' }));
455     throw new Exception(string.Format("Unable to find a compatible handler to parse node: {0}", node_text));
456     }
457 william 82 }
458 william 107 else
459     {
460 william 111 xmltv_logger.Verbose.Debug.WriteLine("Created handler for node: '{0}'", node.Name.ToString());
461 william 107 raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { gInstance, node }, culture);
462     }
463 william 111 raw_instance = null;
464     flags = 0;
465     culture = null;
466     node = null;
467 william 74 return true;
468     }
469 william 107 #region UnhandledExtraMetaData
470     private class UnhandledNodeData : XMLTVBase<XMLTVRuntimeInstance>
471     {
472     public UnhandledNodeData() : base(null, null) { }
473     public UnhandledNodeData(XMLTVRuntimeInstance instance, XElement node)
474     : base(instance, null)
475     {
476     if (node == null) { throw new NullReferenceException("The node instance was null"); }
477     xmltv_logger.Verbose.Debug.WriteLine("Parsng unhandled node data: {0}", node.Name.ToString());
478     if (this.GetInstance() != null)
479     {
480     ExtraMetaData data = new ExtraMetaData(node);
481     instance.ExtraEntries.Add(data);
482 william 111 data = null;
483 william 107 }
484 william 111 node = null;
485 william 107 }
486     }
487     #endregion
488 william 72
489 william 36 }
490     }

  ViewVC Help
Powered by ViewVC 1.1.22