/* (c) 2014 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.catalog;
import com.thoughtworks.xstream.XStream;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CatalogInfo;
import org.geoserver.catalog.event.CatalogEvent;
import org.geoserver.catalog.event.CatalogModifyEvent;
import org.geoserver.catalog.event.impl.CatalogModifyEventImpl;
import org.geoserver.catalog.impl.CatalogImpl;
import org.geoserver.cluster.JMSEventHandler;
import org.geoserver.cluster.JMSEventHandlerSPI;
import javax.jms.JMSException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
/**
* Abstract class which use Xstream as message serializer/de-serializer.
* We extend this class to implementing synchronize method.
*
* @author Carlo Cancellieri - carlo.cancellieri@geo-solutions.it
*
*/
public abstract class JMSCatalogEventHandler extends
JMSEventHandler<String, CatalogEvent> {
public JMSCatalogEventHandler(final XStream xstream,
Class<JMSEventHandlerSPI<String, CatalogEvent>> clazz) {
super(xstream,clazz);
// omit not serializable fields
omitFields();
}
/**
* omit not serializable fields
* @see {@link XStream}
*/
private void omitFields() {
// omit not serializable fields
xstream.omitField(CatalogImpl.class, "listeners");
xstream.omitField(CatalogImpl.class, "facade");
xstream.omitField(CatalogImpl.class, "resourcePool");
xstream.omitField(CatalogImpl.class, "resourceLoader");
}
@Override
public String serialize(CatalogEvent event) throws Exception {
return xstream.toXML(removeCatalogProperties(event));
}
@Override
public CatalogEvent deserialize(String s) throws Exception {
final Object source= xstream.fromXML(s);
if (source instanceof CatalogEvent) {
final CatalogEvent ev = (CatalogEvent) source;
if (LOGGER.isLoggable(Level.FINE)) {
final CatalogInfo info = ev.getSource();
LOGGER.fine("Incoming message event of type CatalogEvent: "
+ info.getId());
}
return ev;
} else {
throw new JMSException("Unable to deserialize the following object:\n"+s);
}
}
/**
* Make sure that properties of type catalog are not serialized
* for catalog modified events.
*/
private CatalogEvent removeCatalogProperties(CatalogEvent event) {
if (!(event instanceof CatalogModifyEvent)) {
// not a modify event so nothing to do
return event;
}
CatalogModifyEvent modifyEvent = (CatalogModifyEvent) event;
// index all the properties that are not of catalog type
List<Integer> indexes = new ArrayList<>();
int totalProperties = modifyEvent.getPropertyNames().size();
for (int i = 0; i < totalProperties; i++) {
// we only need to check the new values
Object value = modifyEvent.getNewValues().get(i);
if (!(value instanceof Catalog)) {
// not a property of type catalog
indexes.add(i);
}
}
// let's see if we need to do anything
if (indexes.size() == totalProperties) {
// no properties of type catalog, we can use the original event
return event;
}
// well we need to create a new modify event and ignore the properties of catalog type
List<String> properties = new ArrayList<>();
List<Object> oldValues = new ArrayList<>();
List<Object> newValues = new ArrayList<>();
for (int index : indexes) {
// add all the properties that are not of catalog type
properties.add(modifyEvent.getPropertyNames().get(index));
oldValues.add(modifyEvent.getOldValues().get(index));
newValues.add(modifyEvent.getNewValues().get(index));
}
// crete the new event
CatalogModifyEventImpl newEvent = new CatalogModifyEventImpl();
newEvent.setPropertyNames(properties);
newEvent.setOldValues(oldValues);
newEvent.setNewValues(newValues);
newEvent.setSource(modifyEvent.getSource());
return newEvent;
}
}