Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /* NOTICE: This file has been changed by Plutext Pty Ltd for use in docx4j.
   * The package name has been changed; there may also be other changes.
   * 
   * This notice is included to meet the condition in clause 4(b) of the License. 
   */
  
   /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 /* $Id: FontCache.java 743273 2009-02-11 08:41:04Z jeremias $ */
 
 package org.docx4j.fonts.fop.fonts;
 
 import java.io.File;
 import java.net.URL;
 import java.util.Map;
 
 
Fop cache (currently only used for font info caching)
 
 public final class FontCache implements Serializable {

    
Serialization Version UID. Change this value if you want to make sure the user's cache file is purged after an update.
 
     private static final long serialVersionUID = 605232520271754719L;

    
logging instance
 
     private static Logger log = LoggerFactory.getLogger(FontCache.class);

    
FOP's user directory name
 
     private static final String FOP_USER_DIR = ".docx4j";

    
font cache file path
 
     private static final String DEFAULT_CACHE_FILENAME = "fop-fonts.cache";


    
has this cache been changed since it was last read?
 
     private transient boolean changed = false;

    
change lock
 
     private final boolean[] changeLock = new boolean[1];

    
master mapping of font url -> font info. This needs to be a list, since a TTC file may contain more than 1 font.
 
     private Map/*<String, CachedFontFile>*/ fontfileMap = null;

    
mapping of font url -> file modified date (for all fonts that have failed to load)
 
     private Map failedFontMap/*<String, Long>*/ = null;

    
Default constructor
 
     public FontCache() {
         //nop
     }
 
     private static File getUserHome() {
         return toDirectory(System.getProperty("user.home"));
     }
 
     private static File getTempDirectory() {
         return toDirectory(System.getProperty("java.io.tmpdir"));
     }
 
     private static File toDirectory(String path) {
         if (path != null) {
             File dir = new File(path);
            if (dir.exists()) {
                return dir;
            }
        }
        return null;
    }

    
Returns the default font cache file.

Parameters:
forWriting true if the user directory should be created
Returns:
the default font cache file
    public static File getDefaultCacheFile(boolean forWriting) {
        File userHome = getUserHome();
        if (userHome != null) {
            File fopUserDir = new File(userHome);
            if (forWriting) {
                boolean writable = fopUserDir.canWrite();
                if (!fopUserDir.exists()) {
                    writable = fopUserDir.mkdir();
                }
                if (!writable) {
                    userHome = getTempDirectory();
                    fopUserDir = new File(userHome);
                    fopUserDir.mkdir();
                }
            }
            return new File(fopUserDir);
        }
        return new File();
    }

    
Reads the default font cache file and returns its contents.

Returns:
the font cache deserialized from the file (or null if no cache file exists or if it could not be read)
    public static FontCache load() {
        return loadFrom(getDefaultCacheFile(false));
    }

    
Reads a font cache file and returns its contents.

Parameters:
cacheFile the cache file
Returns:
the font cache deserialized from the file (or null if no cache file exists or if it could not be read)
    public static FontCache loadFrom(File cacheFile) {
        if (cacheFile.exists()) {
            try {
                if (.isTraceEnabled()) {
                    .trace("Loading font cache from " + cacheFile.getCanonicalPath());
                }
                InputStream in = new java.io.FileInputStream(cacheFile);
                in = new java.io.BufferedInputStream(in);
                ObjectInputStream oin = new ObjectInputStream(in);
                try {
                    return (FontCache)oin.readObject();
                } finally {
                    IOUtils.closeQuietly(oin);
                }
            } catch (ClassNotFoundException e) {
                //We don't really care about the exception since it's just a cache file
                .warn("Could not read font cache. Discarding font cache file. Reason: "
                        + e.getMessage());
            } catch (IOException ioe) {
                //We don't really care about the exception since it's just a cache file
                .warn("I/O exception while reading font cache (" + ioe.getMessage()
                        + "). Discarding font cache file.");
                try {
                    cacheFile.delete();
                } catch (SecurityException ex) {
                    .warn("Failed to delete font cache file: " + cacheFile.getAbsolutePath());
                }
            }
        }
        return null;
    }

    
Writes the font cache to disk.

    public void save() throws FOPException {
        saveTo(getDefaultCacheFile(true));
    }

    
Writes the font cache to disk.

Parameters:
cacheFile the file to write to
Throws:
org.docx4j.fonts.fop.apps.FOPException fop exception
    public void saveTo(File cacheFilethrows FOPException {
        synchronized () {
            if () {
                try {
                    if (.isTraceEnabled()) {
                        .trace("Writing font cache to " + cacheFile.getCanonicalPath());
                    }
                    OutputStream out = new java.io.FileOutputStream(cacheFile);
                    out = new java.io.BufferedOutputStream(out);
                    ObjectOutputStream oout = new ObjectOutputStream(out);
                    try {
                        oout.writeObject(this);
                    } finally {
                        IOUtils.closeQuietly(oout);
                    }
                } catch (IOException ioe) {
                    LogUtil.handleException(ioetrue);
                }
                 = false;
                .trace("Cache file written.");
            }
        }
    }

    
creates a key given a font info for the font mapping

Parameters:
fontInfo font info
Returns:
font cache key
    protected static String getCacheKey(EmbedFontInfo fontInfo) {
        if (fontInfo != null) {
            String embedFile = fontInfo.getEmbedFile();
            String metricsFile = fontInfo.getMetricsFile();
            return (embedFile != null) ? embedFile : metricsFile;
        }
        return null;
    }

    
cache has been updated since it was read

Returns:
if this cache has changed
    public boolean hasChanged() {
        return this.;
    }

    
is this font in the cache?

Parameters:
embedUrl font info
Returns:
boolean
    public boolean containsFont(String embedUrl) {
        return (embedUrl != null
                && getFontFileMap().containsKey(embedUrl));
    }

    
is this font info in the cache?

Parameters:
fontInfo font info
Returns:
font
    public boolean containsFont(EmbedFontInfo fontInfo) {
        return (fontInfo != null
                && getFontFileMap().containsKey(getCacheKey(fontInfo)));
    }

    
Tries to identify a File instance from an array of URLs. If there's no file URL in the array, the method returns null.

Parameters:
urls array of possible font urls
Returns:
file font file
    public static File getFileFromUrls(String[] urls) {
        for (int i = 0; i < urls.lengthi++) {
            String urlStr = urls[i];
            if (urlStr != null) {
                File fontFile = null;
                if (urlStr.startsWith("file:")) {
                    try {
                        URL url = new URL(urlStr);
                        fontFile = FileUtils.toFile(url);
                    } catch (MalformedURLException mfue) {
                        // do nothing
                    }
                }
                if (fontFile == null) {
                    fontFile = new File(urlStr);
                }
                if (fontFile.exists() && fontFile.canRead()) {
                    return fontFile;
                }
            }
        }
        return null;
    }
    private Map/*<String, CachedFontFile>*/ getFontFileMap() {
        if ( == null) {
             = new java.util.HashMap/*<String, CachedFontFile>*/();
        }
        return ;
    }

    
Adds a font info to cache

Parameters:
fontInfo font info
    public void addFont(EmbedFontInfo fontInfo) {
        String cacheKey = getCacheKey(fontInfo);
        synchronized () {
            CachedFontFile cachedFontFile;
            if (containsFont(cacheKey)) {
                cachedFontFile = (CachedFontFile)getFontFileMap().get(cacheKey);
                if (!cachedFontFile.containsFont(fontInfo)) {
                    cachedFontFile.put(fontInfo);
                }
            } else {
                // try and determine modified date
                File fontFile = getFileFromUrls(new String[]
                                     {fontInfo.getEmbedFile(), fontInfo.getMetricsFile()});
                long lastModified = (fontFile != null ? fontFile.lastModified() : -1);
                cachedFontFile = new CachedFontFile(lastModified);
                if (.isTraceEnabled()) {
                    .trace("Font added to cache: " + cacheKey);
                }
                cachedFontFile.put(fontInfo);
                getFontFileMap().put(cacheKeycachedFontFile);
                 = true;
            }
        }
    }

    
Returns a font from the cache.

Parameters:
embedUrl font info
Returns:
CachedFontFile object
    public CachedFontFile getFontFile(String embedUrl) {
        return containsFont(embedUrl) ? (CachedFontFilegetFontFileMap().get(embedUrl) : null;
    }

    
Returns the EmbedFontInfo instances belonging to a font file. If the font file was modified since it was cached the entry is removed and null is returned.

Parameters:
embedUrl the font URL
lastModified the last modified date/time of the font file
Returns:
the EmbedFontInfo instances or null if there's no cached entry or if it is outdated
    public EmbedFontInfo[] getFontInfos(String embedUrllong lastModified) {
        CachedFontFile cff = getFontFile(embedUrl);
        if (cff.lastModified() == lastModified) {
            return cff.getEmbedFontInfos();
        } else {
            removeFont(embedUrl);
            return null;
        }
    }

    
removes font from cache

Parameters:
embedUrl embed url
    public void removeFont(String embedUrl) {
        synchronized () {
            if (containsFont(embedUrl)) {
                if (.isTraceEnabled()) {
                    .trace("Font removed from cache: " + embedUrl);
                }
                getFontFileMap().remove(embedUrl);
                 = true;
            }
        }
    }

    
has this font previously failed to load?

Parameters:
embedUrl embed url
lastModified last modified
Returns:
whether this is a failed font
    public boolean isFailedFont(String embedUrllong lastModified) {
        synchronized () {
            if (getFailedFontMap().containsKey(embedUrl)) {
                long failedLastModified = ((Long)getFailedFontMap().get(embedUrl)).longValue();
                if (lastModified != failedLastModified) {
                    // this font has been changed so lets remove it
                    // from failed font map for now
                    getFailedFontMap().remove(embedUrl);
                     = true;
                }
                return true;
            } else {
                return false;
            }
        }
    }

    
Registers a failed font with the cache

Parameters:
embedUrl embed url
lastModified time last modified
    public void registerFailedFont(String embedUrllong lastModified) {
        synchronized () {
            if (!getFailedFontMap().containsKey(embedUrl)) {
                getFailedFontMap().put(embedUrlnew Long(lastModified));
                 = true;
            }
        }
    }
    private Map/*<String, Long>*/ getFailedFontMap() {
        if ( == null) {
             = new java.util.HashMap/*<String, Long>*/();
        }
        return ;
    }

    
Clears font cache
    public void clear() {
        synchronized () {
            if (.isTraceEnabled()) {
                .trace("Font cache cleared.");
            }
             = null;
             = null;
             = true;
        }
    }

    
Retrieve the last modified date/time of a URL.

Parameters:
url the URL
Returns:
the last modified date/time
    public static long getLastModified(URL url) {
        try {
            URLConnection conn = url.openConnection();
            try {
                return conn.getLastModified();
            } finally {
                //An InputStream is created even if it's not accessed, but we need to close it.
                IOUtils.closeQuietly(conn.getInputStream());
            }
        } catch (IOException e) {
            // Should never happen, because URL must be local
            .debug("IOError: " + e.getMessage());
            return 0;
        }
    }
    private static class CachedFontFile implements Serializable {
        private static final long serialVersionUID = 4524237324330578883L;

        
file modify date (if available)
        private long lastModified = -1;
        private Map/*<String, EmbedFontInfo>*/ filefontsMap = null;
        public CachedFontFile(long lastModified) {
            setLastModified(lastModified);
        }
        private Map/*<String, EmbedFontInfo>*/ getFileFontsMap() {
            if ( == null) {
                 = new java.util.HashMap/*<String, EmbedFontInfo>*/();
            }
            return ;
        }
        void put(EmbedFontInfo efi) {
            getFileFontsMap().put(efi.getPostScriptName(), efi);
        }
        public boolean containsFont(EmbedFontInfo efi) {
            return efi.getPostScriptName() != null
                    && getFileFontsMap().containsKey(efi.getPostScriptName());
        }
        public EmbedFontInfo[] getEmbedFontInfos() {
            return (EmbedFontInfo[])getFileFontsMap().values().toArray(
                    new EmbedFontInfo[getFileFontsMap().size()]);
        }

        
Gets the modified timestamp for font file (not always available)

Returns:
modified timestamp
        public long lastModified() {
            return this.;
        }

        
Gets the modified timestamp for font file (used for the purposes of font info caching)

Parameters:
lastModified modified font file timestamp
        public void setLastModified(long lastModified) {
            this. = lastModified;
        }

        

Returns:
string representation of this object
        public String toString() {
            return super.toString() + ", lastModified=" + ;
        }
    }
New to GrepCode? Check out our FAQ X