Created
March 8, 2011 10:26
-
-
Save zubairov/860126 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************************* | |
* 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