示例#1
0
  /**
   * Creates an input dialog instance. The dialog remains invisible until {@link #open()} is called.
   *
   * @param parent The parent shell.
   * @param title The window title for this input dialog.
   * @param msg The message to display on this input dialog.
   * @param defaultValue The default value for the input field.
   */
  public InputDialog(Shell parent, String title, String msg, String defaultValue) {
    shell = new Shell(parent, SWT.PRIMARY_MODAL | SWT.DIALOG_TRIM | SWT.RESIZE);
    shell.setText(title);

    Label label = new Label(shell, SWT.NONE);
    text = new Combo(shell, SWT.BORDER | SWT.SINGLE);
    Util.selectAllOnFocus(text);
    Label fillerLabel = new Label(shell, SWT.NONE);
    Label separator = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
    Button okBt = new Button(shell, SWT.PUSH);
    Button cancelBt = new Button(shell, SWT.PUSH);

    label.setText(msg);
    text.setText(defaultValue);
    text.setSelection(new Point(0, text.getText().length()));
    okBt.setText(AppUtil.Messages.ok.get());
    cancelBt.setText(AppUtil.Messages.cancel.get());
    Button[] okCancelBts = Util.maybeSwapButtons(okBt, cancelBt);

    shell.setLayout(Util.createFormLayout(5));
    FormDataFactory fdf = FormDataFactory.getInstance();
    fdf.top().left().right().applyTo(label);
    fdf.top(label).applyTo(text);
    fdf.reset().minWidth(Util.BTW).bottom().right().applyTo(okCancelBts[1]);
    fdf.right(okCancelBts[1]).applyTo(okCancelBts[0]);
    fdf.reset().left().right().bottom(okCancelBts[1]).applyTo(separator);
    fdf.top(text).bottom(separator).applyTo(fillerLabel);

    okBt.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            answer = text.getText();
            shell.close();
          }
        });

    cancelBt.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            shell.close();
          }
        });

    text.addKeyListener(
        new KeyAdapter() {
          public void keyReleased(KeyEvent e) {
            if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {
              answer = text.getText();
              shell.close();
            }
          }
        });
  }
  public WebInterfaceDialog(@NotNull Shell parentShell) {
    shell = new Shell(parentShell, SWT.PRIMARY_MODAL | SWT.DIALOG_TRIM);
    shell.setLayout(Util.createFormLayout(5));
    shell.setText(Msg.web_interface.get());

    Composite comp = new Composite(shell, SWT.NONE);
    comp.setLayout(new RowLayout());

    Button enableButton = new Button(comp, SWT.CHECK);
    enableButton.setText(Msg.enable_web_interface.get());

    enableButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            /*
             * TODO web interface: start or stop web interface
             * TODO web interface: also stop web interface automatically when the program exits (in Main class)
             * TODO web interface: remove comment in ProgramConf.Int.WebInterfacePageSize.
             */
          }
        });

    Button closeButton = new Button(shell, SWT.PUSH);
    closeButton.setText(Msg.close.get());
    closeButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            shell.close();
          }
        });

    FormDataFactory fdf = FormDataFactory.getInstance();
    fdf.bottom().right().minWidth(Util.BTW).applyTo(closeButton);
    fdf.reset().bottom(closeButton).left().top().right().applyTo(comp);
  }
示例#3
0
 private ResultPage(
     @NotNull List<ResultDocument> resultDocuments, int pageIndex, int pageCount, int hitCount) {
   this.resultDocuments = Util.checkNotNull(resultDocuments);
   this.pageIndex = pageIndex;
   this.pageCount = pageCount;
   this.hitCount = hitCount;
 }
示例#4
0
 @NotNull
 private static String get(@NotNull String type, @NotNull String subType) {
   Util.checkNotNull(type, subType);
   assert subType.length() > 0;
   assert !subType.startsWith("/") && !subType.startsWith("\\");
   return type + "/" + subType.toLowerCase(Locale.ENGLISH);
 }
 @NotNull
 String[] getStringChoices() {
   EN[] choices = choiceClass.getEnumConstants();
   Util.checkThat(choices.length > 0);
   String[] stringChoices = new String[choices.length];
   for (int i = 0; i < choices.length; i++) stringChoices[i] = toString(choices[i]);
   return stringChoices;
 }
示例#6
0
 // Caller must close returned searcher
 @NotNull
 @NotThreadSafe
 private List<CorruptedIndex> setLuceneSearcher(@NotNull List<LuceneIndex> indexes)
     throws IOException {
   this.indexes = Util.checkNotNull(indexes);
   Searchable[] searchables = new Searchable[indexes.size()];
   LazyList<CorruptedIndex> corrupted = new LazyList<CorruptedIndex>();
   for (int i = 0; i < indexes.size(); i++) {
     LuceneIndex index = indexes.get(i);
     try {
       searchables[i] = new IndexSearcher(index.getLuceneDir());
     } catch (IOException e) {
       Util.printErr(e);
       searchables[i] = new DummySearchable();
       corrupted.add(new CorruptedIndex(index, e));
     }
   }
   luceneSearcher = new MultiSearcher(searchables);
   return corrupted;
 }
示例#7
0
 @NotNull
 public File getCanonicalFile() {
   if (canonicalFile == null) {
     /*
      * On Mac OS X, return a file with decomposed path. On all other
      * platforms, return a file with composed path.
      */
     String path1 = normalizeUnicode(path, !Util.IS_MAC_OS_X);
     canonicalFile = Util.getCanonicalFile(path1);
   }
   return canonicalFile;
 }
示例#8
0
  private static void convertDir(
      @NotNull PegDownProcessor processor,
      @NotNull PageProperties props,
      @NotNull File srcDir,
      @NotNull File dstDir)
      throws IOException {
    for (File mdFile : Util.listFiles(srcDir)) {
      if (mdFile.equals(props.propsFile)) continue;
      if (!mdFile.isFile()) continue;
      String name = mdFile.getName();
      if (!name.endsWith(".markdown")) continue;

      Util.println("Converting: " + name);
      String rawText = CharsetDetectorHelper.toString(mdFile);
      String htmlBody = processor.markdownToHtml(rawText);
      String newFilename = Util.splitFilename(name)[0] + ".html";
      File htmlFile = new File(dstDir, newFilename);
      String html = convertPage(props, mdFile, htmlBody);
      Files.write(html, htmlFile, Charsets.UTF_8);
    }
  }
示例#9
0
  public Path(@NotNull String path) {
    Util.checkNotNull(path);
    this.path = normalizePath(path);
    this.canonicalFile = getCanonicalFile();

    /*
     * If the file is a root, such as '/' or 'C:', then File.getName() will
     * return an empty string. In that case, use toString() instead, which
     * will return '/' and 'C:', respectively. We don't want an empty string
     * as name because it will be used for display on the GUI.
     */
    this.name = getDisplayName(canonicalFile);
  }
示例#10
0
 /** See {@link #getIcon(File, Image)}. */
 @Nullable
 public Image getIcon(@NotNull String filename, @Nullable Image defaultIcon) {
   String extension = Util.getExtension(filename);
   Image image = fileIconMap.get(extension);
   if (image != null) return image;
   Program program = Program.findProgram(extension);
   if (program == null) return defaultIcon;
   ImageData imgData = program.getImageData();
   if (imgData == null) return defaultIcon;
   image = new Image(disposeWidget.getDisplay(), imgData);
   fileIconMap.put(extension, image);
   return image;
 }
示例#11
0
 /** Opens the dialog and returns the input string or null if the dialog was canceled. */
 public String open() {
   Util.setCenteredMinBounds(shell, 300, 150);
   shell.open();
   if (selectFilenameOnly) {
     String s = text.getText();
     int index = s.lastIndexOf('.');
     if (index != -1) text.setSelection(new Point(0, index));
     else text.setSelection(new Point(0, text.getText().length()));
   } else {
     text.setSelection(new Point(0, text.getText().length()));
   }
   while (!shell.isDisposed()) {
     if (!shell.getDisplay().readAndDispatch()) shell.getDisplay().sleep();
   }
   return answer;
 }
