<commit_before>package org.safehaus.subutai.core.peer.ui.forms;


import java.security.KeyStore;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.safehaus.subutai.common.environment.Environment;
import org.safehaus.subutai.common.peer.ContainerHost;
import org.safehaus.subutai.common.peer.Peer;
import org.safehaus.subutai.common.peer.PeerException;
import org.safehaus.subutai.common.peer.PeerInfo;
import org.safehaus.subutai.common.peer.PeerStatus;
import org.safehaus.subutai.common.security.crypto.keystore.KeyStoreData;
import org.safehaus.subutai.common.security.crypto.keystore.KeyStoreManager;
import org.safehaus.subutai.common.settings.ChannelSettings;
import org.safehaus.subutai.common.settings.SecuritySettings;
import org.safehaus.subutai.common.util.JsonUtil;
import org.safehaus.subutai.common.util.RestUtil;
import org.safehaus.subutai.core.peer.api.ContainerGroup;
import org.safehaus.subutai.core.peer.api.ContainerGroupNotFoundException;
import org.safehaus.subutai.core.peer.api.ResourceHost;
import org.safehaus.subutai.core.peer.ui.PeerManagerPortalModule;
import org.safehaus.subutai.server.ui.component.ConfirmationDialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.jaxrs.ext.form.Form;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.data.Property;
import com.vaadin.ui.AbsoluteLayout;
import com.vaadin.ui.Button;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;


/**
 * Registration process should be handled in save manner so no middleware attacks occur. In order to get there peers
 * need to exchange with public keys. This will create ssl layer by encrypting all traffic passing through their
 * connection. So first initial handshake will be one direction, to pass keys through encrypted channel and register
 * them in peers' trust stores. These newly saved keys will be used further for safe communication, with bidirectional
 * authentication.
 *
 *
 * TODO here still exists some issues concerned via registration/reject/approve requests. Some of them must pass through
 * secure channel such as unregister process. Which already must be in bidirectional auth completed stage.
 */
public class PeerRegisterForm extends CustomComponent
{

    private static final Logger LOG = LoggerFactory.getLogger( PeerRegisterForm.class.getName() );
    private final Gson gson = new GsonBuilder().setPrettyPrinting().create();

    @AutoGenerated
    private AbsoluteLayout mainLayout;
    @AutoGenerated
    private Table peersTable;
    @AutoGenerated
    private Button showPeersButton;
    @AutoGenerated
    private Button registerRequestButton;
    @AutoGenerated
    private TextField ipTextField;

    private PeerManagerPortalModule module;

    PeerManageActionsComponent.PeerManagerActionsListener listener =
            new PeerManageActionsComponent.PeerManagerActionsListener()

            {
                @Override
                public void OnPositiveButtonTrigger( final PeerInfo peer,
                                                     PeerManageActionsComponent.PeerManageUpdateViewListener
                                                             updateViewListener )
                {
                    switch ( peer.getStatus() )
                    {
                        case REQUESTED:
                            PeerInfo selfPeer = module.getPeerManager().getLocalPeerInfo();
                            approvePeerRegistration( selfPeer, peer, updateViewListener );
                            break;
                        case REGISTERED:
                            break;
                        case BLOCKED:
                            break;
                        default:
                            throw new IllegalStateException( peer.getStatus().name(),
                                    new Throwable( "Invalid case." ) );
                    }
                }


                @Override
                public void OnNegativeButtonTrigger( final PeerInfo peer,
                                                     PeerManageActionsComponent.PeerManageUpdateViewListener
                                                             updateViewListener )
                {

                    PeerInfo selfPeer = module.getPeerManager().getLocalPeerInfo();
                    switch ( peer.getStatus() )
                    {
                        case REJECTED:
                            removeMeFromRemote( selfPeer, peer, updateViewListener );
                            break;
                        case BLOCKED:
                        case BLOCKED_PEER:
                        case REQUESTED:
                        case REQUEST_SENT:
                            rejectPeerRegistration( selfPeer, peer, updateViewListener );
                            break;
                        case APPROVED:
                            unregisterMeFromRemote( selfPeer, peer, updateViewListener );
                            break;
                        default:
                            throw new TypeNotPresentException( peer.getStatus().name(),
                                    new Throwable( "Invalid case." ) );
                    }
                }
            };


    /**
     * The constructor should first build the main layout, set the composition root and then do any custom
     * initialization. <p/> The constructor will not be automatically regenerated by the visual editor.
     */
    public PeerRegisterForm( final PeerManagerPortalModule module )
    {
        buildMainLayout();
        setCompositionRoot( mainLayout );

        this.module = module;

        showPeersButton.click();
    }


    @AutoGenerated
    private AbsoluteLayout buildMainLayout()
    {
        // common part: create layout
        mainLayout = new AbsoluteLayout();
        mainLayout.setImmediate( false );
        mainLayout.setWidth( "100%" );
        mainLayout.setHeight( "100%" );

        // top-level component properties
        setWidth( "100.0%" );
        setHeight( "100.0%" );

        // peerRegisterLayout
        final AbsoluteLayout peerRegisterLayout = buildAbsoluteLayout();
        mainLayout.addComponent( peerRegisterLayout, "top:20.0px;right:0.0px;bottom:-20.0px;left:0.0px;" );

        return mainLayout;
    }


    @AutoGenerated
    private AbsoluteLayout buildAbsoluteLayout()
    {

        // common part: create layout
        AbsoluteLayout absoluteLayout = new AbsoluteLayout();
        absoluteLayout.setImmediate( false );
        absoluteLayout.setWidth( "100.0%" );
        absoluteLayout.setHeight( "100.0%" );

        // peerRegistration
        final Label peerRegistration = new Label();
        peerRegistration.setImmediate( false );
        peerRegistration.setWidth( "-1px" );
        peerRegistration.setHeight( "-1px" );
        peerRegistration.setValue( "Peer registration" );
        absoluteLayout.addComponent( peerRegistration, "top:0.0px;left:20.0px;" );

        // ip
        final Label ip = new Label();
        ip.setImmediate( false );
        ip.setWidth( "-1px" );
        ip.setHeight( "-1px" );
        ip.setValue( "IP" );
        absoluteLayout.addComponent( ip, "top:36.0px;left:20.0px;" );

        // ipTextField
        ipTextField = new TextField();
        ipTextField.setImmediate( false );
        ipTextField.setWidth( "-1px" );
        ipTextField.setHeight( "-1px" );
        ipTextField.setMaxLength( 15 );
        absoluteLayout.addComponent( ipTextField, "top:36.0px;left:150.0px;" );

        // registerRequestButton
        registerRequestButton = createRegisterButton();
        absoluteLayout.addComponent( registerRequestButton, "top:160.0px;left:20.0px;" );
        registerRequestButton = createRegisterButton();

        // showPeersButton
        showPeersButton = createShowPeersButton();
        absoluteLayout.addComponent( showPeersButton, "top:234.0px;left:20.0px;" );

        // peersTable
        peersTable = new Table();
        peersTable.setCaption( "Peers" );
        peersTable.setImmediate( false );
        peersTable.setWidth( "1000px" );
        peersTable.setHeight( "283px" );
        absoluteLayout.addComponent( peersTable, "top:294.0px;left:20.0px;" );

        return absoluteLayout;
    }


    private Button createShowPeersButton()
    {
        showPeersButton = new Button();
        showPeersButton.setCaption( "Show peers" );
        showPeersButton.setImmediate( false );
        showPeersButton.setWidth( "-1px" );
        showPeersButton.setHeight( "-1px" );

        showPeersButton.addClickListener( new Button.ClickListener()
        {
            @Override
            public void buttonClick( final Button.ClickEvent clickEvent )
            {
                populateData();
                peersTable.refreshRowCache();
            }
        } );

        return showPeersButton;
    }


    private void populateData()
    {
        List<PeerInfo> peers = module.getPeerManager().peers();
        peersTable.removeAllItems();
        peersTable.addContainerProperty( "ID", UUID.class, null );
        peersTable.addContainerProperty( "Name", String.class, null );
        peersTable.addContainerProperty( "IP", String.class, null );
        peersTable.addContainerProperty( "Status", PeerStatus.class, null );
        peersTable.addContainerProperty( "ActionsAdvanced", PeerManageActionsComponent.class, null );

        for ( final PeerInfo peer : peers )
        {
            if ( peer == null || peer.getStatus() == null )
            {
                continue;
            }
            /**
             * According to peer status perform sufficient action
             */
            //TODO perform different actions on peer response
            PeerManageActionsComponent component = new PeerManageActionsComponent( module, peer, listener );
            peersTable
                    .addItem( new Object[] { peer.getId(), peer.getName(), peer.getIp(), peer.getStatus(), component },
                            peer.getId() );
        }
    }


    /**
     * Send peer to register on remote peer. To construct secure connection. For now initializer peer doesn't send its
     * px2 (public key requiring bidirectional authentication).
     *
     * @param peerToRegister - initializer peer info for registration process
     * @param ip - target peer ip address
     */
    private void registerMeToRemote( final PeerInfo peerToRegister, final String ip )
    {
        new Thread( new Runnable()
        {
            @Override
            public void run()
            {
                registrationRequest( peerToRegister, ip );
            }
        } ).start();
    }


    private void registrationRequest( final PeerInfo peerToRegister, final String ip )
    {
        String baseUrl = String.format( "https://%s:%s/cxf", ip, ChannelSettings.SECURE_PORT_X1 );
        WebClient client = RestUtil.createTrustedWebClient( baseUrl );
        client.type( MediaType.MULTIPART_FORM_DATA ).accept( MediaType.APPLICATION_JSON );
        Form form = new Form();
        form.set( "peer", gson.toJson( peerToRegister ) );

        try
        {
            Response response = client.path( "peer/register" ).form( form );
            if ( response.getStatus() == Response.Status.OK.getStatusCode() )
            {
                Notification.show( String.format( "Request sent to %s!", ip ) );
                String responseString = response.readEntity( String.class );
                LOG.info( response.toString() );
                PeerInfo remotePeerInfo = JsonUtil.from( responseString, new TypeToken<PeerInfo>()
                {
                }.getType() );
                registerPeer( remotePeerInfo );
            }
            else if ( response.getStatus() == Response.Status.CONFLICT.getStatusCode() )
            {
                String reason = response.readEntity( String.class );
                Notification.show( reason, Notification.Type.WARNING_MESSAGE );
                LOG.warn( reason );
            }
            else
            {
                LOG.warn( "Response for registering peer: " + response.toString() );
            }
        }
        catch ( Exception e )
        {
            Notification.show( "Please check peer address for correctness", Notification.Type.WARNING_MESSAGE );
            LOG.error( "error sending request", e );
        }
    }


    private void registerPeer( final PeerInfo remotePeerInfo )
    {
        if ( remotePeerInfo != null )
        {
            remotePeerInfo.setStatus( PeerStatus.REQUEST_SENT );
            try
            {
                module.getPeerManager().register( remotePeerInfo );
            }
            catch ( PeerException e )
            {
                Notification.show( "Couldn't register peer. " + e.getMessage(), Notification.Type.WARNING_MESSAGE );
                LOG.error( "Couldn't register peer", e );
            }
        }
    }


    private void unregisterMeFromRemote( final PeerInfo peerToUnregister, final PeerInfo remotePeerInfo,
                                         final PeerManageActionsComponent.PeerManageUpdateViewListener
                                                 updateViewListener )
    {
        int relationExists = 0;
        for ( final Iterator<Environment> itEnv = module.getEnvironmentManager().getEnvironments().iterator();
              itEnv.hasNext() && relationExists == 0; )
        {
            Environment environment = itEnv.next();
            for ( final Iterator<Peer> itPeer = environment.getPeers().iterator();
                  itPeer.hasNext() && relationExists == 0; )
            {
                Peer peer = itPeer.next();
                if ( peer.getPeerInfo().equals( remotePeerInfo ) )
                {
                    relationExists = 1;
                }
            }
        }

        for ( final Iterator<ResourceHost> itResource =
              module.getPeerManager().getLocalPeer().getResourceHosts().iterator();
              itResource.hasNext() && relationExists == 0; )
        {
            ResourceHost resourceHost = itResource.next();
            for ( final Iterator<ContainerHost> itContainer = resourceHost.getContainerHosts().iterator();
                  itContainer.hasNext() && relationExists == 0; )
            {
                ContainerHost containerHost = itContainer.next();
                try
                {
                    ContainerGroup containerGroup = module.getPeerManager().getLocalPeer()
                                                          .findContainerGroupByContainerId( containerHost.getId() );

                    if ( containerGroup.getInitiatorPeerId().equals( remotePeerInfo.getId() ) )
                    {
                        relationExists = 2;
                    }
                }
                catch ( ContainerGroupNotFoundException ignore )
                {
                    //                    LOG.debug( "Couldn't get container group by container id", ignore );
                }
            }
        }

        if ( relationExists != 0 )
        {
            String msg = "";
            switch ( relationExists )
            {
                case 1:
                    msg = "Please destroy all cross peer environments, before you proceed!!!";
                    break;
                case 2:
                    msg = "You cannot unregister Peer, because you are a carrier of Peer's resources!!!"
                            + " Contact with Peer to migrate all his data.";
                    break;
            }
            ConfirmationDialog alert = new ConfirmationDialog( msg, "Ok", "" );
            alert.getOk().addClickListener( new Button.ClickListener()
            {
                @Override
                public void buttonClick( Button.ClickEvent clickEvent )
                {
                    //                    unregisterPeer( peerToUnregister, remotePeerInfo );
                }
            } );

            getUI().addWindow( alert.getAlert() );
        }
        else
        {
            unregisterPeer( peerToUnregister, remotePeerInfo, updateViewListener );
        }
    }


