/[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 167 - (hide annotations) (download)
Sat Mar 16 13:26:09 2013 UTC (7 years, 8 months ago) by william
File size: 23652 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 77 xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Channels from source '{1}'", this.Channels.Count, this.Source.SourceName);
142 william 56 }
143     else
144     {
145 william 72 xmltv_logger.Error.WriteLine("Channels Property is null.");
146     throw new NullReferenceException("Channels Property is null.");
147 william 56 }
148 william 72 if (this.Programs != null)
149 william 56 {
150 william 77 xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Programs from source '{1}'", this.Programs.Count, this.Source.SourceName);
151 william 56 }
152     else
153     {
154 william 72 xmltv_logger.Error.WriteLine("Programs Property is null.");
155     throw new NullReferenceException("Programs Property is null.");
156 william 76 }
157 william 56 return instance;
158     }
159 william 72 #endregion
160     #region CloneFromInstance
161 william 56 private void CloneFromInstance(ref XMLTVRuntimeInstance instance)
162     {
163 william 72 xmltv_logger.Debug.WriteLine("Cloning from instance...");
164 william 56 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
165     CultureInfo culture = CultureInfo.CurrentCulture;
166     Type t = typeof(XMLTVRuntimeInstance);
167     foreach (var field in t.GetFields(flags))
168     {
169     try
170     {
171 william 72 if (field.IsNotSerialized) { continue; }
172     var f = instance.GetType().GetField(field.Name, flags);
173     var v = f.GetValue(instance);
174     if (v != null)
175 william 56 {
176 william 72 field.SetValue(this, v);
177     }
178     else
179     {
180     xmltv_logger.Debug.WriteLine("Attempted to set field: '{0}' with a null value. The operation was aborted.", f.Name);
181 william 56 continue;
182     }
183     }
184     catch (Exception ex)
185     {
186     throw new Exception(string.Format("Unable to copy value for field: '{0}' from instance", field.Name), ex);
187     }
188     }
189     foreach (var property in t.GetProperties(flags))
190     {
191     try
192     {
193     var f = instance.GetType().GetProperty(property.Name);
194     object value = null;
195     try
196     {
197     value = f.GetValue(instance, null);
198     }
199     catch (ArgumentException ex) { if (ex.Message == "Property get method not found.") { Debug.WriteLine(ex.ToString()); } else { throw ex; } }
200     try
201     {
202 william 72 if (value != null)
203     {
204     property.SetValue(this, value, null);
205     }
206     else
207     {
208     xmltv_logger.Debug.WriteLine("Attempted to set property: '{0}' with a null value. The operation was aborted.", f.Name);
209     continue;
210     }
211 william 56 }
212     catch (ArgumentException ex) { if (ex.Message == "Property set method not found.") { Debug.WriteLine(ex.ToString()); } else { throw ex; } }
213    
214     }
215     catch (Exception ex)
216     {
217     throw new Exception(string.Format("Unable to copy value for property: '{0}' from instance", property.Name), ex);
218     }
219     }
220 william 72 xmltv_logger.Debug.WriteLine("Cloned from instance...");
221 william 56 }
222 william 72 #endregion
223 william 36 }
224    
225 william 72 internal class XMLTVInstance : IGetInstance<XMLTVRuntimeInstance>, IDisposable
226 william 36 {
227 william 73 public void Dispose()
228     {
229     //throw new NotImplementedException();
230     }
231    
232 william 72 private XMLTVRuntimeInstance gInstance;
233     public XMLTVRuntimeInstance GetInstance() { return gInstance; }
234     public XMLTVInstance(string xmlfile)
235     {
236     try
237     {
238     CreateLoader(xmlfile);
239 william 73 CreateParser();
240 william 72 }
241 william 79 catch (ThreadAbortException ex) { Debug.WriteLine(ex.ToString()); }
242 william 72 catch (Exception ex)
243     {
244     xmltv_logger.Error.WriteLine(ex.ToString());
245     }
246 william 36 }
247    
248 william 72 private void CreateLoader(string xml_file)
249 william 36 {
250 william 81 xmltv_logger.Verbose.Debug.WriteLine("Creating loader handle");
251 william 72 gInstance = new XMLTVRuntimeInstance();
252     object raw_instance = null;
253 william 81 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
254     CultureInfo culture = CultureInfo.CurrentCulture;
255 william 72 Assembly asm = Assembly.GetExecutingAssembly();
256     var types = asm.GetTypes();
257 william 81 Type handler_type = null;
258 william 72 foreach (var type in types)
259     {
260     if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
261     {
262 william 81 //xmltv_logger.Verbose.Debug.WriteLine("Type: '{0}' Base: '{1}'", type.Name, type.BaseType == null ? "none" : type.BaseType.Name);
263 william 72 object[] args = new object[] { xml_file, gInstance };
264 william 81 var iface = type.GetInterface("IXMLTVHandler", true);
265     if (iface != null)
266 william 72 {
267 william 81 var handler_prop = type.GetProperty("Handler");
268     if (handler_prop != null)
269     {
270     var ctors = type.GetConstructors(flags);
271     bool has_string_ctor = false;
272     foreach (var ctor in ctors) { if (ctor.GetParameters().Count() == 1 && ctor.GetParameters()[0].ParameterType == typeof(string)) { has_string_ctor = true; } }
273     if (!has_string_ctor) { continue; }
274     raw_instance = Activator.CreateInstance(type, flags, null, new object[] { xml_file}, culture);
275     if (raw_instance != null)
276     {
277     object handler_value = handler_prop.GetValue(raw_instance, null);
278     if (handler_value != null && handler_value.ToString() == xml_file)
279     {
280     handler_type = type;
281     break;
282     }
283     }
284     }
285 william 72 }
286     }
287     }
288 william 81 if (handler_type == null) { throw new Exception("Unable to find a compatible XMLTV Data Loader."); }
289     xmltv_logger.Verbose.Debug.WriteLine("Created loader handle");
290     raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] {xml_file , gInstance }, culture);
291 william 72 if (raw_instance == null) { throw new NullReferenceException("Found a compatible XMLTV Data Loader, but it returned invalid data."); }
292     IGetInstance<XMLTVRuntimeInstance> getter_instance = (raw_instance as IGetInstance<XMLTVRuntimeInstance>);
293     if (getter_instance != null) { gInstance = getter_instance.GetInstance(); }
294     else { throw new Exception("Found a compatible XMLTV Data Loader, but was unable to obtain the instance holding the data"); }
295 william 36 }
296 william 73 private void CreateParser()
297 william 36 {
298 william 73 var doc = XDocument.Parse(this.GetInstance().XmlDoc);
299 william 76 var root_element = doc.Root;
300 william 74 CreateHandlerForRootNode(root_element);
301 william 76 var nodes = doc.Root.Elements().ToList();
302 william 72
303 william 76 double total_nodes = nodes.Count;
304     double node_index = 0;
305     double progress = 0;
306 william 74 foreach(var node in nodes)
307     {
308 william 78 if (this.GetInstance().IsAborting)
309     {
310     break;
311     }
312 william 76 if (!CreateHandlerForNode(node)) { xmltv_logger.Verbose.Debug.WriteLine("Unable to create handler for node: '{0}'", node.Name.ToString()); }
313     node_index++;
314     progress = 100.0 * (node_index / total_nodes);
315 william 167 xmltv_logger.ReportProgress(this, new ReportProgressEventArgs((int)progress, string.Format("Loading {0} ==> {1:00}%", this.gInstance.XmlFile_Name, (int)progress)));
316 william 76 Application.DoEvents();
317 william 74 }
318 william 36 }
319 william 44
320 william 73
321 william 74 private void CreateHandlerForRootNode(XElement root)
322     {
323     if (root == null) { throw new NullReferenceException("Root element is null"); }
324     if (root.Name == null) { throw new NullReferenceException("Root element's Name is null"); }
325     var root_name = root.Name.ToString();
326     xmltv_logger.Verbose.Debug.WriteLine("Creating handler for root: '{0}'", root_name.ToString());
327 william 73 object raw_instance = null;
328     BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
329     CultureInfo culture = CultureInfo.CurrentCulture;
330     Assembly asm = Assembly.GetExecutingAssembly();
331     var types = asm.GetTypes();
332     Type handler_type = null;
333     foreach (var type in types)
334     {
335     if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
336 william 81 {
337     var iface = type.GetInterface("IXMLTVHandler", true);
338     if (iface != null)
339 william 73 {
340     var handler_prop = type.GetProperty("Handler");
341     if (handler_prop != null)
342     {
343 william 81 var ctors = type.GetConstructors(flags);
344     bool has_default_ctor = false;
345     foreach (var ctor in ctors) { if (ctor.GetParameters().Count() == 0) { has_default_ctor = true; } }
346 william 111 ctors = null;
347 william 81 if (!has_default_ctor) { continue; }
348 william 73 raw_instance = Activator.CreateInstance(type, flags, null, new object[0], culture);
349     if (raw_instance != null)
350     {
351     object handler_value = handler_prop.GetValue(raw_instance, null);
352 william 74 if (handler_value != null && handler_value.ToString() == root_name)
353 william 73 {
354     handler_type = type;
355 william 111 handler_value = null;
356     raw_instance = null;
357     handler_prop = null;
358     iface = null;
359 william 73 break;
360     }
361 william 111 handler_value = null;
362 william 81 }
363 william 111 raw_instance = null;
364 william 73 }
365 william 111 handler_prop = null;
366 william 73 }
367 william 111 iface = null;
368 william 73 }
369     }
370 william 111 asm = null;
371     types = null;
372 william 82 if (handler_type == null)
373     {
374     StringBuilder node_builder = new StringBuilder();
375     node_builder.AppendFormat("<{0} ", root.Name);
376 william 83 if (root.HasAttributes) { foreach (var attribute in root.Attributes()) { node_builder.AppendFormat("{0}=\"{1}\" ", attribute.Name, attribute.Value); } }
377 william 82 string node_text = string.Format("{0}>", node_builder.ToString().TrimEnd(new char[] { ' ' }));
378 william 83 throw new Exception(string.Format("Unable to find a compatible handler to parse node: {0}", node_text));
379 william 82 }
380 william 74 xmltv_logger.Verbose.Debug.WriteLine("Created handler for root: '{0}'", root_name.ToString());
381 william 73 raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { gInstance }, culture);
382 william 111 raw_instance = null;
383     flags = 0;
384     culture = null;
385 william 44 }
386 william 72
387 william 74 private bool CreateHandlerForNode(XElement node)
388     {
389     if (node == null) { throw new NullReferenceException("Node element is null"); }
390     if (node.Name == null) { throw new NullReferenceException("Node element's Name is null"); }
391 william 111 //var node_name = node.Name.ToString();
392 william 74
393 william 111 xmltv_logger.Verbose.Debug.WriteLine("Creating handler for node: '{0}'", node.Name.ToString());
394 william 74 object raw_instance = null;
395     BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
396     CultureInfo culture = CultureInfo.CurrentCulture;
397     Assembly asm = Assembly.GetExecutingAssembly();
398     var types = asm.GetTypes();
399     Type handler_type = null;
400     foreach (var type in types)
401     {
402     if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
403     {
404 william 81 var iface = type.GetInterface("IXMLTVHandler", true);
405     if (iface != null)
406 william 74 {
407     var handler_prop = type.GetProperty("Handler");
408     if (handler_prop != null)
409     {
410 william 81 var ctors = type.GetConstructors(flags);
411     bool has_default_ctor = false;
412     foreach (var ctor in ctors) { if (ctor.GetParameters().Count() == 0) { has_default_ctor = true; } }
413 william 111 ctors = null;
414 william 81 if (!has_default_ctor) { continue; }
415 william 74 raw_instance = Activator.CreateInstance(type, flags, null, new object[0], culture);
416     if (raw_instance != null)
417     {
418     object handler_value = handler_prop.GetValue(raw_instance, null);
419 william 111 if (handler_value != null && handler_value.ToString() == node.Name.ToString())
420 william 74 {
421     handler_type = type;
422 william 111 handler_value = null;
423     raw_instance = null;
424     handler_prop = null;
425     iface = null;
426 william 74 break;
427     }
428 william 111 handler_value = null;
429 william 74 }
430 william 111 raw_instance = null;
431 william 74 }
432 william 111 handler_prop = null;
433 william 74 }
434 william 111 iface = null;
435 william 74 }
436     }
437 william 111 asm = null;
438     types = null;
439 william 107 if (handler_type == null)
440 william 82 {
441 william 107 try
442     {
443     raw_instance = Activator.CreateInstance(typeof(UnhandledNodeData), flags, null, new object[] { gInstance, node }, culture);
444     }
445     catch (Exception ex) { throw ex; }
446    
447     if (raw_instance == null)
448     {
449     StringBuilder node_builder = new StringBuilder();
450     node_builder.AppendFormat("<{0} ", node.Name);
451     if (node.HasAttributes) { foreach (var attribute in node.Attributes()) { node_builder.AppendFormat("{0}=\"{1}\" ", attribute.Name, attribute.Value); } }
452     string node_text = string.Format("{0}>", node_builder.ToString().TrimEnd(new char[] { ' ' }));
453     throw new Exception(string.Format("Unable to find a compatible handler to parse node: {0}", node_text));
454     }
455 william 82 }
456 william 107 else
457     {
458 william 111 xmltv_logger.Verbose.Debug.WriteLine("Created handler for node: '{0}'", node.Name.ToString());
459 william 107 raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { gInstance, node }, culture);
460     }
461 william 111 raw_instance = null;
462     flags = 0;
463     culture = null;
464     node = null;
465 william 74 return true;
466     }
467 william 107 #region UnhandledExtraMetaData
468     private class UnhandledNodeData : XMLTVBase<XMLTVRuntimeInstance>
469     {
470     public UnhandledNodeData() : base(null, null) { }
471     public UnhandledNodeData(XMLTVRuntimeInstance instance, XElement node)
472     : base(instance, null)
473     {
474     if (node == null) { throw new NullReferenceException("The node instance was null"); }
475     xmltv_logger.Verbose.Debug.WriteLine("Parsng unhandled node data: {0}", node.Name.ToString());
476     if (this.GetInstance() != null)
477     {
478     ExtraMetaData data = new ExtraMetaData(node);
479     instance.ExtraEntries.Add(data);
480 william 111 data = null;
481 william 107 }
482 william 111 node = null;
483 william 107 }
484     }
485     #endregion
486 william 72
487 william 36 }
488     }

  ViewVC Help
Powered by ViewVC 1.1.22