/** * 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); }
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; }
@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; }
// 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; }
@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; }
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); } }
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); }
/** 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; }
/** 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; }
// 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); } } }
@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); }
/** * 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); }
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(); }
/** * 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(); }
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()); }
@NotNull public Path createSubPath(@NotNull String pathPart) { return new Path(Util.joinPath(path, pathPart)); }
/** * 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(); } }
private QueryWrapper(@NotNull Query query, boolean isPhraseQuery) { this.query = Util.checkNotNull(query); this.isPhraseQuery = isPhraseQuery; }