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

org.wildfly.transaction.client.provider.remoting.TransactionServerChannel 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 org.jboss.remoting3.util.StreamUtils.writeInt8;
import static org.jboss.remoting3.util.StreamUtils.writePackedUnsignedInt31;
import static org.wildfly.transaction.client._private.Log.log;
import static org.wildfly.transaction.client.provider.remoting.Protocol.*;
import static org.wildfly.transaction.client.provider.remoting.RemotingTransactionServer.LocalTxn;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import jakarta.transaction.HeuristicMixedException;
import jakarta.transaction.HeuristicRollbackException;
import jakarta.transaction.RollbackException;
import jakarta.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.Channel;
import org.jboss.remoting3.MessageInputStream;
import org.jboss.remoting3.MessageOutputStream;
import org.jboss.remoting3.RemotingOptions;
import org.jboss.remoting3.util.MessageTracker;
import org.jboss.remoting3.util.StreamUtils;
import org.wildfly.common.rpc.RemoteExceptionCause;
import org.wildfly.security.auth.server.SecurityIdentity;
import org.wildfly.transaction.client.ImportResult;
import org.wildfly.transaction.client.LocalTransaction;
import org.wildfly.transaction.client.LocalTransactionContext;
import org.wildfly.transaction.client.RemoteTransactionPermission;
import org.wildfly.transaction.client.SimpleXid;
import org.wildfly.transaction.client.XARecoverable;
import org.wildfly.transaction.client._private.Log;
import org.wildfly.transaction.client.spi.SubordinateTransactionControl;

/**
 * @author David M. Lloyd
 */
final class TransactionServerChannel {
    private final RemotingTransactionServer server;
    private final MessageTracker messageTracker;
    private final Channel channel;
    private final Channel.Receiver receiver = new ReceiverImpl();
    private final LocalTransactionContext localTransactionContext;

    private static final Attachments.Key KEY = new Attachments.Key<>(TransactionServerChannel.class);

    TransactionServerChannel(final RemotingTransactionServer server, final Channel channel, final LocalTransactionContext localTransactionContext) {
        this.server = server;
        this.channel = channel;
        this.localTransactionContext = localTransactionContext;
        messageTracker = new MessageTracker(channel, channel.getOption(RemotingOptions.MAX_OUTBOUND_MESSAGES).intValue());
        channel.getConnection().getAttachments().attach(KEY, this);
    }

    void start() {
        channel.receiveMessage(receiver);
    }

    class ReceiverImpl implements Channel.Receiver {

        ReceiverImpl() {
        }

        public void handleMessage(final Channel channel, final MessageInputStream messageOriginal) {
            channel.receiveMessage(this);
            try (MessageInputStream message = messageOriginal) {
                final int invId = message.readUnsignedShort();
                try {
                    final int id = message.readUnsignedByte();
                    switch (id) {
                        case M_CAPABILITY: {
                            handleCapabilityMessage(message, invId);
                            break;
                        }

                        case M_UT_ROLLBACK: {
                            handleUserTxnRollback(message, invId);
                            break;
                        }
                        case M_UT_COMMIT: {
                            handleUserTxnCommit(message, invId);
                            break;
                        }

                        case M_XA_ROLLBACK: {
                            handleXaTxnRollback(message, invId);
                            break;
                        }
                        case M_XA_BEFORE: {
                            handleXaTxnBefore(message, invId);
                            break;
                        }
                        case M_XA_PREPARE: {
                            handleXaTxnPrepare(message, invId);
                            break;
                        }
                        case M_XA_FORGET: {
                            handleXaTxnForget(message, invId);
                            break;
                        }
                        case M_XA_COMMIT: {
                            handleXaTxnCommit(message, invId);
                            break;
                        }
                        case M_XA_RECOVER: {
                            handleXaTxnRecover(message, invId);
                            break;
                        }
                        case M_XA_RB_ONLY: {
                            handleXaTxnRollbackOnly(message, invId);
                            break;
                        }

                        default: {
                            try (final MessageOutputStream outputStream = messageTracker.openMessageUninterruptibly()) {
                                outputStream.writeShort(invId);
                                outputStream.writeByte(M_RESP_ERROR);
                            } catch (IOException e) {
                                log.outboundException(e);
                            }
                            break;
                        }
                    }
                } catch (Throwable t) {
                    try (final MessageOutputStream outputStream = messageTracker.openMessageUninterruptibly()) {
                        outputStream.writeShort(invId);
                        outputStream.writeByte(M_RESP_ERROR);
                    } catch (IOException e) {
                        log.outboundException(e);
                    }
                    throw t;
                }
            } catch (IOException e) {
                log.inboundException(e);
            }
        }

