4 // Copyright (C) 2004 Novell, Inc.
7 // Fredrik Hedberg (fredrik.hedberg@avafan.com)
11 // Permission is hereby granted, free of charge, to any person obtaining a
12 // copy of this software and associated documentation files (the "Software"),
13 // to deal in the Software without restriction, including without limitation
14 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 // and/or sell copies of the Software, and to permit persons to whom the
16 // Software is furnished to do so, subject to the following conditions:
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 // DEALINGS IN THE SOFTWARE.
32 using System
.Collections
;
34 using System
.Threading
;
37 using Beagle
.Util
.Mozilla
;
39 namespace Beagle
.Daemon
.Mozilla
{
41 internal class MozillaCrawler
: Crawler
{
43 MozillaQueryable queryable
;
45 public MozillaCrawler (MozillaQueryable queryable
, string fingerprint
) : base (fingerprint
)
47 this.queryable
= queryable
;
50 protected override bool SkipByName (FileSystemInfo info
)
52 if (info
as DirectoryInfo
!= null)
55 if (File
.Exists (info
+ ".msf"))
61 protected override void CrawlFile (FileSystemInfo info
)
63 FileInfo file
= info
as FileInfo
;
66 this.queryable
.Index (file
);
70 [QueryableFlavor (Name
="Mail", Domain
=QueryDomain
.Local
)]
71 public class MozillaMailQueryable
: MozillaQueryable
73 public MozillaMailQueryable () : base ("MozillaMailIndex")
75 AddAccountType ("none");
76 AddAccountType ("imap");
79 protected override Indexable
MessageToIndexable (Message message
)
81 Uri uri
= new Uri (String
.Format ("email:///{0};id={1}", message
.Path
, message
.Id
));
83 Indexable indexable
= new Indexable (uri
);
84 indexable
.Type
= "MailMessage";
86 indexable
.AddProperty (Property
.New ("fixme:client", "mozilla"));
88 indexable
.AddProperty (Property
.NewKeyword ("dc:title", message
.Subject
));
90 indexable
.AddProperty (Property
.NewKeyword ("fixme:subject", message
.Subject
));
91 indexable
.AddProperty (Property
.NewKeyword ("fixme:to", message
.To
));
92 indexable
.AddProperty (Property
.NewKeyword ("fixme:from", message
.From
));
94 indexable
.AddProperty (Property
.New ("fixme:offset", message
.Offset
));
96 StringReader reader
= new StringReader (message
.Body
);
97 indexable
.SetTextReader (reader
);
103 [QueryableFlavor (Name
="Feed", Domain
=QueryDomain
.Local
)]
104 public class MozillaFeedQueryable
: MozillaQueryable
106 public MozillaFeedQueryable () : base ("MozillaFeedIndex")
108 AddAccountType ("rss");
111 protected override Indexable
MessageToIndexable (Message message
)
113 Uri uri
= new Uri (String
.Format ("feed:///{0};id={1}", message
.Path
, message
.Id
));
115 Indexable indexable
= new Indexable (uri
);
116 indexable
.MimeType
= "text/html";
117 indexable
.Type
= "FeedItem";
119 indexable
.AddProperty (Property
.New ("fixme:client", "mozilla"));
121 indexable
.AddProperty(Property
.NewKeyword ("dc:title", message
.Subject
));
122 indexable
.AddProperty(Property
.NewKeyword ("fixme:author", message
.From
));
123 //indexable.AddProperty(Property.NewDate ("fixme:published", item.PubDate));
124 indexable
.AddProperty(Property
.NewKeyword ("fixme:itemuri", message
.Headers
["Content-Base"]));
126 indexable
.AddProperty (Property
.New ("fixme:offset", message
.Offset
));
128 StringReader reader
= new StringReader (message
.Body
);
129 indexable
.SetTextReader (reader
);
135 public abstract class MozillaQueryable
: LuceneQueryable
{
137 public static Logger log
= Logger
.Get ("mozilla");
139 private MozillaCrawler crawler
;
141 private ArrayList accountTypes
= new ArrayList ();
143 public MozillaQueryable (string indexname
) : base (indexname
)
148 protected void AddAccountType (string str
)
150 accountTypes
.Add (str
);
153 private void StartWorker ()
155 Stopwatch stopwatch
= new Stopwatch ();
158 Shutdown
.ShutdownEvent
+= OnShutdown
;
160 this.crawler
= new MozillaCrawler (this, this.Driver
.Fingerprint
);
162 foreach (Profile profile
in Profile
.ReadProfiles ()) {
163 foreach (Account account
in profile
.Accounts
) {
164 if (!accountTypes
.Contains (account
.Type
))
167 this.crawler
.ScheduleCrawl (new DirectoryInfo (account
.Path
), -1);
169 FileSystemWatcher fsw
= new FileSystemWatcher ();
170 fsw
.Path
= account
.Path
;
171 fsw
.IncludeSubdirectories
= true;
173 fsw
.Changed
+= new FileSystemEventHandler (OnChanged
);
174 fsw
.Created
+= new FileSystemEventHandler (OnChanged
);
175 fsw
.Deleted
+= new FileSystemEventHandler (OnChanged
);
177 fsw
.EnableRaisingEvents
= true;
181 Shutdown
.ShutdownEvent
+= OnShutdown
;
183 this.crawler
.StopWhenEmpty ();
186 Logger
.Log
.Info ("MozillaQueryable worker thread done in {0}",
190 private void OnChanged (object source
, FileSystemEventArgs args
)
192 switch (args
.ChangeType
) {
193 case WatcherChangeTypes
.Changed
:
194 case WatcherChangeTypes
.Created
:
195 if (File
.Exists (args
.FullPath
+ ".msf"))
196 Index (new FileInfo (args
.FullPath
));
198 case WatcherChangeTypes
.Deleted
:
204 public override void Start ()
208 ExceptionHandlingThread
.Start (new ThreadStart (StartWorker
));
211 private void OnShutdown ()
213 this.crawler
.Stop ();
217 get { return "EvolutionMail"; }
220 public void Index (FileInfo file
)
222 Scheduler
.TaskGroup
group = NewMarkingTaskGroup (file
.FullName
, file
.LastWriteTime
);
224 MessageReader reader
= new MessageReader (file
.FullName
);
226 while (reader
.HasMoreMessages
) {
227 Message message
= reader
.NextMessage
;
228 Indexable indexable
= MessageToIndexable (message
);
230 Scheduler
.Task task
= NewAddTask (indexable
);
231 task
.Priority
= Scheduler
.Priority
.Delayed
;
232 task
.SubPriority
= 0;
233 task
.AddTaskGroup (group);
234 ThisScheduler
.Add (task
);
239 protected abstract Indexable
MessageToIndexable (Message message
);