String outputFormat = request.getOutputFormat();
try {
delegate = FeatureResponse.getDelegate(outputFormat);
} catch (NoSuchElementException ex) {
throw new WfsException("output format: " + outputFormat + " not "
+ "supported by geoserver", ex);
}
if (request instanceof FeatureWithLockRequest) {
featureLock = ((FeatureWithLockRequest) request).toFeatureLock();
String authorization = featureLock.getAuthorization();
LOGGER.finest("FeatureWithLock using Lock:" + authorization);
}
GetFeatureResults results = new GetFeatureResults(request);
results.setFeatureLock(featureLock);
//
// Optimization Idea
//
// We should be able to reduce this to a two pass opperations.
//
// Pass #1 execute
// - Attempt to Locks Fids during the first pass
// - Also collect Bounds information during the first pass
//
// Pass #2 writeTo
// - Using the Bounds to describe our FeatureCollections
// - Iterate through FeatureResults producing GML
//
// And allways remember to release locks if we are failing:
// - if we fail to aquire all the locks we will need to fail and
// itterate through the the FeatureSources to release the locks
//
GeoServer config = request.getWFS().getGeoServer();
Data catalog = request.getWFS().getData();
FeatureTypeInfo meta = null;
NameSpaceInfo namespace;
Query query;
int maxFeatures = request.getMaxFeatures();
int serverMaxFeatures = config.getMaxFeatures();
if (maxFeatures > serverMaxFeatures) {
maxFeatures = serverMaxFeatures;
}
Set lockedFids = new HashSet();
Set lockFailedFids = new HashSet();
FeatureSource source;
Feature feature;
String fid;
FilterFactory filterFactory = FilterFactory.createFilterFactory();
FidFilter fidFilter;
int numberLocked;
try {
for (Iterator it = request.getQueries().iterator();
it.hasNext() && (maxFeatures > 0);) {
query = (Query) it.next();
meta = catalog.getFeatureTypeInfo(query.getTypeName());
namespace = meta.getDataStoreInfo().getNameSpace();
source = meta.getFeatureSource();
List attrs = meta.getAttributes();
List propNames = query.getPropertyNames(); // REAL LIST: be careful here :)
List attributeNames = meta.getAttributeNames();
for (Iterator iter = propNames.iterator(); iter.hasNext();) {
String propName = (String) iter.next();
if (!attributeNames.contains(propName)) {
String mesg = "Requested property: " + propName
+ " is " + "not available for "
+ query.getTypeName() + ". "
+ "The possible propertyName values are: "
+ attributeNames;
throw new WfsException(mesg);
}
}
if (propNames.size() != 0) {
Iterator ii = attrs.iterator();
List tmp = new LinkedList();
while (ii.hasNext()) {
AttributeTypeInfo ati = (AttributeTypeInfo) ii.next();
//String attName = (String) ii.next();
LOGGER.finer("checking to see if " + propNames
+ " contains" + ati);
if (((ati.getMinOccurs() > 0)
&& (ati.getMaxOccurs() != 0))
|| propNames.contains(ati.getName())) {
tmp.add(ati.getName());
}
}
query.setPropertyNames(tmp);
}
// This doesn't seem to be working?
// Run through features and record FeatureIDs
// Lock FeatureIDs as required
//}
LOGGER.fine("Query is " + query + "\n To gt2: "
+ query.toDataQuery(maxFeatures));
//DJB: note if maxFeatures gets to 0 the while loop above takes care of this! (this is a subtle situation)
FeatureResults features = source.getFeatures(query.toDataQuery(
maxFeatures));
if (it.hasNext()) //DJB: dont calculate feature count if you dont have to. The MaxFeatureReader will take care of the last iteration
maxFeatures -= features.getCount();
//GR: I don't know if the featuresults should be added here for later
//encoding if it was a lock request. may be after ensuring the lock
//succeed?
results.addFeatures(meta, features);
if (featureLock != null) {
// geotools2 locking code
if (source instanceof FeatureLocking) {
((FeatureLocking) source).setFeatureLock(featureLock);
}
FeatureReader reader = null;
try {
for (reader = features.reader(); reader.hasNext();) {
feature = reader.next();
fid = feature.getID();
if (!(source instanceof FeatureLocking)) {
LOGGER.finest("Lock " + fid
+ " not supported by data store (authID:"
+ featureLock.getAuthorization() + ")");
lockFailedFids.add(fid);
continue; // locking is not supported!
} else {
fidFilter = filterFactory.createFidFilter(fid);
numberLocked = ((FeatureLocking) source)
.lockFeatures(fidFilter);
if (numberLocked == 1) {
LOGGER.finest("Lock " + fid + " (authID:"
+ featureLock.getAuthorization() + ")");
lockedFids.add(fid);
} else if (numberLocked == 0) {
LOGGER.finest("Lock " + fid
+ " conflict (authID:"
+ featureLock.getAuthorization() + ")");
lockFailedFids.add(fid);
} else {
LOGGER.warning("Lock " + numberLocked + " "
+ fid + " (authID:"
+ featureLock.getAuthorization()
+ ") duplicated FeatureID!");
lockedFids.add(fid);
}
}
}
} finally {
if (reader != null) {
reader.close();
}
}
if (!lockedFids.isEmpty()) {
Transaction t = new DefaultTransaction();
try {
t.addAuthorization(featureLock.getAuthorization());
source.getDataStore().getLockingManager().refresh(featureLock
.getAuthorization(), t);
} finally {
t.commit();
}
}
}
}
//end for
//prepare to encode in the desired output format
delegate.prepare(outputFormat, results);
if ((featureLock != null) && !lockFailedFids.isEmpty()) {
// I think we need to release and fail when lockAll fails
//
// abort will take care of releasing the locks
throw new WfsException("Could not aquire locks for:"
+ lockFailedFids);
}
} catch (IOException e) {
throw new ServiceException(e, "problem with FeatureResults",
request.getHandle());