52n-wps-server-gcube/src/main/java/org/n52/wps/server/CapabilitiesConfiguration.java

466 lines
15 KiB
Java
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (C) 2007 - 2016 52°North Initiative for Geospatial Open Source
* Software GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* If the program is linked with libraries which are licensed under one of
* the following licenses, the combination of the program with the linked
* library is not considered a "derivative work" of the program:
*
* • Apache License, version 2.0
* • Apache Software License, version 1.0
* • GNU Lesser General Public License, version 3
* • Mozilla Public License, versions 1.0, 1.1 and 2.0
* • Common Development and Distribution License (CDDL), version 1.0
*
* Therefore the distribution of the program linked with libraries licensed
* under the aforementioned licenses, is permitted by the copyright holders
* if the distribution is compliant with both the GNU General Public
* License version 2 and the aforementioned licenses.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*/
package org.n52.wps.server;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.concurrent.locks.ReentrantLock;
import net.opengis.ows.x11.CodeType;
import net.opengis.ows.x11.DCPDocument.DCP;
import net.opengis.ows.x11.LanguageStringType;
import net.opengis.ows.x11.OperationDocument.Operation;
import net.opengis.ows.x11.RequestMethodType;
import net.opengis.wps.x100.CapabilitiesDocument;
import net.opengis.wps.x100.ProcessBriefType;
import net.opengis.wps.x100.ProcessDescriptionType;
import net.opengis.wps.x100.ProcessOfferingsDocument.ProcessOfferings;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.n52.wps.commons.WPSConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
/**
* Encapsulation of the WPS Capabilities document. This class has to be initialized with either a
* {@linkplain #getInstance(java.io.File) file}, {@linkplain #getInstance(java.net.URL) URL},
* {@linkplain #getInstance(java.lang.String) path} or
* {@linkplain #getInstance(net.opengis.wps.x100.CapabilitiesDocument) instance}.
*
* @author foerster
* @author Christian Autermann
*
*/
public class CapabilitiesConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(CapabilitiesConfiguration.class);
private static final ReentrantLock lock = new ReentrantLock();
private static CapabilitiesDocument capabilitiesDocumentObj;
private static CapabilitiesSkeletonLoadingStrategy loadingStrategy;
public static String ENDPOINT_URL;
private CapabilitiesConfiguration() {
/* nothing here */
}
/**
* Gets the WPS Capabilities using the specified file to obtain the skeleton. All future calls to
* {@link #getInstance()} and {@link #getInstance(boolean)
* } will use this file to obtain the skeleton.
*
* @param filePath
* the File pointing to a skeleton
*
* @return the capabilities document
*
* @throws XmlException
* if the Capabilities skeleton is not valid
* @throws IOException
* if an IO error occurs
*/
public static CapabilitiesDocument getInstance(String filePath) throws XmlException, IOException {
return getInstance(new FileLoadingStrategy(filePath));
}
/**
* Gets the WPS Capabilities using the specified file to obtain the skeleton. All future calls to
* {@link #getInstance()} and {@link #getInstance(boolean)
* } will use this file to obtain the skeleton.
*
* @param file
* the File pointing to a skeleton
*
* @return the capabilities document
*
* @throws XmlException
* if the Capabilities skeleton is not valid
* @throws IOException
* if an IO error occurs
*/
public static CapabilitiesDocument getInstance(File file) throws XmlException, IOException {
return getInstance(new FileLoadingStrategy(file));
}
/**
* Gets the WPS Capabilities using the specified URL to obtain the skeleton. All future calls to
* {@link #getInstance()} and {@link #getInstance(boolean)
* } will use this URL to obtain the skeleton.
*
* @param url
* the URL pointing to a skeleton
*
* @return the capabilities document
*
* @throws XmlException
* if the Capabilities skeleton is not valid
* @throws IOException
* if an IO error occurs
*/
public static CapabilitiesDocument getInstance(URL url) throws XmlException, IOException {
return getInstance(new URLLoadingStrategy(url));
}
/**
* Gets the WPS Capabilities using the specified skeleton. All future calls to {@link #getInstance()} and
* {@link #getInstance(boolean) } will use this skeleton.
*
* @param skel
* the skeleton
*
* @return the capabilities document
*
* @throws XmlException
* if the Capabilities skeleton is not valid
* @throws IOException
* if an IO error occurs
*/
public static CapabilitiesDocument getInstance(CapabilitiesDocument skel) throws XmlException, IOException {
return getInstance(new InstanceStrategy(skel));
}
/**
* Gets the WPS Capabilities using the specified strategy. All future calls to {@link #getInstance()} and
* {@link #getInstance(boolean) } will use this strategy.
*
* @param strategy
* the strategy to load the skeleton
*
* @return the capabilities document
*
* @throws XmlException
* if the Capabilities skeleton is not valid
* @throws IOException
* if an IO error occurs
*/
private static CapabilitiesDocument getInstance(CapabilitiesSkeletonLoadingStrategy strategy) throws XmlException,
IOException {
Preconditions.checkNotNull(strategy);
lock.lock();
try {
if (strategy.equals(loadingStrategy)) {
return getInstance(false);
}
else {
loadingStrategy = strategy;
return getInstance(true);
}
}
finally {
lock.unlock();
}
}
/**
* Get the WPS Capabilities for this service. The capabilities are reloaded if caching is not enabled in
* the WPS configuration.
*
* @return the capabilities document
*
* @throws XmlException
* if the Capabilities skeleton is not valid
* @throws IOException
* if an IO error occurs
*/
public static CapabilitiesDocument getInstance() throws XmlException, IOException {
return getInstance( !WPSConfig.getInstance().getWPSConfig().getServer().getCacheCapabilites());
}
/**
* Get the WPS Capabilities for this service and optionally force a reload.
*
* @param reload
* if the capabilities should be reloaded
*
* @return the capabilities document
*
* @throws XmlException
* if the Capabilities skeleton is not valid
* @throws IOException
* if an IO error occurs
*/
public static CapabilitiesDocument getInstance(boolean reload) throws XmlException, IOException {
lock.lock();
try {
if (capabilitiesDocumentObj == null || reload) {
capabilitiesDocumentObj = loadingStrategy.loadSkeleton();
initSkeleton(capabilitiesDocumentObj);
}
return capabilitiesDocumentObj;
}
finally {
lock.unlock();
}
}
/**
* Enriches a capabilities skeleton by adding the endpoint URL and creating the process offerings.
*
* @param skel
* the skeleton to enrich
*
* @throws UnknownHostException
* if the local host name can not be obtained
*/
private static void initSkeleton(CapabilitiesDocument skel) throws UnknownHostException {
ENDPOINT_URL = WPSConfig.getServerBaseURL() + "/" + WebProcessingService.SERVLET_PATH;
if (skel.getCapabilities() == null) {
skel.addNewCapabilities();
}
initOperationsMetadata(skel, ENDPOINT_URL);
initProcessOfferings(skel);
}
/**
* Enriches the capabilities skeleton by creating the process offerings.
*
* @param skel
* the skeleton to enrich
*/
private static void initProcessOfferings(CapabilitiesDocument skel) {
ProcessOfferings processes = skel.getCapabilities()
.addNewProcessOfferings();
for (String algorithmName : RepositoryManager.getInstance()
.getAlgorithms()) {
try {
ProcessDescriptionType description = RepositoryManager
.getInstance().getProcessDescription(algorithmName);
if (description != null) {
ProcessBriefType process = processes.addNewProcess();
CodeType ct = process.addNewIdentifier();
ct.setStringValue(algorithmName);
LanguageStringType title = description.getTitle();
String processVersion = description.getProcessVersion();
process.setProcessVersion(processVersion);
process.setTitle(title);
}
}
catch (RuntimeException e) {
LOG.warn("Exception during instantiation of process {}", algorithmName, e);
}
}
}
/**
* Enriches a capabilities skeleton by adding the endpoint URL to the operations meta data.
*
* @param skel
* the skeleton to enrich
* @param endpointUrl
* the endpoint URL of the service
*
*/
private static void initOperationsMetadata(CapabilitiesDocument skel, String endpointUrl) {
if (skel.getCapabilities().getOperationsMetadata() != null) {
String endpointUrlGet = endpointUrl + "?";
for (Operation op : skel.getCapabilities().getOperationsMetadata().getOperationArray()) {
for (DCP dcp : op.getDCPArray()) {
for (RequestMethodType get : dcp.getHTTP().getGetArray()) {
get.setHref(endpointUrlGet);
}
for (RequestMethodType post : dcp.getHTTP().getPostArray()) {
post.setHref(endpointUrl);
}
}
}
}
}
/**
* Force a reload of the capabilities skeleton.
*
* @throws XmlException
* if the Capabilities skeleton is not valid
* @throws IOException
* if an IO error occurs
*/
public static void reloadSkeleton() throws XmlException, IOException {
getInstance(true);
}
/**
* Checks if the capabilities document is loaded.
*
* @return if the capabilities are ready.
*/
public static boolean ready() {
lock.lock();
try {
return capabilitiesDocumentObj != null;
}
finally {
lock.unlock();
}
}
/**
* Strategy to load a capabilities skeleton from a URL.
*/
private static class URLLoadingStrategy implements CapabilitiesSkeletonLoadingStrategy {
private final URL url;
/**
* Creates a new strategy using the specified URL.
*
* @param file
* the file
*/
URLLoadingStrategy(URL url) {
this.url = Preconditions.checkNotNull(url);
}
@Override
public CapabilitiesDocument loadSkeleton() throws XmlException, IOException {
XmlOptions options = new XmlOptions().setLoadStripComments();
return CapabilitiesDocument.Factory.parse(getUrl(), options);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof URLLoadingStrategy) {
URLLoadingStrategy that = (URLLoadingStrategy) obj;
return this.getUrl().equals(that.getUrl());
}
return false;
}
@Override
public int hashCode() {
return getUrl().hashCode();
}
/**
* Gets the URL of this strategy.
*
* @return the URL;
*/
public URL getUrl() {
return url;
}
}
/**
* Strategy to load a capabilities skeleton from a file.
*/
private static class FileLoadingStrategy extends URLLoadingStrategy {
/**
* Creates a new strategy using the specified file.
*
* @param file
* the file
*/
FileLoadingStrategy(File file) throws MalformedURLException {
super(file.toURI().toURL());
}
/**
* Creates a new strategy using the specified file.
*
* @param file
* the path to the file
*/
FileLoadingStrategy(String file) throws MalformedURLException {
this(new File(Preconditions.checkNotNull(file)));
}
}
/**
* Strategy to obtain the capabilities skeleton from an existing instance.
*/
private static class InstanceStrategy implements CapabilitiesSkeletonLoadingStrategy {
private final CapabilitiesDocument instance;
/**
* Creates a new strategy using the specified instance.
*
* @param instance
* the instance
*/
InstanceStrategy(CapabilitiesDocument instance) {
this.instance = Preconditions.checkNotNull(instance);
}
@Override
public CapabilitiesDocument loadSkeleton() {
return (CapabilitiesDocument) getInstance().copy();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof InstanceStrategy) {
InstanceStrategy that = (InstanceStrategy) obj;
return this.getInstance().equals(that.getInstance());
}
return false;
}
@Override
public int hashCode() {
return getInstance().hashCode();
}
/**
* Gets the instance of this strategy.
*
* @return the instance
*/
public CapabilitiesDocument getInstance() {
return instance;
}
}
/**
* Strategy to load a capabilities skeleton.
*/
private interface CapabilitiesSkeletonLoadingStrategy {
/**
* Loads a CapabilitiesDocument skeleton. Every call to this method should return another instance.
*
* @return the capabilities skeleton
*
* @throws XmlException
* if the Capabilities skeleton is not valid
* @throws IOException
* if an IO error occurs
*/
CapabilitiesDocument loadSkeleton() throws XmlException, IOException;
}
}