001: //$Header: /deegreerepository/deegree/src/org/deegree/ogcwebservices/wfs/TransactionHandler.java,v 1.69 2007/03/14 14:41:43 mschneider Exp $
002: /*---------------- FILE HEADER ------------------------------------------
003:
004: This file is part of deegree.
005: Copyright (C) 2001-2008 by:
006: EXSE, Department of Geography, University of Bonn
007: http://www.giub.uni-bonn.de/deegree/
008: lat/lon GmbH
009: http://www.lat-lon.de
010:
011: This library is free software; you can redistribute it and/or
012: modify it under the terms of the GNU Lesser General Public
013: License as published by the Free Software Foundation; either
014: version 2.1 of the License, or (at your option) any later version.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: Contact:
026:
027: Andreas Poth
028: lat/lon GmbH
029: Aennchenstraße 19
030: 53177 Bonn
031: Germany
032: E-Mail: poth@lat-lon.de
033:
034: Prof. Dr. Klaus Greve
035: Department of Geography
036: University of Bonn
037: Meckenheimer Allee 166
038: 53115 Bonn
039: Germany
040: E-Mail: greve@giub.uni-bonn.de
041:
042: ---------------------------------------------------------------------------*/
043:
044: package org.deegree.ogcwebservices.wfs;
045:
046: import java.util.ArrayList;
047: import java.util.HashMap;
048: import java.util.Iterator;
049: import java.util.List;
050: import java.util.Map;
051: import java.util.Set;
052:
053: import org.deegree.datatypes.QualifiedName;
054: import org.deegree.framework.log.ILogger;
055: import org.deegree.framework.log.LoggerFactory;
056: import org.deegree.i18n.Messages;
057: import org.deegree.io.datastore.Datastore;
058: import org.deegree.io.datastore.DatastoreException;
059: import org.deegree.io.datastore.DatastoreTransaction;
060: import org.deegree.io.datastore.FeatureId;
061: import org.deegree.io.datastore.LockManager;
062: import org.deegree.io.datastore.PropertyPathResolver;
063: import org.deegree.io.datastore.idgenerator.FeatureIdAssigner;
064: import org.deegree.io.datastore.schema.MappedFeaturePropertyType;
065: import org.deegree.io.datastore.schema.MappedFeatureType;
066: import org.deegree.io.datastore.schema.MappedGMLSchema;
067: import org.deegree.model.feature.Feature;
068: import org.deegree.model.feature.FeatureCollection;
069: import org.deegree.model.feature.FeatureProperty;
070: import org.deegree.model.feature.GMLFeatureAdapter;
071: import org.deegree.model.feature.GMLFeatureCollectionDocument;
072: import org.deegree.model.feature.Validator;
073: import org.deegree.model.feature.schema.FeatureType;
074: import org.deegree.model.feature.schema.PropertyType;
075: import org.deegree.ogcbase.PropertyPath;
076: import org.deegree.ogcbase.PropertyPathStep;
077: import org.deegree.ogcwebservices.OGCWebServiceException;
078: import org.deegree.ogcwebservices.wfs.operation.transaction.Delete;
079: import org.deegree.ogcwebservices.wfs.operation.transaction.Insert;
080: import org.deegree.ogcwebservices.wfs.operation.transaction.InsertResults;
081: import org.deegree.ogcwebservices.wfs.operation.transaction.Native;
082: import org.deegree.ogcwebservices.wfs.operation.transaction.Transaction;
083: import org.deegree.ogcwebservices.wfs.operation.transaction.TransactionOperation;
084: import org.deegree.ogcwebservices.wfs.operation.transaction.TransactionResponse;
085: import org.deegree.ogcwebservices.wfs.operation.transaction.Update;
086: import org.deegree.ogcwebservices.wfs.operation.transaction.Insert.ID_GEN;
087: import org.deegree.ogcwebservices.wfs.operation.transaction.Transaction.RELEASE_ACTION;
088:
089: /**
090: * Handler for transaction requests to the {@link WFService}.
091: * <p>
092: * If the used backend does not support atomic transactions, it is possible that one part fails
093: * while another works well. Depending on definitions made in the OGC WFS 1.1.0 specification in
094: * this case it is possible that even if a sub part of the request fails no exception will be
095: * thrown. In this case the result objects contains informations on the parts of the request that
096: * worked and that did not.
097: *
098: * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider </a>
099: * @author <a href="mailto:deshmukh@lat-lon.de">Anup Deshmukh </a>
100: * @author last edited by: $Author: apoth $
101: *
102: * @version $Revision: 9345 $, $Date: 2007-12-27 08:22:25 -0800 (Thu, 27 Dec 2007) $
103: */
104: class TransactionHandler {
105:
106: private static final ILogger LOG = LoggerFactory
107: .getLogger(TransactionHandler.class);
108:
109: private WFService service;
110:
111: private Transaction request;
112:
113: private Map<QualifiedName, MappedFeatureType> ftMap;
114:
115: // filled by #acquireDSTransactions()
116: private Map<QualifiedName, DatastoreTransaction> taMap = new HashMap<QualifiedName, DatastoreTransaction>();
117:
118: // filled by #acquireDSTransactions()
119: private Map<Datastore, DatastoreTransaction> dsToTaMap = new HashMap<Datastore, DatastoreTransaction>();
120:
121: /**
122: * Creates a new <code>TransactionHandler</code> instance.
123: *
124: * @param service
125: * @param request
126: */
127: TransactionHandler(WFService service, Transaction request) {
128: this .service = service;
129: this .request = request;
130: this .ftMap = service.getMappedFeatureTypes();
131: }
132:
133: /**
134: * Performs the associated transaction.
135: *
136: * @return transaction response
137: * @throws OGCWebServiceException
138: * if an error occured
139: */
140: TransactionResponse handleRequest() throws OGCWebServiceException {
141:
142: validate(this .request);
143:
144: TransactionResponse response = null;
145:
146: acquireDSTransactions();
147:
148: try {
149: try {
150: response = performOperations();
151: } catch (OGCWebServiceException e) {
152: abortDSTransactions();
153: throw e;
154: }
155: commitDSTransactions();
156: if (request.getLockId() != null
157: && request.getReleaseAction() == RELEASE_ACTION.ALL) {
158: try {
159: LockManager.getInstance().releaseLock(
160: request.getLockId());
161: } catch (DatastoreException e) {
162: LOG.logInfo(e.getMessage());
163: }
164: }
165: } finally {
166: releaseDSTransactions();
167: }
168:
169: return response;
170: }
171:
172: /**
173: * Validates the feature instances in the given transaction against the WFS' application
174: * schemas.
175: * <p>
176: * The feature instances are assigned the corresponding <code>MappedFeatureType</code> in the
177: * process.
178: *
179: * @param request
180: * @throws OGCWebServiceException
181: */
182: private void validate(Transaction request)
183: throws OGCWebServiceException {
184:
185: List<TransactionOperation> operations = request.getOperations();
186:
187: Iterator<TransactionOperation> iter = operations.iterator();
188: while (iter.hasNext()) {
189: TransactionOperation operation = iter.next();
190: if (operation instanceof Insert) {
191: validateInsert((Insert) operation);
192: } else if (operation instanceof Delete) {
193: validateDelete((Delete) operation);
194: } else if (operation instanceof Update) {
195: validateUpdate((Update) operation);
196: } else if (operation instanceof Native) {
197: // nothing to do
198: } else {
199: String msg = "Internal error. Unhandled transaction operation type '"
200: + operation.getClass().getName() + "'.";
201: throw new OGCWebServiceException(this .getClass()
202: .getName(), msg);
203: }
204: }
205: }
206:
207: /**
208: * Validates all feature instances in the given insert operation against the WFS' application
209: * schemas.
210: * <p>
211: * The feature instances are assigned the corresponding <code>MappedFeatureType</code> in the
212: * process.
213: *
214: * @param operation
215: * @throws OGCWebServiceException
216: */
217: @SuppressWarnings("unchecked")
218: private void validateInsert(Insert operation)
219: throws OGCWebServiceException {
220: FeatureCollection fc = operation.getFeatures();
221: if (LOG.getLevel() == ILogger.LOG_DEBUG) {
222: try {
223: GMLFeatureAdapter ada = new GMLFeatureAdapter(false);
224: GMLFeatureCollectionDocument doc = ada.export(fc);
225: LOG.logDebugXMLFile(
226: "TransactionHandler_insert_incoming", doc);
227: } catch (Exception e) {
228: LOG.logError(e.getMessage(), e);
229: }
230: }
231: Validator validator = new Validator((Map) this .service
232: .getMappedFeatureTypes());
233: for (int i = 0; i < fc.size(); i++) {
234: validator.validate(fc.getFeature(i));
235: }
236: }
237:
238: /**
239: * Validates all feature instances in the given insert operation against the WFS' application
240: * schemas.
241: * <p>
242: * The feature instances are assigned the corresponding <code>MappedFeatureType</code> in the
243: * process.
244: *
245: * @param operation
246: * @throws OGCWebServiceException
247: */
248: private void validateDelete(Delete operation)
249: throws OGCWebServiceException {
250: QualifiedName ftName = operation.getTypeName();
251: MappedFeatureType ft = this .ftMap.get(ftName);
252: if (ft == null) {
253: String msg = Messages.getMessage(
254: "WFS_DELETE_FEATURE_TYPE_UNKNOWN", ftName);
255: throw new OGCWebServiceException(this .getClass().getName(),
256: msg);
257: }
258: if (ft.isAbstract()) {
259: String msg = Messages.getMessage(
260: "WFS_DELETE_FEATURE_TYPE_ABSTRACT", ftName);
261: throw new OGCWebServiceException(this .getClass().getName(),
262: msg);
263: }
264: }
265:
266: /**
267: * Validates any feature instance in the given update operation against the WFS' application
268: * schemas.
269: * <p>
270: * Feature instances are assigned the corresponding <code>MappedFeatureType</code> in the
271: * process, property names are normalized and their values are parsed into the respective
272: * objects.
273: *
274: * @param operation
275: * update operation
276: * @throws OGCWebServiceException
277: */
278: @SuppressWarnings("unchecked")
279: private void validateUpdate(Update operation)
280: throws OGCWebServiceException {
281:
282: QualifiedName ftName = operation.getTypeName();
283: MappedFeatureType ft = this .ftMap.get(ftName);
284: if (ft == null) {
285: String msg = Messages.getMessage(
286: "WFS_UPDATE_FEATURE_TYPE_UNKNOWN", ftName);
287: throw new OGCWebServiceException(this .getClass().getName(),
288: msg);
289: }
290:
291: Feature feature = operation.getFeature();
292: if (feature != null) {
293: Validator validator = new Validator((Map) this .service
294: .getMappedFeatureTypes());
295: validator.validate(feature);
296: } else {
297: validateProperties(ft, operation);
298: }
299: }
300:
301: /**
302: * Validates the properties and their replacement values that are specified in the given
303: * <code>Update</code> operation.
304: * <p>
305: * Property names are normalized and their values are parsed into the respective objects.
306: *
307: * @param ft
308: * feature type
309: * @param operation
310: * update operation
311: * @throws OGCWebServiceException
312: */
313: private void validateProperties(MappedFeatureType ft,
314: Update operation) throws OGCWebServiceException {
315:
316: Map<PropertyPath, FeatureProperty> replacementProps = operation
317: .getReplacementProperties();
318: Map<PropertyPath, FeatureProperty> normalizedProps = new HashMap<PropertyPath, FeatureProperty>();
319:
320: for (PropertyPath path : replacementProps.keySet()) {
321: FeatureProperty property = replacementProps.get(path);
322: path = PropertyPathResolver.normalizePropertyPath(ft, null,
323: path);
324: validateProperty(ft, path, property);
325: normalizedProps.put(path, property);
326: }
327:
328: // remove all mappings and add normalized ones
329: replacementProps.clear();
330: for (PropertyPath path : normalizedProps.keySet()) {
331: replacementProps.put(path, normalizedProps.get(path));
332: }
333: }
334:
335: /**
336: * Validates the property name and it's replacement value.
337: * <p>
338: * Values are parsed into the respective objects.
339: *
340: * @param ft
341: * feature type
342: * @param path
343: * property name
344: * @param replacementProperty
345: * replacement property value (as XML node)
346: * @throws OGCWebServiceException
347: */
348: private void validateProperty(MappedFeatureType ft,
349: PropertyPath path, FeatureProperty replacementProperty)
350: throws OGCWebServiceException {
351:
352: for (int i = 0; i < path.getSteps(); i += 2) {
353: // check if feature step is valid
354: PropertyPathStep ftStep = path.getStep(i);
355: FeatureType stepFt = this .ftMap.get(ftStep
356: .getPropertyName());
357: if (stepFt == null) {
358: String msg = Messages.getMessage(
359: "WFS_UPDATE_FEATURE_STEP_UNKNOWN", path, stepFt
360: .getName());
361: throw new OGCWebServiceException(this .getClass()
362: .getName(), msg);
363: }
364: MappedGMLSchema schema = ft.getGMLSchema();
365: if (!schema.isValidSubstitution(ft, stepFt)) {
366: String msg = Messages.getMessage(
367: "WFS_UPDATE_FEATURE_STEP_INVALID", path, stepFt
368: .getName(), ft.getName());
369: throw new OGCWebServiceException(this .getClass()
370: .getName(), msg);
371: }
372:
373: // check if property step is valid
374: PropertyPathStep propertyStep = path.getStep(i + 1);
375: QualifiedName propertyName = propertyStep.getPropertyName();
376: PropertyType pt = ft.getProperty(propertyName);
377: if (pt == null) {
378: String msg = Messages.getMessage(
379: "WFS_UPDATE_PROPERTY_STEP_UNKNOWN", path,
380: propertyName, ft.getName());
381: throw new OGCWebServiceException(this .getClass()
382: .getName(), msg);
383: }
384: if (i + 2 == path.getSteps()) {
385: if (replacementProperty.getValue() == null
386: && pt.getMinOccurs() > 0) {
387: String msg = Messages.getMessage(
388: "WFS_UPDATE_PROPERTY_NULL_INVALID", path,
389: pt.getMinOccurs());
390: throw new OGCWebServiceException(this .getClass()
391: .getName(), msg);
392: }
393: if (replacementProperty.getValue() instanceof Feature) {
394: Validator validator = new Validator(
395: (Map) this .service.getMappedFeatureTypes());
396: validator.validate((Feature) replacementProperty
397: .getValue());
398: }
399: } else {
400: if (!(pt instanceof MappedFeaturePropertyType)) {
401: String msg = Messages.getMessage(
402: "WFS_UPDATE_NOT_FEATURE_PROPERTY", path,
403: propertyName);
404: throw new OGCWebServiceException(this .getClass()
405: .getName(), msg);
406: }
407: MappedFeaturePropertyType fpt = (MappedFeaturePropertyType) pt;
408: ft = fpt.getFeatureTypeReference().getFeatureType();
409: }
410: }
411: }
412:
413: /**
414: * Performs the operations contained in the transaction.
415: *
416: * @throws OGCWebServiceException
417: */
418: private TransactionResponse performOperations()
419: throws OGCWebServiceException {
420:
421: int inserts = 0;
422: int deletes = 0;
423: int updates = 0;
424:
425: List<InsertResults> insertResults = new ArrayList<InsertResults>();
426: List<TransactionOperation> operations = request.getOperations();
427:
428: Iterator<TransactionOperation> iter = operations.iterator();
429: while (iter.hasNext()) {
430: TransactionOperation operation = iter.next();
431: String handle = operation.getHandle();
432: try {
433: if (operation instanceof Insert) {
434: List<FeatureId> insertedFIDs = performInsert((Insert) operation);
435: InsertResults results = new InsertResults(handle,
436: insertedFIDs);
437: insertResults.add(results);
438: inserts += insertedFIDs.size();
439: } else if (operation instanceof Delete) {
440: deletes += performDelete((Delete) operation);
441: } else if (operation instanceof Update) {
442: updates += performUpdate((Update) operation);
443: } else if (operation instanceof Native) {
444: String msg = Messages
445: .getMessage("WFS_NATIVE_OPERATIONS_UNSUPPORTED");
446: throw new OGCWebServiceException(this .getClass()
447: .getName(), msg);
448: } else {
449: String opType = operation.getClass().getName();
450: String msg = Messages.getMessage(
451: "WFS_UNHANDLED_OPERATION_TYPE", opType);
452: throw new OGCWebServiceException(this .getClass()
453: .getName(), msg);
454: }
455: } catch (DatastoreException e) {
456: LOG.logError(e.getMessage(), e);
457: String msg = "A datastore exception occured during the processing of operation with handle '"
458: + handle + "': " + e.getMessage();
459: throw new OGCWebServiceException(this .getClass()
460: .getName(), msg);
461: }
462: }
463: TransactionResponse response = new TransactionResponse(request,
464: inserts, updates, deletes, insertResults);
465: return response;
466: }
467:
468: /**
469: * Performs the given insert operation.
470: *
471: * @param insert
472: * insert operation to be performed
473: * @throws DatastoreException
474: */
475: private List<FeatureId> performInsert(Insert insert)
476: throws DatastoreException {
477:
478: List<FeatureId> fids = new ArrayList<FeatureId>();
479: FeatureCollection fc = insert.getFeatures();
480:
481: // merge all equal and anonymous features (without fid)
482: FeatureDisambiguator merger = new FeatureDisambiguator(fc);
483: if (insert.getIdGen() == ID_GEN.USE_EXISTING) {
484: if (merger.checkForAnonymousFeatures()) {
485: String msg = Messages
486: .getMessage("WFS_INSERT_USE_EXISTING_AND_NO_FID");
487: throw new DatastoreException(msg);
488: }
489: }
490: fc = merger.mergeFeatures();
491:
492: if (LOG.getLevel() == ILogger.LOG_DEBUG) {
493: try {
494: GMLFeatureAdapter ada = new GMLFeatureAdapter(false);
495: GMLFeatureCollectionDocument doc = ada.export(fc);
496: LOG.logDebugXMLFile("TransactionHandler_insert_merged",
497: doc);
498: } catch (Exception e) {
499: LOG.logError(e.getMessage(), e);
500: }
501: }
502:
503: Map<DatastoreTransaction, List<Feature>> taFeaturesMap = new HashMap<DatastoreTransaction, List<Feature>>();
504: FeatureIdAssigner fidAssigner = new FeatureIdAssigner(insert
505: .getIdGen());
506:
507: // assign features to corresponding datastore transactions
508: for (int i = 0; i < fc.size(); i++) {
509: Feature feature = fc.getFeature(i);
510: QualifiedName ftName = feature.getName();
511: DatastoreTransaction dsTa = this .taMap.get(ftName);
512: // reassign feature ids (if necessary)
513: fidAssigner.assignFID(feature, dsTa);
514: List<Feature> features = taFeaturesMap.get(dsTa);
515: if (features == null) {
516: features = new ArrayList<Feature>();
517: taFeaturesMap.put(dsTa, features);
518: }
519: features.add(feature);
520: }
521:
522: // TODO remove this hack
523: fidAssigner.markStoredFeatures();
524:
525: if (LOG.getLevel() == ILogger.LOG_DEBUG) {
526: try {
527: GMLFeatureAdapter ada = new GMLFeatureAdapter(false);
528: GMLFeatureCollectionDocument doc = ada.export(fc);
529: LOG.logDebugXMLFile("TransactionHandler_insert_marked",
530: doc);
531: } catch (Exception e) {
532: LOG.logError(e.getMessage(), e);
533: }
534: }
535:
536: Iterator<DatastoreTransaction> taIter = taFeaturesMap.keySet()
537: .iterator();
538: while (taIter.hasNext()) {
539: DatastoreTransaction ta = taIter.next();
540: List<Feature> features = taFeaturesMap.get(ta);
541: fids.addAll(ta.performInsert(features));
542: }
543: return fids;
544: }
545:
546: /**
547: * Performs the given delete operation.
548: *
549: * @param delete
550: * delete operation to be performed
551: * @throws DatastoreException
552: */
553: private int performDelete(Delete delete) throws DatastoreException {
554:
555: QualifiedName ftName = delete.getTypeName();
556: MappedFeatureType ft = this .ftMap.get(ftName);
557: DatastoreTransaction dsTa = this .taMap.get(ftName);
558: int deleted = dsTa.performDelete(ft, delete.getFilter(),
559: this .request.getLockId());
560: return deleted;
561: }
562:
563: /**
564: * Performs the given update operation.
565: * <p>
566: * Assigning of FIDs to replacment features is performed in the {@link DatastoreTransaction}.
567: *
568: * @param update
569: * update operation to be perform
570: * @throws DatastoreException
571: */
572: private int performUpdate(Update update) throws DatastoreException {
573:
574: QualifiedName ftName = update.getTypeName();
575: MappedFeatureType ft = this .ftMap.get(ftName);
576: DatastoreTransaction dsTa = this .taMap.get(ftName);
577: int updated = 0;
578: if (update.getFeature() == null) {
579: updated = dsTa.performUpdate(ft, update
580: .getReplacementProperties(), update.getFilter(),
581: this .request.getLockId());
582: } else {
583: updated = dsTa.performUpdate(ft, update.getFeature(),
584: update.getFilter(), this .request.getLockId());
585: }
586: return updated;
587: }
588:
589: /**
590: * Acquires the necessary <code>DatastoreTransaction</code>s. For each participating
591: * <code>Datastore</code>, one transaction is needed.
592: * <p>
593: * Fills the <code>taMap</code> and <code>dsToTaMap</code> members of this class.
594: *
595: * @throws OGCWebServiceException
596: * if a feature type is unknown or a DatastoreTransaction could not be acquired
597: */
598: private void acquireDSTransactions() throws OGCWebServiceException {
599: Set<QualifiedName> ftNames = this .request
600: .getAffectedFeatureTypes();
601: for (QualifiedName ftName : ftNames) {
602: MappedFeatureType ft = this .ftMap.get(ftName);
603: if (ft == null) {
604: String msg = "FeatureType '" + ftName
605: + "' is not known to the WFS.";
606: throw new OGCWebServiceException(this .getClass()
607: .getName(), msg);
608: }
609: Datastore ds = ft.getGMLSchema().getDatastore();
610: DatastoreTransaction dsTa = this .dsToTaMap.get(ds);
611: if (dsTa == null) {
612: try {
613: dsTa = ds.acquireTransaction();
614: } catch (DatastoreException e) {
615: LOG.logError(e.getMessage(), e);
616: String msg = "Could not acquire transaction for FeatureType '"
617: + ftName + "'.";
618: throw new OGCWebServiceException(this .getClass()
619: .getName(), msg);
620: }
621: this .dsToTaMap.put(ds, dsTa);
622: }
623: this .taMap.put(ftName, dsTa);
624: }
625: }
626:
627: /**
628: * Releases all acquired <code>DatastoreTransaction</code>s.
629: *
630: * @throws OGCWebServiceException
631: * if a DatastoreTransaction could not be released
632: */
633: private void releaseDSTransactions() throws OGCWebServiceException {
634: String msg = "";
635: for (DatastoreTransaction dsTa : this .dsToTaMap.values()) {
636: LOG.logDebug("Releasing DatastoreTransaction " + dsTa);
637: try {
638: dsTa.release();
639: } catch (DatastoreException e) {
640: LOG.logError("Error releasing DatastoreTransaction: "
641: + e.getMessage(), e);
642: msg += e.getMessage() + "\n";
643: }
644: }
645: if (msg.length() != 0) {
646: msg = "Could not release one or more DatastoreTransactions: "
647: + msg;
648: throw new OGCWebServiceException(this .getClass().getName(),
649: msg);
650: }
651: }
652:
653: /**
654: * Commits all pending <code>DatastoreTransaction</code>s.
655: *
656: * @throws OGCWebServiceException
657: * if a DatastoreException could not be committed
658: */
659: private void commitDSTransactions() throws OGCWebServiceException {
660: String msg = "";
661: for (DatastoreTransaction dsTa : this .dsToTaMap.values()) {
662: LOG.logDebug("Committing DatastoreTransaction " + dsTa);
663: try {
664: dsTa.commit();
665: } catch (DatastoreException e) {
666: LOG.logError("Error committing DatastoreTransaction: "
667: + e.getMessage(), e);
668: msg += e.getMessage() + "\n";
669: }
670: }
671: if (msg.length() != 0) {
672: msg = "Could not commit one or more DatastoreTransactions: "
673: + msg;
674: throw new OGCWebServiceException(this .getClass().getName(),
675: msg);
676: }
677: }
678:
679: /**
680: * Aborts all pending <code>DatastoreTransaction</code>s.
681: *
682: * @throws OGCWebServiceException
683: * if a DatastoreException could not be aborted
684: */
685: private void abortDSTransactions() throws OGCWebServiceException {
686: String msg = "";
687: for (DatastoreTransaction dsTa : this .dsToTaMap.values()) {
688: LOG.logDebug("Aborting DatastoreTransaction " + dsTa);
689: try {
690: dsTa.rollback();
691: } catch (DatastoreException e) {
692: LOG.logError("Error aborting DatastoreTransaction: "
693: + e.getMessage(), e);
694: msg += e.getMessage() + "\n";
695: }
696: }
697: if (msg.length() != 0) {
698: msg = "Could not abort one or more DatastoreTransactions: "
699: + msg;
700: throw new OGCWebServiceException(this.getClass().getName(),
701: msg);
702: }
703: }
704: }
|