/* (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.script.wfs; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; import net.opengis.wfs.TransactionResponseType; import net.opengis.wfs.TransactionType; import org.geoserver.platform.resource.Resource; import org.geoserver.script.ScriptManager; import org.geoserver.wfs.TransactionEvent; import org.geoserver.wfs.TransactionEventType; import org.geoserver.wfs.TransactionPlugin; import org.geoserver.wfs.WFSException; import org.geotools.util.SoftValueHashMap; import org.geotools.util.logging.Logging; import com.google.common.base.Function; import com.google.common.collect.Iterators; public class ScriptTransactionPlugin implements TransactionPlugin { static Logger LOGGER = Logging.getLogger(ScriptTransactionPlugin.class); ScriptManager scriptMgr; SoftValueHashMap<Resource, ScriptTxDelegate> delegates = new SoftValueHashMap<Resource, ScriptTxDelegate>(); public ScriptTransactionPlugin(ScriptManager scriptMgr) { this.scriptMgr = scriptMgr; } @Override public void dataStoreChange(final TransactionEvent event) throws WFSException { TransactionDetail details = details(event.getRequest()); details.update(event); foreach(delegates(), new Function<ScriptTxDelegate, Void>() { @Override public Void apply(@Nullable ScriptTxDelegate input) { TransactionEventType type = event.getType(); if (type == TransactionEventType.PRE_INSERT) { input.preInsert(event); } else if (type == TransactionEventType.POST_INSERT) { input.postInsert(event); } else if (type == TransactionEventType.PRE_UPDATE) { input.preUpdate(event); } else if (type == TransactionEventType.POST_UPDATE) { input.postUpdate(event); } else if (type == TransactionEventType.PRE_DELETE) { input.preDelete(event); } else { //TODO: POST_DELETE } return null; } }); } void foreach(Iterator<ScriptTxDelegate> it, Function<ScriptTxDelegate, Void> f) { while(it.hasNext()) { f.apply(it.next()); } } @Override public TransactionType beforeTransaction(TransactionType request) throws WFSException { for (Iterator<ScriptTxDelegate> it = delegates(); it.hasNext();) { ScriptTxDelegate delegate = it.next(); request = delegate.beforeTransaction(request); } return request; } @Override public void beforeCommit(TransactionType request) throws WFSException { for (Iterator<ScriptTxDelegate> it = delegates(); it.hasNext();) { ScriptTxDelegate delegate = it.next(); delegate.beforeCommit(request); } } @Override public void afterTransaction(TransactionType request, TransactionResponseType result, boolean committed) { for (Iterator<ScriptTxDelegate> it = delegates(); it.hasNext();) { ScriptTxDelegate delegate = it.next(); delegate.afterTransaction(request, result, committed); } } @Override public int getPriority() { //return normal priority for now... we may want to up this or scan through all the scripts // and return whatever the highest priority is return 0; } TransactionDetail details(TransactionType request) { Map context = request.getExtendedProperties(); TransactionDetail details = (TransactionDetail) context.get(TransactionDetail.class); if (details == null) { details = new TransactionDetail(); context.put(TransactionDetail.class, details); } return details; } Iterator<ScriptTxDelegate> delegates() { List<Resource> files; try { files = scriptMgr.wfsTx().list(); } catch (IOException e) { LOGGER.log(Level.WARNING, "Error listing files in wfs/tx directory", e); return Iterators.emptyIterator(); } return Iterators.transform(files.iterator(), new Function<Resource, ScriptTxDelegate>() { @Override public ScriptTxDelegate apply(@Nullable Resource input) { return delegate(input); } }); } ScriptTxDelegate delegate(Resource f) { ScriptTxDelegate delegate = delegates.get(f); if (delegate == null) { synchronized (this) { delegate = delegates.get(f); if (delegate == null) { delegate = new ScriptTxDelegate(f, scriptMgr); delegates.put(f, delegate); } } } return delegate; } }