All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wildfly.transaction.client.provider.remoting.RemotingRemoteTransactionPeer Maven / Gradle / Ivy

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2016 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.wildfly.transaction.client.provider.remoting;

import static java.security.AccessController.doPrivileged;

import java.io.IOException;
import java.net.URI;
import java.security.GeneralSecurityException;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;

import javax.net.ssl.SSLContext;
import javax.transaction.SystemException;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;

import org.jboss.remoting3.Attachments;
import org.jboss.remoting3.Connection;
import org.jboss.remoting3.ConnectionPeerIdentity;
import org.jboss.remoting3.Endpoint;
import org.jboss.remoting3.ServiceOpenException;
import org.wildfly.common.annotation.NotNull;
import org.wildfly.security.auth.client.AuthenticationConfiguration;
import org.wildfly.security.auth.client.AuthenticationContext;
import org.wildfly.security.auth.client.AuthenticationContextConfigurationClient;
import org.wildfly.transaction.client._private.Log;
import org.wildfly.transaction.client.spi.RemoteTransactionPeer;
import org.wildfly.transaction.client.spi.SimpleTransactionControl;
import org.wildfly.transaction.client.spi.SubordinateTransactionControl;

/**
 * @author David M. Lloyd
 */
class RemotingRemoteTransactionPeer implements RemoteTransactionPeer {
    private static final Attachments.Key key = new Attachments.Key<>(RemotingOperations.class);
    private static final AuthenticationContextConfigurationClient CLIENT = doPrivileged(AuthenticationContextConfigurationClient.ACTION);
    private final URI location;
    private final SSLContext sslContext;
    private final AuthenticationConfiguration authenticationConfiguration;
    private final AuthenticationContext authenticationContext;
    private final Endpoint endpoint;
    private final RemotingFallbackPeerProvider fallbackProvider;
    private final Set rollbackOnlyXids = new ConcurrentHashMap().keySet(Boolean.TRUE);

    RemotingRemoteTransactionPeer(final URI location, final SSLContext sslContext, final AuthenticationConfiguration authenticationConfiguration, final Endpoint endpoint, final RemotingFallbackPeerProvider fallbackProvider) {
        this.location = location;
        this.sslContext = sslContext;
        this.authenticationConfiguration = authenticationConfiguration;
        this.authenticationContext = AuthenticationContext.captureCurrent();
        this.endpoint = endpoint;
        this.fallbackProvider = fallbackProvider;
    }

    ConnectionPeerIdentity getPeerIdentity() throws IOException {
        SSLContext finalSslContext;
        if (sslContext == null) {
            try {
                finalSslContext = CLIENT.getSSLContext(location, authenticationContext, "jta", "jboss");
            } catch (GeneralSecurityException e) {
                throw new IOException(e);
            }
        } else {
            finalSslContext = sslContext;
        }
        AuthenticationConfiguration finalAuthenticationConfiguration;
        if (authenticationConfiguration == null) {
            finalAuthenticationConfiguration = CLIENT.getAuthenticationConfiguration(location, authenticationContext, -1, "jta", "jboss");
        } else {
            finalAuthenticationConfiguration = authenticationConfiguration;
        }
        return endpoint.getConnectedIdentity(location, finalSslContext, finalAuthenticationConfiguration).get();
    }

    ConnectionPeerIdentity getPeerIdentityXA() throws XAException {
        try {
            return getPeerIdentity();
        } catch (IOException | CancellationException e) {
            throw Log.log.failedToAcquireConnectionXA(e, XAException.XAER_RMFAIL);
        }
    }

    @NotNull
    RemotingOperations getOperations(Connection connection) throws IOException {
        final Attachments attachments = connection.getAttachments();
        RemotingOperations operations = attachments.getAttachment(key);
        if (operations != null) {
            return operations;
        }
        try {
            operations = TransactionClientChannel.forConnection(connection);
            final RemotingOperations appearing = attachments.attachIfAbsent(key, operations);
            if (appearing != null) {
                return appearing;
            }
        } catch (ServiceOpenException e) {
            // try alternatives
            RemotingFallbackPeerProvider fallbackProvider = this.fallbackProvider;
            if (fallbackProvider == null) {
                throw e;
            }
            try {
                operations = fallbackProvider.getOperations(connection);
            } catch (ServiceOpenException e1) {
                e1.addSuppressed(e);
                throw e1;
            }
            //noinspection ConstantConditions
            if (operations == null) {
                throw e;
            }
            final RemotingOperations appearing = attachments.attachIfAbsent(key, operations);
            if (appearing != null) {
                return appearing;
            }
        }
        return operations;
    }

    RemotingOperations getOperationsXA(Connection connection) throws XAException {
        try {
            return getOperations(connection);
        } catch (IOException e) {
            throw Log.log.failedToAcquireConnectionXA(e, XAException.XAER_RMERR);
        }
    }

    @NotNull
    public SubordinateTransactionControl lookupXid(final Xid xid) throws XAException {
        return new SubordinateTransactionControl() {
            public void rollback() throws XAException {
                try {
                    final ConnectionPeerIdentity peerIdentity = getPeerIdentityXA();
                    getOperationsXA(peerIdentity.getConnection()).rollback(xid, peerIdentity);
                } finally {
                    rollbackOnlyXids.remove(xid);
                }
            }

            public void end(final int flags) throws XAException {
                if (flags == XAResource.TMFAIL && rollbackOnlyXids.add(xid)) try {
                    final ConnectionPeerIdentity peerIdentity = getPeerIdentityXA();
                    getOperationsXA(peerIdentity.getConnection()).setRollbackOnly(xid, peerIdentity);
                } catch (Throwable t) {
                    rollbackOnlyXids.remove(xid);
                    throw t;
                }
            }

            public void beforeCompletion() throws XAException {
                final ConnectionPeerIdentity peerIdentity = getPeerIdentityXA();
                getOperationsXA(peerIdentity.getConnection()).beforeCompletion(xid, peerIdentity);
            }

            public int prepare() throws XAException {
                try {
                    final ConnectionPeerIdentity peerIdentity = getPeerIdentityXA();
                    return getOperationsXA(peerIdentity.getConnection()).prepare(xid, peerIdentity);
                } finally {
                    rollbackOnlyXids.remove(xid);
                }
            }

            public void forget() throws XAException {
                try {
                    final ConnectionPeerIdentity peerIdentity = getPeerIdentityXA();
                    getOperationsXA(peerIdentity.getConnection()).forget(xid, peerIdentity);
                } finally {
                    rollbackOnlyXids.remove(xid);
                }
            }

            public void commit(final boolean onePhase) throws XAException {
                try {
                    final ConnectionPeerIdentity peerIdentity = getPeerIdentityXA();
                    getOperationsXA(peerIdentity.getConnection()).commit(xid, onePhase, peerIdentity);
                } finally {
                    rollbackOnlyXids.remove(xid);
                }
            }
        };
    }

    @NotNull
    public Xid[] recover(final int flag, final String parentName) throws XAException {
        final ConnectionPeerIdentity peerIdentity = getPeerIdentityXA();
        return getOperationsXA(peerIdentity.getConnection()).recover(flag, parentName, peerIdentity);
    }

    @NotNull
    public SimpleTransactionControl begin(final int timeout) throws SystemException {
        // this one is bound to the connection
        try {
            final ConnectionPeerIdentity peerIdentity = getPeerIdentity();
            return getOperations(peerIdentity.getConnection()).begin(peerIdentity);
        } catch (IOException e) {
            throw Log.log.failedToAcquireConnection(e);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy