Browse Source

FOP-2597: Allow hyphenation file without extension

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1737084 13f79535-47bb-0310-9956-ffa450edef68
pull/3/head
Simon Steiner 8 years ago
parent
commit
c3351276c2

+ 8
- 0
fop-core/src/main/java/org/apache/fop/ResourceEventProducer.java View File

@@ -159,4 +159,12 @@ public interface ResourceEventProducer extends EventProducer {
* @event.severity WARN
*/
void imageWarning(Object source, String message);

/**
* Hyphenation not found.
* @param source the event source
* @param uri the original URI of the hyphenation
* @event.severity WARN
*/
void hyphenationNotFound(Object source, String uri);
}

+ 3
- 0
fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java View File

@@ -807,6 +807,9 @@ public class FOUserAgent {
return factory.getHyphenationPatternNames();
}

public InternalResourceResolver getHyphenationResourceResolver() {
return factory.getHyphenationResourceResolver();
}
public SoftMapCache getPDFObjectCache() {
return pdfObjectCache;
}

+ 35
- 6
fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java View File

@@ -45,6 +45,7 @@ import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.fonts.FontManagerConfigurator;
import org.apache.fop.hyphenation.HyphenationTreeCache;
import org.apache.fop.hyphenation.Hyphenator;
import org.apache.fop.util.LogUtil;

/**
@@ -248,6 +249,7 @@ public class FopConfParser {
false));
}

setHyphenationBase(cfg, resourceResolver, baseURI, fopFactoryBuilder);
setHyphPatNames(cfg, fopFactoryBuilder, strict);

// prefer Renderer over IFDocumentHandler
@@ -268,19 +270,38 @@ public class FopConfParser {
configureImageLoading(cfg.getChild("image-loading", false), strict);
}


private void setHyphenationBase(Configuration cfg, ResourceResolver resourceResolver, URI baseURI,
FopFactoryBuilder fopFactoryBuilder) throws FOPException {
if (cfg.getChild("hyphenation-base", false) != null) {
try {
URI fontBase = InternalResourceResolver.getBaseURI(cfg.getChild("hyphenation-base").getValue(null));
fopFactoryBuilder.setHyphenBaseResourceResolver(
ResourceResolverFactory.createInternalResourceResolver(
baseURI.resolve(fontBase), resourceResolver));
} catch (URISyntaxException use) {
LogUtil.handleException(log, use, true);
}
} else {
fopFactoryBuilder.setHyphenBaseResourceResolver(
ResourceResolverFactory.createInternalResourceResolver(
fopFactoryBuilder.getBaseURI(), resourceResolver));
}
}

private void setHyphPatNames(Configuration cfg, FopFactoryBuilder builder, boolean strict)
throws FOPException {
Configuration[] hyphPatConfig = cfg.getChildren("hyphenation-pattern");
if (hyphPatConfig.length != 0) {
Map<String, String> hyphPatNames = new HashMap<String, String>();
for (int i = 0; i < hyphPatConfig.length; ++i) {
for (Configuration aHyphPatConfig : hyphPatConfig) {
String lang;
String country;
String filename;
StringBuffer error = new StringBuffer();
String location = hyphPatConfig[i].getLocation();
String location = aHyphPatConfig.getLocation();

lang = hyphPatConfig[i].getAttribute("lang", null);
lang = aHyphPatConfig.getAttribute("lang", null);
if (lang == null) {
addError("The lang attribute of a hyphenation-pattern configuration"
+ " element must exist (" + location + ")", error);
@@ -291,7 +312,7 @@ public class FopConfParser {
}
lang = lang.toLowerCase(Locale.getDefault());

country = hyphPatConfig[i].getAttribute("country", null);
country = aHyphPatConfig.getAttribute("country", null);
if ("".equals(country)) {
country = null;
}
@@ -304,7 +325,7 @@ public class FopConfParser {
country = country.toUpperCase(Locale.getDefault());
}

filename = hyphPatConfig[i].getValue(null);
filename = aHyphPatConfig.getValue(null);
if (filename == null) {
addError("The value of a hyphenation-pattern configuration"
+ " element may not be empty (" + location + ")", error);
@@ -316,7 +337,15 @@ public class FopConfParser {
}

String llccKey = HyphenationTreeCache.constructLlccKey(lang, country);
hyphPatNames.put(llccKey, filename);

String type = aHyphPatConfig.getAttribute("type", null);
if ("xml".equals(type)) {
hyphPatNames.put(llccKey, filename + Hyphenator.XMLTYPE);
} else if ("hyp".equals(type)) {
hyphPatNames.put(llccKey, filename + Hyphenator.HYPTYPE);
} else {
hyphPatNames.put(llccKey, filename);
}
if (log.isDebugEnabled()) {
log.debug("Using hyphenation pattern filename " + filename
+ " for lang=\"" + lang + "\""

+ 4
- 0
fop-core/src/main/java/org/apache/fop/apps/FopFactory.java View File

@@ -361,6 +361,10 @@ public final class FopFactory implements ImageContext {
return config.getTargetResolution();
}

public InternalResourceResolver getHyphenationResourceResolver() {
return config.getHyphenationResourceResolver();
}

/**
* Returns the conversion factor from pixel units to millimeters. This
* depends on the desired source resolution.

+ 22
- 0
fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java View File

@@ -33,6 +33,7 @@ import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.FallbackResolver;
import org.apache.xmlgraphics.io.ResourceResolver;

import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.layoutmgr.LayoutManagerMaker;
@@ -183,6 +184,11 @@ public final class FopFactoryBuilder {
return this;
}

public FopFactoryBuilder setHyphenBaseResourceResolver(InternalResourceResolver hyphenationResourceResolver) {
fopFactoryConfigBuilder.setHyphenationResourceResolver(hyphenationResourceResolver);
return this;
}

/**
* Sets whether to perform strict validation on the FO used.
*
@@ -329,6 +335,8 @@ public final class FopFactoryBuilder {

private URI baseURI;

private InternalResourceResolver hyphenationResourceResolver;

private boolean hasStrictFOValidation = true;

private boolean hasStrictUserValidation = FopFactoryConfig.DEFAULT_STRICT_USERCONFIG_VALIDATION;
@@ -393,6 +401,10 @@ public final class FopFactoryBuilder {
return baseURI;
}

public InternalResourceResolver getHyphenationResourceResolver() {
return hyphenationResourceResolver;
}

/** {@inheritDoc} */
public boolean validateStrictly() {
return hasStrictFOValidation;
@@ -479,6 +491,8 @@ public final class FopFactoryBuilder {

void setBaseURI(URI baseURI);

void setHyphenationResourceResolver(InternalResourceResolver hyphenationResourceResolver);

void setStrictFOValidation(boolean validateStrictly);

void setStrictUserConfigValidation(boolean validateStrictly);
@@ -528,6 +542,10 @@ public final class FopFactoryBuilder {
throwIllegalStateException();
}

public void setHyphenationResourceResolver(InternalResourceResolver hyphenationResourceResolver) {
throwIllegalStateException();
}

public void setStrictFOValidation(boolean validateStrictly) {
throwIllegalStateException();
}
@@ -603,6 +621,10 @@ public final class FopFactoryBuilder {
config.baseURI = baseURI;
}

public void setHyphenationResourceResolver(InternalResourceResolver hyphenationResourceResolver) {
config.hyphenationResourceResolver = hyphenationResourceResolver;
}

public void setStrictFOValidation(boolean validateStrictly) {
config.hasStrictFOValidation = validateStrictly;
}

+ 3
- 0
fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java View File

@@ -29,6 +29,7 @@ import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.FallbackResolver;
import org.apache.xmlgraphics.io.ResourceResolver;

import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.layoutmgr.LayoutManagerMaker;

@@ -165,6 +166,8 @@ public interface FopFactoryConfig {
/** @return the hyphenation pattern names */
Map<String, String> getHyphenationPatternNames();

InternalResourceResolver getHyphenationResourceResolver();

/**
* Controls the mechanisms that are used in the event that {@link javax.xml.transform.Source}
* used for resources couldn't be read.

+ 50
- 66
fop-core/src/main/java/org/apache/fop/hyphenation/Hyphenator.java View File

@@ -32,7 +32,9 @@ import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.ResourceEventProducer;
import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.events.EventBroadcaster;

/**
* <p>This class is the main entry point to the hyphenation package.
@@ -50,6 +52,9 @@ public final class Hyphenator {
/** Enables a dump of statistics. Note: If activated content is sent to System.out! */
private static boolean statisticsDump;

public static final String HYPTYPE = Hyphenator.class.toString() + "HYP";
public static final String XMLTYPE = Hyphenator.class.toString() + "XML";

/**
* Creates a new hyphenator.
*/
@@ -81,8 +86,13 @@ public final class Hyphenator {
* @param hyphPatNames the map with user-configured hyphenation pattern file names
* @return the hyphenation tree
*/
public static HyphenationTree getHyphenationTree(String lang,
String country, InternalResourceResolver resolver, Map hyphPatNames) {
public static HyphenationTree getHyphenationTree(String lang, String country,
InternalResourceResolver resolver, Map hyphPatNames) {
return getHyphenationTree(lang, country, resolver, hyphPatNames, null);
}

public static HyphenationTree getHyphenationTree(String lang, String country,
InternalResourceResolver resourceResolver, Map hyphPatNames, EventBroadcaster eventBroadcaster) {
String llccKey = HyphenationTreeCache.constructLlccKey(lang, country);
HyphenationTreeCache cache = getHyphenationTreeCache();

@@ -91,57 +101,6 @@ public final class Hyphenator {
return null;
}

HyphenationTree hTree = getHyphenationTree2(lang, country, resolver, hyphPatNames);

// fallback to lang only
if (hTree == null && country != null && !country.equals("none")) {
String llKey = HyphenationTreeCache.constructLlccKey(lang, null);
if (!cache.isMissing(llKey)) {
hTree = getHyphenationTree2(lang, null, resolver, hyphPatNames);
if (hTree != null && log.isDebugEnabled()) {
log.debug("Couldn't find hyphenation pattern "
+ "for lang=\"" + lang + "\",country=\"" + country + "\"."
+ " Using general language pattern "
+ "for lang=\"" + lang + "\" instead.");
}
if (hTree == null) {
// no fallback; register as missing
cache.noteMissing(llKey);
} else {
// also register for (lang,country)
cache.cache(llccKey, hTree);
}
}
}

if (hTree == null) {
// (lang,country) and (lang) tried; register as missing
cache.noteMissing(llccKey);
log.error("Couldn't find hyphenation pattern "
+ "for lang=\"" + lang + "\""
+ (country != null && !country.equals("none")
? ",country=\"" + country + "\""
: "")
+ ".");
}

return hTree;
}

/**
* 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 resourceResolver resolver to find the hyphenation files
* @param hyphPatNames the map with user-configured hyphenation pattern file names
* @return the hyphenation tree
*/
public static HyphenationTree getHyphenationTree2(String lang,
String country, InternalResourceResolver resourceResolver, Map hyphPatNames) {
String llccKey = HyphenationTreeCache.constructLlccKey(lang, country);
HyphenationTreeCache cache = getHyphenationTreeCache();

HyphenationTree hTree;
// first try to find it in the cache
hTree = getHyphenationTreeCache().getHyphenationTree(lang, country);
@@ -153,7 +112,6 @@ public final class Hyphenator {
if (key == null) {
key = llccKey;
}

if (resourceResolver != null) {
hTree = getUserHyphenationTree(key, resourceResolver);
}
@@ -161,11 +119,23 @@ public final class Hyphenator {
hTree = getFopHyphenationTree(key);
}

if (hTree == null && country != null && !country.equals("none")) {
return getHyphenationTree(lang, null, resourceResolver, hyphPatNames, eventBroadcaster);
}

// put it into the pattern cache
if (hTree != null) {
cache.cache(llccKey, hTree);
} else {
if (eventBroadcaster == null) {
log.error("Couldn't find hyphenation pattern " + llccKey);
} else {
ResourceEventProducer producer = ResourceEventProducer.Provider.get(eventBroadcaster);
String name = key.replace(HYPTYPE, "").replace(XMLTYPE, "");
producer.hyphenationNotFound(cache, name);
}
cache.noteMissing(llccKey);
}

return hTree;
}

@@ -254,22 +224,30 @@ public final class Hyphenator {

// first try serialized object
String name = key + ".hyp";
try {
InputStream in = getHyphenationTreeStream(name, resourceResolver);
if (key.endsWith(HYPTYPE)) {
name = key.replace(HYPTYPE, "");
}
if (!key.endsWith(XMLTYPE)) {
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);
InputStream in = getHyphenationTreeStream(name, resourceResolver);
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);
}
}
}

// try the raw XML file
name = key + ".xml";
if (key.endsWith(XMLTYPE)) {
name = key.replace(XMLTYPE, "");
}
hTree = new HyphenationTree();
try {
InputStream in = getHyphenationTreeStream(name, resourceResolver);
@@ -320,7 +298,13 @@ public final class Hyphenator {
public static Hyphenation hyphenate(String lang, String country,
InternalResourceResolver resourceResolver, Map hyphPatNames, String word, int leftMin,
int rightMin) {
HyphenationTree hTree = getHyphenationTree(lang, country, resourceResolver, hyphPatNames);
return hyphenate(lang, country, resourceResolver, hyphPatNames, word, leftMin, rightMin, null);
}

public static Hyphenation hyphenate(String lang, String country, InternalResourceResolver resourceResolver,
Map hyphPatNames, String word, int leftMin, int rightMin,
EventBroadcaster eventBroadcaster) {
HyphenationTree hTree = getHyphenationTree(lang, country, resourceResolver, hyphPatNames, eventBroadcaster);
if (hTree == null) {
return null;
}

+ 3
- 2
fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java View File

@@ -1432,11 +1432,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager
// on an inline or wrapper below the block level.
Hyphenation hyph = Hyphenator.hyphenate(hyphenationProperties.language.getString(),
hyphenationProperties.country.getString(),
getFObj().getUserAgent().getResourceResolver(),
getFObj().getUserAgent().getHyphenationResourceResolver(),
getFObj().getUserAgent().getHyphenationPatternNames(),
sbChars.toString(),
hyphenationProperties.hyphenationRemainCharacterCount.getValue(),
hyphenationProperties.hyphenationPushCharacterCount.getValue());
hyphenationProperties.hyphenationPushCharacterCount.getValue(),
getFObj().getUserAgent().getEventBroadcaster());
// They hyph structure contains the information we need
// Now start from prev: reset to that position, ask that LM to get
// a Position for the first hyphenation offset. If the offset isn't in

+ 1
- 0
fop-core/src/main/resources/org/apache/fop/ResourceEventProducer.xml View File

@@ -30,4 +30,5 @@
<message key="cannotDeleteTempFile">Temporary file could not be deleted: {tempFile}</message>
<message key="catalogResolverNotFound">Catalog resolver not found along the classpath</message>
<message key="catalogResolverNotCreated">Error creating the catalog resolver: {message}</message>
<message key="hyphenationNotFound">Hyphenation pattern not found.[ URI: {uri}.]</message>
</catalogue>

+ 71
- 0
fop-core/src/test/java/org/apache/fop/HyphenationTestCase.java View File

@@ -0,0 +1,71 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */
package org.apache.fop;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.hyphenation.Hyphenation;
import org.apache.fop.hyphenation.HyphenationException;
import org.apache.fop.hyphenation.HyphenationTree;
import org.apache.fop.hyphenation.Hyphenator;

public class HyphenationTestCase {

@Test
public void testHyphenator() {
File f = new File("test/resources/fop");
InternalResourceResolver resourceResolver = ResourceResolverFactory.createDefaultInternalResourceResolver(
f.toURI());
Hyphenation hyph = Hyphenator.hyphenate("fr.xml" + Hyphenator.XMLTYPE, null, resourceResolver, null,
"hello", 0, 0);
assertEquals(hyph.toString(), "-hel-lo");
}

@Test
public void testHyphenatorBinary() throws HyphenationException, IOException {
File f = File.createTempFile("hyp", "fop");
f.delete();
f.mkdir();
InternalResourceResolver resourceResolver = ResourceResolverFactory.createDefaultInternalResourceResolver(
f.toURI());

HyphenationTree hTree = new HyphenationTree();
hTree.loadPatterns(new File("test/resources/fop/fr.xml").getAbsolutePath());
File hyp = new File(f, "fr.hyp");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(hyp));
out.writeObject(hTree);
out.close();

Hyphenation hyph = Hyphenator.hyphenate("fr.hyp" + Hyphenator.HYPTYPE, null, resourceResolver, null,
"oello", 0, 0);
assertEquals(hyph.toString(), "oel-lo");

hyp.delete();
f.delete();
}
}

+ 5
- 0
fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java View File

@@ -27,6 +27,7 @@ import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.FallbackResolver;
import org.apache.xmlgraphics.io.ResourceResolver;

import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.layoutmgr.LayoutManagerMaker;

@@ -132,6 +133,10 @@ public final class MutableConfig implements FopFactoryConfig {
return delegate.getHyphenationPatternNames();
}

public InternalResourceResolver getHyphenationResourceResolver() {
return delegate.getHyphenationResourceResolver();
}

public FallbackResolver getFallbackResolver() {
return delegate.getFallbackResolver();
}

+ 8
- 0
fop-core/src/test/java/org/apache/fop/events/EventProcessingTestCase.java View File

@@ -158,4 +158,12 @@ public class EventProcessingTestCase {
doTest("region-body_overflow.fo", BlockLevelEventProducer.class.getName() + ".regionOverflow",
params);
}

@Test
public void testHyphenationNotFound() throws Exception {
Map<String, Object> noParams = Collections.emptyMap();
doTest(BASE_DIR.resolve("hyphenation.fo").toURL().openStream(),
new File("test/events/hyphenationfop.xconf").toURI(),
ResourceEventProducer.class.getName() + ".hyphenationNotFound", MimeConstants.MIME_PDF, noParams);
}
}

+ 17
- 0
fop/test/events/hyphenation.fo View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" hyphenate="true" language="fr">

<fo:layout-master-set>
<fo:simple-page-master master-name="simple" page-height="27.9cm" page-width="21.6cm">
<fo:region-body />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simple">
<fo:flow flow-name="xsl-region-body">

<fo:block font-size="30pt">Text should have hyphenation:</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>

+ 6
- 0
fop/test/events/hyphenationfop.xconf View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<fop version="1.0">

<hyphenation-pattern lang="fr" type="xml">file:///doesntexist</hyphenation-pattern>

</fop>

+ 16
- 0
fop/test/resources/fop/fr.xml View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<hyphenation-info>
<hyphen-min before="2" after="3"/>

<exceptions>
</exceptions>

<classes>

</classes>
<patterns>
1he
1lo
</patterns>

</hyphenation-info>

Loading…
Cancel
Save