public void UnPackTest() { DateTime now = DateTime.Now; string fileName = DateTime.Now.Ticks + ".kpp"; Guid guid = Guid.NewGuid(); KPPDataHead head = new KPPDataHead(); PackageAttributeDataSection section = new PackageAttributeDataSection(); section.SetField("PackName", "test.package"); section.SetField("PackDescription", "test package description."); section.SetField("EnvironmentFlag", (byte)0x01); section.SetField("Version", "1.0.0"); section.SetField("PackTime", now); section.SetField("ApplicationMainFileName", "1.txt"); section.SetField("GlobalUniqueIdentity", guid); string tmpPath = PrepareTestFiles("res-files"); KPPResource.Pack(tmpPath, fileName, head, true, section); Assert.IsTrue(File.Exists(fileName)); KPPDataStructure structure = KPPResource.UnPack(fileName); Assert.IsTrue(structure.GetSectionField <string>(0x00, "PackName") == "test.package"); Assert.IsTrue(structure.GetSectionField <string>(0x00, "PackDescription") == "test package description."); Assert.IsTrue(structure.GetSectionField <string>(0x00, "Version") == "1.0.0"); Assert.IsTrue(structure.GetSectionField <string>(0x00, "ApplicationMainFileName") == "1.txt"); Assert.IsTrue(structure.GetSectionField <DateTime>(0x00, "PackTime") == now); Assert.IsTrue(structure.GetSectionField <byte>(0x00, "EnvironmentFlag") == 0x01); Assert.IsTrue(structure.GetSectionField <Guid>(0x00, "GlobalUniqueIdentity") == guid); Assert.IsNotNull(structure); File.Delete(fileName); Directory.Delete(tmpPath, true); }
/// <summary> /// 应用初始化 /// </summary> /// <param name="structure">KPP资源包的数据结构</param> /// <param name="settings">APP所使用的网络资源设置集</param> /// <param name="proxy">KAE宿主代理器</param> /// <param name="greyPolicyCode">灰度升级策略脚本</param> internal void Initialize(KPPDataStructure structure, ChannelInternalConfigSettings settings, IKAEResourceProxy proxy, string greyPolicyCode = null) { _structure = structure; Version = _structure.GetSectionField <string>(0x00, "Version"); PackageName = _structure.GetSectionField <string>(0x00, "PackName"); Description = _structure.GetSectionField <string>(0x00, "PackDescription"); GlobalUniqueId = _structure.GetSectionField <Guid>(0x00, "GlobalUniqueIdentity"); Level = (ApplicationLevel)_structure.GetSectionField <byte>(0x00, "ApplicationLevel"); IsCompletedEnvironment = _structure.GetSectionField <bool>(0x00, "IsCompletedEnvironment"); Status = ApplicationStatus.Initializing; try { _processors = CollectAbilityProcessors(); InnerInitialize(); Status = ApplicationStatus.Initialized; } catch (Exception ex) { _tracing.Error(ex); Status = ApplicationStatus.Exception; throw; } }
/// <summary> /// 收集目标KAE应用程序集内部的所有消息处理器 /// </summary> /// <returns>返回消息处理器可以处理的消息标示集合</returns> /// <exception cref="DuplicatedProcessorException">具有多个能处理相同MessageIdentity的KAE处理器</exception> /// <exception cref="NotSupportedException">不支持的Protocol Type</exception> protected virtual IDictionary <MessageIdentity, MetadataKAEProcessor> CollectAbilityProcessors() { IDictionary <MessageIdentity, MetadataKAEProcessor> dic = new Dictionary <MessageIdentity, MetadataKAEProcessor>(new MessageIdentityComparer()); Type[] types = AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(File.ReadAllBytes(_structure.GetSectionField <string>(0x00, "ApplicationMainFileName")))).GetTypes(); foreach (Type type in types) { try { if (type.GetTypeInfo().IsAbstract) { continue; } if (!type.GetTypeInfo().IsSubclassOf(typeof(MetadataKAEProcessor))) { continue; } KAEProcessorPropertiesAttribute[] attributes = (KAEProcessorPropertiesAttribute[])type.GetTypeInfo().GetCustomAttributes(typeof(KAEProcessorPropertiesAttribute), true); if (attributes.Length == 0) { _tracing.Warn("#Found a KAE processor, type: {0}. BUT there wasn't any KAEProcessorPropertiesAttribute can be find.", type.Name); continue; } MessageIdentity identity = new MessageIdentity { ProtocolId = attributes[0].ProtocolId, ServiceId = attributes[0].ServiceId, DetailsId = attributes[0].DetailsId }; if (dic.ContainsKey(identity)) { throw new DuplicatedProcessorException("#Duplicated KAE processor which it has same ability to handle a type of message. #MessageIdentity: " + identity); } dic.Add(identity, (MetadataKAEProcessor)Activator.CreateInstance(type, this)); } catch (Exception ex) { _tracing.Error(ex); } } return(dic); }
/// <summary> /// 读取通知KAE APP所在地址的文件,并将其进行解析 /// </summary> /// <param name="fileFullPath">KAE APP文件的完整路径地址</param> /// <returns>返回解析后的KAE APP信息</returns> /// <exception cref="ArgumentNullException">参数不能为空</exception> /// <exception cref="FileNotFoundException">目标文件不存在</exception> public Tuple <string, ApplicationEntryInfo, KPPDataStructure> ReadKPPFrom(string fileFullPath) { if (string.IsNullOrEmpty(fileFullPath)) { throw new ArgumentNullException(nameof(fileFullPath)); } if (!File.Exists(fileFullPath)) { throw new FileNotFoundException(fileFullPath); } try { //analyzes kpp package. KPPDataStructure dataStructure = KPPResource.UnPack(fileFullPath); if (dataStructure == null) { return(null); } string targetPath = Path.Combine(Path.GetDirectoryName(fileFullPath), string.Format("temp-files\\apps\\tempfiles_{0}_{1}_{2}", Path.GetFileName(fileFullPath), dataStructure.GetSectionField <string>(0x00, "Version"), (ApplicationLevel)dataStructure.GetSectionField <byte>(0x00, "ApplicationLevel"))); //releases files from kpp package. dataStructure.ReleaseFiles(targetPath); //picks up main file data. string mainFilePath = Path.Combine(targetPath, dataStructure.GetSectionField <string>(0x00, "ApplicationMainFileName")); //updating combined full path directory. dataStructure.SetSectionField(0x00, "ApplicationMainFileName", mainFilePath); Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(File.ReadAllBytes(mainFilePath))); Type[] types = assembly.GetTypes(); if (types.Length == 0) { return(null); } Type targetAppType = null; foreach (Type type in types) { try { //找到入口点 if (type.GetTypeInfo().IsClass&& !type.GetTypeInfo().IsAbstract&& type.GetTypeInfo().IsSubclassOf(typeof(Application))) { targetAppType = type; break; } } catch (ReflectionTypeLoadException) { } catch (Exception ex) { _tracing.Error(ex, null); } } //use default application type when current package had missed the main application class. targetAppType = targetAppType ?? typeof(Application); ApplicationEntryInfo info = new ApplicationEntryInfo { FilePath = Path.GetFullPath(mainFilePath), FolderPath = Path.GetFullPath(targetPath), EntryPoint = targetAppType.FullName }; byte[] data = File.ReadAllBytes(fileFullPath); Crc32 crc = new Crc32(); crc.Reset(); crc.Update(data); info.FileCRC = crc.Value; return(new Tuple <string, ApplicationEntryInfo, KPPDataStructure>(dataStructure.GetSectionField <string>(0x00, "PackName"), info, dataStructure)); } catch (ReflectionTypeLoadException) { return(null); } catch (Exception ex) { _tracing.Error(ex, null); return(null); } }