Package org.wso2.carbon.governance.registry.extensions.aspects

Source Code of org.wso2.carbon.governance.registry.extensions.aspects.DistributedLifeCycle$Condition

/*
* Copyright (c) 2007, 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.aspects;

import org.wso2.carbon.registry.core.Aspect;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.ResourceImpl;
import org.wso2.carbon.registry.core.utils.RegistryUtils;
import org.wso2.carbon.registry.core.jdbc.handlers.RequestContext;
import org.wso2.carbon.registry.core.jdbc.handlers.filters.Filter;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.app.RemoteRegistry;
import org.wso2.carbon.utils.NetworkUtils;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.impl.llom.util.AXIOMUtil;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Bundle;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import java.net.MalformedURLException;
import java.util.*;
import java.net.URL;

public class DistributedLifeCycle extends Aspect {
    public static final String PROMOTE = "promote";
    public static final String DEMOTE = "demote";
    public static final String RESOURCE_TYPE = "resource";
    public static final String LITERAL_TYPE = "literal";
    public static final String FILE_TYPE = "file";
    public static final String TYPE_TAG = "type";
    public static final String REGISTRY_TAG = "registry";
    public static final String LOCATION_TAG = "location";
    public static final String URL_TAG = "registry-url";
    public static final String PASSWORD_TAG = "registry-password";
    public static final String USERNAME_TAG = "registry-username";
    public static final String NAME_TAG = "name";
    public static final String DISTRIBUTED_CONFIGURATION_TAG = "distributed-configuration";
   
    public enum ConditionEnum { isNull, equals, contains, lessThan, greaterThan }
    public enum ConfigurationFromEnum { LOCAL_RESOURCE, REMOTE_RESOURCE, FILE, LITERAL }

    static class Condition {
        public String property;
        public ConditionEnum condition;
        public String value;

        Condition(String property, String condition, String value) {
            this.property = property;
            this.condition = ConditionEnum.valueOf(condition);
            this.value = value;
        }

        public boolean isTrue(Resource resource) {
            String propVal = resource.getProperty(property);
            if (propVal == null) {
                return condition == ConditionEnum.isNull;
            }

            switch (condition) {
                case equals:
                    return propVal.equals(value);
                case contains:
                    return propVal.indexOf(value) > -1;
                case lessThan:
                    return Integer.parseInt(propVal) < Integer.parseInt(value);
                case greaterThan:
                    return Integer.parseInt(propVal) > Integer.parseInt(value);
                default:
                    return false;
            }
        }

        public String getDescription() {
            StringBuffer ret = new StringBuffer();
            ret.append("Property '");
            ret.append(property);
            ret.append("' ");
            switch (condition) {
                case isNull:
                    ret.append("must be null");
                    break;
                case equals:
                    ret.append("must equal '");
                    ret.append(value);
                    ret.append("'");
                    break;
                case contains:
                    ret.append("must contain '");
                    ret.append(value);
                    ret.append("'");
                    break;
                case lessThan:
                    ret.append("must be less than ");
                    ret.append(value);
                    break;
                case greaterThan:
                    ret.append("must be greater than ");
                    ret.append(value);
                    break;
            }
            return ret.toString();
        }
    }

    private List<String> states = new ArrayList<String>();
    private Map<String, List<Condition>> transitions = new HashMap<String, List<Condition>>();
    private String stateProperty = "registry.lifecycle.Checklist.state";
    //boolean isConfigurationFromResource = false;
    //boolean configurationFromResourceExtracted = false;
    //String configurationResourcePath = "";

    String aspectConfigurationLocation = "/checklists/products";
    String aspectConfigurationRegistryURL = "https://10.100.1.121:9443/carbon";
    String aspectConfigurationRegistryUsername = "admin";
    String aspectConfigurationRegistryPassword = "password";

    ConfigurationFromEnum configurationFrom = ConfigurationFromEnum.LOCAL_RESOURCE;

    public DistributedLifeCycle() {
        // Lifecycle with no configuration gets the default set of states, with no conditions.
        states.add("Created");
        states.add("Tested");
        states.add("Deployed");
        states.add("Deprecated");
    }

    public DistributedLifeCycle(OMElement config) throws RegistryException {
        String myName = config.getAttributeValue(new QName(NAME_TAG));
        myName = myName.replaceAll("\\s", "");
        stateProperty = "registry.lifecycle." + myName + ".state";
       
        Iterator configurationElements = config.getChildElements();
        while (configurationElements.hasNext()) {
            OMElement configurationElement = (OMElement)configurationElements.next();

            /* expected format @ registry.xml
            <aspect name="Checklist" class="org.wso2.carbon.registry.extensions.aspects.ChecklistLifeCycle">
            <configuration type="resource">/checklists/products</configuration>
          </aspect>
          <aspect name="DistributedLifeCycle" class="org.wso2.carbon.governance.registry.extensions.aspects.DistributedLifeCycle">
                <configuration type="resource">        available options resource/literal/file
                    <location>/checklists/products</location>
                    <registry-url>https://10.100.1.1</registry-url>    local or https://10.100.1.1:9445/
                    <registry-username>admin</registry-username>
                    <registry-password>admin</registry-password>
                </configuration>
            </aspect>
             */

            if (configurationElement.getAttribute(new QName(TYPE_TAG)) != null) {
                String type = configurationElement.getAttributeValue(new QName(TYPE_TAG));
                if (type.equalsIgnoreCase(RESOURCE_TYPE)) {                  
                    states.clear();
                    transitions.clear();

                    Iterator configIterator = configurationElement.getChildrenWithName(new QName(LOCATION_TAG));
                    if (configIterator.hasNext()) {
                        OMElement itemElement = (OMElement)configIterator.next();
                        aspectConfigurationLocation = itemElement.getText();
                    }

                    configIterator = configurationElement.getChildrenWithName(new QName(URL_TAG));
                    if (configIterator.hasNext()) {
                        OMElement itemElement = (OMElement)configIterator.next();
                        aspectConfigurationRegistryURL = itemElement.getText();

                        //TODO: check with registry URL and set the ConfigurationFrom enum
                        //NetworkUtils.getLocalHostname();

                         configurationFrom = ConfigurationFromEnum.REMOTE_RESOURCE;
                    }

                    configIterator = configurationElement.getChildrenWithName(new QName(USERNAME_TAG));
                    if (configIterator.hasNext()) {
                        OMElement itemElement = (OMElement)configIterator.next();
                        aspectConfigurationRegistryUsername = itemElement.getText();
                    }

                    configIterator = configurationElement.getChildrenWithName(new QName(PASSWORD_TAG));
                    if (configIterator.hasNext()) {
                        OMElement itemElement = (OMElement)configIterator.next();
                        aspectConfigurationRegistryPassword = itemElement.getText();
                    }
                   
                    break;
                }
                else if (type.equalsIgnoreCase(LITERAL_TYPE)) {
                    //lifecycle stages are specified inside the configuration itself
                    //TODO: implement/check/bugfix this
                    String name = configurationElement.getAttributeValue(new QName(NAME_TAG));
                    if (name == null) {
                        throw new IllegalArgumentException("Must have a name attribute for each state");
                    }

                    states.add(name);
                    List<Condition> conditions = null;
                    Iterator conditionIterator = configurationElement.getChildElements();
                    while (conditionIterator.hasNext()) {
                        OMElement conditionEl = (OMElement)conditionIterator.next();
                        if (conditionEl.getQName().equals(new QName("condition"))) {
                            String property = conditionEl.getAttributeValue(new QName("property"));
                            String condition = conditionEl.getAttributeValue(new QName("condition"));
                            String value = conditionEl.getAttributeValue(new QName("value"));
                            Condition c = new Condition(property, condition, value);
                            if (conditions == null) conditions = new ArrayList<Condition>();
                            conditions.add(c);
                        }
                    }
                    if (conditions != null) {
                        transitions.put(name, conditions);
                    }
                   
                    break;
                }
                else if (type.equalsIgnoreCase(FILE_TYPE)) {
                    //lifecycle stages are specified in a file
                    //TODO: implement this
                    break;
                }
            }
        }
    }

    public void associate(Resource resource, Registry registry) throws RegistryException {
        try {
            if (configurationFrom == ConfigurationFromEnum.REMOTE_RESOURCE) {
                System.setProperty("javax.net.ssl.trustStore", "CARBON_HOME/resources/security/client-truststore.jks");
                System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");
                System.setProperty("javax.net.ssl.trustStoreType","JKS");

                RemoteRegistry remoteConfigurationRegisitry = new RemoteRegistry(new URL(aspectConfigurationRegistryURL),
                    aspectConfigurationRegistryUsername,
                    aspectConfigurationRegistryPassword);

                Resource configurationResource = remoteConfigurationRegisitry.get(aspectConfigurationLocation);
                String xmlContent = new String((byte[])configurationResource.getContent());  
                OMElement checklistConfiguration = AXIOMUtil.stringToOM(xmlContent);
                Iterator stateElements = checklistConfiguration.getChildElements();
                                                          /*
                <lifecycle-configuration>
                    <state name="Created">
                        <distributed-configuration>
                            <registry-url>https://10.100.1.1</registry-url>
                            <registry-username>admin</registry-username>
                            <registry-password>admin</registry-password>
                            <location>/workspace/development</location>
                        </distributed-configuration>
                        <vote-configuration>
                            <minimum-votes>4</minimum-votes>
                            <description></description>
                            <voted>
                                <user></user>
                                <user></user>
                            </voted>
                        </vote-configuration>
                        <checklist>
                            <item>Load Test Completed</item>
                            <item>Documentation Checked</item>
                            <item>Binary Packs Checked</item>
                            <item>UI Issues Checked</item>
                        </checklist>
                        <permissions>
                            <roles>
                                <promote>
                                    <role>everyone</role>
                                </promote>
                                <demote>
                                    <role>administrator</role>
                                    <role>tester</role>
                                </demote>
                                <vote/>
                                <view/>
                                <checklist-update/>
                            </roles>
                            <users>
                                <promote>
                                    <user>annonymous</user>
                                </promote>
                                <demote>
                                    <user>john</user>
                                    <user>jane</user>
                                </demote>
                                <vote/>
                                <view/>
                                <checklist-update/>
                            </users>
                        </permissions>
                    </state>
                 */
                int propertyOrder = 0;
                while (stateElements.hasNext()) {
                    OMElement stateElement = (OMElement)stateElements.next();
                    String stateName = stateElement.getAttributeValue(new QName(NAME_TAG));
                    if (stateName == null) {
                        throw new IllegalArgumentException("Must have a name attribute for each state");
                    }

                    states.add(stateName);

                    Iterator distConfigIterator = stateElement.getChildrenWithName
                            (new QName(DISTRIBUTED_CONFIGURATION_TAG));
                    if (distConfigIterator.hasNext()) {
                        OMElement distConfigElement = (OMElement)distConfigIterator.next();
                        Iterator configIterator = distConfigElement.getChildrenWithName(new QName(URL_TAG));
                        if (configIterator.hasNext()) {
                           
                        }
                        configIterator = distConfigElement.getChildrenWithName(new QName(PASSWORD_TAG));
                        if (configIterator.hasNext()) {

                        }
                        configIterator = distConfigElement.getChildrenWithName(new QName(USERNAME_TAG));
                        if (configIterator.hasNext()) {

                        }
                        configIterator = distConfigElement.getChildrenWithName(new QName(LOCATION_TAG));
                        if (configIterator.hasNext()) {

                        }
                    }

                    Iterator checkListIterator = stateElement.getChildElements();
                    int checklistItemOrder = 0;
                    while (checkListIterator.hasNext()) {
                        OMElement itemEl = (OMElement)checkListIterator.next();
                        if (itemEl.getQName().equals(new QName("checkitem"))) {
                            List<String> items = new ArrayList<String>();
                            String itemName = itemEl.getText();
                            if (itemName == null)
                                throw new RegistryException("Checklist items should have a name!");
                            items.add("status:" + stateName);
                            items.add("name:" + itemName);
                            items.add("value:false");

                            if (itemEl.getAttribute(new QName("order")) != null) {
                                items.add("order:" + itemEl.getAttributeValue(new QName("order")));
                            }
                            else {
                                items.add("order:" + checklistItemOrder);
                            }

                            String resourcePropertyNameForItem
                                    = "registry.custom_lifecycle.checklist.option" + propertyOrder + ".item";

                            resource.setProperty(resourcePropertyNameForItem, items);
                            checklistItemOrder++;
                            propertyOrder++;
                        }
                    }
                }
            }
        } catch (XMLStreamException e) {
            throw new RegistryException("Resource does not contain valid XML configuration: " + e.toString());
        catch (MalformedURLException e) {
            throw new RegistryException("Invalid URL in aspect configuration: " + e.toString());
        }

        resource.setProperty(stateProperty, states.get(0));
    }

    public void invoke(RequestContext context, String action) throws RegistryException {
        Resource resource = context.getResource();
        String currentState = resource.getProperty(stateProperty);
        int stateIndex = states.indexOf(currentState);
        if (stateIndex == -1) {
            throw new RegistryException("State '" + currentState + "' is not valid!");
        }

        String newState;
        if (PROMOTE.equals(action)) {
            if (stateIndex == states.size() - 1) {
                throw new RegistryException("Can't promote beyond end of configured lifecycle!");
            }

            // Make sure all conditions are met
            List<Condition> conditions = transitions.get(currentState);
            if (conditions != null) {
                for (Condition condition : conditions) {
                    if (!condition.isTrue(resource)) {
                        throw new RegistryException(
                                "Condition failed - " + condition.getDescription());
                    }
                }
            }
            newState = states.get(stateIndex + 1);
        } else if (DEMOTE.equals(action)) {
            if (stateIndex == 0) {
                throw new RegistryException("Can't demote beyond start of configured lifecycle!");
            }
            newState = states.get(stateIndex - 1);
        } else {
            throw new RegistryException("Invalid action '" + action + "'");
        }

        resource.setProperty(stateProperty, newState);
        context.getRepository().put(resource.getPath(), resource);
    }

    public String[] getAvailableActions(RequestContext context) {
        ArrayList<String> actions = new ArrayList<String>();
        Resource resource = context.getResource();
        String currentState = resource.getProperty(stateProperty);

        Properties props = resource.getProperties();
        boolean allItemsAreChecked = true;
        for (Map.Entry<Object, Object> e : props.entrySet()) {
            if (((String) e.getKey()).startsWith("registry.custom_lifecycle.checklist.")) {
                List<String> propValues = (List<String>) e.getValue();
                String[] propertyValues = propValues.toArray(new String[propValues.size()]);
                String itemLifeCycleState = null;
                String itemValue = null;

                if (propertyValues != null) {
                      for (int index = 0; index < propertyValues.length; index++) {
                        String item = propertyValues[index];
                        if ((itemLifeCycleState == null) && (item.startsWith("status:"))) {
                            itemLifeCycleState = item.substring(7);                          
                        }
                        if ((itemValue == null) && (item.startsWith("value:"))) {
                            itemValue = item.substring(6);
                        }
                    }
                }

                if ((itemLifeCycleState != null) && (itemValue != null)) {
                    if (itemLifeCycleState.equalsIgnoreCase(currentState)) {
                        if (itemValue.equalsIgnoreCase("false")) {
                            allItemsAreChecked = false;
                            break;
                        }
                    }
                }
            }
        }

        int stateIndex = states.indexOf(currentState);
        if (stateIndex > -1 && stateIndex < states.size() - 1) {
            if (allItemsAreChecked)
                actions.add(PROMOTE);
        }
        if (stateIndex > 0) {
            actions.add(DEMOTE);
        }
        return actions.toArray(new String[actions.size()]);
    }

    public void dissociate(RequestContext context) {
        Resource resource = context.getResource();
        if (resource != null) {
            resource.removeProperty(stateProperty);
        }
    }

    public String getCurrentState(Resource resource) {
        return resource.getProperty(stateProperty);
    }  
}
TOP

Related Classes of org.wso2.carbon.governance.registry.extensions.aspects.DistributedLifeCycle$Condition

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.