aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache
diff options
context:
space:
mode:
authorJeremias Maerki <jeremias@apache.org>2006-03-21 10:24:45 +0000
committerJeremias Maerki <jeremias@apache.org>2006-03-21 10:24:45 +0000
commita0b61106c184e1ef2b15343241256cceac5e6162 (patch)
tree2e1ec93c5821568d7ff619c8f2cea6ccf338570a /src/java/org/apache
parentde3b319720678e19a7ceacffa15bf36159d34706 (diff)
downloadxmlgraphics-fop-a0b61106c184e1ef2b15343241256cceac5e6162.tar.gz
xmlgraphics-fop-a0b61106c184e1ef2b15343241256cceac5e6162.zip
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. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@387477 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache')
-rw-r--r--src/java/org/apache/fop/apps/FOURIResolver.java6
-rw-r--r--src/java/org/apache/fop/apps/FOUserAgent.java22
-rw-r--r--src/java/org/apache/fop/hyphenation/HyphenationTree.java28
-rw-r--r--src/java/org/apache/fop/hyphenation/HyphenationTreeCache.java101
-rw-r--r--src/java/org/apache/fop/hyphenation/HyphenationTreeResolver.java37
-rw-r--r--src/java/org/apache/fop/hyphenation/Hyphenator.java391
-rw-r--r--src/java/org/apache/fop/hyphenation/PatternParser.java115
7 files changed, 517 insertions, 183 deletions
diff --git a/src/java/org/apache/fop/apps/FOURIResolver.java b/src/java/org/apache/fop/apps/FOURIResolver.java
index ea14a8a2d..9f5cebf8e 100644
--- a/src/java/org/apache/fop/apps/FOURIResolver.java
+++ b/src/java/org/apache/fop/apps/FOURIResolver.java
@@ -21,6 +21,7 @@ package org.apache.fop.apps;
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 @@ public class FOURIResolver
}
}
+ 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);
}
diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java
index 9612d4ae5..c03d904ff 100644
--- a/src/java/org/apache/fop/apps/FOUserAgent.java
+++ b/src/java/org/apache/fop/apps/FOUserAgent.java
@@ -20,7 +20,6 @@ package org.apache.fop.apps;
// 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.commons.logging.LogFactory;
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 @@ public class FOUserAgent {
/** 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 @@ public class FOUserAgent {
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 @@ public class FOUserAgent {
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 @@ public class FOUserAgent {
* @return the font base URL
*/
public String getFontBaseURL() {
- return this.fontBaseURL != null ? this.fontBaseURL : this.baseURL ;
+ return this.fontBaseURL != null ? this.fontBaseURL : this.baseURL;
}
/**
@@ -734,6 +743,11 @@ public class FOUserAgent {
public XMLHandlerRegistry getXMLHandlerRegistry() {
return this.xmlHandlers;
}
+
+ /** @return the HyphenationTreeResolver for resolving user-supplied hyphenation patterns. */
+ public HyphenationTreeResolver getHyphenationTreeResolver() {
+ return this.hyphResolver;
+ }
}
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) + ": "