Skip to content

Instantly share code, notes, and snippets.

@zubairov
Created March 8, 2011 10:26
Show Gist options
  • Save zubairov/860126 to your computer and use it in GitHub Desktop.
Save zubairov/860126 to your computer and use it in GitHub Desktop.
/*******************************************************************************
* Copyright (c) 2009, 2010 SOPERA GmbH
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
******************************************************************************/
package org.sopera.ode.metadata.impl;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.QName;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections.Transformer;
import org.apache.ode.utils.DOMUtils;
import org.apache.xml.security.utils.Base64;
import org.slf4j.Logger;
import org.sopera.ode.SBBRegistry;
import org.sopera.ode.metadata.MetadataParser;
import org.sopera.ode.util.InjectLogger;
import org.sopware.papi.SBB;
import org.sopware.papi.exception.SBBException;
import org.sopware.papi.untyped.IncomingMessage;
import org.sopware.papi.untyped.OutgoingMessage;
import org.sopware.papi.untyped.consumer.RequestResponseOperationProxy;
import org.sopware.papi.untyped.consumer.ServiceProxy;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.google.inject.Inject;
import com.google.inject.name.Named;
/**
* {@link Transformer} that loads central configured metadata.
*
* @author atelesh
*/
public class CentralMetadataLoader implements Transformer {
private static final String CONFIGURATION_TSP_REQUEST =
"<cfg:getResource"
+ " xmlns:cfg='http://types.sopware.org/configuration/ConfigurationQuery/1.0'>"
+ "<cfg:ResourceQuery>"
+ "<bsp:ScopePath separator='.'"
+ " xmlns:bsp='http://types.sopware.org/configuration/BasicScopePath/1.0'>"
+ "<bsp:PathPart type='Location' value=''/>"
+ "<bsp:PathPart type='Application' value=''/>"
+ "</bsp:ScopePath>"
+ "<cfg:tree></cfg:tree>"
+ "<cfg:componentId></cfg:componentId>"
+ "<cfg:resourceId></cfg:resourceId>"
+ "</cfg:ResourceQuery>"
+ "</cfg:getResource>";
private static final String CONFIGURATION_TSP_OPERATION = "getResource";
private static final QName CONFIGURATION_TSP_SERVICE_NAME = new QName(
"http://services.sopware.org/configuration/ConfigurationRuntime/1.0",
"ConfigurationRuntime");
/**
* Logger.
*/
@InjectLogger
Logger log;
private final String cfgTspPolicyId;
private final String cfgResource;
private final String cfgComponent;
private final String cfgLocation;
private final String cfgApplication;
private final String cfgTree;
private final SBBRegistry reg;
private final MetadataParser parser;
private final Document requestTemplate;
/**
* Default constructor for injection.
*
* @param reg SBB registry
* @param parser metadata parser
* @param cfgTspPolicyId policy alias
* @param cfgResource resource id
* @param cfgComponent component id
* @param cfgLocation scope path location
* @param cfgApplication scope path application
* @param cfgTree configuration tree
*/
@Inject
public CentralMetadataLoader(SBBRegistry reg, MetadataParser parser,
@Named("sopera.ode.central.configuration.tsp.policy.id") String cfgTspPolicyId,
@Named("sopera.ode.central.configuration.tsp.request.resource") String cfgResource,
@Named("sopera.ode.central.configuration.tsp.request.component") String cfgComponent,
@Named("sopera.ode.central.configuration.tsp.request.location") String cfgLocation,
@Named("sopera.ode.central.configuration.tsp.request.application") String cfgApplication,
@Named("sopera.ode.central.configuration.tsp.request.tree") String cfgTree) {
this.reg = reg;
this.parser = parser;
this.cfgTspPolicyId = cfgTspPolicyId;
this.cfgResource = cfgResource;
this.cfgComponent = cfgComponent;
this.cfgLocation = cfgLocation;
this.cfgApplication = cfgApplication;
this.cfgTree = cfgTree;
requestTemplate = buildConfigurationTSPGetResourceRequest();
}
/**
* {@inheritDoc}
*/
public Object transform(Object processID) {
return loadData((QName) processID);
}
/**
* Loads metadata from central configuration repository
*
* @param processID
* @return central configuration metadata
*/
private Map<QName, ServiceMetadata> loadData(QName processID) {
Document response = callConfigurationTSPGetResource(cloneDocument(requestTemplate));
if (null == response) {
return new HashMap<QName, ServiceMetadata>();
}
Document configuration = parseConfigurationTSPGetResourceResponse(response);
Map<QName, ServiceMetadata> centralServicesMetadatas;
try {
centralServicesMetadatas = parser.unmarshal(configuration.getDocumentElement());
} catch (Exception e) {
throw new MetadataException(
"error during parsing metadata from central configuration store for process "
+ processID + ": " + e.getMessage(), e);
}
if (0 == centralServicesMetadatas.size()) {
throw new MetadataException(
"empty central configuration retrieved for process " + processID);
}
if (log.isDebugEnabled()) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
MapUtils.verbosePrint(new PrintStream(baos),
"central configuration metadatas for process " + processID,
centralServicesMetadatas);
log.debug(baos.toString());
}
return centralServicesMetadatas;
}
/**
* Performs call to configuration TSP
*
* @param request
* @return response document or null in unsuccessful case
*/
private Document callConfigurationTSPGetResource(Document request) {
try {
SBB sbb = reg.getProviderSBB();
ServiceProxy confServiceProxy = sbb.lookupServiceProxy(
CONFIGURATION_TSP_SERVICE_NAME, cfgTspPolicyId);
RequestResponseOperationProxy operationProxy = confServiceProxy
.getRequestResponseOperation(CONFIGURATION_TSP_OPERATION);
OutgoingMessage requestMessage = operationProxy.getEnvironment()
.getMessageFactory().createMessage(request);
IncomingMessage responseMessage = operationProxy.callBlocking(requestMessage);
if (responseMessage.isFaultMessage()) {
String message = null;
try {
message = responseMessage.getXMLString();
} catch (SBBException e) {
message = "[cannot retrieve fault message]";
}
throw new MetadataException(
"request to configuration TSP returns fault message - " + message);
} else {
return responseMessage.getXMLDocument();
}
} catch (SBBException e) {
if (checkIsResourceNonFoundException(e)) {
log.warn("requested central configuration resource not found -"
+ " resource id: {}, component id {}, scope path location: {},"
+ " scope path application: {}, configuration tree: {}", new String[] {
cfgResource, cfgComponent, cfgLocation, cfgApplication, cfgTree });
} else {
throw new MetadataException("request to configuration TSP failed", e);
}
}
return null;
}
private boolean checkIsResourceNonFoundException(SBBException e) {
// awaited exception description message part:
// org.sopware.configrepos.server.core.exceptions.SBBConfigServerException:
// resource sopera-intalio for component sbbpre:PolicyResolver at
// Resources.Tree-SBB.Component-sbbpre:PolicyResolver.Location-generic_location.Application-Apache_ODE not found
String message = e.getMessage();
return message.contains("SBBConfigServerException")
&& message.contains(cfgResource)
&& message.contains(cfgComponent)
&& message.contains(cfgLocation)
&& message.contains(cfgApplication)
&& message.contains(cfgTree)
&& message.contains("not found");
}
private Document cloneDocument(Document doc) {
Document clone = DOMUtils.newDocument();
clone.appendChild(clone.importNode(doc.getDocumentElement(), true));
return clone;
}
/**
* Builds request to configuration TSP
*
* @return request document or null in unsuccessful case
*/
private Document buildConfigurationTSPGetResourceRequest() {
try {
Element getResource = DOMUtils.stringToDOM(CONFIGURATION_TSP_REQUEST);
Element resourceQuery = DOMUtils.getFirstChildElement(getResource);
Element elTree = DOMUtils.findChildByName(resourceQuery,
new QName("http://types.sopware.org/configuration/ConfigurationQuery/1.0",
"tree"));
elTree.setTextContent(cfgTree);
Element elComponentId = DOMUtils.findChildByName(resourceQuery,
new QName("http://types.sopware.org/configuration/ConfigurationQuery/1.0",
"componentId"));
elComponentId.setTextContent(cfgComponent);
Element elResourceId = DOMUtils.findChildByName(resourceQuery,
new QName("http://types.sopware.org/configuration/ConfigurationQuery/1.0",
"resourceId"));
elResourceId.setTextContent(cfgResource);
Element elScopePath = DOMUtils.findChildByName(resourceQuery,
new QName("http://types.sopware.org/configuration/BasicScopePath/1.0",
"ScopePath"));
Element elPathPartLocation = DOMUtils.findChildElementWithAttribute(
elScopePath, "type", "Location");
elPathPartLocation.setAttribute("value", cfgLocation);
Element elPathPartApplication = DOMUtils.findChildElementWithAttribute(
elScopePath, "type", "Application");
elPathPartApplication.setAttribute("value", cfgApplication);
return getResource.getOwnerDocument();
} catch (Exception e) {
throw new MetadataException("cannot build request to configuration TSP", e);
}
}
/**
* Retrieves configuration from response and parse it into configuration document
*
* @param response
* @return configuration document or null in unsuccessful case
*/
private Document parseConfigurationTSPGetResourceResponse(Document response) {
// expected response -
// <resourceResponse xmlns="http://types.sopware.org/configuration/ConfigurationQuery/1.0">
// PN0ZYo8XN0DQyvcGvcGVT4NCgXN0HNlL3VyYT4=
// </resourceResponse>
String cfgStringBase64Encoded = response.getDocumentElement().getTextContent();
if (null == cfgStringBase64Encoded || 0 == cfgStringBase64Encoded.length()) {
throw new MetadataException("central configuration resource is empty");
}
log.debug("received configuration (base64-encoded) - {}", cfgStringBase64Encoded);
String cfgStringPlainText = null;
try {
cfgStringPlainText = new String(Base64.decode(cfgStringBase64Encoded));
} catch (Exception e) {
throw new MetadataException("cannot decode (base64) received configuration", e);
}
log.debug("received configuration (plain-text) - {}", cfgStringPlainText);
try {
return DOMUtils.stringToDOM(cfgStringPlainText).getOwnerDocument();
} catch (Exception e) {
throw new MetadataException("cannot parse received configuration xml", e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment