You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2006/03/21 11:24:47 UTC

svn commit: r387477 - in /xmlgraphics/fop/trunk: ./ src/documentation/content/xdocs/trunk/ src/java/org/apache/fop/apps/ src/java/org/apache/fop/hyphenation/

Author: jeremias
Date: Tue Mar 21 02:24:45 2006
New Revision: 387477

URL: http://svn.apache.org/viewcvs?rev=387477&view=rev
Log:
Made the loading of user-specified hyphenation patterns usable again and plugged it into URI resolution.
Backwards-compatibility should be maintained.
PatternParser now uses JAXP to get the SAX parser.
Moved the hyphenation pattern cache into a separate class so I can easily plug it into FopFactory later instead of having static variables.
Added serialVersionUID to HyphenationTree. Necessary because the class signature changed.
FOURIResolver does not complain about "file not found" on the log anymore since this should be done by the caller. Until now, this resulted in two log messages about the same problem on the log. "File not found" is still reported but only on level "debug" which might be helpful when tracking down a problem, but at least it's not a "WARNING" anymore.

Added:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTreeCache.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTreeResolver.java   (with props)
Modified:
    xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml
    xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/hyphenation.xml
    xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOURIResolver.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOUserAgent.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTree.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/Hyphenator.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/PatternParser.java
    xmlgraphics/fop/trunk/status.xml

Modified: xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml?rev=387477&r1=387476&r2=387477&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml (original)
+++ xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml Tue Mar 21 02:24:45 2006
@@ -67,14 +67,22 @@
       </tr>
       <tr>
         <td>base</td>
-        <td>URL</td>
+        <td>URL or directory</td>
         <td>Specifies the base URL based on which relative URL will be resolved.</td>
       </tr>
       <tr>
         <td>font-base</td>
-        <td>URL</td>
+        <td>URL or directory</td>
         <td>Specifies the base URL based on which relative font URLs will be resolved.
         If not specified defaults to the base URL above.
+        </td>
+      </tr>
+      <tr>
+        <td>hyphenation-base</td>
+        <td>URL or directory</td>
+        <td>Specifies the base URL based on which relative URLs to hyphenation pattern 
+        files will be resolved. If not specified, support for user-supplied hyphenation 
+        patterns remains disabled.
         </td>
       </tr>
       <tr>

Modified: xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/hyphenation.xml
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/hyphenation.xml?rev=387477&r1=387476&r2=387477&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/hyphenation.xml (original)
+++ xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/hyphenation.xml Tue Mar 21 02:24:45 2006
@@ -113,7 +113,7 @@
              be created from the supplied pattern(s)).</li>
             <li>Put the pattern source file(s) into a directory of your choice and 
              configure FOP to look for custom patterns in this directory, by setting the
-             <a href="configuration.html#hyphenation-dir">&lt;hyphenation-dir&gt;</a> 
+             <a href="configuration.html">&lt;hyphenation-base&gt;</a> 
              configuration option.</li>
           </ul>
         </li>

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOURIResolver.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOURIResolver.java?rev=387477&r1=387476&r2=387477&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOURIResolver.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOURIResolver.java Tue Mar 21 02:24:45 2006
@@ -21,6 +21,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -139,14 +140,17 @@
             }
         }
         
+        String effURL = absoluteURL.toExternalForm();
         try {
-            String effURL = absoluteURL.toExternalForm();
             URLConnection connection = absoluteURL.openConnection();
             connection.setAllowUserInteraction(false);
             connection.setDoInput(true);
             updateURLConnection(connection, href);
             connection.connect();
             return new StreamSource(connection.getInputStream(), effURL);
+        } catch (FileNotFoundException fnfe) {
+            //Note: This is on "debug" level since the caller is supposed to handle this
+            log.debug("File not found: " + effURL);
         } catch (java.io.IOException ioe) {
             log.error("Error with opening URL '" + href + "': " + ioe.getMessage(), ioe);
         }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOUserAgent.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOUserAgent.java?rev=387477&r1=387476&r2=387477&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOUserAgent.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/apps/FOUserAgent.java Tue Mar 21 02:24:45 2006
@@ -20,7 +20,6 @@
 
 // Java
 import java.io.File;
-import java.io.IOException;
 import java.net.URL;
 import java.net.MalformedURLException;
 import java.util.Date;
@@ -42,6 +41,7 @@
 import org.apache.fop.Version;
 import org.apache.fop.fo.ElementMapping;
 import org.apache.fop.fo.FOEventHandler;
+import org.apache.fop.hyphenation.HyphenationTreeResolver;
 import org.apache.fop.layoutmgr.LayoutManagerMaker;
 import org.apache.fop.pdf.PDFEncryptionParams;
 import org.apache.fop.render.Renderer;
@@ -85,6 +85,9 @@
     /** Registry for XML handlers */
     private XMLHandlerRegistry xmlHandlers = new XMLHandlerRegistry();
     
+    /** The resolver for user-supplied hyphenation patterns */
+    private HyphenationTreeResolver hyphResolver;
+    
     /** The base URL for all URL resolutions, especially for external-graphics */
     private String baseURL;
     
@@ -411,6 +414,14 @@
         log.debug("Initializing User Agent Configuration");
         setBaseURL(getBaseURLfromConfig("base"));
         setFontBaseURL(getBaseURLfromConfig("font-base"));
+        final String hyphBase = getBaseURLfromConfig("hyphenation-base");
+        if (hyphBase != null) {
+            this.hyphResolver = new HyphenationTreeResolver() {
+                public Source resolve(String href) {
+                    return resolveURI(href, hyphBase);
+                }
+            };
+        }
         if (userConfig.getChild("source-resolution", false) != null) {
             this.sourceResolution 
                 = userConfig.getChild("source-resolution").getValueAsFloat(
@@ -460,8 +471,6 @@
                 return cfgBaseDir;
             } catch (MalformedURLException mue) {
                 log.error("Base URL in user config is malformed!");
-            } catch (IOException ioe) {
-                log.error("Error converting relative base directory to absolute URL.");
             }
         }
         return null;
@@ -527,7 +536,7 @@
      * @return the font base URL
      */
     public String getFontBaseURL() {
-        return this.fontBaseURL != null ? this.fontBaseURL : this.baseURL ;
+        return this.fontBaseURL != null ? this.fontBaseURL : this.baseURL;
     }
 
     /**
@@ -733,6 +742,11 @@
      */
     public XMLHandlerRegistry getXMLHandlerRegistry() {
         return this.xmlHandlers;
+    }
+
+    /** @return the HyphenationTreeResolver for resolving user-supplied hyphenation patterns. */
+    public HyphenationTreeResolver getHyphenationTreeResolver() {
+        return this.hyphResolver;
     }
     
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTree.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTree.java?rev=387477&r1=387476&r2=387477&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTree.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTree.java Tue Mar 21 02:24:45 2006
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2004,2006 The Apache Software Foundation.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
 package org.apache.fop.hyphenation;
 
 import java.io.BufferedReader;
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.FileReader;
@@ -26,9 +27,12 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
+import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.HashMap;
 
+import org.xml.sax.InputSource;
+
 /**
  * This tree structure stores the hyphenation patterns in an efficient
  * way for fast lookup. It provides the provides the method to
@@ -39,6 +43,8 @@
 public class HyphenationTree extends TernaryTree 
             implements PatternConsumer, Serializable {
 
+    private static final long serialVersionUID = -7842107987915665573L;
+
     /**
      * value space: stores the interletter values
      */
@@ -112,12 +118,30 @@
 
     /**
      * Read hyphenation patterns from an XML file.
+     * @param filename the filename
+     * @throws HyphenationException In case the parsing fails
      */
     public void loadPatterns(String filename) throws HyphenationException {
+        File f = new File(filename);
+        try {
+            InputSource src = new InputSource(f.toURL().toExternalForm());
+            loadPatterns(src);
+        } catch (MalformedURLException e) {
+            throw new HyphenationException("Error converting the File '" + f + "' to a URL: " 
+                    + e.getMessage());
+        }
+    }
+
+    /**
+     * Read hyphenation patterns from an XML file.
+     * @param source the InputSource for the file
+     * @throws HyphenationException In case the parsing fails
+     */
+    public void loadPatterns(InputSource source) throws HyphenationException {
         PatternParser pp = new PatternParser(this);
         ivalues = new TernaryTree();
 
-        pp.parse(filename);
+        pp.parse(source);
 
         // patterns/values should be now in the tree
         // let's optimize a bit

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTreeCache.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTreeCache.java?rev=387477&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTreeCache.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTreeCache.java Tue Mar 21 02:24:45 2006
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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$ */
+
+package org.apache.fop.hyphenation;
+
+import java.util.Hashtable;
+import java.util.Set;
+
+/**
+ * This is a cache for HyphenationTree instances.
+ */
+public class HyphenationTreeCache {
+
+    /** Contains the cached hyphenation trees */
+    private Hashtable hyphenTrees = new Hashtable();
+    /** Used to avoid multiple error messages for the same language if a pattern file is missing. */
+    private Set missingHyphenationTrees;
+    
+    /**
+     * Looks in the cache if a hyphenation tree is available and returns it if it is found.
+     * @param lang the language
+     * @param country the country (may be null or "none")
+     * @return the HyhenationTree instance or null if it's not in the cache
+     */
+    public HyphenationTree getHyphenationTree(String lang, String country) {
+        String key = constructKey(lang, country);
+        
+        // first try to find it in the cache
+        if (hyphenTrees.containsKey(key)) {
+            return (HyphenationTree)hyphenTrees.get(key);
+        } else if (hyphenTrees.containsKey(lang)) {
+            return (HyphenationTree)hyphenTrees.get(lang);
+        } else {
+            return null;
+        }
+    }
+    
+    /**
+     * Constructs the key for the hyphenation pattern file.
+     * @param lang the language
+     * @param country the country (may be null or "none")
+     * @return the resulting key
+     */
+    public static String constructKey(String lang, String country) {
+        String key = lang;
+        // check whether the country code has been used
+        if (country != null && !country.equals("none")) {
+            key += "_" + country;
+        }
+        return key;
+    }
+    
+    /**
+     * Cache a hyphenation tree under its key.
+     * @param key the key (ex. "de_CH" or "en")
+     * @param hTree the hyphenation tree
+     */
+    public void cache(String key, HyphenationTree hTree) {
+        hyphenTrees.put(key, hTree);
+    }
+    
+    /**
+     * Notes a key to a hyphenation tree as missing.
+     * This is to avoid searching a second time for a hyphneation pattern file which is not 
+     * available.
+     * @param key the key (ex. "de_CH" or "en")
+     */
+    public void noteMissing(String key) {
+        if (missingHyphenationTrees == null) {
+            missingHyphenationTrees = new java.util.HashSet();
+        }
+        missingHyphenationTrees.add(key);
+    }
+    
+    /**
+     * Indicates whether a hyphenation file has been requested before but it wasn't available.
+     * This is to avoid searching a second time for a hyphneation pattern file which is not 
+     * available.
+     * @param key the key (ex. "de_CH" or "en")
+     * @return true if the hyphenation tree is unavailable
+     */
+    public boolean isMissing(String key) {
+        return (missingHyphenationTrees != null && missingHyphenationTrees.contains(key));
+    }
+    
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTreeCache.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTreeResolver.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTreeResolver.java?rev=387477&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTreeResolver.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTreeResolver.java Tue Mar 21 02:24:45 2006
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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$ */
+
+package org.apache.fop.hyphenation;
+
+import javax.xml.transform.Source;
+
+/**
+ * This interface is used to resolve relative URIs pointing to hyphenation tree files.
+ */
+public interface HyphenationTreeResolver {
+
+    /**
+     * Called to resolve an URI to a Source instance. The base URI needed by the URIResolver's
+     * resolve() method is defined to be implicitely available in this case. If the URI cannot
+     * be resolved, null is returned.
+     * @param href An href attribute, which may be relative or absolute.
+     * @return A Source object, or null if the href could not resolved.
+     */
+    Source resolve(String href);
+    
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/HyphenationTreeResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/Hyphenator.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/Hyphenator.java?rev=387477&r1=387476&r2=387477&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/Hyphenator.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/Hyphenator.java Tue Mar 21 02:24:45 2006
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 The Apache Software Foundation.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,15 +20,17 @@
 
 import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.ObjectInputStream;
-import java.util.Hashtable;
-import java.util.Set;
 
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.xml.sax.InputSource;
 
 /**
  * This class is the main entry point to the hyphenation package.
@@ -41,16 +43,21 @@
     /** logging instance */
     protected static Log log = LogFactory.getLog(Hyphenator.class);
 
-    /**@todo Don't use statics */
-    private static Hashtable hyphenTrees = new Hashtable();
-    /** Used to avoid multiple error messages for the same language if a pattern file is missing. */
-    private static Set missingHyphenationTrees;
-
+    private static HyphenationTreeCache hTreeCache = null;
+    
     private HyphenationTree hyphenTree = null;
     private int remainCharCount = 2;
     private int pushCharCount = 2;
-    private static boolean errorDump = false;
+    /** Enables a dump of statistics. Note: If activated content is sent to System.out! */
+    private static boolean statisticsDump = false;
 
+    /**
+     * Creates a new hyphenator.
+     * @param lang the language
+     * @param country the country (may be null or "none")
+     * @param leftMin the minimum number of characters before the hyphenation point
+     * @param rightMin the minimum number of characters after the hyphenation point
+     */
     public Hyphenator(String lang, String country, int leftMin,
                       int rightMin) {
         hyphenTree = getHyphenationTree(lang, country);
@@ -58,41 +65,64 @@
         pushCharCount = rightMin;
     }
 
+    /** @return the default (static) hyphenation tree cache */
+    public static synchronized HyphenationTreeCache getHyphenationTreeCache() {
+        if (hTreeCache == null) {
+            hTreeCache = new HyphenationTreeCache();
+        }
+        return hTreeCache;
+    }
+    
+    /**
+     * Returns a hyphenation tree for a given language and country. The hyphenation trees are
+     * cached.
+     * @param lang the language
+     * @param country the country (may be null or "none")
+     * @return the hyphenation tree
+     */
     public static HyphenationTree getHyphenationTree(String lang,
             String country) {
-        String key = lang;
-        // check whether the country code has been used
-        if (country != null && !country.equals("none")) {
-            key += "_" + country;
-        }
+        return getHyphenationTree(lang, country, null); 
+    }
+    
+    /**
+     * Returns a hyphenation tree for a given language and country. The hyphenation trees are
+     * cached.
+     * @param lang the language
+     * @param country the country (may be null or "none")
+     * @param resolver resolver to find the hyphenation files
+     * @return the hyphenation tree
+     */
+    public static HyphenationTree getHyphenationTree(String lang,
+            String country, HyphenationTreeResolver resolver) {
+        String key = HyphenationTreeCache.constructKey(lang, country);
+        HyphenationTreeCache cache = getHyphenationTreeCache();
+        
         // See if there was an error finding this hyphenation tree before
-        if (missingHyphenationTrees != null && missingHyphenationTrees.contains(key)) {
+        if (cache.isMissing(key)) {
             return null;
         }
+        
+        HyphenationTree hTree;
         // first try to find it in the cache
-        if (hyphenTrees.containsKey(key)) {
-            return (HyphenationTree)hyphenTrees.get(key);
-        }
-        if (hyphenTrees.containsKey(lang)) {
-            return (HyphenationTree)hyphenTrees.get(lang);
+        hTree = getHyphenationTreeCache().getHyphenationTree(lang, country);
+        if (hTree != null) {
+            return hTree;
         }
 
-        HyphenationTree hTree = getFopHyphenationTree(key);
+        if (resolver != null) {
+            hTree = getUserHyphenationTree(key, resolver);
+        }
         if (hTree == null) {
-            String hyphenDir = "/hyph";
-            if (hyphenDir != null) {
-                hTree = getUserHyphenationTree(key, hyphenDir);
-            }
+            hTree = getFopHyphenationTree(key);
         }
+        
         // put it into the pattern cache
         if (hTree != null) {
-            hyphenTrees.put(key, hTree);
+            cache.cache(key, hTree);
         } else {
             log.error("Couldn't find hyphenation pattern " + key);
-            if (missingHyphenationTrees == null) {
-                missingHyphenationTrees = new java.util.HashSet();
-            }
-            missingHyphenationTrees.add(key);
+            cache.noteMissing(key);
         }
         return hTree;
     }
@@ -101,12 +131,12 @@
         InputStream is = null;
         // Try to use Context Class Loader to load the properties file.
         try {
-            java.lang.reflect.Method getCCL =
-                Thread.class.getMethod("getContextClassLoader", new Class[0]);
+            java.lang.reflect.Method getCCL = Thread.class.getMethod(
+                    "getContextClassLoader", new Class[0]);
             if (getCCL != null) {
-                ClassLoader contextClassLoader =
-                    (ClassLoader)getCCL.invoke(Thread.currentThread(),
-                                               new Object[0]);
+                ClassLoader contextClassLoader = (ClassLoader)getCCL.invoke(
+                        Thread.currentThread(),
+                        new Object[0]);
                 is = contextClassLoader.getResourceAsStream("hyph/" + key
                                                             + ".hyp");
             }
@@ -122,6 +152,25 @@
         return is;
     }
 
+    private static HyphenationTree readHyphenationTree(InputStream in) {
+        HyphenationTree hTree = null;
+        try {
+            ObjectInputStream ois = new ObjectInputStream(in);
+            hTree = (HyphenationTree)ois.readObject();
+        } catch (IOException ioe) {
+            log.error("I/O error while loading precompiled hyphenation pattern file", ioe);
+        } catch (ClassNotFoundException cnfe) {
+            log.error("Error while reading hyphenation object from file", cnfe);
+        }
+        return hTree;
+    }
+    
+    /**
+     * Returns a hyphenation tree. This method looks in the resources (getResourceStream) for
+     * the hyphenation patterns.
+     * @param key the language/country key
+     * @return the hyphenation tree or null if it wasn't found in the resources
+     */
     public static HyphenationTree getFopHyphenationTree(String key) {
         HyphenationTree hTree = null;
         ObjectInputStream ois = null;
@@ -130,53 +179,66 @@
             is = getResourceStream(key);
             if (is == null) {
                 if (key.length() == 5) {
-                    is = getResourceStream(key.substring(0, 2));
+                    String lang = key.substring(0, 2);
+                    is = getResourceStream(lang);
                     if (is != null) {
-                        //log.error("Couldn't find hyphenation pattern  "
-                        //                       + key
-                        //                       + "\nusing general language pattern "
-                        //                       + key.substring(0, 2)
-                        //                       + " instead.");
+                        if (log.isDebugEnabled()) {
+                            log.debug("Couldn't find hyphenation pattern '"
+                                    + key
+                                    + "'. Using general language pattern '"
+                                    + lang
+                                    + "' instead.");
+                        }
                     } else {
-                        if (errorDump) {
-                            //log.error("Couldn't find precompiled "
-                            //                       + "fop hyphenation pattern "
-                            //                       + key + ".hyp");
+                        if (log.isDebugEnabled()) {
+                            log.debug("Couldn't find precompiled hyphenation pattern "
+                                    + lang + " in resources.");
                         }
                         return null;
                     }
                 } else {
-                    if (errorDump) {
-                        //log.error("Couldn't find precompiled "
-                        //                       + "fop hyphenation pattern "
-                        //                       + key + ".hyp");
+                    if (log.isDebugEnabled()) {
+                        log.debug("Couldn't find precompiled hyphenation pattern "
+                                               + key + " in resources");
                     }
                     return null;
                 }
             }
-            ois = new ObjectInputStream(is);
-            hTree = (HyphenationTree)ois.readObject();
-        } catch (Exception e) {
-            /**@todo proper logging please */
-            e.printStackTrace();
+            hTree = readHyphenationTree(is);
         } finally {
-            if (ois != null) {
-                try {
-                    ois.close();
-                } catch (IOException e) {
-                    //log.error("can't close hyphenation object stream");
-                }
-            }
+            IOUtils.closeQuietly(ois);
         }
         return hTree;
     }
 
     /**
-     * load tree from serialized file or xml file
+     * Load tree from serialized file or xml file
      * using configuration settings
+     * @param key language key for the requested hyphenation file
+     * @param hyphenDir base directory to find hyphenation files in
+     * @return the requested HypenationTree or null if it is not available
      */
     public static HyphenationTree getUserHyphenationTree(String key,
             String hyphenDir) {
+        final File baseDir = new File(hyphenDir);
+        HyphenationTreeResolver resolver = new HyphenationTreeResolver() {
+            public Source resolve(String href) {
+                File f = new File(baseDir, href);
+                return new StreamSource(f);
+            }
+        };
+        return getUserHyphenationTree(key, resolver);
+    }
+    
+    /**
+     * Load tree from serialized file or xml file
+     * using configuration settings
+     * @param key language key for the requested hyphenation file
+     * @param resolver resolver to find the hyphenation files
+     * @return the requested HypenationTree or null if it is not available
+     */
+    public static HyphenationTree getUserHyphenationTree(String key,
+            HyphenationTreeResolver resolver) {
         HyphenationTree hTree = null;
         // I use here the following convention. The file name specified in
         // the configuration is taken as the base name. First we try
@@ -184,98 +246,194 @@
         // we try name + ".xml", assumming a raw hyphenation pattern file.
 
         // first try serialized object
-        File hyphenFile = new File(hyphenDir, key + ".hyp");
-        if (hyphenFile.exists()) {
-            ObjectInputStream ois = null;
+        String name = key + ".hyp";
+        Source source = resolver.resolve(name);
+        if (source != null) {
             try {
-                ois = new ObjectInputStream(new BufferedInputStream(
-                            new FileInputStream(hyphenFile)));
-                hTree = (HyphenationTree)ois.readObject();
-            } catch (Exception e) {
-                log.error("Error while loading the hyphenation file", e);
-            } finally {
-                if (ois != null) {
-                    try {
-                        ois.close();
-                    } catch (IOException e) {
-                        //ignore
-                    }
+                InputStream in = null;
+                if (source instanceof StreamSource) {
+                    in = ((StreamSource) source).getInputStream();
+                }
+                if (in == null && source.getSystemId() != null) {
+                    in = new java.net.URL(source.getSystemId()).openStream();
+                } else {
+                    throw new UnsupportedOperationException("Cannot load hyphenation pattern file"
+                            + " with the supplied Source object: " + source);
+                }
+                in = new BufferedInputStream(in);
+                try {
+                    hTree = readHyphenationTree(in);
+                } finally {
+                    IOUtils.closeQuietly(in);
+                }
+                return hTree;
+            } catch (IOException ioe) {
+                if (log.isDebugEnabled()) {
+                    log.debug("I/O problem while trying to load " + name, ioe);
                 }
             }
-            return hTree;
-        } else {
+        }
 
-            // try the raw XML file
-            hyphenFile = new File(hyphenDir, key + ".xml");
-            if (hyphenFile.exists()) {
-                hTree = new HyphenationTree();
-                if (errorDump) {
-                    //log.error("reading " + hyphenDir + key
-                    //                       + ".xml");
+        // try the raw XML file
+        name = key + ".xml";
+        source = resolver.resolve(name);
+        if (source != null) {
+            hTree = new HyphenationTree();
+            try {
+                InputStream in = null;
+                if (source instanceof StreamSource) {
+                    in = ((StreamSource) source).getInputStream();
                 }
-                try {
-                    hTree.loadPatterns(hyphenFile.getPath());
-                    if (errorDump) {
-                        System.out.println("Stats: ");
-                        hTree.printStats();
-                    }
-                    return hTree;
-                } catch (HyphenationException ex) {
-                    if (errorDump) {
-                        //log.error("Can't load user patterns "
-                        //                       + "from xml file " + hyphenDir
-                        //                       + key + ".xml");
+                if (in == null) {
+                    if (source.getSystemId() != null) {
+                        in = new java.net.URL(source.getSystemId()).openStream();
+                    } else {
+                        throw new UnsupportedOperationException(
+                                "Cannot load hyphenation pattern file"
+                                    + " with the supplied Source object: " + source);
                     }
-                    return null;
                 }
-            } else {
-                if (errorDump) {
-                    //log.error("Tried to load "
-                    //                       + hyphenFile.toString()
-                    //                       + "\nCannot find compiled nor xml file for "
-                    //                       + "hyphenation pattern" + key);
+                if (!(in instanceof BufferedInputStream)) {
+                    in = new BufferedInputStream(in);
+                }
+                try {
+                    InputSource src = new InputSource(in);
+                    src.setSystemId(source.getSystemId()); 
+                    hTree.loadPatterns(src);
+                } finally {
+                    IOUtils.closeQuietly(in);
+                }
+                if (statisticsDump) {
+                    System.out.println("Stats: ");
+                    hTree.printStats();
+                }
+                return hTree;
+            } catch (HyphenationException ex) {
+                log.error("Can't load user patterns from XML file " + source.getSystemId()
+                        + ": " + ex.getMessage());
+                return null;
+            } catch (IOException ioe) {
+                if (log.isDebugEnabled()) {
+                    log.debug("I/O problem while trying to load " + name, ioe);
                 }
                 return null;
             }
+        } else {
+            if (log.isDebugEnabled()) {
+                log.debug("Could not load user hyphenation file for '" + key + "'.");
+            }
+            return null;
         }
     }
 
+    /**
+     * Hyphenates a word.
+     * @param lang the language
+     * @param country the optional country code (may be null or "none")
+     * @param resolver resolver to find the hyphenation files
+     * @param word the word to hyphenate
+     * @param leftMin the minimum number of characters before the hyphenation point
+     * @param rightMin the minimum number of characters after the hyphenation point
+     * @return the hyphenation result
+     */
     public static Hyphenation hyphenate(String lang, String country,
-                                        String word, int leftMin,
-                                        int rightMin) {
-        HyphenationTree hTree = getHyphenationTree(lang, country);
+                                        HyphenationTreeResolver resolver,
+                                        String word, 
+                                        int leftMin, int rightMin) {
+        HyphenationTree hTree = getHyphenationTree(lang, country, resolver);
         if (hTree == null) {
-            //log.error("Error building hyphenation tree for language "
-            //                       + lang);
             return null;
         }
         return hTree.hyphenate(word, leftMin, rightMin);
     }
 
+    /**
+     * Hyphenates a word.
+     * @param lang the language
+     * @param country the optional country code (may be null or "none")
+     * @param word the word to hyphenate
+     * @param leftMin the minimum number of characters before the hyphenation point
+     * @param rightMin the minimum number of characters after the hyphenation point
+     * @return the hyphenation result
+     */
     public static Hyphenation hyphenate(String lang, String country,
+                                        String word, 
+                                        int leftMin, int rightMin) {
+        return hyphenate(lang, country, null, word, leftMin, rightMin);
+    }
+
+    /**
+     * Hyphenates a word.
+     * @param lang the language
+     * @param country the optional country code (may be null or "none")
+     * @param resolver resolver to find the hyphenation files
+     * @param word the word to hyphenate
+     * @param offset the offset of the first character in the "word" character array
+     * @param len the length of the word
+     * @param leftMin the minimum number of characters before the hyphenation point
+     * @param rightMin the minimum number of characters after the hyphenation point
+     * @return the hyphenation result
+     */
+    public static Hyphenation hyphenate(String lang, String country,
+                                        HyphenationTreeResolver resolver,
                                         char[] word, int offset, int len,
                                         int leftMin, int rightMin) {
-        HyphenationTree hTree = getHyphenationTree(lang, country);
+        HyphenationTree hTree = getHyphenationTree(lang, country, resolver);
         if (hTree == null) {
-            //log.error("Error building hyphenation tree for language "
-            //                       + lang);
             return null;
         }
         return hTree.hyphenate(word, offset, len, leftMin, rightMin);
     }
 
+    /**
+     * Hyphenates a word.
+     * @param lang the language
+     * @param country the optional country code (may be null or "none")
+     * @param word the word to hyphenate
+     * @param offset the offset of the first character in the "word" character array
+     * @param len the length of the word
+     * @param leftMin the minimum number of characters before the hyphenation point
+     * @param rightMin the minimum number of characters after the hyphenation point
+     * @return the hyphenation result
+     */
+    public static Hyphenation hyphenate(String lang, String country,
+                                        char[] word, int offset, int len,
+                                        int leftMin, int rightMin) {
+        return hyphenate(lang, country, null, word, offset, len, leftMin, rightMin);
+    }
+
+    /**
+     * Sets the minimum number of characters before the hyphenation point
+     * @param min the number of characters
+     */
     public void setMinRemainCharCount(int min) {
         remainCharCount = min;
     }
 
+    /**
+     * Sets the minimum number of characters after the hyphenation point
+     * @param min the number of characters
+     */
     public void setMinPushCharCount(int min) {
         pushCharCount = min;
     }
 
+    /**
+     * Sets the language and country for the hyphenation process.
+     * @param lang the language
+     * @param country the country (may be null or "none")
+     */
     public void setLanguage(String lang, String country) {
         hyphenTree = getHyphenationTree(lang, country);
     }
 
+    /**
+     * Hyphenates a word.
+     * @param word the word to hyphenate
+     * @param offset the offset of the first character in the "word" character array
+     * @param len the length of the word
+     * @return the hyphenation result
+     */
     public Hyphenation hyphenate(char[] word, int offset, int len) {
         if (hyphenTree == null) {
             return null;
@@ -284,6 +442,11 @@
                                     pushCharCount);
     }
 
+    /**
+     * Hyphenates a word.
+     * @param word the word to hyphenate
+     * @return the hyphenation result
+     */
     public Hyphenation hyphenate(String word) {
         if (hyphenTree == null) {
             return null;

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/PatternParser.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/PatternParser.java?rev=387477&r1=387476&r2=387477&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/PatternParser.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/hyphenation/PatternParser.java Tue Mar 21 02:24:45 2006
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2004,2006 The Apache Software Foundation.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,9 +28,12 @@
 
 // Java
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.net.MalformedURLException;
 import java.util.ArrayList;
-import java.net.URL;
+
+import javax.xml.parsers.SAXParserFactory;
 
 /**
  * A SAX document handler to read and parse hyphenation patterns
@@ -72,73 +75,58 @@
         this.consumer = consumer;
     }
 
+    /**
+     * Parses a hyphenation pattern file.
+     * @param filename the filename
+     * @throws HyphenationException In case of an exception while parsing
+     */
     public void parse(String filename) throws HyphenationException {
-        InputSource uri = fileInputSource(filename);
-
+        parse(new File(filename));
+    }
+    
+    /**
+     * Parses a hyphenation pattern file.
+     * @param file the pattern file
+     * @throws HyphenationException In case of an exception while parsing
+     */
+    public void parse(File file) throws HyphenationException {
         try {
-            parser.parse(uri);
-        } catch (SAXException e) {
-            throw new HyphenationException(errMsg);
-        } catch (IOException e) {
-            throw new HyphenationException(e.getMessage());
-        } catch (NullPointerException e) {
-            throw new HyphenationException("SAX parser not available");
+            InputSource src = new InputSource(file.toURL().toExternalForm());
+            parse(src);
+        } catch (MalformedURLException e) {
+            throw new HyphenationException("Error converting the File '" + file + "' to a URL: " 
+                    + e.getMessage());
         }
     }
 
     /**
-     * creates a SAX parser, using the value of org.xml.sax.parser
-     * defaulting to org.apache.xerces.parsers.SAXParser
-     *
-     * @return the created SAX parser
+     * Parses a hyphenation pattern file.
+     * @param source the InputSource for the file
+     * @throws HyphenationException In case of an exception while parsing
      */
-    static XMLReader createParser() throws HyphenationException {
-        String parserClassName = System.getProperty("org.xml.sax.parser");
-        if (parserClassName == null) {
-            parserClassName = "org.apache.xerces.parsers.SAXParser";
-        }
-        // System.out.println("using SAX parser " + parserClassName);
-
+    public void parse(InputSource source) throws HyphenationException {
         try {
-            return (XMLReader)Class.forName(parserClassName).newInstance();
-        } catch (ClassNotFoundException e) {
-            throw new HyphenationException("Could not find "
-                                           + parserClassName);
-        } catch (InstantiationException e) {
-            throw new HyphenationException("Could not instantiate "
-                                           + parserClassName);
-        } catch (IllegalAccessException e) {
-            throw new HyphenationException("Could not access "
-                                           + parserClassName);
-        } catch (ClassCastException e) {
-            throw new HyphenationException(parserClassName
-                                           + " is not a SAX driver");
+            parser.parse(source);
+        } catch (FileNotFoundException fnfe) {
+            throw new HyphenationException("File not found: " + fnfe.getMessage());
+        } catch (IOException ioe) {
+            throw new HyphenationException(ioe.getMessage());
+        } catch (SAXException e) {
+            throw new HyphenationException(errMsg);
         }
     }
-
+    
     /**
-     * create an InputSource from a file name
-     *
-     * @param filename the name of the file
-     * @return the InputSource created
+     * Creates a SAX parser using JAXP
+     * @return the created SAX parser
      */
-    protected static InputSource fileInputSource(String filename)
-            throws HyphenationException {
-
-        /* this code adapted from James Clark's in XT */
-        File file = new File(filename);
-        String path = file.getAbsolutePath();
-        String fSep = System.getProperty("file.separator");
-        if (fSep != null && fSep.length() == 1) {
-            path = path.replace(fSep.charAt(0), '/');
-        }
-        if (path.length() > 0 && path.charAt(0) != '/') {
-            path = '/' + path;
-        }
+    static XMLReader createParser() {
         try {
-            return new InputSource(new URL("file", null, path).toString());
-        } catch (java.net.MalformedURLException e) {
-            throw new HyphenationException("unexpected MalformedURLException");
+            SAXParserFactory factory = SAXParserFactory.newInstance();
+            factory.setNamespaceAware(true);
+            return factory.newSAXParser().getXMLReader();
+        } catch (Exception e) {
+            throw new RuntimeException("Couldn't create XMLReader", e);
         }
     }
 
@@ -261,11 +249,11 @@
     }
 
     //
-    // DocumentHandler methods
+    // ContentHandler methods
     //
 
     /**
-     * Start element.
+     * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
      */
     public void startElement(String uri, String local, String raw,
                              Attributes attrs) {
@@ -293,6 +281,9 @@
         token.setLength(0);
     }
 
+    /**
+     * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
+     */
     public void endElement(String uri, String local, String raw) {
 
         if (token.length() > 0) {
@@ -328,7 +319,7 @@
     }
 
     /**
-     * Characters.
+     * @see org.xml.sax.ContentHandler#characters(char[], int, int)
      */
     public void characters(char ch[], int start, int length) {
         StringBuffer chars = new StringBuffer(length);
@@ -362,7 +353,7 @@
     //
 
     /**
-     * Warning.
+     * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
      */
     public void warning(SAXParseException ex) {
         errMsg = "[Warning] " + getLocationString(ex) + ": "
@@ -370,14 +361,14 @@
     }
 
     /**
-     * Error.
+     * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
      */
     public void error(SAXParseException ex) {
         errMsg = "[Error] " + getLocationString(ex) + ": " + ex.getMessage();
     }
 
     /**
-     * Fatal error.
+     * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
      */
     public void fatalError(SAXParseException ex) throws SAXException {
         errMsg = "[Fatal Error] " + getLocationString(ex) + ": "

Modified: xmlgraphics/fop/trunk/status.xml
URL: http://svn.apache.org/viewcvs/xmlgraphics/fop/trunk/status.xml?rev=387477&r1=387476&r2=387477&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Tue Mar 21 02:24:45 2006
@@ -27,6 +27,10 @@
 
   <changes>
     <release version="FOP Trunk">
+      <action context="Code" dev="JM" type="add">
+        Reenabled loading of user-supplied hyphenation patterns that was available in
+        FOP 0.20.5. (See "hyphenation-base" option in the user configuration)
+      </action>
       <action context="Code" dev="JM" type="fix">
         Bugfix: Certain filter combinations in PDF could lead to invalid PDFs. 
         DecodeParams were not properly handled.



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org