/** * This class provides a very basic Font Properties Management system. When this class is initiated, * the properites file "pdfviewerfontcache.properties" is read from the default application file * path. If the file cannot be found then all system fonts are read from the operating system and * are written to the "pdfviewerfontcache.properties" file. * * <p> * * <p>This class is designed to speed up the load time of the viewer application by reading already * parsed font information from the properties file. If new fonts are added to the system, the * "pdfviewerfontcache.properties" file can be deleted to trigger this class to re-read the System * fonts and re-create a new "pdfviewerfontcache.properties" properites file. * * @since 2.0 */ public class FontPropertiesManager { private static final Logger logger = Logger.getLogger(FontPropertiesManager.class.toString()); private static final String DEFAULT_HOME_DIR = ".icesoft/icepdf_viewer"; private static final String LOCK_FILE = "_syslock"; private static final String USER_FILENAME = "pdfviewerfontcache.properties"; private FontManager fontManager; // the version name, used in about dialog and start-up message String versionName = Document.getLibraryVersion(); private Properties sysProps; private PropertiesManager props; private Properties fontProps; File userHome; // the swingri home directory private File dataDir; // not to save the bookmarks and properties if lockDir == null, that is // when we do not own the lock private File lockDir; private File propertyFile; private ResourceBundle messageBundle; public FontPropertiesManager( PropertiesManager appProps, Properties sysProps, ResourceBundle messageBundle) { this.sysProps = sysProps; this.props = appProps; this.fontProps = new Properties(); this.messageBundle = messageBundle; // create a new Font Manager. this.fontManager = FontManager.getInstance(); setupHomeDir(null); recordMofifTime(); setupLock(); loadProperties(); } public synchronized void loadProperties() { if (dataDir != null) { propertyFile = new File(dataDir, USER_FILENAME); // load font properties from last invocation if (propertyFile.exists()) { try { InputStream in = new FileInputStream(propertyFile); try { fontProps.load(in); fontManager.setFontProperties(fontProps); } finally { in.close(); } } catch (IOException ex) { // check to make sure the storage relate dialogs can be shown if (getBoolean("application.showLocalStorageDialogs", true)) { Resources.showMessageDialog( null, JOptionPane.ERROR_MESSAGE, messageBundle, "fontManager.properties.title", "manager.properties.session.readError", ex); } // log the error if (logger.isLoggable(Level.WARNING)) { logger.log(Level.WARNING, "Error loading font properties cache", ex); } } catch (IllegalArgumentException e) { // propblem parsing fontProps, reread teh file setupDefaultProperties(); saveProperties(); } } // If no font data, then read font data and save the new file. else { setupDefaultProperties(); saveProperties(); } } } public synchronized void saveProperties() { if (ownLock()) { try { FileOutputStream out = new FileOutputStream(propertyFile); try { fontProps.store(out, "-- ICEpf Font properties --"); } finally { out.close(); } recordMofifTime(); } catch (IOException ex) { // check to make sure the storage relate dialogs can be shown if (getBoolean("application.showLocalStorageDialogs", true)) { Resources.showMessageDialog( null, JOptionPane.ERROR_MESSAGE, messageBundle, "fontManager.properties.title", "manager.properties.saveError", ex); } // log the error if (logger.isLoggable(Level.WARNING)) { logger.log(Level.WARNING, "Error saving font properties cache", ex); } } } } private boolean ownLock() { return lockDir != null; } private void recordMofifTime() { Calendar c = new GregorianCalendar(); c.setTime(new Date()); c.set(Calendar.MINUTE, c.get(Calendar.MINUTE) + 1); c.set(Calendar.SECOND, 0); } private void setupLock() { if (dataDir == null) { lockDir = null; } else { File dir = new File(dataDir, LOCK_FILE); if (!dir.mkdir()) { dir.delete(); if (!dir.mkdir()) { dir = null; if (getBoolean("application.showLocalStorageDialogs", true)) { Resources.showMessageDialog( null, JOptionPane.ERROR_MESSAGE, messageBundle, "fontManager.properties.title", "manager.properties.session.nolock", LOCK_FILE); } } } lockDir = dir; } } private boolean setupDefaultProperties() { fontProps = new Properties(); // create program properties with default try { // If you application needs to look at other font directories // they can be added via the readSystemFonts method. fontManager.readSystemFonts(null); fontProps = fontManager.getFontProperties(); } catch (Exception ex) { if (getBoolean("application.showLocalStorageDialogs", true)) { Resources.showMessageDialog( null, JOptionPane.ERROR_MESSAGE, messageBundle, "fontManager.properties.title", "manager.properties.session.readError", ex); } // log the error if (logger.isLoggable(Level.WARNING)) { logger.log(Level.WARNING, "Error loading default properties", ex); } return false; } return true; } private void setupHomeDir(String homeString) { if (homeString == null) { homeString = sysProps.getProperty("swingri.home"); } if (homeString != null) { dataDir = new File(homeString); } else { userHome = new File(sysProps.getProperty("user.home")); String dataDirStr = props.getString("application.datadir", DEFAULT_HOME_DIR); dataDir = new File(userHome, dataDirStr); } if (!dataDir.isDirectory()) { String path = dataDir.getAbsolutePath(); boolean create; if (props.hasUserRejectedCreatingLocalDataDir()) { create = false; } else if (getBoolean("application.showLocalStorageDialogs", true)) { create = Resources.showConfirmDialog( null, messageBundle, "fontManager.properties.title", "manager.properties.createNewDirectory", path); if (!create) props.setUserRejectedCreatingLocalDataDir(); } else { // Always create local-storage directory if show user prompt dialog setting is false. create = true; } if (!create) { dataDir = null; } else { dataDir.mkdirs(); if (!dataDir.isDirectory()) { // check to make sure that dialog should be shown on the error. if (getBoolean("application.showLocalStorageDialogs", true)) { Resources.showMessageDialog( null, JOptionPane.ERROR_MESSAGE, messageBundle, "fontManager.properties.title", "manager.properties.failedCreation", dataDir.getAbsolutePath()); } dataDir = null; } } } } public boolean getBoolean(String propertyName, boolean defaultValue) { Boolean result = getBooleanImpl(propertyName); if (result == null) { return defaultValue; } return result == Boolean.TRUE; } private Boolean getBooleanImpl(String propertyName) { String value = props.getString(propertyName); if (value != null) { Boolean result = Parse.parseBoolean(value, messageBundle); if (result != null) { return result; } props.remove(propertyName); } value = props.getString(propertyName); if (value != null) { Boolean result = Parse.parseBoolean(value, null); if (result != null) { return result; } throwBrokenDefault(propertyName, value); } return null; } private void throwBrokenDefault(String propertyName, String value) { throw new IllegalStateException( "Broken default property '" + propertyName + "' value: '" + value + "'"); } }