4 // Copyright (C) 2004-2005 Novell, Inc.
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 using System
.Collections
;
30 using System
.Globalization
;
31 using System
.Reflection
;
32 using System
.Threading
;
34 using System
.Text
.RegularExpressions
;
45 static Query query
= null;
46 static DateTime queryStartTime
;
47 static DateTime lastQueryTime
= DateTime
.Now
;
50 static bool keep_running
= false;
51 static bool verbose
= false;
52 static bool display_hits
= true;
53 static bool flood
= false;
54 static bool listener
= false;
55 static DateTime start_date
= DateTime
.MinValue
;
56 static DateTime end_date
= DateTime
.MinValue
;
58 static void OnHitsAdded (HitsAddedResponse response
)
60 lastQueryTime
= DateTime
.Now
;
62 if (count
== 0 && verbose
) {
63 Console
.WriteLine ("First hit returned in {0:0.000}s",
64 (lastQueryTime
- queryStartTime
).TotalSeconds
);
68 count
+= response
.Hits
.Count
;
72 foreach (Hit hit
in response
.Hits
) {
74 Console
.WriteLine (" Uri: {0}", hit
.Uri
);
76 Console
.WriteLine (hit
.Uri
);
79 SnippetRequest sreq
= new SnippetRequest (query
, hit
);
80 SnippetResponse sresp
= (SnippetResponse
) sreq
.Send ();
81 Console
.WriteLine ("PaUri: {0}", hit
.ParentUri
!= null ? hit
.ParentUri
.ToString () : "(null)");
82 Console
.WriteLine (" Snip: {0}", sresp
.Snippet
!= null ? sresp
.Snippet
: "(null)");
83 Console
.WriteLine (" Type: {0}", hit
.Type
);
84 Console
.WriteLine ("MimeT: {0}", hit
.MimeType
== null ? "(null)" : hit
.MimeType
);
85 Console
.WriteLine (" Src: {0}", hit
.Source
);
86 Console
.WriteLine ("Score: {0}", hit
.Score
);
87 if (hit
.ValidTimestamp
)
88 Console
.WriteLine (" Time: {0}", hit
.Timestamp
.ToLocalTime ());
90 foreach (Property prop
in hit
.Properties
)
91 Console
.WriteLine (" {0} = '{1}'", prop
.Key
, prop
.Value
);
100 static void OnHitsSubtracted (HitsSubtractedResponse response
)
102 lastQueryTime
= DateTime
.Now
;
107 foreach (Uri uri
in response
.Uris
) {
108 Console
.WriteLine ("Subtracted Uri '{0}'", uri
);
109 Console
.WriteLine ();
115 static void OnFinished (FinishedResponse response
)
118 Console
.WriteLine ("Elapsed time: {0:0.000}s",
119 (DateTime
.Now
- queryStartTime
).TotalSeconds
);
120 Console
.WriteLine ("Total hits: {0}", count
);
126 Gtk
.Application
.Quit ();
129 public static void PrintUsageAndExit ()
132 "beagle-query: Command-line interface to the Beagle search system.\n" +
133 "Web page: http://www.gnome.org/projects/beagle\n" +
134 "Copyright (C) 2004 Novell, Inc.\n\n";
136 "Usage: beagle-query [OPTIONS] <query string>\n\n" +
138 " --verbose\t\t\tPrint detailed information about each hit.\n" +
139 " --mime <mime type>\t\tConstrain search results to the specified mime\n" +
140 " \t\ttype. Can be used multiply.\n" +
141 " --type <hit type>\t\tConstrain search results to the specified hit\n" +
142 " \t\ttype. Can be used multiply.\n" +
143 " --source <source>\t\tConstrain query to the specified source.\n" +
144 " \t\tSources list available from beagle-status.\n" +
145 " --start <date>\t\tConstrain query to items after specified date.\n" +
146 " \t\tDate must be in the form \"yyyyMMdd\" or \"yyyyMMddHHmmss\"\n" +
147 " --end <date>\t\t\tConstrain query to items before specified date.\n" +
148 " \t\t\tDate must be in the form \"yyyyMMdd\" or \"yyyyMMddHHmmss\"\n" +
149 " --keywords\t\t\tLists the keywords allowed in 'query string'.\n" +
150 " \t\t\tKeyword queries can be specified as keywordname:value e.g. ext:jpg\n" +
151 " --live-query\t\t\tRun continuously, printing notifications if a\n" +
152 " \t\t\tquery changes.\n" +
153 " --stats-only\t\t\tOnly display statistics about the query, not\n" +
154 " \t\t\tthe actual results.\n" +
155 " --max-hits\t\t\tLimit number of search results per backend\n" +
156 " \t\t\t(default = 100, max = 100)\n" +
157 " --flood\t\t\tExecute the query over and over again. Don't do that.\n" +
158 " --listener\t\t\tExecute an index listener query. Don't do that either.\n" +
159 " --help\t\t\tPrint this usage message.\n";
161 Console
.WriteLine (usage
);
163 System
.Environment
.Exit (0);
166 static void ReadBackendMappings ()
168 ArrayList assemblies
= ReflectionFu
.ScanEnvironmentForAssemblies ("BEAGLE_BACKEND_PATH", PathFinder
.BackendDir
);
170 // Add BeagleDaemonLib if it hasn't already been added.
171 bool found_daemon_lib
= false;
172 foreach (Assembly assembly
in assemblies
) {
173 if (assembly
.GetName ().Name
== "BeagleDaemonLib") {
174 found_daemon_lib
= true;
179 if (!found_daemon_lib
) {
181 assemblies
.Add (Assembly
.LoadFrom (Path
.Combine (PathFinder
.PkgLibDir
, "BeagleDaemonLib.dll")));
182 } catch (FileNotFoundException
) {
183 Console
.WriteLine ("WARNING: Could not find backend list.");
184 Environment
.Exit (1);
188 foreach (Assembly assembly
in assemblies
) {
189 foreach (Type type
in ReflectionFu
.ScanAssemblyForInterface (assembly
, typeof (Beagle
.Daemon
.IQueryable
))) {
190 object[] attributes
= type
.GetCustomAttributes (false);
191 foreach (object attribute
in attributes
) {
192 PropertyKeywordMapping mapping
= attribute
as PropertyKeywordMapping
;
195 //Logger.Log.Debug (mapping.Keyword + " => "
196 // + mapping.PropertyName +
197 // + " is-keyword=" + mapping.IsKeyword + " ("
198 // + mapping.Description + ") "
199 // + "(" + type.FullName + ")");
200 PropertyKeywordFu
.RegisterMapping (mapping
);
206 static void OnClosed ()
211 Gtk
.Application
.Quit ();
214 static int query_counter
= 0;
215 static void SendQuery ()
219 if (query_counter
> 1)
220 Console
.WriteLine ();
221 Console
.WriteLine ("Sending query #{0}", query_counter
);
224 queryStartTime
= DateTime
.Now
;
227 } catch (Exception ex
) {
228 Console
.WriteLine ("Could not connect to the Beagle daemon. The daemon probably isn't running.");
229 Console
.WriteLine (ex
);
230 System
.Environment
.Exit (-1);
234 static void Main (string[] args
)
236 Gtk
.Application
.InitCheck ("beagle-query", ref args
);
238 if (args
.Length
== 0 || Array
.IndexOf (args
, "--help") > -1 || Array
.IndexOf (args
, "--usage") > -1)
239 PrintUsageAndExit ();
241 StringBuilder query_str
= new StringBuilder ();
248 query
= new Query ();
252 while (i
< args
.Length
) {
256 if (++i
>= args
.Length
) PrintUsageAndExit ();
257 query
.AddMimeType (args
[i
]);
260 if (++i
>= args
.Length
) PrintUsageAndExit ();
261 query
.AddHitType (args
[i
]);
264 if (++i
>= args
.Length
) PrintUsageAndExit ();
265 query
.AddSource (args
[i
]);
275 display_hits
= false;
278 if (++i
>= args
.Length
) PrintUsageAndExit ();
279 query
.MaxHits
= Int32
.Parse (args
[i
]);
289 if (++i
>= args
.Length
) PrintUsageAndExit ();
291 start_date
= DateTime
.ParseExact (args
[i
], formats
,
292 CultureInfo
.InvariantCulture
,
293 DateTimeStyles
.None
);
294 } catch (FormatException
) {
295 Console
.WriteLine ("Invalid start date");
296 System
.Environment
.Exit (-1);
298 start_date
= start_date
.ToUniversalTime ();
302 if (++i
>= args
.Length
) PrintUsageAndExit ();
304 end_date
= DateTime
.ParseExact (args
[i
], formats
,
305 CultureInfo
.InvariantCulture
,
306 DateTimeStyles
.None
);
307 } catch (FormatException
) {
308 Console
.WriteLine ("Invalid end date");
309 System
.Environment
.Exit (-1);
311 end_date
= end_date
.ToUniversalTime ();
315 ReadBackendMappings ();
316 QueryDriver
.ReadKeywordMappings ();
318 Console
.WriteLine ("Supported query keywords are:");
320 IDictionaryEnumerator property_keyword_enum
= PropertyKeywordFu
.MappingEnumerator
;
321 while (property_keyword_enum
.MoveNext ()) {
322 PropertyDetail prop
= property_keyword_enum
.Value
as PropertyDetail
;
323 if (prop
.Description
!= null)
324 Console
.WriteLine (" {0,-20} for {1}", property_keyword_enum
.Key
, prop
.Description
);
326 Console
.WriteLine (" {0,-20}", property_keyword_enum
.Key
);
329 System
.Environment
.Exit (0);
334 // We have to do some nastiness here to deal with shell quoting.
335 // See beagled/QueryStringParser.cs for an idea of how this works.
336 string Pattern
= "(?<pm>[+-]?) (?<key>\\w+:)? (?<expr>.*)";
337 Regex r
= new Regex (Pattern
, RegexOptions
.IgnorePatternWhitespace
);
338 Match m
= r
.Match (args
[i
]);
340 string quoted_query
= m
.Groups
["pm"].ToString () +
341 m
.Groups
["key"].ToString () +
342 "\"" + m
.Groups
["expr"].ToString () + "\"";
344 if (query_str
.Length
> 0)
345 query_str
.Append (' ');
346 query_str
.Append (quoted_query
);
357 query
.IsIndexListener
= true;
361 if (query_str
.Length
> 0)
362 query
.AddText (query_str
.ToString ());
364 if (start_date
!= DateTime
.MinValue
|| end_date
!= DateTime
.MinValue
) {
365 QueryPart_DateRange part
= new QueryPart_DateRange ();
367 if (start_date
!= DateTime
.MinValue
)
368 part
.StartDate
= start_date
;
370 if (end_date
!= DateTime
.MinValue
)
371 part
.EndDate
= end_date
;
373 query
.AddPart (part
);
377 query
.HitsAddedEvent
+= OnHitsAdded
;
378 query
.HitsSubtractedEvent
+= OnHitsSubtracted
;
382 query
.FinishedEvent
+= OnFinished
;
384 query
.ClosedEvent
+= OnClosed
;
388 Gtk
.Application
.Run ();