📄 transaction.java
字号:
/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.geoserver.wfs;
import net.opengis.wfs.ActionType;
import net.opengis.wfs.AllSomeType;
import net.opengis.wfs.InsertedFeatureType;
import net.opengis.wfs.TransactionResponseType;
import net.opengis.wfs.TransactionType;
import net.opengis.wfs.WfsFactory;
import org.acegisecurity.Authentication;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.userdetails.UserDetails;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.ServiceException;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FeatureSource;
import org.geotools.data.FeatureStore;
import org.geotools.xml.EMFUtils;
import org.opengis.filter.FilterFactory;
import org.springframework.context.ApplicationContext;
import org.vfny.geoserver.global.Data;
import org.vfny.geoserver.global.FeatureTypeInfo;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
/**
* Web Feature Service Transaction operation.
*
* @author Justin Deoliveira, The Open Planning Project
*
*/
public class Transaction {
/**
* logger
*/
static Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geoserver.wfs");
/**
* WFS configuration
*/
protected WFS wfs;
/**
* The catalog
*/
protected Data catalog;
/**
* Filter factory
*/
protected FilterFactory filterFactory;
/** Geotools2 transaction used for this opperations */
protected org.geotools.data.Transaction transaction;
protected List transactionElementHandlers = new ArrayList();
protected List transactionListeners = new ArrayList();
protected List transactionPlugins = new ArrayList();
public Transaction(WFS wfs, Data catalog, ApplicationContext context) {
this.wfs = wfs;
this.catalog = catalog;
// register element handlers, listeners and plugins
transactionElementHandlers.addAll(GeoServerExtensions.extensions(TransactionElementHandler.class));
transactionListeners.addAll(GeoServerExtensions.extensions(TransactionListener.class));
transactionPlugins.addAll(GeoServerExtensions.extensions(TransactionPlugin.class));
// plugins are listeners too, but I want to make sure they are notified
// of
// changes in the same order as the other plugin callbacks
transactionListeners.removeAll(transactionPlugins);
// sort plugins according to priority
Collections.sort(transactionPlugins, new TransactionPluginComparator());
}
public void setFilterFactory(FilterFactory filterFactory) {
this.filterFactory = filterFactory;
}
public TransactionResponseType transaction(TransactionType request)
throws WFSException {
// make sure server is supporting transactions
if ((wfs.getServiceLevel() & WFS.TRANSACTIONAL) == 0) {
throw new WFSException("Transaction support is not enabled");
}
try {
return execute(request);
} catch (WFSException e) {
abort(request); // release any locks
throw e;
} catch (Exception e) {
abort(request); // release any locks
throw new WFSException(e);
}
}
/**
* Execute Transaction request.
*
* <p>
* The results of this opperation are stored for use by writeTo:
*
* <ul>
* <li> transaction: used by abort & writeTo to commit/rollback </li>
* <li> request: used for users getHandle information to report errors </li>
* <li> stores: FeatureStores required for Transaction </li>
* <li> failures: List of failures produced </li>
* </ul>
* </p>
*
* <p>
* Because we are using geotools2 locking facilities our modification will
* simply fail with IOException if we have not provided proper
* authorization.
* </p>
*
* <p>
* The specification allows a WFS to implement PARTIAL sucess if it is
* unable to rollback all the requested changes. This implementation is able
* to offer full Rollback support and will not require the use of PARTIAL
* success.
* </p>
*
* @param transactionRequest
*
* @throws ServiceException
* DOCUMENT ME!
* @throws WfsException
* @throws WfsTransactionException
* DOCUMENT ME!
*/
protected TransactionResponseType execute(TransactionType request)
throws Exception {
// some defaults
if (request.getReleaseAction() == null) {
request.setReleaseAction(AllSomeType.ALL_LITERAL);
}
// inform plugins we're about to start, and let them eventually
// alter the request
for (Iterator it = transactionPlugins.iterator(); it.hasNext();) {
TransactionPlugin tp = (TransactionPlugin) it.next();
tp.beforeTransaction(request);
}
// setup the transaction listener multiplexer
TransactionListenerMux multiplexer = new TransactionListenerMux();
// the geotools transaction
transaction = getDatastoreTransaction(request);
//
// We are going to preprocess our elements,
// gathering all the FeatureSources we need
//
// Map of required FeatureStores by typeName
Map stores = new HashMap();
// Map of required FeatureStores by typeRef (dataStoreId:typeName)
// (This will be added to the contents are harmed)
Map stores2 = new HashMap();
// List of type names, maintain this list because of the insert hack
// described below
// List typeNames = new ArrayList();
Map elementHandlers = gatherElementHandlers(request.getGroup());
// Gather feature types required by transaction elements and validate
// the elements
// finally gather FeatureStores required by Transaction Elements
// and configure them with our transaction
//
// (I am using element rather than transaction sub request
// to agree with the spec docs)
for (Iterator it = elementHandlers.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
EObject element = (EObject) entry.getKey();
TransactionElementHandler handler = (TransactionElementHandler) entry.getValue();
Map featureTypeInfos = new HashMap();
QName[] typeNames = handler.getTypeNames(element);
for (int i = 0; i < typeNames.length; i++) {
final QName typeName = typeNames[i];
final String name = typeName.getLocalPart();
final String namespaceURI;
if (typeName.getNamespaceURI() != null) {
namespaceURI = typeName.getNamespaceURI();
} else {
namespaceURI = catalog.getDefaultNameSpace().getURI();
}
LOGGER.fine("Locating FeatureSource uri:'" + namespaceURI + "' name:'" + name + "'");
final FeatureTypeInfo meta = catalog.getFeatureTypeInfo(name, namespaceURI);
if (meta == null) {
String msg = name + " is not available: ";
String handle = (String) EMFUtils.get(element, "handle");
throw new WFSTransactionException(msg, (String) null, handle);
}
featureTypeInfos.put(typeName, meta);
}
// check element validity
handler.checkValidity(element, featureTypeInfos);
// go through all feature type infos data objects, and load feature
// stores
for (Iterator m = featureTypeInfos.values().iterator(); m.hasNext();) {
FeatureTypeInfo meta = (FeatureTypeInfo) m.next();
String typeRef = meta.getDataStoreInfo().getId() + ":" + meta.getTypeName();
String URI = meta.getNameSpace().getURI();
QName elementName = new QName(URI, meta.getTypeName(),
meta.getNameSpace().getPrefix());
QName elementNameDefault = null;
if (catalog.getDefaultNameSpace().getURI().equals(URI)) {
elementNameDefault = new QName(meta.getTypeName());
}
LOGGER.fine("located FeatureType w/ typeRef '" + typeRef + "' and elementName '"
+ elementName + "'");
if (stores.containsKey(elementName)) {
// typeName already loaded
continue;
}
try {
FeatureSource source = meta.getFeatureSource();
if (source instanceof FeatureStore) {
FeatureStore store = (FeatureStore) source;
store.setTransaction(transaction);
stores.put(elementName, source);
if (elementNameDefault != null) {
stores.put(elementNameDefault, source);
}
stores2.put(typeRef, source);
} else {
String msg = elementName + " is read-only";
String handle = (String) EMFUtils.get(element, "handle");
throw new WFSTransactionException(msg, (String) null, handle);
}
} catch (IOException ioException) {
String msg = elementName + " is not available: "
+ ioException.getLocalizedMessage();
String handle = (String) EMFUtils.get(element, "handle");
throw new WFSTransactionException(msg, ioException, handle);
}
}
}
// provide authorization for transaction
//
String authorizationID = request.getLockId();
if (authorizationID != null) {
if ((wfs.getServiceLevel() & WFS.SERVICE_LOCKING) == 0) {
throw new WFSException("Lock support is not enabled");
}
LOGGER.finer("got lockId: " + authorizationID);
if (!lockExists(authorizationID)) {
String mesg = "Attempting to use a lockID that does not exist"
+ ", it has either expired or was entered wrong.";
throw new WFSException(mesg, "InvalidParameterValue");
}
try {
transaction.addAuthorization(authorizationID);
} catch (IOException ioException) {
// This is a real failure - not associated with a element
//
throw new WFSException("Authorization ID '" + authorizationID + "' not useable",
ioException);
}
}
// result
TransactionResponseType result = WfsFactory.eINSTANCE.createTransactionResponseType();
result.setTransactionResults(WfsFactory.eINSTANCE.createTransactionResultsType());
result.getTransactionResults().setHandle(request.getHandle());
result.setTransactionSummary(WfsFactory.eINSTANCE.createTransactionSummaryType());
result.getTransactionSummary().setTotalInserted(BigInteger.valueOf(0));
result.getTransactionSummary().setTotalUpdated(BigInteger.valueOf(0));
result.getTransactionSummary().setTotalDeleted(BigInteger.valueOf(0));
result.setInsertResults(WfsFactory.eINSTANCE.createInsertResultsType());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -