ingo@1022: /* ingo@1022: * Copyright (c) 2010 by Intevation GmbH ingo@1022: * ingo@1022: * This program is free software under the LGPL (>=v2.1) ingo@1022: * Read the file LGPL.txt coming with the software for details ingo@1022: * or visit http://www.gnu.org/licenses/ if it does not exist. ingo@1022: */ ingo@1022: tim@2: package de.intevation.gnv.artifactdatabase.client; tim@2: tim@1005: import java.io.IOException; tim@1005: import java.io.InputStream; tim@1005: import java.io.InputStreamReader; tim@1005: import java.io.OutputStream; tim@1005: import java.io.OutputStreamWriter; tim@1005: import java.util.ArrayList; tim@1005: import java.util.Collection; tim@1005: import java.util.HashMap; tim@1005: import java.util.Iterator; tim@1005: import java.util.List; tim@1005: import java.util.Locale; tim@1005: import java.util.Map; tim@1005: tim@1005: import org.apache.log4j.Logger; tim@1005: import org.restlet.Client; ingo@1027: import org.restlet.Request; ingo@1027: import org.restlet.Response; tim@1005: import org.restlet.data.ClientInfo; tim@1005: import org.restlet.data.Language; tim@1005: import org.restlet.data.Method; tim@1005: import org.restlet.data.Preference; tim@1005: import org.restlet.data.Protocol; tim@1005: import org.restlet.representation.Representation; tim@1005: import org.restlet.representation.StringRepresentation; tim@1005: import org.w3c.dom.Document; tim@1005: import org.w3c.dom.Element; tim@1005: import org.w3c.dom.Node; tim@1005: import org.w3c.dom.NodeList; tim@1005: tim@2: import de.intevation.gnv.artifactdatabase.client.exception.ArtifactDatabaseClientException; ingo@665: import de.intevation.gnv.artifactdatabase.client.exception.ArtifactDatabaseInputException; tim@7: import de.intevation.gnv.artifactdatabase.objects.Artifact; tim@9: import de.intevation.gnv.artifactdatabase.objects.ArtifactDescription; tim@2: import de.intevation.gnv.artifactdatabase.objects.ArtifactFactory; tim@2: import de.intevation.gnv.artifactdatabase.objects.ArtifactObject; tim@164: import de.intevation.gnv.artifactdatabase.objects.ArtifactStatisticsSet; tim@32: import de.intevation.gnv.artifactdatabase.objects.DefaultArtifactStatisticValue; tim@164: import de.intevation.gnv.artifactdatabase.objects.DefaultArtifactStatisticsSet; ingo@573: import de.intevation.gnv.artifactdatabase.objects.DefaultExportMode; tim@30: import de.intevation.gnv.artifactdatabase.objects.DefaultOutputMode; tim@30: import de.intevation.gnv.artifactdatabase.objects.DefaultOutputParameter; ingo@573: import de.intevation.gnv.artifactdatabase.objects.ExportMode; tim@12: import de.intevation.gnv.artifactdatabase.objects.InputParameter; tim@30: import de.intevation.gnv.artifactdatabase.objects.OutputMode; tim@30: import de.intevation.gnv.artifactdatabase.objects.OutputParameter; tim@558: import de.intevation.gnv.artifactdatabase.objects.ParametrizedArtifactFactory; tim@558: import de.intevation.gnv.artifactdatabase.objects.ParametrizedArtifactObject; tim@558: import de.intevation.gnv.artifactdatabase.objects.map.Layer; tim@402: import de.intevation.gnv.artifactdatabase.objects.map.MapService; tim@23: import de.intevation.gnv.propertiesreader.PropertiesReader; tim@23: import de.intevation.gnv.propertiesreader.PropertiesReaderFactory; tim@2: import de.intevation.gnv.util.XMLUtils; tim@2: tim@2: /** ingo@690: * The default implementation of ArtifactDatabaseClient which ingo@690: * implements methods to communicate via HTTP protocol with the artifact server. sascha@699: * sascha@684: * @author Tim Englich sascha@684: * @author Ingo Weinzierl tim@2: */ tim@2: public class DefaultArtifactDatabaseClient implements ArtifactDatabaseClient { tim@2: /** tim@7: * The URI of the namespace of the artifacts. tim@7: */ tim@7: public final static String NAMESPACE_URI = "http://www.intevation.de/2009/artifacts"; tim@36: tim@7: /** tim@7: * The XML prefix for the artifacts namespace. tim@7: */ tim@7: public final static String NAMESPACE_PREFIX = "art"; tim@7: tim@7: /** ingo@665: * Xpath expression to get general exception messages related to server ingo@665: * errors. ingo@665: */ ingo@665: public static final String EXCEPTION_GENERAL = ingo@665: "/art:exceptionreport/art:exception/text()"; ingo@665: ingo@665: /** ingo@665: * Xpath expression to get exception messages related to invalid user input. ingo@665: */ ingo@665: public static final String EXCEPTION_USER_INPUT = ingo@665: "/art:exceptionreport/art:exception/art:input/text()"; ingo@665: ingo@665: /** tim@2: * the logger, used to log exceptions and additonaly information tim@2: */ tim@36: private static Logger log = Logger tim@36: .getLogger(DefaultArtifactDatabaseClient.class); tim@36: tim@25: /** tim@25: * The Databases which could be used tim@25: */ tim@25: private static Collection artifactDatabases = null; tim@36: tim@25: /** tim@25: * Is the Class initialized? tim@25: */ tim@2: private static boolean initialized = false; tim@36: tim@2: /** tim@40: * Request locale tim@40: */ tim@40: private Locale locale; tim@40: tim@40: tim@40: /** tim@2: * Constructor tim@2: */ tim@2: public DefaultArtifactDatabaseClient() { sascha@681: tim@2: } tim@2: tim@36: public Collection getArtifactFactories() ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException { tim@2: Collection resultValues = null; tim@36: if (!initialized) { tim@2: this.initialize(); tim@2: } tim@2: try { tim@2: log.debug("DefaultArtifactDatabaseClient.getArtifactFactories"); tim@25: Iterator it = artifactDatabases.iterator(); tim@36: while (it.hasNext()) { tim@2: String server = it.next(); tim@36: String url = server + "/factories"; tim@9: Document document = this.doGetRequest(url); tim@36: if (resultValues == null) { tim@565: resultValues = this.getArtifactFactories(document, server,null); tim@36: } else { tim@36: resultValues.addAll(this.getArtifactFactories(document, tim@565: server,null)); tim@2: } tim@2: } tim@2: } catch (IOException e) { tim@36: log.error(e, e); tim@47: throw new ArtifactDatabaseClientException(e); tim@2: } tim@2: return resultValues; tim@2: } tim@2: ingo@690: ingo@690: /** ingo@690: * Returns a collection of artifact factories retrieved by server. sascha@699: * ingo@690: * @param document ingo@690: * @param server ingo@690: * @param geometry ingo@690: * @return a collection of factories. ingo@690: */ tim@36: private Collection getArtifactFactories(Document document, tim@565: String server, tim@565: String geometry) { ingo@690: NodeList artifactFactories = XMLUtils.getNodeSetXPath(document, ingo@389: "/art:result/art:factories/art:factory"); tim@36: Collection resultValues = new ArrayList( tim@36: artifactFactories.getLength()); tim@36: if (artifactFactories != null) { tim@36: for (int i = 0; i < artifactFactories.getLength(); i++) { tim@36: Node artifactFactoryNode = artifactFactories.item(i); ingo@690: String name = XMLUtils.getStringXPath(artifactFactoryNode, ingo@389: "@art:name"); ingo@690: String description = XMLUtils.getStringXPath( ingo@389: artifactFactoryNode, "@art:description"); sascha@681: ingo@690: NodeList parameterNodeList = XMLUtils.getNodeSetXPath( tim@558: artifactFactoryNode, tim@558: "art:parameter"); sascha@681: sascha@681: if ((parameterNodeList != null && sascha@681: parameterNodeList.getLength() > 0) || tim@565: geometry != null){ sascha@681: Collection parameters = tim@558: new ArrayList(parameterNodeList.getLength()); tim@558: for (int j = 0; j < parameterNodeList.getLength(); j++){ tim@558: Element parameterNode = (Element)parameterNodeList.item(j); tim@558: parameters.add(parameterNode.getAttribute("id")); tim@558: } sascha@681: ParametrizedArtifactObject pao = sascha@681: new ParametrizedArtifactFactory(name, tim@558: description, tim@558: server); tim@558: pao.addParameters("parameter", parameters); tim@558: resultValues.add(pao); tim@565: if (geometry != null){ tim@565: Collection geometryList = new ArrayList(1); tim@565: geometryList.add(geometry); tim@565: pao.addParameters("geometry",geometryList); tim@565: } tim@558: }else{ tim@558: ArtifactObject artifactFactory = new ArtifactFactory(name, tim@558: description, tim@558: server); tim@558: resultValues.add(artifactFactory); tim@558: } tim@2: } tim@2: } ingo@389: log.debug("Artifact Factories: " + resultValues.size()); tim@2: return resultValues; tim@2: } tim@36: ingo@690: ingo@665: private Document doGetRequest(String requestUrl) ingo@665: throws IOException, ArtifactDatabaseClientException, ArtifactDatabaseInputException { tim@13: return this.doGetRequest(requestUrl, null); tim@13: } tim@36: ingo@690: tim@36: private Document doGetRequest(String requestUrl, Document requestBody) ingo@665: throws IOException, ArtifactDatabaseClientException, ArtifactDatabaseInputException { tim@25: XMLUtils xmlUtils = new XMLUtils(); tim@13: Representation output = doGetRequestInternal(requestUrl, requestBody); ingo@690: Document document = XMLUtils.readDocument(output.getStream()); tim@25: this.check4ExceptionReport(document); tim@25: return document; tim@13: } tim@13: tim@40: protected Request initialize(Request request) { tim@40: return initialize(request, locale); tim@40: } tim@40: ingo@690: /** ingo@690: * Initialize the ClientInfo object of request with the ingo@690: * given locale. ingo@690: * ingo@690: * @param request The request object. ingo@690: * @param locale The locale. ingo@690: * @return the prepared request object. ingo@690: */ tim@40: protected Request initialize(Request request, Locale locale) { tim@40: if (locale != null) { tim@40: ClientInfo clientInfo = request.getClientInfo(); tim@40: String lang = locale.getLanguage(); tim@40: Language language = new Language(lang); tim@40: List> acceptedLanguages = tim@40: new ArrayList>(2); tim@40: acceptedLanguages.add(new Preference(language, 1.0f)); tim@40: acceptedLanguages.add(new Preference(Language.ALL, 0.5f)); tim@40: clientInfo.setAcceptedLanguages(acceptedLanguages); tim@40: } tim@40: return request; tim@40: } tim@40: ingo@690: tim@13: private Representation doGetRequestInternal(String requestUrl, tim@47: Document requestBody) throws IOException { tim@13: Client client = new Client(Protocol.HTTP); tim@40: Request request = initialize(new Request(Method.GET, requestUrl)); tim@36: if (requestBody != null) { ingo@690: String documentBody = XMLUtils tim@36: .writeDocument2String(requestBody); tim@36: Representation representation = new StringRepresentation( tim@36: documentBody); tim@13: request.setEntity(representation); tim@13: } tim@13: Response response = client.handle(request); tim@47: if (response.getStatus().getCode() != 200){ tim@47: throw new IOException(response.getStatus().getDescription()); tim@47: } tim@13: Representation output = response.getEntity(); tim@13: return output; tim@13: } tim@36: ingo@690: tim@36: private InputStream doPostRequest(String requestUrl, Document requestBody) tim@38: throws IOException { tim@1005: tim@1005: log.debug("URL: "+ requestUrl); tim@1005: log.debug("Body"); tim@1005: log.debug(XMLUtils.writeDocument2String(requestBody)); tim@1005: tim@7: Client client = new Client(Protocol.HTTP); tim@40: Request request = initialize(new Request(Method.POST, requestUrl)); ingo@690: String documentBody = XMLUtils.writeDocument2String(requestBody); tim@7: Representation representation = new StringRepresentation(documentBody); tim@7: request.setEntity(representation); tim@7: Response response = client.handle(request); tim@47: if (response.getStatus().getCode() != 200){ tim@47: throw new IOException(response.getStatus().getDescription()); tim@47: } tim@7: Representation output = response.getEntity(); tim@7: return output.getStream(); tim@7: } tim@36: tim@36: private synchronized void initialize() { tim@36: if (!initialized) { tim@36: PropertiesReader pr = PropertiesReaderFactory.getInstance() tim@36: .getPropertiesReader(); tim@36: int count = Integer.parseInt(pr.getPropertieValue( tim@36: ARTIFACTDATABASE_COUNT_ID, "0")); tim@25: artifactDatabases = new ArrayList(count); tim@36: for (int i = 0; i < count; i++) { tim@36: artifactDatabases.add(pr.getPropertieValue( tim@36: ARTIFACTDATABASE_URL_ID + "." + (i + 1), "N/N")); tim@23: } tim@2: initialized = true; tim@2: } tim@36: tim@2: } tim@7: ingo@690: tim@7: /** ingo@690: * Creates a new artifact with the given artifactFactory. A POST call ingo@690: * is sent to the artifact server which creates a new artifact. ingo@690: * ingo@690: * @param artifactFactory The artifact factory used to create a new ingo@690: * artifact. ingo@690: * @return the created artifact of the artifact server. ingo@690: * @throws ArtifactDatabaseClientException ingo@690: * @throws ArtifactDatabaseInputException tim@7: */ tim@7: public ArtifactObject createNewArtifact(ArtifactObject artifactFactory) ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException { tim@36: tim@7: try { tim@558: Document request = this.createCreateRequestBody(artifactFactory); tim@9: Document result = doPostRequest(artifactFactory, request, "create"); tim@7: return this.getArtifact(result); tim@7: } catch (IOException e) { tim@36: log.error(e, e); tim@7: throw new ArtifactDatabaseClientException(e); tim@7: } tim@7: } tim@36: ingo@690: /** ingo@690: * Returns a new artifact defined by uuid and hash values of the document ingo@690: * returned by the artifact server after creating a new artifact. sascha@699: * ingo@690: * @param document Contains information about the server-side created ingo@690: * artifact. ingo@690: * @return a new artifact object. ingo@690: */ tim@36: private ArtifactObject getArtifact(Document document) { tim@35: XMLUtils xmlUtils = new XMLUtils(); ingo@690: String uuid = XMLUtils.getStringXPath(document, "/art:result/art:uuid/@value"); ingo@690: String hash = XMLUtils.getStringXPath(document, "/art:result/art:hash/@value"); tim@36: log.info("NEW Artifact: " + uuid + " / " + hash); tim@7: return new Artifact(uuid, hash); tim@7: } tim@36: tim@558: private Document createCreateRequestBody(ArtifactObject artifactFactory) { ingo@690: Document document = XMLUtils.newDocument(); tim@36: Node rootNode = this.createRootNode(document); tim@7: Element typeNode = this.createArtifactElement(document, "type"); tim@7: typeNode.setAttribute("name", "create"); tim@7: rootNode.appendChild(typeNode); tim@36: tim@558: Element factoryNode = this.createArtifactElement(document, "factory"); tim@558: factoryNode.setAttribute("name", artifactFactory.getId()); tim@558: rootNode.appendChild(factoryNode); sascha@681: tim@558: if (artifactFactory instanceof ParametrizedArtifactObject){ sascha@681: Map> parameterMap = tim@558: ((ParametrizedArtifactObject)artifactFactory).getParameters(); tim@558: if (parameterMap != null && !parameterMap.isEmpty() ){ tim@558: Iterator keyIt = parameterMap.keySet().iterator(); tim@558: while (keyIt.hasNext()){ tim@558: String key = keyIt.next(); tim@558: Iterator valueIt = parameterMap.get(key).iterator(); tim@558: while (valueIt.hasNext()){ tim@558: String value = valueIt.next(); sascha@681: Element parameterNode = tim@558: this.createArtifactElement(document, "parameter"); tim@558: parameterNode.setAttribute("name", key); tim@558: parameterNode.setAttribute("value", value); tim@558: factoryNode.appendChild(parameterNode); tim@558: } tim@558: } tim@558: } tim@558: } tim@7: return document; tim@7: } tim@36: tim@36: private Element createRootNode(Document document) { tim@36: Element rootNode = this.createArtifactElement(document, "action"); tim@7: document.appendChild(rootNode); tim@7: return rootNode; tim@7: } tim@36: ingo@690: tim@7: private Element createArtifactElement(Document document, String name) { ingo@391: XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( ingo@391: document, ingo@391: NAMESPACE_URI, ingo@391: NAMESPACE_PREFIX ingo@391: ); ingo@391: ingo@391: return creator.create(name); tim@7: } tim@9: ingo@690: tim@25: private Document doPostRequest(ArtifactObject artifactFactory, ingo@665: Document request, String suburl) ingo@665: throws IOException, ArtifactDatabaseClientException, ArtifactDatabaseInputException { tim@25: XMLUtils xmlUtils = new XMLUtils(); tim@36: String url = ((ArtifactFactory) artifactFactory).getDataBaseUrl(); tim@36: InputStream is = this.doPostRequest(url + "/" + suburl, request); ingo@690: Document result = XMLUtils.readDocument(is); tim@25: this.check4ExceptionReport(result); tim@25: return result; tim@25: } tim@9: ingo@690: tim@9: /** ingo@690: * Retrieve the current artifact description after calling the describe ingo@690: * operation of the artifact server. sascha@699: * ingo@690: * @param artifactFactory ingo@690: * @param currentArtifact ingo@690: * @param includeUI Set this option to true, if the user interface ingo@690: * description is required. ingo@690: * @return the artifact description. ingo@690: * @throws ArtifactDatabaseClientException ingo@690: * @throws ArtifactDatabaseInputException tim@9: */ tim@36: public ArtifactDescription getCurrentStepDescription( ingo@665: ArtifactObject artifactFactory, ingo@665: ArtifactObject currentArtifact, ingo@665: boolean includeUI) ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException { tim@9: try { tim@12: String url = this.getArtifactUrl(artifactFactory, currentArtifact); tim@157: Document request = this.createDescribeRequestBody(currentArtifact, tim@157: includeUI); tim@157: InputStream describeResult = this.doPostRequest(url, request); sascha@681: ingo@690: return this.readDescription(XMLUtils.readDocument(describeResult), tim@157: currentArtifact); tim@9: } catch (IOException e) { tim@36: log.error(e, e); tim@9: throw new ArtifactDatabaseClientException(e); tim@9: } tim@9: } sascha@681: sascha@681: tim@157: private Document createDescribeRequestBody(ArtifactObject currentArtifact, tim@157: boolean includeUI){ ingo@690: Document document = XMLUtils.newDocument(); tim@157: Node rootNode = this.createRootNode(document); tim@157: tim@157: Element typeNode = this.createArtifactElement(document, "type"); tim@157: typeNode.setAttribute("name", "describe"); tim@157: rootNode.appendChild(typeNode); tim@157: tim@157: Element uuidNode = this.createArtifactElement(document, "uuid"); tim@157: uuidNode.setAttribute("value", currentArtifact.getId()); tim@157: rootNode.appendChild(uuidNode); tim@157: tim@157: Element hashNode = this.createArtifactElement(document, "hash"); tim@157: hashNode.setAttribute("value", currentArtifact.getHash()); tim@157: rootNode.appendChild(hashNode); tim@157: Element includeUINode = this.createArtifactElement(document, "include-ui"); tim@157: includeUINode.appendChild(document.createTextNode(""+includeUI)); tim@157: rootNode.appendChild(includeUINode); tim@157: return document; tim@157: } tim@12: ingo@690: tim@12: private String getArtifactUrl(ArtifactObject artifactFactory, tim@38: ArtifactObject currentArtifact) { tim@36: String url = ((ArtifactFactory) artifactFactory).getDataBaseUrl() tim@38: + "/artifact/" + currentArtifact.getId(); tim@12: return url; tim@12: } tim@36: tim@36: private ArtifactDescription readDescription(Document document, ingo@665: ArtifactObject artifact) ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException { tim@36: // Check if there was an Error or Exception reported from the tim@36: // ArtifactDatabase tim@25: this.check4ExceptionReport(document); tim@36: if (artifact instanceof ArtifactDescription) { tim@36: ArtifactDescription ad = (ArtifactDescription) artifact; ingo@690: Node uiNode = XMLUtils.getNodeXPath(document, "/art:result/art:ui"); ingo@690: Node outputNode = XMLUtils ingo@389: .getNodeXPath(document, "/art:result/art:outputs"); tim@36: tim@30: Map outputModes = null; tim@36: if (outputNode != null) { ingo@690: NodeList outputModesNodes = XMLUtils.getNodeSetXPath( ingo@389: outputNode, "art:output"); tim@36: if (outputModesNodes != null) { tim@36: outputModes = new HashMap( tim@36: outputModesNodes.getLength()); tim@36: for (int i = 0; i < outputModesNodes.getLength(); i++) { tim@30: Node outputModeNode = outputModesNodes.item(i); ingo@690: String name = XMLUtils.getStringXPath(outputModeNode, tim@36: "@name"); ingo@690: String mimeType = XMLUtils.getStringXPath( tim@36: outputModeNode, "@mime-type"); tim@36: ingo@690: NodeList parameterNodes = XMLUtils.getNodeSetXPath( ingo@389: outputModeNode, "art:parameter/art:parameter"); tim@30: Collection parameter = null; tim@36: if (parameterNodes != null) { tim@36: parameter = new ArrayList( tim@36: parameterNodes.getLength()); tim@36: for (int j = 0; j < parameterNodes.getLength(); j++) { tim@36: Node outputParameterNode = parameterNodes tim@36: .item(j); tim@36: parameter.add(new DefaultOutputParameter( ingo@690: XMLUtils.getStringXPath( tim@36: outputParameterNode, "@name"), ingo@690: XMLUtils.getStringXPath( tim@36: outputParameterNode, "@value"), ingo@690: XMLUtils.getStringXPath( tim@36: outputParameterNode, "@name"), ingo@690: XMLUtils.getStringXPath( tim@36: outputParameterNode, "@type"))); tim@30: } tim@30: } ingo@573: ingo@690: NodeList exportNodes = XMLUtils.getNodeSetXPath( ingo@573: outputModeNode, "art:exports/art:export"); ingo@573: Map exports = null; sascha@681: ingo@573: if (exportNodes != null) { ingo@573: int size = exportNodes.getLength(); ingo@573: exports = new HashMap(size); ingo@573: ingo@573: for (int k = 0; k < size; k++) { ingo@573: Node export = exportNodes.item(k); ingo@690: String expName = XMLUtils.getStringXPath( ingo@573: export, "@name"); ingo@573: exports.put(expName, new DefaultExportMode( ingo@573: expName, ingo@690: XMLUtils.getStringXPath(export, "@description"), ingo@690: XMLUtils.getStringXPath(export, "@mime-type"))); ingo@573: } ingo@573: } ingo@573: tim@36: outputModes.put(name, new DefaultOutputMode(name, ingo@573: mimeType, parameter, exports)); tim@30: } tim@36: tim@30: } tim@30: } tim@36: ingo@690: String currentState = XMLUtils.getStringXPath(document, ingo@389: "/art:result/art:state/@name"); ingo@690: NodeList statesList = XMLUtils.getNodeSetXPath(document, ingo@389: "/art:result/art:reachable-states/art:state/@name"); tim@36: Collection reachableStates = new ArrayList( tim@36: statesList.getLength()); tim@36: for (int i = 0; i < statesList.getLength(); i++) { tim@9: reachableStates.add(statesList.item(i).getNodeValue()); tim@9: } tim@36: ingo@690: NodeList inputNodes = XMLUtils.getNodeSetXPath(document, ingo@389: "/art:result/art:model/art:input"); tim@36: if (inputNodes != null) { tim@36: Collection inputParameter = new ArrayList( tim@36: inputNodes.getLength()); tim@36: for (int i = 0; i < inputNodes.getLength(); i++) { tim@12: Node inputNode = inputNodes.item(i); ingo@690: String name = XMLUtils.getStringXPath(inputNode, "@name"); tim@12: inputParameter.add(name); tim@12: } tim@12: ad.setInputParameter(inputParameter); tim@12: } tim@36: tim@30: ad.setOutputModes(outputModes); tim@9: ad.setCurrentOut(outputNode); tim@9: ad.setCurrentUI(uiNode); tim@9: ad.setCurrentState(currentState); tim@9: ad.setReachableStates(reachableStates); tim@9: return ad; tim@36: } else { tim@9: log.error("Artifact must be Instance of ArtifactDescription"); tim@36: throw new ArtifactDatabaseClientException( tim@36: "Artifact must be Instance of ArtifactDescription"); tim@9: } tim@36: tim@9: } tim@12: ingo@690: tim@12: /** ingo@690: * Feed, advance and describe in one single method. sascha@699: * ingo@690: * @param artifactFactory The factory which created the current artifact. ingo@690: * @param currentArtifact The current artifact. ingo@690: * @param target The target state for advance. ingo@690: * @param inputParameter Input data for feed. ingo@690: * @return the artifact description after calling feed and advance. ingo@690: * @throws ArtifactDatabaseClientException if a general error occured in ingo@690: * the artifact server. ingo@690: * @throws ArtifactDatabaseInputException if the input data was invalid used ingo@690: * for feed. tim@12: */ tim@38: public ArtifactDescription doNextStep( ingo@665: ArtifactObject artifactFactory, ingo@665: ArtifactObject currentArtifact, ingo@665: String target, ingo@665: Collection inputParameter) ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException { tim@36: tim@12: try { tim@12: // 1 Feed tim@13: this.doFeed(artifactFactory, currentArtifact, inputParameter); sascha@681: tim@157: // 2. Noch einmal Describe um das jetzt zu erreichende Ziel zu ermitteln ingo@394: ArtifactDescription ad = getCurrentStepDescription( ingo@394: artifactFactory, ingo@394: new Artifact(currentArtifact.getId(), ingo@394: currentArtifact.getHash()), ingo@394: false ingo@394: ); ingo@394: tim@157: target = ad.getReachableStates().iterator().next(); sascha@681: tim@157: // 3 Advance ingo@394: doAdvance(artifactFactory, currentArtifact, target); sascha@681: tim@25: // 3 Describe tim@36: return this.getCurrentStepDescription(artifactFactory, tim@157: currentArtifact,true); tim@12: } catch (IOException e) { tim@36: log.error(e, e); tim@12: throw new ArtifactDatabaseClientException(e); tim@12: } tim@12: } tim@36: ingo@394: ingo@690: /** ingo@690: * Call the advance operation of the artifact server to step to the next ingo@690: * step of the parameterization. ingo@690: * ingo@690: * @param factory The artifact factory which created the current artifact. ingo@690: * @param artifact The current artifact. ingo@690: * @param target The target state. ingo@690: * @throws IOException if an error occured while reading/writing from/to ingo@690: * stream. ingo@690: * @throws ArtifactDatabaseClientException if a general error occured in ingo@690: * the artifact server. ingo@690: * @throws ArtifactDatabaseInputException if the input data was invalid. ingo@690: */ ingo@394: public void doAdvance( ingo@394: ArtifactObject factory, ingo@394: ArtifactObject artifact, ingo@665: String target) ingo@665: throws IOException, ArtifactDatabaseClientException, ArtifactDatabaseInputException { ingo@394: String url = getArtifactUrl(factory, artifact); ingo@394: Document advanceDocument = createAdvanceRequestBody(artifact, target); ingo@394: InputStream advanceResult = doPostRequest(url, advanceDocument); ingo@690: check4ExceptionReport(XMLUtils.readDocument(advanceResult)); ingo@394: } ingo@394: tim@38: private Document createFeedRequestBody( tim@38: ArtifactObject currentArtifact, tim@38: Collection inputParameter) { ingo@690: Document document = XMLUtils.newDocument(); tim@36: Node rootNode = this.createRootNode(document); tim@36: tim@12: Element typeNode = this.createArtifactElement(document, "type"); tim@12: typeNode.setAttribute("name", "feed"); tim@12: rootNode.appendChild(typeNode); tim@36: tim@12: Element uuidNode = this.createArtifactElement(document, "uuid"); tim@12: uuidNode.setAttribute("value", currentArtifact.getId()); tim@12: rootNode.appendChild(uuidNode); tim@36: tim@12: Element hashNode = this.createArtifactElement(document, "hash"); tim@12: hashNode.setAttribute("value", currentArtifact.getHash()); tim@12: rootNode.appendChild(hashNode); tim@36: tim@36: Node dataNode = this.createParameterNodes(inputParameter, document, tim@36: "data"); tim@12: rootNode.appendChild(dataNode); tim@36: tim@13: return document; tim@13: } tim@13: ingo@690: tim@36: private Node createParameterNodes( tim@38: Collection inputParameter, tim@38: Document document, String nodeName) { tim@13: Element dataNode = this.createArtifactElement(document, nodeName); tim@36: tim@36: if (inputParameter != null) { tim@12: Iterator it = inputParameter.iterator(); tim@36: while (it.hasNext()) { tim@12: InputParameter ip = it.next(); tim@12: String name = ip.getName(); tim@12: String[] values = ip.getValues(); tim@36: if (values != null) { tim@36: for (int i = 0; i < values.length; i++) { tim@12: String value = values[i]; tim@36: Element inputNode = this.createArtifactElement( tim@36: document, "input"); tim@12: inputNode.setAttribute("name", name); tim@12: inputNode.setAttribute("value", value); tim@12: dataNode.appendChild(inputNode); tim@12: } tim@12: } tim@12: } tim@12: } tim@13: return dataNode; tim@12: } tim@36: ingo@690: ingo@690: /** ingo@690: * Creates the xml body for the advance request. ingo@690: * ingo@690: * @param currentArtifact ingo@690: * @param target ingo@690: * @return the advance xml document. ingo@690: */ tim@36: private Document createAdvanceRequestBody(ArtifactObject currentArtifact, tim@38: String target) { ingo@690: Document document = XMLUtils.newDocument(); tim@36: Node rootNode = this.createRootNode(document); tim@36: tim@36: Element typeNode = this.createArtifactElement(document, "type"); tim@36: typeNode.setAttribute("name", "advance"); tim@36: rootNode.appendChild(typeNode); tim@36: tim@36: Element uuidNode = this.createArtifactElement(document, "uuid"); tim@36: uuidNode.setAttribute("value", currentArtifact.getId()); tim@36: rootNode.appendChild(uuidNode); tim@36: tim@36: Element hashNode = this.createArtifactElement(document, "hash"); tim@36: hashNode.setAttribute("value", currentArtifact.getHash()); tim@36: rootNode.appendChild(hashNode); tim@36: Element targetNode = this.createArtifactElement(document, "target"); tim@36: targetNode.setAttribute("name", target); tim@36: rootNode.appendChild(targetNode); tim@36: return document; tim@12: } tim@13: tim@13: /** ingo@690: * Call the out operation of the artifact server and writes the result to ingo@690: * stream. ingo@690: * ingo@690: * @param exportMode ingo@690: * @param inputParameter tim@13: */ ingo@583: public void doOutput( ingo@583: ArtifactObject artifactFactory, ingo@583: ArtifactObject currentArtifact, ingo@583: OutputStream stream, ingo@583: String targetName, ingo@583: String exportMode, ingo@583: String mimeType, ingo@583: Collection inputParameter) ingo@583: throws ArtifactDatabaseClientException ingo@583: { tim@13: try { ingo@583: Document requestBody = this.createOutRequestBody( ingo@583: currentArtifact, ingo@583: targetName, ingo@583: exportMode, ingo@583: mimeType, ingo@583: inputParameter); tim@36: tim@36: String requestUrl = this.getArtifactUrl(artifactFactory, tim@36: currentArtifact) tim@38: + "/" + targetName; tim@36: InputStream is = this.doPostRequest(requestUrl, requestBody); tim@36: tim@13: byte[] b = new byte[4096]; tim@36: int i = -1; tim@36: while ((i = is.read(b)) > 0) { tim@13: stream.write(b, 0, i); tim@13: } tim@36: } catch (IOException e) { tim@36: log.error(e, e); tim@13: throw new ArtifactDatabaseClientException(e); tim@13: } tim@13: } tim@36: ingo@670: ingo@690: /** ingo@690: * Call the out method of the artifact server with a specific export mode. sascha@699: * ingo@690: * @param artifactFactory ingo@690: * @param currentArtifact ingo@690: * @param out ingo@690: * @throws ArtifactDatabaseClientException if an error occured while ingo@690: * reading/writing from/to stream. ingo@690: */ ingo@670: public void doExport( ingo@670: ArtifactObject artifactFactory, ingo@670: ArtifactObject currentArtifact, ingo@670: OutputStream out) ingo@670: throws ArtifactDatabaseClientException ingo@670: { ingo@678: InputStreamReader reader = null; ingo@678: OutputStreamWriter writer = null; ingo@678: ingo@670: try { ingo@670: String url = ((ArtifactFactory) artifactFactory).getDataBaseUrl(); ingo@670: url += "/export/" + currentArtifact.getId(); ingo@670: ingo@678: Representation response = doGetRequestInternal(url, null); ingo@678: InputStream in = response.getStream(); ingo@678: ingo@678: reader = new InputStreamReader(in); ingo@678: writer = new OutputStreamWriter(out); ingo@678: ingo@679: int c; ingo@679: char[] buffer = new char[512]; ingo@679: while ((c = reader.read(buffer)) > 0) { ingo@679: writer.write(buffer, 0, c); ingo@678: } ingo@678: ingo@670: } ingo@670: catch (Exception e) { ingo@670: log.error(e, e); ingo@670: throw new ArtifactDatabaseClientException(e); ingo@670: } ingo@678: finally { ingo@678: try { ingo@678: reader.close(); ingo@678: } catch (IOException ioe) {} ingo@670: ingo@678: try { ingo@678: writer.flush(); ingo@678: } catch (IOException ioe) {} ingo@678: ingo@678: try { ingo@678: writer.close(); ingo@678: } catch (IOException ioe) {} ingo@678: } ingo@670: } ingo@670: ingo@670: ingo@690: /** ingo@690: * Start to import an artifact from xml document. ingo@690: * ingo@690: * @param factory ingo@690: * @param document The artifact as xml document. ingo@690: * @return A status description of the operation (success or failure). ingo@690: * @throws ArtifactDatabaseClientException ingo@690: * @throws IOException ingo@690: */ ingo@673: public Document doImport( ingo@673: ArtifactFactory factory, ingo@673: Document document) ingo@673: throws ArtifactDatabaseClientException, IOException ingo@673: { ingo@673: String url = factory.getDataBaseUrl() + "/import"; ingo@673: InputStream response = doPostRequest(url, document); ingo@673: ingo@673: return XMLUtils.readDocument(response); ingo@673: } ingo@673: ingo@673: ingo@690: /** ingo@690: * Creates the xml request body used for an out-call of the artifact server. sascha@699: * ingo@690: * @param currentArtifact ingo@690: * @param target ingo@690: * @param exportMode ingo@690: * @param mimeType ingo@690: * @param inputParameter ingo@690: * @return the request body. ingo@690: */ tim@38: private Document createOutRequestBody( ingo@583: ArtifactObject currentArtifact, ingo@583: String target, ingo@583: String exportMode, ingo@583: String mimeType, ingo@583: Collection inputParameter) ingo@583: { ingo@690: Document document = XMLUtils.newDocument(); tim@36: Node rootNode = this.createRootNode(document); tim@36: tim@13: Element typeNode = this.createArtifactElement(document, "type"); tim@13: typeNode.setAttribute("name", "out"); tim@13: rootNode.appendChild(typeNode); tim@36: tim@13: Element uuidNode = this.createArtifactElement(document, "uuid"); tim@13: uuidNode.setAttribute("value", currentArtifact.getId()); tim@13: rootNode.appendChild(uuidNode); tim@36: tim@13: Element hashNode = this.createArtifactElement(document, "hash"); tim@13: hashNode.setAttribute("value", currentArtifact.getHash()); tim@13: rootNode.appendChild(hashNode); tim@36: tim@13: Element outNode = this.createArtifactElement(document, "out"); tim@13: outNode.setAttribute("name", target); tim@13: rootNode.appendChild(outNode); tim@36: ingo@583: Element exportNode = this.createArtifactElement(document, "export"); ingo@583: exportNode.setAttribute("name", exportMode); ingo@583: outNode.appendChild(exportNode); ingo@583: ingo@281: Element mimeTypeNode = this.createArtifactElement(document, "mime-type"); tim@13: mimeTypeNode.setAttribute("value", mimeType); tim@13: outNode.appendChild(mimeTypeNode); tim@36: tim@36: Node parameterNode = this.createParameterNodes(inputParameter, tim@36: document, "params"); tim@13: outNode.appendChild(parameterNode); tim@36: tim@13: return document; tim@36: } tim@13: ingo@690: tim@13: /** ingo@690: * Calls the feed operation of the artifact server. ingo@690: * ingo@690: * @param artifactFactory The artifact factory which created the current ingo@690: * artifact. ingo@690: * @param currentArtifact The current artifact. ingo@690: * @param inputParameter The user input. ingo@690: * @throws ArtifactDatabaseClientException ingo@690: * @throws ArtifactDatabaseInputException tim@13: */ ingo@665: public void doFeed( ingo@665: ArtifactObject artifactFactory, ingo@665: ArtifactObject currentArtifact, ingo@665: Collection inputParameter) ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException { tim@36: tim@13: try { tim@36: Document feedDocument = this.createFeedRequestBody(currentArtifact, tim@36: inputParameter); tim@13: String url = this.getArtifactUrl(artifactFactory, currentArtifact); tim@13: InputStream feedResult = this.doPostRequest(url, feedDocument); ingo@690: Document feedResultDocument = XMLUtils tim@36: .readDocument(feedResult); tim@25: this.check4ExceptionReport(feedResultDocument); tim@13: } catch (IOException e) { tim@36: log.error(e, e); tim@25: throw new ArtifactDatabaseClientException(e); tim@13: } tim@13: } tim@36: tim@36: private void check4ExceptionReport(Document document) ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException { ingo@690: String message = XMLUtils.getStringXPath(document, ingo@665: EXCEPTION_GENERAL); tim@36: if (message != null) { tim@25: throw new ArtifactDatabaseClientException(message); tim@25: } tim@36: ingo@665: String input = XMLUtils.getStringXPath(document, EXCEPTION_USER_INPUT); ingo@665: if (input != null) { ingo@665: throw new ArtifactDatabaseInputException(input); ingo@665: } tim@25: } tim@32: ingo@690: ingo@690: /** ingo@690: * Call the specific wms export mode of the out operation of the artifact ingo@690: * server. sascha@699: * ingo@690: * @param factory ingo@690: * @param artifact ingo@690: * @param inputParameter ingo@690: * @return a document that contains information about the wms service and ingo@690: * the created layer. ingo@690: * @throws ArtifactDatabaseClientException ingo@690: * @throws ArtifactDatabaseInputException ingo@690: */ ingo@668: public Document publishWMS( ingo@668: ArtifactObject factory, ingo@668: ArtifactObject artifact, ingo@668: Collection inputParameter tim@676: ) throws ArtifactDatabaseClientException, ArtifactDatabaseInputException{ ingo@570: log.debug("Start wms publishing..."); ingo@570: ingo@570: String target = "wms"; ingo@570: String requestURL = getArtifactUrl(factory, artifact) + "/" + target; ingo@570: Document request = createOutRequestBody( ingo@668: artifact, target, "", "text/xml", inputParameter); ingo@570: try { ingo@570: InputStream input = doPostRequest(requestURL, request); ingo@570: Document result = XMLUtils.readDocument(input); tim@676: this.check4ExceptionReport(result); ingo@585: return result; ingo@570: } ingo@570: catch (IOException ioe) { ingo@570: log.error(ioe, ioe); tim@676: throw new ArtifactDatabaseClientException(ioe); ingo@570: } ingo@570: } ingo@570: sascha@699: tim@164: public Collection calculateStatistics( ingo@570: ArtifactObject artifactFactory, ingo@570: ArtifactObject currentArtifact) ingo@570: throws ArtifactDatabaseClientException ingo@570: { tim@36: log.debug("DefaultArtifactDatabaseClient.calculateStatistics"); tim@164: Collection resultValues = null; sascha@681: tim@32: try { tim@32: String targetName = "statistics"; tim@36: String requestUrl = this.getArtifactUrl(artifactFactory, tim@164: currentArtifact) + "/" + targetName; tim@36: Document requestBody = this.createOutRequestBody(currentArtifact, ingo@583: targetName, "", "text/xml", null); tim@32: XMLUtils xmlUtils = new XMLUtils(); tim@36: InputStream is = this.doPostRequest(requestUrl, requestBody); ingo@690: Document resultDocument = XMLUtils.readDocument(is); tim@36: if (resultDocument != null) { sascha@681: ingo@690: NodeList statisticSetNodes = XMLUtils.getNodeSetXPath(resultDocument, ingo@389: "/art:statistics/art:statistic"); tim@164: resultValues = new ArrayList tim@164: (statisticSetNodes.getLength()); tim@164: for (int i = 0; i < statisticSetNodes.getLength(); i++) { tim@164: Element statisticSetNode = (Element)statisticSetNodes.item(i); tim@164: String name = statisticSetNode.getAttribute("name"); sascha@681: ArtifactStatisticsSet set = tim@164: new DefaultArtifactStatisticsSet(name); ingo@690: NodeList resultNodes = XMLUtils.getNodeSetXPath(statisticSetNode, ingo@389: "art:statistic-value"); tim@164: if (resultNodes != null) { tim@164: for (int j = 0; j < resultNodes.getLength(); j++) { tim@164: Element statisticNode = (Element)resultNodes.item(j); tim@164: String statisticName = statisticNode. tim@164: getAttribute("name"); tim@164: String statisticValue = statisticNode. tim@164: getAttribute("value"); tim@164: set.addStatisticValues( tim@164: new DefaultArtifactStatisticValue tim@164: (statisticName,statisticValue)); tim@164: } tim@32: } tim@164: resultValues.add(set); tim@32: } tim@32: } tim@32: } catch (IOException e) { tim@36: log.error(e, e); tim@35: throw new ArtifactDatabaseClientException(e); tim@32: } tim@36: tim@164: return resultValues; tim@32: } tim@40: tim@40: public void setLocale(Locale locale) { tim@40: this.locale = locale; tim@40: } tim@402: ingo@703: public Locale getLocale() { ingo@703: return locale; ingo@703: } ingo@703: ingo@690: tim@558: public Collection getArtifactFactoryMetaInformation( ingo@665: Collection mapServices, ingo@665: String geometry, ingo@665: String srs) ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException { tim@558: log.debug("DefaultArtifactDatabaseClient.getArtifactFactories"); tim@558: Collection resultValues = null; tim@558: try { tim@558: this.initialize(); tim@558: Iterator it = artifactDatabases.iterator(); sascha@681: Document requestBody = this.createMetaDataRequestBody(mapServices, sascha@681: geometry, tim@558: srs); tim@558: while (it.hasNext()) { tim@558: String server = it.next(); tim@558: String url = server + "/service/metadata/"; tim@558: log.debug(url); sascha@681: tim@558: InputStream resultStream = this.doPostRequest(url, requestBody); tim@565: resultValues = this.parseMetaDataResult(resultStream, server,geometry); tim@558: } tim@558: } catch (IOException e) { tim@558: log.error(e,e); tim@558: } tim@558: return resultValues; tim@558: } sascha@681: tim@558: private Collection parseMetaDataResult( sascha@681: InputStream inputStream, ingo@665: String server, ingo@665: String geometry) ingo@665: throws ArtifactDatabaseClientException, ArtifactDatabaseInputException { tim@558: XMLUtils xmlUtils = new XMLUtils(); ingo@690: Document document = XMLUtils.readDocument(inputStream); tim@558: this.check4ExceptionReport(document); tim@565: return this.getArtifactFactories(document, server,geometry); tim@558: } sascha@681: tim@558: private Document createMetaDataRequestBody(Collection mapServices, tim@558: String geometry, tim@558: String srs){ tim@558: log.debug("DefaultArtifactDatabaseClient.createMetaDataRequestBody"); ingo@690: Document document = XMLUtils.newDocument(); tim@558: Node rootNode = this.createArtifactElement(document, "GetMetaData"); tim@558: document.appendChild(rootNode); sascha@681: tim@1005: if (geometry != null){ tim@1005: Element locationNode = this.createArtifactElement(document, "location"); tim@1005: locationNode.setAttribute("srs", srs); tim@1005: locationNode.appendChild(document.createTextNode(geometry)); tim@1005: rootNode.appendChild(locationNode); tim@1005: } tim@558: Element mapServicesNode = this.createArtifactElement(document, tim@558: "mapservices"); tim@558: Iterator it = mapServices.iterator(); tim@558: while (it.hasNext()){ tim@558: MapService mapService = it.next(); tim@558: Element mapServiceNode = this.createArtifactElement(document, tim@558: "mapservice"); tim@558: mapServiceNode.setAttribute("id", mapService.getID()); tim@558: mapServiceNode.setAttribute("type", mapService.getType()); tim@558: mapServiceNode.setAttribute("url", mapService.getURL()); tim@561: if (mapService.getLayer() != null){ tim@561: Iterator layer = mapService.getLayer().iterator(); tim@561: while (layer.hasNext()){ tim@561: Layer tmpLayer = layer.next(); tim@561: Element layerNode = this.createArtifactElement(document, tim@561: "layer"); tim@561: layerNode.setAttribute("id", tmpLayer.getID()); tim@561: layerNode.setAttribute("name", tmpLayer.getName()); tim@561: layerNode.setAttribute("isgrouplayer", tim@561: ""+tmpLayer.isGroupLayer()); tim@561: layerNode.setAttribute("parentid", tmpLayer.parentID()); tim@561: mapServiceNode.appendChild(layerNode); tim@561: } tim@558: } tim@558: mapServicesNode.appendChild(mapServiceNode); tim@558: } tim@558: rootNode.appendChild(mapServicesNode); tim@558: return document; tim@402: } tim@13: } sascha@700: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :