org.apache.stratos.metadata.service.registry.MetadataApiRegistry.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.stratos.metadata.service.registry.MetadataApiRegistry.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.apache.stratos.metadata.service.registry;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.stratos.common.concurrent.locks.ReadWriteLock;
import org.apache.stratos.metadata.service.MetadataApplicationEventReceiver;
import org.apache.stratos.metadata.service.MetadataTopologyEventReceiver;
import org.apache.stratos.metadata.service.ServiceHolder;
import org.apache.stratos.metadata.service.definition.Property;
import org.apache.stratos.metadata.service.exception.MetadataException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.session.UserRegistry;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Context;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Carbon registry implementation
 */

public class MetadataApiRegistry implements DataStore {

    private static final String mainResource = "metadata/";
    private static Log log = LogFactory.getLog(MetadataApiRegistry.class);
    @Context
    HttpServletRequest httpServletRequest;
    private static final ConcurrentHashMap<String, ReadWriteLock> applicationIdToReadWriteLockMap = new ConcurrentHashMap<>();
    private MetadataTopologyEventReceiver metadataTopologyEventReceiver;
    private MetadataApplicationEventReceiver metadataApplicationEventReceiver;

    public MetadataApiRegistry() {
        metadataTopologyEventReceiver = new MetadataTopologyEventReceiver();
        //        metadataTopologyEventReceiver.execute();

        metadataApplicationEventReceiver = new MetadataApplicationEventReceiver();
        //        metadataApplicationEventReceiver.execute();
    }

    /**
     * Get Properties of application
     *
     * @param applicationId Application ID under which properties should be retrieved
     * @return List of properties
     * @throws MetadataException
     */
    public List<Property> getApplicationProperties(String applicationId) throws MetadataException {
        String resourcePath = mainResource + applicationId;
        try {
            acquireReadLock(applicationId);
            return getRegistryResourceProperties(resourcePath, applicationId);
        } catch (Exception e) {
            String msg = String.format(
                    "Failed to get properties from registry [resource-path] %s for " + "[application-id] %s",
                    resourcePath, applicationId);
            log.error(msg, e);
            throw new MetadataException(msg, e);
        } finally {
            try {
                releaseReadLock(applicationId);
            } catch (MetadataException ignored) {
            }
        }
    }

    /**
     * Get properties of cluster
     *
     * @param applicationId Application ID under which properties should be retrieved
     * @param clusterId     Cluster ID under which properties should be retrieved
     * @return List of properties
     * @throws MetadataException
     */
    public List<Property> getClusterProperties(String applicationId, String clusterId) throws MetadataException {
        String resourcePath = mainResource + applicationId + "/" + clusterId;
        try {
            acquireReadLock(applicationId);
            return getRegistryResourceProperties(resourcePath, applicationId);
        } catch (Exception e) {
            String msg = String
                    .format("Failed to get properties from registry [resource-path] %s for [application-id] "
                            + "%s, [cluster-id] %s", resourcePath, applicationId, clusterId);
            log.error(msg, e);
            throw new MetadataException(msg, e);
        } finally {
            try {
                releaseReadLock(applicationId);
            } catch (MetadataException ignored) {
            }
        }
    }

    private List<Property> getRegistryResourceProperties(String registryResourcePath, String applicationId)
            throws RegistryException, MetadataException {
        Registry tempRegistry = getRegistry();
        if (!tempRegistry.resourceExists(registryResourcePath)) {
            return null;
        }

        // We are using only super tenant registry to persist
        PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
        ctx.setTenantId(MultitenantConstants.SUPER_TENANT_ID);
        ctx.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);

        Resource regResource = tempRegistry.get(registryResourcePath);
        ArrayList<Property> newProperties = new ArrayList<>();
        Properties props = regResource.getProperties();
        Enumeration<?> x = props.propertyNames();
        while (x.hasMoreElements()) {
            String key = (String) x.nextElement();
            List<String> values = regResource.getPropertyValues(key);
            Property property = new Property();
            property.setKey(key);
            String[] valueArr = new String[values.size()];
            property.setValues(values.toArray(valueArr));

            newProperties.add(property);
        }
        return newProperties;
    }

    public void addPropertyToApplication(String applicationId, Property property)
            throws RegistryException, MetadataException {
        Registry registry = getRegistry();
        String resourcePath = mainResource + applicationId;

        try {
            acquireWriteLock(applicationId);
            // We are using only super tenant registry to persist
            PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
            ctx.setTenantId(MultitenantConstants.SUPER_TENANT_ID);
            ctx.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
            Resource nodeResource;
            if (registry.resourceExists(resourcePath)) {
                nodeResource = registry.get(resourcePath);
            } else {
                nodeResource = registry.newCollection();
                if (log.isDebugEnabled()) {
                    log.debug(String.format("Registry resource created: [resource-path] %s", resourcePath));
                }
            }

            boolean updated = false;
            for (String value : property.getValues()) {
                if (!propertyValueExist(nodeResource, property.getKey(), value)) {
                    updated = true;
                    if (log.isDebugEnabled()) {
                        log.debug(
                                String.format("Registry property updated: [resource-path] %s, [key] %s [value] %s",
                                        resourcePath, property.getKey(), value));
                    }
                    nodeResource.addProperty(property.getKey(), value);
                } else {
                    if (log.isDebugEnabled()) {
                        log.debug(String.format(
                                "Registry value already exists: [resource-path] %s, [key] %s, [value] %s",
                                resourcePath, property.getKey(), value));
                    }
                }
            }
            if (updated) {
                registry.put(resourcePath, nodeResource);
                if (log.isDebugEnabled()) {
                    log.debug(String.format(
                            "Registry property is persisted: [resource-path] %s, [key] %s, [values] %s",
                            resourcePath, property.getKey(), Arrays.asList(property.getValues())));
                }
            }
        } catch (Exception e) {
            String msg = String.format(
                    "Failed to persist properties in registry: [resource-path] %s, [key] %s, [values] %s",
                    resourcePath, property.getKey(), Arrays.asList(property.getValues()));
            log.error(msg, e);
            throw new MetadataException(msg, e);
        } finally {
            try {
                releaseWriteLock(applicationId);
            } catch (MetadataException ignored) {
            }
        }
    }

    private boolean propertyValueExist(Resource nodeResource, String key, String value) {
        List<String> properties = nodeResource.getPropertyValues(key);
        return properties != null && properties.contains(value);

    }

    public boolean removePropertyValueFromApplication(String applicationId, String propertyKey,
            String valueToRemove) throws RegistryException, MetadataException {
        Registry registry = getRegistry();
        String resourcePath = mainResource + applicationId;

        try {
            acquireWriteLock(applicationId);
            // We are using only super tenant registry to persist
            PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
            ctx.setTenantId(MultitenantConstants.SUPER_TENANT_ID);
            ctx.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
            Resource nodeResource;
            if (registry.resourceExists(resourcePath)) {
                nodeResource = registry.get(resourcePath);
            } else {
                log.warn(String.format("Registry property not found: [resource-path] %s, [key] %s", resourcePath,
                        propertyKey));
                return false;
            }
            nodeResource.removePropertyValue(propertyKey, valueToRemove);
            registry.put(resourcePath, nodeResource);
            log.info(String.format("Registry property removed: [application-id] %s, [key] %s, [value] %s",
                    applicationId, propertyKey, valueToRemove));
            return true;
        } catch (Exception e) {
            throw new MetadataException(
                    String.format("Could not remove registry resource: [resource-path] %s, [key] %s, [value] %s",
                            resourcePath, propertyKey, valueToRemove),
                    e);
        } finally {
            try {
                releaseWriteLock(applicationId);
            } catch (MetadataException ignored) {
            }
        }
    }

    /**
     * Add property to cluster
     *
     * @param applicationId Application ID against which added property will be stored
     * @param clusterId     Cluster ID against which added property will be stored
     * @param property      Property to be stored in the registry
     * @throws RegistryException, MetadataException
     */
    public void addPropertyToCluster(String applicationId, String clusterId, Property property)
            throws RegistryException, MetadataException {
        Registry registry = getRegistry();
        String resourcePath = mainResource + applicationId + "/" + clusterId;

        try {
            acquireWriteLock(applicationId);
            // We are using only super tenant registry to persist
            PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
            ctx.setTenantId(MultitenantConstants.SUPER_TENANT_ID);
            ctx.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
            Resource nodeResource;
            if (registry.resourceExists(resourcePath)) {
                nodeResource = registry.get(resourcePath);
            } else {
                nodeResource = registry.newResource();
                if (log.isDebugEnabled()) {
                    log.debug(String.format("Registry resource created for [cluster-id] %s", clusterId));
                }
            }
            nodeResource.setProperty(property.getKey(), Arrays.asList(property.getValues()));
            registry.put(resourcePath, nodeResource);
            log.info(String.format(
                    "Registry property persisted: [resource-path] %s [Property Name] %s [Property Values] %s",
                    resourcePath, property.getKey(), Arrays.asList(property.getValues())));
        } catch (Exception e) {
            throw new MetadataException(
                    String.format("Could not add registry resource: [resource-path] %s, [key] %s, [value] %s",
                            resourcePath, property.getKey(), Arrays.asList(property.getValues())),
                    e);

        } finally {
            try {
                releaseWriteLock(applicationId);
            } catch (MetadataException ignored) {
            }
        }
    }

    private UserRegistry getRegistry() throws RegistryException {
        return ServiceHolder.getRegistryService().getGovernanceSystemRegistry();
    }

    /**
     * Delete the resource identified by the applicationId, if exist.
     *
     * @param applicationId ID of the application.
     * @return True if resource exist and able to delete, else false.
     * @throws RegistryException, MetadataException
     */
    public boolean deleteApplicationProperties(String applicationId) throws RegistryException, MetadataException {
        if (StringUtils.isBlank(applicationId)) {
            throw new IllegalArgumentException("Application ID can not be null");
        }
        Registry registry = getRegistry();
        String resourcePath = mainResource + applicationId;

        try {
            acquireWriteLock(applicationId);
            // We are using only super tenant registry to persist
            PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
            ctx.setTenantId(MultitenantConstants.SUPER_TENANT_ID);
            ctx.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
            if (registry.resourceExists(resourcePath)) {
                registry.delete(resourcePath);
                log.info(String.format("Registry properties removed for [application-id] %s", applicationId));
            }
            return true;
        } catch (Exception e) {
            throw new MetadataException(
                    String.format("Could not remove registry resource: [resource-path] %s", resourcePath), e);
        } finally {
            try {
                releaseWriteLock(applicationId);
            } catch (MetadataException ignored) {
            }
        }
    }

    public boolean removePropertyFromApplication(String applicationId, String propertyKey)
            throws RegistryException, MetadataException {
        Registry registry = getRegistry();
        String resourcePath = mainResource + applicationId;
        Resource nodeResource;

        try {
            acquireWriteLock(applicationId);
            // We are using only super tenant registry to persist
            PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
            ctx.setTenantId(MultitenantConstants.SUPER_TENANT_ID);
            ctx.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
            if (registry.resourceExists(resourcePath)) {
                nodeResource = registry.get(resourcePath);
                if (nodeResource.getProperty(propertyKey) == null) {
                    log.info(String.format("Registry property not found: [application-id] %s [key] %s ",
                            applicationId, propertyKey));
                    return false;
                } else {
                    nodeResource.removeProperty(propertyKey);
                    registry.put(resourcePath, nodeResource);
                }
            } else {
                log.error("Registry resource not not found at " + resourcePath);
                return false;
            }

            log.info(String.format("Registry property removed: [application-id] %s, [key] %s", applicationId,
                    propertyKey));
            return true;
        } catch (Exception e) {
            throw new MetadataException(
                    String.format("Could not remove registry resource: [resource-path] %s, [key] %s", resourcePath,
                            propertyKey),
                    e);
        } finally {
            try {
                releaseWriteLock(applicationId);
            } catch (MetadataException ignored) {
            }
        }
    }

    public void acquireReadLock(String applicationId) throws MetadataException {
        if (applicationIdToReadWriteLockMap.get(applicationId) == null) {
            throw new MetadataException(
                    String.format("Invalid application [application-id] %s not found. Failed to acquire read lock.",
                            applicationId));
        } else {
            applicationIdToReadWriteLockMap.get(applicationId).acquireReadLock();
        }
    }

    public void acquireWriteLock(String applicationId) throws MetadataException {
        if (applicationIdToReadWriteLockMap.get(applicationId) == null) {
            throw new MetadataException(String.format(
                    "Invalid application [application-id] %s not found. Failed to acquire write lock.",
                    applicationId));
        } else {
            applicationIdToReadWriteLockMap.get(applicationId).acquireWriteLock();
        }
    }

    public void releaseReadLock(String applicationId) throws MetadataException {
        if (applicationIdToReadWriteLockMap.get(applicationId) == null) {
            throw new MetadataException(
                    String.format("Invalid application [application-id] %s not found. Failed to release read lock.",
                            applicationId));
        } else {
            applicationIdToReadWriteLockMap.get(applicationId).releaseReadLock();
        }
    }

    public void releaseWriteLock(String applicationId) throws MetadataException {
        if (applicationIdToReadWriteLockMap.get(applicationId) == null) {
            throw new MetadataException(String.format(
                    "Invalid application [application-id] %s not found. Failed to release write lock.",
                    applicationId));
        } else {
            applicationIdToReadWriteLockMap.get(applicationId).releaseWriteLock();
        }
    }

    public static ConcurrentHashMap<String, ReadWriteLock> getApplicationIdToReadWriteLockMap() {
        return applicationIdToReadWriteLockMap;
    }

    //    public void stopTopologyReceiver() {
    //        metadataTopologyEventReceiver.terminate();
    //    }

    //    public void stopApplicationReceiver() {
    //        metadataApplicationEventReceiver.terminate();
    //    }
}