Beispiel #1
0
 public CodeSourceUnit(string /*!*/ code, PhpSourceFile /*!*/ sourceFile,
                       Encoding /*!*/ encoding, Lexer.LexicalStates initialState)
     : base(sourceFile, encoding, Text.LineBreaks.Create(code))
 {
     this.code         = code;
     this.initialState = initialState;
 }
Beispiel #2
0
        public SourceUnit(PhpSourceFile/*!*/ sourceFile, Encoding/*!*/ encoding)
        {
            Debug.Assert(sourceFile != null && encoding != null);

            this.sourceFile = sourceFile;
            this.encoding = encoding;
        }
Beispiel #3
0
        /// <summary>
        /// Initializes the script context for a PHP console application.
        /// </summary>
        /// <param name="appContext">Application context.</param>
        /// <param name="mainScript">The main script's type or a <B>null</B> reference for a pure application.</param>
        /// <param name="relativeSourcePath">A path to the main script source file.</param>
        /// <param name="sourceRoot">A source root within which an application has been compiler.</param>
        /// <returns>
        /// A new instance of <see cref="ScriptContext"/> with its own copy of local configuration
        /// to be used by the application.
        /// </returns>
        /// <exception cref="System.Configuration.ConfigurationErrorsException">
        /// Web configuration is invalid. The context is not initialized then.
        /// </exception>
        /// <remarks>
        /// Use this method if you want to initialize application in the same way the PHP console/Windows
        /// application is initialized. The returned script context is initialized as follows:
        /// <list type="bullet">
        ///   <term>The application's source root is set.</term>
        ///   <term>The main script of the application is defined.</term>
        ///   <term>Output and input streams are set to standard output and input, respectively.</term>
        ///   <term>Current culture it set to <see cref="CultureInfo.InvariantCulture"/>.</term>
        ///   <term>Auto-global variables ($_GET, $_SET, etc.) are initialized.</term>
        ///   <term>Working directory is set tothe current working directory.</term>
        /// </list>
        /// </remarks>
        public static ScriptContext /*!*/ InitApplication(ApplicationContext /*!*/ appContext, Type mainScript,
                                                          string relativeSourcePath, string sourceRoot)
        {
            // loads configuration into the given application context
            // (applies only if the config has not been loaded yet by the current thread):
            Configuration.Load(appContext);

            ApplicationConfiguration app_config = Configuration.Application;

            if (mainScript != null)
            {
                if (relativeSourcePath == null)
                {
                    throw new ArgumentNullException("relativeSourcePath");
                }

                if (sourceRoot == null)
                {
                    throw new ArgumentNullException("sourceRoot");
                }

                // overrides source root configuration if not explicitly specified in config file:
                if (!app_config.Compiler.SourceRootSet)
                {
                    app_config.Compiler.SourceRoot = new FullPath(sourceRoot);
                }
            }

            // takes a writable copy of a global configuration:
            LocalConfiguration config = (LocalConfiguration)Configuration.DefaultLocal.DeepCopy();

            // sets invariant culture as a default one:
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            ScriptContext result = new ScriptContext(appContext, config, Console.Out, Console.OpenStandardOutput());

            result.IsOutputBuffered = result.config.OutputControl.OutputBuffering;
            result.AutoGlobals.Initialize(config, null);
            result.WorkingDirectory                 = Directory.GetCurrentDirectory();
            result.ThrowExceptionOnError            = true;
            result.config.ErrorControl.HtmlMessages = false;

            if (mainScript != null)
            {
                // converts relative path of the script source to full canonical path using source root from the configuration:
                PhpSourceFile main_source_file = new PhpSourceFile(
                    app_config.Compiler.SourceRoot,
                    new FullPath(relativeSourcePath, app_config.Compiler.SourceRoot)
                    );

                result.DefineMainScript(new ScriptInfo(mainScript), main_source_file);
            }

            ScriptContext.CurrentContext = result;

            Externals.BeginRequest();

            return(result);
        }
Beispiel #4
0
		/// <summary>
		/// Returns compiled module if exists.
		/// </summary>
		/// <param name="sourceFile">Source file.</param>
		/// <param name="ctx">A compilation context.</param>
		/// <returns>The <see cref="PhpModule"/> or a <B>null</B> reference.</returns>
		/// <remarks>
		/// Checks whether a module associated with a <paramref name="sourceFile"/> has already been compiled.
		/// If so returns the respective <see cref="PhpModule"/>. Otherwise a <B>null</B> reference is returned.
		/// Does no locking since application compiler is thread unsafe.
		/// </remarks>
		public PhpModule LockForCompiling(PhpSourceFile/*!*/ sourceFile, CompilationContext/*!*/ ctx)
		{
            // take a look into script library first
            if (applicationContext.ScriptLibraryDatabase.ContainsScript(sourceFile.FullPath))
            {
                return applicationContext.ScriptLibraryDatabase.GetScriptModule(sourceFile.FullPath);
            }

			return assemblyBuilder.Assembly.GetModule(sourceFile);
		}
Beispiel #5
0
        public SourceUnit(PhpSourceFile /*!*/ sourceFile, Encoding /*!*/ encoding, ILineBreaks /*!*/ lineBreaks)
        {
            Debug.Assert(sourceFile != null && encoding != null);
            Debug.Assert(lineBreaks != null);

            this.sourceFile      = sourceFile;
            this.encoding        = encoding;
            this.innerLineBreaks = lineBreaks;
            this.naming          = new NamingContext(null, null);
        }
Beispiel #6
0
        /// <summary>
        /// Returns compiled module if exists.
        /// </summary>
        /// <param name="sourceFile">Source file.</param>
        /// <param name="ctx">A compilation context.</param>
        /// <returns>The <see cref="PhpModule"/> or a <B>null</B> reference.</returns>
        /// <remarks>
        /// Checks whether a module associated with a <paramref name="sourceFile"/> has already been compiled.
        /// If so returns the respective <see cref="PhpModule"/>. Otherwise a <B>null</B> reference is returned.
        /// Does no locking since application compiler is thread unsafe.
        /// </remarks>
        public PhpModule LockForCompiling(PhpSourceFile /*!*/ sourceFile, CompilationContext /*!*/ ctx)
        {
            // take a look into script library first
            if (applicationContext.ScriptLibraryDatabase.ContainsScript(sourceFile.FullPath))
            {
                return(applicationContext.ScriptLibraryDatabase.GetScriptModule(sourceFile.FullPath));
            }

            return(assemblyBuilder.Assembly.GetModule(sourceFile));
        }
Beispiel #7
0
        /// <summary>
        /// Loads a script type dynamically.
        /// </summary>
        /// <param name="sourceFile">Script's source file.</param>
        private ScriptInfo LoadDynamicScriptType(PhpSourceFile /*!*/ sourceFile)
        {
            Debug.WriteLine("SC", "LoadDynamicScriptType: '{0}'", sourceFile);

            // runtime compiler manages:
            // - 1. script library
            // - 2. optionally bin/WebPages.dll
            // - 3. compiles file from file system if allowed

            return(this.ApplicationContext.RuntimeCompilerManager.GetCompiledScript(sourceFile, RequestContext.CurrentContext));
        }
Beispiel #8
0
        /// <summary>
        /// Creates source unit and parses given <paramref name="code"/>.
        /// </summary>
        /// <param name="code">Source code to be parsed.</param>
        /// <param name="sourceFile">Source file used for error reporting.</param>
        /// <param name="errors">Errors sink. Can be <c>null</c>.</param>
        /// <param name="reductionsSink">Reduction sink. Can be <c>null</c>.</param>
        /// <param name="features">Optional. Language features.</param>
        /// <param name="initialState">
        /// Optional. Initial parser state.
        /// This allows e.g. to parse PHP code without encapsulating the code into opening and closing tags.</param>
        /// <returns></returns>
        public static SourceUnit /*!*/ ParseCode(string code, PhpSourceFile sourceFile,
                                                 ErrorSink /*!*/ errors,
                                                 IReductionsSink /*!*/ reductionsSink = null,
                                                 LanguageFeatures features            = LanguageFeatures.Php5,
                                                 Lexer.LexicalStates initialState     = Lexer.LexicalStates.INITIAL)
        {
            var /*!*/ unit = new CodeSourceUnit(code, sourceFile, Encoding.UTF8, initialState);

            unit.Parse(errors, reductionsSink, features);
            unit.Close();

            //
            return(unit);
        }
		/// <summary>
		/// Translates a source path to an assembly coded name.
		/// </summary>
		/// <param name="sourceFile">Source file.</param>
		/// <param name="config">The compiler configuration.</param>
		/// <returns>
		/// The code name consisting of significant configuration hashcode and source 
		/// path relative to the application source root.
		/// Format of the name: <code>{relativized path}(~{level_count})?#{config hash}#</code>
		/// Backslashes and colons are replaced with underscores, underscores are doubled.
		/// </returns>
		public static string GetAssemblyCodedName(PhpSourceFile/*!*/ sourceFile, CompilerConfiguration/*!*/ config)
		{
			RelativePath rp = sourceFile.RelativePath;
			StringBuilder sb = new StringBuilder(rp.Path);

			if (rp.Level >= 0)
			{
				sb.Append('~');
				sb.Append(rp.Level);
			}

			sb.Append('#');
			sb.Append(config.Compiler.HashCode.ToString("x"));
			sb.Append('#');

            return sb.Replace("_", "__").Replace('/', '_').Replace('\\', '_').Replace(':', '_').ToString();
		}
Beispiel #10
0
        public bool Equals(PhpSourceFile other)
        {
            if (ReferenceEquals(other, this))
            {
                return(true);
            }
            if (other == null)
            {
                return(false);
            }

            // assuming full to relative conversion is faster:
            if (this.fullPath.IsEmpty || other.fullPath.IsEmpty)
            {
                return(this.root.Equals(other.root) && this.RelativePath.Equals(other.RelativePath));
            }
            else
            {
                return(this.fullPath.Equals(other.fullPath));
            }
        }
Beispiel #11
0
        /// <summary>
        /// Performs PHP inclusion on a specified script.
        /// </summary>
        /// <param name="relativeSourcePath">
        /// Path to the target script source file relative to the application source root
        /// (see <c>Configuration.Application.Compiler.SourceRoot</c>.
        /// </param>
        /// <param name="script">
        /// Script type (i.e. type called <c>Default</c> representing the target script) or any type from
        /// the assembly where the target script is contained (useful for multi-script assemblies, where script types are
        /// not directly available from C# as they have mangled names). In the latter case, the script type is searched in the
        /// assembly using value of <paramref name="relativeSourcePath"/>.
        /// </param>
        /// <returns>The value returned by the global code of the target script.</returns>
        /// <remarks>
        /// <para>
        /// The inclusion inheres in adding the target to the list of included scripts on the current script context
        /// (see <c>ScriptContext.Scripts</c> and in a call to the global code of the target script.
        /// </para>
        /// </remarks>
        /// <exception cref="InvalidOperationException">Request context has been disposed.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="relativeSourcePath"/> or <paramref name="script"/> are <B>null</B> references.</exception>
        /// <exception cref="ArgumentException">Script type cannot be resolved.</exception>
        /// <exception cref="InvalidScriptAssemblyException">The target assembly is not a valid Phalanger compiled assembly.</exception>
        internal object IncludeScript(string /*!*/ relativeSourcePath, ScriptInfo /*!*/ script)
        {
            //if (type == null)
            //    throw new ArgumentNullException("type");
            if (relativeSourcePath == null)
            {
                throw new ArgumentNullException("relativeSourcePath");
            }
            if (script == null)
            {
                throw new ArgumentException("script");
            }

            FullPath      source_root = Configuration.Application.Compiler.SourceRoot;
            PhpSourceFile source_file = new PhpSourceFile(
                new FullPath(source_root),
                new FullPath(Path.Combine(source_root, relativeSourcePath)));

            // the first script becomes the main one:
            if (MainScriptFile == null)
            {
                DefineMainScript(script, source_file);
            }

            return(GuardedCall((ScriptInfo scriptInfo) =>
            {
                //return PhpScript.InvokeMainHelper(
                //    (Type)scriptType,
                return scriptInfo.Main(
                    this,
                    null,  // no local variables
                    null,  // no object context
                    null,  // no class context
                    true);
            }, script, true));
        }
Beispiel #12
0
		/// <summary>
		/// Gets the script module contained in the assembly.
		/// </summary>
		/// <returns>The one and only script module of the assembly.</returns>
		public override ScriptModule GetScriptModule(PhpSourceFile dummy)
		{
			return script;
		}
		/// <summary>
		/// Gets a full name of an assembly in which a specified source script is compiled.
		/// </summary>
		/// <param name="sourceFile">Source file.</param>
		/// <returns>The assembly full name.</returns>
		/// <remarks>A name of the assembly consists of a hexa-timestamp and a assembly coded name.</remarks>
		public AssemblyName GetAssemblyFullName(PhpSourceFile/*!*/ sourceFile)
		{
			// timestamp ensures there won't be two loaded assemblies of the same name:
			// (consider editing of a source file)
			string stamp = requestTimestamp.Ticks.ToString("x16");

			AssemblyName result = new AssemblyName();
			result.Name = GetAssemblyCodedName(sourceFile, config) + stamp;
			result.Version = new Version(1, 0, 0, 0);

			return result;
		}
		public static PhpAssemblyBuilder/*!*/ Create(ApplicationContext/*!*/ applicationContext, AssemblyKinds kind,
			bool pure, FullPath outPath, FullPath docPath, PhpSourceFile entryPoint, Version version,
            StrongNameKeyPair key, Win32IconResource icon, ICollection<ResourceFileReference> resources, bool debug, bool force32bit)
		{
			string out_dir = Path.GetDirectoryName(outPath);
			string out_file = Path.GetFileName(outPath);

			AssemblyName assembly_name = new AssemblyName();
			assembly_name.Name = Path.GetFileNameWithoutExtension(outPath);
			assembly_name.Version = version;
			assembly_name.KeyPair = key;

            if (pure)
            {
                return new PureAssemblyBuilder(applicationContext, assembly_name, out_dir, out_file,
                    kind, resources, debug, force32bit, icon);
            }
            else
            {
                return new MultiScriptAssemblyBuilder(applicationContext, assembly_name, out_dir, out_file,
                    kind, resources, debug, force32bit, icon, entryPoint);
            }
		}
Beispiel #15
0
        /// <summary>
        /// Initializes the script context for a PHP console application.
        /// </summary>
        /// <param name="appContext">Application context.</param>
        /// <param name="mainScript">The main script's type or a <B>null</B> reference for a pure application.</param>
        /// <param name="relativeSourcePath">A path to the main script source file.</param>
        /// <param name="sourceRoot">A source root within which an application has been compiler.</param>
        /// <returns>
        /// A new instance of <see cref="ScriptContext"/> with its own copy of local configuration 
        /// to be used by the application.
        /// </returns>
        /// <exception cref="System.Configuration.ConfigurationErrorsException">
        /// Web configuration is invalid. The context is not initialized then.
        /// </exception>
        /// <remarks>
        /// Use this method if you want to initialize application in the same way the PHP console/Windows 
        /// application is initialized. The returned script context is initialized as follows:
        /// <list type="bullet">
        ///   <term>The application's source root is set.</term>
        ///   <term>The main script of the application is defined.</term>
        ///   <term>Output and input streams are set to standard output and input, respectively.</term>
        ///   <term>Current culture it set to <see cref="CultureInfo.InvariantCulture"/>.</term>
        ///   <term>Auto-global variables ($_GET, $_SET, etc.) are initialized.</term>
        ///   <term>Working directory is set tothe current working directory.</term>
        /// </list>
        /// </remarks>
        public static ScriptContext/*!*/ InitApplication(ApplicationContext/*!*/ appContext, Type mainScript,
            string relativeSourcePath, string sourceRoot)
        {
            // loads configuration into the given application context 
            // (applies only if the config has not been loaded yet by the current thread):
            Configuration.Load(appContext);

            ApplicationConfiguration app_config = Configuration.Application;

            if (mainScript != null)
            {
                if (relativeSourcePath == null)
                    throw new ArgumentNullException("relativeSourcePath");

                if (sourceRoot == null)
                    throw new ArgumentNullException("sourceRoot");

                // overrides source root configuration if not explicitly specified in config file:
                if (!app_config.Compiler.SourceRootSet)
                    app_config.Compiler.SourceRoot = new FullPath(sourceRoot);
            }

            // takes a writable copy of a global configuration:
            LocalConfiguration config = (LocalConfiguration)Configuration.DefaultLocal.DeepCopy();

            // sets invariant culture as a default one:
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            ScriptContext result = new ScriptContext(appContext, config, Console.Out, Console.OpenStandardOutput());

            result.IsOutputBuffered = result.config.OutputControl.OutputBuffering;
            result.AutoGlobals.Initialize(config, null);
            result.WorkingDirectory = Directory.GetCurrentDirectory();
            result.ThrowExceptionOnError = true;
            result.config.ErrorControl.HtmlMessages = false;

            if (mainScript != null)
            {
                // converts relative path of the script source to full canonical path using source root from the configuration:
                PhpSourceFile main_source_file = new PhpSourceFile(
                    app_config.Compiler.SourceRoot,
                    new FullPath(relativeSourcePath, app_config.Compiler.SourceRoot)
                );

                result.DefineMainScript(new ScriptInfo(mainScript), main_source_file);
            }

            ScriptContext.CurrentContext = result;

            Externals.BeginRequest();

            return result;
        }
Beispiel #16
0
		/// <summary>
		/// Gets a script type stored in a specified single-script assembly.
		/// </summary>
		public override Type GetScriptType(PhpSourceFile dummy)
		{
			return GetScriptType();
		}
		/// <summary>
		/// Translates a source path to an assembly coded name.
		/// </summary>
		public string GetAssemblyCodedName(PhpSourceFile/*!*/ sourceFile)
		{
			return GetAssemblyCodedName(sourceFile, config);
		}
		/// <summary>
		/// Checks whether a specified source file needs to be (re)compiled and if so locks 
		/// it so that any other compiler from the current app domain will wait until this compilation finishes.
		/// </summary>
		/// <param name="sourceFile">Source file.</param>
		/// <param name="ctx">Compilation context.</param>
		/// <returns>
		/// A compiled module associated with the <paramref name="sourceFile"/> or a <B>null</B> reference
		/// if a compilation of that file is needed.
		/// </returns>
		public PhpModule LockForCompiling(PhpSourceFile/*!*/ sourceFile, CompilationContext/*!*/ ctx)
		{
			Debug.Assert(ctx is WebCompilationContext);
			WebCompilationContext context = (WebCompilationContext)ctx;

            // take a look into script library first
            if (applicationContext.ScriptLibraryDatabase.ContainsScript(sourceFile.FullPath))
            {
                return applicationContext.ScriptLibraryDatabase.GetScriptModule(sourceFile.FullPath);
            }

			for (int i = 0; i < AttemptsToGetCompiledAssembly; i++)
			{
				string ns = ScriptModule.GetSubnamespace(sourceFile.RelativePath, false);

				CacheEntry cache_entry;

				// TODO: Single script assemblies can be loaded and reflected 
				//       but this still have to be done for MSAs
				if (TryLoadCachedEntry(ns, sourceFile, out cache_entry) && !cache_entry.ScriptAssembly.IsMultiScript)
					return cache_entry.ScriptAssembly.GetModule(sourceFile);

				// compilation is in progress or not started yet //
				ManualResetEvent compilation_finished;

				lock (eventsMutex)
				{
					// if compilation of the target file has not started yet:
					if (!events.TryGetValue(sourceFile, out compilation_finished))
					{
						// adds event which others wait on:
						events.Add(sourceFile, new ManualResetEvent(false));

						return null;
					}
				}

				// waits until compilation is finished and assembly has been persisted:
				compilation_finished.WaitOne(CompilationTimeout, false);
			}

			return null;
		}
		/// <summary>
		/// Called by compiler when information about compiling progress is available.
		/// </summary>
		/// <remarks>Ignored by this manager.</remarks>
		public void Info(PhpSourceFile/*!*/ sourceFile, CompilationContext ctx)
		{
			// nop //
		}
Beispiel #20
0
		/// <summary>
		/// Triggered by the compiler on events such are start of compilation, end of compilation etc.
		/// </summary>
		/// <param name="sourceFile">A source path to a script being processed.</param>
		/// <param name="ctx">A compilation context.</param>
		public void Info(PhpSourceFile/*!*/ sourceFile, CompilationContext/*!*/ ctx)
		{
			Console.WriteLine(sourceFile.RelativePath);
		}
		/// <summary>
		/// Retrives a compiled script.
        /// 
        /// The method check scripts in following order:
        /// 1. Script Library database.
        /// 2. Modified source file on the file system.
        /// 3. Unmodified source file in precompiled WebPages.dll.
		/// </summary>
		/// <param name="sourceFile">Script source file.</param>
		/// <param name="requestContext">The current HTTP context. Can be <c>null</c> in case of desktop app.</param>
		/// <returns>The script type or a <B>null</B> reference on failure.</returns>
        /// <remarks>The method do check the script library database.</remarks>
        public ScriptInfo GetCompiledScript(PhpSourceFile/*!*/ sourceFile, RequestContext requestContext)
        {
            Debug.Assert(sourceFile != null);

            // try to get the script from precompiled script library first
            var scriptLibraryModule = applicationContext.ScriptLibraryDatabase.GetScriptModule(sourceFile.FullPath);
            if (scriptLibraryModule != null)
                return scriptLibraryModule.ScriptInfo;

            // loads precompiled assembly if exists and not loaded yet:
            GetPrecompiledAssembly();

            // enables source code watcher if not enabled yet:
            if (watcher != null && !watcher.EnableRaisingEvents)
            {
                Debug.WriteLine("WSSM", "Source code watcher is starting.");

                watcher.EnableRaisingEvents = true;
            }

            string ns = ScriptModule.GetSubnamespace(sourceFile.RelativePath, false);

            CacheEntry cache_entry;

            if (Configuration.Application.Compiler.OnlyPrecompiledCode)
            {
                // Load script from cache (WebPages.dll)
                if (TryGetCachedEntry(ns, out cache_entry))
                    return cache_entry.ScriptInfo;
                else
                    return null;
            }
            else
            {
                // Load script from cache or from ASP.NET Temporary files
                if (TryLoadCachedEntry(ns, sourceFile, out cache_entry))
                    return cache_entry.ScriptInfo;

                lock (this)
                {
                    // double checked lock, CompileScript should not be called on more threads
                    if (TryGetCachedEntry(ns, out cache_entry))
                        return cache_entry.ScriptInfo;

                    Debug.WriteLine("WSSM", "Compile script '{0}'.", sourceFile.ToString());
                    return CompileScriptNoLock(ns, sourceFile, requestContext);
                }
            }
        }
Beispiel #22
0
		/// <summary>
		/// Remembers whether compilation has been successful.
		/// </summary>
		/// <param name="sourceFile">Source file.</param>
		/// <param name="successful">Whether compilation was successful.</param>
		/// <param name="ctx">A compilation context.</param>
		public void UnlockForCompiling(PhpSourceFile/*!*/ sourceFile, bool successful, CompilationContext/*!*/ ctx)
		{
			this.successful &= successful;
		}
Beispiel #23
0
		internal bool ScriptExists(FullPath fullPath)
		{
			PhpSourceFile source_file = new PhpSourceFile(Configuration.Application.Compiler.SourceRoot, fullPath);
			return GetScriptType(source_file) != null;
		}
Beispiel #24
0
		/// <summary>
		/// Gets a full qualified name of a script type given a sub-namespace.
		/// </summary>
		/// <param name="sourceFile">Source file.</param>
		/// <returns>The qualified name.</returns>
		public string GetQualifiedScriptTypeName(PhpSourceFile/*!*/ sourceFile)
		{
			Debug.Assert(sourceFile != null);

			return GetQualifiedScriptTypeName(ScriptModule.GetSubnamespace(sourceFile));
		}
Beispiel #25
0
		/// <summary>
		/// Gets a script type stored in a specified multi-script assembly.
		/// </summary>
		/// <param name="sourceFile">Source file.</param>
		/// <returns>The script type.</returns>
		public override Type GetScriptType(PhpSourceFile/*!*/ sourceFile)
		{
			Debug.Assert(sourceFile != null);

			return module.GetType(GetQualifiedScriptTypeName(sourceFile), false, true);
		}
Beispiel #26
0
		/// <summary>
		/// Gets a script module associated with a specified source file.
		/// </summary>
		public override ScriptModule GetScriptModule(PhpSourceFile/*!*/ sourceFile)
		{
			ScriptModule result;
			scripts.TryGetValue(sourceFile, out result);
			return result;
		}
		/// <summary>
		/// Compiles a script.
		/// Called when the script cannot be loaded from pre-compiled assembly and it should be compiled.
		/// </summary>
		/// <returns>The compiled script type.</returns>
        private ScriptInfo CompileScriptNoLock(string ns, PhpSourceFile/*!*/ sourceFile, RequestContext requestContext)
		{
            Debug.Assert(sourceFile != null);

			CompilerConfiguration config = new CompilerConfiguration(Configuration.Application);
			WebCompilationContext context = new WebCompilationContext(applicationContext, this, config, sourceFile.Directory, 
				(requestContext != null) ? requestContext.HttpContext.Timestamp : DateTime.UtcNow);

			try
			{
				CacheEntry cache_entry;
                if (ScriptAssemblyBuilder.CompileScripts(new PhpSourceFile[] { sourceFile }, context))
                {
                    // assembly should be already added into the cache by Persist() method
                    if (TryGetCachedEntry(ns, out cache_entry))
                        return cache_entry.ScriptInfo;
                }

                return null;
			}
			catch (CompilerException)
			{
				return null;
			}
			catch (Exception)
			{
				// record stack info to the message if the manager resides in a dedicated domain:
				throw;
			}
		}
Beispiel #28
0
        /// <summary>
        /// Includes a specific script using current configuration.
        /// </summary>
        /// <param name="relativeSourcePath">Source root relative path to the script.</param>
        /// <param name="once">Specifies whether script should be included only once.</param>
        /// <returns>The value returned by the global code of the target script.</returns>
        public object Include(string /*!*/ relativeSourcePath, bool once)
        {
            ApplicationConfiguration app_config = Configuration.Application;

            // searches for file:
            FullPath included_full_path = SearchForIncludedFile(PhpError.Error, relativeSourcePath, FullPath.Empty);

            if (included_full_path.IsEmpty)
            {
                return(false);
            }

            ScriptInfo info;
            bool       already_included = scripts.TryGetValue(included_full_path.ToString(), out info);

            // skips inclusion if script has already been included and inclusion's type is "once":
            if (already_included)
            {
                if (once)
                {
                    return(ScriptModule.SkippedIncludeReturnValue);
                }

                // script type loaded, info cannot be null
            }
            else
            {
                PhpSourceFile included_source_file = new PhpSourceFile(app_config.Compiler.SourceRoot, included_full_path);

                // loads script type:
                info = LoadDynamicScriptType(included_source_file);

                // script not found:
                if (info == null)
                {
                    return(false);
                }

                if (MainScriptFile == null)
                {
                    // the first script becomes the main one:
                    DefineMainScript(info, included_source_file);
                }
                else
                {
                    // adds included file into the script list
                    scripts.Add(included_full_path.ToString(), info);
                }
            }

            Debug.Assert(info != null);

            return(GuardedCall((ScriptInfo scriptInfo) =>
            {
                //return PhpScript.InvokeMainHelper(
                //    (Type)scriptType,
                return scriptInfo.Main(
                    this,
                    null,  // no local variables
                    null,  // no object context
                    null,  // no class context
                    true);
            }, info, true));
        }
		/// <summary>
		/// Wakes up threads waiting for a script compilation finish.
		/// </summary>
		/// <param name="sourceFile">The compiled script's source file.</param>
		/// <param name="successful">Whether compilation has been successful.</param>
		/// <param name="ctx">A compilation context.</param>
		/// <remarks>Should be called after <see cref="Persist"/>.</remarks>
		public void UnlockForCompiling(PhpSourceFile/*!*/ sourceFile, bool successful, CompilationContext ctx)
		{
			Debug.Assert(sourceFile != null && ctx is WebCompilationContext);

			ManualResetEvent compilation_finished;

			lock (eventsMutex)
			{
				if (events.TryGetValue(sourceFile, out compilation_finished))
					events.Remove(sourceFile);
			}

			// any waiting thread can access the compiled assembly now:
			if (compilation_finished != null)
				compilation_finished.Set();
		}
Beispiel #30
0
 /// <summary>
 /// Triggered by the compiler on events such are start of compilation, end of compilation etc.
 /// </summary>
 /// <param name="sourceFile">A source path to a script being processed.</param>
 /// <param name="ctx">A compilation context.</param>
 public void Info(PhpSourceFile /*!*/ sourceFile, CompilationContext /*!*/ ctx)
 {
     Console.WriteLine(sourceFile.RelativePath);
 }
		/// <summary>
		/// Loads script from cache (in-memory tables) or from 
		/// previously compiled dll in ASP.NET Temporary files.
		/// </summary>
		private bool TryLoadCachedEntry(string/*!*/ ns, PhpSourceFile/*!*/ sourceFile, out CacheEntry cache_entry)
		{
            // first try in-memory cache
            if (TryGetCachedEntry(ns, out cache_entry))
            {
                Debug.WriteLine("WSSM", "Cache hit.");
                if (CheckEntryFileTime(ns, cache_entry) || !Configuration.Application.Compiler.WatchSourceChanges)
                    return true;
            }

            lock(tempLoadLocks[unchecked((uint)ns.GetHashCode()) % tempLoadLocks.Length])
            {
                // double checked lock
                if (TryGetCachedEntry(ns, out cache_entry))
                    return true;    // do not check source time, since it was currently created

                // try to find previously compiled assembly in temporary files
                if (TryLoadTemporaryCompiledNoLock(ns, sourceFile, out cache_entry))
                {
                    Debug.WriteLine("WSSM", "Loaded from Temporary files.");
                    return true;
                }
            }

            return false;
        }
Beispiel #32
0
		/// <summary>
		/// Performs PHP inclusion on a specified script. 
		/// </summary>
		/// <param name="relativeSourcePath">
		/// Path to the target script source file relative to the application source root 
		/// (see <c>Configuration.Application.Compiler.SourceRoot</c>.
		/// </param>
        /// <param name="script">
		/// Script type (i.e. type called <c>Default</c> representing the target script) or any type from 
		/// the assembly where the target script is contained (useful for multi-script assemblies, where script types are 
		/// not directly available from C# as they have mangled names). In the latter case, the script type is searched in the 
		/// assembly using value of <paramref name="relativeSourcePath"/>.
		/// </param>
		/// <returns>The value returned by the global code of the target script.</returns>
		/// <remarks>
		/// <para>
		/// The inclusion inheres in adding the target to the list of included scripts on the current script context
		/// (see <c>ScriptContext.Scripts</c> and in a call to the global code of the target script.
		/// </para>
		/// </remarks>
		/// <exception cref="InvalidOperationException">Request context has been disposed.</exception>
		/// <exception cref="ArgumentNullException"><paramref name="relativeSourcePath"/> or <paramref name="script"/> are <B>null</B> references.</exception>
		/// <exception cref="ArgumentException">Script type cannot be resolved.</exception>
		/// <exception cref="InvalidScriptAssemblyException">The target assembly is not a valid Phalanger compiled assembly.</exception>
		internal object IncludeScript(string/*!*/ relativeSourcePath, ScriptInfo/*!*/ script)
		{
            //if (type == null)
            //    throw new ArgumentNullException("type");
            if (relativeSourcePath == null)
				throw new ArgumentNullException("relativeSourcePath");
            if (script == null)
                throw new ArgumentException("script");

			FullPath source_root = Configuration.Application.Compiler.SourceRoot;
			PhpSourceFile source_file = new PhpSourceFile(
				new FullPath(source_root),
				new FullPath(Path.Combine(source_root, relativeSourcePath)));

            // the first script becomes the main one:
			if (MainScriptFile == null)
				DefineMainScript(script, source_file);

            return GuardedCall((ScriptInfo scriptInfo) =>
            {
                //return PhpScript.InvokeMainHelper(
                //    (Type)scriptType,
                return scriptInfo.Main(
                    this,
                    null,  // no local variables
                    null,  // no object context
                    null,  // no class context
                    true);
            }, script, true);
		}
        /// <summary>
        /// Tries to load script from ASP.NET Temporary files - this is useful when 
        /// web is not precompiled (so it is compiled into SSAs) and appdomain is reloaded
        /// (which means that we loose the cache)
        /// </summary>
        private bool TryLoadTemporaryCompiledNoLock(string ns, PhpSourceFile/*!*/ sourceFile, out CacheEntry cache_entry)
        {
            CompilerConfiguration config = new CompilerConfiguration(Configuration.Application);
            string name = WebCompilationContext.GetAssemblyCodedName(sourceFile, config);

            string sourcePath = sourceFile.FullPath.ToString();
            bool sourceExists = File.Exists(sourcePath);
            DateTime sourceTime = sourceExists ? File.GetLastWriteTime(sourcePath) : DateTime.UtcNow.AddYears(1);   // If file does not exist, fake the sourceTime to NOT load any SSA DLL. Delete them instead.
            DateTime configTime = Configuration.LastConfigurationModificationTime;

            // here find the max modification of all dependant files (configuration, script itself, other DLLs):
            long sourceStamp = Math.Max(Math.Max(sourceTime.Ticks, configTime.Ticks), appCodeAssemblyCreated.Ticks);

            // Find specified file in temporary files

            if (Directory.Exists(outDir))

            foreach (string file in Directory.GetFiles(outDir, name + "*.dll"))
            {
                Match match = reFileStamp.Match(file);
                if (!match.Success) continue;

                long fileStamp;
                if (!Int64.TryParse((string)match.Groups["Stamp"].Value, NumberStyles.AllowHexSpecifier,
                    CultureInfo.InvariantCulture, out fileStamp)) continue;

                // File is up-to-date
                if (sourceStamp < fileStamp)
                {
                    Debug.WriteLine("WSSM", "Loading from ASP.NET Temporary files.");

                    return LoadSSA(ns, file, out cache_entry);
                }
                else
                {
                    // do "some" cleanup:
                    try
                    {
                        File.Delete(file);
                        File.Delete(Path.ChangeExtension(file, ".pdb"));
                    }
                    catch{ /*nop*/ }
                }
            }
            cache_entry = default(CacheEntry);
            return false;
        }
Beispiel #34
0
 /// <summary>
 /// Remembers whether compilation has been successful.
 /// </summary>
 /// <param name="sourceFile">Source file.</param>
 /// <param name="successful">Whether compilation was successful.</param>
 /// <param name="ctx">A compilation context.</param>
 public void UnlockForCompiling(PhpSourceFile /*!*/ sourceFile, bool successful, CompilationContext /*!*/ ctx)
 {
     this.successful &= successful;
 }
Beispiel #35
0
 /// <summary>
 /// Get the precompiled script from several locations - script library database, precompiled SSA, precompiled MSA (WebPages.dll).
 /// </summary>
 /// <param name="sourceFile">The source file of the script to retrieve.</param>
 /// <returns>The <see cref="ScriptInfo"/> of required script or null if such script cannot be obtained.</returns>
 internal ScriptInfo GetCompiledScript(PhpSourceFile /*!*/ sourceFile)
 {
     return(scriptContext.ApplicationContext.RuntimeCompilerManager.GetCompiledScript(sourceFile, this));
 }
Beispiel #36
0
		public bool Equals(PhpSourceFile other)
		{
			if (ReferenceEquals(other, this)) return true;
			if (other == null) return false;

			// assuming full to relative conversion is faster:
			if (this.fullPath.IsEmpty || other.fullPath.IsEmpty)
				return this.root.Equals(other.root) && this.RelativePath.Equals(other.RelativePath);
			else
				return this.fullPath.Equals(other.fullPath);
		}
		/// <summary>
		/// Creates an instance of of multi-script assembly builder.
		/// </summary>
		/// <param name="applicationContext">Application context.</param>
		/// <param name="assemblyName">Name of the assembly.</param>
		/// <param name="directory">Directory where assembly will be stored.</param>
		/// <param name="fileName">Name of the assembly file including an extension.</param>
        /// <param name="kind">Assembly file kind.</param>
		/// <param name="debug">Whether to include debug information.</param>
        /// <param name="force32bit">Whether to force 32bit execution of generated assembly.</param>
		/// <param name="entryPoint">Entry point.</param>
		/// <param name="icon">Icon.</param>
        /// <param name="resources">Resources to embed</param>
        public MultiScriptAssemblyBuilder(ApplicationContext/*!*/ applicationContext, AssemblyName assemblyName,
            string directory, string fileName, AssemblyKinds kind, ICollection<ResourceFileReference> resources,
                        bool debug, bool force32bit, Win32IconResource icon, PhpSourceFile entryPoint)
            : base(new MultiScriptAssembly(applicationContext), assemblyName, directory, fileName, kind, resources, debug, force32bit, false, icon)
        {
            this.entryPoint = entryPoint;
        }
Beispiel #38
0
        /// <summary>
        /// Get the precompiled script from several locations - script library database, precompiled SSA, precompiled MSA (WebPages.dll).
        /// </summary>
        /// <param name="sourceFile">The source file of the script to retrieve.</param>
        /// <returns>The <see cref="ScriptInfo"/> of required script or null if such script cannot be obtained.</returns>
		internal ScriptInfo GetCompiledScript(PhpSourceFile/*!*/ sourceFile)
		{
            return scriptContext.ApplicationContext.RuntimeCompilerManager.GetCompiledScript(sourceFile, this);
		}
Beispiel #39
0
        /// <summary>
        /// Includes a specific script using current configuration.
        /// </summary>
        /// <param name="relativeSourcePath">Source root relative path to the script.</param>
        /// <param name="once">Specifies whether script should be included only once.</param>
        /// <returns>The value returned by the global code of the target script.</returns>
        public object Include(string/*!*/ relativeSourcePath, bool once)
        {
            ApplicationConfiguration app_config = Configuration.Application;

            // searches for file:
            FullPath included_full_path = SearchForIncludedFile(PhpError.Error, relativeSourcePath, FullPath.Empty);
            if (included_full_path.IsEmpty) return false;

            ScriptInfo info;
            bool already_included = scripts.TryGetValue(included_full_path.ToString(), out info);

            // skips inclusion if script has already been included and inclusion's type is "once":
            if (already_included)
            {
                if(once)
                    return ScriptModule.SkippedIncludeReturnValue;

                // script type loaded, info cannot be null
            }
            else
            {
                PhpSourceFile included_source_file = new PhpSourceFile(app_config.Compiler.SourceRoot, included_full_path);
                
                // loads script type:
                info = LoadDynamicScriptType(included_source_file);

                // script not found:
                if (info == null)
                    return false;

                if (MainScriptFile == null)
                    // the first script becomes the main one:
                    DefineMainScript(info, included_source_file);
                else
                    // adds included file into the script list
                    scripts.Add(included_full_path.ToString(), info);
            }

            Debug.Assert(info != null);

            return GuardedCall((ScriptInfo scriptInfo) =>
            {
                //return PhpScript.InvokeMainHelper(
                //    (Type)scriptType,
                return scriptInfo.Main(
                    this,
                    null,  // no local variables
                    null,  // no object context
                    null,  // no class context
                    true);
            }, info, true);
        }
Beispiel #40
0
		public abstract Type GetScriptType(PhpSourceFile sourceFile);
Beispiel #41
0
		/// <summary>
		/// Loads a script type dynamically.
		/// </summary>
		/// <param name="sourceFile">Script's source file.</param>
		private ScriptInfo LoadDynamicScriptType(PhpSourceFile/*!*/ sourceFile)
		{
            Debug.WriteLine("SC", "LoadDynamicScriptType: '{0}'", sourceFile);

            // runtime compiler manages:
            // - 1. script library
            // - 2. optionally bin/WebPages.dll
            // - 3. compiles file from file system if allowed

            return this.ApplicationContext.RuntimeCompilerManager.GetCompiledScript(sourceFile, RequestContext.CurrentContext);
		}
Beispiel #42
0
		public static PhpAssemblyBuilder/*!*/ Create(ApplicationContext/*!*/ applicationContext, AssemblyKinds kind,
			bool pure, FullPath outPath, FullPath docPath, string duckPath, string duckNs, PhpSourceFile entryPoint, Version version,
			StrongNameKeyPair key, Win32IconResource icon, ICollection<ResourceFileReference> resources, bool debug)
		{
			string out_dir = Path.GetDirectoryName(outPath);
			string out_file = Path.GetFileName(outPath);

			AssemblyName assembly_name = new AssemblyName();
			assembly_name.Name = Path.GetFileNameWithoutExtension(outPath);
			assembly_name.Version = version;
			assembly_name.KeyPair = key;

			if (pure)
			{
				// This is primarilly supported for non-pure mode, but it could be extended..
				if (duckPath != null)
					throw new NotSupportedException("Generation of duck type interfaces isn't supported for pure assemblies!");
				return new PureAssemblyBuilder(applicationContext, assembly_name, out_dir, out_file, kind, resources, debug, icon);
			}
			else
				return new MultiScriptAssemblyBuilder(applicationContext, assembly_name, out_dir, out_file, 
										duckPath, duckNs, kind, resources, debug, icon, entryPoint);
		}