Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

336 lines
9.0 KiB
C#

//
// MSXslScriptManager.cs
//
// Author:
// Atsushi Enomoto (atsushi@ximian.com)
//
// (C)2003 Novell inc.
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Security;
using System.Security.Policy;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;
using System.Xml.Xsl;
using Microsoft.CSharp;
using Microsoft.VisualBasic;
namespace Mono.Xml.Xsl
{
internal abstract class ScriptCompilerInfo
{
string compilerCommand;
string defaultCompilerOptions;
public virtual string CompilerCommand {
get { return compilerCommand; }
set { compilerCommand = value; }
}
public virtual string DefaultCompilerOptions {
get { return defaultCompilerOptions; }
set { defaultCompilerOptions = value; }
}
public abstract CodeDomProvider CodeDomProvider { get; }
public abstract string Extension { get; }
public abstract string SourceTemplate { get; }
public abstract string FormatSource (IXmlLineInfo li, string file, string code);
public virtual string GetCompilerArguments (string targetFileName)
{
return String.Concat (DefaultCompilerOptions, " ", targetFileName);
}
public virtual Type GetScriptClass (string code, string classSuffix, XPathNavigator scriptNode, Evidence evidence)
{
PermissionSet ps = SecurityManager.ResolvePolicy (evidence);
if (ps != null)
ps.Demand ();
// The attempt to use an already pre-compiled
// class assumes the caller has computed the
// classSuffix as a hash of the code
// string. MSXslScriptManager.cs does that.
// The mechanism how exactly such pre-compiled
// classes should be produced are not
// specified here.
string scriptname = "Script" + classSuffix;
string typename = "GeneratedAssembly." + scriptname;
try {
Type retval = Type.GetType (typename);
if (retval != null)
return retval;
} catch {
}
try {
Type retval = Assembly.LoadFrom (scriptname + ".dll").GetType (typename);
if (retval != null)
return retval;
} catch {
}
// OK, we have to actually compile the script.
ICodeCompiler compiler = CodeDomProvider.CreateCompiler ();
CompilerParameters parameters = new CompilerParameters ();
parameters.CompilerOptions = DefaultCompilerOptions;
// get source filename
string filename = String.Empty;
try {
if (scriptNode.BaseURI != String.Empty)
filename = new Uri (scriptNode.BaseURI).LocalPath;
} catch (FormatException) {
}
if (filename == String.Empty)
filename = "__baseURI_not_supplied__";
// get source location
IXmlLineInfo li = scriptNode as IXmlLineInfo;
string source = SourceTemplate.Replace ("{0}",
DateTime.Now.ToString (CultureInfo.InvariantCulture))
.Replace ("{1}", classSuffix)
.Replace ("{2}", code);
source = FormatSource (li, filename, source);
CompilerResults res = compiler.CompileAssemblyFromSource (parameters, source);
foreach (CompilerError err in res.Errors)
if (!err.IsWarning)
// Actually it should be
// XsltCompileException, but to match
// with silly MS implementation...
// throw new XsltCompileException ("Stylesheet script compile error: \n" + FormatErrorMessage (res) /*+ "Code :\n" + source*/, null, scriptNode);
throw new XsltException ("Stylesheet script compile error: \n" + FormatErrorMessage (res) /*+ "Code :\n" + source*/, null, scriptNode);
if (res.CompiledAssembly == null)
throw new XsltCompileException ("Cannot compile stylesheet script", null, scriptNode);
return res.CompiledAssembly.GetType (typename);
}
private string FormatErrorMessage (CompilerResults res)
{
string s = String.Empty;
foreach (CompilerError e in res.Errors) {
object [] parameters = new object [] {"\n",
e.FileName,
e.Line > 0 ? " line " + e.Line : String.Empty,
e.IsWarning ? " WARNING: " : " ERROR: ",
e.ErrorNumber,
": ",
e.ErrorText};
s += String.Concat (parameters);
}
return s;
}
}
internal class CSharpCompilerInfo : ScriptCompilerInfo
{
public CSharpCompilerInfo ()
{
this.CompilerCommand = "mcs";
#if MS_NET
this.CompilerCommand = "csc.exe";
#endif
this.DefaultCompilerOptions = "/t:library /r:System.dll /r:System.Xml.dll";
}
public override CodeDomProvider CodeDomProvider {
get { return new CSharpCodeProvider (); }
}
public override string Extension {
get { return ".cs"; }
}
public override string SourceTemplate {
get {
return @"// This file is automatically created by Mono managed XSLT engine.
// Created time: {0}
using System;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using Microsoft.VisualBasic;
namespace GeneratedAssembly
{
public class Script{1}
{
{2}
}
}";
}
}
public override string FormatSource (IXmlLineInfo li, string file, string source)
{
if (li == null)
return source;
return String.Format (CultureInfo.InvariantCulture, "#line {0} \"{1}\"\n{2}", li.LineNumber, file, source);
}
}
internal class VBCompilerInfo : ScriptCompilerInfo
{
public VBCompilerInfo ()
{
this.CompilerCommand = "mbas";
this.DefaultCompilerOptions = "/t:library";
#if MS_NET
this.CompilerCommand = "vbc.exe";
this.DefaultCompilerOptions = "/t:library /r:System.dll /r:System.Xml.dll /r:Microsoft.VisualBasic.dll";
#endif
}
public override CodeDomProvider CodeDomProvider {
get { return new VBCodeProvider (); }
}
public override string Extension {
get { return ".vb"; }
}
public override string SourceTemplate {
get {
return @"' This file is automatically created by Mono managed XSLT engine.
' Created time: {0}
imports System
imports System.Collections
imports System.Text
imports System.Text.RegularExpressions
imports System.Xml
imports System.Xml.XPath
imports System.Xml.Xsl
imports Microsoft.VisualBasic
namespace GeneratedAssembly
public Class Script{1}
{2}
end Class
end namespace
";
}
}
public override string FormatSource (IXmlLineInfo li, string file, string source)
{
if (li == null)
return source;
return String.Format (CultureInfo.InvariantCulture,
"#ExternalSource (\"{1}\", {0})\n{2}\n#end ExternalSource",
li.LineNumber, new FileInfo (file).Name, source);
}
}
internal class JScriptCompilerInfo : ScriptCompilerInfo
{
static Type providerType;
public JScriptCompilerInfo ()
{
this.CompilerCommand = "mjs";
#if MS_NET
this.CompilerCommand = "jsc.exe";
#endif
this.DefaultCompilerOptions = "/t:library";
}
public override CodeDomProvider CodeDomProvider {
get {
// no need for locking
if (providerType == null) {
Assembly jsasm = Assembly.LoadWithPartialName ("Microsoft.JScript", null);
if (jsasm != null)
providerType = jsasm.GetType ("Microsoft.JScript.JScriptCodeProvider");
}
return (CodeDomProvider) Activator.CreateInstance (providerType);
}
}
public override string Extension {
get { return ".js"; }
}
public override string SourceTemplate {
get {
return @"// This file is automatically created by Mono managed XSLT engine.
// Created time: {0}
import System;
import System.Collections;
import System.Text;
import System.Text.RegularExpressions;
import System.Xml;
import System.Xml.XPath;
import System.Xml.Xsl;
import Microsoft.VisualBasic;
package GeneratedAssembly
{
class Script{1} {
{2}
}
}
";
}
}
public override string FormatSource (IXmlLineInfo li, string file, string source)
{
#if true // remove when mjs got @set @position support
return source;
#else
if (li == null)
return source;
return String.Format (CultureInfo.InvariantCulture,
"@set @position ({0}{1}{2}line={3};column={4})\n{5}",
file != null ? "file=" : String.Empty,
file,
file != null ? "; " : String.Empty,
li.LineNumber,
li.LinePosition,
source);
#endif
}
}
}