/*
* Copyright (c) 2005-2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wso2.carbon.bpel.core.ode.integration.config.analytics;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.bpel.core.BPELConstants;
import org.wso2.carbon.bpel.core.internal.BPELServiceComponent;
import org.wso2.carbon.bpel.core.ode.integration.store.BPELDeploymentException;
import org.wso2.carbon.core.util.CryptoException;
import org.wso2.carbon.core.util.CryptoUtil;
import org.wso2.carbon.registry.api.Registry;
import org.wso2.carbon.registry.api.RegistryException;
import org.wso2.carbon.registry.api.Resource;
import org.wso2.carbon.unifiedendpoint.core.UnifiedEndpointConstants;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
/**
* Builds the Analytics Server Profile {@link AnalyticsServerProfile}
*/
public class AnalyticsServerProfileBuilder {
// Log factory.
private static Log log = LogFactory.getLog(AnalyticsServerProfileBuilder.class);
// Analytic profile location
private String profileLocation;
// Tenant ID.
private Integer tenantId;
/**
* Creates AnalyticsServerProfileBuilder instance for given tenant and Analytic profile location.
*
* @param profileLocation location of Analytics profile.
* @param tenantId tenant ID.
*/
public AnalyticsServerProfileBuilder(String profileLocation, Integer tenantId) {
this.profileLocation = profileLocation;
this.tenantId = tenantId;
}
/**
* Creates AnalyticsServerProfile for given tenant and Analytic profile.
*
* @return AnalyticsServerProfile instance
*/
public AnalyticsServerProfile build() {
AnalyticsServerProfile analyticsServerProfile = new AnalyticsServerProfile();
Registry registry;
String location;
if (profileLocation.startsWith(UnifiedEndpointConstants.VIRTUAL_CONF_REG)) {
try {
registry =
BPELServiceComponent.getRegistryService().getConfigSystemRegistry(tenantId);
location = profileLocation.substring(profileLocation.indexOf(
UnifiedEndpointConstants.VIRTUAL_CONF_REG) +
UnifiedEndpointConstants.VIRTUAL_CONF_REG.length());
loadAnalyticsProfileFromRegistry(analyticsServerProfile, registry, location);
} catch (RegistryException re) {
String errMsg = "Error while loading Analytic profile from config registry.";
handleError(errMsg, re);
}
} else if (profileLocation.startsWith(UnifiedEndpointConstants.VIRTUAL_GOV_REG)) {
try {
registry = BPELServiceComponent.getRegistryService().getGovernanceSystemRegistry(tenantId);
location = profileLocation.substring(profileLocation.indexOf(
UnifiedEndpointConstants.VIRTUAL_GOV_REG) +
UnifiedEndpointConstants.VIRTUAL_GOV_REG.length());
loadAnalyticsProfileFromRegistry(analyticsServerProfile, registry, location);
} catch (RegistryException re) {
String errMsg = "Error while loading Analytic profile from governance registry.";
handleError(errMsg, re);
}
} else if (profileLocation.startsWith(UnifiedEndpointConstants.VIRTUAL_REG)) {
try {
registry = BPELServiceComponent.getRegistryService().getLocalRepository(tenantId);
location = profileLocation.substring(profileLocation.indexOf(
UnifiedEndpointConstants.VIRTUAL_REG) +
UnifiedEndpointConstants.VIRTUAL_REG.length());
loadAnalyticsProfileFromRegistry(analyticsServerProfile, registry, location);
} catch (RegistryException re) {
String errMsg = "Error while loading Analytic profile from local registry";
handleError(errMsg, re);
}
} else if (profileLocation.startsWith(UnifiedEndpointConstants.VIRTUAL_FILE)) {
location = profileLocation.substring(profileLocation.indexOf(
UnifiedEndpointConstants.VIRTUAL_FILE) +
UnifiedEndpointConstants.VIRTUAL_FILE.length());
loadAnalyticsProfileFromFileSystem(analyticsServerProfile, location);
} else {
String errMsg = "Invalid analytics profile location: " + profileLocation;
handleError(errMsg);
}
return analyticsServerProfile;
}
/**
* Load Analytics profile from file system.
*
* @param analyticsServerProfile AnalyticsServerProfile instance
* @param location File system path of the profile file
*/
private void loadAnalyticsProfileFromFileSystem(AnalyticsServerProfile analyticsServerProfile, String location) {
File file = new File(location);
if (file.exists()) {
try {
String profileFileContent = FileUtils.readFileToString(file, "UTF-8");
parseAnalyticsProfile(profileFileContent, analyticsServerProfile);
} catch (IOException e) {
String errMsg = "Error occurred while reading the file from file system: " +
location + "to build the Analytics server profile:" + profileLocation;
handleError(errMsg, e);
}
}
}
/**
* Load Analytics profile from given registry and registry path.
*
* @param analyticsServerProfile AnalyticsServerProfile instance
* @param registry Registry space where file is located
* @param location Registry path of the profile file
*/
private void loadAnalyticsProfileFromRegistry(AnalyticsServerProfile analyticsServerProfile, Registry registry,
String location) {
try {
if (registry.resourceExists(location)) {
Resource resource = registry.get(location);
String resourceContent = new String((byte[]) resource.getContent());
parseAnalyticsProfile(resourceContent, analyticsServerProfile);
} else {
String errMsg = "The resource: " + location + " does not exist.";
handleError(errMsg);
}
} catch (RegistryException e) {
String errMsg = "Error occurred while reading the resource from registry: " +
location + " to build the Analytics server profile: " + profileLocation;
handleError(errMsg, e);
}
}
/**
* Parse Analytics Profile file content and adding content to AnalyticsProfile instance.
*
* @param content Content of Analytics Profile
* @param analyticsServerProfile AnalyticsServerProfile instance
*/
private void parseAnalyticsProfile(String content, AnalyticsServerProfile analyticsServerProfile) {
try {
OMElement resourceElement =
new StAXOMBuilder(new ByteArrayInputStream(content.getBytes())).getDocumentElement();
processAnalyticsServerProfileName(resourceElement, analyticsServerProfile);
processCredentialElement(resourceElement, analyticsServerProfile);
processConnectionElement(resourceElement, analyticsServerProfile);
processStreamsElement(resourceElement, analyticsServerProfile);
} catch (XMLStreamException e) {
String errMsg = "Error occurred while creating the OMElement out of Analytics server " +
"profile: " + profileLocation;
handleError(errMsg, e);
} catch (CryptoException e) {
String errMsg = "Error occurred while decrypting password in Analytics server profile: " + profileLocation;
handleError(errMsg, e);
}
}
/**
* Reading Analytics Server profile name and Agent type and setting them to given analyticsServerProfile instance.
*
* @param analyticsServerConfig OMElement of analyticsServerConfig
* @param analyticsServerProfile AnalyticsServerProfile instance
*/
private void processAnalyticsServerProfileName(OMElement analyticsServerConfig,
AnalyticsServerProfile analyticsServerProfile) {
OMAttribute name = analyticsServerConfig.getAttribute(new QName(AnalyticsConstants.NAME));
if (name != null && name.getAttributeValue() != null &&
!AnalyticsConstants.EMPTY.equals(name.getAttributeValue().trim())) {
analyticsServerProfile.setName(name.getAttributeValue().trim());
} else {
String errMsg =
AnalyticsConstants.NAME + " attribute not found for Analytics server profile: " + profileLocation;
handleError(errMsg);
}
OMAttribute type = analyticsServerConfig.getAttribute(new QName(AnalyticsConstants.TYPE));
if (type != null && type.getAttributeValue() != null &&
!AnalyticsConstants.EMPTY.equals(type.getAttributeValue().trim())) {
analyticsServerProfile.setType(type.getAttributeValue().trim());
} else {
// This value can be null or empty. Then default agent will get selected.
analyticsServerProfile.setType(null);
}
}
/**
* Reading Analytics Server profile credentials and setting them to given analyticsServerProfile instance.
*
* @param analyticsServerConfig OMElement of analyticsServerConfig
* @param analyticsServerProfile AnalyticsServerProfile instance
* @throws CryptoException
*/
private void processCredentialElement(OMElement analyticsServerConfig,
AnalyticsServerProfile analyticsServerProfile) throws CryptoException {
OMElement credentialElement = analyticsServerConfig.getFirstChildWithName(
new QName(BPELConstants.ANALYTICS_SERVER_PROFILE_NS, AnalyticsConstants.CREDENTIAL));
if (credentialElement != null) {
OMAttribute userNameAttr =
credentialElement.getAttribute(new QName(AnalyticsConstants.CREDENTIAL_USER_NAME));
OMAttribute passwordAttr =
credentialElement.getAttribute(new QName(AnalyticsConstants.CREDENTIAL_PASSWORD));
OMAttribute encryptPasswordAttr =
credentialElement.getAttribute(new QName(AnalyticsConstants.CREDENTIAL_ENCRYPT_PASSWORD));
if (userNameAttr != null && passwordAttr != null && userNameAttr.getAttributeValue() != null &&
passwordAttr.getAttributeValue() != null &&
!AnalyticsConstants.EMPTY.equals(userNameAttr.getAttributeValue().trim()) &&
!AnalyticsConstants.EMPTY.equals(passwordAttr.getAttributeValue().trim())) {
analyticsServerProfile.setUserName(userNameAttr.getAttributeValue().trim());
if (encryptPasswordAttr != null && encryptPasswordAttr.getAttributeValue() != null &&
"TRUE".equals(encryptPasswordAttr.getAttributeValue().trim().toUpperCase())) {
analyticsServerProfile.setPassword(new String(CryptoUtil.getDefaultCryptoUtil().
base64DecodeAndDecrypt(passwordAttr.getAttributeValue())));
} else {
analyticsServerProfile.setPassword(passwordAttr.getAttributeValue().trim());
}
} else {
String errMsg =
AnalyticsConstants.CREDENTIAL_USER_NAME + " or " + AnalyticsConstants.CREDENTIAL_PASSWORD +
" not found for Analytics server profile: " + profileLocation;
handleError(errMsg);
}
} else {
String errMsg = AnalyticsConstants.CREDENTIAL + " element not found for Analytics server profile: " +
profileLocation;
handleError(errMsg);
}
}
/**
* Reading Analytics Server profile connections URLs and setting them to given analyticsServerProfile instance.
*
* @param analyticsServerConfig OMElement of analyticsServerConfig
* @param analyticsServerProfile AnalyticsServerProfile instance
*/
private void processConnectionElement(OMElement analyticsServerConfig,
AnalyticsServerProfile analyticsServerProfile) {
OMElement connectionElement = analyticsServerConfig.getFirstChildWithName(
new QName(BPELConstants.ANALYTICS_SERVER_PROFILE_NS, AnalyticsConstants.CONNECTION));
if (connectionElement != null) {
OMAttribute receiverURLsSet =
connectionElement.getAttribute(new QName(AnalyticsConstants.CONNECTION_RECEIVER_URL_SET));
OMAttribute authURLsSet =
connectionElement.getAttribute(new QName(AnalyticsConstants.CONNECTION_AUTH_URL_SET));
if (receiverURLsSet != null && receiverURLsSet.getAttributeValue() != null &&
!AnalyticsConstants.EMPTY.equals(receiverURLsSet.getAttributeValue().trim())) {
analyticsServerProfile.setReceiverURLSet(receiverURLsSet.getAttributeValue().trim());
} else {
String errMsg = "Connection details are missing for Analytics server profile: " + profileLocation;
handleError(errMsg);
}
// AuthURLsSet can be null or empty.
if (authURLsSet != null && authURLsSet.getAttributeValue() != null &&
!AnalyticsConstants.EMPTY.equals(authURLsSet.getAttributeValue().trim())) {
analyticsServerProfile.setAuthURLSet(authURLsSet.getAttributeValue().trim());
} else {
analyticsServerProfile.setAuthURLSet(null);
}
} else {
String errMsg = "Connection details not found for Analytics server profile: " + profileLocation;
handleError(errMsg);
}
}
/**
* Read Steams element and parse subsequent steam elements.
*
* @param analyticsServerConfigElement OMElement of analyticsServerConfig
* @param analyticsServerProfile AnalyticsServerProfile instance
*/
private void processStreamsElement(OMElement analyticsServerConfigElement,
AnalyticsServerProfile analyticsServerProfile) {
OMElement streamsElement = analyticsServerConfigElement.getFirstChildWithName(
new QName(BPELConstants.ANALYTICS_SERVER_PROFILE_NS, AnalyticsConstants.STREAMS));
if (streamsElement == null) {
log.warn("No " + AnalyticsConstants.STREAMS + " found for Analytics server profile: " + profileLocation);
} else {
Iterator itr = streamsElement.getChildrenWithName(
new QName(BPELConstants.ANALYTICS_SERVER_PROFILE_NS, AnalyticsConstants.STREAM));
OMElement streamElement;
while (itr.hasNext()) {
streamElement = (OMElement) itr.next();
processStreamElement(streamElement, analyticsServerProfile);
}
}
}
/**
* Parse Steam element and setting stream data into given analyticsServerProfile instance.
*
* @param streamElement OMElement of Steam element.
* @param analyticsServerProfile AnalyticsServerProfile instance
*/
private void processStreamElement(OMElement streamElement, AnalyticsServerProfile analyticsServerProfile) {
OMAttribute nameAttr = streamElement.getAttribute(new QName(AnalyticsConstants.STREAM_NAME));
OMAttribute versionAttr = streamElement.getAttribute(new QName(AnalyticsConstants.STREAM_VERSION));
OMAttribute nickNameAttr = streamElement.getAttribute(new QName(AnalyticsConstants.STREAM_NICKNAME));
OMAttribute descriptionAttr = streamElement.getAttribute(new QName(AnalyticsConstants.STREAM_DESCRIPTION));
if (nameAttr != null && nickNameAttr != null && descriptionAttr != null && versionAttr != null &&
nameAttr.getAttributeValue() != null && nickNameAttr.getAttributeValue() != null &&
descriptionAttr.getAttributeValue() != null && versionAttr.getAttributeValue() != null &&
!AnalyticsConstants.EMPTY.equals(nameAttr.getAttributeValue().trim()) &&
!AnalyticsConstants.EMPTY.equals(nickNameAttr.getAttributeValue().trim()) &&
//!AnalyticsConstants.EMPTY.equals(descriptionAttr.getAttributeValue().trim()) &&
!AnalyticsConstants.EMPTY.equals(versionAttr.getAttributeValue().trim())) {
AnalyticsStreamConfiguration streamConfiguration =
new AnalyticsStreamConfiguration(nameAttr.getAttributeValue().trim(),
nickNameAttr.getAttributeValue().trim(),
descriptionAttr.getAttributeValue(),
versionAttr.getAttributeValue().trim());
OMElement dataElement = streamElement.getFirstChildWithName(
new QName(BPELConstants.ANALYTICS_SERVER_PROFILE_NS, AnalyticsConstants.STREAM_DATA));
if (dataElement == null) {
String errMsg =
AnalyticsConstants.STREAM_DATA + " element is not available for Analytics server profile: " +
profileLocation;
handleError(errMsg);
}
Iterator itr = dataElement.getChildrenWithName(
new QName(BPELConstants.ANALYTICS_SERVER_PROFILE_NS, AnalyticsConstants.STREAM_DATA_KEY));
OMElement keyElement;
while (itr.hasNext()) {
keyElement = (OMElement) itr.next();
processKeyElement(keyElement, streamConfiguration);
}
analyticsServerProfile
.addAnalyticsStreamConfiguration(streamConfiguration.getName(), streamConfiguration.getVersion(),
streamConfiguration);
} else {
String errMsg =
"One or many of the attributes of " + AnalyticsConstants.STREAM + " element is not available " +
"for Analytics server profile: " + profileLocation;
handleError(errMsg);
}
}
/**
* Process Key Element.
*
* @param keyElement OMElement of Key element
* @param streamConfiguration AnalyticsStreamConfiguration instance
*/
private void processKeyElement(OMElement keyElement, AnalyticsStreamConfiguration streamConfiguration) {
AnalyticsKey analyticsKey;
String name;
AnalyticsKey.AnalyticsKeyType type = AnalyticsKey.AnalyticsKeyType.NONE;
String variable;
String expression;
String part = null;
String query = null;
AnalyticsKey.AnalyticsKeyDataType dataType = AnalyticsKey.AnalyticsKeyDataType.STRING;
OMAttribute nameAttribute = keyElement.getAttribute(new QName(AnalyticsConstants.STREAM_DATA_KEY_NAME));
if (nameAttribute == null || nameAttribute.getAttributeValue() == null ||
AnalyticsConstants.EMPTY.equals(nameAttribute.getAttributeValue().trim())) {
String errMsg = AnalyticsConstants.STREAM_DATA_KEY_NAME +
" attribute of Key element cannot be null for Analytics server " +
"profile: " + profileLocation;
handleError(errMsg);
}
name = nameAttribute.getAttributeValue().trim();
OMAttribute typeAttribute = keyElement.getAttribute(new QName(AnalyticsConstants.STREAM_DATA_KEY_TYPE));
if (typeAttribute == null || typeAttribute.getAttributeValue() == null ||
AnalyticsConstants.EMPTY.equals((typeAttribute.getAttributeValue().trim()))) {
type = AnalyticsKey.AnalyticsKeyType.PAYLOAD;
log.debug("type attribute of Key element: " + name + " is not available. " +
"Type is default to payload");
}
try {
type = AnalyticsKey.AnalyticsKeyType.valueOf(typeAttribute.getAttributeValue().trim().toUpperCase());
} catch (IllegalArgumentException e) {
String errMsg = "Invalid key type specified for key name " + name;
handleError(errMsg, e);
}
OMAttribute dataTypeAttribute = keyElement.getAttribute(new QName(AnalyticsConstants.STREAM_DATA_KEY_DATA_TYPE));
if (dataTypeAttribute == null || dataTypeAttribute.getAttributeValue() == null ||
AnalyticsConstants.EMPTY.equals((dataTypeAttribute.getAttributeValue().trim()))) {
dataType = AnalyticsKey.AnalyticsKeyDataType.STRING;
log.debug("dataType attribute of Key element: " + name + " is not available. " +
"dataType default STRING set");
}
try {
dataType = AnalyticsKey.AnalyticsKeyDataType.valueOf(dataTypeAttribute.getAttributeValue().trim().toUpperCase());
} catch (IllegalArgumentException e) {
String errMsg = "Invalid key data type specified for key data type " + name;
handleError(errMsg, e);
}
OMElement fromElement = keyElement.getFirstChildWithName(
new QName(BPELConstants.ANALYTICS_SERVER_PROFILE_NS, AnalyticsConstants.STREAM_DATA_KEY_FROM));
if (fromElement == null) {
String errMsg = "From element not found for Key element: " + name + " for Analytics server " +
"profile: " + profileLocation;
handleError(errMsg);
}
OMAttribute variableAttribute =
fromElement.getAttribute(new QName(AnalyticsConstants.STREAM_DATA_KEY_FROM_VARIABLE));
if (variableAttribute != null && variableAttribute.getAttributeValue() != null &&
!AnalyticsConstants.EMPTY.equals(variableAttribute.getAttributeValue().trim())) {
variable = variableAttribute.getAttributeValue().trim();
OMAttribute partAttribute =
fromElement.getAttribute(new QName(AnalyticsConstants.STREAM_DATA_KEY_FROM_PART));
if (partAttribute != null && partAttribute.getAttributeValue() != null && !AnalyticsConstants.EMPTY
.equals(partAttribute.getAttributeValue().trim())) {
part = partAttribute.getAttributeValue().trim();
}
OMElement queryElement = fromElement.getFirstChildWithName(
new QName(BPELConstants.ANALYTICS_SERVER_PROFILE_NS, AnalyticsConstants
.STREAM_DATA_KEY_FROM_QUERY));
if (queryElement != null && !AnalyticsConstants.EMPTY.equals(queryElement.getText().trim())) {
query = queryElement.getText();
}
analyticsKey = new AnalyticsKey(name, variable, part, query, type, dataType);
} else {
if (fromElement.getText() == null || AnalyticsConstants.EMPTY.equals(fromElement.getText())) {
String errMsg = "Variable name or XPath expression not found for From of Key: " +
name + " for Analytics server profile: " + profileLocation;
handleError(errMsg);
}
expression = fromElement.getText().trim();
analyticsKey = new AnalyticsKey(name, type, dataType);
analyticsKey.setExpression(expression);
}
switch (analyticsKey.getType()) {
case PAYLOAD:
streamConfiguration.addPayloadAnalyticsKey(analyticsKey);
break;
case CORRELATION:
streamConfiguration.addCorrelationAnalyticsKey(analyticsKey);
break;
case META:
streamConfiguration.addMetaAnalyticsKey(analyticsKey);
break;
default:
String errMsg = "Unknown Analytics key type: " + type + " with Analytics key name: " +
analyticsKey.getName() + " in stream: " + streamConfiguration.getName();
handleError(errMsg);
}
}
private void handleError(String errMsg) {
log.error(errMsg);
throw new BPELDeploymentException(errMsg);
}
private void handleError(String errMsg, Exception e) {
log.error(errMsg, e);
throw new BPELDeploymentException(errMsg, e);
}
}