        public void handleError(final Channel channel, final IOException error) {
        }

        public void handleEnd(final Channel channel) {
        }
    }

    void handleCapabilityMessage(final MessageInputStream message, final int invId) throws IOException {
        while (message.read() != -1) {
            // ignore parameters
            readIntParam(message, StreamUtils.readPackedUnsignedInt32(message));
        }
        // acknowledge no capabilities
        try (final MessageOutputStream outputStream = messageTracker.openMessageUninterruptibly()) {
            outputStream.writeShort(invId);
            outputStream.writeByte(M_RESP_CAPABILITY);
        }
        return;
    }

    void handleUserTxnRollback(final MessageInputStream message, final int invId) throws IOException {
        int param;
        int len;
        int context = 0;
        int secContext = 0;
        boolean hasContext = false;
        boolean hasSecContext = false;
        while ((param = message.read()) != -1) {
            len = StreamUtils.readPackedUnsignedInt32(message);
            switch (param) {
                case P_TXN_CONTEXT: {
                    context = readIntParam(message, len);
                    hasContext = true;
                    break;
                }
                case P_SEC_CONTEXT: {
                    secContext = readIntParam(message, len);
                    hasSecContext = true;
                    break;
                }
                default: {
                    // ignore bad parameter
                    readIntParam(message, len);
                }
            }
        }
        if (! hasContext) {
            writeParamError(invId);
            return;
        }
        final LocalTxn txn = server.getTxnMap().removeKey(context);
        if (txn == null) {
            // nothing to roll back!
            writeSimpleResponse(M_RESP_UT_ROLLBACK, invId);
            return;
        }
        SecurityIdentity securityIdentity = getSecurityIdentity(M_RESP_UT_ROLLBACK, invId, secContext, hasSecContext);
        if (securityIdentity == null) {
            return;
        }
        securityIdentity.runAs((Runnable) () -> {
            final LocalTransaction transaction = txn.getTransaction();
            if (transaction != null) try {
                transaction.performAction(transaction::rollback);
                writeSimpleResponse(M_RESP_UT_ROLLBACK, invId);
                return;
            } catch (SystemException e) {
                writeExceptionResponse(M_RESP_UT_ROLLBACK, invId, e);
                return;
            } catch (Exception e) {
                writeExceptionResponse(M_RESP_UT_ROLLBACK, invId, log.unexpectedException(e));
                return;
            } else {
                writeParamError(invId);
                return;
            }
        });
    }

    void handleUserTxnCommit(final MessageInputStream message, final int invId) throws IOException {
        int param;
        int len;
        int context = 0;
        int secContext = 0;
        boolean hasContext = false;
        boolean hasSecContext = false;
        while ((param = message.read()) != -1) {
            len = StreamUtils.readPackedUnsignedInt32(message);
            switch (param) {
                case P_TXN_CONTEXT: {
                    context = readIntParam(message, len);
                    hasContext = true;
                    break;
                }
                case P_SEC_CONTEXT: {
                    secContext = readIntParam(message, len);
                    hasSecContext = true;
                    break;
                }
                default: {
                    // ignore bad parameter
                    readIntParam(message, len);
                }
            }
        }
        if (! hasContext) {
            writeParamError(invId);
            return;
        }
        final LocalTxn txn = server.getTxnMap().removeKey(context);
        if (txn == null) {
            // nothing to commit!
            writeSimpleResponse(M_RESP_UT_COMMIT, invId);
            return;
        }
        SecurityIdentity securityIdentity = getSecurityIdentity(M_RESP_UT_COMMIT, invId, secContext, hasSecContext);
        if (securityIdentity == null) {
            return;
        }
        securityIdentity.runAs(() -> {
            final LocalTransaction transaction = txn.getTransaction();
            if (transaction != null) try {
                transaction.performAction(transaction::commit);
                writeSimpleResponse(M_RESP_UT_COMMIT, invId);
                return;
            } catch (HeuristicRollbackException e) {
                writeExceptionResponse(M_RESP_UT_COMMIT, invId, P_UT_HRE_EXC, e);
                return;
            } catch (RollbackException e) {
                writeExceptionResponse(M_RESP_UT_COMMIT, invId, P_UT_RB_EXC, e);
                return;
            } catch (HeuristicMixedException e) {
                writeExceptionResponse(M_RESP_UT_COMMIT, invId, P_UT_HME_EXC, e);
                return;
            } catch (SystemException e) {
                writeExceptionResponse(M_RESP_UT_COMMIT, invId, e);
                return;
            } catch (Exception e) {
                writeExceptionResponse(M_RESP_UT_COMMIT, invId, log.unexpectedException(e));
                return;
            } else {
                writeParamError(invId);
            }
        });
    }

    /////////////////////////

    void handleXaTxnRollback(final MessageInputStream message, final int invId) throws IOException {
        int param;
        int len;
        SimpleXid xid = null;
        int secContext = 0;
        boolean hasSecContext = false;
        while ((param = message.read()) != - 1) {
            len = StreamUtils.readPackedUnsignedInt32(message);
            switch (param) {
                case P_XID: {
                    xid = readXid(message, len);
                    break;
                }
                case P_SEC_CONTEXT: {
                    secContext = readIntParam(message, len);
                    hasSecContext = true;
                    break;
                }
                default: {
                    // ignore bad parameter
                    readIntParam(message, len);
                }
            }
        }
        if (xid == null) {
            writeParamError(invId);
            return;
        }
        SecurityIdentity securityIdentity = getSecurityIdentity(M_RESP_XA_ROLLBACK, invId, secContext, hasSecContext);
        if (securityIdentity == null) {
            return;
        }
        securityIdentity.runAsObjIntConsumer((x, i) -> {
            try {
                final ImportResult importResult = localTransactionContext.findOrImportTransaction(x, 0, true);
                if (importResult == null) {
                    writeExceptionResponse(M_RESP_XA_ROLLBACK, i, new XAException(XAException.XAER_NOTA));
                    return;
                }
                // run operation while associated
                importResult.getTransaction().performConsumer(SubordinateTransactionControl::rollback, importResult.getControl());
                writeSimpleResponse(M_RESP_XA_ROLLBACK, i);
            } catch (SystemException e) {
                final XAException xae = new XAException(XAException.XAER_RMERR);
                xae.initCause(e);
                writeExceptionResponse(M_RESP_XA_ROLLBACK, i, xae);
                return;
            } catch (XAException e) {
                writeExceptionResponse(M_RESP_XA_ROLLBACK, i, e);
                return;
            }
        }, xid, invId);
    }

