Exemple #1
0
        /*
         * Delete an assembly that is out of date, as well as the associated files
         */
        internal static void RemoveOutOfDateAssembly(string assemblyName)
        {
            DirectoryInfo directory = new DirectoryInfo(HttpRuntime.CodegenDirInternal);

            FileInfo[] files = directory.GetFiles(assemblyName + ".*");
            foreach (FileInfo f in files)
            {
                try {
                    // First, just try to delete the file
                    f.Delete();
                }
                catch (Exception) {
                    try {
                        // If the delete failed, rename it to ".delete", so it'll get
                        // cleaned up next time by RemoveOldTempFiles()
                        // Don't do that if it already has the delete extension
                        if (f.Extension != ".delete")
                        {
                            f.MoveTo(f.FullName + ".delete");
                        }
                    }
                    catch (Exception) {
                        // Ignore all exceptions
                        Debug.Assert(false, "Cannot delete " + f.Name + " from " + directory);
                    }
                }
            }
        }
        /*
         * Set some fields that are needed for code generation
         */
        internal BaseCompiler(TemplateParser parser)
        {
            _parser = parser;

            _baseClassType = Parser.BaseType;
            Debug.Assert(_baseClassType != null);
        }
        /// <include file='doc\BaseCompiler.uex' path='docs/doc[@for="BaseCompiler.GetGeneratedClassName"]/*' />
        /// <devdoc>
        ///     Create a name for the generated class
        /// </devdoc>
        private string GetGeneratedClassName()
        {
            string className;

            // If the user specified the class name, just use that
            if (Parser.GeneratedClassName != null)
            {
                return(Parser.GeneratedClassName);
            }

            // If we know the input file name, use it to generate the class name
            if (Parser.InputFile != null)
            {
                // Make sure we have the file name's correct case (ASURT 59179)
                className = Util.CheckExistsAndGetCorrectCaseFileName(Parser.InputFile);

                Debug.Assert(className != null);

                // Get rid of the path
                className = Path.GetFileName(className);

                // Change invalid chars to underscores
                className = Util.MakeValidTypeNameFromString(className);
            }
            else
            {
                // Otherwise, use a default name
                className = tempClassName;
            }

            return(className);
        }
        private void CreateHost()
        {
            Debug.Trace("CBM", "CreateHost");
            Debug.Assert(_host == null);

            Debug.Assert(!_hostCreationPending, "CreateHost: creation already pending");

            _hostCreationPending = true;

            // Use a local to avoid having a partially created _host
            BuildManagerHost host = null;

            try {
                string           appId;
                IApplicationHost appHost;

                ApplicationManager appManager = ApplicationManager.GetApplicationManager();

                host = (BuildManagerHost)appManager.CreateObjectWithDefaultAppHostAndAppId(
                    _physicalPath, _virtualPath,
                    typeof(BuildManagerHost), false /*failIfExists*/,
                    _hostingParameters, out appId, out appHost);

                // host appdomain cannot be unloaded during creation.
                host.AddPendingCall();

                host.Configure(this);

                _host    = host;
                _appId   = appId;
                _appHost = appHost;

                _hostCreationException = _host.InitializationException;
            }
            catch (Exception e) {
                // If an exception happens, keep track of it
                _hostCreationException = e;

                // Even though the host initialization failed, keep track of it so subsequent
                // request will see the error
                _host = host;
            }
            finally {
                _hostCreationPending = false;

                if (host != null)
                {
                    // Notify the client that the host is ready
                    if (AppDomainStarted != null)
                    {
                        AppDomainStarted(this, EventArgs.Empty);
                    }

                    // The host can be unloaded safely now.
                    host.RemovePendingCall();
                }
            }

            Debug.Trace("CBM", "CreateHost LEAVE");
        }
        static bool GetSiteNameFromISAPI()
        {
            Debug.Trace("config_loc", "GetSiteNameFromISAPI()");
            HttpContext context = HttpContext.Current;

            if (context != null)
            {
                string       metabaseAppKey = context.Request.ServerVariables["INSTANCE_META_PATH"];
                const string KEY_LMW3SVC    = "/LM/W3SVC/";
                Debug.Assert(metabaseAppKey.StartsWith(KEY_LMW3SVC));
                string appNumber = metabaseAppKey.Substring(KEY_LMW3SVC.Length - 1);
                //string appServerComment = "/" + appNumber + "/ServerComment";
                Debug.Trace("config_loc", "appNumber:" + appNumber + " INSTANCE_META_PATH:" + metabaseAppKey);

                UnicodeEncoding encoding = new UnicodeEncoding();

                // null-terminate appNumber and convert to byte array
                byte [] byteAppNumber = encoding.GetBytes(appNumber + "\0");

                int     retVal   = 2;
                byte [] outBytes = new byte[64];
                while (retVal == 2)
                {
                    retVal = context.CallISAPI(UnsafeNativeMethods.CallISAPIFunc.GetSiteServerComment,
                                               byteAppNumber, outBytes);
                    if (retVal == 2)
                    {
                        if (outBytes.Length > 1024)   // should never happen
                        {
                            throw new ConfigurationException(HttpRuntime.FormatResourceString(
                                                                 SR.Config_site_name_too_long,
                                                                 metabaseAppKey));
                        }
                        outBytes = new byte[outBytes.Length * 2];
                    }
                }

                // find WCHAR null terminator in byte array
                int i = 0;
                while (i + 1 < outBytes.Length && (outBytes[i] != 0 || outBytes[i + 1] != 0))
                {
                    i += 2;
                }

                // decode up to null terminator
                s_siteName = encoding.GetString(outBytes, 0, i);
                Debug.Trace("config_loc", "i: " + i + " site name:" + s_siteName);

                return(true);
            }
            else
            {
                Debug.Trace("config_loc", "could not query site name.  No Context.");
            }

            return(false); // keep trying to evaluate
        }
        // GetSection
        //
        // Get the Config for a specific path
        //
        static internal object GetSection(string sectionName, VirtualPath path)
        {
            Debug.Assert(UseHttpConfigurationSystem, "UseHttpConfigurationSystem");

            CachedPathData pathData;

            pathData = CachedPathData.GetVirtualPathData(path, true);

            return(pathData.ConfigRecord.GetSection(sectionName));
        }
Exemple #7
0
        protected SimpleWebHandlerParser(HttpContext context, string virtualPath, string physicalPath)
        {
            // These obsolete parameters should never be set
            Debug.Assert(context == null);
            Debug.Assert(physicalPath == null);

            Debug.Assert(virtualPath != null);

            _virtualPath = VirtualPath.Create(virtualPath);
        }
        // GetAppSection
        //
        // Get the Config for a specific path
        //
        static internal object GetApplicationSection(string sectionName)
        {
            Debug.Assert(UseHttpConfigurationSystem, "UseHttpConfigurationSystem");

            CachedPathData pathData;

            pathData = CachedPathData.GetApplicationPathData();

            return(pathData.ConfigRecord.GetSection(sectionName));
        }
Exemple #9
0
        /*
         * Build first-time intialization statements
         */
        protected override void BuildInitStatements(CodeStatementCollection trueStatements, CodeStatementCollection topLevelStatements)
        {
            base.BuildInitStatements(trueStatements, topLevelStatements);

            CodeMemberField fileDependencies = new CodeMemberField(typeof(ArrayList), fileDependenciesName);

            fileDependencies.Attributes |= MemberAttributes.Static;
            _sourceDataClass.Members.Add(fileDependencies);

            // Note: it may look like this local variable declaraiton is redundant. However it is necessary
            // to make this init code re-entrant safe. This way, even if two threads enter the contructor
            // at the same time, they will not add multiple dependencies.

            // e.g. ArrayList dependencies;
            CodeVariableDeclarationStatement dependencies = new CodeVariableDeclarationStatement();

            dependencies.Type = new CodeTypeReference(typeof(ArrayList));
            dependencies.Name = dependenciesLocalName;
            topLevelStatements.Insert(0, dependencies);

            // e.g. dependencies = new System.Collections.ArrayList();
            CodeAssignStatement assignDependencies = new CodeAssignStatement();

            assignDependencies.Left  = new CodeVariableReferenceExpression(dependenciesLocalName);
            assignDependencies.Right = new CodeObjectCreateExpression(typeof(ArrayList));
            // Note: it is important to add all local variables at the top level for CodeDom Subset compliance.
            trueStatements.Add(assignDependencies);

            Debug.Assert(Parser.FileDependencies != null);
            if (Parser.FileDependencies != null)
            {
                int count = Parser.FileDependencies.Length;
                for (int i = 0; i < count; i++)
                {
                    // depdendencies.Add("...");
                    CodeMethodInvokeExpression addFileDep = new CodeMethodInvokeExpression();
                    addFileDep.Method.TargetObject = new CodeVariableReferenceExpression(dependenciesLocalName);
                    addFileDep.Method.MethodName   = "Add";
                    addFileDep.Parameters.Add(new CodePrimitiveExpression((string)Parser.FileDependencies[i]));
                    trueStatements.Add(new CodeExpressionStatement(addFileDep));
                }
            }

            // e.g. __fileDependencies = dependencies;
            CodeAssignStatement initFile = new CodeAssignStatement();

            initFile.Left = new CodeFieldReferenceExpression(_classTypeExpr,
                                                             fileDependenciesName);
            initFile.Right = new CodeVariableReferenceExpression(dependenciesLocalName);

#if DBG
            AppendDebugComment(trueStatements);
#endif
            trueStatements.Add(initFile);
        }
Exemple #10
0
 internal static void RemoveBackgroundBatchCompilation(BackgroundBatchCompiler bbc)
 {
     lock (_backgroundBatchCompilations) {
         try {
             _backgroundBatchCompilations.Remove(bbc);
         }
         catch {
             Debug.Assert(false, "RemoveBackgroundBatchCompilation failed");
         }
     }
 }
        /// <devdoc>
        /// Returns an IEnumerable that is the DataSource, which either came
        /// from the DataSource property or from the control bound via the
        /// DataSourceID property.
        /// </devdoc>
        protected virtual IEnumerable GetData()
        {
            DataSourceView view = ConnectToDataSourceView();

            Debug.Assert(_currentViewValid);

            if (view != null)
            {
                return(view.ExecuteSelect(DataSourceSelectArguments.Empty));
            }
            return(null);
        }
        /*
         * Build a ProcessRequest override which just calls the base.  This is used to make sure
         * there is user code on the stack when requests are executed (VSWhidbey 499386)
         */
        private void BuildProcessRequestOverride()
        {
            //  public override void ProcessRequest(HttpContext context) {
            //      base.ProcessRequest(context);
            //  }

            CodeMemberMethod method = new CodeMemberMethod();

            AddDebuggerNonUserCodeAttribute(method);
            method.Name        = "ProcessRequest";
            method.Attributes &= ~MemberAttributes.AccessMask;
            method.Attributes &= ~MemberAttributes.ScopeMask;

            // If the base type is non-default (i.e. not Page) we have to be careful overriding
            // ProcessRequest, because if the base has its own IHttpHandler.ProcessRequest implementation
            // and it's not overridable, we would fail to compile.  So when we detect this situation,
            // we instead generate it as a new IHttpHandler.ProcessRequest implementation instead of an
            // override.  In theory, we could *always* do this, but it's safer to limit it to this
            // constrained scenario (VSWhidbey 517240)
            MethodInfo methodInfo = null;

            if (Parser.BaseType != typeof(Page))
            {
                methodInfo = Parser.BaseType.GetMethod("ProcessRequest",
                                                       BindingFlags.Public | BindingFlags.Instance,
                                                       null, new Type[] { typeof(HttpContext) }, null);
                Debug.Assert(methodInfo != null);
            }

            _sourceDataClass.BaseTypes.Add(new CodeTypeReference(typeof(IHttpHandler)));

            if (methodInfo != null && methodInfo.DeclaringType != typeof(Page))
            {
                method.Attributes |= MemberAttributes.New | MemberAttributes.Public;
            }
            else
            {
                method.Attributes |= MemberAttributes.Override | MemberAttributes.Public;
            }

            method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(HttpContext), "context"));

            CodeMethodInvokeExpression invokeExpr = new CodeMethodInvokeExpression();

            invokeExpr.Method.TargetObject = new CodeBaseReferenceExpression();
            invokeExpr.Method.MethodName   = "ProcessRequest";
            invokeExpr.Parameters.Add(new CodeArgumentReferenceExpression("context"));

            method.Statements.Add(invokeExpr);

            _sourceDataClass.Members.Add(method);
        }
Exemple #13
0
        private void CacheEntryToMemory(SourceCompilerCachedEntry scce)
        {
            Debug.Assert(_utcStart != DateTime.MinValue);

            // Always add the main compiled file itself as a source dependency
            AddSourceDependency(_physicalPath);

            // Get an array of source file dependencies
            string[] sourceDependencies = Util.StringArrayFromHashtable(_sourceDependencies);

            _cache.UtcInsert(_cacheKey, scce, new CacheDependency(false, sourceDependencies, _utcStart),
                             Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
                             CacheItemPriority.NotRemovable, null);

            Debug.Trace("Template", "Caching source code (" + _virtualPath + "," + scce._assembly.GetName().Name + ")");
        }
        /*
         * Compile an .aspx file into an HttpApplication Type
         */
        internal static Type GetCompiledApplicationType(string inputFile, HttpContext context,
                                                        out ApplicationFileParser parser)
        {
            parser = new ApplicationFileParser();
            parser.CurrentVirtualPath = UrlPath.Combine(context.Request.ApplicationPath,
                                                        HttpApplicationFactory.applicationFileName);
            parser.InputFile = inputFile;
            parser.Context   = context;

            // Never use trivial pages for global.asax (ASURT 32420)
            parser._fAlwaysCompile = true;

            ParserCacheItem cacheItem = parser.GetParserCacheItem();

            Debug.Assert(cacheItem.type != null);
            return(cacheItem.type);
        }
Exemple #15
0
        /*
         * Preserve the combined hash of the special files to a file.
         */
        private static void WritePreservedSpecialFilesCombinedHash(long hash)
        {
            Debug.Assert(hash != 0, "WritePreservedSpecialFilesCombinedHash: hash != 0");
            StreamWriter writer = null;

            try {
                writer = new StreamWriter(GetSpecialFilesCombinedHashFileName(),
                                          false, Encoding.UTF8);
                writer.Write(hash.ToString("x"));
            }
            finally {
                if (writer != null)
                {
                    writer.Close();
                }
            }
        }
        /*
         * Create an object in the runtime appdomain
         */

        public IRegisteredObject CreateObject(Type type, bool failIfExists)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            EnsureHostCreated();
            Debug.Assert(_appId != null);
            Debug.Assert(_appHost != null);

            _host.RegisterAssembly(type.Assembly.FullName, type.Assembly.Location);

            ApplicationManager appManager = ApplicationManager.GetApplicationManager();

            return(appManager.CreateObjectInternal(_appId, type, _appHost, failIfExists, _hostingParameters));
        }
Exemple #17
0
        internal PreservedAssemblyEntry(HttpContext context, string virtualPath, bool fApplicationFile,
                                        Assembly assembly, Type type, Hashtable sourceDependencies)
        {
            _context          = context;
            _virtualPath      = virtualPath;
            _fApplicationFile = fApplicationFile;
            if (assembly != null)
            {
                _assembly = assembly;
            }
            else
            {
                _assembly = type.Module.Assembly;
            }
            _type = type;
            _sourceDependencies = sourceDependencies;

            _assemblyDependencies = Util.GetReferencedAssembliesHashtable(_assembly);

            // If any of the assemblies we depend on are in the bin directory,
            // add a file dependency for them.

            string binDir = HttpRuntime.BinDirectoryInternal;

            foreach (Assembly a in AssemblyDependencies.Keys)
            {
                string assemblyFilePath = Util.FilePathFromFileUrl(a.EscapedCodeBase);
                if (assemblyFilePath.StartsWith(binDir))
                {
                    _sourceDependencies[assemblyFilePath] = assemblyFilePath;
                }
            }

            // If there are some web.config files other than the global ones, depend on them

            string baseVirtualDir = UrlPath.GetDirectory(virtualPath);

            string[] configFiles = context.GetConfigurationDependencies(baseVirtualDir);

            Debug.Assert(configFiles.Length >= _numTopLevelConfigFiles, "configFiles.Length >= _numTopLevelConfigFiles");

            for (int i = 0; i < configFiles.Length - _numTopLevelConfigFiles; i++)
            {
                _sourceDependencies[configFiles[i]] = configFiles[i];
            }
        }
Exemple #18
0
        private void AddConstructorToSource(ConstructorInfo ctor)
        {
            Debug.Assert(ctor != null);
            Debug.Assert(ctor.GetParameters().Length > 0);

            var ctorCode = new CodeConstructor();

            AddDebuggerNonUserCodeAttribute(ctorCode);
            ctorCode.Attributes &= ~MemberAttributes.AccessMask;
            ctorCode.Attributes |= MemberAttributes.Public;

            // copy all the attributes of the contrustor parameters
            foreach (var p in ctor.GetParameters())
            {
                var parameterExpr = new CodeParameterDeclarationExpression(p.ParameterType, p.Name);
                foreach (var attr in p.CustomAttributes)
                {
                    var attrArgs = new List <CodeAttributeArgument>();
                    foreach (var arg in attr.ConstructorArguments)
                    {
                        attrArgs.Add(new CodeAttributeArgument(new CodePrimitiveExpression(arg.Value)));
                    }

                    foreach (var arg in attr.NamedArguments)
                    {
                        attrArgs.Add(new CodeAttributeArgument(arg.MemberName, new CodePrimitiveExpression(arg.TypedValue.Value)));
                    }

                    var customAttrExpr = new CodeAttributeDeclaration(new CodeTypeReference(attr.AttributeType), attrArgs.ToArray());
                    parameterExpr.CustomAttributes.Add(customAttrExpr);
                }
                if (p.HasDefaultValue)
                {
                    var defaultValAttrExpr = new CodeAttributeDeclaration(new CodeTypeReference(typeof(DefaultParameterValueAttribute)),
                                                                          new CodeAttributeArgument(new CodePrimitiveExpression(p.DefaultValue)));
                    parameterExpr.CustomAttributes.Add(defaultValAttrExpr);
                }
                ctorCode.Parameters.Add(parameterExpr);
                ctorCode.BaseConstructorArgs.Add(new CodeVariableReferenceExpression(p.Name));
            }

            ctorCode.Statements.Add(CreateInitInvoke());
            _sourceDataClass.Members.Add(ctorCode);
        }
Exemple #19
0
        private void AddConstructorToSource(ConstructorInfo ctor)
        {
            Debug.Assert(ctor != null);
            Debug.Assert(ctor.GetParameters().Length > 0);

            var ctorCode = new CodeConstructor();

            AddDebuggerNonUserCodeAttribute(ctorCode);
            ctorCode.Attributes &= ~MemberAttributes.AccessMask;
            ctorCode.Attributes |= MemberAttributes.Public;

            foreach (var p in ctor.GetParameters())
            {
                ctorCode.Parameters.Add(new CodeParameterDeclarationExpression(p.ParameterType, p.Name));
                ctorCode.BaseConstructorArgs.Add(new CodeVariableReferenceExpression(p.Name));
            }

            ctorCode.Statements.Add(CreateInitInvoke());
            _sourceDataClass.Members.Add(ctorCode);
        }
Exemple #20
0
        private long NextSample()
        {
            // not thread-safe, only invoke from timer callback
            Debug.Assert(_inPBytesMonitorThread == 1);

            // NtQuerySystemInformation is a very expensive call. A new function
            // exists on XP Pro and later versions of the OS and it performs much
            // better. The name of that function is GetProcessMemoryInfo. For hosting
            // scenarios where a larger number of w3wp.exe instances are running, we
            // want to use the new API (VSWhidbey 417366).
            long privateBytes;

            if (_useGetProcessMemoryInfo)
            {
                long privatePageCount;
                UnsafeNativeMethods.GetPrivateBytesIIS6(out privatePageCount, true /*nocache*/);
                privateBytes = privatePageCount;
            }
            else
            {
                uint dummy;
                uint privatePageCount = 0;
                // this is a very expensive call
                UnsafeNativeMethods.GetProcessMemoryInformation(_pid, out privatePageCount, out dummy, true /*nocache*/);
                privateBytes = (long)privatePageCount << MEGABYTE_SHIFT;
            }

            // increment the index (it's either 1 or 0)
            Debug.Assert(SAMPLE_COUNT == 2);
            _idx = _idx ^ 1;
            // remember the sample time
            _sampleTimes[_idx] = DateTime.UtcNow;
            // remember the sample value
            _samples[_idx] = privateBytes;

#if PERF
            SafeNativeMethods.OutputDebugString(String.Format("CacheManager.NextSample:  privateBytes={0:N}, _highPresureMark={1:N}\n", privateBytes, _highPressureMark));
#endif

            return(privateBytes);
        }
        /*
         * Helper method for building application and session scope injected
         * properties.  If useApplicationState, build application properties, otherwise
         * build session properties.
         */
        private void BuildObjectPropertiesHelper(IDictionary objects, bool useApplicationState)
        {
            IDictionaryEnumerator en = objects.GetEnumerator();

            while (en.MoveNext())
            {
                HttpStaticObjectsEntry entry = (HttpStaticObjectsEntry)en.Value;

                // e.g. (PropType)Session.StaticObjects["PropName"]

                // Use the appropriate collection
                CodePropertyReferenceExpression stateObj = new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(),
                                                                                                                                   useApplicationState ? "Application" : "Session"),
                                                                                               "StaticObjects");

                CodeMethodInvokeExpression getObject = new CodeMethodInvokeExpression(stateObj, "GetObject");
                getObject.Parameters.Add(new CodePrimitiveExpression(entry.Name));


                Type declaredType = entry.DeclaredType;
                Debug.Assert(!Util.IsLateBoundComClassicType(declaredType));

                if (useApplicationState)
                {
                    // for application state use property that does caching in a member
                    BuildInjectedGetPropertyMethod(entry.Name, declaredType.FullName,
                                                   new CodeCastExpression(declaredType.FullName, getObject),
                                                   false /*fPublicProp*/);
                }
                else
                {
                    // for session state use lookup every time, as one application instance deals with many sessions
                    CodeMemberProperty prop = new CodeMemberProperty();
                    prop.Name = entry.Name;
                    prop.Type = new CodeTypeReference(declaredType.FullName);
                    prop.GetStatements.Add(new CodeMethodReturnStatement(new CodeCastExpression(declaredType.FullName, getObject)));
                    _sourceDataClass.Members.Add(prop);
                }
            }
        }
Exemple #22
0
        internal BatchCompilationEntry(string virtualPath, string filename, HttpContext context)
        {
            _virtualPath = virtualPath;
            string extension = Path.GetExtension(filename);

            if (string.Compare(extension, ".aspx", true, CultureInfo.InvariantCulture) == 0)
            {
                _templateParser = new PageParser();
            }
            else if (string.Compare(extension, ".ascx", true, CultureInfo.InvariantCulture) == 0)
            {
                _templateParser = new UserControlParser();
                _fUserControl   = true;
            }
            else
            {
                Debug.Assert(false, "Unexpected extension");
            }

            _templateParser.InputFile          = filename;
            _templateParser.Context            = context;
            _templateParser.CurrentVirtualPath = virtualPath;
        }
Exemple #23
0
        internal override CodeExpression BuildStringPropertyExpression(PropertyEntry pse)
        {
            // Make the UrlProperty based on virtualDirPath for control themes.
            if (pse.PropertyInfo != null)
            {
                UrlPropertyAttribute urlAttrib = Attribute.GetCustomAttribute(pse.PropertyInfo, typeof(UrlPropertyAttribute)) as UrlPropertyAttribute;

                if (urlAttrib != null)
                {
                    if (pse is SimplePropertyEntry)
                    {
                        SimplePropertyEntry spse = (SimplePropertyEntry)pse;

                        string strValue = (string)spse.Value;
                        if (UrlPath.IsRelativeUrl(strValue) && !UrlPath.IsAppRelativePath(strValue))
                        {
                            spse.Value = UrlPath.MakeVirtualPathAppRelative(UrlPath.Combine(_themeParser.VirtualDirPath.VirtualPathString, strValue));
                        }
                    }
                    else
                    {
                        Debug.Assert(pse is ComplexPropertyEntry);
                        ComplexPropertyEntry  cpe     = (ComplexPropertyEntry)pse;
                        StringPropertyBuilder builder = (StringPropertyBuilder)cpe.Builder;

                        string strValue = (string)builder.BuildObject();
                        if (UrlPath.IsRelativeUrl(strValue) && !UrlPath.IsAppRelativePath(strValue))
                        {
                            cpe.Builder = new StringPropertyBuilder(UrlPath.MakeVirtualPathAppRelative(UrlPath.Combine(_themeParser.VirtualDirPath.VirtualPathString, strValue)));
                        }
                    }
                }
            }

            return(base.BuildStringPropertyExpression(pse));
        }
Exemple #24
0
        protected override void BuildSourceDataTreeFromBuilder(ControlBuilder builder,
                                                               bool fInTemplate, bool topLevelControlInTemplate,
                                                               PropertyEntry pse)
        {
            // Don't do anything for code blocks
            if (builder is CodeBlockBuilder)
            {
                return;
            }

            // Is the current builder for a template?
            bool fTemplate = (builder is TemplateBuilder);

            // Is the current builder the root builder?
            bool fRootBuilder = (builder == _themeParser.RootBuilder);

            // Is this a control theme?
            bool fControlSkin = !fInTemplate && !fTemplate && topLevelControlInTemplate;

            // Ignore the ID attribute, always auto generate ID.
            _controlCount++;
            builder.ID            = "__control" + _controlCount.ToString(NumberFormatInfo.InvariantInfo);
            builder.IsGeneratedID = true;

            // Check for the SkinID property.
            if (fControlSkin && !(builder is DataBoundLiteralControlBuilder))
            {
                Type ctrlType = builder.ControlType;
                Debug.Assert(typeof(Control).IsAssignableFrom(ctrlType));
                Debug.Assert(ThemeableAttribute.IsTypeThemeable(ctrlType));

                string skinID  = builder.SkinID;
                object skinKey = PageTheme.CreateSkinKey(builder.ControlType, skinID);

                if (_controlSkinTypeNameCollection.Contains(skinKey))
                {
                    if (String.IsNullOrEmpty(skinID))
                    {
                        throw new HttpParseException(SR.GetString(SR.Page_theme_default_theme_already_defined,
                                                                  builder.ControlType.FullName), null, builder.VirtualPath, null, builder.Line);
                    }
                    else
                    {
                        throw new HttpParseException(SR.GetString(SR.Page_theme_skinID_already_defined, skinID),
                                                     null, builder.VirtualPath, null, builder.Line);
                    }
                }

                _controlSkinTypeNameCollection.Add(skinKey, true);
                _controlSkinBuilderEntryList.Add(new ControlSkinBuilderEntry(builder, skinID));
            }

            // Process the children
            // only root builders and template builders are processed.
            if (builder.SubBuilders != null)
            {
                foreach (object child in builder.SubBuilders)
                {
                    if (child is ControlBuilder)
                    {
                        bool isTopLevelCtrlInTemplate = fTemplate && typeof(Control).IsAssignableFrom(((ControlBuilder)child).ControlType);
                        BuildSourceDataTreeFromBuilder((ControlBuilder)child, fInTemplate, isTopLevelCtrlInTemplate, null);
                    }
                }
            }

            foreach (TemplatePropertyEntry entry in builder.TemplatePropertyEntries)
            {
                BuildSourceDataTreeFromBuilder(((TemplatePropertyEntry)entry).Builder, true, false /*topLevelControlInTemplate*/, entry);
            }

            foreach (ComplexPropertyEntry entry in builder.ComplexPropertyEntries)
            {
                if (!(entry.Builder is StringPropertyBuilder))
                {
                    BuildSourceDataTreeFromBuilder(((ComplexPropertyEntry)entry).Builder, fInTemplate, false /*topLevelControlInTemplate*/, entry);
                }
            }

            // Build a Build method for the control
            // fControlSkin indicates whether the method is a theme build method.
            if (!fRootBuilder)
            {
                BuildBuildMethod(builder, fTemplate, fInTemplate, topLevelControlInTemplate, pse,
                                 fControlSkin);
            }

            // Build a Render method for the control, unless it has no code
            if (!fControlSkin && builder.HasAspCode)
            {
                BuildRenderMethod(builder, fTemplate);
            }

            // Build a method to extract values from the template
            BuildExtractMethod(builder);

            // Build a property binding method for the control
            BuildPropertyBindingMethod(builder, fControlSkin);
        }
Exemple #25
0
        void Adjust()
        {
            // not thread-safe, only invoke from timer callback
            Debug.Assert(_inPBytesMonitorThread == 1);

            Debug.Assert(SAMPLE_COUNT == 2);
            // current sample
            long s2 = _samples[_idx];
            // previous sample
            long s1 = _samples[_idx ^ 1];

            // adjust _maxDelta and pressure marks
            if (s2 > s1 && s1 > 0)
            {
                // current time
                DateTime d2 = _sampleTimes[_idx];
                // previous time
                DateTime d1 = _sampleTimes[_idx ^ 1];

                long numBytes   = s2 - s1;
                long numSeconds = (long)Math.Round(d2.Subtract(d1).TotalSeconds);
                if (numSeconds > 0)
                {
                    long delta = numBytes / numSeconds;
                    _deltaSamples[_idxDeltaSamples] = delta;
                    _idxDeltaSamples = (_idxDeltaSamples + 1) % DELTA_SAMPLE_COUNT;
                    // update rate of change in private bytes and pressure marks
                    AdjustMaxDeltaAndPressureMarks(delta);
                }
            }

            lock (_timerLock) {
                if (_timer == null)
                {
                    return;
                }

                // adjust timer frequency
                if (s2 > _mediumPressureMark)
                {
                    if (_currentPollInterval > HIGH_FREQ_INTERVAL_MS)
                    {
                        _currentPollInterval = HIGH_FREQ_INTERVAL_MS;
                        _timer.Change(_currentPollInterval, _currentPollInterval);
                    }
                }
                else if (s2 > _lowPressureMark)
                {
                    if (_currentPollInterval > MEDIUM_FREQ_INTERVAL_MS)
                    {
                        _currentPollInterval = MEDIUM_FREQ_INTERVAL_MS;
                        _timer.Change(_currentPollInterval, _currentPollInterval);
                    }
                }
                else
                {
                    if (_currentPollInterval != LOW_FREQ_INTERVAL_MS)
                    {
                        _currentPollInterval = LOW_FREQ_INTERVAL_MS;
                        _timer.Change(_currentPollInterval, _currentPollInterval);
                    }
                }
            }
        }
Exemple #26
0
        void AdjustMaxDeltaAndPressureMarks(long delta)
        {
            // not thread-safe...only invoke from ctor or timer callback
            Debug.Assert(_inPBytesMonitorThread == 1 || _timer == null);

            // The value of _maxDelta is the largest rate of change we've seen,
            // but it is reduced if the rate is now consistently less than what
            // it once was.
            long newMaxDelta = _maxDelta;

            if (delta > newMaxDelta)
            {
                // set maxDelta to the current rate of change
                newMaxDelta = delta;
            }
            else
            {
                // if _maxDelta is at least four times larger than every sample rate in the history,
                // then reduce _maxDelta
                bool reduce   = true;
                long maxDelta = _maxDelta / 4;
                foreach (long rate in _deltaSamples)
                {
                    if (rate > maxDelta)
                    {
                        reduce = false;
                        break;
                    }
                }
                if (reduce)
                {
                    newMaxDelta = maxDelta * 2;
                }
            }

            // ensure that maxDelta is sufficiently large so that the _highPressureMark is sufficiently
            // far away from the memory limit
            newMaxDelta = Math.Max(newMaxDelta, _minMaxDelta);

            // Do we have a new maxDelta?  If so, adjust it and pressure marks.
            if (_maxDelta != newMaxDelta)
            {
                // adjust _maxDelta
                _maxDelta = newMaxDelta;
                // instead of using _maxDelta, use twice _maxDelta since recycling is
                // expensive and the real delta fluctuates
                _highPressureMark   = Math.Max(_limit * 9 / 10, _limit - (_maxDelta * 2 * HIGH_FREQ_INTERVAL_S));
                _lowPressureMark    = Math.Max(_limit * 6 / 10, _limit - (_maxDelta * 2 * LOW_FREQ_INTERVAL_S));
                _mediumPressureMark = Math.Max((_highPressureMark + _lowPressureMark) / 2, _limit - (_maxDelta * 2 * MEDIUM_FREQ_INTERVAL_S));
                _mediumPressureMark = Math.Min(_highPressureMark, _mediumPressureMark);

#if PERF
                SafeNativeMethods.OutputDebugString(String.Format("CacheManager.AdjustMaxDeltaAndPressureMarks:  _highPressureMark={0:N}, _mediumPressureMark={1:N}, _lowPressureMark={2:N}, _maxDelta={3:N}\n", _highPressureMark, _mediumPressureMark, _lowPressureMark, _maxDelta));
#endif

#if DBG
                Debug.Trace("CacheMemory", "AdjustMaxDeltaAndPressureMarks "
                            + "delta=" + delta
                            + ", _maxDelta=" + _maxDelta
                            + ", _highPressureMark=" + _highPressureMark
                            + ", _mediumPressureMark=" + _mediumPressureMark
                            + ", _lowPressureMark=" + _lowPressureMark);
#endif
            }
        }
        // This function is named after a comment in the original code that sums up what it does nicely.
        //  // now we zip up the path, composing config
        HttpConfigurationRecord ComposeConfig(String reqPath, IHttpMapPath configmap)
        {
            // remove ending "/"
            if (reqPath != null && reqPath.Length > 0 && reqPath[reqPath.Length - 1] == '/')
            {
                reqPath = reqPath.Substring(0, reqPath.Length - 1);
            }

            if (configmap == null && reqPath != null)
            {
                //
                // s_contextlessMapPath only works for paths from machine-level to application-level
                // This is only exposed to internal APIs, so this is just to make sure we don't break ourselves.
                //
                Debug.Assert(reqPath != null && (reqPath.Length > s_contextlessMapPath.ApplicationPath.Length ||
                                                 s_contextlessMapPath.ApplicationPath.Substring(0, reqPath.Length) == reqPath));

                configmap = s_contextlessMapPath;
            }
            // QUICK: look up record in cache (case-insensitive)

            //
            // This is the common case because most pages are requested more than once every five minutes
            // Note: will be null on first invocation
            //
            HttpConfigurationRecord configRecord = CacheLookup(reqPath);

            if (configRecord != null)
            {
                return(configRecord);
            }

            DateTime utcStart = DateTime.UtcNow;

            // SLOW: hunt around

            //
            // Next, we start from the end of the request path and work our way toward the machine-level config
            // record.  The first record we find is the one we use.  Later we'll walk back down the path stack
            // building all the records that weren't found in the cache.
            //
            // Note: On first invocation for this appdomain we won't find anything in the cache, so we'll compose
            //      all config records from machine-level down.
            //
            ArrayList pathStack = new ArrayList();
            String    path      = reqPath;
            HttpConfigurationRecord parentRecord = null;

            for (;;)
            {
                // stack child
                pathStack.Add(path);

                // escape from root
                if (path == null)
                {
                    break;
                }

                // go to parent
                path = ParentPath(path);

                // look it up
                parentRecord = CacheLookup(path);

                if (parentRecord == null)
                {
                    configRecord = null;
                }
                else
                {
                    if (parentRecord.IsInheritable)   // only inherit from directory ConfigRecords, else keep looking
                    {
                        Debug.Trace("config", "Config located in cache " + QuoteString(path));
                        break;
                    }
                    configRecord = parentRecord;
                }
            }

            // now we zip down the path, composing config

            //
            // We walk down the path ...
            // For each directory, we build a config record and add a dependency on the config file
            // The first path that doesn't map to a directory we assume
            //   is a file (leaf in the config system and not inheritable)
            // Anything left in the path stack after the file* is assumed to
            //      be pathinfo** and is ignored.
            //
            // Notes:
            // * - we never verify the physical file, it's assumed if the mapped path
            //      is not a directory (is this correct behavior?)
            // ** - pathinfo is the possible junk on the path after the file path:
            //      example: http://localhost/myapp/foo.aspx/bar
            //          /myapp/foo.aspx - file path (see Request.FilePath)
            //          /bar            - pathinfo
            //
            bool          isDir         = true;
            CacheInternal cacheInternal = HttpRuntime.CacheInternal;

            for (int i = pathStack.Count - 1; i >= 0 && isDir == true; i--)
            {
                String    configFile = null;
                String    mappedPath = null;
                Hashtable cachedeps  = null;

                path = (String)pathStack[i];


                if (path == null)
                {
                    mappedPath = "";
                    if (configmap == null)
                    {
                        configFile = HttpConfigurationSystemBase.MachineConfigurationFilePath;
                    }
                    else
                    {
                        configFile = configmap.MachineConfigPath;
                    }

                    // null MachineConfigPath -> never cache config - always return an empty record.
                    if (configFile == null)
                    {
                        return(HttpConfigurationRecord.Empty);
                    }

                    AddFileDependency(configFile);
                }
                else
                {
                    if (IsPath(path))
                    {
                        mappedPath = configmap.MapPath(path);

                        if (IsDirectory(mappedPath))
                        {
                            // for the directory case, grab the config file and a dependency on it
                            configFile = Path.Combine(mappedPath, WebConfigFileName);
                            AddFileDependency(configFile);
                        }
                        else
                        {
                            // otherwise, we're a file and we go ahead and compute as a file
                            isDir = false; // break loop (after record is built)

                            // we need make the cache item dependent on the mapped file location
                            // in case it becomes a directory.
                            if (mappedPath != null)
                            {
                                Debug.Assert(cachedeps == null, "ctracy investigation - cachedeps == null");
                                cachedeps             = new Hashtable(SymbolHashCodeProvider.Default, SymbolEqualComparer.Default);
                                cachedeps[mappedPath] = mappedPath;
                            }
                        }
                    }
                }

                configRecord = new HttpConfigurationRecord(configFile, parentRecord, /*mappedPath,*/ isDir, path);
                string          key        = CacheKey(path);
                CacheDependency dependency = GetCacheDependencies(cachedeps, utcStart);

                Debug.Trace("config_verbose", "Inserting :" + path);

                if (IsBreakOnUnrecognizedElement)
                {
                    // If the registry key is set to debug the rare 'Unrecognized Element'
                    // stress error, lets try to reproduce the error by having an absolute
                    // expiry of 5 minutes (this will cause us to re-read config much more
                    // often.  Before it took memory pressure.
                    DateTime absouteExpiry = DateTime.UtcNow + new TimeSpan(0, 5, 0);
                    cacheInternal.UtcInsert(key, configRecord, dependency, absouteExpiry, Cache.NoSlidingExpiration);
                }
                else
                {
                    if (configRecord.HasError)
                    {
                        cacheInternal.UtcInsert(key, configRecord, dependency,
                                                DateTime.UtcNow.AddSeconds(5), Cache.NoSlidingExpiration);
                    }
                    else
                    {
                        // default: default cache priority, sliding expiration
                        // this will make us rarely expire, config is expensive
                        cacheInternal.UtcInsert(key, configRecord, dependency);
                    }
                }

                // This is to wire-up notification of directories who exist (without a config file) and
                // are then deleted.  In this case we don't want to restart the appdomain because no config information has
                // changed.  We do want to remove the cache record and recreate it on the next request.  (Something in
                // the cache record might be assuming the directory still exists.)
                if (isDir && !FileUtil.FileExists(configFile) && HandlerBase.IsPathAtAppLevel(path) == PathLevel.BelowApp)
                {
                    //AddDirectoryDependency(mappedPath, path, configRecord);
                }

                configRecord.CheckCachedException();
                parentRecord = configRecord;
            }

            return(configRecord);
        }
Exemple #28
0
        private void CollectInfrequently(long privateBytes)
        {
            // not thread-safe, only invoke from timer callback
            Debug.Assert(_inPBytesMonitorThread == 1);

            // The Server GC on x86 can traverse ~200mb per CPU per second, and the maximum heap size
            // is about 3400mb, so the worst case scenario on x86 would take about 8 seconds to collect
            // on a dual CPU box.
            //
            // The Server GC on x64 can traverse ~300mb per CPU per second, so a 6000 MB heap will take
            // about 10 seconds to collect on a dual CPU box.  The worst case scenario on x64 would make
            // you want to return your hardware for a refund.

            long timeSinceInducedGC = DateTime.UtcNow.Subtract(_inducedGCFinishTime).Ticks;
            bool infrequent         = (timeSinceInducedGC > _inducedGCMinInterval);

            // if we haven't collected recently, or if the trim percent is low (less than 50%),
            // we need to collect again
            if (infrequent || _lastTrimPercent < 50)
            {
                // if we're inducing GC too frequently, increase the trim percentage, but don't go above 50%
                if (!infrequent)
                {
                    _lastTrimPercent = Math.Min(50, _lastTrimPercent + 10);
                }
                // if we're inducing GC infrequently, we may want to decrease the trim percentage
                else if (_lastTrimPercent > 10 && timeSinceInducedGC > 2 * _inducedGCMinInterval)
                {
                    _lastTrimPercent = Math.Max(10, _lastTrimPercent - 10);
                }
                int  percent          = (_totalCacheSize > 0) ? _lastTrimPercent : 0;
                long trimmedOrExpired = 0;
                if (percent > 0)
                {
                    Stopwatch sw1 = Stopwatch.StartNew();
                    trimmedOrExpired = _appManager.TrimCaches(percent);
                    sw1.Stop();
                    _trimDurationTicks = sw1.Elapsed.Ticks;
                }

                //

                if (trimmedOrExpired == 0 || _appManager.ShutdownInProgress)
                {
                    return;
                }

                // collect and record statistics
                Stopwatch sw2 = Stopwatch.StartNew();
                GC.Collect();
                sw2.Stop();

                _inducedGCCount++; // only used for debugging
                _inducedGCFinishTime         = DateTime.UtcNow;
                _inducedGCDurationTicks      = sw2.Elapsed.Ticks;
                _inducedGCPostPrivateBytes   = NextSample();
                _inducedGCPrivateBytesChange = privateBytes - _inducedGCPostPrivateBytes;
                // target 3.3% Time in GC, but don't induce a GC more than once every 5 seconds
                // Notes on calculation below:  If G is duration of garbage collection and T is duration
                // between starting the next collection, then G/T is % Time in GC.  If we target 3.3%,
                // then G/T = 3.3% = 33/1000, so T = G * 1000/33.
                _inducedGCMinInterval = Math.Max(_inducedGCDurationTicks * 1000 / 33, 5 * TimeSpan.TicksPerSecond);
                // no more frequently than every 60 seconds if change is less than 1%
                if (_inducedGCPrivateBytesChange * 100 <= privateBytes)
                {
                    _inducedGCMinInterval = Math.Max(_inducedGCMinInterval, 60 * TimeSpan.TicksPerSecond);
                }
#if DBG
                Debug.Trace("CacheMemory", "GC.COLLECT STATS "
                            + "TrimCaches(" + percent + ")"
                            + ", trimDurationSeconds=" + (_trimDurationTicks / TimeSpan.TicksPerSecond)
                            + ", trimmedOrExpired=" + trimmedOrExpired
                            + ", #secondsSinceInducedGC=" + (timeSinceInducedGC / TimeSpan.TicksPerSecond)
                            + ", InducedGCCount=" + _inducedGCCount
                            + ", gcDurationSeconds=" + (_inducedGCDurationTicks / TimeSpan.TicksPerSecond)
                            + ", PrePrivateBytes=" + privateBytes
                            + ", PostPrivateBytes=" + _inducedGCPostPrivateBytes
                            + ", PrivateBytesChange=" + _inducedGCPrivateBytesChange
                            + ", gcMinIntervalSeconds=" + (_inducedGCMinInterval / TimeSpan.TicksPerSecond));
#endif

#if PERF
                SafeNativeMethods.OutputDebugString("  ** COLLECT **: "
                                                    + percent + "%, "
                                                    + (_trimDurationTicks / TimeSpan.TicksPerSecond) + " seconds"
                                                    + ", infrequent=" + infrequent
                                                    + ", removed=" + trimmedOrExpired
                                                    + ", sinceIGC=" + (timeSinceInducedGC / TimeSpan.TicksPerSecond)
                                                    + ", IGCCount=" + _inducedGCCount
                                                    + ", IGCDuration=" + (_inducedGCDurationTicks / TimeSpan.TicksPerSecond)
                                                    + ", preBytes=" + privateBytes
                                                    + ", postBytes=" + _inducedGCPostPrivateBytes
                                                    + ", byteChange=" + _inducedGCPrivateBytesChange
                                                    + ", IGCMinInterval=" + (_inducedGCMinInterval / TimeSpan.TicksPerSecond) + "\n");
#endif
            }
        }
