/// <summary> /// Executes the custom runtime task component to process the input message and returns the result message. /// </summary> /// <param name="pContext">A reference to <see cref="Microsoft.BizTalk.Component.Interop.IPipelineContext"/> object that contains the current pipeline context.</param> /// <param name="pInMsg">A reference to <see cref="Microsoft.BizTalk.Message.Interop.IBaseMessage"/> object that contains the message to process.</param> /// <returns>A reference to the returned <see cref="Microsoft.BizTalk.Message.Interop.IBaseMessage"/> object which will contain the output message.</returns> public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg) { Guard.ArgumentNotNull(pContext, "pContext"); Guard.ArgumentNotNull(pInMsg, "pInMsg"); var callToken = TraceManager.PipelineComponent.TraceIn(); // It is OK to load the entire message into XML DOM. The size of these requests is anticipated to be very small. XDocument request = XDocument.Load(pInMsg.BodyPart.GetOriginalDataStream()); string transformName = (from childNode in request.Root.Descendants() where childNode.Name.LocalName == WellKnownContractMember.MessageParameters.TransformName select childNode.Value).FirstOrDefault <string>(); TraceManager.PipelineComponent.TraceInfo(TraceLogMessages.GetXslTransformRequest, transformName); IBaseMessagePart responsePart = BizTalkUtility.CreateResponsePart(pContext.GetMessageFactory(), pInMsg); XmlWriterSettings settings = new XmlWriterSettings(); MemoryStream dataStream = new MemoryStream(); pContext.ResourceTracker.AddResource(dataStream); settings.CloseOutput = false; settings.CheckCharacters = false; settings.ConformanceLevel = ConformanceLevel.Fragment; settings.NamespaceHandling = NamespaceHandling.OmitDuplicates; using (XmlWriter responseWriter = XmlWriter.Create(dataStream, settings)) { responseWriter.WriteResponseStartElement("r", WellKnownContractMember.MethodNames.GetXslTransformMetadata, WellKnownNamespace.ServiceContracts.General); try { Type transformType = ResolveTransformType(transformName); if (transformType != null) { // Get the actual map from the BizTalk metadata cache. BtsTransformMetadata btsTransform = BtsTransformMetadata.For(transformType); if (btsTransform != null) { // Map existence confirmed, now it's safe to instantiate the transform type. TransformBase transform = Activator.CreateInstance(transformType) as TransformBase; // Is this really a valid map that implements TransformBase? if (transform != null) { XslTransformMetadata transformMetadata = new XslTransformMetadata(transform.XmlContent, transform.XsltArgumentListContent, transform.SourceSchemas, transform.TargetSchemas); DataContractSerializer dcSerializer = new DataContractSerializer(typeof(XslTransformMetadata), String.Concat(WellKnownContractMember.MethodNames.GetXslTransformMetadata, WellKnownContractMember.ResultMethodSuffix), WellKnownNamespace.ServiceContracts.General); dcSerializer.WriteObject(responseWriter, transformMetadata); } } } } catch (Exception ex) { // Log but do not pass the exception to the caller. TraceManager.PipelineComponent.TraceError(ex); } responseWriter.WriteEndElement(); responseWriter.Flush(); } dataStream.Seek(0, SeekOrigin.Begin); responsePart.Data = dataStream; TraceManager.PipelineComponent.TraceOut(callToken); return(pInMsg); }
/// <summary> /// Returns an object carrying the XSLT transformation metadata, XSLT transformation engine and its arguments. /// </summary> /// <param name="transformName">Either partial or fully qualified name of the transformation object.</param> /// <returns>An instance of the object carrying the XSLT transformation metadata, XSLT transformation engine and its arguments, or null if the specified transform was not found.</returns> public XslTransformSet GetXslTransform(string transformName) { var callToken = TraceManager.WorkerRoleComponent.TraceIn(transformName); try { ICollection <IXslTransformCacheExtension> transformCacheCollection = this.owner.Extensions.FindAll <IXslTransformCacheExtension>(); XslTransformSet transformSet = null; // If cache is enabled, try to get from the cache first. if (transformCacheCollection != null) { // Find a cached transform instance in all registered cache extensions, break at the first match. foreach (var transformCache in transformCacheCollection) { if ((transformSet = transformCache.Get(transformName)) != null) { break; } } } // Reason 1: cache miss or no caching functionality is provided via extensions. // Reason 2: transform set doesn't have the XSLT transform engine instance. // Reason 3: XSLT transform engine in the transform set doesn't have a loaded template. if (null == transformSet || null == transformSet.Transform || null == transformSet.Transform.OutputSettings) { // Try to re-use the transform metadata (if available), otherwise XslTransformMetadata metadata = transformSet != null && transformSet.Metadata != null ? transformSet.Metadata : this.metadataProvider.GetXslTransformMetadata(transformName); if (metadata != null) { XslCompiledTransform transform = new XslCompiledTransform(); XsltArgumentList arguments = new XsltArgumentList(); XsltSettings xsltSettings = new XsltSettings() { EnableDocumentFunction = true, EnableScript = true }; XmlReaderSettings readerSettings = new XmlReaderSettings() { CheckCharacters = false, IgnoreComments = true, IgnoreProcessingInstructions = true, IgnoreWhitespace = true, ValidationType = ValidationType.None }; // Read the XSLT template from the metadata and load it into XSLT transformation engine. using (StringReader rawDataReader = new StringReader(metadata.XsltContentRaw)) using (XmlReader xsltReader = XmlReader.Create(rawDataReader, readerSettings)) { transform.Load(xsltReader, xsltSettings, null); } // Check if XSLT arguments are provided. if (!String.IsNullOrEmpty(metadata.XsltArgumentsRaw)) { // Read the XSLT argument list from the metadata and load it into a XsltArgumentList collection. using (StringReader argDataReader = new StringReader(metadata.XsltArgumentsRaw)) using (XmlReader argContentReader = XmlReader.Create(argDataReader, readerSettings)) { XDocument xsltArgs = XDocument.Load(argContentReader); var extObjects = (from x in xsltArgs.Root.Descendants() select new { Namespace = x.Attribute(Resources.ExtensionObjectNamespaceAttributeName).Value, AssemblyName = x.Attribute(Resources.ExtensionObjectAssemblyAttributeName).Value, ClassName = x.Attribute(Resources.ExtensionObjectClassAttributeName).Value }); foreach (var extObjectInfo in extObjects) { Type extObjectType = Type.GetType(String.Concat(extObjectInfo.ClassName, ", ", extObjectInfo.AssemblyName), false); object extObject = null; if (extObjectType != null && (extObject = Activator.CreateInstance(extObjectType)) != null) { arguments.AddExtensionObject(extObjectInfo.Namespace, extObject); } } } } transformSet = new XslTransformSet(metadata, transform, arguments); // If cache is enabled, place the transform instance and its metadata to the cache. if (transformCacheCollection != null) { foreach (var transformCache in transformCacheCollection) { transformCache.Put(transformName, transformSet); } } } } return(transformSet); } finally { TraceManager.WorkerRoleComponent.TraceOut(callToken); } }