Java tutorial
/* Copyright (C) 2003-2015 JabRef contributors. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package net.sf.jabref; import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; import com.jgoodies.looks.plastic.theme.SkyBluer; import net.sf.jabref.exporter.*; import net.sf.jabref.gui.*; import net.sf.jabref.gui.remote.JabRefMessageHandler; import net.sf.jabref.gui.util.FocusRequester; import net.sf.jabref.importer.*; import net.sf.jabref.importer.fetcher.EntryFetcher; import net.sf.jabref.importer.fetcher.EntryFetchers; import net.sf.jabref.logic.CustomEntryTypesManager; import net.sf.jabref.logic.journals.JournalAbbreviationLoader; import net.sf.jabref.logic.l10n.Localization; import net.sf.jabref.logic.labelpattern.LabelPatternUtil; import net.sf.jabref.logic.logging.JabRefLogger; import net.sf.jabref.logic.net.ProxyAuthenticator; import net.sf.jabref.logic.net.ProxyPreferences; import net.sf.jabref.logic.net.ProxyRegisterer; import net.sf.jabref.logic.preferences.LastFocusedTabPreferences; import net.sf.jabref.logic.remote.RemotePreferences; import net.sf.jabref.logic.remote.client.RemoteListenerClient; import net.sf.jabref.logic.search.DatabaseSearcher; import net.sf.jabref.logic.search.SearchQuery; import net.sf.jabref.logic.util.OS; import net.sf.jabref.logic.util.io.FileBasedLock; import net.sf.jabref.logic.util.strings.StringUtil; import net.sf.jabref.migrations.PreferencesMigrations; import net.sf.jabref.model.database.BibDatabase; import net.sf.jabref.model.database.BibDatabaseMode; import net.sf.jabref.model.entry.BibEntry; import net.sf.jabref.util.Util; import net.sf.jabref.cli.AuxCommandLine; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.swing.*; import javax.swing.plaf.FontUIResource; import java.awt.*; import java.io.File; import java.io.IOException; import java.net.Authenticator; import java.nio.charset.Charset; import java.util.*; import java.util.List; import java.util.prefs.BackingStoreException; /** * JabRef Main Class - The application gets started here. */ public class JabRef { private static final Log LOGGER = LogFactory.getLog(JabRef.class); public static JabRefFrame jrf; private JabRefCLI cli; public void start(String[] args) { JabRefPreferences preferences = JabRefPreferences.getInstance(); ProxyPreferences proxyPreferences = ProxyPreferences.loadFromPreferences(preferences); ProxyRegisterer.register(proxyPreferences); if (proxyPreferences.isUseProxy() && proxyPreferences.isUseAuthentication()) { Authenticator.setDefault(new ProxyAuthenticator()); } Globals.startBackgroundTasks(); Globals.prefs = preferences; Localization.setLanguage(preferences.get(JabRefPreferences.LANGUAGE)); Globals.prefs.setLanguageDependentDefaultValues(); // Update which fields should be treated as numeric, based on preferences: InternalBibtexFields.setNumericFieldsFromPrefs(); /* Build list of Import and Export formats */ Globals.importFormatReader.resetImportFormats(); CustomEntryTypesManager.loadCustomEntryTypes(preferences); ExportFormats.initAllExports(); // Read list(s) of journal names and abbreviations Globals.journalAbbreviationLoader = new JournalAbbreviationLoader(Globals.prefs); // Check for running JabRef RemotePreferences remotePreferences = new RemotePreferences(Globals.prefs); if (remotePreferences.useRemoteServer()) { Globals.remoteListener.open(new JabRefMessageHandler(this), remotePreferences.getPort()); if (Globals.remoteListener.isOpen()) { Globals.remoteListener.start(); // we are alone, we start the server } else { // we are not alone, there is already a server out there, try to contact already running JabRef: if (RemoteListenerClient.sendToActiveJabRefInstance(args, remotePreferences.getPort())) { /* * We have successfully sent our command line options * through the socket to another JabRef instance. So we * assume it's all taken care of, and quit. */ System.out.println( Localization.lang("Arguments passed on to running JabRef instance. Shutting down.")); JabRefExecutorService.INSTANCE.shutdownEverything(); return; } } } // override used newline character with the one stored in the preferences // The preferences return the system newline character sequence as default Globals.NEWLINE = Globals.prefs.get(JabRefPreferences.NEWLINE); Optional<Vector<ParserResult>> loaded = processArguments(args, true); if ((!(loaded.isPresent())) || cli.isDisableGui() || cli.isShowVersion()) { JabRefExecutorService.INSTANCE.shutdownEverything(); return; } SwingUtilities.invokeLater(() -> openWindow(loaded.get())); } public Optional<Vector<ParserResult>> processArguments(String[] args, boolean initialStartup) { cli = new JabRefCLI(args); if (!cli.isBlank() && cli.isDebugLogging()) { JabRefLogger.setDebug(); } if (initialStartup && cli.isShowVersion()) { cli.displayVersion(); } if (initialStartup && cli.isHelp()) { cli.printUsage(); return Optional.empty(); } // Check if we should reset all preferences to default values: if (cli.isPreferencesReset()) { String value = cli.getPreferencesReset(); if ("all".equals(value.trim())) { try { System.out.println(Localization.lang("Setting all preferences to default values.")); Globals.prefs.clear(); } catch (BackingStoreException e) { System.err.println(Localization.lang("Unable to clear preferences.")); e.printStackTrace(); } } else { String[] keys = value.split(","); for (String key : keys) { if (Globals.prefs.hasKey(key.trim())) { System.out.println(Localization.lang("Resetting preference key '%0'", key.trim())); Globals.prefs.clear(key.trim()); } else { System.out.println(Localization.lang("Unknown preference key '%0'", key.trim())); } } } } // Check if we should import preferences from a file: if (cli.isPreferencesImport()) { try { Globals.prefs.importPreferences(cli.getPreferencesImport()); CustomEntryTypesManager.loadCustomEntryTypes(Globals.prefs); ExportFormats.initAllExports(); } catch (JabRefException ex) { LOGGER.error("Cannot import preferences", ex); } } // Vector to put imported/loaded database(s) in. Vector<ParserResult> loaded = new Vector<>(); Vector<String> toImport = new Vector<>(); if (!cli.isBlank() && (cli.getLeftOver().length > 0)) { for (String aLeftOver : cli.getLeftOver()) { // Leftover arguments that have a "bib" extension are interpreted as // bib files to open. Other files, and files that could not be opened // as bib, we try to import instead. boolean bibExtension = aLeftOver.toLowerCase().endsWith("bib"); ParserResult pr = null; if (bibExtension) { pr = JabRef.openBibFile(aLeftOver, false); } if ((pr == null) || (pr == ParserResult.INVALID_FORMAT)) { // We will try to import this file. Normally we // will import it into a new tab, but if this import has // been initiated by another instance through the remote // listener, we will instead import it into the current database. // This will enable easy integration with web browsers that can // open a reference file in JabRef. if (initialStartup) { toImport.add(aLeftOver); } else { loaded.add(JabRef.importToOpenBase(aLeftOver).orElse(ParserResult.INVALID_FORMAT)); } } else if (pr != ParserResult.FILE_LOCKED) { loaded.add(pr); } } } if (!cli.isBlank() && cli.isFileImport()) { toImport.add(cli.getFileImport()); } for (String filenameString : toImport) { importFile(filenameString).ifPresent(loaded::add); } if (!cli.isBlank() && cli.isImportToOpenBase()) { importToOpenBase(cli.getImportToOpenBase()).ifPresent(loaded::add); } if (!cli.isBlank() && cli.isFetcherEngine()) { fetch(cli.getFetcherEngine()).ifPresent(loaded::add); } if (cli.isExportMatches()) { if (!loaded.isEmpty()) { String[] data = cli.getExportMatches().split(","); String searchTerm = data[0].replace("\\$", " "); //enables blanks within the search term: //? stands for a blank ParserResult pr = loaded.elementAt(loaded.size() - 1); BibDatabase dataBase = pr.getDatabase(); SearchQuery query = new SearchQuery(searchTerm, Globals.prefs.getBoolean(JabRefPreferences.SEARCH_CASE_SENSITIVE), Globals.prefs.getBoolean(JabRefPreferences.SEARCH_REG_EXP)); BibDatabase newBase = new DatabaseSearcher(query, dataBase).getDatabaseFromMatches(); //newBase contains only match entries //export database if ((newBase != null) && (newBase.getEntryCount() > 0)) { String formatName; //read in the export format, take default format if no format entered switch (data.length) { case 3: formatName = data[2]; break; case 2: //default ExportFormat: HTML table (with Abstract & BibTeX) formatName = "tablerefsabsbib"; break; default: System.err.println(Localization.lang("Output file missing").concat(". \n \t ") .concat(Localization.lang("Usage")).concat(": ") + JabRefCLI.getExportMatchesSyntax()); return Optional.empty(); } //end switch //export new database IExportFormat format = ExportFormats.getExportFormat(formatName); if (format == null) { System.err.println(Localization.lang("Unknown export format") + ": " + formatName); } else { // We have an ExportFormat instance: try { System.out.println(Localization.lang("Exporting") + ": " + data[1]); format.performExport(newBase, pr.getMetaData(), data[1], pr.getEncoding(), null); } catch (Exception ex) { System.err.println(Localization.lang("Could not export file") + " '" + data[1] + "': " + ex.getMessage()); } } } /*end if newBase != null*/ else { System.err.println(Localization.lang("No search matches.")); } } else { System.err.println(Localization.lang("The output option depends on a valid input option.")); } //end if(loaded.size > 0) } if (cli.isGenerateBibtexKeys()) { regenerateBibtexKeys(loaded); } if (cli.isAutomaticallySetFileLinks()) { automaticallySetFileLinks(loaded); } if (cli.isFileExport()) { if (!loaded.isEmpty()) { String[] data = cli.getFileExport().split(","); if (data.length == 1) { // This signals that the latest import should be stored in BibTeX // format to the given file. if (!loaded.isEmpty()) { ParserResult pr = loaded.elementAt(loaded.size() - 1); if (!pr.isInvalid()) { try { System.out.println(Localization.lang("Saving") + ": " + data[0]); SavePreferences prefs = SavePreferences.loadForSaveFromPreferences(Globals.prefs); Defaults defaults = new Defaults(BibDatabaseMode.fromPreference( Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); BibDatabaseWriter databaseWriter = new BibDatabaseWriter(); SaveSession session = databaseWriter.saveDatabase( new BibDatabaseContext(pr.getDatabase(), pr.getMetaData(), defaults), prefs); // Show just a warning message if encoding didn't work for all characters: if (!session.getWriter().couldEncodeAll()) { System.err.println(Localization.lang("Warning") + ": " + Localization.lang( "The chosen encoding '%0' could not encode the following characters:", session.getEncoding().displayName()) + " " + session.getWriter().getProblemCharacters()); } session.commit(new File(data[0])); } catch (SaveException ex) { System.err.println(Localization.lang("Could not save file.") + "\n" + ex.getLocalizedMessage()); } } } else { System.err .println(Localization.lang("The output option depends on a valid import option.")); } } else if (data.length == 2) { // This signals that the latest import should be stored in the given // format to the given file. ParserResult pr = loaded.elementAt(loaded.size() - 1); // Set the global variable for this database's file directory before exporting, // so formatters can resolve linked files correctly. // (This is an ugly hack!) File theFile = pr.getFile(); if (!theFile.isAbsolute()) { theFile = theFile.getAbsoluteFile(); } MetaData metaData = pr.getMetaData(); metaData.setFile(theFile); Globals.prefs.fileDirForDatabase = metaData.getFileDirectory(Globals.FILE_FIELD) .toArray(new String[0]); Globals.prefs.databaseFile = metaData.getFile(); System.out.println(Localization.lang("Exporting") + ": " + data[0]); IExportFormat format = ExportFormats.getExportFormat(data[1]); if (format == null) { System.err.println(Localization.lang("Unknown export format") + ": " + data[1]); } else { // We have an ExportFormat instance: try { format.performExport(pr.getDatabase(), pr.getMetaData(), data[0], pr.getEncoding(), null); } catch (Exception ex) { System.err.println(Localization.lang("Could not export file") + " '" + data[0] + "': " + ex.getMessage()); } } } } else { System.err.println(Localization.lang("The output option depends on a valid import option.")); } } LOGGER.debug("Finished export"); if (cli.isPreferencesExport()) { try { Globals.prefs.exportPreferences(cli.getPreferencesExport()); } catch (JabRefException ex) { LOGGER.error("Cannot export preferences", ex); } } if (!cli.isBlank() && cli.isAuxImport()) { boolean usageMsg = false; if (!loaded.isEmpty()) // bibtex file loaded { String[] data = cli.getAuxImport().split(","); if (data.length == 2) { ParserResult pr = loaded.firstElement(); AuxCommandLine acl = new AuxCommandLine(data[0], pr.getDatabase()); BibDatabase newBase = acl.perform(); boolean notSavedMsg = false; // write an output, if something could be resolved if (newBase != null) { if (newBase.getEntryCount() > 0) { String subName = StringUtil.getCorrectFileName(data[1], "bib"); try { System.out.println(Localization.lang("Saving") + ": " + subName); SavePreferences prefs = SavePreferences.loadForSaveFromPreferences(Globals.prefs); BibDatabaseWriter databaseWriter = new BibDatabaseWriter(); Defaults defaults = new Defaults(BibDatabaseMode.fromPreference( Globals.prefs.getBoolean(JabRefPreferences.BIBLATEX_DEFAULT_MODE))); SaveSession session = databaseWriter .saveDatabase(new BibDatabaseContext(newBase, defaults), prefs); // Show just a warning message if encoding didn't work for all characters: if (!session.getWriter().couldEncodeAll()) { System.err.println(Localization.lang("Warning") + ": " + Localization.lang( "The chosen encoding '%0' could not encode the following characters:", session.getEncoding().displayName()) + " " + session.getWriter().getProblemCharacters()); } session.commit(new File(subName)); } catch (SaveException ex) { System.err.println(Localization.lang("Could not save file.") + "\n" + ex.getLocalizedMessage()); } notSavedMsg = true; } } if (!notSavedMsg) { System.out.println(Localization.lang("no database generated")); } } else { usageMsg = true; } } else { usageMsg = true; } if (usageMsg) { System.out.println(Localization.lang("no base-BibTeX-file specified") + "!"); System.out.println(Localization.lang("usage") + " :"); System.out.println("jabref --aux infile[.aux],outfile[.bib] base-BibTeX-file"); } } return Optional.of(loaded); } private void automaticallySetFileLinks(List<ParserResult> loaded) { for (ParserResult parserResult : loaded) { BibDatabase database = parserResult.getDatabase(); MetaData metaData = parserResult.getMetaData(); if (metaData != null) { LOGGER.info(Localization.lang("Automatically setting file links")); Util.autoSetLinks(database.getEntries(), metaData); } } } private void regenerateBibtexKeys(List<ParserResult> loaded) { for (ParserResult parserResult : loaded) { BibDatabase database = parserResult.getDatabase(); MetaData metaData = parserResult.getMetaData(); if (metaData != null) { LOGGER.info(Localization.lang("Regenerating bibtex keys according to metadata")); for (BibEntry entry : database.getEntries()) { // try to make a new label LabelPatternUtil.makeLabel(metaData, database, entry); } } else { LOGGER.info(Localization.lang("No meta data present in bibfile. Cannot regenerate bibtex keys")); } } } /** * Run an entry fetcher from the command line. * <p> * Note that this only works headlessly if the EntryFetcher does not show any GUI. * * @param fetchCommand A string containing both the fetcher to use (id of EntryFetcherExtension minus Fetcher) and * the search query, separated by a : * @return A parser result containing the entries fetched or null if an error occurred. */ private Optional<ParserResult> fetch(String fetchCommand) { if ((fetchCommand == null) || !fetchCommand.contains(":") || (fetchCommand.split(":").length != 2)) { System.out.println(Localization.lang("Expected syntax for --fetch='<name of fetcher>:<query>'")); System.out.println(Localization.lang("The following fetchers are available:")); return Optional.empty(); } String[] split = fetchCommand.split(":"); String engine = split[0]; EntryFetchers fetchers = new EntryFetchers(Globals.journalAbbreviationLoader); EntryFetcher fetcher = null; for (EntryFetcher e : fetchers.getEntryFetchers()) { if (engine.equalsIgnoreCase(e.getClass().getSimpleName().replaceAll("Fetcher", ""))) { fetcher = e; } } if (fetcher == null) { System.out.println(Localization.lang("Could not find fetcher '%0'", engine)); System.out.println(Localization.lang("The following fetchers are available:")); for (EntryFetcher e : fetchers.getEntryFetchers()) { System.out.println(" " + e.getClass().getSimpleName().replaceAll("Fetcher", "").toLowerCase()); } return Optional.empty(); } String query = split[1]; System.out.println(Localization.lang("Running Query '%0' with fetcher '%1'.", query, engine) + " " + Localization.lang("Please wait...")); Collection<BibEntry> result = new ImportInspectionCommandLine().query(query, fetcher); if ((result == null) || result.isEmpty()) { System.out.println( Localization.lang("Query '%0' with fetcher '%1' did not return any results.", query, engine)); return Optional.empty(); } return Optional.of(new ParserResult(result)); } private void setLookAndFeel() { try { String lookFeel; String systemLnF = UIManager.getSystemLookAndFeelClassName(); if (Globals.prefs.getBoolean(JabRefPreferences.USE_DEFAULT_LOOK_AND_FEEL)) { // Use system Look & Feel by default lookFeel = systemLnF; } else { lookFeel = Globals.prefs.get(JabRefPreferences.WIN_LOOK_AND_FEEL); } // At all cost, avoid ending up with the Metal look and feel: if ("javax.swing.plaf.metal.MetalLookAndFeel".equals(lookFeel)) { Plastic3DLookAndFeel lnf = new Plastic3DLookAndFeel(); Plastic3DLookAndFeel.setCurrentTheme(new SkyBluer()); com.jgoodies.looks.Options.setPopupDropShadowEnabled(true); UIManager.setLookAndFeel(lnf); } else { try { UIManager.setLookAndFeel(lookFeel); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { // specified look and feel does not exist on the classpath, so use system l&f UIManager.setLookAndFeel(systemLnF); // also set system l&f as default Globals.prefs.put(JabRefPreferences.WIN_LOOK_AND_FEEL, systemLnF); // notify the user JOptionPane.showMessageDialog(JabRef.jrf, Localization.lang( "Unable to find the requested Look & Feel and thus the default one is used."), Localization.lang("Warning"), JOptionPane.WARNING_MESSAGE); } } } catch (Exception e) { LOGGER.warn("Look and feel could not be set", e); } // In JabRef v2.8, we did it only on NON-Mac. Now, we try on all platforms boolean overrideDefaultFonts = Globals.prefs.getBoolean(JabRefPreferences.OVERRIDE_DEFAULT_FONTS); if (overrideDefaultFonts) { int fontSize = Globals.prefs.getInt(JabRefPreferences.MENU_FONT_SIZE); UIDefaults defaults = UIManager.getDefaults(); Enumeration<Object> keys = defaults.keys(); Double zoomLevel = null; for (Object key : Collections.list(keys)) { if ((key instanceof String) && ((String) key).endsWith(".font")) { FontUIResource font = (FontUIResource) UIManager.get(key); if (zoomLevel == null) { // zoomLevel not yet set, calculate it based on the first found font zoomLevel = (double) fontSize / (double) font.getSize(); } font = new FontUIResource(font.getName(), font.getStyle(), fontSize); defaults.put(key, font); } } if (zoomLevel != null) { GUIGlobals.zoomLevel = zoomLevel; } } } private void openWindow(List<ParserResult> loaded) { // Perform checks and changes for users with a preference set from an older // JabRef version. PreferencesMigrations.replaceAbstractField(); PreferencesMigrations.upgradeSortOrder(); PreferencesMigrations.upgradeFaultyEncodingStrings(); // Set up custom or default icon theme: // This is now done at processArguments // This property is set to make the Mac OSX Java VM move the menu bar to // the top of the screen, where Mac users expect it to be. System.setProperty("apple.laf.useScreenMenuBar", "true"); // Set antialiasing on everywhere. This only works in JRE >= 1.5. // Or... it doesn't work, period. // TODO test and maybe remove this! I found this commented out with no additional info ( payload@lavabit.com ) // Enabled since JabRef 2.11 beta 4 System.setProperty("swing.aatext", "true"); // Default is "on". // "lcd" instead of "on" because of http://wiki.netbeans.org/FaqFontRendering and http://docs.oracle.com/javase/6/docs/technotes/guides/2d/flags.html#aaFonts System.setProperty("awt.useSystemAAFontSettings", "lcd"); // Set the Look & Feel for Swing. try { setLookAndFeel(); } catch (Throwable e) { LOGGER.error("Swing look and feel could not be loaded.", e); } // If the option is enabled, open the last edited databases, if any. if (!cli.isBlank() && Globals.prefs.getBoolean(JabRefPreferences.OPEN_LAST_EDITED) && (Globals.prefs.get(JabRefPreferences.LAST_EDITED) != null)) { // How to handle errors in the databases to open? List<String> names = Globals.prefs.getStringList(JabRefPreferences.LAST_EDITED); lastEdLoop: for (String name : names) { File fileToOpen = new File(name); for (int j = 0; j < loaded.size(); j++) { ParserResult pr = loaded.get(j); if ((pr.getFile() != null) && pr.getFile().equals(fileToOpen)) { continue lastEdLoop; } } if (fileToOpen.exists()) { ParserResult pr = JabRef.openBibFile(name, false); if (pr != null) { if (pr == ParserResult.INVALID_FORMAT) { System.out.println( Localization.lang("Error opening file") + " '" + fileToOpen.getPath() + "'"); } else if (pr != ParserResult.FILE_LOCKED) { loaded.add(pr); } } } } } GUIGlobals.init(); GUIGlobals.CURRENTFONT = new Font(Globals.prefs.get(JabRefPreferences.FONT_FAMILY), Globals.prefs.getInt(JabRefPreferences.FONT_STYLE), Globals.prefs.getInt(JabRefPreferences.FONT_SIZE)); LOGGER.debug("Initializing frame"); JabRef.jrf = new JabRefFrame(this); // Add all loaded databases to the frame: boolean first = true; List<File> postponed = new ArrayList<>(); List<ParserResult> failed = new ArrayList<>(); List<ParserResult> toOpenTab = new ArrayList<>(); if (!loaded.isEmpty()) { for (Iterator<ParserResult> i = loaded.iterator(); i.hasNext();) { ParserResult pr = i.next(); if (new LastFocusedTabPreferences(Globals.prefs).hadLastFocus(pr.getFile())) { first = true; } if (pr.isInvalid()) { failed.add(pr); i.remove(); } else if (!pr.isPostponedAutosaveFound()) { if (pr.toOpenTab()) { // things to be appended to an opened tab should be done after opening all tabs // add them to the list toOpenTab.add(pr); } else { JabRef.jrf.addParserResult(pr, first); first = false; } } else { i.remove(); postponed.add(pr.getFile()); } } } // finally add things to the currently opened tab for (ParserResult pr : toOpenTab) { JabRef.jrf.addParserResult(pr, first); first = false; } // Start auto save timer: if (Globals.prefs.getBoolean(JabRefPreferences.AUTO_SAVE)) { Globals.startAutoSaveManager(JabRef.jrf); } // If we are set to remember the window location, we also remember the maximised // state. This needs to be set after the window has been made visible, so we // do it here: if (Globals.prefs.getBoolean(JabRefPreferences.WINDOW_MAXIMISED)) { JabRef.jrf.setExtendedState(JFrame.MAXIMIZED_BOTH); } JabRef.jrf.setVisible(true); if (Globals.prefs.getBoolean(JabRefPreferences.WINDOW_MAXIMISED)) { JabRef.jrf.setExtendedState(JFrame.MAXIMIZED_BOTH); } for (ParserResult pr : failed) { String message = "<html>" + Localization.lang("Error opening file '%0'.", pr.getFile().getName()) + "<p>" + pr.getErrorMessage() + "</html>"; JOptionPane.showMessageDialog(JabRef.jrf, message, Localization.lang("Error opening file"), JOptionPane.ERROR_MESSAGE); } for (int i = 0; i < loaded.size(); i++) { if (Globals.prefs.getBoolean(JabRefPreferences.DISPLAY_KEY_WARNING_DIALOG_AT_STARTUP)) { ParserResultWarningDialog.showParserResultWarningDialog(loaded.get(i), JabRef.jrf, i); } } // After adding the databases, go through each and see if // any post open actions need to be done. For instance, checking // if we found new entry types that can be imported, or checking // if the database contents should be modified due to new features // in this version of JabRef. // Note that we have to check whether i does not go over getBasePanelCount(). // This is because importToOpen might have been used, which adds to // loaded, but not to getBasePanelCount() for (int i = 0; (i < loaded.size()) && (i < JabRef.jrf.getBasePanelCount()); i++) { ParserResult pr = loaded.get(i); BasePanel panel = JabRef.jrf.getBasePanelAt(i); OpenDatabaseAction.performPostOpenActions(panel, pr, true); } LOGGER.debug("Finished adding panels"); // If any database loading was postponed due to an autosave, schedule them // for handing now: if (!postponed.isEmpty()) { AutosaveStartupPrompter asp = new AutosaveStartupPrompter(JabRef.jrf, postponed); SwingUtilities.invokeLater(asp); } if (!loaded.isEmpty()) { new FocusRequester(JabRef.jrf.getCurrentBasePanel().mainTable); } } public static ParserResult openBibFile(String name, boolean ignoreAutosave) { // String in OpenDatabaseAction.java LOGGER.info("Opening: " + name); File file = new File(name); if (!file.exists()) { ParserResult pr = new ParserResult(null, null, null); pr.setFile(file); pr.setInvalid(true); System.err.println(Localization.lang("Error") + ": " + Localization.lang("File not found")); return pr; } try { if (!ignoreAutosave) { boolean autoSaveFound = AutoSaveManager.newerAutoSaveExists(file); if (autoSaveFound) { // We have found a newer autosave. Make a note of this, so it can be // handled after startup: ParserResult postp = new ParserResult(null, null, null); postp.setPostponedAutosaveFound(true); postp.setFile(file); return postp; } } if (!FileBasedLock.waitForFileLock(file, 10)) { System.out.println(Localization.lang("Error opening file") + " '" + name + "'. " + "File is locked by another JabRef instance."); return ParserResult.FILE_LOCKED; } Charset encoding = Globals.prefs.getDefaultEncoding(); ParserResult pr = OpenDatabaseAction.loadDatabase(file, encoding); if (pr == null) { pr = new ParserResult(null, null, null); pr.setFile(file); pr.setInvalid(true); return pr; } pr.setFile(file); if (pr.hasWarnings()) { for (String aWarn : pr.warnings()) { LOGGER.warn(aWarn); } } return pr; } catch (Throwable ex) { ParserResult pr = new ParserResult(null, null, null); pr.setFile(file); pr.setInvalid(true); pr.setErrorMessage(ex.getMessage()); ex.printStackTrace(); return pr; } } private static Optional<ParserResult> importFile(String argument) { String[] data = argument.split(","); try { if ((data.length > 1) && !"*".equals(data[1])) { System.out.println(Localization.lang("Importing") + ": " + data[0]); try { List<BibEntry> entries; if (OS.WINDOWS) { entries = Globals.importFormatReader.importFromFile(data[1], data[0], JabRef.jrf); } else { entries = Globals.importFormatReader.importFromFile(data[1], data[0].replaceAll("~", System.getProperty("user.home")), JabRef.jrf); } return Optional.of(new ParserResult(entries)); } catch (IllegalArgumentException ex) { System.err.println(Localization.lang("Unknown import format") + ": " + data[1]); return Optional.empty(); } } else { // * means "guess the format": System.out.println(Localization.lang("Importing in unknown format") + ": " + data[0]); ImportFormatReader.UnknownFormatImport importResult; if (OS.WINDOWS) { importResult = Globals.importFormatReader.importUnknownFormat(data[0]); } else { importResult = Globals.importFormatReader .importUnknownFormat(data[0].replaceAll("~", System.getProperty("user.home"))); } if (importResult == null) { System.out.println(Localization.lang("Could not find a suitable import format.")); } else { System.out.println(Localization.lang("Format used") + ": " + importResult.format); return Optional.of(importResult.parserResult); } } } catch (IOException ex) { System.err.println( Localization.lang("Error opening file") + " '" + data[0] + "': " + ex.getLocalizedMessage()); } return Optional.empty(); } /** * Will open a file (like importFile), but will also request JabRef to focus on this database * * @param argument See importFile. * @return ParserResult with setToOpenTab(true) */ private static Optional<ParserResult> importToOpenBase(String argument) { Optional<ParserResult> result = JabRef.importFile(argument); result.ifPresent(x -> x.setToOpenTab(true)); return result; } }