All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mapfish.print.servlet.ServletMapPrinterFactory Maven / Gradle / Ivy

package org.mapfish.print.servlet;

import com.google.common.base.Optional;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.vividsolutions.jts.util.Assert;
import org.mapfish.print.MapPrinter;
import org.mapfish.print.MapPrinterFactory;
import org.mapfish.print.servlet.fileloader.ConfigFileLoaderManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.channels.ClosedByInterruptException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct;

/**
 * A {@link org.mapfish.print.MapPrinterFactory} that reads configuration from files and uses servlet's methods for resolving
 * the paths to the files.
 * 

*/ public class ServletMapPrinterFactory implements MapPrinterFactory { private static final Logger LOGGER = LoggerFactory.getLogger(ServletMapPrinterFactory.class); /** * The name of the default app. This is always required to be one of the apps that are registered. */ public static final String DEFAULT_CONFIGURATION_FILE_KEY = "default"; @Autowired private ApplicationContext applicationContext; @Autowired private ConfigFileLoaderManager configFileLoader; private Map configurationFiles = new HashMap(); private final Map printers = Maps.newConcurrentMap(); private final HashMap configurationFileLastModifiedTimes = new HashMap(); @PostConstruct private void validateConfigurationFiles() { if (!this.configurationFiles.containsKey(DEFAULT_CONFIGURATION_FILE_KEY)) { throw new BeanCreationException(getClass().getName() + " requires that one of the configurationFiles is called '" + DEFAULT_CONFIGURATION_FILE_KEY + "'"); } for (URI file : this.configurationFiles.values()) { Assert.isTrue(this.configFileLoader.isAccessible(file), file + " does not exist or is not accessible."); } } @Override public final synchronized MapPrinter create(@Nullable final String app) throws NoSuchAppException { String finalApp = app; if (app == null) { finalApp = DEFAULT_CONFIGURATION_FILE_KEY; } URI configFile = this.configurationFiles.get(finalApp); if (configFile == null) { throw new NoSuchAppException("There is no configurationFile registered in the " + getClass().getName() + " bean with the " + "id: " + "'" + finalApp + "'"); } final long lastModified; if (this.configurationFileLastModifiedTimes.containsKey(finalApp)) { lastModified = this.configurationFileLastModifiedTimes.get(finalApp); } else { lastModified = 0L; } MapPrinter printer = this.printers.get(finalApp); Optional configFileLastModified = this.configFileLoader.lastModified(configFile); if (configFileLastModified.isPresent() && configFileLastModified.get() > lastModified) { // file modified, reload it LOGGER.info("Configuration file modified. Reloading..."); this.printers.remove(finalApp); printer = null; } if (printer == null) { if (configFileLastModified.isPresent()) { this.configurationFileLastModifiedTimes.put(finalApp, configFileLastModified.get()); } try { LOGGER.info("Loading configuration file: " + configFile); printer = this.applicationContext.getBean(MapPrinter.class); byte[] bytes = this.configFileLoader.loadFile(configFile); printer.setConfiguration(configFile, bytes); this.printers.put(finalApp, printer); } catch (ClosedByInterruptException e) { // because of a bug in the JDK, the interrupted status might not be set // when throwing a ClosedByInterruptException. so, we do it manually. // see also http://bugs.java.com/view_bug.do?bug_id=7043425 Thread.currentThread().interrupt(); LOGGER.error(String.format( "Error occurred while reading configuration file '%s'", configFile), e); throw new RuntimeException(String.format( "Error occurred while reading configuration file '%s': ", configFile), e); } catch (Throwable e) { LOGGER.error(String.format( "Error occurred while reading configuration file '%s'", configFile), e); throw new RuntimeException(String.format( "Error occurred while reading configuration file '%s': ", configFile), e); } } return printer; } @Override public final Set getAppIds() { return this.configurationFiles.keySet(); } /** * The setter for setting configuration file. It will convert the value to a URI. * * @param configurationFiles the configuration file map. */ public final void setConfigurationFiles(final Map configurationFiles) throws URISyntaxException { this.configurationFiles.clear(); this.configurationFileLastModifiedTimes.clear(); for (Map.Entry entry : configurationFiles.entrySet()) { if (!entry.getValue().contains(":/")) { // assume is a file this.configurationFiles.put(entry.getKey(), new File(entry.getValue()).toURI()); } else { this.configurationFiles.put(entry.getKey(), new URI(entry.getValue())); } } if (this.configFileLoader != null) { this.validateConfigurationFiles(); } } /** * Set a single directory that contains one or more subdirectories, each one that contains a config.yaml file will * be considered a print app. * * This can be called multiple times and each directory will add to the apps found in the other directories. However * the appId is based on the directory names so if there are 2 directories with the same name the second will overwrite the * first encounter. * * @param directory the root directory containing the sub-app-directories. This must resolve to a file with the */ public final void setAppsRootDirectory(final String directory) throws URISyntaxException { final Iterable children; if (!directory.contains(":/")) { children = Files.fileTreeTraverser().children(new File(directory)); } else { final Optional fileOptional = this.configFileLoader.toFile(new URI(directory)); if (fileOptional.isPresent()) { children = Files.fileTreeTraverser().children(fileOptional.get()); } else { throw new IllegalArgumentException(directory + " does not refer to a file on the current system."); } } for (File child : children) { final File configFile = new File(child, "config.yaml"); if (configFile.exists()) { this.configurationFiles.put(child.getName(), configFile.toURI()); } } if (this.configurationFiles.isEmpty()) { throw new IllegalArgumentException(directory + " is an emptry directory. There must be at least one subdirectory " + "containing a config.yaml file"); } // ensure there is a "default" app if (!this.configurationFiles.containsKey(DEFAULT_CONFIGURATION_FILE_KEY)) { final String next = this.configurationFiles.keySet().iterator().next(); final URI uri = this.configurationFiles.get(next); this.configurationFiles.put(DEFAULT_CONFIGURATION_FILE_KEY, uri); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy