diff options
Diffstat (limited to 'src/java/org/apache/fop/hyphenation')
5 files changed, 494 insertions, 178 deletions
diff --git a/src/java/org/apache/fop/hyphenation/HyphenationTree.java b/src/java/org/apache/fop/hyphenation/HyphenationTree.java index a726d9501..d67405c93 100644 --- a/src/java/org/apache/fop/hyphenation/HyphenationTree.java +++ b/src/java/org/apache/fop/hyphenation/HyphenationTree.java @@ -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.IOException; 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 @@ import java.util.HashMap; public class HyphenationTree extends TernaryTree implements PatternConsumer, Serializable { + private static final long serialVersionUID = -7842107987915665573L; + /** * value space: stores the interletter values */ @@ -112,12 +118,30 @@ public class HyphenationTree extends TernaryTree /** * 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 diff --git a/src/java/org/apache/fop/hyphenation/HyphenationTreeCache.java b/src/java/org/apache/fop/hyphenation/HyphenationTreeCache.java new file mode 100644 index 000000000..df1ae590c --- /dev/null +++ b/src/java/org/apache/fop/hyphenation/HyphenationTreeCache.java @@ -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)); + } + +} diff --git a/src/java/org/apache/fop/hyphenation/HyphenationTreeResolver.java b/src/java/org/apache/fop/hyphenation/HyphenationTreeResolver.java new file mode 100644 index 000000000..65c8da5b8 --- /dev/null +++ b/src/java/org/apache/fop/hyphenation/HyphenationTreeResolver.java @@ -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); + +} diff --git a/src/java/org/apache/fop/hyphenation/Hyphenator.java b/src/java/org/apache/fop/hyphenation/Hyphenator.java index 4d4a1d03e..b455ec74f 100644 --- a/src/java/org/apache/fop/hyphenation/Hyphenator.java +++ b/src/java/org/apache/fop/hyphenation/Hyphenator.java @@ -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 @@ package org.apache.fop.hyphenation; 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 @@ public class Hyphenator { /** 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 @@ public class Hyphenator { 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 @@ public class Hyphenator { 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 @@ public class Hyphenator { 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 @@ public class Hyphenator { 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 @@ public class Hyphenator { // 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 @@ public class Hyphenator { pushCharCount); } + /** + * Hyphenates a word. + * @param word the word to hyphenate + * @return the hyphenation result + */ public Hyphenation hyphenate(String word) { if (hyphenTree == null) { return null; diff --git a/src/java/org/apache/fop/hyphenation/PatternParser.java b/src/java/org/apache/fop/hyphenation/PatternParser.java index bde436f82..56670fd23 100644 --- a/src/java/org/apache/fop/hyphenation/PatternParser.java +++ b/src/java/org/apache/fop/hyphenation/PatternParser.java @@ -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 @@ import org.xml.sax.Attributes; // 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 @@ public class PatternParser extends DefaultHandler implements PatternConsumer { 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 @@ public class PatternParser extends DefaultHandler implements PatternConsumer { } // - // 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 @@ public class PatternParser extends DefaultHandler implements PatternConsumer { 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 @@ public class PatternParser extends DefaultHandler implements PatternConsumer { } /** - * 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 @@ public class PatternParser extends DefaultHandler implements PatternConsumer { // /** - * Warning. + * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException) */ public void warning(SAXParseException ex) { errMsg = "[Warning] " + getLocationString(ex) + ": " @@ -370,14 +361,14 @@ public class PatternParser extends DefaultHandler implements PatternConsumer { } /** - * 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) + ": " |