/* (c) 2017 Open Source Geospatial Foundation - all rights reserved * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.notification; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.beanutils.BeanToPropertyValueTransformer; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.geoserver.catalog.CatalogException; import org.geoserver.catalog.CatalogInfo; import org.geoserver.catalog.CoverageInfo; import org.geoserver.catalog.FeatureTypeInfo; import org.geoserver.catalog.LayerGroupInfo; import org.geoserver.catalog.LayerInfo; import org.geoserver.catalog.NamespaceInfo; import org.geoserver.catalog.ResourceInfo; import org.geoserver.catalog.StoreInfo; import org.geoserver.catalog.StyleInfo; import org.geoserver.catalog.WMSLayerInfo; import org.geoserver.catalog.WorkspaceInfo; import org.geoserver.catalog.event.CatalogAddEvent; import org.geoserver.catalog.event.CatalogModifyEvent; import org.geoserver.catalog.event.CatalogPostModifyEvent; import org.geoserver.catalog.event.CatalogRemoveEvent; import org.geoserver.catalog.impl.ModificationProxy; import org.geoserver.notification.common.Notification; import org.geoserver.notification.common.Notification.Action; import org.geoserver.notification.common.Notification.Type; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; public class NotificationCatalogListener extends NotificationListener implements INotificationCatalogListener { private Boolean filterEvent(CatalogInfo source) { return (source instanceof WorkspaceInfo || source instanceof NamespaceInfo || source instanceof FeatureTypeInfo || source instanceof CoverageInfo || source instanceof WMSLayerInfo || source instanceof StoreInfo || source instanceof LayerInfo || source instanceof LayerGroupInfo); } @Override public void handleRemoveEvent(CatalogRemoveEvent event) throws CatalogException { if (filterEvent(event.getSource())) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); String user = (auth != null) ? auth.getName() : null; CatalogInfo info = ModificationProxy.unwrap(event.getSource()); Notification notification = new NotificationImpl(Type.Catalog, event.getSource() .getId(), Action.Remove, info, null, user); notify(notification); } } @Override public void handleModifyEvent(CatalogModifyEvent event) throws CatalogException { if (filterEvent(event.getSource())) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); String user = (auth != null) ? auth.getName() : null; CatalogInfo info = ModificationProxy.unwrap(event.getSource()); Notification notification = new NotificationImpl(Type.Catalog, event.getSource() .getId(), Action.Update, info, handleModifiedProperties(event), user); notify(notification); } } @Override public void handleAddEvent(CatalogAddEvent event) throws CatalogException { if (filterEvent(event.getSource())) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); String user = (auth != null) ? auth.getName() : null; CatalogInfo info = ModificationProxy.unwrap(event.getSource()); Notification notification = new NotificationImpl(Type.Catalog, event.getSource() .getId(), Action.Add, info, null, user); notify(notification); } } private Map<String, Object> handleModifiedProperties(CatalogModifyEvent event) { final Map<String, Object> properties = new HashMap<String, Object>(); final CatalogInfo source = event.getSource(); final List<String> changedProperties = event.getPropertyNames(); final List<Object> oldValues = event.getOldValues(); final List<Object> newValues = event.getNewValues(); if (source instanceof FeatureTypeInfo || source instanceof CoverageInfo || source instanceof WMSLayerInfo || source instanceof LayerGroupInfo) { if (changedProperties.contains("name") || changedProperties.contains("namespace") || changedProperties.contains("workspace")) { handleRename(properties, source, changedProperties, oldValues, newValues); } } else if (source instanceof WorkspaceInfo) { if (changedProperties.contains("name")) { handleWorkspaceRename(properties, source, changedProperties, oldValues, newValues); } } if (source instanceof LayerInfo) { final LayerInfo li = (LayerInfo) source; handleLayerInfoChange(properties, changedProperties, oldValues, newValues, li); } else if (source instanceof LayerGroupInfo) { LayerGroupInfo lgInfo = (LayerGroupInfo) source; handleLayerGroupInfoChange(properties, changedProperties, oldValues, newValues, lgInfo); } return properties; } private void handleLayerGroupInfoChange(Map<String, Object> properties, final List<String> changedProperties, final List<Object> oldValues, final List<Object> newValues, final LayerGroupInfo lgInfo) { if (changedProperties.contains("layers")) { final int layersIndex = changedProperties.indexOf("layers"); Object oldLayers = oldValues.get(layersIndex); Object newLayers = newValues.get(layersIndex); } if (changedProperties.contains("styles")) { final int stylesIndex = changedProperties.indexOf("styles"); BeanToPropertyValueTransformer transformer = new BeanToPropertyValueTransformer("name"); String oldStyles = StringUtils.join(CollectionUtils.collect( (Set<StyleInfo>) oldValues.get(stylesIndex), transformer).toArray()); String newStyles = StringUtils.join(CollectionUtils.collect( (Set<StyleInfo>) newValues.get(stylesIndex), transformer).toArray()); if (!oldStyles.equals(newStyles)) { properties.put("styles", newStyles); } } } private void handleLayerInfoChange(Map<String, Object> properties, final List<String> changedProperties, final List<Object> oldValues, final List<Object> newValues, final LayerInfo li) { 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.prefixedName(); final String newStyleName = newStyle.prefixedName(); if (!oldStyleName.equals(newStyleName)) { properties.put("defaultStyle", newStyleName); } } if (changedProperties.contains("styles")) { final int stylesIndex = changedProperties.indexOf("styles"); BeanToPropertyValueTransformer transformer = new BeanToPropertyValueTransformer("name"); String oldStyles = StringUtils.join(CollectionUtils.collect( (Set<StyleInfo>) oldValues.get(stylesIndex), transformer).toArray()); String newStyles = StringUtils.join(CollectionUtils.collect( (Set<StyleInfo>) newValues.get(stylesIndex), transformer).toArray()); if (!oldStyles.equals(newStyles)) { properties.put("styles", newStyles); } } } private void handleWorkspaceRename(Map<String, Object> properties, final CatalogInfo source, final List<String> changedProperties, final List<Object> oldValues, final List<Object> newValues) { final int nameIndex = changedProperties.indexOf("name"); final String oldWorkspaceName = (String) oldValues.get(nameIndex); final String newWorkspaceName = (String) newValues.get(nameIndex); } private void handleRename(Map<String, Object> properties, final CatalogInfo source, final List<String> changedProperties, final List<Object> oldValues, final List<Object> newValues) { final int nameIndex = changedProperties.indexOf("name"); final int namespaceIndex = changedProperties.indexOf("namespace"); String oldLayerName; String newLayerName; if (source instanceof ResourceInfo) {// covers LayerInfo, CoverageInfo, and WMSLayerInfo // must cover prefix:name final ResourceInfo resourceInfo = (ResourceInfo) source; final NamespaceInfo currNamespace = resourceInfo.getNamespace(); final NamespaceInfo oldNamespace; if (namespaceIndex > -1) { oldNamespace = (NamespaceInfo) oldValues.get(namespaceIndex); } else { oldNamespace = currNamespace; } newLayerName = resourceInfo.prefixedName(); if (nameIndex > -1) { oldLayerName = (String) oldValues.get(nameIndex); } else { oldLayerName = resourceInfo.getName(); } oldLayerName = oldNamespace.getPrefix() + ":" + oldLayerName; } } @Override public void setMessageMultiplexer(MessageMultiplexer messageMultiplexer) { this.messageMultiplexer = messageMultiplexer; } @Override public MessageMultiplexer getMessageMultiplexer() { return messageMultiplexer; } @Override public void handlePostModifyEvent(CatalogPostModifyEvent event) throws CatalogException { int a = 1; } @Override public void reloaded() { } }