示例#12
0
  // Given deletions should not be in the registry anymore, since the receiver
  // will retrieve a fresh set of indexes from the registry before approval
  @ThreadSafe
  @VisibleForPackageGroup
  public void approveDeletions(@NotNull List<PendingDeletion> deletions) {
    Util.checkNotNull(deletions);
    if (deletions.isEmpty()) return;

    /*
     * If the deletion thread is not available anymore, approve of deletions
     * immediately. - Otherwise the given deletion objects would just hang
     * around in the queue until program shutdown and never receive
     * approval, thus the associated indexes would never get deleted.
     */
    synchronized (this) {
      if (deletionThread.isInterrupted()) {
        for (PendingDeletion pendingDeletion : deletions) pendingDeletion.setApprovedBySearcher();
      } else {
        deletionQueue.add(deletions);
      }
    }
  }
示例#13
0
  @Nullable
  @RecursiveMethod
  private static PathParts splitFromRight(
      @NotNull Path left, @NotNull String right, @NotNull Predicate<Path> leftPredicate) {
    if (leftPredicate.apply(left)) return new PathParts(left, right);

    // Reached left end of a relative path
    if (!left.getPath().contains("/") && !left.getPath().contains("\\")) return null;

    String[] leftParts = splitAtLastSeparator(left.getPath());

    // Reached Unix root
    if (leftParts[0].isEmpty()) return null;

    // Reached Windows root
    if (leftParts[0].matches("[a-zA-Z]:")) return null;

    // Move by one path part to the left and recurse
    String newRight = Util.joinPath(leftParts[1], right);
    return splitFromRight(new Path(leftParts[0]), newRight, leftPredicate);
  }
示例#14
0
  /**
   * Disposes of the receiver. The caller should make sure that no more search requests are
   * submitted to the receiver after this method is called.
   */
  @ThreadSafe
  public void shutdown() {
    if (ioException != null) Util.printErr(ioException);

    writeLock.lock();
    try {
      indexRegistry.removeListeners(addedListener, null);
      Closeables.closeQuietly(luceneSearcher);
    } finally {
      writeLock.unlock();
    }

    /*
     * This should be done after closing the Lucene searcher in order to
     * ensure that no indexes will be deleted outside the deletion queue
     * while the Lucene searcher is still open.
     */
    synchronized (this) {
      deletionThread.interrupt();
    }
  }
  public static void main(String[] args) {
    Display display = new Display();
    final Shell shell = new Shell(display);
    Util.setCenteredBounds(shell, 200, 100);
    shell.setLayout(new GridLayout());

    Button bt = new Button(shell, SWT.PUSH);
    bt.setText("Open Dialog");
    bt.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
    bt.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            WebInterfaceDialog dialog = new WebInterfaceDialog(shell);
            dialog.open();
          }
        });

    shell.open();
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) display.sleep();
    }
    display.dispose();
  }
 protected ComboEditSupport(@NotNull Class<EN> choiceClass) {
   this.choiceClass = Util.checkNotNull(choiceClass);
 }
示例#17
0
 public Attachment(@NotNull String filename, @NotNull FileResource fileResource) {
   this.filename = Util.checkNotNull(filename);
   this.fileResource = Util.checkNotNull(fileResource);
 }
 public void open() {
   Util.setCenteredBounds(shell, 300, 200);
   shell.open();
 }
示例#19
0
  /**
   * This method should not be called by clients. Use {@link IndexRegistry#getSearcher()} instead.
   *
   * @param corruptedIndexes A list that will be filled by this constructor with indexes that
   *     couldn't be loaded.
   */
  @VisibleForPackageGroup
  public Searcher(
      @NotNull IndexRegistry indexRegistry,
      @NotNull FileFactory fileFactory,
      @NotNull OutlookMailFactory outlookMailFactory,
      @NotNull final List<CorruptedIndex> corruptedIndexes)
      throws IOException {
    Util.checkNotNull(indexRegistry, fileFactory, outlookMailFactory);
    this.indexRegistry = indexRegistry;
    this.fileFactory = fileFactory;
    this.outlookMailFactory = outlookMailFactory;

    readLock = indexRegistry.getReadLock();
    writeLock = indexRegistry.getWriteLock();

    // Handler for index additions
    addedListener =
        new Event.Listener<LuceneIndex>() {
          public void update(LuceneIndex eventData) {
            replaceLuceneSearcher();
          }
        };

    /*
     * This lock could be moved into the indexes handler, but we'll put it
     * here to avoid releasing and reacquiring it.
     */
    writeLock.lock();
    try {
      indexRegistry.addListeners(
          new ExistingIndexesHandler() {
            // Handle existing indexes
            public void handleExistingIndexes(List<LuceneIndex> indexes) {
              try {
                corruptedIndexes.addAll(setLuceneSearcher(indexes));
              } catch (IOException e) {
                ioException = e;
              }
            }
          },
          addedListener,
          null); // removedListener is null, see deletion thread below
    } finally {
      writeLock.unlock();
    }

    if (ioException != null) throw ioException;

    // Handler for index removals
    deletionThread =
        new Thread(Searcher.class.getName() + " (Approve pending deletions)") {
          public void run() {
            while (true) {
              try {
                List<PendingDeletion> deletions = deletionQueue.take();
                replaceLuceneSearcher();
                for (PendingDeletion deletion : deletions) deletion.setApprovedBySearcher();
              } catch (InterruptedException e) {
                break;
              }
            }
          }
        };
    deletionThread.start();
  }
示例#20
0
  public static void main(String[] args) throws Exception {
    for (File srcDir : Util.listFiles(websiteDir)) {
      if (!srcDir.isDirectory()) continue;
      if (srcDir.getName().equals("all")) continue;

      File dstDir = new File("dist/website/" + srcDir.getName());
      dstDir.mkdirs();
      Util.deleteContents(dstDir);

      PegDownProcessor processor = new PegDownProcessor(Extensions.TABLES);
      File propsFile = new File(srcDir, "/page.properties");
      PageProperties props = new PageProperties(propsFile);
      convertDir(processor, props, srcDir, dstDir);
    }

    // Deploy files in the website/all directory
    for (File file : Util.listFiles(new File(websiteDir + "/all"))) {
      File dstFile = new File("dist/website/all", file.getName());
      Files.createParentDirs(dstFile);
      Files.copy(file, dstFile);
    }

    // Deploy PAD file
    File padFileSrc = new File(websiteDir, "docfetcher-pad-template.xml");
    File padFileDst = new File("dist/website", "docfetcher-pad.xml");
    String padContents = CharsetDetectorHelper.toString(padFileSrc);
    padContents = UtilGlobal.replace(padFileSrc.getPath(), padContents, "${version}", version);
    Files.write(padContents, padFileDst, Charsets.UTF_8);
    Util.println("File written: " + padFileDst.getPath());

    // Deploy English Resource.properties; this is currently used for
    // GUI translation via transifex.com
    Properties prop = new Properties();
    for (Msg msg : Msg.values()) prop.put(msg.name(), msg.get());
    File propFile = new File("dist/website", "Resource.properties");
    FileWriter w = new FileWriter(propFile);
    prop.store(w, "");
    Closeables.closeQuietly(w);
    Util.println("File written: " + propFile.getPath());

    // Deploy index.php file
    File indexPhpFile = new File("dist/website/index.php");
    Files.copy(new File(websiteDir, "index.php"), indexPhpFile);
    Util.println("File written: " + indexPhpFile.getPath());

    // Deploy help file for GUI translators
    File propHelpSrc = new File(websiteDir, "prop-help-template.html");
    File propHelpDst = new File("dist/website", "properties-help.html");
    StringBuilder sb = new StringBuilder();
    for (Msg msg : Msg.values()) {
      sb.append("<tr align=\"left\">");
      sb.append("<td>");
      sb.append(escapeHtml(propHelpSrc.getPath(), msg.get()));
      sb.append("</td>");
      sb.append(Util.LS);
      sb.append("<td>");
      sb.append(msg.getComment());
      sb.append("</td>");
      sb.append("</tr>");
      sb.append(Util.LS);
    }
    String propHelpContents = CharsetDetectorHelper.toString(propHelpSrc);
    propHelpContents =
        UtilGlobal.replace(propHelpSrc.getPath(), propHelpContents, "${contents}", sb.toString());
    Files.write(propHelpContents, propHelpDst, Charsets.UTF_8);
    Util.println("File written: " + propHelpDst.getPath());
  }
示例#21
0
 @NotNull
 public Path createSubPath(@NotNull String pathPart) {
   return new Path(Util.joinPath(path, pathPart));
 }
示例#22
0
  /**
   * For the given query, returns the requested page of results. This method should not be called
   * anymore after {@link #shutdown()} has been called, otherwise an IOException will be thrown.
   */
  @NotNull
  @ThreadSafe
  public ResultPage search(@NotNull WebQuery webQuery)
      throws IOException, SearchException, CheckedOutOfMemoryError {
    Util.checkNotNull(webQuery);

    if (ioException != null) throw ioException;

    List<Filter> filters = new ArrayList<Filter>(3);

    // Add size filter to filter chain
    if (webQuery.minSize != null || webQuery.maxSize != null) {
      filters.add(
          NumericRangeFilter.newLongRange(
              Fields.SIZE.key(), webQuery.minSize, webQuery.maxSize, true, true));
    }

    // Add type filter to filter chain
    if (webQuery.parsers != null) {
      TermsFilter typeFilter = new TermsFilter();
      String fieldName = Fields.PARSER.key();
      typeFilter.addTerm(new Term(fieldName, Fields.EMAIL_PARSER));
      for (Parser parser : webQuery.parsers) {
        String parserName = parser.getClass().getSimpleName();
        typeFilter.addTerm(new Term(fieldName, parserName));
      }
      filters.add(typeFilter);
    }

    // Add location filter to filter chain
    if (webQuery.indexes != null) {
      Filter[] indexFilters = new Filter[webQuery.indexes.size()];
      int i = 0;
      for (LuceneIndex index : webQuery.indexes) {
        Path path = index.getRootFolder().getPath();
        String uid = index.getDocumentType().createUniqueId(path);
        Term prefix = new Term(Fields.UID.key(), uid + "/");
        indexFilters[i++] = new PrefixFilter(prefix);
      }
      filters.add(new ChainedFilter(indexFilters, ChainedFilter.OR));
    }

    // Construct filter chain
    Filter filter =
        filters.size() == 0
            ? null
            : new ChainedFilter(filters.toArray(new Filter[filters.size()]), ChainedFilter.AND);

    // Create query
    QueryWrapper queryWrapper = createQuery(webQuery.query);
    Query query = queryWrapper.query;
    boolean isPhraseQuery = queryWrapper.isPhraseQuery;

    readLock.lock();
    try {
      checkIndexesExist();

      // Perform search; might throw OutOfMemoryError
      int maxResults = (webQuery.pageIndex + 1) * PAGE_SIZE;
      TopDocs topDocs = luceneSearcher.search(query, filter, maxResults);
      ScoreDoc[] scoreDocs = topDocs.scoreDocs;

      // Compute start and end indices of returned page
      int start;
      int end = scoreDocs.length;
      if (end <= PAGE_SIZE) {
        start = 0;
      } else {
        int r = end % PAGE_SIZE;
        start = end - (r == 0 ? PAGE_SIZE : r);
      }

      // Create and fill list of result documents to return
      ResultDocument[] results = new ResultDocument[end - start];
      for (int i = start; i < end; i++) {
        Document doc = luceneSearcher.doc(scoreDocs[i].doc);
        float score = scoreDocs[i].score;
        LuceneIndex index = indexes.get(luceneSearcher.subSearcher(i));
        IndexingConfig config = index.getConfig();
        results[i - start] =
            new ResultDocument(
                doc, score, query, isPhraseQuery, config, fileFactory, outlookMailFactory);
      }

      int hitCount = topDocs.totalHits;
      int newPageIndex = start / PAGE_SIZE;
      int pageCount = (int) Math.ceil((float) hitCount / PAGE_SIZE);

      return new ResultPage(Arrays.asList(results), newPageIndex, pageCount, hitCount);
    } catch (IllegalArgumentException e) {
      throw wrapEmptyIndexException(e);
    } catch (OutOfMemoryError e) {
      throw new CheckedOutOfMemoryError(e);
    } finally {
      readLock.unlock();
    }
  }
示例#23
0
 private QueryWrapper(@NotNull Query query, boolean isPhraseQuery) {
   this.query = Util.checkNotNull(query);
   this.isPhraseQuery = isPhraseQuery;
 }