001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
002: * This code is licensed under the GPL 2.0 license, availible at the root
003: * application directory.
004: */
005: package org.geoserver.wfs;
006:
007: import net.opengis.wfs.GetCapabilitiesType;
008: import org.geotools.util.Version;
009: import org.vfny.geoserver.global.Data;
010: import java.util.Iterator;
011: import java.util.TreeSet;
012:
013: /**
014: * Web Feature Service GetCapabilities operation.
015: * <p>
016: * This operation returns a {@link org.geotools.xml.transform.TransformerBase} instance
017: * which will serialize the wfs capabilities document. This class uses ows version negotiation
018: * to determine which version of the wfs capabilities document to return.
019: * </p>
020: *
021: * @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org
022: *
023: */
024: public class GetCapabilities {
025: /**
026: * WFS service configuration
027: */
028: WFS wfs;
029:
030: /**
031: * The catalog
032: */
033: Data catalog;
034:
035: /**
036: * Creates a new wfs GetCapabilitis operation.
037: *
038: * @param wfs The wfs configuration
039: * @param catalog The geoserver catalog.
040: */
041: public GetCapabilities(WFS wfs, Data catalog) {
042: this .wfs = wfs;
043: this .catalog = catalog;
044: }
045:
046: public CapabilitiesTransformer run(GetCapabilitiesType request)
047: throws WFSException {
048: //cite requires that we fail when we see an "invalid" update sequence,
049: // since we dont support update sequences, all are invalid, but we take
050: // our more lax approach and just ignore it when not doint the cite thing
051: if (wfs.getCiteConformanceHacks()) {
052: if (request.getUpdateSequence() != null) {
053: throw new WFSException("Invalid update sequence",
054: "InvalidUpdateSequence");
055: }
056: }
057:
058: //TODO: the rest of this routine should be done by the dispatcher
059: //make sure service is set, cite conformance thing
060: //JD - We wrap this in a cite conformance check because cite stricly
061: // tests that every request includes the 'service=WFS' key value pair.
062: // However often the the context of the request is good enough to
063: // determine what the service is, like in 'geoserver/wfs?request=GetCapabilities'
064: if (wfs.getCiteConformanceHacks()) {
065: if (!request.isSetService()) {
066: //give up
067: throw new WFSException("Service not set",
068: "MissingParameterValue", "service");
069: }
070: }
071:
072: //do the version negotiation dance
073:
074: //any accepted versions
075: if ((request.getAcceptVersions() == null)
076: || request.getAcceptVersions().getVersion().isEmpty()) {
077: //no, respond with highest
078: return new CapabilitiesTransformer.WFS1_1(wfs, catalog);
079: }
080:
081: //first check the format of each of the version numbers
082: for (Iterator i = request.getAcceptVersions().getVersion()
083: .iterator(); i.hasNext();) {
084: String version = (String) i.next();
085:
086: if (!version.matches("[0-99]\\.[0-99]\\.[0-99]")) {
087: String msg = version + " is an invalid version numver";
088: throw new WFSException(msg, "VersionNegotiationFailed");
089: }
090: }
091:
092: //first figure out which versions are provided
093: //TODO: use an extension point?
094: TreeSet provided = new TreeSet();
095: provided.add(new Version("1.0.0"));
096: provided.add(new Version("1.1.0"));
097:
098: //next figure out what the client accepts
099: TreeSet accepted = new TreeSet();
100:
101: for (Iterator v = request.getAcceptVersions().getVersion()
102: .iterator(); v.hasNext();) {
103: accepted.add(new Version((String) v.next()));
104: }
105:
106: //prune out those not provided
107: for (Iterator v = accepted.iterator(); v.hasNext();) {
108: Version version = (Version) v.next();
109:
110: if (!provided.contains(version)) {
111: v.remove();
112: }
113: }
114:
115: String version = null;
116:
117: if (!accepted.isEmpty()) {
118: //return the highest version provided
119: version = ((Version) accepted.last()).toString();
120: } else {
121: accepted = new TreeSet();
122:
123: for (Iterator v = request.getAcceptVersions().getVersion()
124: .iterator(); v.hasNext();) {
125: accepted.add(new Version((String) v.next()));
126: }
127:
128: //if highest accepted less then lowest provided, send lowest
129: if (((Version) accepted.last()).compareTo(provided.first()) < 0) {
130: version = ((Version) provided.first()).toString();
131: }
132:
133: //if lowest accepted is greater then highest provided, send highest
134: if (((Version) accepted.first()).compareTo(provided.last()) > 0) {
135: version = ((Version) provided.last()).toString();
136: }
137:
138: if (version == null) {
139: //go through from lowest to highest, and return highest provided
140: // that is less than the highest accepted
141: Iterator v = provided.iterator();
142: Version last = (Version) v.next();
143:
144: for (; v.hasNext();) {
145: Version current = (Version) v.next();
146:
147: if (current.compareTo(accepted.last()) > 0) {
148: break;
149: }
150:
151: last = current;
152: }
153:
154: version = last.toString();
155: }
156: }
157:
158: if ("1.0.0".equals(version)) {
159: return new CapabilitiesTransformer.WFS1_0(wfs, catalog);
160: }
161:
162: if ("1.1.0".equals(version)) {
163: return new CapabilitiesTransformer.WFS1_1(wfs, catalog);
164: }
165:
166: throw new WFSException("Could not understand version:"
167: + version);
168: }
169: }
|