/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.gwc.layer; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Throwables.propagate; import java.io.Serializable; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; import org.geotools.util.logging.Logging; import org.geowebcache.config.BlobStoreConfig; import org.geowebcache.config.XMLGridSubset; import org.geowebcache.filter.parameters.ParameterFilter; import org.geowebcache.filter.request.RequestFilter; import org.geowebcache.layer.ExpirationRule; import org.geowebcache.layer.meta.LayerMetaInformation; import org.geowebcache.layer.updatesource.UpdateSourceDefinition; import org.geowebcache.mime.FormatModifier; import org.geowebcache.util.GWCVars; import com.google.common.collect.ImmutableSet; /** * @author groldan * */ public class GeoServerTileLayerInfoImpl implements Serializable, GeoServerTileLayerInfo { /** serialVersionUID */ private static final long serialVersionUID = 8277055420849712230L; private static final Logger LOGGER = Logging.getLogger(GeoServerTileLayerInfoImpl.class); private String id; // // AbstractTileLayer mirror properties //// private boolean enabled; private Boolean inMemoryCached; private String name; private String blobStoreId; @SuppressWarnings("unused") transient private LayerMetaInformation metaInformation; private Set<String> mimeFormats; @SuppressWarnings("unused") private List<FormatModifier> formatModifiers; private Set<XMLGridSubset> gridSubsets; @SuppressWarnings("unused") transient private List<? extends UpdateSourceDefinition> updateSources; @SuppressWarnings("unused") transient private List<? extends RequestFilter> requestFilters; @SuppressWarnings("unused") transient private boolean useETags; private int[] metaWidthHeight; /** * @see GWCVars#CACHE_DISABLE_CACHE * @see GWCVars#CACHE_NEVER_EXPIRE * @see GWCVars#CACHE_USE_WMS_BACKEND_VALUE * @see GWCVars#CACHE_VALUE_UNSET */ private int expireCache; private List<ExpirationRule> expireCacheList; private int expireClients; @SuppressWarnings("unused") transient private List<ExpirationRule> expireClientsList; @SuppressWarnings("unused") transient private Integer backendTimeout; @SuppressWarnings("unused") transient private Boolean cacheBypassAllowed; @SuppressWarnings("unused") transient private Boolean queryable; // The actual storage transient private Map<String, ParameterFilter> parameterFiltersMap; // Just used for serialize/deserialize to make xstream keep the same format it used to. private Set<ParameterFilter> parameterFilters; // //// GeoServerTileLayer specific properties ////// private int gutter; // For backward compatibility with 2.2 and 2.3 // FIXME need to hide this when serializing back out private Boolean autoCacheStyles; public GeoServerTileLayerInfoImpl() { readResolve(); } /** * XStream initialization of unset fields * * @return {@code this} */ private final Object readResolve() { if (null == metaWidthHeight) { metaWidthHeight = new int[2]; } gridSubsets = nonNull(gridSubsets); mimeFormats = nonNull(mimeFormats); // Convert the deserialized set into a map. parameterFilters = nonNull(parameterFilters); setParameterFilters(parameterFilters); // Apply the old autoCacheStyles flag if it was specified. if(autoCacheStyles!=null){ if(autoCacheStyles) { if(!isAutoCacheStyles()){ addParameterFilter(new StyleParameterFilter()); } } else { if(isAutoCacheStyles()){ this.removeParameterFilter("STYLES"); } } autoCacheStyles = null; } return this; } private final Object writeReplace() { parameterFilters = getParameterFilters(); return this; } /** * @see java.lang.Object#clone() */ @Override public GeoServerTileLayerInfoImpl clone() { GeoServerTileLayerInfoImpl clone; try { clone = (GeoServerTileLayerInfoImpl) super.clone(); } catch (CloneNotSupportedException e) { throw propagate(e); } clone.metaWidthHeight = metaWidthHeight.clone(); clone.gridSubsets = nonNull((Set<XMLGridSubset>)null); for (XMLGridSubset gs : gridSubsets) { clone.gridSubsets.add(gs.clone()); } clone.mimeFormats = nonNull((Set<String>)null); clone.mimeFormats.addAll(mimeFormats); clone.parameterFiltersMap = nonNull((Map<String, ParameterFilter>)null); for (ParameterFilter pf : parameterFiltersMap.values()) { clone.addParameterFilter(pf.clone()); } return clone; } private <T> Set<T> nonNull(Set<T> set) { return set == null ? new HashSet<T>() : set; } private <K,T> Map<K, T> nonNull(Map<K,T> set) { return set == null ? new HashMap<K,T>() : set; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#getId() */ @Override public String getId() { return id; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#setId(java.lang.String) */ @Override public void setId(String id) { this.id = id; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#getName() */ @Override public String getName() { return name; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#setName(java.lang.String) */ @Override public void setName(String name) { this.name = name; } @Override @Nullable public String getBlobStoreId() { return blobStoreId; } @Override public void setBlobStoreId(@Nullable String blobStoreId) { this.blobStoreId = blobStoreId; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#getMetaTilingX() */ @Override public int getMetaTilingX() { return metaWidthHeight[0]; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#getMetaTilingY() */ @Override public int getMetaTilingY() { return metaWidthHeight[1]; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#setMetaTilingY(int) */ @Override public void setMetaTilingY(int metaTilingY) { checkArgument(metaTilingY > 0); metaWidthHeight[1] = metaTilingY; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#setMetaTilingX(int) */ @Override public void setMetaTilingX(int metaTilingX) { checkArgument(metaTilingX > 0); metaWidthHeight[0] = metaTilingX; } public int getExpireCache() { return expireCache; } public void setExpireCache(int expireCache) { this.expireCache = expireCache; } public List<ExpirationRule> getExpireCacheList() { return expireCacheList; } public void setExpireCacheList(List<ExpirationRule> expireCacheList) { this.expireCacheList = expireCacheList; } @Override public int getExpireClients() { return expireClients; } @Override public void setExpireClients(int seconds) { expireClients = seconds; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#cachedStyles() */ @Override public ImmutableSet<String> cachedStyles() { ParameterFilter styleQualifier = getParameterFilter("STYLES"); try { if (styleQualifier != null) { List<String> styles = styleQualifier.getLegalValues(); if(styles!=null) { return ImmutableSet.copyOf(styles); } } } catch (IllegalStateException ex) { LOGGER.log(Level.WARNING, "StyleParameterFilter was not initialized properly", ex); } return ImmutableSet.of(); } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#getMimeFormats() */ @Override public Set<String> getMimeFormats() { return mimeFormats; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#getGridSubsets() */ @Override public Set<XMLGridSubset> getGridSubsets() { return gridSubsets; } @Override public void setGridSubsets(Set<XMLGridSubset> gridSubsets) { this.gridSubsets = nonNull(gridSubsets); } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#setEnabled(boolean) */ @Override public void setEnabled(boolean enabled) { this.enabled = enabled; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#isEnabled() */ @Override public boolean isEnabled() { return enabled; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#setGutter(int) */ @Override public void setGutter(int gutter) { this.gutter = gutter; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#getGutter() */ @Override public int getGutter() { return gutter; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#isAutoCacheStyles() */ @Override public boolean isAutoCacheStyles() { ParameterFilter filter = getParameterFilter("STYLES"); return filter!=null && filter instanceof StyleParameterFilter && ((StyleParameterFilter)filter).getStyles()==null; } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#setAutoCacheStyles(boolean) * @deprecated */ @Override public void setAutoCacheStyles(boolean autoCacheStyles) { if(autoCacheStyles){ // Add a default StyleParameterFilter. ParameterFilter newFilter = new StyleParameterFilter(); addParameterFilter(newFilter); } else { ParameterFilter filter = getParameterFilter("STYLES"); if(filter!=null && filter instanceof StyleParameterFilter){ parameterFilters.remove(filter); } } } /** * @see org.geoserver.gwc.layer.GeoServerTileLayerInfo#getParameterFilters() */ @Override public Set<ParameterFilter> getParameterFilters() { return new HashSet<ParameterFilter>(parameterFiltersMap.values()); } @Override public void setParameterFilters(Set<ParameterFilter> parameterFilters) { parameterFiltersMap = new HashMap<String, ParameterFilter>(); for (ParameterFilter pf: parameterFilters){ addParameterFilter(pf); } } @Override public boolean equals(Object other) { return EqualsBuilder.reflectionEquals(this, other); } @Override public int hashCode() { return HashCodeBuilder.reflectionHashCode(this); } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); // return GeoServerTileLayerInfoLoader.marshalJson(this); } @Override public boolean addParameterFilter(ParameterFilter parameterFilter) { return parameterFiltersMap.put(parameterFilter.getKey().toUpperCase(), parameterFilter) !=null; } @Override public boolean removeParameterFilter(String key) { return parameterFiltersMap.remove(key.toUpperCase()) !=null; } @Override public ParameterFilter getParameterFilter(String key) { return parameterFiltersMap.get(key.toUpperCase()); } @Override public boolean isInMemoryCached() { return inMemoryCached != null ? inMemoryCached : true; } @Override public void setInMemoryCached(boolean inMemoryCached) { this.inMemoryCached = inMemoryCached; } }