void setupExtras(org.geoserver.data.test.SystemTestData testData, Catalog catalog) throws IOException { // associate Lakes to Buildings as an extra style LayerInfo buildings = catalog.getLayerByName(getLayerId(BUILDINGS)); buildings.getStyles().add(catalog.getStyleByName(LAKES.getLocalPart())); catalog.save(buildings); // add a layer group CatalogFactory factory = catalog.getFactory(); LayerGroupInfo globalGroup = factory.createLayerGroup(); globalGroup.setName(LAKES_GROUP); globalGroup.getLayers().add(catalog.getLayerByName(getLayerId(LAKES))); globalGroup.getLayers().add(catalog.getLayerByName(getLayerId(FORESTS))); globalGroup.getLayers().add(catalog.getLayerByName(getLayerId(BRIDGES))); catalog.add(globalGroup); // add a layer group containing a layer group LayerGroupInfo nestGroup = factory.createLayerGroup(); nestGroup.setName(NEST_GROUP); nestGroup.getLayers().add(catalog.getLayerByName(getLayerId(LAKES))); nestGroup.getLayers().add(globalGroup); catalog.add(nestGroup); // add a workspace specific style WorkspaceInfo ws = catalog.getWorkspaceByName(CITE_PREFIX); testData.addStyle(ws, WS_STYLE, "Streams.sld", SystemTestData.class, catalog); };
/** @return the list of the alternate style names registered for this layer */ public List<String> getOtherStyleNames() { if (layerInfo == null) { return Collections.emptyList(); } final List<String> styleNames = new ArrayList<String>(); for (StyleInfo si : layerInfo.getStyles()) { styleNames.add(si.getName()); } return styleNames; }
public void validate(LayerInfo lyr, boolean isNew) { if (lyr.isEnabled() == false) { // short-circuit - for disabled layers we don't need to validate // anything because it won't cause service exceptions for anyone return; } if (lyr.getResource() == null || (hasGeometry(lyr) && (lyr.getResource().getSRS() == null || lyr.getResource().getLatLonBoundingBox() == null))) throw new RuntimeException("Layer's resource is not fully configured"); // Resource-dependent checks if (lyr.getType() == PublishedType.RASTER) { if (!(lyr.getResource() instanceof CoverageInfo)) throw new RuntimeException("Layer with type RASTER doesn't have a coverage associated"); CoverageInfo cvinfo = (CoverageInfo) lyr.getResource(); try { cvinfo .getCatalog() .getResourcePool() .getGridCoverageReader(cvinfo, GeoTools.getDefaultHints()); } catch (Throwable t) { throw new RuntimeException("Couldn't connect to raster layer's resource"); } } else if (lyr.getType() == PublishedType.VECTOR) { if (!(lyr.getResource() instanceof FeatureTypeInfo)) throw new RuntimeException("Layer with type VECTOR doesn't have a featuretype associated"); FeatureTypeInfo ftinfo = (FeatureTypeInfo) lyr.getResource(); } else throw new RuntimeException("Layer is neither RASTER nor VECTOR type"); // Style-dependent checks if (hasGeometry(lyr) && (lyr.getDefaultStyle() == null || lyr.getStyles().contains(null))) throw new RuntimeException("Layer has null styles!"); }
/** * Calls super.handleFeatureType to add common FeatureType content such as Name, Title and * LatLonBoundingBox, and then writes WMS specific layer properties as Styles, Scale Hint, etc. * * @throws IOException * @task TODO: write wms specific elements. */ @SuppressWarnings("deprecation") protected void handleLayer(final LayerInfo layer) { // HACK: by now all our layers are queryable, since they reference // only featuretypes managed by this server AttributesImpl qatts = new AttributesImpl(); boolean queryable = wmsConfig.isQueryable(layer); qatts.addAttribute("", "queryable", "queryable", "", queryable ? "1" : "0"); start("Layer", qatts); element("Name", layer.getResource().getNamespace().getPrefix() + ":" + layer.getName()); // REVISIT: this is bad, layer should have title and anbstract by itself element("Title", layer.getResource().getTitle()); element("Abstract", layer.getResource().getAbstract()); handleKeywordList(layer.getResource().getKeywords()); /** * @task REVISIT: should getSRS() return the full URL? no - the spec says it should be a set * of <SRS>EPSG:#</SRS>... */ final String srs = layer.getResource().getSRS(); element("SRS", srs); // DJB: I want to be nice to the people reading the capabilities // file - I'm going to get the // human readable name and stick it in the capabilities file // NOTE: this isnt well done because "comment()" isnt in the // ContentHandler interface... try { CoordinateReferenceSystem crs = layer.getResource().getCRS(); String desc = "WKT definition of this CRS:\n" + crs; comment(desc); } catch (Exception e) { if (LOGGER.isLoggable(Level.WARNING)) { LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e); } } Envelope bbox; try { bbox = layer.getResource().boundingBox(); } catch (Exception e) { throw new RuntimeException( "Unexpected error obtaining bounding box for layer " + layer.getName(), e); } Envelope llbbox = layer.getResource().getLatLonBoundingBox(); handleLatLonBBox(llbbox); // the native bbox might be null if (bbox != null) { handleBBox(bbox, srs); } // handle dimensions String timeMetadata = null; String elevationMetadata = null; if (layer.getType() == Type.VECTOR) { dimensionHelper.handleVectorLayerDimensions(layer); } else if (layer.getType() == Type.RASTER) { dimensionHelper.handleRasterLayerDimensions(layer); } // handle data attribution handleAttribution(layer); // handle metadata URLs handleMetadataList(layer.getResource().getMetadataLinks()); if (layer.getResource() instanceof WMSLayerInfo) { // do nothing for the moment, we may want to list the set of cascaded named styles // in the future (when we add support for that) } else { // add the layer style start("Style"); StyleInfo defaultStyle = layer.getDefaultStyle(); if (defaultStyle == null) { throw new NullPointerException("Layer " + layer.getName() + " has no default style"); } Style ftStyle; try { ftStyle = defaultStyle.getStyle(); } catch (IOException e) { throw new RuntimeException(e); } element("Name", defaultStyle.getName()); element("Title", ftStyle.getTitle()); element("Abstract", ftStyle.getAbstract()); handleLegendURL(layer.getName(), layer.getLegend(), null); end("Style"); Set<StyleInfo> styles = layer.getStyles(); for (StyleInfo styleInfo : styles) { try { ftStyle = styleInfo.getStyle(); } catch (IOException e) { throw new RuntimeException(e); } start("Style"); element("Name", styleInfo.getName()); element("Title", ftStyle.getTitle()); element("Abstract", ftStyle.getAbstract()); handleLegendURL(layer.getName(), null, styleInfo); end("Style"); } } end("Layer"); }
/** * Handles changes of interest to GWC on a {@link LayerInfo}. * * <ul> * <li>If the name of the default style changed, then the layer's cache for the default style is * truncated. This method doesn't check if the contents of the styles are equal. That is * handled by {@link CatalogStyleChangeListener} whenever a style is modified. * <li>If the tile layer is {@link GeoServerTileLayerInfo#isAutoCacheStyles() auto caching * styles} and the layerinfo's "styles" list changed, the tile layer's STYLE parameter * filter is updated to match the actual list of layer styles and any removed style is * truncated. * </ul> * * @param changedProperties * @param oldValues * @param newValues * @param li * @param tileLayerInfo */ private void handleLayerInfoChange( final List<String> changedProperties, final List<Object> oldValues, final List<Object> newValues, final LayerInfo li, final GeoServerTileLayerInfo tileLayerInfo) { checkNotNull(tileLayerInfo); final String layerName = tileLayerName(li); boolean save = false; final String defaultStyle; /* * If default style name changed */ if (changedProperties.contains("defaultStyle")) { final int propIndex = changedProperties.indexOf("defaultStyle"); final StyleInfo oldStyle = (StyleInfo) oldValues.get(propIndex); final StyleInfo newStyle = (StyleInfo) newValues.get(propIndex); final String oldStyleName = oldStyle.getName(); defaultStyle = newStyle.getName(); if (!Objects.equal(oldStyleName, defaultStyle)) { save = true; log.info( "Truncating default style for layer " + layerName + ", as it changed from " + oldStyleName + " to " + defaultStyle); mediator.truncateByLayerAndStyle(layerName, oldStyleName); } } else { StyleInfo styleInfo = li.getDefaultStyle(); defaultStyle = styleInfo == null ? null : styleInfo.getName(); } if (tileLayerInfo.isAutoCacheStyles()) { Set<String> styles = new HashSet<String>(); for (StyleInfo s : li.getStyles()) { styles.add(s.getName()); } ImmutableSet<String> cachedStyles = tileLayerInfo.cachedStyles(); if (!styles.equals(cachedStyles)) { // truncate no longer existing cached styles Set<String> notCachedAnyMore = Sets.difference(cachedStyles, styles); for (String oldCachedStyle : notCachedAnyMore) { log.info( "Truncating cached style " + oldCachedStyle + " of layer " + layerName + " as it's no longer one of the layer's styles"); mediator.truncateByLayerAndStyle(layerName, oldCachedStyle); } // reset STYLES parameter filter final boolean createParamIfNotExists = true; TileLayerInfoUtil.updateStringParameterFilter( tileLayerInfo, "STYLES", createParamIfNotExists, defaultStyle, styles); save = true; } } if (save) { GridSetBroker gridSetBroker = mediator.getGridSetBroker(); GeoServerTileLayer tileLayer = new GeoServerTileLayer(li, gridSetBroker, tileLayerInfo); mediator.save(tileLayer); } }
/** * Adds a vector layer to the catalog setup. * * <p>The layer is created within a store named <code>qName.getPrefix()</code>, creating it if it * does not exist. The resulting store is a {@link PropertyDataStore} that points at the directory * <code>getDataDirectoryRoot()/qName.getPrefix()</code>. Similarily the layer and store are * created within a workspace named <code>qName.getPrefix()</code>, which is created if it does * not already exist. * * <p>The properties data for the layer is copied from the classpath, with a file name of "<code> * filename</code>.properties". The <tt>scope</tt> parameter is used as the class from which to * load the properties file relative to. * * <p>The <tt>props</tt> parameter is used to define custom properties for the layer. See the * {@link LayerProperty} class for supported properties. */ public void addVectorLayer( QName qName, Map<LayerProperty, Object> props, String filename, Class scope, Catalog catalog) throws IOException { String prefix = qName.getPrefix(); String name = qName.getLocalPart(); String uri = qName.getNamespaceURI(); // configure workspace if it doesn;t already exist if (catalog.getWorkspaceByName(prefix) == null) { addWorkspace(prefix, uri, catalog); } // configure store if it doesn't already exist File storeDir = catalog.getResourceLoader().findOrCreateDirectory(prefix); DataStoreInfo store = catalog.getDataStoreByName(prefix); if (store == null) { store = catalog.getFactory().createDataStore(); store.setName(prefix); store.setWorkspace(catalog.getWorkspaceByName(prefix)); store.setEnabled(true); store.getConnectionParameters().put(PropertyDataStoreFactory.DIRECTORY.key, storeDir); store.getConnectionParameters().put(PropertyDataStoreFactory.NAMESPACE.key, uri); catalog.add(store); } // copy the properties file over catalog.getResourceLoader().copyFromClassPath(filename, new File(storeDir, filename), scope); // configure feature type FeatureTypeInfo featureType = catalog.getFactory().createFeatureType(); featureType.setStore(store); featureType.setNamespace(catalog.getNamespaceByPrefix(prefix)); featureType.setName(LayerProperty.NAME.get(props, name)); featureType.setNativeName(FilenameUtils.getBaseName(filename)); featureType.setTitle(name); featureType.setAbstract("abstract about " + name); Integer srs = LayerProperty.SRS.get(props, SRS.get(qName)); if (srs == null) { srs = 4326; } featureType.setSRS("EPSG:" + srs); try { featureType.setNativeCRS(CRS.decode("EPSG:" + srs)); } catch (Exception e) { LOGGER.warning("Failed to decode EPSG:" + srs + ", setting the native SRS to null"); } featureType.setNumDecimals(8); featureType.getKeywords().add(new Keyword(name)); featureType.setEnabled(true); featureType.setProjectionPolicy( LayerProperty.PROJECTION_POLICY.get(props, ProjectionPolicy.NONE)); featureType.setLatLonBoundingBox( LayerProperty.LATLON_ENVELOPE.get(props, DEFAULT_LATLON_ENVELOPE)); featureType.setNativeBoundingBox(LayerProperty.ENVELOPE.get(props, null)); FeatureTypeInfo ft = catalog.getFeatureTypeByDataStore(store, name); LayerInfo layer = catalog.getLayerByName(new NameImpl(prefix, name)); if (ft == null) { ft = featureType; catalog.add(featureType); } else { if (layer == null) { // handles the case of layer removed, but feature type not catalog.remove(ft); ft = featureType; catalog.add(featureType); } else { new CatalogBuilder(catalog).updateFeatureType(ft, featureType); catalog.save(ft); } } if (layer == null || !layer.getResource().getNamespace().equals(catalog.getNamespaceByPrefix(prefix))) { layer = catalog.getFactory().createLayer(); } layer.setResource(ft); StyleInfo defaultStyle = null; if (LayerProperty.STYLE.get(props, null) != null) { defaultStyle = catalog.getStyleByName(LayerProperty.STYLE.get(props, null)); } else { // look for a style matching the layer name defaultStyle = catalog.getStyleByName(name); if (defaultStyle == null) { // see if the resource exists and we just need to create it if (getClass().getResource(name + ".sld") != null) { addStyle(name, catalog); defaultStyle = catalog.getStyleByName(name); } } } if (defaultStyle == null) { defaultStyle = catalog.getStyleByName(DEFAULT_VECTOR_STYLE); } layer.getStyles().clear(); layer.setDefaultStyle(defaultStyle); layer.setType(LayerInfo.Type.VECTOR); layer.setEnabled(true); if (layer.getId() == null) { catalog.add(layer); } else { catalog.save(layer); } }