/tags/3.1.0/src/org/getopt/luke/Luke.java
Java | 4726 lines | 4239 code | 178 blank | 309 comment | 988 complexity | ed6ce736556028291fd87ef78bffcd8e MD5 | raw file
Large files files are truncated, but you can click here to view the full file
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17package org.getopt.luke; 18 19import java.awt.Color; 20import java.awt.Font; 21import java.awt.GraphicsEnvironment; 22import java.awt.Toolkit; 23import java.awt.datatransfer.Clipboard; 24import java.awt.datatransfer.ClipboardOwner; 25import java.awt.datatransfer.StringSelection; 26import java.awt.datatransfer.Transferable; 27import java.io.*; 28import java.lang.reflect.Constructor; 29import java.lang.reflect.Method; 30import java.text.DecimalFormat; 31import java.text.NumberFormat; 32import java.util.*; 33import java.util.Map.Entry; 34import java.util.zip.GZIPOutputStream; 35 36import javax.swing.JFileChooser; 37import javax.swing.UIManager; 38 39import org.apache.lucene.LucenePackage; 40import org.apache.lucene.analysis.*; 41import org.apache.lucene.analysis.payloads.PayloadHelper; 42import org.apache.lucene.analysis.standard.StandardAnalyzer; 43import org.apache.lucene.document.DateTools; 44import org.apache.lucene.document.Document; 45import org.apache.lucene.document.Field; 46import org.apache.lucene.document.NumberTools; 47import org.apache.lucene.document.Field.Index; 48import org.apache.lucene.document.Field.Store; 49import org.apache.lucene.index.*; 50import org.apache.lucene.index.IndexReader.FieldOption; 51import org.apache.lucene.index.IndexWriter.MaxFieldLength; 52import org.apache.lucene.misc.SweetSpotSimilarity; 53import org.apache.lucene.queryParser.QueryParser; 54import org.apache.lucene.search.*; 55import org.apache.lucene.search.BooleanClause.Occur; 56import org.apache.lucene.search.payloads.PayloadNearQuery; 57import org.apache.lucene.search.payloads.PayloadTermQuery; 58import org.apache.lucene.search.similar.MoreLikeThis; 59import org.apache.lucene.search.spans.SpanFirstQuery; 60import org.apache.lucene.search.spans.SpanNearQuery; 61import org.apache.lucene.search.spans.SpanNotQuery; 62import org.apache.lucene.search.spans.SpanOrQuery; 63import org.apache.lucene.search.spans.SpanQuery; 64import org.apache.lucene.search.spans.SpanTermQuery; 65import org.apache.lucene.search.spans.Spans; 66import org.apache.lucene.store.*; 67import org.apache.lucene.util.NumericUtils; 68import org.apache.lucene.util.Version; 69import org.apache.lucene.xmlparser.CoreParser; 70import org.apache.lucene.xmlparser.CorePlusExtensionsParser; 71import org.getopt.luke.DocReconstructor.Reconstructed; 72import org.getopt.luke.decoders.BinaryDecoder; 73import org.getopt.luke.decoders.DateDecoder; 74import org.getopt.luke.decoders.Decoder; 75import org.getopt.luke.decoders.NumDoubleDecoder; 76import org.getopt.luke.decoders.NumFloatDecoder; 77import org.getopt.luke.decoders.NumIntDecoder; 78import org.getopt.luke.decoders.NumLongDecoder; 79import org.getopt.luke.decoders.OldDateFieldDecoder; 80import org.getopt.luke.decoders.OldNumberToolsDecoder; 81import org.getopt.luke.decoders.StringDecoder; 82import org.getopt.luke.plugins.ScriptingPlugin; 83import org.getopt.luke.xmlQuery.XmlQueryParserFactory; 84import org.getopt.luke.xmlQuery.CorePlusExtensionsParserFactory; 85 86import thinlet.FrameLauncher; 87import thinlet.Thinlet; 88 89/** 90 * This class allows you to browse a <a href="jakarta.apache.org/lucene">Lucene 91 * </a> index in several ways - by document, by term, by query, and by most 92 * frequent terms. 93 * 94 * @author Andrzej Bialecki 95 * 96 */ 97public class Luke extends Thinlet implements ClipboardOwner { 98 99 private Directory dir = null; 100 String pName = null; 101 private IndexReader ir = null; 102 private IndexSearcher is = null; 103 private boolean slowAccess = false; 104 private Collection<String> fn = null; 105 private String[] idxFields = null; 106 private HashMap<String, FieldTermCount> termCounts = new HashMap<String, FieldTermCount>(); 107 private List<LukePlugin> plugins = new ArrayList<LukePlugin>(); 108 private Object errorDlg = null; 109 private Object infoDlg = null; 110 private Object statmsg = null; 111 private Object slowstatus = null; 112 private Object slowmsg = null; 113 private Analyzer stdAnalyzer = new StandardAnalyzer(Version.LUCENE_CURRENT); 114 private Analyzer analyzer = null; 115 //private QueryParser qp = null; 116 private boolean readOnly = false; 117 private boolean ram = false; 118 private boolean keepCommits = false; 119 private boolean multi = false; 120 private int tiiDiv = 1; 121 private IndexCommit currentCommit = null; 122 private Similarity similarity = null; 123 private Object lastST; 124 private HashMap<String, Decoder> decoders = new HashMap<String, Decoder>(); 125 private Decoder defDecoder = new StringDecoder(); 126 127 /** Default salmon theme. */ 128 public static final int THEME_DEFAULT = 0; 129 /** Gray theme. */ 130 public static final int THEME_GRAY = 1; 131 /** Sandstone theme. */ 132 public static final int THEME_SANDSTONE = 2; 133 /** Sky blue theme. */ 134 public static final int THEME_SKY = 3; 135 /** Navy blue reverse theme. */ 136 public static final int THEME_NAVY = 4; 137 138 /** Theme color contants. */ 139 public int[][] themes = { 140 {0xece9d0, 0x000000, 0xf5f4f0, 0x919b9a, 0xb0b0b0, 0xeeeeee, 0xb9b9b9, 0xff8080, 0xc5c5dd}, // default 141 {0xe6e6e6, 0x000000, 0xffffff, 0x909090, 0xb0b0b0, 0xededed, 0xb9b9b9, 0x89899a, 0xc5c5dd}, // gray 142 {0xeeeecc, 0x000000, 0xffffff, 0x999966, 0xb0b096, 0xededcb, 0xcccc99, 0xcc6600, 0xffcc66}, // sandstone 143 {0xf0f0ff, 0x0000a0, 0xffffff, 0x8080ff, 0xb0b0b0, 0xededed, 0xb0b0ff, 0xff0000, 0xfde0e0}, // sky 144 {0x6375d6, 0xffffff, 0x7f8fdd, 0xd6dff5, 0x9caae5, 0x666666, 0x003399, 0xff3333, 0x666666} // navy 145 }; 146 147 private int numTerms = 0; 148 private static boolean exitOnDestroy = false; 149 private Class[] analyzers = null; 150 151 private String baseDir = null; 152 153 private Class[] defaultAnalyzers = { SimpleAnalyzer.class, StandardAnalyzer.class, StopAnalyzer.class, 154 WhitespaceAnalyzer.class }; 155 156 private static final String MSG_NOINDEX = "FAILED: No index, or index is closed. Reopen it."; 157 private static final String MSG_READONLY = "FAILED: Read-Only index."; 158 private static final String MSG_CONV_ERROR = "Some values could not be properly represented in this format. " + 159 "They are marked in grey and presented as a hex dump."; 160 161 /** Default constructor, loads preferences, initializes plugins and GUI. */ 162 public Luke() { 163 super(); 164 Prefs.load(); 165 try { 166 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 167 } catch (Exception e) {} 168 setTheme(Prefs.getInteger(Prefs.P_THEME, THEME_DEFAULT)); 169 String fontName = Prefs.getProperty(Prefs.P_FONT_NAME, "SansSerif"); 170 String fontSize = Prefs.getProperty(Prefs.P_FONT_SIZE, "12.0"); 171 float fsize = 12.0f; 172 try { 173 fsize = Float.parseFloat(fontSize); 174 } catch (Exception e) {}; 175 Font f = new Font(fontName, Font.PLAIN, (int)fsize); 176 setFont(f); 177 addComponent(this, "/xml/luke.xml", null, null); 178 errorDlg = addComponent(null, "/xml/error.xml", null, null); 179 infoDlg = addComponent(null, "/xml/info.xml", null, null); 180 statmsg = find("statmsg"); 181 slowstatus = find("slowstat"); 182 slowmsg = find(slowstatus, "slowmsg"); 183 // populate analyzers 184 try { 185 Class[] an = ClassFinder.getInstantiableSubclasses(Analyzer.class); 186 if (an == null || an.length == 0) { 187 analyzers = defaultAnalyzers; 188 } else { 189 HashSet<Class> uniq = new HashSet<Class>(Arrays.asList(an)); 190 analyzers = (Class[])uniq.toArray(new Class[uniq.size()]); 191 } 192 Object cbType = find("cbType"); 193 populateAnalyzers(cbType); 194 } catch (Exception e) { 195 e.printStackTrace(); 196 } 197 loadPlugins(); 198 199 } 200 201 /** 202 * Set color theme for the UI. 203 * @param which one of the predefined themes. For custom themes use {@link Thinlet#setColors(int, int, int, int, int, int, int, int, int)}. 204 */ 205 public void setTheme(int which) { 206 if (which < 0 || which >= themes.length) which = THEME_DEFAULT; 207 int[] t = themes[which]; 208 setColors(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8]); 209 Prefs.setProperty(Prefs.P_THEME, which + ""); 210 } 211 212 /** 213 * Action handler to select color theme. 214 * @param menu 215 */ 216 public void actionTheme(Object menu) { 217 String which = (String)getProperty(menu, "t"); 218 int t = THEME_DEFAULT; 219 try { 220 t = Integer.parseInt(which); 221 } catch (Exception e) {}; 222 setTheme(t); 223 } 224 225 /** 226 * Populate a combobox with the current list of analyzers. 227 * @param combo 228 */ 229 public void populateAnalyzers(Object combo) { 230 removeAll(combo); 231 String[] aNames = new String[analyzers.length]; 232 for (int i = 0; i < analyzers.length; i++) { 233 aNames[i] = analyzers[i].getName(); 234 } 235 Arrays.sort(aNames); 236 for (int i = 0; i < aNames.length; i++) { 237 Object choice = create("choice"); 238 setString(choice, "text", aNames[i]); 239 add(combo, choice); 240 if (i == 0) { 241 setString(combo, "text", aNames[i]); 242 } 243 } 244 int lastAnalyzerIdx = 0; 245 String lastAnalyzer = Prefs.getProperty(Prefs.P_ANALYZER); 246 if (lastAnalyzer != null) lastAnalyzerIdx = getIndex(combo, lastAnalyzer); 247 if (lastAnalyzerIdx < 0) lastAnalyzerIdx = 0; 248 setInteger(combo, "selected", lastAnalyzerIdx); 249 } 250 251 /** 252 * Return an array of available Analyzer implementations. 253 * @return 254 */ 255 public Class[] getAnalyzers() { 256 return analyzers; 257 } 258 259 /** 260 * Loads plugins. Plugins are first searched from the CLASSPATH, and then from a 261 * plugin list contained in a resource file "/.plugins". The "/.plugins" resource file 262 * has a simple format - one fully qualified class name per line. Blank lines and 263 * lines starting with '#' are ignored. 264 */ 265 private void loadPlugins() { 266 List pluginClasses = new ArrayList(); 267 // try to find all plugins 268 try { 269 Class classes[] = ClassFinder.getInstantiableSubclasses(LukePlugin.class); 270 if (classes != null && classes.length > 0) { 271 pluginClasses.addAll(Arrays.asList(classes)); 272 } 273 } catch (Exception e) { 274 e.printStackTrace(); 275 } 276 // load plugins declared in the ".plugins" file 277 try { 278 InputStream is = getClass().getResourceAsStream("/.plugins"); 279 if (is != null) { 280 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 281 String line = null; 282 while ((line = br.readLine()) != null) { 283 if (line.startsWith("#")) continue; 284 if (line.trim().equals("")) continue; 285 try { 286 Class clazz = Class.forName(line.trim()); 287 if (clazz.getSuperclass().equals(LukePlugin.class) && !pluginClasses.contains(clazz)) { 288 pluginClasses.add(clazz); 289 } 290 } catch (Throwable x) { 291 // 292 } 293 } 294 } 295 } catch (Exception e) { 296 e.printStackTrace(); 297 } 298 try { 299 StringBuffer errors = new StringBuffer("Unable to load some plugins:"); 300 boolean failures = false; 301 for (int i = 0; i < pluginClasses.size(); i++) { 302 try { 303 LukePlugin plugin = (LukePlugin) ((Class) pluginClasses.get(i)).getConstructor(new Class[0]).newInstance( 304 new Object[0]); 305 String xul = plugin.getXULName(); 306 if (xul == null) continue; 307 Object ui = parse(xul, plugin); 308 plugin.setApplication(this); 309 plugin.setMyUi(ui); 310 plugins.add(plugin); 311 } catch (Exception e) { 312 failures = true; 313 e.printStackTrace(); 314 errors.append("\n" + pluginClasses.get(i).toString()); 315 } 316 } 317 if (failures) { 318 errorMsg(errors.toString()); 319 } 320 } catch (Exception e) { 321 e.printStackTrace(); 322 errorMsg(e.toString()); 323 } 324 if (plugins.size() == 0) return; 325 initPlugins(); 326 } 327 328 /** 329 * Create UI for a single plugin. 330 * @param tabs parent tabbedpane 331 * @param plugin plugin instance 332 */ 333 private void addPluginTab(Object tabs, LukePlugin plugin) { 334 Object tab = create("tab"); 335 setColor(tab, "foreground", new Color(0x006000)); 336 setString(tab, "text", plugin.getPluginName()); 337 setFont(tab, getFont().deriveFont(Font.BOLD)); 338 add(tabs, tab); 339 Object panel = create("panel"); 340 setInteger(panel, "gap", 2); 341 setInteger(panel, "weightx", 1); 342 setInteger(panel, "weighty", 1); 343 setChoice(panel, "halign", "fill"); 344 setChoice(panel, "valign", "fill"); 345 setInteger(panel, "columns", 1); 346 add(tab, panel); 347 Object infobar = create("panel"); 348 setInteger(infobar, "gap", 8); 349 setInteger(infobar, "top", 2); 350 setInteger(infobar, "bottom", 2); 351 setInteger(infobar, "weightx", 1); 352 setChoice(infobar, "halign", "fill"); 353 setColor(infobar, "background", new Color(0xc0f0c0)); 354 add(panel, infobar); 355 Object label = create("label"); 356 setString(label, "text", plugin.getPluginInfo()); 357 add(infobar, label); 358 Object link = create("button"); 359 setChoice(link, "type", "link"); 360 setString(link, "text", plugin.getPluginHome()); 361 putProperty(link, "url", plugin.getPluginHome()); 362 setMethod(link, "action", "goUrl(this)", infobar, this); 363 add(infobar, link); 364 add(panel, create("separator")); 365 add(panel, plugin.getMyUi()); 366 } 367 368 /** 369 * Return the list of active plugin instances. 370 * @return 371 */ 372 public List getPlugins() { 373 return Collections.unmodifiableList(plugins); 374 } 375 376 /** 377 * Get an already instantiated plugin, or null if such plugin was 378 * not loaded on startup. 379 * @param className fully qualified plugin classname 380 * @return 381 */ 382 public LukePlugin getPlugin(String className) { 383 for (int i = 0; i < plugins.size(); i++) { 384 Object plugin = plugins.get(i); 385 if (plugin.getClass().getName().equals(className)) 386 return (LukePlugin)plugin; 387 } 388 return null; 389 } 390 391 Thread statusThread = null; 392 long lastUpdate = 0; 393 long statusSleep = 0; 394 395 /** 396 * Display a message on the status bar for 5 seconds. 397 * @param msg message to display. Too long messages will be truncated by the UI. 398 */ 399 public void showStatus(final String msg) { 400 if (statusThread != null && statusThread.isAlive()) { 401 setString(statmsg, "text", msg); 402 statusSleep = 5000; 403 } else { 404 statusThread = new Thread() { 405 public void run() { 406 statusSleep = 5000; 407 setString(statmsg, "text", msg); 408 while (statusSleep > 0) { 409 try { 410 sleep(500); 411 } catch (Exception e) {}; 412 statusSleep -= 500; 413 } 414 setString(statmsg, "text", ""); 415 } 416 }; 417 statusThread.start(); 418 } 419 } 420 421 /** 422 * As {@link #showStatus(String)} but also sets the "Last search time" label. 423 * @param msg 424 */ 425 public void showSearchStatus(String msg) { 426 setString(lastST, "text", msg); 427 showStatus(msg); 428 } 429 430 long lastSlowUpdate = 0L; 431 long lastSlowCounter = 0L; 432 Thread slowThread = null; 433 long slowSleep = 0; 434 435 public void showSlowStatus(final String msg, final long counter) { 436 if (slowThread != null && slowThread.isAlive()) { 437 lastSlowCounter += counter; 438 setString(slowmsg, "text", msg + " " + lastSlowCounter); 439 slowSleep = 5000; 440 } else { 441 slowThread = new Thread() { 442 public void run() { 443 slowSleep = 5000; 444 lastSlowCounter = counter; 445 setBoolean(slowstatus, "visible", true); 446 setString(slowmsg, "text", msg + " " + lastSlowCounter); 447 while (slowSleep > 0) { 448 try { 449 sleep(500); 450 } catch (Exception e) {}; 451 slowSleep -= 500; 452 } 453 setString(slowmsg, "text", ""); 454 setBoolean(slowstatus, "visible", false); 455 } 456 }; 457 slowThread.start(); 458 } 459 } 460 461 /** 462 * Add a Thinlet component from XUL file. 463 * @param parent add the new component to this parent 464 * @param compView path to the XUL resource 465 * @param handlerStr fully qualified classname of the handler to instantiate, 466 * or null if the current class will become the handler 467 * @param argv if not null, these arguments will be passed to the 468 * appropriate constructor. 469 * @return 470 */ 471 public Object addComponent(Object parent, String compView, String handlerStr, Object[] argv) { 472 Object res = null; 473 Object handler = null; 474 try { 475 if (handlerStr != null) { 476 if (argv == null) { 477 handler = Class.forName(handlerStr).getConstructor(new Class[] { Thinlet.class }).newInstance( 478 new Object[] { this }); 479 } else { 480 handler = Class.forName(handlerStr).getConstructor(new Class[] { Thinlet.class, Object[].class }) 481 .newInstance(new Object[] { this, argv }); 482 } 483 } 484 if (handler != null) { 485 res = parse(compView, handler); 486 } else res = parse(compView); 487 if (parent != null) { 488 if (parent instanceof Thinlet) 489 add(res); 490 else add(parent, res); 491 } 492 return res; 493 } catch (Exception exc) { 494 exc.printStackTrace(); 495 errorMsg(exc.getMessage()); 496 return null; 497 } 498 } 499 500 /** 501 * Show a modal error dialog with OK button. 502 * @param msg error message 503 */ 504 public void errorMsg(String msg) { 505 Object fMsg = find(errorDlg, "msg"); 506 setString(fMsg, "text", msg); 507 add(errorDlg); 508 } 509 510 /** 511 * Show a modal info dialog with OK button. 512 * @param msg info message 513 */ 514 public void infoMsg(String msg) { 515 Object fMsg = find(infoDlg, "msg"); 516 setString(fMsg, "text", msg); 517 add(infoDlg); 518 } 519 520 /** 521 * Show an "Open Index" dialog. 522 * 523 */ 524 public void actionOpen() { 525 Object dialog = addComponent(this, "/xml/lukeinit.xml", null, null); 526 Object path = find(dialog, "path"); 527 if (this.baseDir != null) 528 setString(path, "text", this.baseDir); 529 else setString(path, "text", System.getProperty("user.dir")); 530 } 531 532 /** 533 * Browse for a directory, and put the selection result in the 534 * indicated widget. 535 * @param path Thinlet widget to put the result 536 */ 537 public void openBrowse(Object path) { 538 JFileChooser fd = new JFileChooser(); 539 fd.setDialogType(JFileChooser.OPEN_DIALOG); 540 fd.setDialogTitle("Select Index directory"); 541 fd.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 542 fd.setFileHidingEnabled(false); 543 String strPath = getString(path, "text"); 544 if (strPath != null) strPath.trim(); 545 if (strPath != null && strPath.length() > 0) 546 fd.setCurrentDirectory(new File(strPath)); 547 else if (this.baseDir != null) 548 fd.setCurrentDirectory(new File(this.baseDir)); 549 else fd.setCurrentDirectory(new File(System.getProperty("user.dir"))); 550 int res = fd.showOpenDialog(this); 551 File iDir = null; 552 if (res == JFileChooser.APPROVE_OPTION) iDir = fd.getSelectedFile(); 553 if (iDir != null && iDir.exists()) { 554 if (!iDir.isDirectory()) iDir = iDir.getParentFile(); 555 setString(path, "text", iDir.toString()); 556 } 557 } 558 559 560 /** 561 * Select an output file name, and put the selection result in the 562 * indicated widget. 563 * @param path Thinlet widget to put the result 564 */ 565 public void saveBrowse(Object path, Object startButton) { 566 JFileChooser fd = new JFileChooser(); 567 fd.setDialogType(JFileChooser.SAVE_DIALOG); 568 fd.setDialogTitle("Select Output File"); 569 fd.setFileSelectionMode(JFileChooser.FILES_ONLY); 570 fd.setFileHidingEnabled(false); 571 String strPath = getString(path, "text"); 572 if (strPath != null) strPath.trim(); 573 if (strPath != null && strPath.length() > 0) 574 fd.setCurrentDirectory(new File(strPath)); 575 else if (this.baseDir != null) 576 fd.setCurrentDirectory(new File(this.baseDir)); 577 else fd.setCurrentDirectory(new File(System.getProperty("user.dir"))); 578 int res = fd.showSaveDialog(this); 579 setBoolean(startButton, "enabled", false); 580 File iFile = null; 581 if (res == JFileChooser.APPROVE_OPTION) iFile = fd.getSelectedFile(); 582 if (iFile != null) { 583 setString(path, "text", iFile.toString()); 584 setBoolean(startButton, "enabled", true); 585 } 586 } 587 588 589 /** 590 * Initialize MRU list of indexes in the open index dialog. 591 * @param dialog 592 */ 593 public void setupInit(Object dialog) { 594 Object path = find(dialog, "path"); 595 syncMRU(path); 596 } 597 598 /** 599 * Attempt to load the index with parameters specified in the dialog. 600 * <p>NOTE: this method is invoked from the UI. If you need to open an index 601 * programmatically, you should use {@link #openIndex(String, boolean, boolean, boolean)} instead.</p> 602 * @param dialog UI dialog with parameters 603 */ 604 public void openOk(Object dialog) { 605 Object path = find(dialog, "path"); 606 pName = getString(path, "text").trim(); 607 608 boolean force = getBoolean(find(dialog, "force"), "selected"); 609 boolean noReader = getBoolean(find(dialog, "cbNoReader"), "selected"); 610 tiiDiv = 1; 611 try { 612 tiiDiv = Integer.parseInt(getString(find(dialog, "tiiDiv"), "text")); 613 } catch (Exception e) { 614 e.printStackTrace(); 615 } 616 Object dirImpl = getSelectedItem(find(dialog, "dirImpl")); 617 String dirClass = null; 618 if (dirImpl == null) { 619 dirClass = FSDirectory.class.getName(); 620 } else { 621 String name = getString(dirImpl, "name"); 622 if (name == null) { 623 dirClass = getString(dirImpl, "text"); 624 } else { 625 if (name.equals("fs")) { 626 dirClass = FSDirectory.class.getName(); 627 } else if (name.equals("mmap")) { 628 dirClass = MMapDirectory.class.getName(); 629 } else if (name.equals("niofs")) { 630 dirClass = NIOFSDirectory.class.getName(); 631 } 632 } 633 } 634 if (pName == null || pName.trim().equals("")) { 635 errorMsg("Invalid path."); 636 return; 637 } 638 readOnly = getBoolean(find(dialog, "ro"), "selected"); 639 ram = getBoolean(find(dialog, "ram"), "selected"); 640 keepCommits = getBoolean(find(dialog, "cbKeepCommits"), "selected"); 641 slowAccess = getBoolean(find(dialog, "cbSlowIO"), "selected"); 642 decoders.clear(); 643 currentCommit = null; 644 Prefs.addToMruList(pName); 645 syncMRU(path); 646 remove(dialog); 647 if (noReader) { 648 removeAll(); 649 addComponent(this, "/xml/luke.xml", null, null); 650 try { 651 Directory d = openDirectory(dirClass, pName, false); 652 if (IndexReader.indexExists(d)) { 653 throw new Exception("there is no valid Lucene index in this directory."); 654 } 655 dir = d; 656 initOverview(); 657 infoMsg("There is no IndexReader - most actions are disabled. " + 658 "You can open IndexReader from current Directory using 'Re-Open'"); 659 } catch (Exception e) { 660 errorMsg("ERROR: " + e.toString()); 661 } 662 } else { 663 openIndex(pName, force, dirClass, readOnly, ram, keepCommits, null, tiiDiv); 664 } 665 } 666 667 public void actionClose() { 668 if (ir != null) { 669 try { 670 if (is != null) is.close(); 671 ir.close(); 672 if (dir != null) dir.close(); 673 } catch (Exception e) { 674 e.printStackTrace(); 675 errorMsg("Close failed: " + e.getMessage()); 676 } 677 } 678 ir = null; 679 dir = null; 680 is = null; 681 removeAll(); 682 addComponent(this, "/xml/luke.xml", null, null); 683 initPlugins(); 684 } 685 686 public void actionCommit() { 687 if (ir == null) { 688 showStatus(MSG_NOINDEX); 689 return; 690 } 691 if (readOnly) { 692 showStatus(MSG_READONLY); 693 return; 694 } 695 if (!IndexGate.hasChanges(ir)) { 696 showStatus("No changes - commit ignored."); 697 return; 698 } 699 Object dialog = addComponent(this, "/xml/commit.xml", null, null); 700 Map userData = ir.getCommitUserData(); 701 TreeMap ud = new TreeMap(userData); 702 putProperty(dialog, "userData", ud); 703 _showUserData(dialog); 704 } 705 706 private void _showUserData(Object dialog) { 707 Object table = find(dialog, "data"); 708 removeAll(table); 709 Map<Object,Object> ud = (Map)getProperty(dialog, "userData"); 710 for (Entry e : ud.entrySet()) { 711 Object row = create("row"); 712 putProperty(row, "key", e.getKey()); 713 add(table, row); 714 Object cell = create("cell"); 715 setString(cell, "text", e.getKey().toString()); 716 add(row, cell); 717 cell = create("cell"); 718 setString(cell, "text", e.getValue().toString()); 719 add(row, cell); 720 } 721 } 722 723 public void putUserData(Object dialog) { 724 Object key = find(dialog, "key"); 725 Object value = find(dialog, "value"); 726 String k = getString(key, "text"); 727 String v = getString(value, "text"); 728 if (k.equals("")) { 729 showStatus("Cannot add empty key."); 730 return; 731 } 732 Map<Object,Object> ud = (Map)getProperty(dialog, "userData"); 733 ud.put(k, v); 734 _showUserData(dialog); 735 } 736 737 public void deleteUserData(Object dialog) { 738 Object table = find(dialog, "data"); 739 Map ud = (Map)getProperty(dialog, "userData"); 740 Object[] rows = getSelectedItems(table); 741 if (rows == null || rows.length == 0) { 742 return; 743 } 744 for (Object row : rows) { 745 Object key = getProperty(row, "key"); 746 ud.remove(key); 747 } 748 _showUserData(dialog); 749 } 750 751 public void commitUserData(Object dialog) { 752 Map userData = (Map)getProperty(dialog, "userData"); 753 remove(dialog); 754 try { 755 ir.flush(userData); 756 initOverview(); 757 showFiles(dir, Collections.EMPTY_LIST); 758 } catch (Exception e) { 759 errorMsg("Error: " + e.toString()); 760 } 761 } 762 763 public void actionReopen() { 764 if (dir == null) { 765 return; 766 } 767 openIndex(pName, false, dir.getClass().getName(), readOnly, ram, 768 keepCommits, currentCommit, tiiDiv); 769 } 770 /** 771 * Open indicated index and re-initialize all GUI and plugins. 772 * @param pName path to index 773 * @param force if true, and the index is locked, unlock it first. If false, and 774 * the index is locked, an error will be reported. 775 * @param readOnly open in read-only mode, and disallow modifications. 776 */ 777 public void openIndex(String name, boolean force, String dirImpl, boolean ro, 778 boolean ramdir, boolean keepCommits, IndexCommit point, int tiiDivisor) { 779 pName = name; 780 readOnly = ro; 781 removeAll(); 782 File baseFileDir = new File(name); 783 this.baseDir = baseFileDir.toString(); 784 addComponent(this, "/xml/luke.xml", null, null); 785 statmsg = find("statmsg"); 786 if (dir != null) { 787 try { 788 if (ir != null) ir.close(); 789 } catch (Exception e) {} 790 ; 791 try { 792 if (dir != null) dir.close(); 793 } catch (Exception e) {} 794 ; 795 } 796 ArrayList<Directory> dirs = new ArrayList<Directory>(); 797 try { 798 Directory d = openDirectory(dirImpl, pName, false); 799 if (IndexWriter.isLocked(d)) { 800 if (ro) { 801 errorMsg("Index is locked and Read-Only. Open for read-write and 'Force unlock'."); 802 d.close(); 803 d = null; 804 return; 805 } 806 if (force) { 807 IndexWriter.unlock(d); 808 } else { 809 errorMsg("Index is locked. Try 'Force unlock' when opening."); 810 d.close(); 811 d = null; 812 return; 813 } 814 } 815 boolean existsSingle = false; 816 try { 817 existsSingle = IndexReader.indexExists(d); 818 } catch (Exception e) { 819 // 820 } 821 822 if (!existsSingle) { // try multi 823 File[] files = baseFileDir.listFiles(); 824 for (File f : files) { 825 if (f.isFile()) { 826 continue; 827 } 828 Directory d1 = openDirectory(dirImpl, f.toString(), false); 829 if (IndexWriter.isLocked(d1)) { 830 if (ro) { 831 errorMsg("Index is locked and Read-Only. Open for read-write and 'Force unlock'."); 832 d1.close(); 833 d1 = null; 834 return; 835 } 836 if (force) { 837 IndexWriter.unlock(d1); 838 } else { 839 errorMsg("Index is locked. Try 'Force unlock' when opening."); 840 d1.close(); 841 d1 = null; 842 return; 843 } 844 } 845 existsSingle = false; 846 try { 847 existsSingle = IndexReader.indexExists(d1); 848 } catch (Exception e) {}; 849 if (!existsSingle) { 850 d1.close(); 851 continue; 852 } 853 dirs.add(d1); 854 } 855 } else { 856 dirs.add(d); 857 } 858 859 if (dirs.size() == 0) { 860 errorMsg("No valid directory at the location, try another location."); 861 return; 862 } 863 864 if (ramdir) { 865 showStatus("Loading index into RAMDirectory ..."); 866 Directory dir1 = new RAMDirectory(); 867 IndexWriter iw1 = new IndexWriter(dir1, new SimpleAnalyzer(), MaxFieldLength.UNLIMITED); 868 iw1.addIndexesNoOptimize((Directory[])dirs.toArray(new Directory[dirs.size()])); 869 iw1.close(); 870 showStatus("RAMDirectory loading done!"); 871 dir.close(); 872 dir = dir1; 873 } 874 IndexDeletionPolicy policy; 875 if (keepCommits) { 876 policy = new KeepAllIndexDeletionPolicy(); 877 } else { 878 policy = new KeepLastIndexDeletionPolicy(); 879 } 880 ArrayList<IndexReader> readers = new ArrayList<IndexReader>(); 881 for (Directory dd : dirs) { 882 IndexReader reader; 883 if (tiiDivisor > 1) { 884 reader = IndexReader.open(dd, policy, ro, tiiDivisor); 885 } else { 886 reader = IndexReader.open(dd, policy, ro); 887 } 888 readers.add(reader); 889 } 890 if (readers.size() == 1) { 891 ir = readers.get(0); 892 dir = ir.directory(); 893 } else { 894 ir = new MultiReader((IndexReader[])readers.toArray(new IndexReader[readers.size()])); 895 } 896 is = new IndexSearcher(ir); 897 // XXX 898 slowAccess = false; 899 initOverview(); 900 initPlugins(); 901 showStatus("Index successfully open."); 902 } catch (Exception e) { 903 e.printStackTrace(); 904 errorMsg(e.getMessage()); 905 return; 906 } 907 } 908 909 /** 910 * Open a single directory. 911 * @param dirImpl fully-qualified class name of Directory implementation, 912 * or "FSDirectory" for {@link FSDirectory} 913 * @param file index directory 914 * @param create if true, create a new directory 915 * @return directory implementation 916 */ 917 Class defaultDirImpl = null; 918 919 public Directory openDirectory(String dirImpl, String file, boolean create) throws Exception { 920 File f = new File(file); 921 if (!f.exists()) { 922 throw new Exception("Index directory doesn't exist."); 923 } 924 Directory res = null; 925 if (dirImpl == null || dirImpl.equals(FSDirectory.class.getName())) { 926 return FSDirectory.open(f); 927 } 928 try { 929 Class implClass = Class.forName(dirImpl); 930 Constructor<Directory> constr = implClass.getConstructor(File.class); 931 res = constr.newInstance(f); 932 } catch (Throwable e) { 933 errorMsg("Invalid directory implementation class: " + dirImpl + " " + e); 934 return null; 935 } 936 if (res != null) return res; 937 // fall-back to FSDirectory. 938 if (res == null) return FSDirectory.open(f); 939 return null; 940 } 941 942 /** 943 * Indicates whether I/O access should be optimized because 944 * the index is on a slow medium (e.g. remote). 945 * @return true if I/O access is costly and should be minimized 946 */ 947 public boolean isSlowAccess() { 948 return slowAccess; 949 } 950 951 /** 952 * Set whether the I/O access to this index is costly and 953 * should be minimized. 954 */ 955 public void setSlowAccess(boolean slowAccess) { 956 this.slowAccess = slowAccess; 957 if (slowAccess) { 958 959 } 960 } 961 962 /** 963 * Initialize plugins. This method should always be called when a new index is open. 964 * 965 */ 966 public void initPlugins() { 967 Object pluginsTabs = find("pluginsTabs"); 968 removeAll(pluginsTabs); 969 for (int i = 0; i < plugins.size(); i++) { 970 LukePlugin plugin = (LukePlugin) plugins.get(i); 971 addPluginTab(pluginsTabs, plugin); 972 plugin.setDirectory(dir); 973 plugin.setIndexReader(ir); 974 try { 975 plugin.init(); 976 } catch (Exception e) { 977 e.printStackTrace(); 978 showStatus("PLUGIN ERROR: " + e.getMessage()); 979 } 980 } 981 } 982 983 /** 984 * Initialize index overview and other GUI elements. This method is called always 985 * when a new index is open. 986 * 987 */ 988 private void initOverview() { 989 try { 990 courier = new Font("Courier", getFont().getStyle(), getFont().getSize()); 991 lastST = find("lastST"); 992 setBoolean(find("bReload"), "enabled", true); 993 setBoolean(find("bClose"), "enabled", true); 994 setBoolean(find("bCommit"), "enabled", true); 995 Object cbType = find("cbType"); 996 populateAnalyzers(cbType); 997 Object pOver = find("pOver"); 998 Object iName = find("idx"); 999 String idxName; 1000 if (pName.length() > 40) { 1001 idxName = pName.substring(0, 10) + "..." + pName.substring(pName.length() - 27); 1002 } else { 1003 idxName = pName; 1004 } 1005 setString(iName, "text", idxName + (readOnly ? " (R)" : "")); 1006 iName = find(pOver, "iName"); 1007 setString(iName, "text", pName + (readOnly ? " (Read-Only)" : "")); 1008 Object dirImpl = find("dirImpl"); 1009 String implName = "N/A"; 1010 if (dir == null) { 1011 if (ir != null) { 1012 implName = "N/A (reader is " + ir.getClass().getName() + ")"; 1013 } 1014 } else { 1015 implName = dir.getClass().getName(); 1016 } 1017 setString(dirImpl, "text", implName); 1018 Object fileSize = find("iFileSize"); 1019 long totalFileSize = Util.calcTotalFileSize(pName, dir); 1020 setString(fileSize, "text", Util.normalizeSize(totalFileSize) + Util.normalizeUnit(totalFileSize)); 1021 if (ir == null) { 1022 return; 1023 } 1024 // we need IndexReader from now on 1025 Object iMod = find(pOver, "iMod"); 1026 String modText = "N/A"; 1027 if (dir != null) { 1028 modText = new Date(IndexReader.lastModified(dir)).toString(); 1029 } 1030 setString(iMod, "text", modText); 1031 Object iDocs = find(pOver, "iDocs"); 1032 String numdocs = String.valueOf(ir.numDocs()); 1033 setString(iDocs, "text", numdocs); 1034 iDocs = find("iDocs1"); 1035 setString(iDocs, "text", String.valueOf(ir.maxDoc() - 1)); 1036 Object iFields = find(pOver, "iFields"); 1037 fn = ir.getFieldNames(IndexReader.FieldOption.ALL); 1038 if (fn.size() == 0) { 1039 showStatus("Empty index."); 1040 } 1041 showFiles(dir, null); 1042 showCommits(); 1043 final Object fList = find(pOver, "fList"); 1044 final Object defFld = find("defFld"); 1045 final Object fCombo = find("fCombo"); 1046 TreeSet<String> fields = new TreeSet<String>(fn); 1047 idxFields = (String[])fields.toArray(new String[fields.size()]); 1048 setString(iFields, "text", String.valueOf(idxFields.length)); 1049 final Object iTerms = find(pOver, "iTerms"); 1050 if (!slowAccess) { 1051 Thread t = new Thread() { 1052 public void run() { 1053 Object r = create("row"); 1054 Object cell = create("cell"); 1055 add(r, cell); 1056 add(fList, r); 1057 setBoolean(cell, "enabled", false); 1058 setString(cell, "text", "..wait.."); 1059 termCounts.clear(); 1060 FieldTermCount ftc = null; 1061 try { 1062 TermEnum te = ir.terms(); 1063 numTerms = 0; 1064 while (te.next()) { 1065 Term currTerm = te.term(); 1066 if (ftc == null) { 1067 // initialize 1068 ftc = new FieldTermCount(); 1069 ftc.fieldname = currTerm.field(); 1070 termCounts.put(ftc.fieldname, ftc); 1071 } 1072 if (ftc.fieldname == currTerm.field()) { 1073 ftc.termCount++; 1074 } else { 1075 ftc = new FieldTermCount(); 1076 ftc.fieldname = currTerm.field(); 1077 ftc.termCount++; 1078 termCounts.put(ftc.fieldname, ftc); 1079 } 1080 numTerms++; 1081 } 1082 te.close(); 1083 setString(iTerms, "text", String.valueOf(numTerms)); 1084 initFieldList(fList, fCombo, defFld); 1085 } catch (Exception e) { 1086 showStatus("ERROR: can't count terms per field"); 1087 } 1088 } 1089 }; 1090 t.start(); 1091 } else { 1092 setString(iTerms, "text", "N/A"); 1093 initFieldList(fList, fCombo, defFld); 1094 } 1095 Object iDel = find(pOver, "iDelOpt"); 1096 String sDel = ir.hasDeletions() ? "Yes (" + ir.numDeletedDocs() + ")" : "No"; 1097 String sDelOpt = sDel + " / " + 1098 (ir.isOptimized() ? "Yes" : "No"); 1099 setString(iDel, "text", sDelOpt); 1100 Object iVer = find(pOver, "iVer"); 1101 String verText = "N/A"; 1102 if (dir != null) { 1103 verText = Long.toHexString(IndexReader.getCurrentVersion(dir)); 1104 } 1105 setString(iVer, "text", verText); 1106 Object iFormat = find(pOver, "iFormat"); 1107 Object iCaps = find(pOver, "iCaps"); 1108 String formatText = "N/A"; 1109 String formatCaps = "N/A"; 1110 if (dir != null) { 1111 int format = IndexGate.getIndexFormat(dir); 1112 IndexGate.FormatDetails formatDetails = IndexGate.getFormatDetails(format); 1113 formatText = format + " (" + formatDetails.genericName + ")"; 1114 formatCaps = formatDetails.capabilities; 1115 } 1116 setString(iFormat, "text", formatText); 1117 setString(iCaps, "text", formatCaps); 1118 Object iTiiDiv = find(pOver, "iTiiDiv"); 1119 String divText = "N/A"; 1120 // not available in Lucene 3.0 1121// try { 1122// divText = String.valueOf(ir.getTermInfosIndexDivisor()); 1123// } catch (UnsupportedOperationException uoe) { 1124// } 1125 setString(iTiiDiv, "text", divText); 1126 Object iCommit = find(pOver, "iCommit"); 1127 String commitText = "N/A"; 1128 try { 1129 IndexCommit commit = ir.getIndexCommit(); 1130 commitText = commit.getSegmentsFileName() + " (" + 1131 new Date(commit.getTimestamp()).toString() + ")"; 1132 } catch (UnsupportedOperationException uoe) { 1133 } 1134 setString(iCommit, "text", commitText); 1135 Object iUser = find(pOver, "iUser"); 1136 String userData = null; 1137 try { 1138 Map userDataMap = ir.getCommitUserData(); 1139 if (userDataMap != null && !userDataMap.isEmpty()) { 1140 userData = ir.getCommitUserData().toString(); 1141 } else { 1142 userData = "--"; 1143 } 1144 } catch (UnsupportedOperationException uoe) { 1145 userData = "(not supported)"; 1146 } 1147 setString(iUser, "text", userData); 1148 final Object nTerms = find("nTerms"); 1149 if (!slowAccess) { 1150 Thread t = new Thread() { 1151 public void run() { 1152 actionTopTerms(nTerms); 1153 } 1154 }; 1155 t.start(); 1156 } 1157 } catch (Exception e) { 1158 e.printStackTrace(); 1159 errorMsg(e.getMessage()); 1160 } 1161 } 1162 1163 private void initFieldList(Object fList, Object fCombo, Object defFld) { 1164 removeAll(fList); 1165 removeAll(fCombo); 1166 removeAll(defFld); 1167 setString(fCombo, "text", idxFields[0]); 1168 setString(defFld, "text", idxFields[0]); 1169 NumberFormat intCountFormat = NumberFormat.getIntegerInstance(); 1170 NumberFormat percentFormat = NumberFormat.getNumberInstance(); 1171 intCountFormat.setGroupingUsed(true); 1172 percentFormat.setMaximumFractionDigits(2); 1173 // sort by names now 1174 for (String s : idxFields) { 1175 Object row = create("row"); 1176 putProperty(row, "fName", s); 1177 add(fList, row); 1178 Object cell = create("cell"); 1179 setString(cell, "text", s); 1180 add(row, cell); 1181 cell = create("cell"); 1182 FieldTermCount ftc = termCounts.get(s); 1183 if (ftc != null) { 1184 long cnt = ftc.termCount; 1185 setString(cell, "text", intCountFormat.format(cnt)); 1186 setChoice(cell, "alignment", "right"); 1187 add(row, cell); 1188 float pcent = (float)(cnt * 100) / (float)numTerms; 1189 cell = create("cell"); 1190 setString(cell, "text", percentFormat.format(pcent) + " %"); 1191 setChoice(cell, "alignment", "right"); 1192 add(row, cell); 1193 } else { 1194 setString(cell, "text", "0"); 1195 setChoice(cell, "alignment", "right"); 1196 add(row, cell); 1197 cell = create("cell"); 1198 setString(cell, "text", "0.00 %"); 1199 setChoice(cell, "alignment", "right"); 1200 add(row, cell); 1201 } 1202 cell = create("cell"); 1203 setChoice(cell, "alignment", "right"); 1204 Decoder dec = decoders.get(s); 1205 if (dec == null) dec = defDecoder; 1206 setString(cell, "text", dec.toString()); 1207 add(row, cell); 1208 // populate combos 1209 Object choice = create("choice"); 1210 add(fCombo, choice); 1211 setString(choice, "text", s); 1212 putProperty(choice, "fName", s); 1213 choice = create("choice"); 1214 add(defFld, choice); 1215 setString(choice, "text", s); 1216 putProperty(choice, "fName", s); 1217 } 1218 setString(find("defFld"), "text", idxFields[0]); 1219 // Remove columns 1220 Object header = get(find("sTable"), "header"); 1221 removeAll(header); 1222 Object c = create("column"); 1223 setString(c, "text", "#"); 1224 setInteger(c, "width", 40); 1225 add(header, c); 1226 c = create("column"); 1227 setString(c, "text", "Score"); 1228 setInteger(c, "width", 50); 1229 add(header, c); 1230 c = create("column"); 1231 setString(c, "text", "Doc. Id"); 1232 setInteger(c, "width", 60); 1233 add(header, c); 1234 for (int j = 0; j < idxFields.length; j++) { 1235 c = create("column"); 1236 setString(c, "text", idxFields[j]); 1237 add(header, c); 1238 } 1239 } 1240 1241 private void showCommits() throws Exception { 1242 Object commitsTable = find("commitsTable"); 1243 removeAll(commitsTable); 1244 if (dir == null) { 1245 Object row = create("row"); 1246 Object cell = create("cell"); 1247 setString(cell, "text", "<not available>"); 1248 setBoolean(cell, "enabled", false); 1249 add(row, cell); 1250 add(commitsTable, row); 1251 return; 1252 } 1253 Collection commits = IndexReader.listCommits(dir); 1254 // commits are ordered from oldest to newest ? 1255 Iterator it = commits.iterator(); 1256 int rowNum = 0; 1257 while (it.hasNext()) { 1258 IndexCommit commit = (IndexCommit)it.next(); 1259 // figure out the name of the segment files 1260 Collection files = commit.getFileNames(); 1261 Iterator itf = files.iterator(); 1262 Object row = create("row"); 1263 boolean enabled = rowNum < commits.size() - 1; 1264 Color color = null; 1265 rowNum++; 1266 add(commitsTable, row); 1267 putProperty(row, "commit", commit); 1268 if (enabled) { 1269 putProperty(row, "commitDeletable", Boolean.TRUE); 1270 } 1271 Object cell = create("cell"); 1272 setString(cell, "text", String.valueOf(commit.getGeneration())); 1273 add(row, cell); 1274 cell = create("cell"); 1275 char[] flags = new char[]{'-', '-'}; 1276 if (commit.isDeleted()) flags[0] = 'D'; 1277 if (commit.isOptimized()) flags[1] = 'O'; 1278 setString(cell, "text", new String(flags)); 1279 setFont(cell, "font", courier); 1280 setChoice(cell, "alignment", "center"); 1281 add(row, cell); 1282 cell = create("cell"); 1283 setString(cell, "text", Long.toHexString(commit.getVersion())); 1284 add(row, cell); 1285 cell = create("cell"); 1286 setString(cell, "text", new Date(commit.getTimestamp()).toString()); 1287 add(row, cell); 1288 cell = create("cell"); 1289 Map userData = commit.getUserData(); 1290 if (userData != null && !userData.isEmpty()) { 1291 setString(cell, "text", userData.toString()); 1292 } else { 1293 setString(cell, "text", "--"); 1294 } 1295 add(row, cell); 1296 } 1297 } 1298 1299 public void showCommitFiles(Object commitTable) throws Exception { 1300 List commits = new ArrayList(); 1301 Object[] rows = getSelectedItems(commitTable); 1302 if (rows == null || rows.length == 0) { 1303 showFiles(dir, commits); 1304 return; 1305 } 1306 for (int i = 0; i < rows.length; i++) { 1307 IndexCommit commit = (IndexCommit)getProperty(rows[i], "commit"); 1308 if (commit != null) { 1309 commits.add(commit); 1310 } 1311 } 1312 showFiles(dir, commits); 1313 } 1314 1315 private void showFiles(Directory dir, List commits) throws Exception { 1316 Object filesTable = find("filesTable"); 1317 if (dir == null) { 1318 removeAll(filesTable); 1319 Object row = create("row"); 1320 Object cell = create("cell"); 1321 setString(cell, "text", "<not available>"); 1322 setBoolean(cell, "enabled", false); 1323 add(row, cell); 1324 add(filesTable, row); 1325 return; 1326 } 1327 String[] physFiles = dir.listAll(); 1328 List<String> files = new ArrayList(); 1329 if (commits != null && commits.size() > 0) { 1330 for (int i = 0; i < commits.size(); i++) { 1331 IndexCommit commit = (IndexCommit)commits.get(i); 1332 files.addAll(commit.getFileNames()); 1333 } 1334 } else { 1335 files.addAll(Arrays.asList(physFiles)); 1336 } 1337 Collections.sort(files); 1338 List segs = getIndexFileNames(dir); 1339 List dels = getIndexDeletableNames(dir); 1340 removeAll(filesTable); 1341 for (int i = 0; i < files.size(); i++) { 1342 String fileName = files.get(i); 1343 String pathName; 1344 if (pName.endsWith(File.separator)) { 1345 pathName = pName; 1346 } else { 1347 pathName = pName + File.separator; 1348 } 1349 File file = new File(pathName + fileName); 1350 Object row = create("row"); 1351 Object nameCell = create("cell"); 1352 setString(nameCell, "text", fileName); 1353 add(row, nameCell); 1354 Object sizeCell = create("cell"); 1355 setString(sizeCell, "text", Util.normalizeSize(file.length())); 1356 setChoice(sizeCell, "alignment", "right"); 1357 add(row, sizeCell); 1358 Object unitCell = create("cell"); 1359 setString(unitCell, "text", Util.normalizeUnit(file.length())); 1360 add(row, unitCell); 1361 boolean deletable = dels.contains(fileName.intern()); 1362 String inuse = getFileFunction(fileName); 1363 Object delCell = create("cell"); 1364 setString(delCell, "text", deletable ? "YES" : "-"); 1365 add(row, delCell); 1366 Object inuseCell = create("cell"); 1367 setString(inuseCell, "text", inuse); 1368 add(row, inuseCell); 1369 add(filesTable, row); 1370 } 1371 } 1372 1373 private String getFileFunction(String file) { 1374 String res = IndexGate.getFileFunction(file); 1375 if (res == null) { 1376 res = "YES"; 1377 } 1378 return res; 1379 } 1380 1381 private void syncMRU(Object path) { 1382 removeAll(path); 1383 for (Iterator iter = Prefs.getMruList().iterator(); iter.hasNext();) { 1384 String element = (String) iter.next(); 1385 Object choice = create("choice"); 1386 setString(choice, "text", element); 1387 add(path, choice); 1388 } 1389 } 1390 1391 /** 1392 * Update the list of top terms. 1393 * @param nTerms Thinlet widget containing the number of top terms to show 1394 */ 1395 public void actionTopTerms(Object nTerms) { 1396 if (ir == null) { 1397 showStatus(MSG_NOINDEX); 1398 return; 1399 } 1400 String sndoc = getString(nTerms, "text"); 1401 int nd = 50; 1402 try { 1403 nd = Integer.parseInt(sndoc); 1404 } catch (Exception e) {} 1405 final int ndoc = nd; 1406 Object[] fields = getSelectedItems(find("fList")); 1407 String[] flds = null; 1408 if (fields == null || fields.length == 0) { 1409 flds = idxFields; 1410 } else { 1411 flds = new String[fields.length]; 1412 for (int i = 0; i < fields.length; i++) { 1413 flds[i] = (String) getProperty(fields[i], "fName"); 1414 } 1415 } 1416 final String[] fflds = flds; 1417 SlowThread st = new SlowThread(this) { 1418 public void execute() { 1419 try { 1420 TermInfo[] tis = HighFreqTerms.getHighFreqTerms(ir, null, ndoc + 1, fflds); 1421 Object table = find("tTable"); 1422 removeAll(table); 1423 if (tis == null || tis.length == 0) { 1424 Object row = create("row"); 1425 Object cell = create("cell"); 1426 add(row, cell); 1427 cell = create("cell"); 1428 add(row, cell); 1429 cell = create("cell"); 1430 add(row, cell); 1431 cell = create("cell"); 1432 setBoolean(cell, "enabled", false); 1433 setString(cell, "text", "No Results"); 1434 add(row, cell); 1435 add(table, row); 1436 return; 1437 } 1438 for (int i = 0; i < tis.length; i++) { 1439 Object row = create("row"); 1440 add(table, row); 1441 putProperty(row, "term", tis[i].term); 1442 putProperty(row, "ti", tis[i]); 1443 Object cell = create("cell"); 1444 setChoice(cell, "alignment", "right"); 1445 setString(cell, "text", String.valueOf(i + 1)); 1446 add(row, cell); 1447 cell = create("cell"); 1448 setChoice(cell, "alignment", "right"); 1449 setString(cell, "text", String.valueOf(tis[i].docFreq) + " "); 1450 add(row, cell); 1451 cell = create("cell"); 1452 setString(cell, "text", tis[i].term.field()); 1453 add(row, cell); 1454 cell = create("cell"); 1455 Decoder dec = decoders.get(tis[i].term.field()); 1456 if (dec == null) dec = defDecoder; 1457 String s; 1458 try { 1459 s = dec.decodeTerm(tis[i].term.field(), tis[i].term.text()); 1460 } catch (Throwable e) { 1461 s = tis[i].term.text(); 1462 setColor(cell, "foreground", Color.RED); 1463 } 1464 setString(cell, "text", " " + s); 1465 add(row, cell); 1466 } 1467 } catch (Exception e) { 1468 e.printStackTrace(); 1469 errorMsg(e.getMessage()); 1470 } 1471 } 1472 }; 1473 if (slowAccess) { 1474 st.start(); 1475 } else { 1476 st.execute(); 1477 } 1478 } 1479 1480 public void clipTopTerms(Object tTable) { 1481 Object[] rows = getItems(tTable); 1482 StringBuffer sb = new StringBuffer(); 1483 for (int i = 0; i < rows.length; i++) { 1484 TermInfo ti = (Term…
Large files files are truncated, but you can click here to view the full file