/*
* Copyright (c) 2005-2011, 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.governance.registry.extensions.utils;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.util.AXIOMUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.wso2.carbon.CarbonException;
import org.wso2.carbon.governance.api.exception.GovernanceException;
import org.wso2.carbon.governance.api.util.GovernanceArtifactConfiguration;
import org.wso2.carbon.governance.api.util.GovernanceConstants;
import org.wso2.carbon.governance.common.utils.GovernanceUtils;
import org.wso2.carbon.registry.core.Collection;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.RegistryConstants;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.config.RegistryContext;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.session.CurrentSession;
import org.wso2.carbon.registry.core.utils.RegistryUtils;
import org.wso2.carbon.registry.extensions.services.RXTStoragePathService;
import org.wso2.carbon.registry.extensions.services.RXTStoragePathServiceImpl;
import org.wso2.carbon.registry.extensions.utils.CommonConstants;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.FileUtil;
import org.xml.sax.SAXException;
import javax.cache.Cache;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;
import java.io.*;
import java.util.*;
import static org.wso2.carbon.governance.api.util.GovernanceUtils.getGovernanceArtifactConfiguration;
import static org.wso2.carbon.governance.api.util.GovernanceUtils.getRXTConfigCache;
public class CommonUtil {
private static final Log log = LogFactory.getLog(CommonUtil.class);
private final static Map<String, HashMap<String, String>>
associationConfigMap = new HashMap<>();
private final static Map<String, HashMap<String, String>>
reverseAssociationConfigMap = new HashMap<>();
private static final Map<String, HashMap<String, String>> associationTypeIconConfigMap = new HashMap();
public static final String REVERSE_ASSOCIATION = "reverseAssociation";
public static final String TYPE = "type";
public static final String ASSOCIATION_CONFIG = "AssociationConfig";
public static final String ICON_CLASS = "iconClass";
private static int dependencyGraphMaxDepth = -1;
private static RXTStoragePathService rxtSPService;
public static RXTStoragePathService getRxtStoragePathService() {
return rxtSPService;
}
public static void setRxtStoragePathService(RXTStoragePathService rxtSPService) {
CommonUtil.rxtSPService = rxtSPService;
}
public static String[] getAllLifeCycleStates(Registry registry, String lifeCycleName) throws RegistryException {
boolean isLiteral = true;
List<String> stateList = new ArrayList<String>();
String[] allAspects = registry.getAvailableAspects();
// Check if the given LC name is there in the registry. If not will return null
if (!Arrays.asList(allAspects).contains(lifeCycleName)) {
String msg = "There are no lifecycles with the given name";
throw new RegistryException(msg);
}
// Here we are getting the LC configuration from the default LC configuration path.
// If this fails we use the registry.xml to see whether the LC name is there and will get the resource.
Resource resource=null;
// reading the registry.xml to see of the LC configuration is there
if (!registry.resourceExists(RegistryConstants.CONFIG_REGISTRY_BASE_PATH+
RegistryConstants.LIFECYCLE_CONFIGURATION_PATH + lifeCycleName)) {
/*
* Getting the registry.xml from the client side is not possible.
* Therefore if there are no resource in the default life cycle resource store path we consider this life cycle
* as a static life cycle which has been configured using the registry.xml
* Since we are unable to read the registry.xml from a client program we throw an exception here.
* */
String msg = "The given lifecycle configuration is an static configuration. Unable to read the registry.xml";
throw new RegistryException(msg);
/*
try {
FileInputStream inputStream = new FileInputStream(getConfigFile());
StAXOMBuilder builder = new StAXOMBuilder(inputStream);
OMElement configElement = builder.getDocumentElement();
Iterator aspectElement = configElement.getChildrenWithName(new QName("aspect"));
while (aspectElement.hasNext()) {
OMElement next = (OMElement) aspectElement.next();
String name = next.getAttributeValue(new QName("name"));
if(name.equals(lifeCycleName)){
OMElement element = next.getFirstElement();
resource = registry.get(element.getText());
isLiteral = false;
break;
}
}
} catch (FileNotFoundException e) {
throw new RegistryException("", e);
} catch (XMLStreamException e) {
throw new RegistryException("", e);
}
*/
}else{
resource = registry.get(RegistryConstants.CONFIG_REGISTRY_BASE_PATH+
RegistryConstants.LIFECYCLE_CONFIGURATION_PATH + lifeCycleName);
}
// here we get the resource content and build a OMElement from it
try {
String xmlContent = RegistryUtils.decodeBytes((byte[])resource.getContent());
OMElement configurationElement = AXIOMUtil.stringToOM(xmlContent);
// if the config type is literal we take the lifecycle element from it
if(isLiteral){
OMElement typeElement = configurationElement.getFirstElement();
configurationElement = typeElement.getFirstElement();
}
// this is to see whether this is the new configuration or the old one
Iterator statesElement = configurationElement.getChildrenWithName(new QName("scxml"));
// if it is the new configuration we use the scxml parser to get all the elements
if(statesElement.hasNext()){
while (statesElement.hasNext()) {
OMElement scxmlElement = (OMElement) statesElement.next();
Iterator stateElements = scxmlElement.getChildrenWithName(new QName("state"));
while (stateElements.hasNext()) {
OMElement next = (OMElement) stateElements.next();
stateList.add(next.getAttributeValue(new QName("id")));
}
}
}
else{
Iterator states = configurationElement.getChildElements();
while (states.hasNext()) {
OMElement next = (OMElement) states.next();
stateList.add(next.getAttributeValue(new QName("name")));
}
}
} catch (XMLStreamException e) {
throw new RegistryException("", e);
}
String[] retArray = new String[stateList.size()];
return stateList.toArray(retArray);
}
public static void addRxtConfigs(Registry systemRegistry, int tenantId) throws RegistryException {
loadAssociationConfig();
Cache<String,Boolean> rxtConfigCache = getRXTConfigCache(GovernanceConstants.RXT_CONFIG_CACHE_ID);
String rxtDir = CarbonUtils.getCarbonHome() + File.separator + "repository" + File.separator +
"resources" + File.separator + "rxts";
File file = new File(rxtDir);
if(!file.exists()){
return;
}
//create a FilenameFilter
FilenameFilter filenameFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
//if the file extension is .rxt return true, else false
return name.endsWith(".rxt");
}
};
String[] rxtFilePaths = file.list(filenameFilter);
if(rxtFilePaths.length == 0){
return;
}
for (String rxtPath : rxtFilePaths) {
String resourcePath = RegistryConstants.GOVERNANCE_COMPONENT_PATH +
RegistryConstants.PATH_SEPARATOR + "types" + RegistryConstants.PATH_SEPARATOR + rxtPath;
int currentTenantId = CurrentSession.getTenantId();
CurrentSession.setTenantId(tenantId);
RegistryContext registryContext = systemRegistry.getRegistryContext();
String absolutePath = RegistryUtils.getAbsolutePath(registryContext, resourcePath);
if (registryContext.isSystemResourcePathRegistered(absolutePath)) {
CurrentSession.setTenantId(currentTenantId);
continue;
} else {
registryContext.registerSystemResourcePath(absolutePath);
CurrentSession.setTenantId(currentTenantId);
}
try {
String rxtConfigRelativePath = RegistryUtils.getRelativePathToOriginal(GovernanceConstants.RXT_CONFIGS_PATH,
RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH);
if (!systemRegistry.resourceExists(rxtConfigRelativePath)) {
Collection collection = systemRegistry.newCollection();
systemRegistry.put(rxtConfigRelativePath, collection);
}
Resource rxtCollection = systemRegistry.get(rxtConfigRelativePath);
String rxtName = resourcePath.substring(resourcePath.lastIndexOf("/") + 1).split("\\.")[0];
if (!systemRegistry.resourceExists(resourcePath)) {
String propertyName = "registry." + rxtName;
if (rxtCollection.getProperty(propertyName) == null) {
rxtCollection.setProperty(propertyName, "true");
String rxt = FileUtil.readFileToString(rxtDir + File.separator + rxtPath);
Resource resource = systemRegistry.newResource();
resource.setContent(rxt.getBytes());
resource.setMediaType(CommonConstants.RXT_MEDIA_TYPE);
systemRegistry.put(resourcePath, resource);
rxtConfigCache.put(resourcePath,true);
GovernanceArtifactConfiguration configuration = getGovernanceArtifactConfiguration(rxt);
String mediaType = configuration.getMediaType();
String storagePath = configuration.getPathExpression();
addStoragePath(mediaType, storagePath);
}
} else {
Resource resource = systemRegistry.get(resourcePath);
Object content = resource.getContent();
String elementString;
if (content instanceof String) {
elementString = (String) content;
} else {
elementString = RegistryUtils.decodeBytes((byte[]) content);
}
GovernanceArtifactConfiguration configuration = getGovernanceArtifactConfiguration(elementString);
String mediaType = configuration.getMediaType();
String storagePath = configuration.getPathExpression();
addStoragePath(mediaType, storagePath);
if (log.isDebugEnabled()) {
log.debug("RXT " + rxtName + " already exists.");
}
}
} catch (IOException e) {
String msg = "Failed to read rxt files";
throw new RegistryException(msg, e);
} catch (RegistryException e) {
String msg = "Failed to add rxt to registry ";
throw new RegistryException(msg, e);
}
}
}
/**
* This method reads the Association Config xml and populates the association and reverse association map.
*/
public static void loadAssociationConfig() {
String associationConfigFile =
CarbonUtils.getCarbonConfigDirPath() + File.separator + GovernanceUtils.GOVERNANCE_CONFIG_FILE;
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(new File(associationConfigFile));
doc.getDocumentElement().normalize();
NodeList associationConfigNode = doc.getElementsByTagName(ASSOCIATION_CONFIG);
NodeList nodeList = associationConfigNode.item(0).getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node association = nodeList.item(i);
if (association.getNodeType() == Node.ELEMENT_NODE) {
HashMap<String, String> associationMap = new HashMap<>();
HashMap<String, String> reverseAssociationMap = new HashMap<>();
HashMap iconClassMap = new HashMap();
NodeList childNodeList = association.getChildNodes();
if (childNodeList != null) {
for (int j = 0; j < childNodeList.getLength(); j++) {
Node types = childNodeList.item(j);
if (types.getNodeType() == Node.ELEMENT_NODE) {
associationMap.put(types.getNodeName(), types.getFirstChild().getNodeValue());
if (((Element) types).hasAttribute(REVERSE_ASSOCIATION)) {
reverseAssociationMap.put(types.getNodeName(),
((Element) types).getAttribute(REVERSE_ASSOCIATION));
}
if(((Element)types).hasAttribute(ICON_CLASS)) {
iconClassMap.put(types.getNodeName(), ((Element)types).getAttribute(ICON_CLASS));
}
}
}
}
associationConfigMap.put(((Element) association).getAttribute(TYPE), associationMap);
reverseAssociationConfigMap.put(((Element) association).getAttribute(TYPE), reverseAssociationMap);
associationTypeIconConfigMap.put(((Element)association).getAttribute(TYPE), iconClassMap);
}
}
} catch (FileNotFoundException e) {
log.error("Failed to find the governance.xml", e);
} catch (ParserConfigurationException | SAXException e) {
log.error("Failed to parse the governance.xml", e);
} catch (IOException e) {
log.error("Error while reading the governance.xml", e);
}
}
/**
* This method is used by greg-publisher-api.js to read the association configuration map.
* @param shortName short name of the artifact type.
* @return map containing association type as key and
*/
public static HashMap<String, String> getAssociationConfig(String shortName){
if(associationConfigMap.size() == 0){
log.warn("Failed to find association mappings");
return null;
}
if(associationConfigMap.containsKey(shortName)){
return associationConfigMap.get(shortName);
}else{
return null;
}
}
/**
* This method is used by greg-publisher-api.js to read the reverse association type for a given short name and
* association type.
* @param shortName short name of the artifact type.
* @param associationType association type from source asset to destination asset.
* @return reverse association type from destination asset to source asset.
*/
public static String getReverseAssociationType(String shortName, String associationType){
if(reverseAssociationConfigMap.size() == 0){
log.warn("Failed to find reverse association mappings");
return null;
}
if(reverseAssociationConfigMap.containsKey(shortName) && reverseAssociationConfigMap.get(shortName)
.containsKey(associationType)){
return reverseAssociationConfigMap.get(shortName).get(associationType);
}else{
return null;
}
}
/**
* This method is used by greg-publisher-api.js to read the reverse association type for a given short name and
* association type when removing the bi-directional association. If the association removal is done from the
* destination asset, then this method will determine association type from source asset to destination asset.
* @param shortName short name of the artifact type.
* @param associationType association type from source asset to destination asset.
* @return reverse association type from source asset to destination asset.
*/
public static String getAssociationTypeForRemoveOperation (String shortName, String
associationType){
if(reverseAssociationConfigMap.size() == 0){
log.warn("Failed to find association mappings");
return null;
}
String reverseAssociationType = null;
if(reverseAssociationConfigMap.containsKey(shortName)){
for (Map.Entry<String, String> entry : reverseAssociationConfigMap.get(shortName).entrySet()){
if(associationType.equals(entry.getValue())) {
reverseAssociationType = entry.getKey();
break;
}
}
return reverseAssociationType;
}else{
return null;
}
}
public static HashMap<String, String> getAssociationWithIcons(String shortName) {
if (associationTypeIconConfigMap.size() == 0) {
log.warn("Failed to find association mappings");
return null;
}
if (associationTypeIconConfigMap.containsKey(shortName)) {
return associationTypeIconConfigMap.get(shortName);
} else {
return null;
}
}
public static void loadDependencyGraphMaxDepthConfig() {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(getConfigFile());
StAXOMBuilder builder = new StAXOMBuilder(
CarbonUtils.replaceSystemVariablesInXml(fileInputStream));
OMElement configElement = builder.getDocumentElement();
OMElement dependencyGraphMaxDepthConfig = configElement.getFirstChildWithName(
new QName("dependencyGraphMaxDepth"));
if (dependencyGraphMaxDepthConfig != null) {
dependencyGraphMaxDepth = Integer.parseInt(dependencyGraphMaxDepthConfig.getText());
}
} catch (FileNotFoundException | GovernanceException e) {
log.error("Failed to find the registry.xml", e);
} catch (CarbonException e) {
log.error("Could not replace system variables in registry.xml", e);
} catch (XMLStreamException e) {
log.error("could not build registry.xml OM", e);
}
}
// Get registry.xml instance.
private static File getConfigFile() throws GovernanceException {
String configPath = CarbonUtils.getRegistryXMLPath();
if (configPath != null) {
File registryXML = new File(configPath);
if (!registryXML.exists()) {
String msg = "Registry configuration file (registry.xml) file does " +
"not exist in the path " + configPath;
throw new GovernanceException(msg);
}
return registryXML;
} else {
String msg = "Cannot find registry.xml";
throw new GovernanceException(msg);
}
}
public static int getDependencyGraphMaxDepth(){
return dependencyGraphMaxDepth;
}
public static void addStoragePath(String mediaType, String storagePath) {
RXTStoragePathServiceImpl service = (RXTStoragePathServiceImpl) getRxtStoragePathService();
service.addStoragePath(mediaType, storagePath);
}
public static void removeStoragePath(String mediaType) {
RXTStoragePathServiceImpl service = (RXTStoragePathServiceImpl) getRxtStoragePathService();
service.removeStoragePath(mediaType);
}
// handling the possibility that handlers are not called within each other.
private static ThreadLocal<Boolean> clearMetaDataInProgress = new ThreadLocal<Boolean>() {
protected Boolean initialValue() {
return false;
}
};
public static boolean isMetaDataClearLockAvailable() {
return !clearMetaDataInProgress.get();
}
public static void acquireMetaDataClearLock() {
clearMetaDataInProgress.set(true);
}
public static void releaseMetaDataClearLock() {
clearMetaDataInProgress.set(false);
}
}