public OpenSocialHelper(int viewerId, int ownerId, Page page)
    {
        this.viewerId = viewerId;
        this.ownerId  = ownerId;
        this.isDebug  = page.Session != null && page.Session[OPENSOCIAL_DEBUG] != null && (bool)page.Session[OPENSOCIAL_DEBUG];
        this.noCache  = page.Session != null && page.Session[OPENSOCIAL_NOCACHE] != null && (bool)page.Session[OPENSOCIAL_NOCACHE];
        this.pageName = page.AppRelativeVirtualPath.Substring(2);

        if (ConfigUtil.GetConfigItem("OpenSocialURL") == null)
        {
            // do nothing
            return;
        }

        Random random = new Random();

        bool   gadgetLogin  = page.AppRelativeVirtualPath.EndsWith("gadgetlogin.aspx");
        String requestAppId = page.Request.QueryString["appId"];

        Dictionary <string, GadgetSpec> dbApps       = new Dictionary <string, GadgetSpec>();
        Dictionary <string, GadgetSpec> officialApps = new Dictionary <string, GadgetSpec>();
        // Load gadgets from the DB first
        IDataReader reader = null;

        try
        {
            Database db = DatabaseFactory.CreateDatabase();

            string sqlCommand = "select appId, name, url, channels, enabled from shindig_apps";
            // if a specific app is requested, only grab it
            if (requestAppId != null)
            {
                sqlCommand += " where appId = " + requestAppId;
            }
            DbCommand dbCommand = db.GetSqlStringCommand(sqlCommand);
            reader = db.ExecuteReader(dbCommand);
            while (reader.Read())
            {
                GadgetSpec spec           = new GadgetSpec(Convert.ToInt32(reader[0]), reader[1].ToString(), reader[2].ToString(), reader[3].ToString());
                string     gadgetFileName = GetGadgetFileNameFromURL(reader[2].ToString());

                dbApps.Add(gadgetFileName, spec);
                if (requestAppId != null || Convert.ToBoolean(reader[4]))
                {
                    officialApps.Add(gadgetFileName, spec);
                }
            }
        }
        catch (Exception e)
        {
            throw new Exception(e.Message);
        }
        finally
        {
            if (reader != null)
            {
                reader.Close();
            }
        }


        // Add manual gadgets if there are any
        // Note that this block of code only gets executed after someone logs in with gadgetlogin.aspx!
        int moduleId = 0;

        if (page.Session != null && (string)page.Session[OPENSOCIAL_GADGETS] != null)
        {
            String   openSocialGadgetURLS = (string)page.Session[OPENSOCIAL_GADGETS];
            String[] urls = openSocialGadgetURLS.Split(Environment.NewLine.ToCharArray());
            for (int i = 0; i < urls.Length; i++)
            {
                String openSocialGadgetURL = urls[i];
                if (openSocialGadgetURL.Length == 0)
                {
                    continue;
                }
                int      appId          = 0; // if URL matches one in the DB, use DB provided appId, otherwise generate one
                string   gadgetFileName = GetGadgetFileNameFromURL(openSocialGadgetURL);
                string   name           = gadgetFileName;
                string[] channels       = new string[0];
                bool     sandboxOnly    = true;
                if (dbApps.ContainsKey(gadgetFileName))
                {
                    appId       = dbApps[gadgetFileName].GetAppId();
                    name        = dbApps[gadgetFileName].GetName();
                    channels    = dbApps[gadgetFileName].GetChannels();
                    sandboxOnly = false;
                }
                else
                {
                    CharEnumerator ce = openSocialGadgetURL.GetEnumerator();
                    while (ce.MoveNext())
                    {
                        appId += (int)ce.Current;
                    }
                }
                // if they asked for a specific one, only let it in
                if (requestAppId != null && Convert.ToInt32(requestAppId) != appId)
                {
                    continue;
                }
                GadgetSpec gadget = new GadgetSpec(appId, name, openSocialGadgetURL, channels, sandboxOnly);
                // only add ones that are visible in this context!
                if (sandboxOnly || gadget.Show(viewerId, ownerId, page.AppRelativeVirtualPath.Substring(2)))
                {
                    String securityToken = SocketSendReceive(viewerId, ownerId, "" + gadget.GetAppId());
                    gadgets.Add(new PreparedGadget(gadget, this, moduleId++, securityToken));
                }
            }
        }

        // if no manual one were added, use the ones from the DB
        if (gadgets.Count == 0)
        {
            // Load DB gadgets
            if (gadgetLogin)
            {
                officialApps = dbApps;
            }
            foreach (KeyValuePair <string, GadgetSpec> pair in officialApps)
            {
                GadgetSpec gadget = new GadgetSpec(pair.Value.GetAppId(), pair.Value.GetName(), pair.Value.GetGadgetURL(), pair.Value.GetChannels(), false);
                // only add ones that are visible in this context!
                if (gadgetLogin || gadget.Show(viewerId, ownerId, GetPageName()))
                {
                    String securityToken = SocketSendReceive(viewerId, ownerId, "" + gadget.GetAppId());
                    gadgets.Add(new PreparedGadget(gadget, this, moduleId++, securityToken));
                }
            }
        }
        // sort the gadgets
        gadgets.Sort();

        // trigger the javascript to render gadgets
        HtmlGenericControl body = (HtmlGenericControl)page.Master.FindControl("bodyMaster");

        if (body == null)
        {
            body = (HtmlGenericControl)page.Master.Master.FindControl("bodyMaster");
        }
        body.Attributes.Add("onload", "my.init();");
    }