/**
     * Asynchronous method to handle the incoming request.
     */
@Override
    @Committing
    @PureWithSideEffects
    @SuppressWarnings("UseSpecificCatch")
    public void run() {
        try {
            final @Nonnull String address = getSocket().getInetAddress().getHostAddress();
            Log.debugging("Received a request from $.", address);
            final @Nonnull Time start = TimeBuilder.build();
            @Nullable Encryption<Signature<Compression<Pack>>> encryptedMethod = null;
            @Nullable Signature<Compression<Pack>> signedMethod = null;
            @Nullable Method<?> method = null;
            @Nullable Reply<?> reply = null;
            try {
                try {
                    final @Nonnull Pack pack = Pack.loadFrom(getSocket());
                    final @Nonnull Request request = pack.unpack(RequestConverter.INSTANCE, null);
                    encryptedMethod = request.getEncryption();
                    final @Nullable HostIdentifier recipient = encryptedMethod.getRecipient();
                    if (recipient == null) { throw RequestExceptionBuilder.withCode(RequestErrorCode.RECIPIENT).withMessage("The recipient may not be null.").build(); }
                    final @Nonnull Host host = Host.of(recipient);
                    signedMethod = encryptedMethod.getObject();
                    final @Nonnull SemanticType type = signedMethod.getObject().getObject().getType();
                    Log.debugging("Executing the method $ on host $.", type.getAddress(), recipient);
                    final @Nonnull InternalIdentifier subject;
                    if (type.equals(OpenAccount.TYPE)) { subject = recipient; } else { subject = signedMethod.getSubject(); }
                    final @Nonnull Account account = Account.with(host, subject.resolve());
                    method = MethodIndex.get(signedMethod, account);
                    reply = method.executeOnHost();
                    Database.commit();
                } catch (@Nonnull InternalException exception) {
                    throw RequestExceptionBuilder.withCode(RequestErrorCode.INTERNAL).withMessage("An internal problem occurred.").withCause(exception).build();
                } catch (@Nonnull ExternalException exception) {
                    throw RequestExceptionBuilder.withCode(RequestErrorCode.EXTERNAL).withMessage("An external problem occurred.").withCause(exception).build();
                }
            } catch (@Nonnull RequestException exception) {
                Database.rollback();
                Log.warning("A request error occurred:", exception);
                reply = RequestExceptionReplyBuilder.withRequestException(exception.isDecoded() ? RequestExceptionBuilder.withCode(RequestErrorCode.REQUEST).withMessage("Another server responded with a request error.").withCause(exception).build() : exception).build();
            }
            if (reply == null) { reply = EmptyReplyBuilder.build(); }
            final @Nonnull Compression<Pack> compressedReply = CompressionBuilder.withObject(reply.pack()).build();
            // The reply.pack() statement maps the semantic type of the reply converter, which results in a concurrent update if the client unpacks the response with the same database. The following commit prevents this. However, it is a suboptimal fix for this problem.
            try { Database.commit(); } catch (@Nonnull DatabaseException exception) { Database.rollback(); }
            final @Nonnull Signature<Compression<Pack>> signedReply;
            if (encryptedMethod != null && signedMethod != null) {
                signedReply = HostSignatureCreator.sign(compressedReply, CompressionConverterBuilder.withObjectConverter(PackConverter.INSTANCE).build()).about(signedMethod.getSubject()).as(encryptedMethod.getRecipient());
            } else {
                signedReply = SignatureBuilder.withObjectConverter(CompressionConverterBuilder.withObjectConverter(PackConverter.INSTANCE).build()).withObject(compressedReply).withSubject(HostIdentifier.DIGITALID).build();
            }
            final @Nonnull Encryption<Signature<Compression<Pack>>> encryptedReply;
            if (encryptedMethod instanceof RequestEncryption) {
                encryptedReply = ResponseEncryptionBuilder.withObject(signedReply).withSymmetricKey(((RequestEncryption) encryptedMethod).getSymmetricKey()).build();
            } else {
                encryptedReply = EncryptionBuilder.withObject(signedReply).build();
            }
            final @Nonnull Response response = ResponseBuilder.withEncryption(encryptedReply).build();
            response.pack().storeTo(getSocket());
            Log.information(method + " from " + address + " handled in " + start.ago().getValue() + " ms.");
        } catch (@Nonnull NetworkException exception) {
            Log.warning("Could not send a response.", exception);
        } catch (@Nonnull Throwable throwable) {
            Log.warning("Something went wrong.", throwable);
        } finally {
            try {
                if (!getSocket().isClosed()) { getSocket().close(); }
            } catch (@Nonnull IOException exception) {
                Log.warning("Could not close the socket.", exception);
            }
        }
    }