    void handleXaTxnRollbackOnly(final MessageInputStream message, final int invId) throws IOException {
        int param;
        int len;
        SimpleXid xid = null;
        int secContext = 0;
        boolean hasSecContext = false;
        while ((param = message.read()) != - 1) {
            len = StreamUtils.readPackedUnsignedInt32(message);
            switch (param) {
                case P_XID: {
                    xid = readXid(message, len);
                    break;
                }
                case P_SEC_CONTEXT: {
                    secContext = readIntParam(message, len);
                    hasSecContext = true;
                    break;
                }
                default: {
                    // ignore bad parameter
                    readIntParam(message, len);
                }
            }
        }
        if (xid == null) {
            writeParamError(invId);
            return;
        }
        SecurityIdentity securityIdentity = getSecurityIdentity(M_RESP_XA_RB_ONLY, invId, secContext, hasSecContext);
        if (securityIdentity == null) {
            return;
        }
        securityIdentity.runAsObjIntConsumer((x, i) -> {
            try {
                final ImportResult importResult = localTransactionContext.findOrImportTransaction(x, 0, true);
                if (importResult != null) {
                    importResult.getControl().end(XAResource.TMFAIL);
                } else {
                    Log.log.debugf("No transaction associated with xid %s during setRollbackOnly execution", x);
                }
                writeSimpleResponse(M_RESP_XA_RB_ONLY, i);
            } catch (XAException e) {
                writeExceptionResponse(M_RESP_XA_RB_ONLY, i, e);
                return;
            }
        }, xid, invId);
    }

    void handleXaTxnBefore(final MessageInputStream message, final int invId) throws IOException {
        int param;
        int len;
        SimpleXid xid = null;
        int secContext = 0;
        boolean hasSecContext = false;
        while ((param = message.read()) != - 1) {
            len = StreamUtils.readPackedUnsignedInt32(message);
            switch (param) {
                case P_XID: {
                    xid = readXid(message, len);
                    break;
                }
                case P_SEC_CONTEXT: {
                    secContext = readIntParam(message, len);
                    hasSecContext = true;
                    break;
                }
                default: {
                    // ignore bad parameter
                    readIntParam(message, len);
                }
            }
        }
        if (xid == null) {
            writeParamError(invId);
            return;
        }
        SecurityIdentity securityIdentity = getSecurityIdentity(M_RESP_XA_BEFORE, invId, secContext, hasSecContext);
        if (securityIdentity == null) {
            return;
        }
        securityIdentity.runAsObjIntConsumer((x, i) -> {
            try {
                final ImportResult importResult = localTransactionContext.findOrImportTransaction(x, 0, true);
                if (importResult == null) {
                    writeExceptionResponse(M_RESP_XA_BEFORE, i, new XAException(XAException.XAER_NOTA));
                    return;
                }
                // run operation while associated
                importResult.getTransaction().performConsumer(SubordinateTransactionControl::beforeCompletion, importResult.getControl());
                writeSimpleResponse(M_RESP_XA_BEFORE, i);
            } catch (SystemException e) {
                final XAException xae = new XAException(XAException.XAER_RMERR);
                xae.initCause(e);
                writeExceptionResponse(M_RESP_XA_BEFORE, i, xae);
                return;
            } catch (XAException e) {
                writeExceptionResponse(M_RESP_XA_BEFORE, i, e);
                return;
            }
        }, xid, invId);
    }

    void handleXaTxnPrepare(final MessageInputStream message, final int invId) throws IOException {
        int param;
        int len;
        SimpleXid xid = null;
        int secContext = 0;
        boolean hasSecContext = false;
        while ((param = message.read()) != - 1) {
            len = StreamUtils.readPackedUnsignedInt32(message);
            switch (param) {
                case P_XID: {
                    xid = readXid(message, len);
                    break;
                }
                case P_SEC_CONTEXT: {
                    secContext = readIntParam(message, len);
                    hasSecContext = true;
                    break;
                }
                default: {
                    // ignore bad parameter
                    readIntParam(message, len);
                }
            }
        }
        if (xid == null) {
            writeParamError(invId);
            return;
        }
        SecurityIdentity securityIdentity = getSecurityIdentity(M_RESP_XA_PREPARE, invId, secContext, hasSecContext);
        if (securityIdentity == null) {
            return;
        }
        securityIdentity.runAsObjIntConsumer((x, i) -> {
            try {
                final ImportResult importResult = localTransactionContext.findOrImportTransaction(x, 0, true);
                if (importResult == null) {
                    writeExceptionResponse(M_RESP_XA_PREPARE, invId, new XAException(XAException.XAER_NOTA));
                    return;
                }
                // run operation while associated
                int result = ! importResult.getTransaction().isImported() ? XAResource.XA_RDONLY : importResult.getControl().prepare();
                if (result == XAResource.XA_RDONLY) {
                    writeSimpleResponse(M_RESP_XA_PREPARE, i, P_XA_RDONLY);
                } else {
                    // XA_OK
                    writeSimpleResponse(M_RESP_XA_PREPARE, i);
                }
            } catch (XAException e) {
                writeExceptionResponse(M_RESP_XA_PREPARE, i, e);
                return;
            } catch (Exception e) {
                final XAException xae = new XAException(XAException.XAER_RMERR);
                xae.initCause(e);
                writeExceptionResponse(M_RESP_XA_PREPARE, i, xae);
                return;
            }
        }, xid, invId);
    }

