org.mapfish.print.config.Config Maven / Gradle / Ivy
/*
* Copyright (C) 2013 Camptocamp
*
* This file is part of MapFish Print
*
* MapFish Print is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MapFish Print is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MapFish Print. If not, see .
*/
package org.mapfish.print.config;
//import org.apache.commons.httpclient.HostConfiguration;
import com.codahale.metrics.MetricRegistry;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.json.JSONException;
import org.json.JSONWriter;
import org.mapfish.print.Constants;
import org.mapfish.print.InvalidValueException;
import org.mapfish.print.PDFUtils;
import org.mapfish.print.ThreadResources;
import org.mapfish.print.config.layout.Layout;
import org.mapfish.print.config.layout.Layouts;
import org.mapfish.print.map.MapTileTask;
import org.mapfish.print.map.readers.MapReaderFactoryFinder;
import org.mapfish.print.map.readers.WMSServiceInfo;
import org.mapfish.print.output.OutputFactory;
import org.pvalsecc.concurrent.OrderedResultsExecutor;
import java.io.Closeable;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketException;
import java.net.URI;
import java.net.UnknownHostException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.TreeSet;
//import org.mapfish.print.output.OutputFormat;
/**
* Bean mapping the root of the configuration file.
*/
public class Config implements Closeable {
public static final Logger LOGGER = Logger.getLogger(Config.class);
private Layouts layouts;
private TreeSet dpis;
private TreeSet scales;
private String maxSvgWidth = "";
private String maxSvgHeight = "";
private double maxSvgW = Double.MAX_VALUE;
private double maxSvgH = Double.MAX_VALUE;
private Float tmsDefaultOriginX = null;
private Float tmsDefaultOriginY = null;
private boolean reloadConfig = false;
private boolean ignoreCapabilities = false;
private int maxPrintTimeBeforeWarningInSeconds = 30;
private int printTimeoutMinutes = 5;
private ThreadResources threadResources;
private boolean integerSvg = true;
private List overlayLayers = null;
private TreeSet fonts = null;
private List hosts = new ArrayList();
private HashMap localHostForward;
private TreeSet headers;
private TreeSet keys;
private int globalParallelFetches = 5;
private int perHostParallelFetches = 5;
private int socketTimeout = 40*60*1000; // 40 minutes //3*60*1000;
private int connectionTimeout = 40*60*1000; // 40 minutes //30*1000;
private boolean tilecacheMerging = false;
private boolean disableScaleLocking = false;
private List security = Collections.emptyList();
private String outputFilename = "mapfish-print.pdf";
/**
* How much of the asked map we tolerate to be outside of the printed area.
* Used only in case of bbox printing (use by the PrintAction JS component).
*/
private static final double BEST_SCALE_TOLERANCE = 0.98;
private TreeSet formats; // private int svgMaxWidth = -1; private int svgMaxHeight = -1;
private OutputFactory outputFactory;
private MapReaderFactoryFinder mapReaderFactoryFinder;
private String brokenUrlPlaceholder = Constants.ImagePlaceHolderConstants.THROW;
private String proxyBaseUrl;
private MetricRegistry metricRegistry;
public Config() {
hosts.add(new LocalHostMatcher());
}
public void setOutputFactory(OutputFactory outputFactory) {
this.outputFactory = outputFactory;
}
public Layout getLayout(String name) {
return layouts.get(name);
}
public void setLayouts(Layouts layouts) {
this.layouts = layouts;
}
public void setDpis(TreeSet dpis) {
this.dpis = dpis;
}
public void setMaxSvgWidth(String maxSvgWidth) {
this.maxSvgWidth = maxSvgWidth;
this.maxSvgW = Double.parseDouble(maxSvgWidth);
}
public String getMaxSvgWidth() {
return this.maxSvgWidth;
}
public void setMaxSvgHeight(String maxSvgHeight) {
this.maxSvgHeight = maxSvgHeight;
this.maxSvgH = Double.parseDouble(maxSvgHeight);
}
public String getMaxSvgHeight() {
return this.maxSvgHeight;
}
public double getMaxSvgW() {
return this.maxSvgW;
}
public double getMaxSvgH() {
return this.maxSvgH;
}
public TreeSet getDpis() {
return dpis;
}
public void printClientConfig(JSONWriter json) throws JSONException {
json.key("scales");
json.array();
for (Double scale : scales) {
json.object();
json.key("name").value("1:" + NumberFormat.getIntegerInstance().format(scale));
json.key("value").value(scale.toString());
json.endObject();
}
json.endArray();
json.key("dpis");
json.array();
for (Integer dpi : dpis) {
json.object();
json.key("name").value(dpi.toString());
json.key("value").value(dpi.toString());
json.endObject();
}
json.endArray();
json.key("outputFormats");
json.array();
if (outputFactory != null) {
for (String format : outputFactory.getSupportedFormats(this)) {
json.object();
json.key("name").value(format);
json.endObject();
}
}
json.endArray();
json.key("layouts");
json.array();
ArrayList sortedLayouts = new ArrayList();
sortedLayouts.addAll(layouts.keySet());
Collections.sort(sortedLayouts);
for (int i = 0; i < sortedLayouts.size(); i++) {
String key = sortedLayouts.get(i);
json.object();
json.key("name").value(key);
layouts.get(key).printClientConfig(json);
json.endObject();
}
json.endArray();
}
public void setScales(TreeSet scales) {
// it is common for the config.yaml file to have integers only in the file
this.scales = new TreeSet();
for (Number scale : scales) {
this.scales.add(scale.doubleValue());
}
}
public boolean isScalePresent(double targetScale) {
for (double scale : scales) {
if (Math.abs(scale - targetScale) < 0.001) {
return true;
}
}
return false;
}
public void setHosts(List hosts) {
this.hosts = hosts;
}
public void setFonts(TreeSet fonts) {
this.fonts = fonts;
}
public TreeSet getFonts() {
return fonts;
}
public void setKeys(TreeSet keys) {
this.keys = keys;
}
public TreeSet getKeys() {
TreeSet k = keys;
if(k == null) k = new TreeSet();
return k;
}
/**
* Make sure an URI is authorized
*/
public boolean validateUri(URI uri) throws UnknownHostException, SocketException, MalformedURLException {
for (int i = 0; i < hosts.size(); i++) {
HostMatcher matcher = hosts.get(i);
if (matcher.validate(uri)) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("URI [" + uri + "] accepted by: " + matcher);
}
return true;
}
}
return false;
}
/**
* Called just after the config has been loaded to check it is valid.
*
* @throws InvalidValueException When there is a problem
*/
public void validate() {
if (this.threadResources == null) {
throw new IllegalStateException("Config was not configured with a threadResources object. Check spring configuration file " +
"and make sure there is a ThreadResources bean");
}
if (layouts == null) throw new InvalidValueException("layouts", "null");
layouts.validate();
if (dpis == null) throw new InvalidValueException("dpis", "null");
if (dpis.size() < 1) throw new InvalidValueException("dpis", "[]");
if (scales == null) throw new InvalidValueException("scales", "null");
if (scales.size() < 1) throw new InvalidValueException("scales", "[]");
if (!(scales.iterator().next() instanceof Double)) throw new Error("scales should be converted to Doubles");
if (hosts == null) throw new InvalidValueException("hosts", "null");
if (hosts.size() < 1) throw new InvalidValueException("hosts", "[]");
if (globalParallelFetches < 1) {
throw new InvalidValueException("globalParallelFetches", globalParallelFetches);
}
if (perHostParallelFetches < 1) {
throw new InvalidValueException("perHostParallelFetches", perHostParallelFetches);
}
if (socketTimeout < 0) {
throw new InvalidValueException("socketTimeout", socketTimeout);
}
if (connectionTimeout < 0) {
throw new InvalidValueException("connectionTimeout", connectionTimeout);
}
for (Key key : getKeys()) {
key.validate();
}
}
/**
* @return The first scale that is bigger or equal than the target.
*/
public double getBestScale(double target) {
if (this.disableScaleLocking) {
return target;
}
else {
double finalTarget = target * BEST_SCALE_TOLERANCE;
for (double scale : scales) {
if (scale >= finalTarget) {
return scale;
}
}
return scales.last();
}
}
public OrderedResultsExecutor getMapRenderingExecutor() {
return this.threadResources.getMapRenderingExecutor();
}
/**
* Stop all the threads and stuff used for this config.
*/
public synchronized void close() {
WMSServiceInfo.clearCache();
}
public void setGlobalParallelFetches(int globalParallelFetches) {
this.globalParallelFetches = globalParallelFetches;
}
public void setPerHostParallelFetches(int perHostParallelFetches) {
this.perHostParallelFetches = perHostParallelFetches;
System.getProperties().setProperty("http.maxConnections", Integer.toString(perHostParallelFetches));
}
/**
* Get or create the http client to be used to fetch all the map data.
*/
public HttpClient getHttpClient(URI uri) {
MultiThreadedHttpConnectionManager connectionManager = getConnectionManager();
HttpClient httpClient = new HttpClient(connectionManager);
// httpclient is a bit pesky about loading everything in memory...
// disabling the warnings.
Logger.getLogger(HttpMethodBase.class).setLevel(Level.ERROR);
// configure proxies for URI
ProxySelector selector = ProxySelector.getDefault();
List proxyList = selector.select(uri);
Proxy proxy = proxyList.get(0);
if (!proxy.equals(Proxy.NO_PROXY)) {
InetSocketAddress socketAddress = (InetSocketAddress) proxy.address();
String hostName = socketAddress.getHostName();
int port = socketAddress.getPort();
httpClient.getHostConfiguration().setProxy(hostName, port);
}
for(SecurityStrategy sec : security)
if(sec.matches(uri)) {
sec.configure(uri, httpClient);
break;
}
return httpClient;
}
private MultiThreadedHttpConnectionManager getConnectionManager() {
return this.threadResources.getConnectionManager();
}
public void setTilecacheMerging(boolean tilecacheMerging) {
this.tilecacheMerging = tilecacheMerging;
}
public boolean isTilecacheMerging() {
return tilecacheMerging;
}
public void setDisableScaleLocking(boolean disableScaleLocking) {
this.disableScaleLocking = disableScaleLocking;
}
public boolean isDisableScaleLocking() {
return disableScaleLocking;
}
public void setSocketTimeout(int socketTimeout) {
this.socketTimeout = socketTimeout;
}
public void setConnectionTimeout(int connectionTimeout) {
this.connectionTimeout = connectionTimeout;
}
public String getOutputFilename(String layoutName) {
Layout layout = layouts.get(layoutName);
String name = null;
if(layout != null) {
name = layout.getOutputFilename();
if (name != null) {
name = PDFUtils.getValueFromString(name); // get the string if it has ${now} or ${now DATEFORMAT} in it
}
}
return name == null ? outputFilename : name;
}
public String getOutputFilename() {
return outputFilename;
}
public void setOutputFilename(String outputFilename) {
this.outputFilename = outputFilename;
}
public TreeSet getFormats() {
if(formats == null) return new TreeSet();
return formats;
}
public void setFormats(TreeSet formats) {
this.formats = formats;
}
public void setOverlayLayers(List overlayLayers) {
this.overlayLayers = overlayLayers;
}
public List getOverlayLayers() {
return overlayLayers;
}
/**
* @return the integerSvg true if for example MapServer 5.6 or earlier is used where integers are put into the SVG
*/
public boolean getIntegerSvg() {
return integerSvg;
}
/**
* @param integerSvg the integerSvg to set
*/
public void setIntegerSvg(boolean integerSvg) {
this.integerSvg = integerSvg;
}
/**
* @return the reloadConfig
*/
public boolean getReloadConfig() {
return reloadConfig;
}
/**
* @param reloadConfig the reloadConfig to set
*/
public void setReloadConfig(boolean reloadConfig) {
this.reloadConfig = reloadConfig;
}
public void setSecurity(List security) {
this.security = security;
}
public void setMapReaderFactoryFinder(
MapReaderFactoryFinder mapReaderFactoryFinder) {
this.mapReaderFactoryFinder = mapReaderFactoryFinder;
}
public MapReaderFactoryFinder getMapReaderFactoryFinder() {
return mapReaderFactoryFinder;
}
public void setLocalHostForward(HashMap localHostForward) {
this.localHostForward = localHostForward;
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
}
public boolean localHostForwardIsHttps2http() {
if (localHostForward != null) {
Object https2http = localHostForward.get("https2http");
if (https2http != null && https2http instanceof Boolean) {
return (Boolean)https2http;
}
}
return false;
}
public boolean localHostForwardIsFrom(String host) {
if (localHostForward != null) {
Object from = localHostForward.get("from");
if (from != null && from instanceof List) {
return ((List)from).indexOf(host) >= 0;
}
}
return false;
}
public void setHeaders(TreeSet headers) {
this.headers = headers;
}
public TreeSet getHeaders() {
return this.headers;
}
public void setBrokenUrlPlaceholder(String brokenUrlPlaceholder) {
this.brokenUrlPlaceholder = brokenUrlPlaceholder;
}
public String getBrokenUrlPlaceholder() {
return brokenUrlPlaceholder;
}
/**
* Get the url of the proxy that resides between the servlet and the internet.
*
* This method may return null if there is no proxy between the servlet and the internet.
*
* @return the url of the proxy that resides between the servlet and the internet.
*/
public String getProxyBaseUrl() {
return proxyBaseUrl;
}
/**
* Set the url of the proxy that resides between the servlet and the internet.
*
* This is an optional parameter as there may not be a proxy.
*
* @param proxyBaseUrl the url of the proxy as seen from the internet.
*/
public void setProxyBaseUrl(String proxyBaseUrl) {
this.proxyBaseUrl = proxyBaseUrl;
}
/**
* Specify the default x - origin used by TMS map reader. If null then the value will be derived from maxExtent.
*/
public Float getTmsDefaultOriginX() {
return tmsDefaultOriginX;
}
/**
* Specify the default x - origin used by TMS map reader. If null then the value will be derived from maxExtent.
*/
public void setTmsDefaultOriginX(Float tmsDefaultOriginX) {
this.tmsDefaultOriginX = tmsDefaultOriginX;
}
/**
* Specify the default y - origin used by TMS map reader. If null then the value will be derived from maxExtent.
*/
public Float getTmsDefaultOriginY() {
return tmsDefaultOriginY;
}
/**
* Specify the default y - origin used by TMS map reader. If null then the value will be derived from maxExtent.
*/
public void setTmsDefaultOriginY(Float tmsDefaultOriginY) {
this.tmsDefaultOriginY = tmsDefaultOriginY;
}
public void setThreadResources(ThreadResources threadResources) {
this.threadResources = threadResources;
}
public boolean isIgnoreCapabilities() {
return ignoreCapabilities;
}
public void setIgnoreCapabilities(boolean ignoreCapabilities) {
this.ignoreCapabilities = ignoreCapabilities;
}
public int getMaxPrintTimeBeforeWarningInSeconds() {
return maxPrintTimeBeforeWarningInSeconds;
}
public int getPrintTimeoutMinutes() {
return printTimeoutMinutes;
}
public void setPrintTimeoutMinutes(int printTimeoutMinutes) {
this.printTimeoutMinutes = printTimeoutMinutes;
}
public void setMaxPrintTimeBeforeWarningInSeconds(int maxPrintTimeBeforeWarningInSeconds) {
this.maxPrintTimeBeforeWarningInSeconds = maxPrintTimeBeforeWarningInSeconds;
}
public void setMetricRegistry(MetricRegistry metricRegistry) {
this.metricRegistry = metricRegistry;
}
public MetricRegistry getMetricRegistry() {
return metricRegistry;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy