it.txt.ens.authorisationService.util.AccessRequestEvaluator.java Source code

Java tutorial

Introduction

Here is the source code for it.txt.ens.authorisationService.util.AccessRequestEvaluator.java

Source

/***************************************************************************
 * Copyright 2012-2013 TXT e-solutions SpA
 * 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.
 * 
 * This work was performed within the IoT_at_Work Project
 * and partially funded by the European Commission's
 * 7th Framework Programme under the research area ICT-2009.1.3
 * Internet of Things and enterprise environments.
 *
 * Authors:
 *      Salvatore Piccione (TXT e-solutions SpA)
 *
 * Contributors:
 *        Domenico Rotondi (TXT e-solutions SpA)
 **************************************************************************/
package it.txt.ens.authorisationService.util;

import it.txt.access.capability.commons.schema.validation.CapabilitySchemaValidationHandlerException;
import it.txt.access.capability.commons.signer.X509DocumentSigner;
import it.txt.access.capability.commons.signer.model.X509CertificateKeyValues;
import it.txt.access.capability.commons.signer.model.X509CertificateSubjectInfo;
import it.txt.access.capability.commons.utils.XMLPrinter;
import it.txt.access.capability.factory.CapabilitySchemaFactory;
import it.txt.access.capability.factory.CapabilitySchemaFactoryException;
import it.txt.access.capability.pdp.client.PDPClient;
import it.txt.access.capability.schema.AccessRightType;
import it.txt.access.capability.schema.AccessRightsCapabilityType;
import it.txt.access.capability.verifier.CapabilityVerifier;
import it.txt.access.capability.verifier.CapabilityVerifierException;
import it.txt.access.capability.verifier.VerifiedCapability;
import it.txt.ens.authorisationService.amqp.AMQPConnectionHelper;
import it.txt.ens.authorisationService.amqp.AMQPExchangeHelper;
import it.txt.ens.authorisationService.amqp.AMQPQueueHelper;
import it.txt.ens.authorisationService.amqp.ManagedBroker;
import it.txt.ens.authorisationService.amqp.ManagedNamespace;
import it.txt.ens.authorisationService.amqp.ManagedVirtualHost;
import it.txt.ens.authorisationService.gui.standalone.util.SimplePasswordGenerator;
import it.txt.ens.core.ENSResource;
import it.txt.ens.core.KeystoreParameters;
import it.txt.ens.core.X509CertificateRetrievalParameters;
import it.txt.ens.core.factory.ENSResourceFactory;
import it.txt.ens.core.factory.URIParseException;
import it.txt.ens.namespace.NamespaceInquirer;
import it.txt.ens.namespace.exception.NamespaceInquirerException;
import it.txt.ens.namespace.exception.SyntaxPatternException;
import it.txt.ens.schema.RequestType;
import it.txt.ens.schema.ResponseType;
import it.txt.ens.schema.factory.ENSRequestFactoryException;
import it.txt.ens.schema.factory.ENSResponseFactoryException;
import it.txt.ens.schema.factory.model.FailureResponseDetails;
import it.txt.ens.schema.factory.model.SuccessResponseDetails;
import it.txt.ens.schema.request.factory.ENSAuthorisationRequestFactory;
import it.txt.ens.schema.response.factory.ENSAuthorisationResponseFactory;
import it.txt.rabbitmq.management.rest.factory.PermissionServiceFactory;
import it.txt.rabbitmq.management.rest.factory.UserServiceFactory;
import it.txt.rabbitmq.management.rest.resources.Permission;
import it.txt.rabbitmq.management.rest.resources.User;
import it.txt.rabbitmq.management.rest.services.PermissionService;
import it.txt.rabbitmq.management.rest.services.UserService;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.crypto.MarshalException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;

import oasis.names.tc.saml._2_0.assertion.ActionType;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.ShutdownListener;
import com.rabbitmq.client.ShutdownSignalException;
//import it.txt.ens.authorisationService.gui.standalone.util.ApplicationPropertiesRepository;

/**
 * This class evaluates an access request and send back to the service requester
 * a message with the processing outcome.
 * 
 * @author Carbone Matteo
 * @author Salvatore Piccione (TXT e-solutions SpA - salvatore.piccione AT network.txtgroup.com)
 */
class AccessRequestEvaluator implements Runnable, ShutdownListener {

    //    private static final String PERMISSION_SEPARATOR = "|";
    private static final String CHARSET = "UTF-8";
    private static final long SESSION_DURATION = 1000 * 60 * 60 * 24 * 30;

    public static final String OPERATIVE_QUEUE_NAME_FORMAT = "ENS-queue-%1$s-%2$tQ";
    public static final String RABBITMQ_USERNAME_FORMAT = "ENS-%1$s-%2$tQ";
    public static ConcurrentMap<String, ManagedNamespace> namespaces;
    public static ConcurrentMap<String, ManagedVirtualHost> virtualHosts;
    public static ConcurrentMap<String, ManagedBroker> brokers;
    public static final String TRANSFORMER_FACTORY_CLASS_NAME = "javax.xml.transform.TransformerFactory";
    public static final String DEFAULT_FACTORY_CLASS_NAME = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";

    private ENSAuthorisationResponseFactory ensResponseFactory;
    private ENSAuthorisationRequestFactory ensRequestFactory;
    private PDPClient pdpClient;
    private NamespaceInquirer namespaceInquirer;
    private UserServiceFactory rabbitMQUserSF;
    private PermissionServiceFactory rabbitMQPermissionSF;
    private ENSResourceFactory ensResourceFactory;

    private SimplePasswordGenerator pwdGen;
    //private FailureResponseDetails failureDetails;
    //private SuccessResponseDetails successDetails;
    private ResponseType responseType = null;
    private RequestType requestType = null;
    private String namespace;
    private String routingKey;
    private String operation;
    //private X509CertificateSubjectInfo x509CertificateSubjectInfo;
    //   private String requestMsg;
    //   private String keystorePwd;
    //   private String keystorePath;
    //   private String privateKeyPwd;
    //   private String keystoreAlias;
    private KeystoreParameters keystoreParams;
    private X509CertificateRetrievalParameters certParams;
    private final byte[] accessRequest;
    private Connection connection;
    private BasicProperties requestProperties;
    private AccessRightsCapabilityType capability;
    private String operativeHost;
    private int operativePort;
    private volatile boolean isClosed;
    private String subjectID;

    private static final String INTERNAL_ERROR = "INTERNAL_ERROR";
    //private static final String EXCHANGE_SUFFIX = "_exchange";

    private final static Logger LOGGER = Logger.getLogger(AccessRequestEvaluator.class.getName());
    private static final ResourceBundle MESSAGES = ResourceBundle
            .getBundle("message-bundles/" + AccessRequestEvaluator.class.getSimpleName(), Locale.ROOT);

    public static final String OPERATION_SUBSCRIBE = "subscribe";
    public static final String OPERATION_PUBLISH = "publish";

    //thread introduced to not use the one provided by RabbitMQ
    //    private static final ExecutorService THREAD_POOL = Executors.newSingleThreadExecutor();

    public AccessRequestEvaluator(ENSAuthorisationResponseFactory ensResponseFactory,
            ENSAuthorisationRequestFactory ensRequestFactory, KeystoreParameters keystoreParams,
            X509CertificateRetrievalParameters certParams, ENSResourceFactory ensResourceFactory,
            PDPClient pdpClient, NamespaceInquirer namespaceInquirer, UserServiceFactory rabbitMQUserService,
            PermissionServiceFactory rabbitMQPermissionService,
            //            ConcurrentMap<String,ManagedNamespace> namespaceMap,
            //            ConcurrentMap<String,ManagedVirtualHost> virtualHostMap,
            //            ConcurrentMap<String,ManagedBroker> brokerMap,
            byte[] accessRequest, Connection connection, BasicProperties properties) {
        this.ensRequestFactory = ensRequestFactory;
        this.ensResponseFactory = ensResponseFactory;
        this.keystoreParams = keystoreParams;
        this.certParams = certParams;
        this.pdpClient = pdpClient;
        this.namespaceInquirer = namespaceInquirer;
        this.rabbitMQUserSF = rabbitMQUserService;
        this.rabbitMQPermissionSF = rabbitMQPermissionService;
        this.pwdGen = new SimplePasswordGenerator(10);
        this.certParams = certParams;
        //        this.namespaces = namespaceMap;
        //        this.virtualHosts = virtualHostMap;
        //        this.brokers = brokerMap;
        this.accessRequest = accessRequest;
        this.connection = connection;
        this.requestProperties = properties;
        this.ensResourceFactory = ensResourceFactory;
        this.isClosed = true;
    }

    /* (non-Javadoc)
      * @see java.lang.Runnable#run()
      */
    @Override
    public void run() {
        Channel channel = null;
        String correlationId = requestProperties.getCorrelationId();
        String replyTo = requestProperties.getReplyTo();
        try {
            byte[] response = evaluate();
            channel = connection.createChannel();
            isClosed = false;
            channel.addShutdownListener(this);
            if (correlationId != null && replyTo != null) {
                AMQP.BasicProperties replyProperties = new AMQP.BasicProperties.Builder()
                        .correlationId(correlationId).build();
                channel.basicPublish("", replyTo, replyProperties, response);
                if (LOGGER.isLoggable(Level.FINER))
                    LOGGER.log(Level.FINER, MESSAGES.getString("responsePublished"));
            } else {
                LOGGER.severe(MESSAGES.getString("missingCorrelationIDAndReplyTo"));
            }
            //            channel.basicAck(envelope.getDeliveryTag(), false);
        } catch (IOException e) {
            LOGGER.log(Level.SEVERE,
                    MessageFormat.format(MESSAGES.getString("responsePublishFailure"), correlationId, replyTo), e);
        } finally {
            if (channel != null)
                try {
                    isClosed = true;
                    channel.close();
                } catch (IOException e) {
                } catch (ShutdownSignalException e) {
                }
        }
    }

    public String evaluateToString() throws IOException {
        try {
            return new String(evaluate(), CHARSET);
        } catch (UnsupportedEncodingException e) {
            LOGGER.log(Level.SEVERE, MessageFormat.format(MESSAGES.getString("byteEncodingFailure"), CHARSET), e);
            return INTERNAL_ERROR;
        }
    }

    public byte[] evaluate() throws IOException {
        if (LOGGER.isLoggable(Level.FINEST))
            LOGGER.log(Level.FINEST, MESSAGES.getString("startingAccessRequestEvaluation"));

        Document responseDoc = null;

        try {
            requestType = ensRequestFactory.parseInputStream(new ByteArrayInputStream(accessRequest));
            //pretty print of the request
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.log(Level.FINE, MessageFormat.format(MESSAGES.getString("receivedAccessRequestDetail"),
                        XMLPrinter.printDocumentNode(ensRequestFactory.marshal(requestType), true)));
            operation = requestType.getOperation();
            String resourceID = requestType.getResourceID();
            subjectID = requestType.getSubject().getSubjectID();
            ENSResource ensResource;
            try {
                ensResource = ensResourceFactory.create(new URI(resourceID));
                namespace = ensResource.getNamespace();
                routingKey = ensResource.getPattern();
                if (LOGGER.isLoggable(Level.INFO))
                    LOGGER.info(MessageFormat.format(MESSAGES.getString("receivedAccessRequest"), subjectID,
                            operation, namespace, routingKey));

                capability = requestType.getAccessRightsCapability().getCapability();
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.fine(MESSAGES.getString("evaluationStep1"));

                if (subjectID.equalsIgnoreCase(capability.getSubject().getSubjectID().getValue())) {
                    if (LOGGER.isLoggable(Level.FINE))
                        LOGGER.fine(MESSAGES.getString("evaluationStep2"));
                    if (operation.equalsIgnoreCase(OPERATION_PUBLISH)
                            || operation.equalsIgnoreCase(OPERATION_SUBSCRIBE)) {
                        if (LOGGER.isLoggable(Level.FINE))
                            LOGGER.fine(MESSAGES.getString("evaluationStep3"));
                        List<AccessRightType> accessRights = capability.getAccessRights().getAccessRight();
                        if (isOperationAmongGrantedRights(accessRights, operation)) {
                            // Verify the capability through the CapabilityVerifier
                            if (executeCapabilityVerifierCheck()) {
                                if (executePDPCapabilityCheck()) {
                                    if (executeNamespaceCapabilityCheck()) {
                                        executeRabbitMQOperations();
                                    }
                                }
                            }
                        } else {
                            FailureResponseDetails failureDetails = new FailureResponseDetails();
                            String reason = MESSAGES.getString(ErrorCodes.REQUESTED_OPERATION_IS_NOT_GRANTED_RIGHT);
                            failureDetails.setErrorReason(reason);
                            failureDetails.setErrorCode(ErrorCodes.REQUESTED_OPERATION_IS_NOT_GRANTED_RIGHT);
                            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                                    requestType.getTimeStamp(), failureDetails);
                            if (LOGGER.isLoggable(Level.INFO))
                                LOGGER.info(MessageFormat.format(MESSAGES.getString("evaluationStep3Failure"),
                                        ErrorCodes.REQUESTED_OPERATION_IS_NOT_GRANTED_RIGHT, reason, operation,
                                        printAccessRightsList(accessRights)));
                        }
                    } else {
                        FailureResponseDetails failureDetails = new FailureResponseDetails();
                        String reason = MESSAGES.getString(ErrorCodes.ENS_OPERATION_NOT_MANAGED);
                        failureDetails.setErrorReason(reason);
                        failureDetails.setErrorCode(ErrorCodes.ENS_OPERATION_NOT_MANAGED);
                        responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                                requestType.getTimeStamp(), failureDetails);
                        if (LOGGER.isLoggable(Level.INFO))
                            LOGGER.info(MessageFormat.format(MESSAGES.getString("evaluationStep2Failure"),
                                    ErrorCodes.ENS_OPERATION_NOT_MANAGED, reason, operation));
                    }
                } else {
                    FailureResponseDetails failureDetails = new FailureResponseDetails();
                    String reason = MESSAGES.getString(ErrorCodes.REQUESTOR_NOT_EQUAL_TO_CAPABILITY_SUBJECT);
                    failureDetails.setErrorReason(reason);
                    failureDetails.setErrorCode(ErrorCodes.REQUESTOR_NOT_EQUAL_TO_CAPABILITY_SUBJECT);
                    responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                            requestType.getTimeStamp(), failureDetails);
                    if (LOGGER.isLoggable(Level.INFO))
                        LOGGER.info(MessageFormat.format("evaluationStep1Failure",
                                ErrorCodes.REQUESTOR_NOT_EQUAL_TO_CAPABILITY_SUBJECT, reason));
                }
            } catch (URIParseException e) {
                FailureResponseDetails failureDetails = new FailureResponseDetails();
                String reason = MESSAGES.getString(ErrorCodes.CAPABILITY_RESOURCE_ID_PARSING_FAILURE);
                failureDetails.setErrorReason(reason);
                failureDetails.setErrorCode(ErrorCodes.CAPABILITY_RESOURCE_ID_PARSING_FAILURE);
                responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                        requestType.getTimeStamp(), failureDetails);
                LOGGER.log(Level.SEVERE, MessageFormat.format(MESSAGES.getString("genericError"),
                        ErrorCodes.CAPABILITY_RESOURCE_ID_PARSING_FAILURE, reason), e);
            } catch (URISyntaxException e) {
                FailureResponseDetails failureDetails = new FailureResponseDetails();
                String reason = MESSAGES.getString(ErrorCodes.CAPABILITY_RESOURCE_ID_PARSING_FAILURE);
                failureDetails.setErrorReason(reason);
                failureDetails.setErrorCode(ErrorCodes.CAPABILITY_RESOURCE_ID_PARSING_FAILURE);
                responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                        requestType.getTimeStamp(), failureDetails);
                LOGGER.log(Level.SEVERE, MessageFormat.format(MESSAGES.getString("genericError"),
                        ErrorCodes.CAPABILITY_RESOURCE_ID_PARSING_FAILURE, reason), e);
            }

            if (responseType != null) {
                if (responseType.isResult()) {
                    LOGGER.info(MessageFormat.format(MESSAGES.getString("evaluationOK"), subjectID, operation,
                            namespace, routingKey));
                }
            }

            X509CertificateKeyValues keyValues = X509DocumentSigner.getCertificateKeyValues(
                    keystoreParams.getKeystorePath().getAbsolutePath(), keystoreParams.getKeystorePassword(),
                    //indeed this is the alias not the certificate subject
                    certParams.getX509CertificateSubject(), certParams.getPrivateKeyPassword());
            responseDoc = ensResponseFactory.marshal(responseType);
            X509DocumentSigner.signXMLElement(responseDoc.getDocumentElement(), keyValues,
                    ENSAuthorisationResponseFactory.SIGN_DOCUMENT_AFTER_NODE);

            //pretty print of the response
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.log(Level.FINE, MessageFormat.format(MESSAGES.getString("accessResponse"),
                        XMLPrinter.printDocumentNode(responseDoc, true)));

            ByteArrayOutputStream xmlos = (ByteArrayOutputStream) XMLPrinter
                    .convertDOMIntoByteStream(responseDoc, false, null, new ByteArrayOutputStream())
                    .getOutputStream();
            new ByteArrayOutputStream();
            return xmlos.toByteArray();
        } catch (GeneralSecurityException e) {
            LOGGER.log(Level.SEVERE, "Internal error:", e);
        } catch (TransformerException e) {
            LOGGER.log(Level.SEVERE, "Internal error:", e);
        } catch (TransformerFactoryConfigurationError e) {
            LOGGER.log(Level.SEVERE, "Internal error:", e);
        } catch (ENSResponseFactoryException e) {
            LOGGER.log(Level.SEVERE, "Internal error:", e);
        } catch (ENSRequestFactoryException e) {
            LOGGER.log(Level.SEVERE, "Internal error:", e);
        }
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.log(Level.FINE, MessageFormat.format(MESSAGES.getString("accessResponse"), INTERNAL_ERROR));
        return INTERNAL_ERROR.getBytes(CHARSET);
    }

    /**
     * @param accessRights
     * @return
     */
    private String printAccessRightsList(List<AccessRightType> accessRights) {
        StringBuilder builder = new StringBuilder();
        ActionType operation;
        String namespace;
        for (AccessRightType accessRight : accessRights) {
            operation = accessRight.getPermittedAction();
            if (builder.length() > 0)
                builder.append(", ");
            namespace = operation.getNamespace();
            if (namespace != null) {
                builder.append(namespace);
                builder.append(":");
            }
            builder.append(operation.getValue());
        }
        return builder.toString();
    }

    private boolean isOperationAmongGrantedRights(List<AccessRightType> rights, String operation) {
        //At the moment we don't care about conditions
        boolean found = false;
        int i = 0;
        while (!found && i < rights.size()) {
            if (operation.equalsIgnoreCase(rights.get(i).getPermittedAction().getValue()))
                found = true;
            else
                i++;
        }
        return found;
    }

    /**
     * @throws ENSResponseFactoryException 
     * @throws ENSServiceFactoryException 
     * 
     */
    private void executeRabbitMQOperations() throws ENSResponseFactoryException {
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(MessageFormat.format(MESSAGES.getString("evaluationStep8"), namespace));

        ManagedNamespace mNamespace = namespaces.get(namespace);
        if (mNamespace == null) {
            FailureResponseDetails failureDetails = new FailureResponseDetails();
            String reason = MESSAGES.getString(ErrorCodes.NAMESPACE_NOT_MANAGED);
            failureDetails.setErrorReason(reason);
            failureDetails.setErrorCode(ErrorCodes.NAMESPACE_NOT_MANAGED);
            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                    requestType.getTimeStamp(), failureDetails);
            if (LOGGER.isLoggable(Level.INFO))
                LOGGER.info(MessageFormat.format(MESSAGES.getString("evaluationStep8Failure"),
                        ErrorCodes.NAMESPACE_NOT_MANAGED, reason, namespace));
            return;
        }
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(MessageFormat.format(MESSAGES.getString("evaluationStep8OK1"),
                    mNamespace.getNamespaceAMQPExchangeName()));

        ManagedVirtualHost virtualHost = virtualHosts.get(mNamespace.getVirtualHostName());
        if (virtualHost == null) {
            FailureResponseDetails failureDetails = new FailureResponseDetails();
            String reason = MESSAGES.getString(ErrorCodes.VIRTUAL_HOST_NOT_MANAGED);
            failureDetails.setErrorReason(reason);
            failureDetails.setErrorCode(ErrorCodes.VIRTUAL_HOST_NOT_MANAGED);
            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                    requestType.getTimeStamp(), failureDetails);
            if (LOGGER.isLoggable(Level.INFO))
                LOGGER.info(MessageFormat.format(MESSAGES.getString("evaluationStep8Failure"),
                        ErrorCodes.VIRTUAL_HOST_NOT_MANAGED, reason, mNamespace.getVirtualHostName()));
            return;
        }
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(MessageFormat.format(MESSAGES.getString("evaluationStep8OK2"), virtualHost));

        ManagedBroker broker = brokers.get(virtualHost.getHostingBrokerName());
        if (broker == null) {
            FailureResponseDetails failureDetails = new FailureResponseDetails();
            String reason = MESSAGES.getString(ErrorCodes.BROKER_NOT_MANAGED);
            failureDetails.setErrorReason(reason);
            failureDetails.setErrorCode(ErrorCodes.BROKER_NOT_MANAGED);
            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                    requestType.getTimeStamp(), failureDetails);
            if (LOGGER.isLoggable(Level.INFO))
                LOGGER.info(MessageFormat.format(MESSAGES.getString("evaluationStep8Failure"),
                        ErrorCodes.BROKER_NOT_MANAGED, reason, virtualHost.getHostingBrokerName()));
            return;
        }
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(MessageFormat.format(MESSAGES.getString("evaluationStep8OK3"), broker));
        String operativeVhost = virtualHost.getVirtualHostName();

        //ensUsername subject + timestamp
        Date requestTimestamp = requestType.getTimeStamp().toGregorianCalendar().getTime();
        String ensUsername = String.format(RABBITMQ_USERNAME_FORMAT, subjectID, requestTimestamp);
        String ensPwd = pwdGen.getNextPassword();
        operativeHost = broker.getIpAddress();
        operativePort = broker.getTcpPortNumber();
        int httpPort = broker.getHttpPortNumber();
        String adminUsername = virtualHost.getBrokerUsername();
        String adminPwd = virtualHost.getBrokerPassword();

        UserService userService = rabbitMQUserSF.create(operativeHost, httpPort, adminUsername, adminPwd);

        //create user account
        List<String> listTags = new ArrayList<String>();
        listTags.add("ensUser");
        User ensUser;
        try {
            ensUser = new User(ensUsername, ensPwd, listTags, false);

            PermissionService permissionService = rabbitMQPermissionSF.create(operativeHost, httpPort,
                    adminUsername, adminPwd);
            //merge the permissions
            boolean userAlreadyExists = userService.getUser(ensUsername) != null;
            Permission permissions;
            String destinationName;
            if (requestType.getOperation().equalsIgnoreCase(OPERATION_PUBLISH)) {
                destinationName = mNamespace.getNamespaceAMQPExchangeName();
                permissions = this.createPublishingPermissionsAndResources(userAlreadyExists, operativeHost,
                        httpPort, operativePort, operativeVhost, ensUsername, ensPwd, adminUsername, adminPwd,
                        permissionService, destinationName);
            } else {
                String exchangeName = mNamespace.getNamespaceAMQPExchangeName();
                destinationName = String.format(OPERATIVE_QUEUE_NAME_FORMAT, ensUsername, requestTimestamp);
                permissions = createSubscribingPermissionsAndResources(userAlreadyExists, operativeHost, httpPort,
                        operativePort, operativeVhost, ensUsername, ensPwd, adminUsername, adminPwd,
                        permissionService, destinationName, exchangeName);
            }
            if (userAlreadyExists) {
                //delete the user
                //userService.deleteUser(ensUsername);
                LOGGER.warning(MessageFormat.format(MESSAGES.getString("alreadyExistingCredentials"), ensUsername));
            }
            //create the user if everything is OK (i.e. the permission are not null)
            if (permissions != null) {
                userService.putUser(ensUser);
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.fine(MessageFormat.format("createdCredentials", ensUser.toString()));
                permissionService.putPermission(permissions);

                SuccessResponseDetails details = new SuccessResponseDetails();
                details.setSubjectID(ensUsername);
                details.setAccessToken(ensPwd);
                details.setVirtualHost(operativeVhost);
                details.setBrokerHost(operativeHost);
                details.setBrokerPort(operativePort);
                details.setQueueName(destinationName);
                //This might be a possible concurrency bottleneck 
                details.setSesionToken(UUID.randomUUID().toString());
                Date sessionTimeline = new Date();
                sessionTimeline.setTime(new Date().getTime() + SESSION_DURATION);
                Calendar calendar = new GregorianCalendar();
                calendar.setTime(sessionTimeline);
                details.setSessionExpiration(calendar.getTime());
                details.setUseTLS(true);

                responseType = ensResponseFactory.createSuccessResponse(requestType.getRequestID(),
                        requestType.getTimeStamp(), details);
            }
        } catch (Exception e) {
            FailureResponseDetails failureDetails = new FailureResponseDetails();
            String reason = MESSAGES.getString(ErrorCodes.ENS_RESOURCE_RESERVATION_FAILURE);
            failureDetails.setErrorReason(reason);
            failureDetails.setErrorCode(ErrorCodes.ENS_RESOURCE_RESERVATION_FAILURE);
            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                    requestType.getTimeStamp(), failureDetails);
            if (LOGGER.isLoggable(Level.INFO))
                LOGGER.log(Level.INFO, MessageFormat.format(MESSAGES.getString("evaluationStep9Failure"),
                        ErrorCodes.ENS_RESOURCE_RESERVATION_FAILURE, reason, e.getMessage()), e);
            return;
        }
    }

    //   private class NamespaceInquirerThread implements Runnable {
    //       private boolean res;
    //       private NamespaceInquirer namespaceInquirer;
    //       private ResponseType responseType;
    //       private String namespace;
    //       private String routingKey;
    //       private ENSResponseFactoryException e;
    //       
    //        /**
    //         * @param res
    //         * @param namespaceInquirer
    //         * @param responseType
    //         * @param namespace
    //         * @param routingKey
    //         * @param e
    //         */
    //        public NamespaceInquirerThread(
    //                NamespaceInquirer namespaceInquirer,
    //                String namespace, String routingKey) {
    //            this.namespaceInquirer = namespaceInquirer;
    //            this.namespace = namespace;
    //            this.routingKey = routingKey;
    //        }
    //
    //        /* (non-Javadoc)
    //         * @see java.lang.Runnable#run()
    //         */
    //        @Override
    //        public void run() {
    //            boolean res = false;
    //            
    //            if (LOGGER.isLoggable(Level.FINE))
    //                LOGGER.fine(MessageFormat.format(
    //                        MESSAGES.getString("evaluationStep6"),namespace,routingKey));
    //            
    //            //boolean validNamespace = false;
    //            try {
    //                if(res = namespaceInquirer.patternExist(routingKey, namespace)){
    //                    if (LOGGER.isLoggable(Level.FINE))
    //                        LOGGER.fine(MessageFormat.format(
    //                                MESSAGES.getString("evaluationStep6OK"), namespace, routingKey));
    //                }else{
    //                    FailureResponseDetails failureDetails = new FailureResponseDetails();
    //                    String reason = MESSAGES.getString(ErrorCodes.NAMESPACE_EXISTENCE_NOT_EXIST);
    //                    failureDetails.setErrorReason(reason);
    //                    failureDetails.setErrorCode(ErrorCodes.NAMESPACE_EXISTENCE_NOT_EXIST);
    //                    responseType = ensResponseFactory.createFailureResponse(
    //                            requestType.getRequestID(), requestType.getTimeStamp(), failureDetails);
    //                    if (LOGGER.isLoggable(Level.INFO))
    //                        LOGGER.info(MessageFormat.format(MESSAGES.getString("evaluationStep6Failure"),
    //                                ErrorCodes.NAMESPACE_EXISTENCE_NOT_EXIST,reason));
    //                }
    //            } catch (SyntaxPatternException e) {
    //                FailureResponseDetails failureDetails = new FailureResponseDetails();
    //                String reason = MESSAGES.getString(ErrorCodes.INVALID_NAMESPACE_PATTERN_SYNTAX);
    //                failureDetails.setErrorReason(reason);
    //                failureDetails.setErrorCode(ErrorCodes.INVALID_NAMESPACE_PATTERN_SYNTAX);
    //                try {
    //                    responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(), requestType.getTimeStamp(), failureDetails);
    //                } catch (ENSResponseFactoryException e1) {
    //                    this.e = e1;
    //                }
    //                if (LOGGER.isLoggable(Level.INFO))
    //                    LOGGER.log(Level.INFO, MessageFormat.format(MESSAGES.getString("evaluationStep6Failure"),
    //                            ErrorCodes.INVALID_NAMESPACE_PATTERN_SYNTAX,reason),e);
    //            } catch (NamespaceInquirerException e) {
    //                FailureResponseDetails failureDetails = new FailureResponseDetails();
    //                String reason = MESSAGES.getString(ErrorCodes.NAMESPACE_EXISTENCE_INTERNAL_ERROR);
    //                failureDetails.setErrorReason(reason);
    //                failureDetails.setErrorCode(ErrorCodes.NAMESPACE_EXISTENCE_INTERNAL_ERROR);
    //                try {
    //                    responseType = ensResponseFactory.createFailureResponse(
    //                            requestType.getRequestID(), requestType.getTimeStamp(), failureDetails);
    //                } catch (ENSResponseFactoryException e1) {
    //                    this.e = e1;
    //                }
    //                if (LOGGER.isLoggable(Level.INFO))
    //                    LOGGER.log(Level.INFO, MessageFormat.format(MESSAGES.getString("evaluationStep6Failure"),
    //                            ErrorCodes.NAMESPACE_EXISTENCE_INTERNAL_ERROR,reason),e);
    //            } catch (ENSResponseFactoryException e) {
    //                this.e = e;
    //            }
    //            
    //            //certificate control
    //            if(res){
    //                try {
    //                    if (LOGGER.isLoggable(Level.FINE))
    //                        LOGGER.fine(MESSAGES.getString("evaluationStep7"));
    //                    
    //                    Element rootAuCapDoc = getRootAuCapDoc();
    //                    X509CertificateSubjectInfo x509CertificateSubjectInfo = 
    //                            X509DocumentSigner.getX509CertificateSubjectInfo(rootAuCapDoc);
    //                    String rootSubjectId = x509CertificateSubjectInfo.getX509IssuerName();
    //                    String rootSerial = x509CertificateSubjectInfo.getX509SerialNumber().toString();
    //                    
    //                    if(res = namespaceInquirer.isTrustedCertificate(rootSubjectId,rootSerial, namespace)){
    //                        if (LOGGER.isLoggable(Level.FINE))
    //                            LOGGER.fine(MessageFormat.format(MESSAGES.getString("evaluationStep7OK"),
    //                                    rootSubjectId));
    //                    }else{
    //                        FailureResponseDetails failureDetails = new FailureResponseDetails();
    //                        String reason = MESSAGES.getString(ErrorCodes.CERTIFICATE_VERIFIER_NOT_VALID);
    //                        failureDetails.setErrorReason(reason);
    //                        failureDetails.setErrorCode(ErrorCodes.CERTIFICATE_VERIFIER_NOT_VALID);
    //                        responseType = ensResponseFactory.createFailureResponse(
    //                                requestType.getRequestID(), requestType.getTimeStamp(), failureDetails);
    //                        if (LOGGER.isLoggable(Level.INFO))
    //                            LOGGER.info(MessageFormat.format(MESSAGES.getString("evaluationStep7Failure"),
    //                                    ErrorCodes.CERTIFICATE_VERIFIER_NOT_VALID,reason));
    //                    }
    //                } catch (NamespaceInquirerException e) {
    //                    FailureResponseDetails failureDetails = new FailureResponseDetails();
    //                    String reason = MESSAGES.getString(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
    //                    failureDetails.setErrorCode(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
    //                    try {
    //                        responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(), 
    //                                requestType.getTimeStamp(), failureDetails);
    //                    } catch (ENSResponseFactoryException e1) {
    //                        this.e = e1;
    //                    }
    //                    if (LOGGER.isLoggable(Level.INFO))
    //                        LOGGER.log(Level.INFO,MessageFormat.format(MESSAGES.getString("evaluationStep7Failure"),
    //                                ErrorCodes.CERTIFICATE_VERIFIER_NOT_VALID,reason),e);
    //                } catch (GeneralSecurityException e) {
    //                    FailureResponseDetails failureDetails = new FailureResponseDetails();
    //                    String reason = MESSAGES.getString(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
    //                    failureDetails.setErrorCode(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
    //                    try {
    //                        responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
    //                                requestType.getTimeStamp(), failureDetails);
    //                    } catch (ENSResponseFactoryException e1) {
    //                        this.e = e1;
    //                    }
    //                    if (LOGGER.isLoggable(Level.INFO))
    //                        LOGGER.log(Level.INFO,MessageFormat.format(MESSAGES.getString("evaluationStep7Failure"),
    //                                ErrorCodes.CERTIFICATE_VERIFIER_NOT_VALID,reason),e);
    //                } catch (MarshalException e) {
    //                    FailureResponseDetails failureDetails = new FailureResponseDetails();
    //                    String reason = MESSAGES.getString(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
    //                    failureDetails.setErrorCode(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
    //                    try {
    //                        responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
    //                                requestType.getTimeStamp(), failureDetails);
    //                    } catch (ENSResponseFactoryException e1) {
    //                        this.e = e1;
    //                    }
    //                    if (LOGGER.isLoggable(Level.INFO))
    //                        LOGGER.log(Level.INFO,MessageFormat.format(MESSAGES.getString("evaluationStep7Failure"),
    //                                ErrorCodes.CERTIFICATE_VERIFIER_NOT_VALID,reason),e);
    //                } catch (CapabilitySchemaFactoryException e) {
    //                    FailureResponseDetails failureDetails = new FailureResponseDetails();
    //                    String reason = MESSAGES.getString(ErrorCodes.INTERNAL_ERROR);
    //                    failureDetails.setErrorCode(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
    //                    try {
    //                        responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
    //                                requestType.getTimeStamp(), failureDetails);
    //                    } catch (ENSResponseFactoryException e1) {
    //                        this.e = e1;
    //                    }
    //                    if (LOGGER.isLoggable(Level.INFO))
    //                        LOGGER.log(Level.INFO,MessageFormat.format(MESSAGES.getString("evaluationStep7FailureDetails"),
    //                                ErrorCodes.INTERNAL_ERROR,reason, MESSAGES.getString("rootCapabilityMarshallingFailure")),e);
    //                } catch (CapabilitySchemaValidationHandlerException e) {
    //                    FailureResponseDetails failureDetails = new FailureResponseDetails();
    //                    String reason = MESSAGES.getString(ErrorCodes.INTERNAL_ERROR);
    //                    failureDetails.setErrorCode(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
    //                    try {
    //                        responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
    //                                requestType.getTimeStamp(), failureDetails);
    //                    } catch (ENSResponseFactoryException e1) {
    //                        this.e = e1;
    //                    }
    //                    if (LOGGER.isLoggable(Level.INFO))
    //                        LOGGER.log(Level.INFO,MessageFormat.format(MESSAGES.getString("evaluationStep7FailureDetails"),
    //                                ErrorCodes.INTERNAL_ERROR,reason, MESSAGES.getString("rootCapabilityMarshallingFailure")),e);
    //                } catch (ENSResponseFactoryException e) {
    //                    this.e = e;
    //                }
    //            }
    //        }
    //
    //        /**
    //         * @return the res
    //         */
    //        public boolean isRes() {
    //            return res;
    //        }
    //
    //        /**
    //         * @return the responseType
    //         */
    //        public ResponseType getResponseType() {
    //            return responseType;
    //        }
    //
    //        /**
    //         * @return the e
    //         */
    //        public ENSResponseFactoryException getE() {
    //            return e;
    //        }
    //       
    //   }

    private boolean executeNamespaceCapabilityCheck() throws ENSResponseFactoryException {
        //       NamespaceInquirerThread t = new NamespaceInquirerThread(
        //               namespaceInquirer, namespace, routingKey);
        //       Future<?> f = THREAD_POOL.submit(t);
        //       try {
        //            f.get();
        //        } catch (Throwable e) {
        //            FailureResponseDetails failureDetails = new FailureResponseDetails();
        //            String reason = "Thread";
        //            failureDetails.setErrorCode(ErrorCodes.INTERNAL_ERROR);
        //            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
        //                    requestType.getTimeStamp(), failureDetails);
        //            if (LOGGER.isLoggable(Level.INFO))
        //                LOGGER.log(Level.INFO,reason, e);
        //            return false;
        //        }
        //       if (t.getE() != null)
        //           throw t.getE();
        //       responseType = t.getResponseType();
        //       return t.isRes();

        boolean res = false;

        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(MessageFormat.format(MESSAGES.getString("evaluationStep6"), namespace, routingKey));

        //boolean validNamespace = false;

        try {
            if (namespaceInquirer == null) {
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.fine(
                            MessageFormat.format(MESSAGES.getString("evaluationStep6OK"), namespace, routingKey));
                res = true;
            } else if (res = namespaceInquirer.patternExist(routingKey, namespace)) {
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.fine(
                            MessageFormat.format(MESSAGES.getString("evaluationStep6OK"), namespace, routingKey));
            } else {
                FailureResponseDetails failureDetails = new FailureResponseDetails();
                String reason = MESSAGES.getString(ErrorCodes.NAMESPACE_EXISTENCE_NOT_EXIST);
                failureDetails.setErrorReason(reason);
                failureDetails.setErrorCode(ErrorCodes.NAMESPACE_EXISTENCE_NOT_EXIST);
                responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                        requestType.getTimeStamp(), failureDetails);
                if (LOGGER.isLoggable(Level.INFO))
                    LOGGER.info(MessageFormat.format(MESSAGES.getString("evaluationStep6Failure"),
                            ErrorCodes.NAMESPACE_EXISTENCE_NOT_EXIST, reason));
            }
        } catch (SyntaxPatternException e) {
            FailureResponseDetails failureDetails = new FailureResponseDetails();
            String reason = MESSAGES.getString(ErrorCodes.INVALID_NAMESPACE_PATTERN_SYNTAX);
            failureDetails.setErrorReason(reason);
            failureDetails.setErrorCode(ErrorCodes.INVALID_NAMESPACE_PATTERN_SYNTAX);
            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                    requestType.getTimeStamp(), failureDetails);
            if (LOGGER.isLoggable(Level.INFO))
                LOGGER.log(Level.INFO, MessageFormat.format(MESSAGES.getString("evaluationStep6Failure"),
                        ErrorCodes.INVALID_NAMESPACE_PATTERN_SYNTAX, reason), e);
        } catch (NamespaceInquirerException e) {
            FailureResponseDetails failureDetails = new FailureResponseDetails();
            String reason = MESSAGES.getString(ErrorCodes.NAMESPACE_EXISTENCE_INTERNAL_ERROR);
            failureDetails.setErrorReason(reason);
            failureDetails.setErrorCode(ErrorCodes.NAMESPACE_EXISTENCE_INTERNAL_ERROR);
            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                    requestType.getTimeStamp(), failureDetails);
            if (LOGGER.isLoggable(Level.INFO))
                LOGGER.log(Level.INFO, MessageFormat.format(MESSAGES.getString("evaluationStep6Failure"),
                        ErrorCodes.NAMESPACE_EXISTENCE_INTERNAL_ERROR, reason), e);
        }

        //certificate control
        if (res) {
            try {
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.fine(MESSAGES.getString("evaluationStep7"));

                Element rootAuCapDoc = getRootAuCapDoc();
                X509CertificateSubjectInfo x509CertificateSubjectInfo = X509DocumentSigner
                        .getX509CertificateSubjectInfo(rootAuCapDoc);
                String rootSubjectId = x509CertificateSubjectInfo.getX509IssuerName();
                String rootSerial = x509CertificateSubjectInfo.getX509SerialNumber().toString();

                if (namespaceInquirer == null) {
                    if (LOGGER.isLoggable(Level.FINE))
                        LOGGER.fine(MessageFormat.format(MESSAGES.getString("evaluationStep7OK"), rootSubjectId));
                    res = true;
                } else if (res = namespaceInquirer.isTrustedCertificate(rootSubjectId, rootSerial, namespace)) {
                    if (LOGGER.isLoggable(Level.FINE))
                        LOGGER.fine(MessageFormat.format(MESSAGES.getString("evaluationStep7OK"), rootSubjectId));
                } else {
                    FailureResponseDetails failureDetails = new FailureResponseDetails();
                    String reason = MESSAGES.getString(ErrorCodes.CERTIFICATE_VERIFIER_NOT_VALID);
                    failureDetails.setErrorReason(reason);
                    failureDetails.setErrorCode(ErrorCodes.CERTIFICATE_VERIFIER_NOT_VALID);
                    responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                            requestType.getTimeStamp(), failureDetails);
                    if (LOGGER.isLoggable(Level.INFO))
                        LOGGER.info(MessageFormat.format(MESSAGES.getString("evaluationStep7Failure"),
                                ErrorCodes.CERTIFICATE_VERIFIER_NOT_VALID, reason));
                }
            } catch (NamespaceInquirerException e) {
                FailureResponseDetails failureDetails = new FailureResponseDetails();
                String reason = MESSAGES.getString(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
                failureDetails.setErrorCode(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
                responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                        requestType.getTimeStamp(), failureDetails);
                if (LOGGER.isLoggable(Level.INFO))
                    LOGGER.log(Level.INFO, MessageFormat.format(MESSAGES.getString("evaluationStep7Failure"),
                            ErrorCodes.CERTIFICATE_VERIFIER_NOT_VALID, reason), e);
            } catch (GeneralSecurityException e) {
                FailureResponseDetails failureDetails = new FailureResponseDetails();
                String reason = MESSAGES.getString(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
                failureDetails.setErrorCode(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
                responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                        requestType.getTimeStamp(), failureDetails);
                if (LOGGER.isLoggable(Level.INFO))
                    LOGGER.log(Level.INFO, MessageFormat.format(MESSAGES.getString("evaluationStep7Failure"),
                            ErrorCodes.CERTIFICATE_VERIFIER_NOT_VALID, reason), e);
            } catch (MarshalException e) {
                FailureResponseDetails failureDetails = new FailureResponseDetails();
                String reason = MESSAGES.getString(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
                failureDetails.setErrorCode(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
                responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                        requestType.getTimeStamp(), failureDetails);
                if (LOGGER.isLoggable(Level.INFO))
                    LOGGER.log(Level.INFO, MessageFormat.format(MESSAGES.getString("evaluationStep7Failure"),
                            ErrorCodes.CERTIFICATE_VERIFIER_NOT_VALID, reason), e);
            } catch (CapabilitySchemaFactoryException e) {
                FailureResponseDetails failureDetails = new FailureResponseDetails();
                String reason = MESSAGES.getString(ErrorCodes.INTERNAL_ERROR);
                failureDetails.setErrorCode(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
                responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                        requestType.getTimeStamp(), failureDetails);
                if (LOGGER.isLoggable(Level.INFO))
                    LOGGER.log(Level.INFO,
                            MessageFormat.format(MESSAGES.getString("evaluationStep7FailureDetails"),
                                    ErrorCodes.INTERNAL_ERROR, reason,
                                    MESSAGES.getString("rootCapabilityMarshallingFailure")),
                            e);
            } catch (CapabilitySchemaValidationHandlerException e) {
                FailureResponseDetails failureDetails = new FailureResponseDetails();
                String reason = MESSAGES.getString(ErrorCodes.INTERNAL_ERROR);
                failureDetails.setErrorCode(ErrorCodes.CERTIFICATE_VERIFIER_FAILURE);
                responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                        requestType.getTimeStamp(), failureDetails);
                if (LOGGER.isLoggable(Level.INFO))
                    LOGGER.log(Level.INFO,
                            MessageFormat.format(MESSAGES.getString("evaluationStep7FailureDetails"),
                                    ErrorCodes.INTERNAL_ERROR, reason,
                                    MESSAGES.getString("rootCapabilityMarshallingFailure")),
                            e);
            }
        }
        return res;
    }

    private Element getRootAuCapDoc()
            throws CapabilitySchemaFactoryException, CapabilitySchemaValidationHandlerException {
        AccessRightsCapabilityType issuerAuCap = capability;
        //debugging
        //        try {
        //            X509CertificateSubjectInfo x509CertificateSubjectInfo = X509DocumentSigner.getX509CertificateSubjectInfo(
        //                CapabilitySchemaFactory.getInstance().createAccessRightsDocument(issuerAuCap).getDocumentElement());
        //            String rootSubjectId = x509CertificateSubjectInfo.getX509IssuerName();
        //            String rootSerial = x509CertificateSubjectInfo.getX509SerialNumber().toString();
        //            LOGGER.fine("init " + x509CertificateSubjectInfo.getX509SubjectName() + 
        //                    " " + rootSubjectId + " " + rootSerial);
        //        } catch (GeneralSecurityException e) {
        //            e.printStackTrace();
        //        } catch (MarshalException e) {
        //            e.printStackTrace();
        //        }

        //        issuerAuCap = capability;
        while (issuerAuCap.getIssuerAccessRightsCapability().getAccessRightsCapability() != null) {
            issuerAuCap = issuerAuCap.getIssuerAccessRightsCapability().getAccessRightsCapability();
            //debugging
            //            try {
            //                X509CertificateSubjectInfo x509CertificateSubjectInfo = X509DocumentSigner.getX509CertificateSubjectInfo(
            //                    CapabilitySchemaFactory.getInstance().createAccessRightsDocument(issuerAuCap).getDocumentElement());
            //                String rootSubjectId = x509CertificateSubjectInfo.getX509IssuerName();
            //                String rootSerial = x509CertificateSubjectInfo.getX509SerialNumber().toString();
            //                LOGGER.fine("loop " + x509CertificateSubjectInfo.getX509SubjectName() + 
            //                        " " + rootSubjectId + " " + rootSerial);
            //            } catch (GeneralSecurityException e) {
            //                e.printStackTrace();
            //            } catch (MarshalException e) {
            //                e.printStackTrace();
            //            }
        }
        return CapabilitySchemaFactory.getInstance().createAccessRightsDocument(issuerAuCap).getDocumentElement();
    }

    private boolean executePDPCapabilityCheck() throws ENSResponseFactoryException {
        boolean res = false;
        try {
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.fine(
                        MessageFormat.format(MESSAGES.getString("evaluationStep5"), pdpClient.getURL().toString()));
            //         if(!pdpClient.executePDPCapabilityEvaluation(capability)){
            if (!pdpClient
                    .executePDPCapabilityEvaluation(requestType.getAccessRightsCapability().getCapability())) {
                FailureResponseDetails failureDetails = new FailureResponseDetails();
                String reason = MESSAGES.getString(ErrorCodes.PDP_EVALUATION_NOT_VALID);
                failureDetails.setErrorReason(reason);
                failureDetails.setErrorCode(ErrorCodes.PDP_EVALUATION_NOT_VALID);
                responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                        requestType.getTimeStamp(), failureDetails);
                if (LOGGER.isLoggable(Level.INFO))
                    LOGGER.info(MessageFormat.format(MESSAGES.getString("evaluationStep5Failure"),
                            ErrorCodes.PDP_EVALUATION_NOT_VALID, reason));
            } else
                res = true;
        } catch (Exception e) {
            FailureResponseDetails failureDetails = new FailureResponseDetails();
            String reason = MESSAGES.getString(ErrorCodes.PDP_EVALUATION_FAILURE);
            failureDetails.setErrorReason(reason);
            failureDetails.setErrorCode(ErrorCodes.PDP_EVALUATION_FAILURE);
            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                    requestType.getTimeStamp(), failureDetails);
            if (LOGGER.isLoggable(Level.INFO))
                LOGGER.log(Level.INFO, MessageFormat.format(MESSAGES.getString("evaluationStep5Failure"),
                        ErrorCodes.PDP_EVALUATION_FAILURE, reason), e);
        }
        return res;
    }

    /**
     * 
     * @param capability
     * @param vcs
     * @return
     * @throws ENSResponseFactoryException 
     * @throws ENSServiceFactoryException 
     */
    private boolean executeCapabilityVerifierCheck() throws ENSResponseFactoryException {
        boolean res = false;
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(MESSAGES.getString("evaluationStep4"));

        try {
            if (!CapabilityVerifier.accessRightsCapabilityValidityCheck(capability,
                    new ArrayList<VerifiedCapability>())) {
                FailureResponseDetails failureDetails = new FailureResponseDetails();
                String reason = MESSAGES.getString(ErrorCodes.CAPABILITY_VERIFIER_NOT_VALID);
                failureDetails.setErrorReason(reason);
                failureDetails.setErrorCode(ErrorCodes.CAPABILITY_VERIFIER_NOT_VALID);
                responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                        requestType.getTimeStamp(), failureDetails);
                if (LOGGER.isLoggable(Level.INFO))
                    LOGGER.log(Level.INFO, MessageFormat.format(MESSAGES.getString("evaluationStep4Failure"),
                            ErrorCodes.CAPABILITY_VERIFIER_NOT_VALID, reason));
            } else {
                res = true;
            }
        } catch (CapabilitySchemaValidationHandlerException e) {
            //String errors = CapabilitySchemaValidationHandler.dumpValidationEvents(e.getValidationEvents());
            FailureResponseDetails failureDetails = new FailureResponseDetails();
            String reason = MESSAGES.getString(ErrorCodes.INVALID_CAPABILITY_TOKEN);
            failureDetails.setErrorReason(reason);
            failureDetails.setErrorCode(ErrorCodes.INVALID_CAPABILITY_TOKEN);
            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                    requestType.getTimeStamp(), failureDetails);
            LOGGER.log(Level.INFO,
                    MessageFormat.format("evaluationStep4Failure", ErrorCodes.CAPABILITY_VERIFIER_FAILURE, reason),
                    e);
        } catch (CapabilityVerifierException e) {
            FailureResponseDetails failureDetails = new FailureResponseDetails();
            String reason = ErrorCodes.CAPABILITY_VERIFIER_FAILURE;
            failureDetails.setErrorReason(reason);
            failureDetails.setErrorCode(ErrorCodes.CAPABILITY_VERIFIER_FAILURE);
            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                    requestType.getTimeStamp(), failureDetails);
            LOGGER.log(Level.INFO,
                    MessageFormat.format("evaluationStep4Failure", ErrorCodes.CAPABILITY_VERIFIER_FAILURE, reason),
                    e);
        }

        return res;
    }

    //   private AccessRightsCapabilityType getRootAuCap(AccessRightsCapabilityType capability) {
    //      AccessRightsCapabilityType parentAuCap = capability;
    //      AccessRightsCapabilityType currentCapability = capability;
    //      boolean stop = false;
    //      AccessRightsCapabilityType rootAuCap = null;
    //      do {
    //         System.out.println(capability);
    //          parentAuCap = currentCapability.getIssuerAccessRightsCapability().getAccessRightsCapability();
    //          if (parentAuCap == null) {
    //              rootAuCap = currentCapability;
    //              stop = true;
    //          }
    //           else
    //               currentCapability = parentAuCap;
    //      } while (!stop);
    //      
    //      return rootAuCap;
    //   }

    private Permission createSubscribingPermissionsAndResources(boolean userAlreadyExists, String operativeHost,
            int httpPort, int operativePort, String operativeVhost, String ensUsername, String ensPwd,
            String adminUsername, String adminPwd, PermissionService permissionService, String queueName,
            String exchangeName) throws ENSResponseFactoryException {
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(MessageFormat.format(MESSAGES.getString("evaluationStep9ExplainationS"), ensUsername,
                    namespace, routingKey));
        Connection adminConnection = null;
        ConnectionFactory factory = new ConnectionFactory();
        factory.setUsername(adminUsername);
        factory.setPassword(adminPwd);
        factory.setVirtualHost(operativeVhost);
        factory.setHost(operativeHost);
        factory.setPort(operativePort);
        try {
            adminConnection = factory.newConnection();
            Channel channel = adminConnection.createChannel();
            //check if the queue exists
            if (AMQPQueueHelper.exists(channel, queueName)) {
                FailureResponseDetails failureDetails = new FailureResponseDetails();
                String reason = ErrorCodes.INTERNAL_ERROR;
                failureDetails.setErrorReason(reason);
                failureDetails.setErrorCode(ErrorCodes.INTERNAL_ERROR);
                responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                        requestType.getTimeStamp(), failureDetails);
                if (LOGGER.isLoggable(Level.INFO))
                    LOGGER.log(Level.INFO,
                            MessageFormat.format(MESSAGES.getString("evaluationStep9Failure"),
                                    ErrorCodes.INTERNAL_ERROR, reason,
                                    MessageFormat.format(MESSAGES.getString("alreadyExistingQueue"), queueName,
                                            operativeVhost, operativeHost + ":" + operativePort)));
                return null;
            }
            //forcing creating a new Connection because the following exception is thrown even on new Channel
            //            com.rabbitmq.client.AlreadyClosedException: clean connection shutdown; reason: Attempt to use closed channel
            //            at com.rabbitmq.client.impl.AMQChannel.ensureIsOpen(AMQChannel.java:190)
            //            at com.rabbitmq.client.impl.AMQChannel.rpc(AMQChannel.java:223)
            //            at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:209)
            //            at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:118)
            //            at com.rabbitmq.client.impl.ChannelN.queueDeclare(ChannelN.java:766)
            //            at com.rabbitmq.client.impl.ChannelN.queueDeclare(ChannelN.java:61)
            //            at it.txt.ens.authorisationService.amqp.AMQPQueueHelper.creates(AMQPQueueHelper.java:42)
            //            at it.txt.ens.authorisationService.util.AccessRequestEvaluator.createSubscribingPermissionsAndResources(AccessRequestEvaluator.java:893)
            //            at it.txt.ens.authorisationService.util.AccessRequestEvaluator.executeRabbitMQOperations(AccessRequestEvaluator.java:499)
            //            at it.txt.ens.authorisationService.util.AccessRequestEvaluator.evaluate(AccessRequestEvaluator.java:284)
            //            at it.txt.ens.authorisationService.util.AccessRequestEvaluator.run(AccessRequestEvaluator.java:216)
            //            at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
            //            at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
            //            at java.util.concurrent.FutureTask.run(Unknown Source)
            //            at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
            //            at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
            //            at java.lang.Thread.run(Unknown Source)
            adminConnection.close();
            adminConnection = factory.newConnection();
            AMQPQueueHelper.creates(adminConnection.createChannel(), queueName, false, false, true);
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.fine(MessageFormat.format(MESSAGES.getString("evaluationStep9OK-1S"), queueName,
                        operativeVhost, operativeHost + ":" + operativePort));
            adminConnection.createChannel().queueBind(queueName, exchangeName, routingKey);
            if (LOGGER.isLoggable(Level.FINE))
                LOGGER.fine(
                        MessageFormat.format(MESSAGES.getString("evaluationStep9OK-2S"), queueName, exchangeName));
            //            if (userAlreadyExists)
            //                return mergePermissions(permissionService , operativeVhost, ensUsername, "", "", queueName);
            //            else
            return new Permission(operativeVhost, ensUsername, "", "", queueName);
        } catch (Exception e) {
            FailureResponseDetails failureDetails = new FailureResponseDetails();
            String reason = MESSAGES.getString(ErrorCodes.ENS_RESOURCE_RESERVATION_FAILURE);
            failureDetails.setErrorReason(reason);
            failureDetails.setErrorCode(ErrorCodes.ENS_RESOURCE_RESERVATION_FAILURE);
            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                    requestType.getTimeStamp(), failureDetails);
            if (LOGGER.isLoggable(Level.INFO))
                LOGGER.log(Level.INFO, MessageFormat.format(MESSAGES.getString("evaluationStep9Failure"),
                        ErrorCodes.ENS_RESOURCE_RESERVATION_FAILURE, reason, e.getMessage()), e);
            return null;
        } finally {
            if (adminConnection != null)
                try {
                    adminConnection.close();
                } catch (IOException e) {
                }
        }
    }

    private Permission createPublishingPermissionsAndResources(boolean userAlreadyExists, String operativeHost,
            int httpPort, int operativePort, String operativeVhost, String ensUsername, String ensPwd,
            String adminUsername, String adminPwd, PermissionService permissionService, String exchangeName)
            throws ENSResponseFactoryException {
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(MessageFormat.format(MESSAGES.getString("evaluationStep9ExplainationP"), ensUsername,
                    namespace, routingKey));

        AMQPConnectionHelper mc = new AMQPConnectionHelper();
        Connection adminConnection = null;
        try {
            adminConnection = mc.connection(adminUsername, adminPwd, operativeVhost, operativeHost, operativePort);
            Channel channel = adminConnection.createChannel();
            //check if the exchange exists
            AMQPExchangeHelper exchHelper = new AMQPExchangeHelper();
            if (!exchHelper.exists(channel, exchangeName)) {
                exchHelper.creates(channel, exchangeName, "topic", true, false);
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.fine(MessageFormat.format(MESSAGES.getString("evaluationStep9OK-1P"), exchangeName,
                            operativeVhost, operativeHost + ":" + operativePort));
            } else if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine(MESSAGES.getString("evaluationStep9OK-2P"));
            }
            //           if (userAlreadyExists)
            //               return mergePermissions(permissionService , operativeVhost, ensUsername, "", exchangeName, "");
            //           else
            return new Permission(operativeVhost, ensUsername, "", exchangeName, "");
        } catch (IOException e) {
            FailureResponseDetails failureDetails = new FailureResponseDetails();
            String reason = MESSAGES.getString(ErrorCodes.ENS_RESOURCE_RESERVATION_FAILURE);
            failureDetails.setErrorReason(reason);
            failureDetails.setErrorCode(ErrorCodes.ENS_RESOURCE_RESERVATION_FAILURE);
            responseType = ensResponseFactory.createFailureResponse(requestType.getRequestID(),
                    requestType.getTimeStamp(), failureDetails);
            if (LOGGER.isLoggable(Level.INFO))
                LOGGER.log(Level.INFO, MessageFormat.format(MESSAGES.getString("evaluationStep9Failure"),
                        ErrorCodes.ENS_RESOURCE_RESERVATION_FAILURE, reason), e);
            return null;
        } finally {
            if (adminConnection != null)
                try {
                    adminConnection.close();
                } catch (IOException e) {
                }
        }
    }

    @Override
    public void shutdownCompleted(ShutdownSignalException cause) {
        if (!isClosed)
            LOGGER.log(Level.SEVERE, MessageFormat.format(MESSAGES.getString("channelShutdown"),
                    connection.getAddress().getHostName() + ":" + connection.getPort()), cause);
    }
}