    void handleXaTxnForget(final MessageInputStream message, final int invId) throws IOException {
        int param;
        int len;
        SimpleXid xid = null;
        int secContext = 0;
        boolean hasSecContext = false;
        while ((param = message.read()) != - 1) {
            len = StreamUtils.readPackedUnsignedInt32(message);
            switch (param) {
                case P_XID: {
                    xid = readXid(message, len);
                    break;
                }
                case P_SEC_CONTEXT: {
                    secContext = readIntParam(message, len);
                    hasSecContext = true;
                    break;
                }
                default: {
                    // ignore bad parameter
                    readIntParam(message, len);
                }
            }
        }
        if (xid == null) {
            writeParamError(invId);
            return;
        }
        SecurityIdentity securityIdentity = getSecurityIdentity(M_RESP_XA_FORGET, invId, secContext, hasSecContext);
        if (securityIdentity == null) {
            return;
        }
        securityIdentity.runAsObjIntConsumer((x, i) -> {
            try {
                final ImportResult importResult = localTransactionContext.findOrImportTransaction(x, 0, true);
                if (importResult == null) {
                    writeExceptionResponse(M_RESP_XA_FORGET, i, new XAException(XAException.XAER_NOTA));
                    return;
                }
                // run operation while associated
                importResult.getControl().forget();
                writeSimpleResponse(M_RESP_XA_FORGET, i);
            } catch (XAException e) {
                writeExceptionResponse(M_RESP_XA_FORGET, i, e);
                return;
            } catch (Exception e) {
                final XAException xae = new XAException(XAException.XAER_RMERR);
                xae.initCause(e);
                writeExceptionResponse(M_RESP_XA_FORGET, i, xae);
                return;
            }
        }, xid, invId);
    }

    void handleXaTxnCommit(final MessageInputStream message, final int invId) throws IOException {
        int param;
        int len;
        SimpleXid xid = null;
        int secContext = 0;
        boolean hasSecContext = false;
        boolean onePhase = false;
        while ((param = message.read()) != - 1) {
            len = StreamUtils.readPackedUnsignedInt32(message);
            switch (param) {
                case P_XID: {
                    xid = readXid(message, len);
                    break;
                }
                case P_SEC_CONTEXT: {
                    secContext = readIntParam(message, len);
                    hasSecContext = true;
                    break;
                }
                case P_ONE_PHASE: {
                    onePhase = true;
                    readIntParam(message, len);
                    break;
                }
                default: {
                    // ignore bad parameter
                    readIntParam(message, len);
                }
            }
        }
        if (xid == null) {
            writeParamError(invId);
            return;
        }
        SecurityIdentity securityIdentity = getSecurityIdentity(M_RESP_XA_COMMIT, invId, secContext, hasSecContext);
        if (securityIdentity == null) {
            return;
        }
        securityIdentity.runAsConsumer((o, x) -> {
            try {
                final boolean onePhaseCopy = o.booleanValue();
                final ImportResult importResult = localTransactionContext.findOrImportTransaction(x, 0, ! onePhaseCopy);
                if (importResult == null) {
                    writeExceptionResponse(M_RESP_XA_COMMIT, invId, new XAException(XAException.XAER_NOTA));
                    return;
                }
                // run operation while associated
                importResult.getControl().commit(onePhaseCopy);
                writeSimpleResponse(M_RESP_XA_COMMIT, invId);
            } catch (XAException e) {
                writeExceptionResponse(M_RESP_XA_COMMIT, invId, e);
                return;
            } catch (Exception e) {
                final XAException xae = new XAException(XAException.XAER_RMERR);
                xae.initCause(e);
                writeExceptionResponse(M_RESP_XA_COMMIT, invId, xae);
                return;
            }
        }, Boolean.valueOf(onePhase), xid);
    }

    void handleXaTxnRecover(final MessageInputStream message, final int invId) throws IOException {
        int param;
        int len;
        int secContext = 0;
        String parentName = null;
        boolean hasSecContext = false;
        while ((param = message.read()) != - 1) {
            len = StreamUtils.readPackedUnsignedInt32(message);
            switch (param) {
                case P_SEC_CONTEXT: {
                    secContext = readIntParam(message, len);
                    hasSecContext = true;
                    break;
                }
                case P_PARENT_NAME: {
                    parentName = readStringParam(message, len);
                    break;
                }
                default: {
                    // ignore bad parameter
                    readIntParam(message, len);
                }
            }
        }
        SecurityIdentity securityIdentity = getSecurityIdentity(M_RESP_XA_RECOVER, invId, secContext, hasSecContext);
        if (securityIdentity == null) {
            return;
        }
        final String finalParentName = parentName;
        securityIdentity.runAs(() -> {
            final XARecoverable recoverable = localTransactionContext.getRecoveryInterface();
            Xid[] xids;
            try {
                // get the first batch
                xids = recoverable.recover(XAResource.TMSTARTRSCAN, finalParentName);
            } catch (XAException e) {
                writeExceptionResponse(M_RESP_XA_RECOVER, invId, e);
                return;
            }
            try (final MessageOutputStream outputStream = messageTracker.openMessageUninterruptibly()) {
                outputStream.writeShort(invId);
                outputStream.writeByte(M_RESP_XA_RECOVER);
                // maintain a "seen" set as some transaction managers don't treat recovery scanning as a cursor...
                // once the "seen" set hasn't been modified by a scan request, the scan is done
                Set seen = new HashSet();
                boolean added;
                do {
                    added = false;
                    for (final Xid xid : xids) {
                        SimpleXid gtid = SimpleXid.of(xid).withoutBranch();
                        if (seen.add(gtid)) {
                            added = true;
                            writeParam(P_XID, outputStream, xid);
                        }
                    }
                    if (added) try {
                        // get the next batch
                        xids = recoverable.recover(XAResource.TMNOFLAGS, finalParentName);
                    } catch (XAException e) {
                        try {
                            recoverable.recover(XAResource.TMENDRSCAN, finalParentName);
                            writeExceptionResponse(M_RESP_XA_RECOVER, invId, e);
                        } catch (XAException e1) {
                            e1.addSuppressed(e);
                            writeExceptionResponse(M_RESP_XA_RECOVER, invId, e1);
                        }
                        return;
                    }
                } while (xids.length > 0 && added);
                try {
                    xids = recoverable.recover(XAResource.TMENDRSCAN, finalParentName);
                } catch (XAException e) {
                    try {
                        recoverable.recover(XAResource.TMENDRSCAN, finalParentName);
                        writeExceptionResponse(M_RESP_XA_RECOVER, invId, e);
                    } catch (XAException e1) {
                        e1.addSuppressed(e);
                        writeExceptionResponse(M_RESP_XA_RECOVER, invId, e1);
                    }
                    return;
                }
                for (final Xid xid : xids) {
                    SimpleXid gtid = SimpleXid.of(xid).withoutBranch();
                    if (seen.add(gtid)) {
                        writeParam(P_XID, outputStream, xid);
                    }
                }
            } catch (IOException e) {
                log.outboundException(e);
                try {
                    recoverable.recover(XAResource.TMENDRSCAN);
                } catch (XAException e1) {
                    // ignored
                    log.recoverySuppressedException(e1);
                }
            }
        });
    }

    private SecurityIdentity getSecurityIdentity(int msgId, int invId, int secContext, boolean hasSecContext) {
        SecurityIdentity securityIdentity;
        if (hasSecContext) {
            securityIdentity = channel.getConnection().getLocalIdentity(secContext);
        } else {
            securityIdentity = channel.getConnection().getLocalIdentity();
        }
        if(!securityIdentity.implies(RemoteTransactionPermission.getInstance())) {
            writeExceptionResponse(msgId, invId, P_SEC_EXC, log.noPermission(securityIdentity.getPrincipal().getName(), RemoteTransactionPermission.getInstance()));
            return null;
        }
        return securityIdentity;
    }

    ///////////////////////////////////////////////////////////////

    void writeSimpleResponse(final int msgId, final int invId, final int param1) {
        try (final MessageOutputStream outputStream = messageTracker.openMessageUninterruptibly()) {
            outputStream.writeShort(invId);
            outputStream.writeByte(msgId);
            writeParam(param1, outputStream);
        } catch (IOException e) {
            log.outboundException(e);
        }
    }

    private void writeExceptionResponse(final int msgId, final int invId, final int exceptionKind, final Exception e) {
        try (final MessageOutputStream outputStream = messageTracker.openMessageUninterruptibly()) {
            outputStream.writeShort(invId);
            outputStream.writeByte(msgId);
            writeInt8(outputStream, exceptionKind);
            final RemoteExceptionCause remoteExceptionCause = RemoteExceptionCause.of(e);
            final ByteArrayOutputStream os = new ByteArrayOutputStream();
            final DataOutputStream dos = new DataOutputStream(os);
            remoteExceptionCause.writeToStream(dos);
            dos.flush();
            writePackedUnsignedInt31(outputStream, os.size());
            os.writeTo(outputStream);
        } catch (IOException ioe) {
            log.outboundException(ioe);
        }
    }

    private void writeExceptionResponse(final int msgId, final int invId, final int exceptionKind, final Exception e, int errorCode) {
        try (final MessageOutputStream outputStream = messageTracker.openMessageUninterruptibly()) {
            outputStream.writeShort(invId);
            outputStream.writeByte(msgId);
            writeInt8(outputStream, exceptionKind);
            final RemoteExceptionCause remoteExceptionCause = RemoteExceptionCause.of(e);
            final ByteArrayOutputStream os = new ByteArrayOutputStream();
            final DataOutputStream dos = new DataOutputStream(os);
            dos.writeInt(errorCode);
            remoteExceptionCause.writeToStream(dos);
            dos.flush();
            writePackedUnsignedInt31(outputStream, os.size());
            os.writeTo(outputStream);
        } catch (IOException ioe) {
            log.outboundException(ioe);
        }
    }

    private void writeExceptionResponse(final int msgId, final int invId, final SystemException e) {
        writeExceptionResponse(msgId, invId, P_UT_SYS_EXC, e, e.errorCode);
    }

    private void writeExceptionResponse(final int msgId, final int invId, final XAException e) {
        writeExceptionResponse(msgId, invId, P_XA_ERROR, e, e.errorCode);
    }

    void writeSimpleResponse(final int msgId, final int invId) {
        try (final MessageOutputStream outputStream = messageTracker.openMessageUninterruptibly()) {
            outputStream.writeShort(invId);
            outputStream.writeByte(msgId);
        } catch (IOException e) {
            log.outboundException(e);
        }
    }

    void writeParamError(final int invId) {
        try (final MessageOutputStream outputStream = messageTracker.openMessageUninterruptibly()) {
            outputStream.writeShort(invId);
            outputStream.writeByte(M_RESP_PARAM_ERROR);
        } catch (IOException e) {
            log.outboundException(e);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy