private ResponseMessage HandleMessage(RequestMessage msg)
        {
            IndexingServiceRequest isr = (IndexingServiceRequest)msg;

            LuceneQueryable backend = this;

            if (isr.Source != null)
            {
                Queryable target = QueryDriver.GetQueryable(isr.Source);

                if (target == null)
                {
                    string err = String.Format("Unable to find backend matching '{0}'", isr.Source);

                    Log.Error(err);
                    return(new ErrorResponse(err));
                }

                if (!(target.IQueryable is LuceneQueryable))
                {
                    string err = String.Format("Backend '{0}' is not an indexed backend", isr.Source);

                    Log.Error(err);
                    return(new ErrorResponse(err));
                }

                backend = (LuceneQueryable)target.IQueryable;
                Log.Debug("Found backend for IndexingServiceRequest: {0}", backend.IndexName);
            }

            // FIXME: There should be a way for the request to control the
            // scheduler priority of the task.

            if (isr.ToAdd.Count > 0 || isr.ToRemove.Count > 0)
            {
                Log.Debug("IndexingService: Adding {0} indexables, removing {1} indexables.", isr.ToAdd.Count, isr.ToRemove.Count);

                IndexableGenerator ind_gen;
                ind_gen = new IndexableGenerator(isr.ToAdd, isr.ToRemove, this);
                Scheduler.Task task = backend.NewAddTask(ind_gen);
                task.Priority = Scheduler.Priority.Immediate;
                ThisScheduler.Add(task);
            }

            // FIXME: There should be an asynchronous response  (fired by a Scheduler.Hook)
            // that fires when all of the items have been added to the index.

            // No response
            return(new EmptyResponse());
        }
        public static void SendUpdate(IBrowsableItem item)
        {
            Indexable indexable = new Indexable(item.DefaultVersionUri);

            indexable.Type = IndexableType.PropertyChange;
            Beagle.Property prop;

            // Clear the existing tags
            prop              = Beagle.Property.NewKeyword("fspot:Tag", "");
            prop.IsMutable    = true;
            prop.IsPersistent = true;
            indexable.AddProperty(prop);
            prop              = Beagle.Property.NewKeyword("image:Tag", "");
            prop.IsMutable    = true;
            prop.IsPersistent = true;
            indexable.AddProperty(prop);

            foreach (Tag t in item.Tags)
            {
                prop              = Beagle.Property.NewKeyword("fspot:Tag", t.Name);
                prop.IsMutable    = true;
                prop.IsPersistent = true;
                indexable.AddProperty(prop);
                prop              = Beagle.Property.NewKeyword("image:Tag", t.Name);
                prop.IsMutable    = true;
                prop.IsPersistent = true;
                indexable.AddProperty(prop);
            }

            prop              = Beagle.Property.New("fspot:Description", item.Description);
            prop.IsMutable    = true;
            prop.IsPersistent = true;
            indexable.AddProperty(prop);

            // Create a message to send to the daemon with this information.
            // The source tells it what index the existing "/home/joe/test.txt" document lives.
            IndexingServiceRequest req = new IndexingServiceRequest();

            req.Keepalive = false;
            req.Source    = "Files";
            req.Add(indexable);

            req.SendAsync();
        }
    static void Main(String[] args)
    {
        string uriStr           = null;
        string title            = null;
        string sourcefile       = null;
        bool   deletesourcefile = false;

        if (args.Length == 0 || Array.IndexOf(args, "--help") > -1)
        {
            PrintUsage();
            Environment.Exit(1);
        }

        for (int i = 0; i < args.Length; i++)
        {
            switch (args [i])
            {
            case "--url":
            case "--title":
            case "--sourcefile":
                if (i + 1 >= args.Length ||
                    args [i + 1].StartsWith("--"))
                {
                    PrintUsage();
                    Environment.Exit(1);
                }
                break;
            }

            switch (args [i])
            {
            case "--url":
                uriStr = args [++i];
                break;

            case "--title":
                title = args [++i];
                break;

            case "--sourcefile":
                sourcefile = args [++i];
                break;

            case "--deletesourcefile":
                deletesourcefile = true;
                break;

            case "--help":
                PrintUsage();
                return;

            case "--version":
                VersionFu.PrintVersion();
                return;
            }
        }

        if (uriStr == null)
        {
            Logger.Log.Error("URI not specified!\n");
            PrintUsage();
            Environment.Exit(1);
        }

        Uri uri = new Uri(uriStr, true);

        if (uri.Scheme == Uri.UriSchemeHttps)
        {
            // For security/privacy reasons, we don't index any
            // SSL-encrypted pages.
            Logger.Log.Error("Indexing secure https:// URIs is not secure!");
            Environment.Exit(1);
        }

        // We don't index file: Uris.  Silently exit.
        if (uri.IsFile)
        {
            return;
        }

        // We *definitely* don't index mailto: Uris.  Silently exit.
        if (uri.Scheme == Uri.UriSchemeMailto)
        {
            return;
        }

        Indexable indexable;

        indexable           = new Indexable(uri);
        indexable.HitType   = "WebHistory";
        indexable.MimeType  = "text/html";
        indexable.Timestamp = DateTime.Now;

        if (title != null)
        {
            indexable.AddProperty(Property.New("dc:title", title));
        }

        if (sourcefile != null)
        {
            if (!File.Exists(sourcefile))
            {
                Logger.Log.Error("sourcefile '{0}' does not exist!", sourcefile);
                Environment.Exit(1);
            }

            indexable.ContentUri    = UriFu.PathToFileUri(sourcefile);
            indexable.DeleteContent = deletesourcefile;
        }
        else
        {
            Stream stdin = Console.OpenStandardInput();
            if (stdin == null)
            {
                Logger.Log.Error("No sourcefile specified, and no standard input!\n");
                PrintUsage();
                Environment.Exit(1);
            }

            indexable.SetTextReader(new StreamReader(stdin));
        }

        IndexingServiceRequest req = new IndexingServiceRequest();

        req.Add(indexable);

        try {
            Logger.Log.Info("Indexing");
            Logger.Log.Debug("SendAsync");
            req.SendAsync();
            Logger.Log.Debug("Close");
            req.Close();
            Logger.Log.Debug("Done");
        } catch (Exception e) {
            Logger.Log.Error("Indexing failed: {0}", e);

            // Still clean up after ourselves, even if we couldn't
            // index the content.
            if (deletesourcefile)
            {
                File.Delete(sourcefile);
            }

            Environment.Exit(1);
        }
    }