class RemoteOutgoingServerSession extends RemoteSession implements OutgoingServerSession {

    private AuthenticationMethod authenticationMethod;
    private final DomainPair pair;

    public RemoteOutgoingServerSession(byte[] nodeID, DomainPair address) {
        super(nodeID, new JID(null, address.getRemote(), null, true));
        this.pair = address;
    }

    @Override
    public Collection<DomainPair> getOutgoingDomainPairs()
    {
        ClusterTask task = getRemoteSessionTask(RemoteSessionTask.Operation.getOutgoingDomainPairs);
        return (Collection<DomainPair>) doSynchronousClusterTask(task);
    }

    @Override
    public void addOutgoingDomainPair(@Nonnull final DomainPair domainPair)
    {
        doClusterTask(new AddOutgoingDomainPair(domainPair));
    }

    @Override
    public boolean authenticateSubdomain(@Nonnull final DomainPair domainPair) {
        ClusterTask task = new AuthenticateSubdomainTask(domainPair);
        return (Boolean) doSynchronousClusterTask(task);
    }

    @Override
    public AuthenticationMethod getAuthenticationMethod() {<FILL_FUNCTION_BODY>}

    @Override
    public boolean checkOutgoingDomainPair(@Nonnull final DomainPair domainPair) {
        ClusterTask task = new CheckOutgoingDomainPairTask(domainPair);
        return (Boolean)doSynchronousClusterTask(task);
    }

    @Override
    RemoteSessionTask getRemoteSessionTask(RemoteSessionTask.Operation operation) {
        return new OutgoingServerSessionTask(pair, operation);
    }

    @Override
    ClusterTask getDeliverRawTextTask(String text) {
        return new DeliverRawTextServerTask(pair, text);
    }

    @Override
    ClusterTask getProcessPacketTask(Packet packet) {
        return new ProcessPacketTask(this, address, packet);
    }

    private static class DeliverRawTextServerTask extends OutgoingServerSessionTask {
        private String text;

        public DeliverRawTextServerTask() {
            super();
        }

        protected DeliverRawTextServerTask(DomainPair address, String text) {
            super(address, null);
            this.text = text;
        }

        @Override
        public void run() {
            getSession().deliverRawText(text);
        }

        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            super.writeExternal(out);
            ExternalizableUtil.getInstance().writeSafeUTF(out, text);
        }

        @Override
        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            super.readExternal(in);
            text = ExternalizableUtil.getInstance().readSafeUTF(in);
        }
    }

    private static class AddOutgoingDomainPair extends OutgoingServerSessionTask {

        public AddOutgoingDomainPair() {
            super();
        }

        protected AddOutgoingDomainPair(DomainPair address) {
            super(address, null);
        }

        @Override
        public void run() {
            ((OutgoingServerSession) getSession()).addOutgoingDomainPair(domainPair);
        }
    }

    private static class AuthenticateSubdomainTask extends OutgoingServerSessionTask {

        public AuthenticateSubdomainTask() {
            super();
        }

        protected AuthenticateSubdomainTask(DomainPair address) {
            super(address, null);
        }

        @Override
        public void run() {
            result = ((OutgoingServerSession) getSession()).authenticateSubdomain(domainPair);
        }
    }

    private static class CheckOutgoingDomainPairTask extends OutgoingServerSessionTask {

        public CheckOutgoingDomainPairTask() {
            super();
        }

        protected CheckOutgoingDomainPairTask(DomainPair address) {
            super(address, null);
        }

        @Override
        public void run() {
            result = ((OutgoingServerSession) getSession()).checkOutgoingDomainPair(this.domainPair);
        }
    }
}

        if (authenticationMethod == null) {
            ClusterTask task = getRemoteSessionTask(RemoteSessionTask.Operation.getAuthenticationMethod);
            authenticationMethod = (AuthenticationMethod) doSynchronousClusterTask(task);
        }
        return authenticationMethod;
    
<methods>public void <init>(byte[], JID) ,public void close() ,public void deliverRawText(java.lang.String) ,public JID getAddress() ,public java.lang.String getCipherSuiteName() ,public java.util.Date getCreationDate() ,public java.lang.String getHostAddress() throws java.net.UnknownHostException,public java.lang.String getHostName() throws java.net.UnknownHostException,public final java.util.Locale getLanguage() ,public java.util.Date getLastActiveDate() ,public long getNumClientPackets() ,public long getNumServerPackets() ,public java.security.cert.Certificate[] getPeerCertificates() ,public java.lang.String getServerName() ,public Map<java.lang.String,java.lang.String> getSoftwareVersion() ,public org.jivesoftware.openfire.session.Session.Status getStatus() ,public org.jivesoftware.openfire.StreamID getStreamID() ,public java.lang.String getTLSProtocolName() ,public boolean isClosed() ,public boolean isEncrypted() ,public boolean isSecure() ,public void process(Packet) ,public boolean validate() <variables>protected JID address,private java.util.Date creationDate,private java.lang.String hostAddress,private java.lang.String hostName,protected byte[] nodeID,private java.lang.String serverName,protected org.jivesoftware.openfire.StreamID streamID