package org.mapfish.print.config;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.geotools.styling.AbstractStyleVisitor;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.LineSymbolizer;
import org.geotools.styling.PointPlacement;
import org.geotools.styling.PointSymbolizer;
import org.geotools.styling.PolygonSymbolizer;
import org.geotools.styling.RasterSymbolizer;
import org.geotools.styling.Rule;
import org.geotools.styling.Style;
import org.geotools.styling.Symbolizer;
import org.geotools.styling.TextSymbolizer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.junit.After;
import org.junit.Test;
import org.mapfish.print.AbstractMapfishSpringTest;
import org.mapfish.print.Constants;
import org.mockito.Mockito;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nullable;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Tests for {@link org.mapfish.print.config.Configuration} class.
*/
public class ConfigurationTest {
@After
public void tearDown() throws Exception {
SecurityContextHolder.clearContext();
}
@Test
public void testGetTemplate() throws Exception {
final Configuration configuration = new Configuration();
Map<String, Template> templates = Maps.newHashMap();
final Template t1Template = new Template();
templates.put("t1", t1Template);
configuration.setTemplates(templates);
assertEquals(t1Template, configuration.getTemplate("t1"));
assertEquals(1, configuration.getTemplates().size());
assertEquals(t1Template, configuration.getTemplates().values().iterator().next());
try {
configuration.getTemplate("Doesn't exist");
fail("Exception should have been thrown");
} catch (Exception e) {
// good
}
}
@Test
public void testGetDefaultStyle_IsPresentInMap() throws Exception {
final Configuration configuration = new Configuration();
Map<String, Style> styles = new HashMap<String, Style>();
final Style pointStyle = Mockito.mock(Style.class);
final Style lineStyle = Mockito.mock(Style.class);
final Style polygonStyle = Mockito.mock(Style.class);
final Style geomStyle = Mockito.mock(Style.class);
styles.put("point", pointStyle);
styles.put("line", lineStyle);
styles.put("polygon", polygonStyle);
styles.put("geometry", geomStyle);
styles.put("grid", lineStyle);
configuration.setDefaultStyle(styles);
assertSame(pointStyle, configuration.getDefaultStyle("POINT"));
assertSame(pointStyle, configuration.getDefaultStyle("MultiPOINT"));
assertSame(lineStyle, configuration.getDefaultStyle("lIne"));
assertSame(lineStyle, configuration.getDefaultStyle("lInestring"));
assertSame(lineStyle, configuration.getDefaultStyle("linearRing"));
assertSame(lineStyle, configuration.getDefaultStyle("multilInestring"));
assertSame(lineStyle, configuration.getDefaultStyle("multiline"));
assertSame(lineStyle, configuration.getDefaultStyle("grid"));
assertSame(polygonStyle, configuration.getDefaultStyle("poly"));
assertSame(polygonStyle, configuration.getDefaultStyle("polygon"));
assertSame(polygonStyle, configuration.getDefaultStyle("multiPolygon"));
assertSame(geomStyle, configuration.getDefaultStyle("geom"));
assertSame(geomStyle, configuration.getDefaultStyle("geometry"));
assertSame(geomStyle, configuration.getDefaultStyle("geometryCollection"));
assertSame(geomStyle, configuration.getDefaultStyle("MultiGeometry"));
assertSame(geomStyle, configuration.getDefaultStyle("other"));
}
@Test
public void testGetDefaultStyle_NotInMap() throws Exception {
final Configuration configuration = new Configuration();
Map<String, Style> styles = new HashMap<String, Style>();
final Style geomStyle = Mockito.mock(Style.class);
styles.put("geometry", geomStyle);
configuration.setDefaultStyle(styles);
assertStyleType(PointSymbolizer.class, configuration.getDefaultStyle("POINT"));
assertStyleType(PointSymbolizer.class, configuration.getDefaultStyle("MultiPOINT"));
assertStyleType(LineSymbolizer.class, configuration.getDefaultStyle("lIne"));
assertStyleType(LineSymbolizer.class, configuration.getDefaultStyle("lInestring"));
assertStyleType(LineSymbolizer.class, configuration.getDefaultStyle("linearRing"));
assertStyleType(LineSymbolizer.class, configuration.getDefaultStyle("multilInestring"));
assertStyleType(LineSymbolizer.class, configuration.getDefaultStyle("multiline"));
assertStyleType(PolygonSymbolizer.class, configuration.getDefaultStyle("poly"));
assertStyleType(PolygonSymbolizer.class, configuration.getDefaultStyle("polygon"));
assertStyleType(PolygonSymbolizer.class, configuration.getDefaultStyle("multiPolygon"));
assertStyleType(RasterSymbolizer.class, configuration.getDefaultStyle(Constants.Style.Raster.NAME));
assertSame(geomStyle, configuration.getDefaultStyle("geom"));
assertSame(geomStyle, configuration.getDefaultStyle("geometry"));
assertSame(geomStyle, configuration.getDefaultStyle("geometryCollection"));
assertSame(geomStyle, configuration.getDefaultStyle("MultiGeometry"));
}
@Test
public void testGetDefaultStyle_GeomNotInMap() throws Exception {
final Configuration configuration = new Configuration();
assertStyleType(Symbolizer.class, configuration.getDefaultStyle("geom"));
assertStyleType(Symbolizer.class, configuration.getDefaultStyle("geometry"));
assertStyleType(Symbolizer.class, configuration.getDefaultStyle("geometryCollection"));
assertStyleType(Symbolizer.class, configuration.getDefaultStyle("MultiGeometry"));
assertStyleType(Symbolizer.class, configuration.getDefaultStyle(Constants.Style.Grid.NAME_LINES));
assertStyleType(Symbolizer.class, configuration.getDefaultStyle(Constants.Style.Raster.NAME));
}
@Test
public void testTemplateAccess() throws Exception {
Configuration configuration = new Configuration();
Map<String, Template> templates = Maps.newHashMap();
Template unrestricted = new Template();
templates.put("unrestricted", unrestricted);
Template restricted = new Template();
restricted.setAccess(Lists.newArrayList("ROLE_USER", "ROLE_ADMIN"));
templates.put("restricted", restricted);
configuration.setTemplates(templates);
assertCorrectTemplates(configuration, unrestricted, restricted, AuthenticationCredentialsNotFoundException.class);
SimpleGrantedAuthority userAuth = new SimpleGrantedAuthority("ROLE_USER");
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
SecurityContextHolder.setContext(securityContext);
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("user", "", Lists.newArrayList(userAuth)));
assertCorrectTemplates(configuration, unrestricted, restricted, null);
securityContext = SecurityContextHolder.createEmptyContext();
SecurityContextHolder.setContext(securityContext);
assertCorrectTemplates(configuration, unrestricted, restricted, AuthenticationCredentialsNotFoundException.class);
SimpleGrantedAuthority adminAuth = new SimpleGrantedAuthority("ROLE_ADMIN");
securityContext = SecurityContextHolder.createEmptyContext();
SecurityContextHolder.setContext(securityContext);
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "", Lists.newArrayList(adminAuth)));
assertCorrectTemplates(configuration, unrestricted, restricted, null);
SecurityContextHolder.clearContext();
assertCorrectTemplates(configuration, unrestricted, restricted, AuthenticationCredentialsNotFoundException.class);
SimpleGrantedAuthority otherAuth = new SimpleGrantedAuthority("ROLE_OTHER");
securityContext = SecurityContextHolder.createEmptyContext();
SecurityContextHolder.setContext(securityContext);
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("other", "", Lists.newArrayList(otherAuth)));
assertCorrectTemplates(configuration, unrestricted, restricted, AccessDeniedException.class);
}
@Test
public void testTemplateAccess_ConfigHasAccess() throws Exception {
Configuration configuration = new Configuration();
Map<String, Template> templates = Maps.newHashMap();
Template template1 = new Template();
templates.put("template1", template1);
Template template2 = new Template();
templates.put("template2", template2);
configuration.setTemplates(templates);
configuration.setAccess(Lists.newArrayList("ROLE_USER", "ROLE_ADMIN"));
assertAccessTemplate_ConfigSecured(configuration, AuthenticationCredentialsNotFoundException.class);
SimpleGrantedAuthority userAuth = new SimpleGrantedAuthority("ROLE_USER");
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
SecurityContextHolder.setContext(securityContext);
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("user", "", Lists.newArrayList(userAuth)));
assertAccessTemplate_ConfigSecured(configuration, null);
securityContext = SecurityContextHolder.createEmptyContext();
SecurityContextHolder.setContext(securityContext);
assertAccessTemplate_ConfigSecured(configuration, AuthenticationCredentialsNotFoundException.class);
SimpleGrantedAuthority adminAuth = new SimpleGrantedAuthority("ROLE_ADMIN");
securityContext = SecurityContextHolder.createEmptyContext();
SecurityContextHolder.setContext(securityContext);
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "", Lists.newArrayList(adminAuth)));
assertAccessTemplate_ConfigSecured(configuration, null);
SecurityContextHolder.clearContext();
assertAccessTemplate_ConfigSecured(configuration, AuthenticationCredentialsNotFoundException.class);
SimpleGrantedAuthority otherAuth = new SimpleGrantedAuthority("ROLE_OTHER");
securityContext = SecurityContextHolder.createEmptyContext();
SecurityContextHolder.setContext(securityContext);
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("other", "", Lists.newArrayList(otherAuth)));
assertAccessTemplate_ConfigSecured(configuration, AccessDeniedException.class);
}
private void assertAccessTemplate_ConfigSecured(Configuration configuration,
@Nullable Class<?> expectedException) throws Exception {
final int numExpectedTemplates = expectedException == null ? 2 : 0;
assertEquals(numExpectedTemplates, configuration.getTemplates().size());
if (expectedException != null) {
try {
configuration.getTemplate("template1");
fail("Expected " + expectedException + " to be thrown");
} catch (Exception e) {
if (!expectedException.isInstance(e)) {
throw e;
}
}
} else {
assertNotNull(configuration.getTemplate("template1"));
assertNotNull(configuration.getTemplate("template2"));
}
final JSONArray layouts = getClientConfigJson(configuration);
assertEquals(numExpectedTemplates, layouts.length());
}
private JSONArray getClientConfigJson(Configuration configuration) throws JSONException {
final StringWriter w = new StringWriter();
JSONWriter writer = new JSONWriter(w);
writer.object();
configuration.printClientConfig(writer);
writer.endObject();
final JSONObject clientConfig = new JSONObject(w.toString());
return clientConfig.getJSONArray("layouts");
}
private void assertCorrectTemplates(Configuration configuration,
Template unrestricted,
Template restricted,
@Nullable Class<? extends Exception> expectedException) throws Exception {
if (expectedException != null) {
try {
configuration.getTemplate("restricted");
fail("Expected " + expectedException + " to be thrown");
} catch (Exception e) {
if (!expectedException.isInstance(e)) {
throw e;
}
}
assertFalse(configuration.getTemplates().containsKey("restricted"));
} else {
assertEquals(restricted, configuration.getTemplate("restricted"));
assertTrue(configuration.getTemplates().containsKey("restricted"));
}
assertEquals(unrestricted, configuration.getTemplate("unrestricted"));
final int expectedNumTemplates = expectedException == null ? 2 : 1;
assertEquals(expectedNumTemplates, configuration.getTemplates().size());
assertTrue(configuration.getTemplates().containsKey("unrestricted"));
final JSONArray layouts = getClientConfigJson(configuration);
assertEquals(expectedNumTemplates, layouts.length());
}
@Test
public void testRenderAsSvg() throws Exception {
final Configuration config = new Configuration();
config.setDefaultToSvg(false);
assertFalse(config.renderAsSvg(null));
assertFalse(config.renderAsSvg(false));
assertTrue(config.renderAsSvg(true));
config.setDefaultToSvg(true);
assertTrue(config.renderAsSvg(null));
assertFalse(config.renderAsSvg(false));
assertTrue(config.renderAsSvg(true));
}
@Test
public void testJdbcDrivers() throws Exception {
final Configuration config = new Configuration();
Map<String, Template> templates = new HashMap<String, Template>();
config.setTemplates(templates);
config.setConfigurationFile(AbstractMapfishSpringTest.getFile(ConfigurationTest.class, "/org/mapfish/print/config/config-test-application-context.xml"));
List<Throwable> errors = config.validate();
assertEquals(1, errors.size()); // no templates error
config.setJdbcDrivers(Sets.newHashSet("non.existant.driver.Driver"));
errors = config.validate();
assertEquals(2, errors.size());
config.setJdbcDrivers(Sets.newHashSet("org.hsqldb.jdbc.JDBCDriver"));
errors = config.validate();
assertEquals(1, errors.size());
}
private void assertStyleType(Class<?> expectedSymbolizerType, Style style) {
assertNotNull(style);
final FeatureTypeStyle featureTypeStyle = style.featureTypeStyles().get(0);
final Rule rule = featureTypeStyle.rules().get(0);
final Class<? extends Symbolizer> symbClass = rule.symbolizers().get(0).getClass();
assertTrue("Expected: " + expectedSymbolizerType.getName() + " but was: " + symbClass,
expectedSymbolizerType.isAssignableFrom(symbClass));
}
}