/*
* Copyright (c) 2008, 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.services.services;
import org.apache.axiom.om.OMException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.core.AbstractAdmin;
import org.wso2.carbon.governance.api.common.dataobjects.GovernanceArtifact;
import org.wso2.carbon.governance.api.services.ServiceManager;
import org.wso2.carbon.governance.api.services.dataobjects.Service;
import org.wso2.carbon.governance.api.util.GovernanceUtils;
import org.wso2.carbon.registry.common.CommonConstants;
import org.wso2.carbon.registry.core.*;
import org.wso2.carbon.registry.core.session.UserRegistry;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.utils.RegistryUtils;
import org.wso2.carbon.registry.core.utils.UUIDGenerator;
import org.wso2.carbon.registry.extensions.utils.CommonUtil;
import org.wso2.carbon.governance.services.util.Util;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.namespace.QName;
import java.io.StringReader;
import java.sql.SQLException;
import java.util.*;
public class AddServicesService extends AbstractAdmin {
private static final Log log = LogFactory.getLog(AddServicesService.class);
private static Map<String, Boolean> lifecycleAspects = new HashMap<String, Boolean>();
private static final String TRUNK = "trunk";
public boolean addService(String info)throws RegistryException{
Registry registry = getGovernanceRegistry();
if (RegistryUtils.isRegistryReadOnly(registry.getRegistryContext())) {
return false;
}
try {
XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(info));
StAXOMBuilder builder = new StAXOMBuilder(reader);
OMElement serviceElement = builder.getDocumentElement();
// get the details about the operations current name and the namespace before an update.
OMElement operationElement = serviceElement.getFirstChildWithName(new QName("operation"));
String operation;
if (operationElement != null) {
operation = operationElement.getText();
// and then remove the operation child,
operationElement.detach();
} else {
operation = "Add";
}
OMElement currentNameElement = serviceElement.getFirstChildWithName(new QName("currentName"));
String currentName;
if (currentNameElement != null) {
currentName = currentNameElement.getText();
currentNameElement.detach();
} else {
currentName = CommonUtil.getServiceName(serviceElement);
}
OMElement currentNamespaceElement = serviceElement.getFirstChildWithName(new QName("currentNamespace"));
String currentNamespace;
if (currentNamespaceElement != null) {
currentNamespace = currentNamespaceElement.getText();
currentNamespaceElement.detach();
} else {
currentNamespace = CommonUtil.getServiceNamespace(serviceElement);
}
ServiceManager serviceManager = new ServiceManager(registry);
Service service = serviceManager.newService(serviceElement);
String lifeCycleName = service.getAttribute("serviceLifecycle_lifecycleName");
String finalPath="";
if ("Edit".equals(operation)) {
// this is an edit operation, retrieve the old namespace and name
String currentPath = "";
if (serviceElement.getChildrenWithLocalName("newServicePath").hasNext()) {
Iterator OmElementIterator = serviceElement.getChildrenWithLocalName("newServicePath");
while (OmElementIterator.hasNext()) {
OMElement next = (OMElement) OmElementIterator.next();
currentPath = next.getText();
break;
}
}else{
currentPath = registry.getRegistryContext().getServicePath() +
CommonUtil.derivePathFragmentFromNamespace(currentNamespace) + currentName;
}
currentPath = RegistryUtils.getRelativePathToOriginal(currentPath,
RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH);
finalPath = new String(currentPath);
String version = service.getAttribute("overview_version");
if (version == null ) {
currentPath = CommonUtil.computeServicePathWithVersion(currentPath, "1.0.0-SNAPSHOT");
}else{
currentPath = CommonUtil.computeServicePathWithVersion(currentPath, version);
}
if (registry.resourceExists(currentPath)) {
GovernanceArtifact oldArtifact =
GovernanceUtils.retrieveGovernanceArtifactByPath(registry, currentPath);
if (!(oldArtifact instanceof Service)) {
String msg = "The updated path is occupied by a non-service. path: " +
currentPath + ".";
log.error(msg);
throw new Exception(msg);
}
// id is used to differentiate the service
String id = oldArtifact.getId();
service.setId(id);
serviceManager.updateService(service);
Resource serviceResource = registry.get(service.getPath());
String oldLifeCycleName = serviceResource.getProperty("registry.LC.name");
if (lifeCycleName == null) {
removeAspect(registry, service.getPath(), oldLifeCycleName);
}
if (lifeCycleName != null) {
if (oldLifeCycleName == null || !oldLifeCycleName.equals(lifeCycleName)) {
// if user select a different lifecycle for the service, first delete
// the previous one and then associate the new one.
removeAspect(registry, service.getPath(), oldLifeCycleName);
registry.associateAspect(service.getPath(), lifeCycleName);
}
}
return true;
}
}
serviceManager.addService(service);
if (lifeCycleName != null) {
registry.associateAspect(service.getPath(), lifeCycleName);
}
/*if (!"".equals(finalPath)) {
if(service.getPath().startsWith(RegistryConstants.PATH_SEPARATOR+ TRUNK)){
Association[] allAssociations = registry.getAllAssociations(finalPath);
for (Association allAssociation : allAssociations) {
if(!allAssociation.getSourcePath().startsWith(RegistryConstants.PATH_SEPARATOR+ TRUNK)
|| !allAssociation.getDestinationPath().startsWith(RegistryConstants.PATH_SEPARATOR+ TRUNK)){
registry.removeAssociation(allAssociation.getSourcePath(),allAssociation.getDestinationPath(),
allAssociation.getAssociationType());
}
}
}
else if(service.getPath().startsWith(RegistryConstants.PATH_SEPARATOR+"branches"+
RegistryConstants.PATH_SEPARATOR+"testing")){
Association[] allAssociations = registry.getAllAssociations(finalPath);
for (Association allAssociation : allAssociations) {
if(!allAssociation.getSourcePath().startsWith(RegistryConstants.PATH_SEPARATOR+"branches"+
RegistryConstants.PATH_SEPARATOR+"testing")
|| !allAssociation.getSourcePath().startsWith(RegistryConstants.PATH_SEPARATOR+"branches"+
RegistryConstants.PATH_SEPARATOR+"testing")){
registry.removeAssociation(allAssociation.getSourcePath(),allAssociation.getDestinationPath(),
allAssociation.getAssociationType());
}
}
}
else if(service.getPath().startsWith(RegistryConstants.PATH_SEPARATOR+"branches"+
RegistryConstants.PATH_SEPARATOR+"production")){
Association[] allAssociations = registry.getAllAssociations(finalPath);
for (Association allAssociation : allAssociations) {
if(!allAssociation.getSourcePath().startsWith(RegistryConstants.PATH_SEPARATOR+"branches"+
RegistryConstants.PATH_SEPARATOR+"production")
||!allAssociation.getSourcePath().startsWith(RegistryConstants.PATH_SEPARATOR+"branches"+
RegistryConstants.PATH_SEPARATOR+"production")){
registry.removeAssociation(allAssociation.getSourcePath(),allAssociation.getDestinationPath(),
allAssociation.getAssociationType());
}
}
}
}*/
} catch (Exception e) {
String msg = "Unable to add service. ";
if (e instanceof RegistryException) {
throw (RegistryException)e;
}else if (e instanceof OMException) {
msg += "Unexpected character found in input-field name.";
log.error(msg, e);
throw new RegistryException( msg, e );
}
throw new RegistryException( msg + (e.getCause() instanceof SQLException ? "" : e.getCause().getMessage()), e);
}
return true;
}
public String editService(String servicename)throws RegistryException{
Registry registry = getGovernanceRegistry();
// String path = registry.getRegistryContext().getServicePath() + servicename;
String path = servicename;
// resource path is created to make sure the version page doesn't give null values
if(!registry.resourceExists(new ResourcePath(path).getPath())){
return null; //Wrong service name is given or service is no longer in Registry in the given name
}
Resource resource = registry.get(path);
String serviceinfo = new String((byte[])resource.getContent());
return serviceinfo;
}
public String getServiceConfiguration()throws RegistryException{
try{
Registry registry = getConfigSystemRegistry();
return Util.getServiceConfig(registry);
}catch (Exception e){
return null;
}
}
public boolean saveServiceConfiguration(String update) throws RegistryException{
Registry registry = getConfigSystemRegistry();
if (RegistryUtils.isRegistryReadOnly(registry.getRegistryContext())) {
return false;
}
try{
Resource resource = registry.get(RegistryConstants.GOVERNANCE_SERVICES_CONFIG_PATH + "service");
resource.setContent(update);
registry.put(RegistryConstants.GOVERNANCE_SERVICES_CONFIG_PATH + "service",resource);
return true;
}catch(Exception RegistryException){
return false;
}
}
public String getServicePath()throws RegistryException{
try{
Registry registry = getGovernanceRegistry();
return registry.getRegistryContext().getServicePath();
}catch(Exception RegistryException){
return null;
}
}
/* this method is useful when adding the service edit button, do a check before displaying service Edit button */
public boolean canChange(String path)throws Exception{
UserRegistry registry = (UserRegistry)getGovernanceRegistry();
if(registry.getUserName() != null && registry.getUserRealm() != null){
return registry.getUserRealm().getAuthorizationManager().isUserAuthorized(registry.getUserName(),
path, ActionConstants.PUT);
}
return false;
}
/* get available aspects */
public String[] getAvailableAspects()throws Exception{
UserRegistry registry = (UserRegistry)getGovernanceRegistry();
Registry systemRegistry = getConfigSystemRegistry();
String[] aspectsToAdd = registry.getAvailableAspects();
if (aspectsToAdd == null) {
return new String[0];
}
List<String> lifecycleAspectsToAdd = new LinkedList<String>();
boolean isTransactionStarted = false;
String tempResourcePath = "/governance/lcm/" + UUIDGenerator.generateUUID();
for (String aspectToAdd : aspectsToAdd) {
if (systemRegistry.getRegistryContext().isReadOnly()) {
lifecycleAspectsToAdd.add(aspectToAdd);
continue;
}
Boolean isLifecycleAspect = lifecycleAspects.get(aspectToAdd);
if (isLifecycleAspect == null) {
if (!isTransactionStarted) {
registry.beginTransaction();
isTransactionStarted = true;
}
systemRegistry.put(tempResourcePath, systemRegistry.newResource());
systemRegistry.associateAspect(tempResourcePath, aspectToAdd);
Resource r = systemRegistry.get(tempResourcePath);
Properties props = r.getProperties();
Set keys = props.keySet();
for (Object key : keys) {
String propKey = (String) key;
if (propKey.startsWith("registry.lifecycle.")
|| propKey.startsWith("registry.custom_lifecycle.checklist.")) {
isLifecycleAspect = Boolean.TRUE;
break;
}
}
if (isLifecycleAspect == null) {
isLifecycleAspect = Boolean.FALSE;
}
lifecycleAspects.put(aspectToAdd, isLifecycleAspect);
}
if (isLifecycleAspect) {
lifecycleAspectsToAdd.add(aspectToAdd);
}
}
if (isTransactionStarted) {
systemRegistry.delete(tempResourcePath);
systemRegistry.rollbackTransaction();
}
return lifecycleAspectsToAdd.toArray(new String[lifecycleAspectsToAdd.size()]);
}
private void removeAspect(Registry registry,String path,String aspect)throws Exception{
try {
/* set all the variables to the resource */
Resource resource = registry.get(path);
Properties props = resource.getProperties();
//List<Property> propList = new ArrayList<Property>();
Iterator iKeys = props.keySet().iterator();
ArrayList<String> propertiesToRemove = new ArrayList<String>();
while (iKeys.hasNext()) {
String propKey = (String) iKeys.next();
if (propKey.startsWith("registry.custom_lifecycle.checklist.")
|| propKey.startsWith("registry.LC.name")
|| propKey.startsWith("registry.lifecycle.")
|| propKey.startsWith("registry.Aspects")) {
propertiesToRemove.add(propKey);
}
}
for(String propertyName : propertiesToRemove) {
resource.removeProperty(propertyName);
}
registry.put(path, resource);
} catch (RegistryException e) {
String msg = "Failed to remove aspect " + aspect +
" on resource " + path + ". " + e.getMessage();
log.error(msg, e);
throw new RegistryException(msg, e);
}
}
}