@Override
@Committing
@PureWithSideEffects
@SuppressWarnings("UseSpecificCatch")
public void run() {
try {
final @Nonnull String address = getSocket().getInetAddress().getHostAddress();
Log.debugging("Received a request from $.", address);
final @Nonnull Time start = TimeBuilder.build();
@Nullable Encryption<Signature<Compression<Pack>>> encryptedMethod = null;
@Nullable Signature<Compression<Pack>> signedMethod = null;
@Nullable Method<?> method = null;
@Nullable Reply<?> reply = null;
try {
try {
final @Nonnull Pack pack = Pack.loadFrom(getSocket());
final @Nonnull Request request = pack.unpack(RequestConverter.INSTANCE, null);
encryptedMethod = request.getEncryption();
final @Nullable HostIdentifier recipient = encryptedMethod.getRecipient();
if (recipient == null) { throw RequestExceptionBuilder.withCode(RequestErrorCode.RECIPIENT).withMessage("The recipient may not be null.").build(); }
final @Nonnull Host host = Host.of(recipient);
signedMethod = encryptedMethod.getObject();
final @Nonnull SemanticType type = signedMethod.getObject().getObject().getType();
Log.debugging("Executing the method $ on host $.", type.getAddress(), recipient);
final @Nonnull InternalIdentifier subject;
if (type.equals(OpenAccount.TYPE)) { subject = recipient; } else { subject = signedMethod.getSubject(); }
final @Nonnull Account account = Account.with(host, subject.resolve());
method = MethodIndex.get(signedMethod, account);
reply = method.executeOnHost();
Database.commit();
} catch (@Nonnull InternalException exception) {
throw RequestExceptionBuilder.withCode(RequestErrorCode.INTERNAL).withMessage("An internal problem occurred.").withCause(exception).build();
} catch (@Nonnull ExternalException exception) {
throw RequestExceptionBuilder.withCode(RequestErrorCode.EXTERNAL).withMessage("An external problem occurred.").withCause(exception).build();
}
} catch (@Nonnull RequestException exception) {
Database.rollback();
Log.warning("A request error occurred:", exception);
reply = RequestExceptionReplyBuilder.withRequestException(exception.isDecoded() ? RequestExceptionBuilder.withCode(RequestErrorCode.REQUEST).withMessage("Another server responded with a request error.").withCause(exception).build() : exception).build();
}
if (reply == null) { reply = EmptyReplyBuilder.build(); }
final @Nonnull Compression<Pack> compressedReply = CompressionBuilder.withObject(reply.pack()).build();
// The reply.pack() statement maps the semantic type of the reply converter, which results in a concurrent update if the client unpacks the response with the same database. The following commit prevents this. However, it is a suboptimal fix for this problem.
try { Database.commit(); } catch (@Nonnull DatabaseException exception) { Database.rollback(); }
final @Nonnull Signature<Compression<Pack>> signedReply;
if (encryptedMethod != null && signedMethod != null) {
signedReply = HostSignatureCreator.sign(compressedReply, CompressionConverterBuilder.withObjectConverter(PackConverter.INSTANCE).build()).about(signedMethod.getSubject()).as(encryptedMethod.getRecipient());
} else {
signedReply = SignatureBuilder.withObjectConverter(CompressionConverterBuilder.withObjectConverter(PackConverter.INSTANCE).build()).withObject(compressedReply).withSubject(HostIdentifier.DIGITALID).build();
}
final @Nonnull Encryption<Signature<Compression<Pack>>> encryptedReply;
if (encryptedMethod instanceof RequestEncryption) {
encryptedReply = ResponseEncryptionBuilder.withObject(signedReply).withSymmetricKey(((RequestEncryption) encryptedMethod).getSymmetricKey()).build();
} else {
encryptedReply = EncryptionBuilder.withObject(signedReply).build();
}
final @Nonnull Response response = ResponseBuilder.withEncryption(encryptedReply).build();
response.pack().storeTo(getSocket());
Log.information(method + " from " + address + " handled in " + start.ago().getValue() + " ms.");
} catch (@Nonnull NetworkException exception) {
Log.warning("Could not send a response.", exception);
} catch (@Nonnull Throwable throwable) {
Log.warning("Something went wrong.", throwable);
} finally {
try {
if (!getSocket().isClosed()) { getSocket().close(); }
} catch (@Nonnull IOException exception) {
Log.warning("Could not close the socket.", exception);
}
}
}
@Override
@Committing
@PureWithSideEffects
@SuppressWarnings("UseSpecificCatch")
public void run() {
try {
final @Nonnull String address = getSocket().getInetAddress().getHostAddress();
Log.debugging("Received a request from $.", address);
final @Nonnull Time start = TimeBuilder.build();
@Nullable Encryption<Signature<Compression<Pack>>> encryptedMethod = null;
@Nullable Signature<Compression<Pack>> signedMethod = null;
@Nullable Method<?> method = null;
@Nullable Reply<?> reply = null;
try {
try {
final @Nonnull Pack pack = Pack.loadFrom(getSocket());
final @Nonnull Request request = pack.unpack(RequestConverter.INSTANCE, null);
encryptedMethod = request.getEncryption();
final @Nullable HostIdentifier recipient = encryptedMethod.getRecipient();
if (recipient == null) { throw RequestExceptionBuilder.withCode(RequestErrorCode.RECIPIENT).withMessage("The recipient may not be null.").build(); }
final @Nonnull Host host = Host.of(recipient);
signedMethod = encryptedMethod.getObject();
final @Nonnull SemanticType type = signedMethod.getObject().getObject().getType();
Log.debugging("Executing the method $ on host $.", type.getAddress(), recipient);
final @Nonnull InternalIdentifier subject;
if (type.equals(OpenAccount.TYPE)) { subject = recipient; } else { subject = signedMethod.getSubject(); }
final @Nonnull Account account = Account.with(host, subject.resolve());
method = MethodIndex.get(signedMethod, account);
reply = method.executeOnHost();
Database.commit();
} catch (@Nonnull InternalException exception) {
throw RequestExceptionBuilder.withCode(RequestErrorCode.INTERNAL).withMessage("An internal problem occurred.").withCause(exception).build();
} catch (@Nonnull ExternalException exception) {
throw RequestExceptionBuilder.withCode(RequestErrorCode.EXTERNAL).withMessage("An external problem occurred.").withCause(exception).build();
}
} catch (@Nonnull RequestException exception) {
Database.rollback();
Log.warning("A request error occurred:", exception);
reply = RequestExceptionReplyBuilder.withRequestException(exception.isDecoded() ? RequestExceptionBuilder.withCode(RequestErrorCode.REQUEST).withMessage("Another server responded with a request error.").withCause(exception).build() : exception).build();
}
if (reply == null) { reply = EmptyReplyBuilder.build(); }
final @Nonnull Compression<Pack> compressedReply = CompressionBuilder.withObject(reply.pack()).build();
// The reply.pack() statement maps the semantic type of the reply converter, which results in a concurrent update if the client unpacks the response with the same database. The following commit prevents this. However, it is a suboptimal fix for this problem.
try { Database.commit(); } catch (@Nonnull DatabaseException exception) { Database.rollback(); }
final @Nonnull Signature<Compression<Pack>> signedReply;
if (encryptedMethod != null && signedMethod != null) {
signedReply = HostSignatureCreator.sign(compressedReply, CompressionConverterBuilder.withObjectConverter(PackConverter.INSTANCE).build()).about(signedMethod.getSubject()).as(encryptedMethod.getRecipient());
} else {
signedReply = SignatureBuilder.withObjectConverter(CompressionConverterBuilder.withObjectConverter(PackConverter.INSTANCE).build()).withObject(compressedReply).withSubject(HostIdentifier.DIGITALID).build();
}
final @Nonnull Encryption<Signature<Compression<Pack>>> encryptedReply;
if (encryptedMethod instanceof RequestEncryption) {
encryptedReply = ResponseEncryptionBuilder.withObject(signedReply).withSymmetricKey(((RequestEncryption) encryptedMethod).getSymmetricKey()).build();
} else {
encryptedReply = EncryptionBuilder.withObject(signedReply).build();
}
final @Nonnull Response response = ResponseBuilder.withEncryption(encryptedReply).build();
response.pack().storeTo(getSocket());
Log.information(method + " from " + address + " handled in " + start.ago().getValue() + " ms.");
} catch (@Nonnull NetworkException exception) {
Log.warning("Could not send a response.", exception);
} catch (@Nonnull Throwable throwable) {
Log.warning("Something went wrong.", throwable);
} finally {
try {
if (!getSocket().isClosed()) { getSocket().close(); }
} catch (@Nonnull IOException exception) {
Log.warning("Could not close the socket.", exception);
}
}
}
@Override
@Committing
@PureWithSideEffects
@SuppressWarnings("UseSpecificCatch")
public void run() {
try {
final @Nonnull String address = getSocket().getInetAddress().getHostAddress();
Log.debugging("Received a request from $.", address);
final @Nonnull Time start = TimeBuilder.build();
@Nullable Encryption<Signature<Compression<Pack>>> encryptedMethod = null;
@Nullable Signature<Compression<Pack>> signedMethod = null;
@Nullable Method<?> method = null;
@Nullable Reply<?> reply = null;
try {
try {
final @Nonnull Pack pack = Pack.loadFrom(getSocket());
final @Nonnull Request request = pack.unpack(RequestConverter.INSTANCE, null);
encryptedMethod = request.getEncryption();
final @Nullable HostIdentifier recipient = encryptedMethod.getRecipient();
if (recipient == null) { throw RequestExceptionBuilder.withCode(RequestErrorCode.RECIPIENT).withMessage("The recipient may not be null.").build(); }
final @Nonnull Host host = Host.of(recipient);
signedMethod = encryptedMethod.getObject();
final @Nonnull SemanticType type = signedMethod.getObject().getObject().getType();
Log.debugging("Executing the method $ on host $.", type.getAddress(), recipient);
final @Nonnull InternalIdentifier subject;
if (type.equals(OpenAccount.TYPE)) { subject = recipient; } else { subject = signedMethod.getSubject(); }
final @Nonnull Account account = Account.with(host, subject.resolve());
method = MethodIndex.get(signedMethod, account);
reply = method.executeOnHost();
Database.commit();
} catch (@Nonnull InternalException exception) {
throw RequestExceptionBuilder.withCode(RequestErrorCode.INTERNAL).withMessage("An internal problem occurred.").withCause(exception).build();
} catch (@Nonnull ExternalException exception) {
throw RequestExceptionBuilder.withCode(RequestErrorCode.EXTERNAL).withMessage("An external problem occurred.").withCause(exception).build();
}
} catch (@Nonnull RequestException exception) {
Database.rollback();
Log.warning("A request error occurred:", exception);
reply = RequestExceptionReplyBuilder.withRequestException(exception.isDecoded() ? RequestExceptionBuilder.withCode(RequestErrorCode.REQUEST).withMessage("Another server responded with a request error.").withCause(exception).build() : exception).build();
}
if (reply == null) { reply = EmptyReplyBuilder.build(); }
final @Nonnull Compression<Pack> compressedReply = CompressionBuilder.withObject(reply.pack()).build();
// The reply.pack() statement maps the semantic type of the reply converter, which results in a concurrent update if the client unpacks the response with the same database. The following commit prevents this. However, it is a suboptimal fix for this problem.
try { Database.commit(); } catch (@Nonnull DatabaseException exception) { Database.rollback(); }
final @Nonnull Signature<Compression<Pack>> signedReply;
if (encryptedMethod != null && signedMethod != null) {
signedReply = HostSignatureCreator.sign(compressedReply, CompressionConverterBuilder.withObjectConverter(PackConverter.INSTANCE).build()).about(signedMethod.getSubject()).as(encryptedMethod.getRecipient());
} else {
signedReply = SignatureBuilder.withObjectConverter(CompressionConverterBuilder.withObjectConverter(PackConverter.INSTANCE).build()).withObject(compressedReply).withSubject(HostIdentifier.DIGITALID).build();
}
final @Nonnull Encryption<Signature<Compression<Pack>>> encryptedReply;
if (encryptedMethod instanceof RequestEncryption) {
encryptedReply = ResponseEncryptionBuilder.withObject(signedReply).withSymmetricKey(((RequestEncryption) encryptedMethod).getSymmetricKey()).build();
} else {
encryptedReply = EncryptionBuilder.withObject(signedReply).build();
}
final @Nonnull Response response = ResponseBuilder.withEncryption(encryptedReply).build();
response.pack().storeTo(getSocket());
Log.information(method + " from " + address + " handled in " + start.ago().getValue() + " ms.");
} catch (@Nonnull NetworkException exception) {
Log.warning("Could not send a response.", exception);
} catch (@Nonnull Throwable throwable) {
Log.warning("Something went wrong.", throwable);
} finally {
try {
if (!getSocket().isClosed()) { getSocket().close(); }
} catch (@Nonnull IOException exception) {
Log.warning("Could not close the socket.", exception);
}
}
}