public MockCatalogBuilder layerGroup( String name, List<String> layerNames, List<String> styleNames) { final LayerGroupInfo lg = createMock(LayerGroupInfo.class); layerGroups.add(lg); expect(lg.getId()).andReturn(newId()).anyTimes(); expect(lg.getName()).andReturn(name).anyTimes(); List<PublishedInfo> grpLayers = new ArrayList<PublishedInfo>(); List<StyleInfo> grpStyles = new ArrayList<StyleInfo>(); for (int i = 0; i < layerNames.size(); i++) { String layerName = layerNames.get(i); LayerInfo l = null; for (LayerInfo layer : layers) { if (layerName.equals(layer.getName())) { l = layer; break; } } if (l == null) { throw new RuntimeException("No such layer: " + layerName); } grpLayers.add(l); StyleInfo s = null; if (styleNames != null) { String styleName = styleNames.get(i); for (StyleInfo style : styles) { if (styleName.equals(style.getName())) { s = style; break; } } } grpStyles.add(s); } expect(lg.getLayers()).andReturn(grpLayers).anyTimes(); expect(lg.getStyles()).andReturn(grpStyles).anyTimes(); lg.accept((CatalogVisitor) anyObject()); expectLastCall() .andAnswer( new VisitAnswer() { @Override protected void doVisit(CatalogVisitor visitor) { visitor.visit(lg); } }) .anyTimes(); expect(catalog.getLayerGroupByName(name)).andReturn(lg).anyTimes(); callback.onLayerGroup(name, lg, this); replay(lg); return this; }
/** * Gets a unique fileName for a sample. * * @param style * @return */ private String getSampleFileName(StyleInfo style) { String prefix = ""; if (style.getWorkspace() != null) { prefix = style.getWorkspace().getName() + "_"; } String fileName = prefix + style.getName() + "." + DEFAULT_SAMPLE_FORMAT; return fileName; }
/** @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; }
void loadStyles(File styles, Catalog catalog, XStreamPersister xp) { for (File sf : list(styles, new SuffixFileFilter(".xml"))) { try { // handle the .xml.xml case if (new File(styles, sf.getName() + ".xml").exists()) { continue; } StyleInfo s = depersist(xp, sf, StyleInfo.class); catalog.add(s); LOGGER.info("Loaded style '" + s.getName() + "'"); } catch (Exception e) { LOGGER.log(Level.WARNING, "Failed to load style from file '" + sf.getName() + "'", e); } } }
public MockCatalogBuilder style(String name) { String filename = name + ".sld"; if (getClass().getResourceAsStream(filename) == null) { return this; } String sId = newId(); Version version = Styles.Handler.SLD_10.getVersion(); final StyleInfo s = createNiceMock(StyleInfo.class); styles.add(s); expect(s.getId()).andReturn(sId); expect(s.getName()).andReturn(name).anyTimes(); expect(s.getFilename()).andReturn(filename).anyTimes(); expect(s.getSLDVersion()).andReturn(version).anyTimes(); try { expect(s.getStyle()) .andReturn( Styles.style(Styles.parse(getClass().getResourceAsStream(filename), null, version))) .anyTimes(); } catch (IOException e) { throw new RuntimeException(e); } expect(catalog.getStyle(sId)).andReturn(s).anyTimes(); expect(catalog.getStyleByName(name)).andReturn(s).anyTimes(); s.accept((CatalogVisitor) anyObject()); expectLastCall() .andAnswer( new VisitAnswer() { @Override protected void doVisit(CatalogVisitor visitor) { visitor.visit(s); } }) .anyTimes(); callback.onStyle(name, s, this); replay(s); return this; }
/** Clean up no more valid samples: SLD updated from latest sample creation. */ private void clean() { for (StyleInfo style : catalog.getStyles()) { synchronized (style) { Resource styleResource = getStyleResource(style); File sampleFile; try { // remove old samples sampleFile = getSampleFile(style); if (isStyleNewerThanSample(styleResource, sampleFile)) { sampleFile.delete(); } } catch (IOException e) { LOGGER.log( Level.SEVERE, "Error cleaning invalid legend sample for " + style.getName(), e); } } } invalidated = new HashSet<String>(); }
/** * Gets a unique name for a style, considering the workspace definition, in the form * worspacename:stylename (or stylename if the style is global). * * @param styleInfo * @return */ private String getStyleName(StyleInfo styleInfo) { return styleInfo.getWorkspace() != null ? (styleInfo.getWorkspace().getName() + ":" + styleInfo.getName()) : styleInfo.getName(); }
/** * 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"); }
/** * Writes layer LegendURL pointing to the user supplied icon URL, if any, or to the proper * GetLegendGraphic operation if an URL was not supplied by configuration file. * * <p>It is common practice to supply a URL to a WMS accesible legend graphic when it is * difficult to create a dynamic legend for a layer. * * @param ft The FeatureTypeInfo that holds the legendURL to write out, or<code>null</code> if * dynamically generated. * @task TODO: figure out how to unhack legend parameters such as WIDTH, HEIGHT and FORMAT */ protected void handleLegendURL(String layerName, LegendInfo legend, StyleInfo style) { if (legend != null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("using user supplied legend URL"); } AttributesImpl attrs = new AttributesImpl(); attrs.addAttribute("", "width", "width", "", String.valueOf(legend.getWidth())); attrs.addAttribute("", "height", "height", "", String.valueOf(legend.getHeight())); start("LegendURL", attrs); element("Format", legend.getFormat()); attrs.clear(); attrs.addAttribute("", "xmlns:xlink", "xmlns:xlink", "", XLINK_NS); attrs.addAttribute(XLINK_NS, "type", "xlink:type", "", "simple"); attrs.addAttribute(XLINK_NS, "href", "xlink:href", "", legend.getOnlineResource()); element("OnlineResource", null, attrs); end("LegendURL"); } else { String defaultFormat = GetLegendGraphicRequest.DEFAULT_FORMAT; if (null == wmsConfig.getLegendGraphicOutputFormat(defaultFormat)) { if (LOGGER.isLoggable(Level.WARNING)) { LOGGER.warning( new StringBuffer("Default legend format (") .append(defaultFormat) .append(")is not supported (jai not available?), can't add LegendURL element") .toString()); } return; } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Adding GetLegendGraphic call as LegendURL"); } AttributesImpl attrs = new AttributesImpl(); attrs.addAttribute( "", "width", "width", "", String.valueOf(GetLegendGraphicRequest.DEFAULT_WIDTH)); // DJB: problem here is that we do not know the size of the // legend apriori - we need // to make one and find its height. Not the best way, but it // would work quite well. // This was advertising a 20*20 icon, but actually producing // ones of a different size. // An alternative is to just scale the resulting icon to what // the server requested, but this isnt // the nicest thing since warped images dont look nice. The // client should do the warping. // however, to actually estimate the size is a bit difficult. // I'm going to do the scaling // so it obeys the what the request says. For people with a // problem with that should consider // changing the default size here so that the request is for the // correct size. attrs.addAttribute( "", "height", "height", "", String.valueOf(GetLegendGraphicRequest.DEFAULT_HEIGHT)); start("LegendURL", attrs); element("Format", defaultFormat); attrs.clear(); Map<String, String> params = params( "request", "GetLegendGraphic", "format", defaultFormat, "width", String.valueOf(GetLegendGraphicRequest.DEFAULT_WIDTH), "height", String.valueOf(GetLegendGraphicRequest.DEFAULT_HEIGHT), "layer", layerName); if (style != null) { params.put("style", style.getName()); } String legendURL = buildURL(request.getBaseUrl(), "wms", params, URLType.SERVICE); attrs.addAttribute("", "xmlns:xlink", "xmlns:xlink", "", XLINK_NS); attrs.addAttribute(XLINK_NS, "type", "xlink:type", "", "simple"); attrs.addAttribute(XLINK_NS, "href", "xlink:href", "", legendURL); element("OnlineResource", null, attrs); end("LegendURL"); } }
/** * 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); } }