    private void unregisterPeer( final PeerInfo peerToUnregister, final PeerInfo remotePeerInfo,
                                 final PeerManageActionsComponent.PeerManageUpdateViewListener updateViewListener )
    {<commit_msg>sonar fix Methods should not be too complex<commit_after>package org.safehaus.subutai.core.peer.ui.forms;


import java.security.KeyStore;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.safehaus.subutai.common.environment.Environment;
import org.safehaus.subutai.common.peer.ContainerHost;
import org.safehaus.subutai.common.peer.Peer;
import org.safehaus.subutai.common.peer.PeerException;
import org.safehaus.subutai.common.peer.PeerInfo;
import org.safehaus.subutai.common.peer.PeerStatus;
import org.safehaus.subutai.common.security.crypto.keystore.KeyStoreData;
import org.safehaus.subutai.common.security.crypto.keystore.KeyStoreManager;
import org.safehaus.subutai.common.settings.ChannelSettings;
import org.safehaus.subutai.common.settings.SecuritySettings;
import org.safehaus.subutai.common.util.JsonUtil;
import org.safehaus.subutai.common.util.RestUtil;
import org.safehaus.subutai.core.peer.api.ContainerGroup;
import org.safehaus.subutai.core.peer.api.ContainerGroupNotFoundException;
import org.safehaus.subutai.core.peer.api.ResourceHost;
import org.safehaus.subutai.core.peer.ui.PeerManagerPortalModule;
import org.safehaus.subutai.server.ui.component.ConfirmationDialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.jaxrs.ext.form.Form;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.data.Property;
import com.vaadin.ui.AbsoluteLayout;
import com.vaadin.ui.Button;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;


/**
 * Registration process should be handled in save manner so no middleware attacks occur. In order to get there peers
 * need to exchange with public keys. This will create ssl layer by encrypting all traffic passing through their
 * connection. So first initial handshake will be one direction, to pass keys through encrypted channel and register
 * them in peers' trust stores. These newly saved keys will be used further for safe communication, with bidirectional
 * authentication.
 *
 *
 * TODO here still exists some issues concerned via registration/reject/approve requests. Some of them must pass through
 * secure channel such as unregister process. Which already must be in bidirectional auth completed stage.
 */
public class PeerRegisterForm extends CustomComponent
{

    private static final Logger LOG = LoggerFactory.getLogger( PeerRegisterForm.class.getName() );
    private final Gson gson = new GsonBuilder().setPrettyPrinting().create();

    @AutoGenerated
    private AbsoluteLayout mainLayout;
    @AutoGenerated
    private Table peersTable;
    @AutoGenerated
    private Button showPeersButton;
    @AutoGenerated
    private Button registerRequestButton;
    @AutoGenerated
    private TextField ipTextField;

    private PeerManagerPortalModule module;

    PeerManageActionsComponent.PeerManagerActionsListener listener =
            new PeerManageActionsComponent.PeerManagerActionsListener()

            {
                @Override
                public void OnPositiveButtonTrigger( final PeerInfo peer,
                                                     PeerManageActionsComponent.PeerManageUpdateViewListener
                                                             updateViewListener )
                {
                    switch ( peer.getStatus() )
                    {
                        case REQUESTED:
                            PeerInfo selfPeer = module.getPeerManager().getLocalPeerInfo();
                            approvePeerRegistration( selfPeer, peer, updateViewListener );
                            break;
                        case REGISTERED:
                            break;
                        case BLOCKED:
                            break;
                        default:
                            throw new IllegalStateException( peer.getStatus().name(),
                                    new Throwable( "Invalid case." ) );
                    }
                }


                @Override
                public void OnNegativeButtonTrigger( final PeerInfo peer,
                                                     PeerManageActionsComponent.PeerManageUpdateViewListener
                                                             updateViewListener )
                {

                    PeerInfo selfPeer = module.getPeerManager().getLocalPeerInfo();
                    switch ( peer.getStatus() )
                    {
                        case REJECTED:
                            removeMeFromRemote( selfPeer, peer, updateViewListener );
                            break;
                        case BLOCKED:
                        case BLOCKED_PEER:
                        case REQUESTED:
                        case REQUEST_SENT:
                            rejectPeerRegistration( selfPeer, peer, updateViewListener );
                            break;
                        case APPROVED:
                            unregisterMeFromRemote( selfPeer, peer, updateViewListener );
                            break;
                        default:
                            throw new TypeNotPresentException( peer.getStatus().name(),
                                    new Throwable( "Invalid case." ) );
                    }
                }
            };


    /**
     * The constructor should first build the main layout, set the composition root and then do any custom
     * initialization. <p/> The constructor will not be automatically regenerated by the visual editor.
     */
    public PeerRegisterForm( final PeerManagerPortalModule module )
    {
        buildMainLayout();
        setCompositionRoot( mainLayout );

        this.module = module;

        showPeersButton.click();
    }


    @AutoGenerated
    private AbsoluteLayout buildMainLayout()
    {
        // common part: create layout
        mainLayout = new AbsoluteLayout();
        mainLayout.setImmediate( false );
        mainLayout.setWidth( "100%" );
        mainLayout.setHeight( "100%" );

        // top-level component properties
        setWidth( "100.0%" );
        setHeight( "100.0%" );

        // peerRegisterLayout
        final AbsoluteLayout peerRegisterLayout = buildAbsoluteLayout();
        mainLayout.addComponent( peerRegisterLayout, "top:20.0px;right:0.0px;bottom:-20.0px;left:0.0px;" );

        return mainLayout;
    }


    @AutoGenerated
    private AbsoluteLayout buildAbsoluteLayout()
    {

        // common part: create layout
        AbsoluteLayout absoluteLayout = new AbsoluteLayout();
        absoluteLayout.setImmediate( false );
        absoluteLayout.setWidth( "100.0%" );
        absoluteLayout.setHeight( "100.0%" );

        // peerRegistration
        final Label peerRegistration = new Label();
        peerRegistration.setImmediate( false );
        peerRegistration.setWidth( "-1px" );
        peerRegistration.setHeight( "-1px" );
        peerRegistration.setValue( "Peer registration" );
        absoluteLayout.addComponent( peerRegistration, "top:0.0px;left:20.0px;" );

        // ip
        final Label ip = new Label();
        ip.setImmediate( false );
        ip.setWidth( "-1px" );
        ip.setHeight( "-1px" );
        ip.setValue( "IP" );
        absoluteLayout.addComponent( ip, "top:36.0px;left:20.0px;" );

        // ipTextField
        ipTextField = new TextField();
        ipTextField.setImmediate( false );
        ipTextField.setWidth( "-1px" );
        ipTextField.setHeight( "-1px" );
        ipTextField.setMaxLength( 15 );
        absoluteLayout.addComponent( ipTextField, "top:36.0px;left:150.0px;" );

        // registerRequestButton
        registerRequestButton = createRegisterButton();
        absoluteLayout.addComponent( registerRequestButton, "top:160.0px;left:20.0px;" );
        registerRequestButton = createRegisterButton();

        // showPeersButton
        showPeersButton = createShowPeersButton();
        absoluteLayout.addComponent( showPeersButton, "top:234.0px;left:20.0px;" );

        // peersTable
        peersTable = new Table();
        peersTable.setCaption( "Peers" );
        peersTable.setImmediate( false );
        peersTable.setWidth( "1000px" );
        peersTable.setHeight( "283px" );
        absoluteLayout.addComponent( peersTable, "top:294.0px;left:20.0px;" );

        return absoluteLayout;
    }


    private Button createShowPeersButton()
    {
        showPeersButton = new Button();
        showPeersButton.setCaption( "Show peers" );
        showPeersButton.setImmediate( false );
        showPeersButton.setWidth( "-1px" );
        showPeersButton.setHeight( "-1px" );

        showPeersButton.addClickListener( new Button.ClickListener()
        {
            @Override
            public void buttonClick( final Button.ClickEvent clickEvent )
            {
                populateData();
                peersTable.refreshRowCache();
            }
        } );

        return showPeersButton;
    }


    private void populateData()
    {
        List<PeerInfo> peers = module.getPeerManager().peers();
        peersTable.removeAllItems();
        peersTable.addContainerProperty( "ID", UUID.class, null );
        peersTable.addContainerProperty( "Name", String.class, null );
        peersTable.addContainerProperty( "IP", String.class, null );
        peersTable.addContainerProperty( "Status", PeerStatus.class, null );
        peersTable.addContainerProperty( "ActionsAdvanced", PeerManageActionsComponent.class, null );

        for ( final PeerInfo peer : peers )
        {
            if ( peer == null || peer.getStatus() == null )
            {
                continue;
            }
            /**
             * According to peer status perform sufficient action
             */
            //TODO perform different actions on peer response
            PeerManageActionsComponent component = new PeerManageActionsComponent( module, peer, listener );
            peersTable
                    .addItem( new Object[] { peer.getId(), peer.getName(), peer.getIp(), peer.getStatus(), component },
                            peer.getId() );
        }
    }


    /**
     * Send peer to register on remote peer. To construct secure connection. For now initializer peer doesn't send its
     * px2 (public key requiring bidirectional authentication).
     *
     * @param peerToRegister - initializer peer info for registration process
     * @param ip - target peer ip address
     */
    private void registerMeToRemote( final PeerInfo peerToRegister, final String ip )
    {
        new Thread( new Runnable()
        {
            @Override
            public void run()
            {
                registrationRequest( peerToRegister, ip );
            }
        } ).start();
    }


    private void registrationRequest( final PeerInfo peerToRegister, final String ip )
    {
        String baseUrl = String.format( "https://%s:%s/cxf", ip, ChannelSettings.SECURE_PORT_X1 );
        WebClient client = RestUtil.createTrustedWebClient( baseUrl );
        client.type( MediaType.MULTIPART_FORM_DATA ).accept( MediaType.APPLICATION_JSON );
        Form form = new Form();
        form.set( "peer", gson.toJson( peerToRegister ) );

        try
        {
            Response response = client.path( "peer/register" ).form( form );
            if ( response.getStatus() == Response.Status.OK.getStatusCode() )
            {
                Notification.show( String.format( "Request sent to %s!", ip ) );
                String responseString = response.readEntity( String.class );
                LOG.info( response.toString() );
                PeerInfo remotePeerInfo = JsonUtil.from( responseString, new TypeToken<PeerInfo>()
                {
                }.getType() );
                registerPeer( remotePeerInfo );
            }
            else if ( response.getStatus() == Response.Status.CONFLICT.getStatusCode() )
            {
                String reason = response.readEntity( String.class );
                Notification.show( reason, Notification.Type.WARNING_MESSAGE );
                LOG.warn( reason );
            }
            else
            {
                LOG.warn( "Response for registering peer: " + response.toString() );
            }
        }
        catch ( Exception e )
        {
            Notification.show( "Please check peer address for correctness", Notification.Type.WARNING_MESSAGE );
            LOG.error( "error sending request", e );
        }
    }


    private void registerPeer( final PeerInfo remotePeerInfo )
    {
        if ( remotePeerInfo != null )
        {
            remotePeerInfo.setStatus( PeerStatus.REQUEST_SENT );
            try
            {
                module.getPeerManager().register( remotePeerInfo );
            }
            catch ( PeerException e )
            {
                Notification.show( "Couldn't register peer. " + e.getMessage(), Notification.Type.WARNING_MESSAGE );
                LOG.error( "Couldn't register peer", e );
            }
        }
    }


    private void unregisterMeFromRemote( final PeerInfo peerToUnregister, final PeerInfo remotePeerInfo,
                                         final PeerManageActionsComponent.PeerManageUpdateViewListener
                                                 updateViewListener )
    {
        int relationExists = 0;
        relationExists = checkEnvironmentExistence( remotePeerInfo );

        relationExists = isRemotePeerContainersHost( remotePeerInfo );

        if ( relationExists != 0 )
        {
            String msg = "";
            switch ( relationExists )
            {
                case 1:
                    msg = "Please destroy all cross peer environments, before you proceed!!!";
                    break;
                case 2:
                    msg = "You cannot unregister Peer, because you are a carrier of Peer's resources!!!"
                            + " Contact with Peer to migrate all his data.";
                    break;
                default:
                    msg = "Cannot break peer relationship.";
            }
            ConfirmationDialog alert = new ConfirmationDialog( msg, "Ok", "" );
            alert.getOk().addClickListener( new Button.ClickListener()
            {
                @Override
                public void buttonClick( Button.ClickEvent clickEvent )
                {
                }
            } );

            getUI().addWindow( alert.getAlert() );
        }
        else
        {
            unregisterPeer( peerToUnregister, remotePeerInfo, updateViewListener );
        }
    }


    private int checkEnvironmentExistence( final PeerInfo remotePeerInfo )
    {
        int relationExists = 0;
        for ( final Iterator<Environment> itEnv = module.getEnvironmentManager().getEnvironments().iterator();
              itEnv.hasNext() && relationExists == 0; )
        {
            Environment environment = itEnv.next();
            for ( final Iterator<Peer> itPeer = environment.getPeers().iterator();
                  itPeer.hasNext() && relationExists == 0; )
            {
                Peer peer = itPeer.next();
                if ( peer.getPeerInfo().equals( remotePeerInfo ) )
                {
                    relationExists = 1;
                }
            }
        }
        return relationExists;
    }


    private int isRemotePeerContainersHost( final PeerInfo remotePeerInfo )
    {
        int relationExists = 0;
        for ( final Iterator<ResourceHost> itResource =
              module.getPeerManager().getLocalPeer().getResourceHosts().iterator();
              itResource.hasNext() && relationExists == 0; )
        {
            ResourceHost resourceHost = itResource.next();
            for ( final Iterator<ContainerHost> itContainer = resourceHost.getContainerHosts().iterator();
                  itContainer.hasNext() && relationExists == 0; )
            {
                ContainerHost containerHost = itContainer.next();
                try
                {
                    ContainerGroup containerGroup = module.getPeerManager().getLocalPeer()
                                                          .findContainerGroupByContainerId( containerHost.getId() );

                    if ( containerGroup.getInitiatorPeerId().equals( remotePeerInfo.getId() ) )
                    {
                        relationExists = 2;
                    }
                }
                catch ( ContainerGroupNotFoundException ignore )
                {
                }
            }
        }
        return relationExists;
    }


    private void unregisterPeer( final PeerInfo peerToUnregister, final PeerInfo remotePeerInfo,
                                 final PeerManageActionsComponent.PeerManageUpdateViewListener updateViewListener )
    {
{'fraction_non_alphanumeric': 0.0870128722495508, 'fraction_numerical': 0.006067925417538072, 'mean_word_length': 1.8642537754155066, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1800006', 'n_tokens_mistral': 8557, 'n_tokens_neox': 8056, 'n_words': 1914}