/* (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.wfs;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import org.eclipse.emf.ecore.EObject;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.ows.Request;
import org.geoserver.ows.WorkspaceQualifyingCallback;
import org.geoserver.ows.util.OwsUtils;
import org.geoserver.platform.Operation;
import org.geoserver.platform.Service;
import org.geoserver.wfs.request.DescribeFeatureTypeRequest;
import org.geoserver.wfs.request.GetCapabilitiesRequest;
import org.geoserver.wfs.request.GetFeatureRequest;
import org.geoserver.wfs.request.Insert;
import org.geoserver.wfs.request.Lock;
import org.geoserver.wfs.request.LockFeatureRequest;
import org.geoserver.wfs.request.Query;
import org.geoserver.wfs.request.TransactionElement;
import org.geoserver.wfs.request.TransactionRequest;
import org.opengis.feature.Feature;
import org.opengis.feature.type.Name;
public class WFSWorkspaceQualifier extends WorkspaceQualifyingCallback {
public WFSWorkspaceQualifier(Catalog catalog) {
super(catalog);
}
@Override
protected void qualifyRequest(WorkspaceInfo workspace, LayerInfo layer, Service service, Request request) {
if (request.getContext() != null) {
// if a qualifying workspace exist, try to qualify the request typename
// parameter, if present
if (workspace != null && request.getKvp().containsKey("TYPENAME")) {
Iterable typeNames = (Iterable) request.getKvp().get("TYPENAME");
NamespaceInfo ns = catalog
.getNamespaceByPrefix(workspace.getName());
if (ns != null) {
List<QName> qualifiedNames = new ArrayList<QName>();
for (Object name : typeNames) {
if (name != null && name instanceof QName) {
QName typeName = (QName) name;
// no namespace specified, we can qualify
if (typeName.getNamespaceURI() == null
|| typeName.getNamespaceURI().equals("")) {
typeName = new QName(ns.getURI(),
typeName.getLocalPart());
} else if (typeName.getNamespaceURI().equals(
catalog.getDefaultNamespace().getURI())) {
// more complex case, if we have the default
// namespace, we have to check if it's been
// specified on the request, or assigned by parser
typeName = checkDefaultNamespace(request, ns,
typeName);
}
qualifiedNames.add(typeName);
}
}
request.getKvp().put("TYPENAME", qualifiedNames);
}
}
}
}
/**
* Checks if the typeName default namespace is present
* in the original request, or it has been overridden by
* parser. If it's been overridden we can qualify with
* the given namespace.
*
* @param request
* @param ns
* @param typeName
* @return
*/
private QName checkDefaultNamespace(Request request, NamespaceInfo ns,
QName typeName) {
Map<String, String[]> originalParams = request
.getHttpRequest().getParameterMap();
for (String paramName : originalParams.keySet()) {
if (paramName.equalsIgnoreCase("TYPENAME")) {
for (String originalTypeName : originalParams
.get(paramName)) {
if (originalTypeName.equals(typeName
.getLocalPart())) {
// the original typeName was not
// qualified, we can qualify it
typeName = new QName(ns.getURI(),
typeName.getLocalPart());
}
}
}
}
return typeName;
}
@Override
protected void qualifyRequest(WorkspaceInfo workspace, LayerInfo layer, Operation operation, Request request) {
NamespaceInfo ns = catalog.getNamespaceByPrefix(workspace.getName());
GetCapabilitiesRequest caps = GetCapabilitiesRequest.adapt(
OwsUtils.parameter(operation.getParameters(), EObject.class));
if (caps != null) {
caps.setNamespace(workspace.getName());
return;
}
DescribeFeatureTypeRequest dft = DescribeFeatureTypeRequest.adapt(
OwsUtils.parameter(operation.getParameters(), EObject.class));
if (dft != null) {
qualifyTypeNames(dft.getTypeNames(), workspace, ns);
return;
}
GetFeatureRequest gf = GetFeatureRequest.adapt(
OwsUtils.parameter(operation.getParameters(), EObject.class));
if (gf != null) {
for (Query q : gf.getQueries()) {
qualifyTypeNames(q.getTypeNames(), workspace, ns);
}
return;
}
LockFeatureRequest lf = LockFeatureRequest.adapt(
OwsUtils.parameter(operation.getParameters(), EObject.class));
if (lf != null) {
for (Lock lock : lf.getLocks()) {
lock.setTypeName(qualifyTypeName(lock.getTypeName(), workspace, ns));
}
return;
}
TransactionRequest t = TransactionRequest.adapt(
OwsUtils.parameter(operation.getParameters(), EObject.class));
if (t != null) {
for (TransactionElement el : t.getElements()) {
if (el instanceof Insert) {
Insert in = (Insert) el;
//in the insert case the objects are gt feature types which are not mutable
// so we just check them and throw an exception if a name does not match
for (Iterator j = in.getFeatures().iterator(); j.hasNext(); ) {
Feature f = (Feature) j.next();
Name n = f.getType().getName();
if (n.getNamespaceURI() != null && !ns.getURI().equals(n.getNamespaceURI())) {
throw new WFSException(t, "No such feature type " + n);
}
}
}
else {
el.setTypeName(qualifyTypeName(el.getTypeName(), workspace, ns));
}
}
}
}
void qualifyTypeNames(List names, WorkspaceInfo ws, NamespaceInfo ns) {
for (int i = 0; i < names.size(); i++) {
QName name = (QName) names.get(i);
names.set(i, qualifyTypeName(name, ws, ns));
}
}
QName qualifyTypeName(QName name, WorkspaceInfo ws, NamespaceInfo ns) {
return new QName(ns.getURI(), name.getLocalPart(), ws.getName());
}
}