/* (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.cluster.impl.handlers.configuration; import java.lang.reflect.InvocationTargetException; import java.util.List; import org.apache.commons.lang.NullArgumentException; import org.geoserver.cluster.events.ToggleSwitch; import org.geoserver.cluster.impl.events.configuration.JMSServiceModifyEvent; import org.geoserver.cluster.impl.utils.BeanUtils; import org.geoserver.config.GeoServer; import org.geoserver.config.ServiceInfo; import com.thoughtworks.xstream.XStream; /** * * @see {@link JMSServiceHandlerSPI} * @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it * */ public class JMSServiceHandler extends JMSConfigurationHandler<JMSServiceModifyEvent> { private final GeoServer geoServer; private final ToggleSwitch producer; public JMSServiceHandler(GeoServer geo, XStream xstream, Class clazz, ToggleSwitch producer) { super(xstream, clazz); this.geoServer = geo; this.producer = producer; } @Override protected void omitFields(final XStream xstream) { // omit not serializable fields xstream.omitField(GeoServer.class, "geoServer"); } @Override public boolean synchronize(JMSServiceModifyEvent ev) throws Exception { if (ev == null) { throw new NullArgumentException("Incoming event is null"); } try { // disable the message producer to avoid recursion producer.disable(); // let's see which type of event we have switch (ev.getEventType()) { case MODIFIED: // localize service final ServiceInfo localObject = localizeService(geoServer, ev); // save the localized object geoServer.save(localObject); break; case ADDED: // checking that this service is not already present, we don't synchronize this check // if two threads add the same service well one of them will fail and throw an exception // this event may be generated for a service that already exists if (geoServer.getService(ev.getSource().getId(), ServiceInfo.class) == null) { // this is a new service so let's add it to this GeoServer instance geoServer.add(ev.getSource()); } break; case REMOVED: // this service was removed so let's remove it from this geoserver geoServer.remove(ev.getSource()); break; } } catch (Exception e) { if (LOGGER.isLoggable(java.util.logging.Level.SEVERE)) LOGGER.severe(this.getClass() + " is unable to synchronize the incoming event: " + ev); throw e; } finally { producer.enable(); } return true; } /** * Starting from an incoming de-serialized ServiceInfo modify event, search for it (by name) into local geoserver and update changed members. * * @param geoServer local GeoServer instance * @param ev the incoming event * @return the localized and updated ServiceInfo to save * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException */ private static ServiceInfo localizeService(final GeoServer geoServer, final JMSServiceModifyEvent ev) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { if (geoServer == null || ev == null) throw new IllegalArgumentException("wrong passed arguments are null"); final ServiceInfo info = JMSServiceHandler.getLocalService(geoServer, ev); BeanUtils.smartUpdate(info, ev.getPropertyNames(), ev.getNewValues()); // LOCALIZE service info.setGeoServer(geoServer); return info; } /** * get local object searching by name if name is changed (remotely), search is performed using the old one * * @param geoServer * @param ev * */ public static ServiceInfo getLocalService(final GeoServer geoServer, final JMSServiceModifyEvent ev) { final ServiceInfo service = ev.getSource(); if (service == null) { throw new IllegalArgumentException("passed service is null"); } // localize service final ServiceInfo localObject; // check if name is changed final List<String> props = ev.getPropertyNames(); final int index = props.indexOf("name"); String serviceName = service.getName(); if (index != -1) { // the service name was updated so we need to use old service name final List<Object> oldValues = ev.getOldValues(); serviceName = oldValues.get(index).toString(); } if (service.getWorkspace() == null) { // no virtual service return geoServer.getServiceByName(serviceName, ServiceInfo.class); } // globals service return geoServer.getServiceByName(service.getWorkspace(), serviceName, ServiceInfo.class); } }