Exemple #29
0
        private Control LoadControl(IWebObjectFactory objectFactory, VirtualPath virtualPath, Type t, object[] parameters)
        {
            // Make sure we get an object factory or a type, but not both
            Debug.Assert((objectFactory == null) != (t == null));

            BuildResultCompiledType         compiledUCResult  = null;
            BuildResultNoCompileUserControl noCompileUCResult = null;

            if (objectFactory != null)
            {
                // It can be a compiled or no-compile user control
                compiledUCResult = objectFactory as BuildResultCompiledType;
                if (compiledUCResult != null)
                {
                    t = compiledUCResult.ResultType;
                    Debug.Assert(t != null);

                    // Make sure it's a user control (VSWhidbey 428718)
                    Util.CheckAssignableType(typeof(UserControl), t);
                }
                else
                {
                    noCompileUCResult = (BuildResultNoCompileUserControl)objectFactory;
                    Debug.Assert(noCompileUCResult != null);
                }
            }
            else
            {
                // Make sure the type has the correct base class (ASURT 123677)
                if (t != null)
                {
                    Util.CheckAssignableType(typeof(Control), t);
                }
            }

            PartialCachingAttribute cacheAttrib;

            // Check if the user control has a PartialCachingAttribute attribute
            if (t != null)
            {
                cacheAttrib = (PartialCachingAttribute)
                              TypeDescriptor.GetAttributes(t)[typeof(PartialCachingAttribute)];
            }
            else
            {
                cacheAttrib = noCompileUCResult.CachingAttribute;
            }

            if (cacheAttrib == null)
            {
                // The control is not cached.  Just create it.
                Control c;
                if (objectFactory != null)
                {
                    c = (Control)objectFactory.CreateInstance();
                }
                else
                {
                    c = (Control)HttpRuntime.CreatePublicInstance(t, parameters);
                }

                // If it's a user control, do some extra initialization
                UserControl uc = c as UserControl;
                if (uc != null)
                {
                    Debug.Assert(virtualPath != null);
                    if (virtualPath != null)
                    {
                        uc.TemplateControlVirtualPath = virtualPath;
                    }
                    uc.InitializeAsUserControl(Page);
                }

                return(c);
            }

            HashCodeCombiner combinedHashCode = new HashCodeCombiner();

            // Start by adding the type or object factory of the user control to the hash.
            // This guarantees that two unrelated user controls don't share the same cached data.
            if (objectFactory != null)
            {
                combinedHashCode.AddObject(objectFactory);
            }
            else
            {
                combinedHashCode.AddObject(t);
            }

            // If it's not shared, add some stack frames to the hash
            if (!cacheAttrib.Shared)
            {
                AddStackContextToHashCode(combinedHashCode);
            }

            string cacheKey = combinedHashCode.CombinedHashString;

            // Wrap it to allow it to be cached
            return(new PartialCachingControl(objectFactory, t, cacheAttrib, "_" + cacheKey, parameters));
        }
        /*
         * Build first-time intialization statements
         */
        protected override void BuildInitStatements(CodeStatementCollection trueStatements, CodeStatementCollection topLevelStatements)
        {
            base.BuildInitStatements(trueStatements, topLevelStatements);

            //



            CodeMemberField fileDependencies = new CodeMemberField(typeof(object), fileDependenciesName);

            fileDependencies.Attributes |= MemberAttributes.Static;
            _sourceDataClass.Members.Add(fileDependencies);

            // Note: it may look like this local variable declaration is redundant. However it is necessary
            // to make this init code re-entrant safe. This way, even if two threads enter the contructor
            // at the same time, they will not add multiple dependencies.

            // e.g. string[] dependencies;
            CodeVariableDeclarationStatement dependencies = new CodeVariableDeclarationStatement();

            dependencies.Type = new CodeTypeReference(typeof(string[]));
            dependencies.Name = dependenciesLocalName;
            // Note: it is important to add all local variables at the top level for CodeDom Subset compliance.
            topLevelStatements.Insert(0, dependencies);

            Debug.Assert(Parser.SourceDependencies != null);

            StringSet virtualDependencies = new StringSet();

            virtualDependencies.AddCollection(Parser.SourceDependencies);

            // e.g. dependencies = new string[{{virtualDependencies.Count}}];;
            CodeAssignStatement assignDependencies = new CodeAssignStatement();

            assignDependencies.Left =
                new CodeVariableReferenceExpression(dependenciesLocalName);
            assignDependencies.Right =
                new CodeArrayCreateExpression(typeof(String), virtualDependencies.Count);
            trueStatements.Add(assignDependencies);

            int i = 0;

            foreach (string virtualDependency in virtualDependencies)
            {
                // e.g. dependencies[i] = "~/sub/foo.aspx";
                CodeAssignStatement addFileDep = new CodeAssignStatement();
                addFileDep.Left =
                    new CodeArrayIndexerExpression(
                        new CodeVariableReferenceExpression(dependenciesLocalName),
                        new CodeExpression[] { new CodePrimitiveExpression(i++) });
                string src = UrlPath.MakeVirtualPathAppRelative(virtualDependency);
                addFileDep.Right = new CodePrimitiveExpression(src);
                trueStatements.Add(addFileDep);
            }

            // e.g. __fileDependencies = this.GetWrappedFileDependencies(dependencies);
            CodeAssignStatement initFile = new CodeAssignStatement();

            initFile.Left = new CodeFieldReferenceExpression(_classTypeExpr, fileDependenciesName);
            CodeMethodInvokeExpression createWrap = new CodeMethodInvokeExpression();

            createWrap.Method.TargetObject = new CodeThisReferenceExpression();
            createWrap.Method.MethodName   = "GetWrappedFileDependencies";
            createWrap.Parameters.Add(new CodeVariableReferenceExpression(dependenciesLocalName));
            initFile.Right = createWrap;

#if DBG
            AppendDebugComment(trueStatements);
#endif
            trueStatements.Add(initFile);
        }