diff --git a/client/src/main/java/io/opencmw/client/cmwlight/CmwLightProtocol.java b/client/src/main/java/io/opencmw/client/cmwlight/CmwLightProtocol.java index 9dc2d777..4fb3fcca 100644 --- a/client/src/main/java/io/opencmw/client/cmwlight/CmwLightProtocol.java +++ b/client/src/main/java/io/opencmw/client/cmwlight/CmwLightProtocol.java @@ -24,7 +24,7 @@ * Serializes CmwLightMessage to ZeroMQ messages and vice versa. */ @SuppressWarnings("PMD.UnusedLocalVariable") // Unused variables are taken from the protocol and should be available for reference -public class CmwLightProtocol { +public class CmwLightProtocol { //NOPMD -- nomen est omen private static final String CONTEXT_ACQ_STAMP = "ContextAcqStamp"; private static final String CONTEXT_CYCLE_STAMP = "ContextCycleStamp"; private static final String MESSAGE = "Message"; @@ -37,6 +37,10 @@ public class CmwLightProtocol { public static final String VERSION = "1.0.0"; // Protocol version used if msg.version is null or empty private static final int SERIALISER_QUIRK = 100; // there seems to be a bug in the serialiser which does not update the buffer position correctly, so send more + private CmwLightProtocol() { + // utility class + } + /** * The message specified by the byte contained in the first frame of a message defines what type of message is present */ diff --git a/client/src/main/java/io/opencmw/client/rest/RestDataSource.java b/client/src/main/java/io/opencmw/client/rest/RestDataSource.java index cd5f2f2f..4d1a339c 100644 --- a/client/src/main/java/io/opencmw/client/rest/RestDataSource.java +++ b/client/src/main/java/io/opencmw/client/rest/RestDataSource.java @@ -17,8 +17,7 @@ import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.ReentrantLock; -import javax.validation.constraints.NotNull; - +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.spi.LoggingEventBuilder; @@ -106,7 +105,7 @@ public RestDataSource(final ZContext ctx, final String endpoint, final Duration super(endpoint); synchronized (LOGGER) { // prevent race condition between multiple constructor invocations if (okClient == null) { - okClient = new OkHttpClient(); + okClient = new OkHttpClient(); // NOPMD eventSourceFactory = EventSources.createFactory(okClient); } } @@ -317,7 +316,7 @@ public void run() { // NOPMD NOSONAR - complexity housekeeping(); } } - } catch (final Exception e) { // NOSONAR -- terminate normally beyond this point + } catch (final Exception e) { // NOPMD NOSONAR -- terminate normally beyond this point LOGGER.atError().setCause(e).log("data acquisition loop abnormally terminated"); } finally { externalSocket.close(); @@ -328,7 +327,7 @@ public void run() { // NOPMD NOSONAR - complexity public void start() { createPair(); - new Thread(this).start(); + new Thread(this).start(); // NOPMD } public void stop() { diff --git a/client/src/main/java/module-info.java b/client/src/main/java/module-info.java index 1802faa2..0dc004ca 100644 --- a/client/src/main/java/module-info.java +++ b/client/src/main/java/module-info.java @@ -10,6 +10,7 @@ requires java.validation; requires kotlin.stdlib; requires it.unimi.dsi.fastutil; + requires org.jetbrains.annotations; exports io.opencmw.client.cmwlight; exports io.opencmw.client.rest; diff --git a/concepts/src/main/java/io/opencmw/concepts/ManyVsLargeFrameEvaluation.java b/concepts/src/main/java/io/opencmw/concepts/ManyVsLargeFrameEvaluation.java index 7b45fc70..180821a8 100644 --- a/concepts/src/main/java/io/opencmw/concepts/ManyVsLargeFrameEvaluation.java +++ b/concepts/src/main/java/io/opencmw/concepts/ManyVsLargeFrameEvaluation.java @@ -23,8 +23,8 @@ public class ManyVsLargeFrameEvaluation { // NOPMD -- nomen est omen private static int sampleSize = 100_000; private static final int N_BUFFER_SIZE = 8; private static final int N_FRAMES = 10; - public static volatile byte[] smallMessage = new byte[N_BUFFER_SIZE * N_FRAMES]; - public static volatile byte[] largeMessage = new byte[N_BUFFER_SIZE]; + public static volatile byte[] smallMessage = new byte[N_BUFFER_SIZE * N_FRAMES]; // NOPMD - volatile on purpose + public static volatile byte[] largeMessage = new byte[N_BUFFER_SIZE]; // NOPMD - volatile on purpose private static final int N_LOOPS = 5; diff --git a/concepts/src/main/java/io/opencmw/concepts/RestBehindRouterEvaluation.java b/concepts/src/main/java/io/opencmw/concepts/RestBehindRouterEvaluation.java index 5167e991..62c4f3fb 100644 --- a/concepts/src/main/java/io/opencmw/concepts/RestBehindRouterEvaluation.java +++ b/concepts/src/main/java/io/opencmw/concepts/RestBehindRouterEvaluation.java @@ -134,8 +134,8 @@ private static ZFrame getRequest(final Socket socket) { private static void handleRouterSocket(final Socket router) { System.err.println("### called handleRouterSocket"); // Get [id, ] message on client connection. - ZFrame handle; - if ((handle = getConnectionID(router)) == null) { + ZFrame handle = getConnectionID(router); + if (handle == null) { // did not receive proper [ID, null msg] frames return; } diff --git a/concepts/src/main/java/io/opencmw/concepts/RoundTripAndNotifyEvaluation.java b/concepts/src/main/java/io/opencmw/concepts/RoundTripAndNotifyEvaluation.java index 2a3770d5..403e125f 100644 --- a/concepts/src/main/java/io/opencmw/concepts/RoundTripAndNotifyEvaluation.java +++ b/concepts/src/main/java/io/opencmw/concepts/RoundTripAndNotifyEvaluation.java @@ -31,7 +31,7 @@ * (ie. JIT, whether services are identified by single characters etc.) */ @SuppressWarnings("PMD.DoNotUseThreads") -class RoundTripAndNotifyEvaluation { // NOPMD -- nomen est omen +class RoundTripAndNotifyEvaluation { // private static final String SUB_TOPIC = "x"; private static final String SUB_TOPIC = "/?# - a very long topic to test the dependence of pub/sub pairs on topic lengths"; private static final byte[] SUB_DATA = "D".getBytes(StandardCharsets.UTF_8); // custom minimal data @@ -39,8 +39,12 @@ class RoundTripAndNotifyEvaluation { // NOPMD -- nomen est omen private static final byte[] WORKER_ID = "W".getBytes(StandardCharsets.UTF_8); // worker-service name private static final byte[] PUBLISH_ID = "P".getBytes(StandardCharsets.UTF_8); // publish-service name private static final byte[] SUBSCRIBER_ID = "S".getBytes(StandardCharsets.UTF_8); // subscriber name + public static final String START = "start"; + public static final String TCP_LOCALHOST_5555 = "tcp://localhost:5555"; private static final AtomicBoolean run = new AtomicBoolean(true); private static final boolean VERBOSE_PRINTOUT = false; + public static final char TAG_INTERNAL = 'I'; + public static final char TAG_EXTERNAL = 'E'; private static int sampleSize = 10_000; private static int sampleSizePub = 100_000; @@ -147,18 +151,18 @@ public void run() { // NOPMD single-loop broker ... simplifies reading ZFrame address = msg.pop(); ZFrame internal = msg.pop(); if (address.getData()[0] == CLIENT_ID[0]) { - if ('E' == internal.getData()[0]) { + if (TAG_EXTERNAL == internal.getData()[0]) { msg.addFirst(new ZFrame(WORKER_ID)); msg.send(tcpBackend); - } else if ('I' == internal.getData()[0]) { + } else if (TAG_INTERNAL == internal.getData()[0]) { msg.addFirst(new ZFrame(WORKER_ID)); msg.send(inprocBackend); } } else { - if ('E' == internal.getData()[0]) { + if (TAG_EXTERNAL == internal.getData()[0]) { msg.addFirst(new ZFrame(PUBLISH_ID)); msg.send(tcpBackend); - } else if ('I' == internal.getData()[0]) { + } else if (TAG_INTERNAL == internal.getData()[0]) { msg.addFirst(new ZFrame(PUBLISH_ID)); msg.send(inprocBackend); } @@ -251,7 +255,7 @@ public void run() { worker.connect("inproc://broker"); while (run.get() && !Thread.currentThread().isInterrupted()) { ZMsg msg = ZMsg.recvMsg(worker); - if ("start".equals(msg.getFirst().getString(ZMQ.CHARSET))) { + if (START.equals(msg.getFirst().getString(ZMQ.CHARSET))) { // System.err.println("dealer (indirect): start pushing"); for (int requests = 0; requests < sampleSizePub; requests++) { worker.send(SUB_TOPIC, ZMQ.SNDMORE); @@ -313,7 +317,7 @@ public void run() { worker.connect("tcp://localhost:5556"); while (run.get() && !Thread.currentThread().isInterrupted()) { ZMsg msg = ZMsg.recvMsg(worker); - if ("start".equals(msg.getFirst().getString(ZMQ.CHARSET))) { + if (START.equals(msg.getFirst().getString(ZMQ.CHARSET))) { // System.err.println("dealer (indirect): start pushing"); for (int requests = 0; requests < sampleSizePub; requests++) { worker.send(SUB_TOPIC, ZMQ.SNDMORE); @@ -337,7 +341,7 @@ public void run() { worker.bind("tcp://localhost:5558"); while (run.get() && !Thread.currentThread().isInterrupted()) { ZMsg msg = ZMsg.recvMsg(worker); - if ("start".equals(msg.getFirst().getString(ZMQ.CHARSET))) { + if (START.equals(msg.getFirst().getString(ZMQ.CHARSET))) { // System.err.println("dealer (direct): start pushing"); for (int requests = 0; requests < sampleSizePub; requests++) { worker.send(SUB_TOPIC, ZMQ.SNDMORE); @@ -358,7 +362,7 @@ public void run() { Socket client = ctx.createSocket(SocketType.DEALER); client.setHWM(0); client.setIdentity(CLIENT_ID); - client.connect("tcp://localhost:5555"); + client.connect(TCP_LOCALHOST_5555); Socket subClient = ctx.createSocket(SocketType.SUB); subClient.setHWM(0); @@ -418,24 +422,24 @@ public void run() { }); subClient.unsubscribe(SUB_TOPIC.getBytes(ZMQ.CHARSET)); - client.disconnect("tcp://localhost:5555"); + client.disconnect(TCP_LOCALHOST_5555); client.setIdentity(SUBSCRIBER_ID); - client.connect("tcp://localhost:5555"); - ZMsg.newStringMsg("start").addFirst("E").send(client); + client.connect(TCP_LOCALHOST_5555); + ZMsg.newStringMsg(START).addFirst("E").send(client); measure("Subscription (DEALER) test (TCP)", sampleSizePub, () -> { ZMsg req = ZMsg.recvMsg(client); req.destroy(); }); - ZMsg.newStringMsg("start").addFirst("I").send(client); + ZMsg.newStringMsg(START).addFirst("I").send(client); measure("Subscription (DEALER) test (InProc)", sampleSizePub, () -> { ZMsg req = ZMsg.recvMsg(client); req.destroy(); }); - client.disconnect("tcp://localhost:5555"); + client.disconnect(TCP_LOCALHOST_5555); client.connect("tcp://localhost:5558"); - ZMsg.newStringMsg("start").send(client); + ZMsg.newStringMsg(START).send(client); measure("Subscription (direct DEALER) test", sampleSizePub, () -> { ZMsg req = ZMsg.recvMsg(client); req.destroy(); diff --git a/concepts/src/main/java/io/opencmw/concepts/aggregate/DemuxEventDispatcher.java b/concepts/src/main/java/io/opencmw/concepts/aggregate/DemuxEventDispatcher.java index 35c1afab..57ba153a 100644 --- a/concepts/src/main/java/io/opencmw/concepts/aggregate/DemuxEventDispatcher.java +++ b/concepts/src/main/java/io/opencmw/concepts/aggregate/DemuxEventDispatcher.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.concurrent.locks.LockSupport; import io.opencmw.utils.Cache; @@ -33,7 +32,7 @@ public class DemuxEventDispatcher implements SequenceReportingEventHandler freeWorkers = Collections.synchronizedList(new ArrayList<>(N_WORKERS)); private final RingBuffer rb; // private Map aggregatedBpcts = new SoftHashMap<>(RETENTION_SIZE); - private Map aggregatedBpcts = new Cache<>(RETENTION_SIZE); + private final Cache aggregatedBpcts = new Cache<>(RETENTION_SIZE); private Sequence seq; public DemuxEventDispatcher(final RingBuffer ringBuffer) { diff --git a/concepts/src/main/java/io/opencmw/concepts/majordomo/ClientSampleV1.java b/concepts/src/main/java/io/opencmw/concepts/majordomo/ClientSampleV1.java index b7065bbb..e46bb209 100644 --- a/concepts/src/main/java/io/opencmw/concepts/majordomo/ClientSampleV1.java +++ b/concepts/src/main/java/io/opencmw/concepts/majordomo/ClientSampleV1.java @@ -10,9 +10,13 @@ /** * Majordomo Protocol client example. Uses the mdcli API to hide all OpenCmwProtocol aspects */ -public class ClientSampleV1 { +public final class ClientSampleV1 { // nomen est omen private static final int N_SAMPLES = 50_000; + private ClientSampleV1() { + // requires only static methods for testing + } + public static void main(String[] args) { MajordomoClientV1 clientSession = new MajordomoClientV1("tcp://localhost:5555", "customClientName"); final byte[] serviceBytes = "mmi.echo".getBytes(StandardCharsets.UTF_8); diff --git a/concepts/src/main/java/io/opencmw/concepts/majordomo/ClientSampleV2.java b/concepts/src/main/java/io/opencmw/concepts/majordomo/ClientSampleV2.java index 2bfe5e48..4fbd44d6 100644 --- a/concepts/src/main/java/io/opencmw/concepts/majordomo/ClientSampleV2.java +++ b/concepts/src/main/java/io/opencmw/concepts/majordomo/ClientSampleV2.java @@ -9,8 +9,13 @@ * all OpenCmwProtocol aspects */ -public class ClientSampleV2 { +public final class ClientSampleV2 { // NOPMD -- nomen est omen private static final int N_SAMPLES = 1_000_000; + + private ClientSampleV2() { + // requires only static methods for testing + } + public static void main(String[] args) { MajordomoClientV2 clientSession = new MajordomoClientV2("tcp://localhost:5555"); final byte[] serviceBytes = "mmi.echo".getBytes(StandardCharsets.UTF_8); diff --git a/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoBroker.java b/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoBroker.java index 86b3ef0a..598da616 100644 --- a/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoBroker.java +++ b/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoBroker.java @@ -31,8 +31,8 @@ * * default client time-out [s] is set by system property: 'OpenCMW.clientTimeOut' // default: 3600 [s] -- after which unanswered client messages and infos are being deleted * -*/ -@SuppressWarnings("PMD.DoNotUseThreads") + */ +@SuppressWarnings({ "PMD.DoNotUseThreads", "PMD.TooManyMethods", "PMD.GodClass", "PMD.UseConcurrentHashMap" }) // this is a concept, HashMap invoked in single-threaded context public class MajordomoBroker extends Thread { private static final Logger LOGGER = LoggerFactory.getLogger(MajordomoBroker.class); private static final byte[] INTERNAL_SENDER_ID = null; @@ -50,7 +50,7 @@ public class MajordomoBroker extends Thread { private final Socket internalRouterSocket; private final Socket internalServiceSocket; private final List routerSockets = new ArrayList<>(); // Sockets for clients & public external workers - private final AtomicBoolean run = new AtomicBoolean(false); + private final AtomicBoolean run = new AtomicBoolean(false); // NOPMD private final SortedSet> rbacRoles; private final Map services = new HashMap<>(); // known services Map<'service name', Service> private final Map workers = new HashMap<>(); // known workers Map @@ -174,7 +174,7 @@ public void run() { } @Override - public synchronized void start() { + public void start() { run.set(true); services.forEach((serviceName, service) -> service.internalWorkers.forEach(Thread::start)); super.start(); @@ -352,7 +352,7 @@ protected void processWorker(final Socket receiveSocket, final MdpWorkerMessage /** * Look for & kill expired clients. */ - protected /*synchronized*/ void purgeClients() { + protected void purgeClients() { if (CLIENT_TIMEOUT <= 0) { return; } @@ -508,7 +508,7 @@ protected class Service { protected final byte[] nameBytes; // Service name as byte array protected final MajordomoWorker mdpWorker; protected final boolean isInternal; - protected final Map, Queue> requests = new HashMap<>(); // RBAC-based queuing + protected final Map, Queue> requests = new HashMap<>(); // NOPMD RBAC-based queuing - thread-safe use of HashMap protected final Deque waiting = new ArrayDeque<>(); // List of waiting workers protected final List internalWorkers = new ArrayList<>(); protected final Socket internalDispatchSocket; diff --git a/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoClientV1.java b/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoClientV1.java index 6fbeba55..2b27d98c 100644 --- a/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoClientV1.java +++ b/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoClientV1.java @@ -26,12 +26,12 @@ public class MajordomoClientV1 { private static final AtomicInteger CLIENT_V1_INSTANCE = new AtomicInteger(); private final String uniqueID; private final byte[] uniqueIdBytes; - private String broker; - private ZContext ctx; + private final String broker; + private final ZContext ctx; private ZMQ.Socket clientSocket; private long timeout = 2500; private int retries = 3; - private Formatter log = new Formatter(System.out); + private final Formatter log = new Formatter(System.out); private ZMQ.Poller poller; public MajordomoClientV1(String broker, String clientName) { diff --git a/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoClientV2.java b/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoClientV2.java index 20727306..3049c6d6 100644 --- a/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoClientV2.java +++ b/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoClientV2.java @@ -101,7 +101,7 @@ public void setTimeout(long timeout) { /** * Connect or reconnect to broker */ - void reconnectToBroker() { + private void reconnectToBroker() { if (clientSocket != null) { clientSocket.close(); } diff --git a/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoProtocol.java b/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoProtocol.java index 2a954789..a09af2e3 100644 --- a/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoProtocol.java +++ b/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoProtocol.java @@ -346,9 +346,10 @@ public MdpMessage(final byte[] senderID, final MdpSubProtocol protocol, final by public byte[] getRbacFrame() { if (hasRbackToken()) { - return payload[payload.length - 1]; + final byte[] rbacFrame = payload[payload.length - 1]; + return Arrays.copyOf(rbacFrame, rbacFrame.length); } - return null; + return new byte[0]; } public boolean hasRbackToken() { diff --git a/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoWorker.java b/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoWorker.java index b8f4a998..650f62a0 100644 --- a/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoWorker.java +++ b/concepts/src/main/java/io/opencmw/concepts/majordomo/MajordomoWorker.java @@ -214,7 +214,7 @@ protected void handleReceive() { // NOPMD -- single serial function .. easier to } liveness = HEARTBEAT_LIVENESS; // Don't try to handle errors, just assert noisily - assert msg.payload.length > 0 : "MdpWorkerMessage payload is equal or less than zero: " + msg.payload.length; + assert msg.payload != null : "MdpWorkerMessage payload is null"; if (!(msg instanceof MdpWorkerMessage)) { assert false : "msg is not instance of MdpWorkerMessage"; continue; diff --git a/concepts/src/main/java/io/opencmw/concepts/majordomo/SimpleEchoServiceWorker.java b/concepts/src/main/java/io/opencmw/concepts/majordomo/SimpleEchoServiceWorker.java index 85e1443c..3e82007f 100644 --- a/concepts/src/main/java/io/opencmw/concepts/majordomo/SimpleEchoServiceWorker.java +++ b/concepts/src/main/java/io/opencmw/concepts/majordomo/SimpleEchoServiceWorker.java @@ -6,7 +6,12 @@ * Majordomo Protocol worker example. Uses the mdwrk API to hide all OpenCmwProtocol aspects * */ -public class SimpleEchoServiceWorker { +public class SimpleEchoServiceWorker { // NOPMD - nomen est omen + + private SimpleEchoServiceWorker() { + // private helper/test class + } + public static void main(String[] args) { MajordomoWorker workerSession = new MajordomoWorker("tcp://localhost:5556", "echo", BasicRbacRole.ADMIN); // workerSession.setDaemon(true); // use this if running in another app that controls threads diff --git a/concepts/src/main/java/io/opencmw/concepts/majordomo/legacy/CmwLightClient.java b/concepts/src/main/java/io/opencmw/concepts/majordomo/legacy/CmwLightClient.java index f125fec2..7b742f21 100644 --- a/concepts/src/main/java/io/opencmw/concepts/majordomo/legacy/CmwLightClient.java +++ b/concepts/src/main/java/io/opencmw/concepts/majordomo/legacy/CmwLightClient.java @@ -32,6 +32,7 @@ */ @Deprecated(since = "2020") public class CmwLightClient { + public static final String FAIR_SELECTOR_ALL = "FAIR.SELECTOR.ALL"; private final ZContext context = new ZContext(); private final ZMQ.Socket controlChannel; private final AtomicInteger connectionState = new AtomicInteger(0); @@ -187,7 +188,7 @@ public void subscribeSnoopFromDigitizer() { connectClient(); - subscribe("GSCD001", "SnoopTriggerEvents", "FAIR.SELECTOR.ALL"); + subscribe("GSCD001", "SnoopTriggerEvents", FAIR_SELECTOR_ALL); while (!Thread.currentThread().isInterrupted()) { receiveData(); @@ -217,7 +218,7 @@ public void getLocal() { sendHeartBeat(); - get("testdevice", "unknownProp", "FAIR.SELECTOR.ALL"); + get("testdevice", "unknownProp", FAIR_SELECTOR_ALL); // return reply to data while (true) { @@ -228,12 +229,12 @@ public void getLocal() { } System.out.println("Received GET Exception"); - get("testdevice", "testproperty", "FAIR.SELECTOR.ALL"); + get("testdevice", "testproperty", FAIR_SELECTOR_ALL); receiveData(); receiveData(); - subscribe("testdevice", "testproperty", "FAIR.SELECTOR.ALL"); + subscribe("testdevice", "testproperty", FAIR_SELECTOR_ALL); // just return all data while (!Thread.currentThread().isInterrupted()) { receiveData(); diff --git a/concepts/src/test/java/io/opencmw/concepts/majordomo/MajordomoBrokerTests.java b/concepts/src/test/java/io/opencmw/concepts/majordomo/MajordomoBrokerTests.java index 6be58fe5..bee46941 100644 --- a/concepts/src/test/java/io/opencmw/concepts/majordomo/MajordomoBrokerTests.java +++ b/concepts/src/test/java/io/opencmw/concepts/majordomo/MajordomoBrokerTests.java @@ -11,7 +11,6 @@ import org.awaitility.Awaitility; import org.hamcrest.Matchers; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.zeromq.SocketType; import org.zeromq.Utils; @@ -38,13 +37,13 @@ public void basicLowLevelRequestReplyTest() throws InterruptedException, IOExcep broker.start(); assertTrue(broker.isRunning(), "broker running"); // test interfaces - Assertions.assertNotNull(broker.getContext()); - Assertions.assertNotNull(broker.getInternalRouterSocket()); - Assertions.assertNotNull(broker.getServices()); + assertNotNull(broker.getContext()); + assertNotNull(broker.getInternalRouterSocket()); + assertNotNull(broker.getServices()); assertEquals(2, broker.getServices().size()); - Assertions.assertDoesNotThrow(() -> broker.addInternalService(new MajordomoWorker(broker.getContext(), "demoService"), 10)); + assertDoesNotThrow(() -> broker.addInternalService(new MajordomoWorker(broker.getContext(), "demoService"), 10)); assertEquals(3, broker.getServices().size()); - Assertions.assertDoesNotThrow(() -> broker.removeService("demoService")); + assertDoesNotThrow(() -> broker.removeService("demoService")); assertEquals(2, broker.getServices().size()); // wait until all services are initialised @@ -60,18 +59,19 @@ public void basicLowLevelRequestReplyTest() throws InterruptedException, IOExcep sendClientMessage(clientSocket, MdpClientCommand.C_UNKNOWN, null, DEFAULT_ECHO_SERVICE, DEFAULT_REQUEST_MESSAGE_BYTES); final MdpMessage reply = receiveMdpMessage(clientSocket); - Assertions.assertNotNull(reply.toString()); + assertNotNull(reply.toString()); assertNotNull(reply, "reply message w/o RBAC token not being null"); - Assertions.assertTrue(reply instanceof MdpClientMessage); + assertTrue(reply instanceof MdpClientMessage); MdpClientMessage clientMessage = (MdpClientMessage) reply; - Assertions.assertNull(clientMessage.senderID); // default dealer socket does not export sender ID (only ROUTER and/or enabled sockets) + assertNull(clientMessage.senderID); // default dealer socket does not export sender ID (only ROUTER and/or enabled sockets) assertEquals(MdpSubProtocol.C_CLIENT, clientMessage.protocol, "equal protocol"); assertEquals(MdpClientCommand.C_UNKNOWN, clientMessage.command, "matching command"); assertArrayEquals(DEFAULT_ECHO_SERVICE, clientMessage.serviceNameBytes, "equal service name"); assertNotNull(clientMessage.payload, "user-data not being null"); assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, clientMessage.payload[0], "equal data"); assertFalse(clientMessage.hasRbackToken()); - Assertions.assertNull(clientMessage.getRbacFrame()); + assertNotNull(clientMessage.getRbacFrame()); + assertArrayEquals(new byte[0], clientMessage.getRbacFrame()); broker.stopBroker(); } @@ -107,53 +107,53 @@ public void basicSynchronousRequestReplyTest() throws InterruptedException, IOEx // using simple synchronous client MajordomoClientV1 clientSession = new MajordomoClientV1("tcp://localhost:" + openPort, "customClientName"); assertEquals(3, clientSession.getRetries()); - Assertions.assertDoesNotThrow(() -> clientSession.setRetries(4)); + assertDoesNotThrow(() -> clientSession.setRetries(4)); assertEquals(4, clientSession.getRetries()); assertEquals(2500, clientSession.getTimeout()); - Assertions.assertDoesNotThrow(() -> clientSession.setTimeout(2000)); + assertDoesNotThrow(() -> clientSession.setTimeout(2000)); assertEquals(2000, clientSession.getTimeout()); - Assertions.assertNotNull(clientSession.getUniqueID()); + assertNotNull(clientSession.getUniqueID()); { final byte[] serviceBytes = "mmi.echo".getBytes(StandardCharsets.UTF_8); final ZMsg replyWithoutRbac = clientSession.send(serviceBytes, DEFAULT_REQUEST_MESSAGE_BYTES); // w/o RBAC - Assertions.assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); - Assertions.assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); - Assertions.assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, replyWithoutRbac.pollLast().getData(), "equal data"); + assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); + assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); + assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, replyWithoutRbac.pollLast().getData(), "equal data"); } { final byte[] serviceBytes = "inproc.echo".getBytes(StandardCharsets.UTF_8); final ZMsg replyWithoutRbac = clientSession.send(serviceBytes, DEFAULT_REQUEST_MESSAGE_BYTES); // w/o RBAC - Assertions.assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); - Assertions.assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); - Assertions.assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, replyWithoutRbac.pollLast().getData(), "equal data"); + assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); + assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); + assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, replyWithoutRbac.pollLast().getData(), "equal data"); } { final byte[] serviceBytes = "ext.echo".getBytes(StandardCharsets.UTF_8); final ZMsg replyWithoutRbac = clientSession.send(serviceBytes, DEFAULT_REQUEST_MESSAGE_BYTES); // w/o RBAC - Assertions.assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); - Assertions.assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); - Assertions.assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, replyWithoutRbac.pollLast().getData(), "equal data"); + assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); + assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); + assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, replyWithoutRbac.pollLast().getData(), "equal data"); } { final byte[] serviceBytes = "inproc.exception".getBytes(StandardCharsets.UTF_8); final ZMsg replyWithoutRbac = clientSession.send(serviceBytes, DEFAULT_REQUEST_MESSAGE_BYTES); // w/o RBAC - Assertions.assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); - Assertions.assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); + assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); + assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); // future: check exception type } { final byte[] serviceBytes = "mmi.echo".getBytes(StandardCharsets.UTF_8); final ZMsg replyWithRbac = clientSession.send(serviceBytes, DEFAULT_REQUEST_MESSAGE_BYTES, DEFAULT_RBAC_TOKEN); // with RBAC - Assertions.assertNotNull(replyWithRbac, "reply message with RBAC token not being null"); - Assertions.assertNotNull(replyWithRbac.peekLast(), "RBAC token not being null"); - Assertions.assertArrayEquals(DEFAULT_RBAC_TOKEN, replyWithRbac.pollLast().getData(), "equal RBAC token"); - Assertions.assertNotNull(replyWithRbac.peekLast(), "user-data not being null"); - Assertions.assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, replyWithRbac.pollLast().getData(), "equal data"); + assertNotNull(replyWithRbac, "reply message with RBAC token not being null"); + assertNotNull(replyWithRbac.peekLast(), "RBAC token not being null"); + assertArrayEquals(DEFAULT_RBAC_TOKEN, replyWithRbac.pollLast().getData(), "equal RBAC token"); + assertNotNull(replyWithRbac.peekLast(), "user-data not being null"); + assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, replyWithRbac.pollLast().getData(), "equal data"); } internal.stopWorker(); @@ -175,39 +175,39 @@ public void basicMmiTests() throws IOException { { final ZMsg replyWithoutRbac = clientSession.send("mmi.echo", DEFAULT_REQUEST_MESSAGE_BYTES); // w/o RBAC - Assertions.assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); - Assertions.assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); - Assertions.assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, replyWithoutRbac.pollLast().getData(), "MMI echo service request"); + assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); + assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); + assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, replyWithoutRbac.pollLast().getData(), "MMI echo service request"); } { final ZMsg replyWithoutRbac = clientSession.send(DEFAULT_MMI_SERVICE, DEFAULT_MMI_SERVICE); // w/o RBAC - Assertions.assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); - Assertions.assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); - Assertions.assertEquals("200", new String(replyWithoutRbac.pollLast().getData(), StandardCharsets.UTF_8), "known MMI service request"); + assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); + assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); + assertEquals("200", new String(replyWithoutRbac.pollLast().getData(), StandardCharsets.UTF_8), "known MMI service request"); } { final ZMsg replyWithoutRbac = clientSession.send(DEFAULT_MMI_SERVICE, DEFAULT_ECHO_SERVICE); // w/o RBAC - Assertions.assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); - Assertions.assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); - Assertions.assertEquals("200", new String(replyWithoutRbac.pollLast().getData(), StandardCharsets.UTF_8), "known MMI service request"); + assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); + assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); + assertEquals("200", new String(replyWithoutRbac.pollLast().getData(), StandardCharsets.UTF_8), "known MMI service request"); } { // MMI service request: service should not exist final ZMsg replyWithoutRbac = clientSession.send(DEFAULT_MMI_SERVICE, DEFAULT_REQUEST_MESSAGE_BYTES); // w/o RBAC - Assertions.assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); - Assertions.assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); - Assertions.assertEquals("400", new String(replyWithoutRbac.pollLast().getData(), StandardCharsets.UTF_8), "unknown MMI service request"); + assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); + assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); + assertEquals("400", new String(replyWithoutRbac.pollLast().getData(), StandardCharsets.UTF_8), "unknown MMI service request"); } { // unknown service name final ZMsg replyWithoutRbac = clientSession.send("unknownService".getBytes(StandardCharsets.UTF_8), DEFAULT_REQUEST_MESSAGE_BYTES); // w/o RBAC - Assertions.assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); - Assertions.assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); - Assertions.assertEquals("501", new String(replyWithoutRbac.pollLast().getData()), "unknown service"); + assertNotNull(replyWithoutRbac, "reply message w/o RBAC token not being null"); + assertNotNull(replyWithoutRbac.peekLast(), "user-data not being null"); + assertEquals("501", new String(replyWithoutRbac.pollLast().getData()), "unknown service"); } broker.stopBroker(); @@ -226,7 +226,7 @@ public void basicASynchronousRequestReplyTest() throws IOException { // using simple synchronous client MajordomoClientV2 clientSession = new MajordomoClientV2("tcp://localhost:" + openPort); assertEquals(2500, clientSession.getTimeout()); - Assertions.assertDoesNotThrow(() -> clientSession.setTimeout(2000)); + assertDoesNotThrow(() -> clientSession.setTimeout(2000)); assertEquals(2000, clientSession.getTimeout()); // send bursts of 10 messages @@ -238,15 +238,15 @@ public void basicASynchronousRequestReplyTest() throws IOException { // send bursts of 10 messages for (int i = 0; i < 10; i++) { final ZMsg reply = clientSession.recv(); - Assertions.assertNotNull(reply, "reply message w/o RBAC token not being null"); - Assertions.assertNotNull(reply.peekLast(), "user-data not being null"); - Assertions.assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, reply.getLast().getData()); + assertNotNull(reply, "reply message w/o RBAC token not being null"); + assertNotNull(reply.peekLast(), "user-data not being null"); + assertArrayEquals(DEFAULT_REQUEST_MESSAGE_BYTES, reply.getLast().getData()); counter.getAndIncrement(); } }).start(); Awaitility.await().alias("wait for reply messages").atMost(1, TimeUnit.SECONDS).until(counter::get, Matchers.equalTo(10)); - Assertions.assertEquals(10, counter.get(), "received expected number of replies"); + assertEquals(10, counter.get(), "received expected number of replies"); broker.stopBroker(); } diff --git a/core/src/main/java/io/opencmw/EventStore.java b/core/src/main/java/io/opencmw/EventStore.java index 148155f6..90e52879 100644 --- a/core/src/main/java/io/opencmw/EventStore.java +++ b/core/src/main/java/io/opencmw/EventStore.java @@ -277,7 +277,7 @@ public final LocalEventHandlerGroup then(final Predicate filter } public static class EventStoreFactory { - private boolean isSingleProducer = false; + private boolean singleProducer = false; private int maxThreadNumber = 4; private int ringbufferSize = 64; private int lengthHistoryBuffer = 10; @@ -291,7 +291,7 @@ public EventStore build() { if (muxBuilder == null) { muxBuilder = Cache.>builder().withLimit(lengthHistoryBuffer); } - return new EventStore(muxBuilder, muxCtxFunction, ringbufferSize, lengthHistoryBuffer, maxThreadNumber, isSingleProducer, waitStrategy, filterConfig); + return new EventStore(muxBuilder, muxCtxFunction, ringbufferSize, lengthHistoryBuffer, maxThreadNumber, singleProducer, waitStrategy, filterConfig); } public Class[] getFilterConfig() { @@ -376,11 +376,11 @@ public EventStoreFactory setWaitStrategy(final WaitStrategy waitStrategy) { } public boolean isSingleProducer() { - return isSingleProducer; + return singleProducer; } public EventStoreFactory setSingleProducer(final boolean singleProducer) { - isSingleProducer = singleProducer; + this.singleProducer = singleProducer; return this; } } @@ -422,7 +422,7 @@ public void onEvent(final RingBufferEvent event, final long sequence, final bool final RingBufferEvent result; try { result = callback.onEvent(history, eventStore, sequence, endOfBatch); - } catch (Exception e) { + } catch (Exception e) { // NOPMD - part of exception handling/forwarding scheme LOGGER.atError().setCause(e).addArgument(history.size()).addArgument(sequence).addArgument(endOfBatch) // .log("caught error for arguments (history={}, eventStore, sequence={}, endOfBatch={})"); event.throwables.add(e); diff --git a/core/src/main/java/io/opencmw/OpenCmwProtocol.java b/core/src/main/java/io/opencmw/OpenCmwProtocol.java index 42cfc616..b67525c1 100644 --- a/core/src/main/java/io/opencmw/OpenCmwProtocol.java +++ b/core/src/main/java/io/opencmw/OpenCmwProtocol.java @@ -360,6 +360,7 @@ public static MdpMessage receive(final Socket socket) { * @param wait setting the flag to ZMQ.DONTWAIT does a non-blocking recv. * @return MdpMessage if valid, or {@code null} otherwise */ + @SuppressWarnings("NPath.Complexity") public static MdpMessage receive(@NotNull final Socket socket, final boolean wait) { final int flags = wait ? 0 : ZMQ.DONTWAIT; final ZMsg msg = ZMsg.recvMsg(socket, flags); diff --git a/core/src/main/java/io/opencmw/RingBufferEvent.java b/core/src/main/java/io/opencmw/RingBufferEvent.java index 2ae9c266..bb9f05c7 100644 --- a/core/src/main/java/io/opencmw/RingBufferEvent.java +++ b/core/src/main/java/io/opencmw/RingBufferEvent.java @@ -17,6 +17,7 @@ import com.lmax.disruptor.EventHandler; +@SuppressWarnings("PMD.TooManyMethods") public class RingBufferEvent implements FilterPredicate, Cloneable { private final static Logger LOGGER = LoggerFactory.getLogger(RingBufferEvent.class); /** @@ -119,7 +120,7 @@ public final void clear() { if (payload != null) { payload.release(); } - payload = null; + payload = null; // NOPMD - null use on purpose (faster/easier than an Optional) } @Override diff --git a/core/src/main/java/io/opencmw/filter/EvtTypeFilter.java b/core/src/main/java/io/opencmw/filter/EvtTypeFilter.java index 1d979abf..ad35fb57 100644 --- a/core/src/main/java/io/opencmw/filter/EvtTypeFilter.java +++ b/core/src/main/java/io/opencmw/filter/EvtTypeFilter.java @@ -8,7 +8,7 @@ public class EvtTypeFilter implements Filter { public DataType evtType = DataType.UNKNOWN; public UpdateType updateType = UpdateType.UNKNOWN; - public String typeName = null; + public String typeName = ""; protected int hashCode = 0; @Override @@ -16,7 +16,7 @@ public void clear() { hashCode = 0; evtType = DataType.UNKNOWN; updateType = UpdateType.UNKNOWN; - typeName = null; + typeName = ""; } @Override diff --git a/core/src/main/java/io/opencmw/filter/TimingCtx.java b/core/src/main/java/io/opencmw/filter/TimingCtx.java index 1b5e1671..6bf20a7c 100644 --- a/core/src/main/java/io/opencmw/filter/TimingCtx.java +++ b/core/src/main/java/io/opencmw/filter/TimingCtx.java @@ -46,7 +46,7 @@ public void clear() { pid = -1; gid = -1; bpcts = -1; - ctxName = null; + ctxName = ""; } @Override diff --git a/core/src/main/java/io/opencmw/utils/AssertUtils.java b/core/src/main/java/io/opencmw/utils/AssertUtils.java deleted file mode 100644 index 7f5479c8..00000000 --- a/core/src/main/java/io/opencmw/utils/AssertUtils.java +++ /dev/null @@ -1,393 +0,0 @@ -package io.opencmw.utils; - -/** - * Utility class used to examine function parameters. All the methods throw IllegalArgumentException if the - * argument doesn't fulfil constraints. - * - * @author rstein - */ -public final class AssertUtils { - private static final String MUST_BE_GREATER_THAN_OR_EQUAL_TO_0 = " must be greater than or equal to 0!"; - private static final String MUST_BE_NON_EMPTY = " must be non-empty!"; - - private AssertUtils() { - } - - /** - * The method returns true if both values area equal. The method differs from simple == compare because it takes - * into account that both values can be Double.NaN, in which case == operator returns false. - * - * @param v1 to be checked - * @param v2 to be checked - * - * @return true if v1 and v2 are Double.NaN or v1 == v2. - */ - public static boolean areEqual(final double v1, final double v2) { - return (Double.isNaN(v1) && Double.isNaN(v2)) || (v1 == v2); - } - - /** - * Asserts if the specified object is an instance of the specified type. - * - * @param obj to be checked - * @param type required class type - * - * @throws IllegalArgumentException in case of problems - */ - public static void assertType(final Object obj, final Class type) { - if (!type.isInstance(obj)) { - throw new IllegalArgumentException( - "The argument has incorrect type. The correct type is " + type.getName()); - } - } - - public static void belongsToEnum(final String name, final int[] allowedElements, final int value) { - for (final int allowedElement : allowedElements) { - if (value == allowedElement) { - return; - } - } - throw new IllegalArgumentException("The " + name + " has incorrect value!"); - } - - public static void checkArrayDimension(final String name, final boolean[] array, final int defaultLength) { - AssertUtils.notNull(name, array); - AssertUtils.nonEmptyArray(name, array); - if (array.length != defaultLength) { - throw new IllegalArgumentException("The " + name + " boolean array must have a length of " + defaultLength); - } - } - - public static void checkArrayDimension(final String name, final byte[] array, final int defaultLength) { - AssertUtils.notNull(name, array); - AssertUtils.nonEmptyArray(name, array); - if (array.length != defaultLength) { - throw new IllegalArgumentException("The " + name + " byte array must have a length of " + defaultLength); - } - } - - public static void checkArrayDimension(final String name, final double[] array, final int defaultLength) { - AssertUtils.notNull(name, array); - AssertUtils.nonEmptyArray(name, array); - if (array.length != defaultLength) { - throw new IllegalArgumentException("The " + name + " double array must have a length of " + defaultLength); - } - } - - public static void checkArrayDimension(final String name, final float[] array, final int defaultLength) { - AssertUtils.notNull(name, array); - AssertUtils.nonEmptyArray(name, array); - if (array.length != defaultLength) { - throw new IllegalArgumentException("The " + name + " float array must have a length of " + defaultLength); - } - } - - public static void checkArrayDimension(final String name, final int[] array, final int defaultLength) { - AssertUtils.notNull(name, array); - AssertUtils.nonEmptyArray(name, array); - if (array.length != defaultLength) { - throw new IllegalArgumentException("The " + name + " int array must have a length of " + defaultLength); - } - } - - /** - * Asserts that the specified arrays have the same length. - * - * @param generics object to be checked - * - * @param array1 to be checked - * @param array2 to be checked - */ - public static void equalArrays(final T[] array1, final T[] array2) { - if (array1.length != array2.length) { - throw new IllegalArgumentException("The double arrays must have the same length!"); - } - } - - /** - * Asserts that the specified arrays have the same length. - * - * @param array1 to be checked - * @param array2 to be checked - */ - public static void equalDoubleArrays(final double[] array1, final double[] array2) { - if (array1.length != array2.length) { - throw new IllegalArgumentException("The double arrays must have the same length! length1 = " + array1.length - + " vs. length2 = " + array2.length); - } - } - - /** - * Asserts that the specified arrays have the same length or are at least min size. - * - * @param array1 to be checked - * @param array2 to be checked - * @param nMinSize minimum required size - */ - public static void equalDoubleArrays(final double[] array1, final double[] array2, final int nMinSize) { - final int length1 = Math.min(nMinSize, array1.length); - final int length2 = Math.min(nMinSize, array2.length); - if (length1 != length2) { - throw new IllegalArgumentException("The double arrays must have the same length! length1 = " + array1.length - + " vs. length2 = " + array2.length + " (nMinSize = " + nMinSize + ")"); - } - } - - /** - * Asserts that the specified arrays have the same length. - * - * @param array1 to be checked - * @param array2 to be checked - */ - public static void equalFloatArrays(final float[] array1, final float[] array2) { - if (array1.length != array2.length) { - throw new IllegalArgumentException("The float arrays must have the same length! length1 = " + array1.length - + " vs. length2 = " + array2.length); - } - } - - /** - * Asserts that the specified arrays have the same length or are at least min size. - * - * @param array1 to be checked - * @param array2 to be checked - * @param nMinSize minimum required size - */ - public static void equalFloatArrays(final float[] array1, final float[] array2, final int nMinSize) { - final int length1 = Math.min(nMinSize, array1.length); - final int length2 = Math.min(nMinSize, array2.length); - if (length1 != length2) { - throw new IllegalArgumentException("The double arrays must have the same length! length1 = " + array1.length - + " vs. length2 = " + array2.length + " (nMinSize = " + nMinSize + ")"); - } - } - - /** - * Checks if the int value is >= 0 - * - * @param name name to be included in the exception message - * @param value to be checked - */ - public static void gtEqThanZero(final String name, final double value) { - if (value < 0) { - throw new IllegalArgumentException("The " + name + MUST_BE_GREATER_THAN_OR_EQUAL_TO_0); - } - } - - /** - * Checks if the int value is >= 0 - * - * @param name name to be included in the exception message - * @param value to be checked - */ - public static void gtEqThanZero(final String name, final int value) { - if (value < 0) { - throw new IllegalArgumentException("The " + name + MUST_BE_GREATER_THAN_OR_EQUAL_TO_0); - } - } - - /** - * Checks if the value is >= 0 - * - * @param generics object to be checked - * - * @param name name to be included in the exception message - * @param value to be checked - */ - public static void gtEqThanZero(final String name, final T value) { - if (value.doubleValue() < 0) { - throw new IllegalArgumentException("The " + name + MUST_BE_GREATER_THAN_OR_EQUAL_TO_0); - } - } - - /** - * Checks if the int value is >= 0 - * - * @param name name to be included in the exception message - * @param value to be checked - */ - public static void gtThanZero(final String name, final int value) { - if (value <= 0) { - throw new IllegalArgumentException("The " + name + " must be greater than 0!"); - } - } - - /** - * Checks if the value is >= 0 - * - * @param generics object to be checked - * - * @param name name to be included in the exception message - * @param value to be checked - */ - public static void gtThanZero(final String name, final T value) { - if (value.doubleValue() <= 0) { - throw new IllegalArgumentException("The " + name + " must be greater than 0!"); - } - } - - /** - * Checks if the index is >= 0 and < bounds - * - * @param index index to be checked - * @param bounds maximum bound - */ - public static void indexInBounds(final int index, final int bounds) { - AssertUtils.indexInBounds(index, bounds, "The index is out of bounds: 0 <= " + index + " < " + bounds); - } - - /** - * Checks if the index is >= 0 and < bounds - * - * @param index index to be checked - * @param bounds maximum bound - * @param message exception message - */ - public static void indexInBounds(final int index, final int bounds, final String message) { - if ((index < 0) || (index >= bounds)) { - throw new IndexOutOfBoundsException(message); - } - } - - /** - * Checks if the index1 <= index2 - * - * @param index1 index1 to be checked - * @param index2 index1 to be checked - * @param msg exception message - */ - public static void indexOrder(final int index1, final int index2, final String msg) { - if (index1 > index2) { - throw new IndexOutOfBoundsException(msg); - } - } - - /** - * Checks if the index1 <= index2 - * - * @param index1 index1 to be checked - * @param name1 name of index1 - * @param index2 index1 to be checked - * @param name2 name of index2 - */ - public static void indexOrder(final int index1, final String name1, final int index2, final String name2) { - if (index1 > index2) { - throw new IndexOutOfBoundsException( - "Index " + name1 + "(" + index1 + ") is greated than index " + name2 + "(" + index2 + ")"); - } - } - - /** - * Checks if the variable is less or equal than the reference - * - * @param name name to be included in exception message. - * @param ref reference - * @param len object to be checked - */ - public static void gtOrEqual(final String name, final double ref, final double len) { - if (len < ref) { - throw new IllegalArgumentException("The " + name + " len = '" + len + "' must be less or equal than " + ref); - } - } - - /** - * Checks if the variable is less or equal than the reference - * - * @param name name to be included in exception message. - * @param ref reference - * @param len object to be checked - */ - public static void gtOrEqual(final String name, final float ref, final float len) { - if (len < ref) { - throw new IllegalArgumentException("The " + name + " len = '" + len + "' must be less or equal than " + ref); - } - } - - /** - * Checks if the variable is greater or equal than the reference - * - * @param name name to be included in exception message. - * @param ref reference - * @param len object to be checked - */ - public static void gtOrEqual(final String name, final int ref, final int len) { - if (len < ref) { - throw new IllegalArgumentException("The " + name + " len = '" + len + "' must be greater or equal than " + ref); - } - } - - /** - * Checks if the variable is less or equal than the reference - * - * @param name name to be included in exception message. - * @param ref reference - * @param len object to be checked - */ - public static void gtOrEqual(final String name, final long ref, final long len) { - if (len < ref) { - throw new IllegalArgumentException("The " + name + " len = '" + len + "' must be less or equal than " + ref); - } - } - - public static void nonEmptyArray(final String name, final boolean[] array) { - AssertUtils.notNull(name, array); - if (array.length == 0) { - throw new IllegalArgumentException("The " + name + MUST_BE_NON_EMPTY); - } - } - - public static void nonEmptyArray(final String name, final byte[] array) { - AssertUtils.notNull(name, array); - if (array.length == 0) { - throw new IllegalArgumentException("The " + name + MUST_BE_NON_EMPTY); - } - } - - public static void nonEmptyArray(final String name, final double[] array) { - AssertUtils.notNull(name, array); - if (array.length == 0) { - throw new IllegalArgumentException("The " + name + MUST_BE_NON_EMPTY); - } - } - - public static void nonEmptyArray(final String name, final float[] array) { - AssertUtils.notNull(name, array); - if (array.length == 0) { - throw new IllegalArgumentException("The " + name + MUST_BE_NON_EMPTY); - } - } - - public static void nonEmptyArray(final String name, final int[] array) { - AssertUtils.notNull(name, array); - if (array.length == 0) { - throw new IllegalArgumentException("The " + name + MUST_BE_NON_EMPTY); - } - } - - public static void nonEmptyArray(final String name, final Object[] array) { - AssertUtils.notNull(name, array); - if (array.length == 0) { - throw new IllegalArgumentException("The " + name + MUST_BE_NON_EMPTY); - } - - for (final Object element : array) { - if (element == null) { - throw new NullPointerException("Elements of the " + name + " must be non-null!"); // #NOPMD - } - } - } - - /** - * Checks if the object is not null. - * - * @param generics object to be checked - * - * @param name name to be included in exception message. - * @param obj object to be checked - */ - public static void notNull(final String name, final T obj) { - if (obj == null) { - throw new IllegalArgumentException("The " + name + " must be non-null!"); - } - } -} \ No newline at end of file diff --git a/core/src/main/java/io/opencmw/utils/Cache.java b/core/src/main/java/io/opencmw/utils/Cache.java index c050388d..e8ad468d 100644 --- a/core/src/main/java/io/opencmw/utils/Cache.java +++ b/core/src/main/java/io/opencmw/utils/Cache.java @@ -78,6 +78,7 @@ * @param search key * @param cached value */ +@SuppressWarnings({ "PMD.DoNotUseThreads", "PMD.TooManyMethods" }) // thread use necessary for maintenance tasks, methods due to Map interface public class Cache implements Map { private final ConcurrentHashMap dataCache; private final ConcurrentHashMap timeOutMap; diff --git a/core/src/test/java/io/opencmw/filter/EvtTypeFilterTests.java b/core/src/test/java/io/opencmw/filter/EvtTypeFilterTests.java index 1afb27eb..28c00f56 100644 --- a/core/src/test/java/io/opencmw/filter/EvtTypeFilterTests.java +++ b/core/src/test/java/io/opencmw/filter/EvtTypeFilterTests.java @@ -69,7 +69,8 @@ void predicateTsts() { } private static void assertInitialised(final EvtTypeFilter evtTypeFilter) { - assertNull(evtTypeFilter.typeName); + assertNotNull(evtTypeFilter.typeName); + assertTrue(evtTypeFilter.typeName.isBlank()); assertEquals(EvtTypeFilter.DataType.UNKNOWN, evtTypeFilter.evtType); assertEquals(0, evtTypeFilter.hashCode); } diff --git a/serialiser/src/main/java/io/opencmw/serialiser/IoClassSerialiser.java b/serialiser/src/main/java/io/opencmw/serialiser/IoClassSerialiser.java index 6fed8b5b..616c0968 100644 --- a/serialiser/src/main/java/io/opencmw/serialiser/IoClassSerialiser.java +++ b/serialiser/src/main/java/io/opencmw/serialiser/IoClassSerialiser.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -40,13 +39,14 @@ * * @author rstein */ +@SuppressWarnings("PMD.TooManyMethods") public class IoClassSerialiser { private static final Logger LOGGER = LoggerFactory.getLogger(IoClassSerialiser.class); public static final String UNCHECKED_CAST_SUPPRESSION = "unchecked"; private static final Map> CLASS_CONSTRUCTOR_MAP = new ConcurrentHashMap<>(); protected final List ioSerialisers = new ArrayList<>(); - private final Map>> classMap = new HashMap<>(); - private final Map cachedFieldMatch = new HashMap<>(); + private final Map>> classMap = new ConcurrentHashMap<>(); + private final Map cachedFieldMatch = new ConcurrentHashMap<>(); protected IoSerialiser matchedIoSerialiser; protected IoBuffer dataBuffer; protected Consumer startMarkerFunction; @@ -71,9 +71,9 @@ public IoClassSerialiser(final IoBuffer ioBuffer, final Class 0) { - setMatchedIoSerialiser(ioSerialiserTypeClass[0]); + setMatchedIoSerialiser(ioSerialiserTypeClass[0]); // NOPMD } else { - setMatchedIoSerialiser(ioSerialisers.get(0)); + setMatchedIoSerialiser(ioSerialisers.get(0)); // NOPMD } // register primitive and boxed data type handlers @@ -228,7 +228,7 @@ public void finaliseBuffer(ByteArrayCache arrayCache) { for (IoSerialiser serialiser : ioSerialisers) { serialiser.setBuffer(null); } - } catch (Exception e) { + } catch (Exception e) { // NOPMD // do nothing } } @@ -337,6 +337,7 @@ public WireDataFieldDescription parseWireFormat() { return matchedIoSerialiser.parseIoStream(true); } + @SuppressWarnings("PMD.NPathComplexity") public void serialiseObject(final Object rootObj, final ClassFieldDescription classField, final int recursionDepth) { final FieldSerialiser existingSerialiser = classField.getFieldSerialiser(); final FieldSerialiser fieldSerialiser = existingSerialiser == null ? cacheFindFieldSerialiser(classField.getType(), classField.getActualTypeArguments()) : existingSerialiser; diff --git a/serialiser/src/main/java/io/opencmw/serialiser/IoSerialiser.java b/serialiser/src/main/java/io/opencmw/serialiser/IoSerialiser.java index 2e6d1c09..2f9a7ce9 100644 --- a/serialiser/src/main/java/io/opencmw/serialiser/IoSerialiser.java +++ b/serialiser/src/main/java/io/opencmw/serialiser/IoSerialiser.java @@ -11,6 +11,7 @@ import io.opencmw.serialiser.spi.ProtocolInfo; import io.opencmw.serialiser.spi.WireDataFieldDescription; +@SuppressWarnings({ "PMD.TooManyMethods", "PMD.ExcessivePublicCount" }) // unavoidable since Java does not support templates (issue: primitive types) public interface IoSerialiser { /** * Reads and checks protocol header information. diff --git a/serialiser/src/main/java/io/opencmw/serialiser/spi/BinarySerialiser.java b/serialiser/src/main/java/io/opencmw/serialiser/spi/BinarySerialiser.java index 5f765092..505168db 100644 --- a/serialiser/src/main/java/io/opencmw/serialiser/spi/BinarySerialiser.java +++ b/serialiser/src/main/java/io/opencmw/serialiser/spi/BinarySerialiser.java @@ -401,6 +401,7 @@ public String getEnumTypeList() { } @Override + @SuppressWarnings("PMD.NPathComplexity") public WireDataFieldDescription getFieldHeader() { final int headerStart = buffer.position(); final byte dataTypeByte = buffer.getByte(); @@ -670,6 +671,7 @@ public Queue getQueue(final Queue collection) { } @Override + @SuppressWarnings("PMD.NPathComplexity") public Set getSet(final Set collection) { getArraySizeDescriptor(); final int nElements = buffer.getInt(); diff --git a/serialiser/src/main/java/io/opencmw/serialiser/spi/ByteBuffer.java b/serialiser/src/main/java/io/opencmw/serialiser/spi/ByteBuffer.java index b2c8d2bf..7fd6ea46 100644 --- a/serialiser/src/main/java/io/opencmw/serialiser/spi/ByteBuffer.java +++ b/serialiser/src/main/java/io/opencmw/serialiser/spi/ByteBuffer.java @@ -9,6 +9,7 @@ /** * @author rstein */ +@SuppressWarnings({ "PMD.TooManyMethods", "PMD.ExcessivePublicCount" }) // unavoidable: each primitive type needs to handled individually (no templates) public class ByteBuffer implements IoBuffer { public static final int SIZE_OF_BOOLEAN = 1; public static final int SIZE_OF_BYTE = 1; diff --git a/serialiser/src/main/java/io/opencmw/serialiser/spi/ClassFieldDescription.java b/serialiser/src/main/java/io/opencmw/serialiser/spi/ClassFieldDescription.java index 48744eb2..96d3f3c3 100644 --- a/serialiser/src/main/java/io/opencmw/serialiser/spi/ClassFieldDescription.java +++ b/serialiser/src/main/java/io/opencmw/serialiser/spi/ClassFieldDescription.java @@ -32,6 +32,7 @@ /** * @author rstein */ +@SuppressWarnings("PMD.ExcessivePublicCount") // utility class for safe reflection handling public class ClassFieldDescription implements FieldDescription { private static final Logger LOGGER = LoggerFactory.getLogger(ClassFieldDescription.class); private final int hierarchyDepth; @@ -65,9 +66,9 @@ public class ClassFieldDescription implements FieldDescription { private final boolean modStrict; private final boolean modInterface; // additional qualities - private final boolean isprimitive; - private final boolean isclass; - private final boolean isEnum; + private final boolean isPrimitiveType; + private final boolean isClassType; + private final boolean isEnumType; private final List enumDefinitions; private final boolean serializable; private String toStringName; // computed on demand and cached @@ -155,10 +156,10 @@ protected ClassFieldDescription(final Class referenceClass, final Field field modInterface = classType.isInterface(); // additional fields - isprimitive = classType.isPrimitive(); - isclass = !isprimitive && !modInterface; - isEnum = Enum.class.isAssignableFrom(classType); - if (isEnum) { + isPrimitiveType = classType.isPrimitive(); + isClassType = !isPrimitiveType && !modInterface; + isEnumType = Enum.class.isAssignableFrom(classType); + if (isEnumType) { enumDefinitions = Collections.unmodifiableList(Arrays.asList(classType.getEnumConstants())); } else { enumDefinitions = Collections.emptyList(); @@ -503,14 +504,14 @@ public boolean isAnnotationPresent() { * @return the isClass */ public boolean isClass() { - return isclass; + return isClassType; } /** * @return whether class is an Enum type */ public boolean isEnum() { - return isEnum; + return isEnumType; } /** @@ -545,7 +546,7 @@ public boolean isNative() { * @return {@code true} if the class field is a primitive type (ie. boolean, byte, ..., int, float, double) */ public boolean isPrimitive() { - return isprimitive; + return isPrimitiveType; } /** diff --git a/serialiser/src/main/java/io/opencmw/serialiser/spi/FastByteBuffer.java b/serialiser/src/main/java/io/opencmw/serialiser/spi/FastByteBuffer.java index 93ab6933..e19fc2d6 100644 --- a/serialiser/src/main/java/io/opencmw/serialiser/spi/FastByteBuffer.java +++ b/serialiser/src/main/java/io/opencmw/serialiser/spi/FastByteBuffer.java @@ -11,7 +11,7 @@ import io.opencmw.serialiser.utils.AssertUtils; import io.opencmw.serialiser.utils.ByteArrayCache; -import sun.misc.Unsafe; +import sun.misc.Unsafe; // NOPMD - there is still nothing better under the Sun // import static jdk.internal.misc.Unsafe; // NOPMD by rstein TODO replaces sun in JDK11 @@ -35,7 +35,7 @@ * * @author rstein */ -@SuppressWarnings("restriction") +@SuppressWarnings({ "restriction", "PMD.TooManyMethods", "PMD.ExcessivePublicCount" }) // unavoidable: each primitive type needs to handled individually (no templates) public class FastByteBuffer implements IoBuffer { public static final int SIZE_OF_BOOLEAN = 1; public static final int SIZE_OF_BYTE = 1; @@ -62,16 +62,16 @@ public class FastByteBuffer implements IoBuffer { unsafe = (Unsafe) field.get(null); unsafe.putObjectVolatile(cls, unsafe.staticFieldOffset(logger), null); - } catch (NoSuchFieldException | SecurityException | IllegalAccessException | ClassNotFoundException e) { + } catch (NoSuchFieldException | SecurityException | IllegalAccessException | ClassNotFoundException e) { // NOPMD throw new SecurityException(e); // NOPMD } } - private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final ReadWriteLock internalLock = new ReentrantReadWriteLock(); private final StringBuilder builder = new StringBuilder(100); private ByteArrayCache byteArrayCache; - private int position; - private int limit; + private int intPos; + private int intLimit; private byte[] buffer; private boolean enforceSimpleStringEncoding = false; private boolean autoResize; @@ -94,8 +94,8 @@ public FastByteBuffer(final byte[] buffer, final int limit) { throw new IllegalArgumentException(String.format("limit %d >= capacity %d", limit, buffer.length)); } this.buffer = buffer; - this.limit = limit; - position = 0; + this.intLimit = limit; + intPos = 0; } /** @@ -117,8 +117,8 @@ public FastByteBuffer(final int size) { public FastByteBuffer(final int size, final boolean autoResize, final ByteArrayCache byteArrayCache) { AssertUtils.gtEqThanZero("size", size); buffer = new byte[size]; - position = 0; - limit = buffer.length; + intPos = 0; + intLimit = buffer.length; this.autoResize = autoResize; this.byteArrayCache = byteArrayCache; } @@ -129,21 +129,21 @@ public int capacity() { } public void checkAvailable(final int bytes) { - if (position + bytes > limit) { - throw new IndexOutOfBoundsException("read unavailable " + bytes + " bytes at position " + position + " (limit: " + limit + ")"); + if (intPos + bytes > intLimit) { + throw new IndexOutOfBoundsException("read unavailable " + bytes + " bytes at position " + intPos + " (limit: " + intLimit + ")"); } } public void checkAvailableAbsolute(final int position) { - if (position > limit) { - throw new IndexOutOfBoundsException("read unavailable bytes at end position " + position + " (limit: " + limit + ")"); + if (position > intLimit) { + throw new IndexOutOfBoundsException("read unavailable bytes at end position " + position + " (limit: " + intLimit + ")"); } } @Override public void clear() { - position = 0; - limit = capacity(); + intPos = 0; + intLimit = capacity(); } @Override @@ -161,8 +161,8 @@ public void ensureCapacity(final int newCapacity) { if (newCapacity <= capacity()) { return; } - if (position > capacity()) { // invalid state, should never occur - throw new IllegalStateException("position " + position + " is beyond buffer capacity " + capacity()); + if (intPos > capacity()) { // invalid state, should never occur + throw new IllegalStateException("position " + intPos + " is beyond buffer capacity " + capacity()); } if (!autoResize) { throw new IndexOutOfBoundsException("required capacity: " + newCapacity + " out of bounds: " + capacity() + "and autoResize is disabled"); @@ -175,8 +175,8 @@ public void ensureCapacity(final int newCapacity) { @Override public void flip() { - limit = position; - position = 0; + intLimit = intPos; + intPos = 0; } /** @@ -188,25 +188,25 @@ public void flip() { @Override public void forceCapacity(final int length, final int preserve) { if (length == capacity()) { - limit = length; + intLimit = length; return; } final byte[] newBuffer = byteArrayCache == null ? new byte[length] : byteArrayCache.getArray(length); final int bytesToCopy = preserve * SIZE_OF_BYTE; copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET, newBuffer, ARRAY_BYTE_BASE_OFFSET, bytesToCopy); - position = Math.min(position, newBuffer.length); + intPos = Math.min(intPos, newBuffer.length); if (byteArrayCache != null) { byteArrayCache.add(buffer); } buffer = newBuffer; - limit = buffer.length; + intLimit = buffer.length; } @Override public boolean getBoolean() { // NOPMD by rstein checkAvailable(SIZE_OF_BOOLEAN); - final boolean value = unsafe.getBoolean(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position); - position += SIZE_OF_BOOLEAN; + final boolean value = unsafe.getBoolean(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos); + intPos += SIZE_OF_BOOLEAN; return value; } @@ -224,8 +224,8 @@ public boolean[] getBooleanArray(final boolean[] dst, final int length) { final boolean[] values = initNeeded ? new boolean[arraySize] : dst; checkAvailable(arraySize * SIZE_OF_BOOLEAN); - copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + position, values, ARRAY_BOOLEAN_BASE_OFFSET, arraySize); - position += arraySize; + copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + intPos, values, ARRAY_BOOLEAN_BASE_OFFSET, arraySize); + intPos += arraySize; return values; } @@ -233,8 +233,8 @@ public boolean[] getBooleanArray(final boolean[] dst, final int length) { @Override public byte getByte() { checkAvailable(SIZE_OF_BYTE); - final byte value = unsafe.getByte(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position); - position += SIZE_OF_BYTE; + final byte value = unsafe.getByte(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos); + intPos += SIZE_OF_BYTE; return value; } @@ -252,8 +252,8 @@ public byte[] getByteArray(final byte[] dst, final int length) { final byte[] values = initNeeded ? new byte[arraySize] : dst; checkAvailable(arraySize); - copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + position, values, ARRAY_BYTE_BASE_OFFSET, arraySize); - position += arraySize; + copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + intPos, values, ARRAY_BYTE_BASE_OFFSET, arraySize); + intPos += arraySize; return values; } @@ -265,8 +265,8 @@ public ByteArrayCache getByteArrayCache() { @Override public char getChar() { checkAvailable(SIZE_OF_CHAR); - final char value = unsafe.getChar(buffer, (long) ARRAY_CHAR_BASE_OFFSET + position); - position += SIZE_OF_CHAR; + final char value = unsafe.getChar(buffer, (long) ARRAY_CHAR_BASE_OFFSET + intPos); + intPos += SIZE_OF_CHAR; return value; } @@ -285,8 +285,8 @@ public char[] getCharArray(final char[] dst, final int length) { final int bytesToCopy = arraySize * SIZE_OF_CHAR; checkAvailable(bytesToCopy); - copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + position, values, ARRAY_SHORT_BASE_OFFSET, bytesToCopy); - position += bytesToCopy; + copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + intPos, values, ARRAY_SHORT_BASE_OFFSET, bytesToCopy); + intPos += bytesToCopy; return values; } @@ -294,8 +294,8 @@ public char[] getCharArray(final char[] dst, final int length) { @Override public double getDouble() { checkAvailable(SIZE_OF_DOUBLE); - final double value = unsafe.getDouble(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position); - position += SIZE_OF_DOUBLE; + final double value = unsafe.getDouble(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos); + intPos += SIZE_OF_DOUBLE; return value; } @@ -314,8 +314,8 @@ public double[] getDoubleArray(final double[] dst, final int length) { final int bytesToCopy = arraySize * SIZE_OF_DOUBLE; checkAvailable(bytesToCopy); - copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + position, values, ARRAY_DOUBLE_BASE_OFFSET, bytesToCopy); - position += bytesToCopy; + copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + intPos, values, ARRAY_DOUBLE_BASE_OFFSET, bytesToCopy); + intPos += bytesToCopy; return values; } @@ -323,8 +323,8 @@ public double[] getDoubleArray(final double[] dst, final int length) { @Override public float getFloat() { checkAvailable(SIZE_OF_FLOAT); - final float value = unsafe.getFloat(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position); - position += SIZE_OF_FLOAT; + final float value = unsafe.getFloat(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos); + intPos += SIZE_OF_FLOAT; return value; } @@ -343,8 +343,8 @@ public float[] getFloatArray(final float[] dst, final int length) { final int bytesToCopy = arraySize * SIZE_OF_FLOAT; checkAvailable(bytesToCopy); - copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + position, values, ARRAY_FLOAT_BASE_OFFSET, bytesToCopy); - position += bytesToCopy; + copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + intPos, values, ARRAY_FLOAT_BASE_OFFSET, bytesToCopy); + intPos += bytesToCopy; return values; } @@ -352,8 +352,8 @@ public float[] getFloatArray(final float[] dst, final int length) { @Override public int getInt() { checkAvailable(SIZE_OF_INT); - final int value = unsafe.getInt(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position); - position += SIZE_OF_INT; + final int value = unsafe.getInt(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos); + intPos += SIZE_OF_INT; return value; } @@ -372,8 +372,8 @@ public int[] getIntArray(final int[] dst, final int length) { final int bytesToCopy = arraySize * SIZE_OF_INT; checkAvailable(bytesToCopy); - copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + position, values, ARRAY_INT_BASE_OFFSET, bytesToCopy); - position += bytesToCopy; + copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + intPos, values, ARRAY_INT_BASE_OFFSET, bytesToCopy); + intPos += bytesToCopy; return values; } @@ -381,8 +381,8 @@ public int[] getIntArray(final int[] dst, final int length) { @Override public long getLong() { checkAvailable(SIZE_OF_LONG); - final long value = unsafe.getLong(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position); - position += SIZE_OF_LONG; + final long value = unsafe.getLong(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos); + intPos += SIZE_OF_LONG; return value; } @@ -401,8 +401,8 @@ public long[] getLongArray(final long[] dst, final int length) { final int bytesToCopy = arraySize * SIZE_OF_LONG; checkAvailable(bytesToCopy); - copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + position, values, ARRAY_LONG_BASE_OFFSET, bytesToCopy); - position += bytesToCopy; + copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + intPos, values, ARRAY_LONG_BASE_OFFSET, bytesToCopy); + intPos += bytesToCopy; return values; } @@ -410,8 +410,8 @@ public long[] getLongArray(final long[] dst, final int length) { @Override public short getShort() { // NOPMD by rstein checkAvailable(SIZE_OF_SHORT); - final short value = unsafe.getShort(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position); // NOPMD - position += SIZE_OF_SHORT; + final short value = unsafe.getShort(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos); // NOPMD + intPos += SIZE_OF_SHORT; return value; } @@ -430,8 +430,8 @@ public short[] getShortArray(final short[] dst, final int length) { // NOPMD by final int bytesToCopy = arraySize * SIZE_OF_SHORT; checkAvailable(bytesToCopy); - copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + position, values, ARRAY_SHORT_BASE_OFFSET, bytesToCopy); - position += bytesToCopy; + copyMemory(buffer, ARRAY_BYTE_BASE_OFFSET + intPos, values, ARRAY_SHORT_BASE_OFFSET, bytesToCopy); + intPos += bytesToCopy; return values; } @@ -444,9 +444,9 @@ public String getString() { final int arraySize = getInt(); // for C++ zero terminated string checkAvailable(arraySize); // alt: final String str = new String(buffer, position, arraySize - 1, StandardCharsets.UTF_8) - decodeUTF8(buffer, position, arraySize - 1, builder); + decodeUTF8(buffer, intPos, arraySize - 1, builder); - position += arraySize; // N.B. +1 larger to be compatible with C++ zero terminated string + intPos += arraySize; // N.B. +1 larger to be compatible with C++ zero terminated string // alt: return str return builder.toString(); } @@ -477,9 +477,9 @@ public String getStringISO8859() { final int arraySize = getInt(); // for C++ zero terminated string checkAvailable(arraySize); //alt safe-fallback final String str = new String(buffer, position, arraySize - 1, StandardCharsets.ISO_8859_1) - final String str = new String(buffer, 0, position, arraySize - 1); // NOSONAR NOPMD fastest alternative that is public API + final String str = new String(buffer, 0, intPos, arraySize - 1); // NOSONAR NOPMD fastest alternative that is public API // final String str = FastStringBuilder.iso8859BytesToString(buffer, position, arraySize - 1) - position += arraySize; // N.B. +1 larger to be compatible with C++ zero terminated string + intPos += arraySize; // N.B. +1 larger to be compatible with C++ zero terminated string return str; } @@ -507,43 +507,43 @@ public boolean isReadOnly() { @Override public int limit() { - return limit; + return intLimit; } @Override public void limit(final int newLimit) { if ((newLimit > capacity()) || (newLimit < 0)) { - throw new IllegalArgumentException(String.format("invalid newLimit: [0, position: %d, newLimit:%d, %d]", position, newLimit, capacity())); + throw new IllegalArgumentException(String.format("invalid newLimit: [0, position: %d, newLimit:%d, %d]", intPos, newLimit, capacity())); } - limit = newLimit; - if (position > limit) { - position = limit; + intLimit = newLimit; + if (intPos > intLimit) { + intPos = intLimit; } } @Override public ReadWriteLock lock() { - return lock; + return internalLock; } @Override public int position() { - return position; + return intPos; } @Override public void position(final int newPosition) { - if ((newPosition > limit) || (newPosition < 0) || (newPosition > capacity())) { - throw new IllegalArgumentException(String.format("invalid newPosition: %d vs. [0, position=%d, limit:%d, capacity:%d]", newPosition, position, limit, capacity())); + if ((newPosition > intLimit) || (newPosition < 0) || (newPosition > capacity())) { + throw new IllegalArgumentException(String.format("invalid newPosition: %d vs. [0, position=%d, limit:%d, capacity:%d]", newPosition, intPos, intLimit, capacity())); } - position = newPosition; + intPos = newPosition; } @Override public void putBoolean(final boolean value) { ensureAdditionalCapacity(SIZE_OF_BOOLEAN); - unsafe.putBoolean(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position, value); - position += SIZE_OF_BOOLEAN; + unsafe.putBoolean(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos, value); + intPos += SIZE_OF_BOOLEAN; } @Override @@ -558,15 +558,15 @@ public void putBooleanArray(final boolean[] values, final int n) { final int nElements = n >= 0 ? Math.min(n, valuesSize) : valuesSize; ensureAdditionalCapacity(nElements); putInt(nElements); // strided-array size - copyMemory(values, ARRAY_BOOLEAN_BASE_OFFSET, buffer, ARRAY_BYTE_BASE_OFFSET + position, nElements); - position += nElements; + copyMemory(values, ARRAY_BOOLEAN_BASE_OFFSET, buffer, ARRAY_BYTE_BASE_OFFSET + intPos, nElements); + intPos += nElements; } @Override public void putByte(final byte value) { ensureAdditionalCapacity(SIZE_OF_BYTE); - unsafe.putByte(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position, value); - position += SIZE_OF_BYTE; + unsafe.putByte(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos, value); + intPos += SIZE_OF_BYTE; } @Override @@ -581,15 +581,15 @@ public void putByteArray(final byte[] values, final int n) { final int nElements = (n >= 0 ? Math.min(n, valuesSize) : valuesSize); ensureAdditionalCapacity(nElements + SIZE_OF_INT); putInt(nElements); // strided-array size - copyMemory(values, ARRAY_BOOLEAN_BASE_OFFSET, buffer, ARRAY_BYTE_BASE_OFFSET + position, nElements); - position += nElements; + copyMemory(values, ARRAY_BOOLEAN_BASE_OFFSET, buffer, ARRAY_BYTE_BASE_OFFSET + intPos, nElements); + intPos += nElements; } @Override public void putChar(final char value) { ensureAdditionalCapacity(SIZE_OF_CHAR); - unsafe.putChar(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position, value); - position += SIZE_OF_CHAR; + unsafe.putChar(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos, value); + intPos += SIZE_OF_CHAR; } @Override @@ -606,15 +606,15 @@ public void putCharArray(final char[] values, final int n) { final int bytesToCopy = nElements * SIZE_OF_CHAR; ensureAdditionalCapacity(bytesToCopy + SIZE_OF_INT); putInt(nElements); // strided-array size - copyMemory(values, arrayOffset, buffer, arrayOffset + position, bytesToCopy); - position += bytesToCopy; + copyMemory(values, arrayOffset, buffer, arrayOffset + intPos, bytesToCopy); + intPos += bytesToCopy; } @Override public void putDouble(final double value) { ensureAdditionalCapacity(SIZE_OF_DOUBLE); - unsafe.putDouble(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position, value); - position += SIZE_OF_DOUBLE; + unsafe.putDouble(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos, value); + intPos += SIZE_OF_DOUBLE; } @Override @@ -631,15 +631,15 @@ public void putDoubleArray(final double[] values, final int n) { final int bytesToCopy = nElements * SIZE_OF_DOUBLE; ensureAdditionalCapacity(bytesToCopy + SIZE_OF_INT); putInt(nElements); // strided-array size - copyMemory(values, arrayOffset, buffer, arrayOffset + position, bytesToCopy); - position += bytesToCopy; + copyMemory(values, arrayOffset, buffer, arrayOffset + intPos, bytesToCopy); + intPos += bytesToCopy; } @Override public void putFloat(final float value) { ensureAdditionalCapacity(SIZE_OF_FLOAT); - unsafe.putFloat(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position, value); - position += SIZE_OF_FLOAT; + unsafe.putFloat(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos, value); + intPos += SIZE_OF_FLOAT; } @Override @@ -656,15 +656,15 @@ public void putFloatArray(final float[] values, final int n) { final int bytesToCopy = nElements * SIZE_OF_FLOAT; ensureAdditionalCapacity(bytesToCopy + SIZE_OF_INT); putInt(nElements); // strided-array size - copyMemory(values, arrayOffset, buffer, arrayOffset + position, bytesToCopy); - position += bytesToCopy; + copyMemory(values, arrayOffset, buffer, arrayOffset + intPos, bytesToCopy); + intPos += bytesToCopy; } @Override public void putInt(final int value) { ensureAdditionalCapacity(SIZE_OF_INT); - unsafe.putInt(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position, value); - position += SIZE_OF_INT; + unsafe.putInt(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos, value); + intPos += SIZE_OF_INT; } @Override @@ -681,15 +681,15 @@ public void putIntArray(final int[] values, final int n) { final int bytesToCopy = nElements * SIZE_OF_INT; ensureAdditionalCapacity(bytesToCopy + SIZE_OF_INT); putInt(nElements); // strided-array size - copyMemory(values, arrayOffset, buffer, arrayOffset + position, bytesToCopy); - position += bytesToCopy; + copyMemory(values, arrayOffset, buffer, arrayOffset + intPos, bytesToCopy); + intPos += bytesToCopy; } @Override public void putLong(final long value) { ensureAdditionalCapacity(SIZE_OF_LONG); - unsafe.putLong(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position, value); - position += SIZE_OF_LONG; + unsafe.putLong(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos, value); + intPos += SIZE_OF_LONG; } @Override @@ -706,15 +706,15 @@ public void putLongArray(final long[] values, final int n) { final int bytesToCopy = nElements * SIZE_OF_LONG; ensureAdditionalCapacity(bytesToCopy + SIZE_OF_INT); putInt(nElements); // strided-array size - copyMemory(values, arrayOffset, buffer, arrayOffset + position, bytesToCopy); - position += bytesToCopy; + copyMemory(values, arrayOffset, buffer, arrayOffset + intPos, bytesToCopy); + intPos += bytesToCopy; } @Override public void putShort(final short value) { // NOPMD by rstein ensureAdditionalCapacity(SIZE_OF_SHORT); - unsafe.putShort(buffer, (long) ARRAY_BYTE_BASE_OFFSET + position, value); - position += SIZE_OF_SHORT; + unsafe.putShort(buffer, (long) ARRAY_BYTE_BASE_OFFSET + intPos, value); + intPos += SIZE_OF_SHORT; } @Override @@ -731,8 +731,8 @@ public void putShortArray(final short[] values, final int n) { // NOPMD by rstei final int bytesToCopy = nElements * SIZE_OF_SHORT; ensureAdditionalCapacity(bytesToCopy + SIZE_OF_INT); putInt(nElements); // strided-array size - copyMemory(values, arrayOffset, buffer, arrayOffset + position, bytesToCopy); - position += bytesToCopy; + copyMemory(values, arrayOffset, buffer, arrayOffset + intPos, bytesToCopy); + intPos += bytesToCopy; } @Override @@ -746,16 +746,16 @@ public void putString(final String string) { return; } final int utf16StringLength = string.length(); - final int initialPos = position; - position += SIZE_OF_INT; + final int initialPos = intPos; + intPos += SIZE_OF_INT; // write string-to-byte (in-place) ensureAdditionalCapacity(3 * utf16StringLength + SIZE_OF_INT); - final int strLength = encodeUTF8(string, buffer, position, 3 * utf16StringLength); - final int endPos = position + strLength; + final int strLength = encodeUTF8(string, buffer, intPos, 3 * utf16StringLength); + final int endPos = intPos + strLength; // write length of string byte representation putInt(initialPos, strLength + 1); - position = endPos; + intPos = endPos; putByte((byte) 0); // For C++ zero terminated string } @@ -772,7 +772,7 @@ public void putString(final int position, final String value) { public void putStringArray(final String[] values, final int n) { final int valuesSize = values == null ? 0 : values.length; final int nElements = n >= 0 ? Math.min(n, valuesSize) : valuesSize; - final int originalPos = position; // NOPMD + final int originalPos = intPos; // NOPMD putInt(nElements); // strided-array size if (values == null) { return; @@ -788,7 +788,7 @@ public void putStringArray(final String[] values, final int n) { putString(values[k]); } } catch (IndexOutOfBoundsException e) { - position = originalPos; // reset the position to the original position before any strings where added + intPos = originalPos; // reset the position to the original position before any strings where added throw e; // rethrow the exception } } @@ -799,29 +799,29 @@ public void putStringISO8859(final String string) { putStringISO8859(""); return; } - final int initialPos = position; - position += SIZE_OF_INT; + final int initialPos = intPos; + intPos += SIZE_OF_INT; // write string-to-byte (in-place) - final int strLength = encodeISO8859(string, buffer, position, string.length()); - final int endPos = position + strLength; + final int strLength = encodeISO8859(string, buffer, intPos, string.length()); + final int endPos = intPos + strLength; // write length of string byte representation - position = initialPos; + intPos = initialPos; putInt(strLength + 1); - position = endPos; + intPos = endPos; putByte((byte) 0); // For C++ zero terminated string } @Override public int remaining() { - return limit - position; + return intLimit - intPos; } @Override public void reset() { - position = 0; - limit = buffer.length; + intPos = 0; + intLimit = buffer.length; } /** @@ -842,7 +842,7 @@ public void setEnforceSimpleStringEncoding(final boolean state) { @Override public String toString() { - return super.toString() + String.format(" - [0, position=%d, limit:%d, capacity:%d]", position, limit, capacity()); + return super.toString() + String.format(" - [0, position=%d, limit:%d, capacity:%d]", intPos, intLimit, capacity()); } /** @@ -878,7 +878,7 @@ public void trim(final int requestedCapacity) { byteArrayCache.add(buffer); } buffer = newBuffer; - limit = newBuffer.length; + intLimit = newBuffer.length; } /** diff --git a/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/DataSetSerialiser.java b/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/DataSetSerialiser.java index 298fe1bf..dac052e6 100644 --- a/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/DataSetSerialiser.java +++ b/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/DataSetSerialiser.java @@ -308,7 +308,7 @@ protected void writeDataLabelsToStream(final DataSet dataSet) { } final int dataCount = dataSet.getDataCount(); - final Map labelMap = new HashMap<>(); + final Map labelMap = new HashMap<>(); // NOPMD - protected by lock and faster for (int index = 0; index < dataCount; index++) { final String label = dataSet.getDataLabel(index); if ((label != null) && !label.isEmpty()) { @@ -319,7 +319,7 @@ protected void writeDataLabelsToStream(final DataSet dataSet) { ioSerialiser.put(DATA_LABELS, labelMap, Integer.class, String.class); } - final Map styleMap = new HashMap<>(); + final Map styleMap = new HashMap<>(); // NOPMD - protected by lock and faster for (int index = 0; index < dataCount; index++) { final String style = dataSet.getStyle(index); if ((style != null) && !style.isEmpty()) { diff --git a/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/FieldCollectionsHelper.java b/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/FieldCollectionsHelper.java index f9773998..eecd634a 100644 --- a/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/FieldCollectionsHelper.java +++ b/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/FieldCollectionsHelper.java @@ -9,7 +9,7 @@ import io.opencmw.serialiser.IoClassSerialiser; import io.opencmw.serialiser.utils.ClassUtils; -public class FieldCollectionsHelper { +public final class FieldCollectionsHelper { private FieldCollectionsHelper() { // utility class } diff --git a/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/FieldMultiArrayHelper.java b/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/FieldMultiArrayHelper.java index ad71bcfa..d046844e 100644 --- a/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/FieldMultiArrayHelper.java +++ b/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/FieldMultiArrayHelper.java @@ -138,6 +138,7 @@ public static void put(final IoSerialiser serialiser, final FieldDescription * * @param serialiser for which the field serialisers should be registered */ + @SuppressWarnings("NPathComplexity") public static void register(final IoClassSerialiser serialiser) { serialiser.addClassDefinition(new FieldSerialiser<>( // (io, obj, field) -> field.getField().set(obj, getMultiArray(io, (MultiArray) field.getField().get(obj), field.getDataType())), // reader diff --git a/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/FieldPrimitiveValueHelper.java b/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/FieldPrimitiveValueHelper.java index e17e1c7c..a354f2f8 100644 --- a/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/FieldPrimitiveValueHelper.java +++ b/serialiser/src/main/java/io/opencmw/serialiser/spi/iobuffer/FieldPrimitiveValueHelper.java @@ -9,6 +9,8 @@ * @author rstein */ public final class FieldPrimitiveValueHelper { + public static final String UNSUPPORTED = "return function not supported for primitive types"; + private FieldPrimitiveValueHelper() { // utility class } @@ -21,55 +23,55 @@ private FieldPrimitiveValueHelper() { public static void register(final IoClassSerialiser serialiser) { serialiser.addClassDefinition(new FieldSerialiser<>( // (io, obj, field) -> field.getField().setBoolean(obj, io.getBoolean()), // reader - (io, obj, field) -> { throw new UnsupportedOperationException("return function not supported for primitive types"); }, // return + (io, obj, field) -> { throw new UnsupportedOperationException(UNSUPPORTED); }, // return (io, obj, field) -> io.put(field, field.getField().getBoolean(obj)), // writer boolean.class)); serialiser.addClassDefinition(new FieldSerialiser<>( // (io, obj, field) -> field.getField().setByte(obj, io.getByte()), // reader - (io, obj, field) -> { throw new UnsupportedOperationException("return function not supported for primitive types"); }, // return + (io, obj, field) -> { throw new UnsupportedOperationException(UNSUPPORTED); }, // return (io, obj, field) -> io.put(field, field.getField().getByte(obj)), // writer byte.class)); serialiser.addClassDefinition(new FieldSerialiser<>( // (io, obj, field) -> field.getField().setChar(obj, io.getChar()), // reader - (io, obj, field) -> { throw new UnsupportedOperationException("return function not supported for primitive types"); }, // return + (io, obj, field) -> { throw new UnsupportedOperationException(UNSUPPORTED); }, // return (io, obj, field) -> io.put(field, field.getField().getChar(obj)), // writer char.class)); serialiser.addClassDefinition(new FieldSerialiser<>( // (io, obj, field) -> field.getField().setShort(obj, io.getShort()), // reader - (io, obj, field) -> { throw new UnsupportedOperationException("return function not supported for primitive types"); }, // return + (io, obj, field) -> { throw new UnsupportedOperationException(UNSUPPORTED); }, // return (io, obj, field) -> io.put(field, field.getField().getShort(obj)), // writer short.class)); serialiser.addClassDefinition(new FieldSerialiser<>( // (io, obj, field) -> field.getField().setInt(obj, io.getInt()), // reader - (io, obj, field) -> { throw new UnsupportedOperationException("return function not supported for primitive types"); }, // return + (io, obj, field) -> { throw new UnsupportedOperationException(UNSUPPORTED); }, // return (io, obj, field) -> io.put(field, field.getField().getInt(obj)), // writer int.class)); serialiser.addClassDefinition(new FieldSerialiser<>( // (io, obj, field) -> field.getField().setLong(obj, io.getLong()), // reader - (io, obj, field) -> { throw new UnsupportedOperationException("return function not supported for primitive types"); }, // return + (io, obj, field) -> { throw new UnsupportedOperationException(UNSUPPORTED); }, // return (io, obj, field) -> io.put(field, field.getField().getLong(obj)), // writer long.class)); serialiser.addClassDefinition(new FieldSerialiser<>( // (io, obj, field) -> field.getField().setFloat(obj, io.getFloat()), // reader - (io, obj, field) -> { throw new UnsupportedOperationException("return function not supported for primitive types"); }, // return + (io, obj, field) -> { throw new UnsupportedOperationException(UNSUPPORTED); }, // return (io, obj, field) -> io.put(field, field.getField().getFloat(obj)), // writer float.class)); serialiser.addClassDefinition(new FieldSerialiser<>( // (io, obj, field) -> field.getField().setDouble(obj, io.getDouble()), // reader - (io, obj, field) -> { throw new UnsupportedOperationException("return function not supported for primitive types"); }, // return + (io, obj, field) -> { throw new UnsupportedOperationException(UNSUPPORTED); }, // return (io, obj, field) -> io.put(field, field.getField().getDouble(obj)), // writer double.class)); serialiser.addClassDefinition(new FieldSerialiser<>( // (io, obj, field) -> field.getField().set(obj, io.getString()), // reader - (io, obj, field) -> { throw new UnsupportedOperationException("return function not supported for primitive types"); }, // return + (io, obj, field) -> { throw new UnsupportedOperationException(UNSUPPORTED); }, // return (io, obj, field) -> io.put(field, (String) field.getField().get(obj)), // writer String.class)); } diff --git a/serialiser/src/main/java/io/opencmw/serialiser/utils/GenericsHelper.java b/serialiser/src/main/java/io/opencmw/serialiser/utils/GenericsHelper.java index f09bc3c7..e5405164 100644 --- a/serialiser/src/main/java/io/opencmw/serialiser/utils/GenericsHelper.java +++ b/serialiser/src/main/java/io/opencmw/serialiser/utils/GenericsHelper.java @@ -6,6 +6,7 @@ * * @author rstein */ +@SuppressWarnings({ "PMD.TooManyMethods", "PMD.ExcessivePublicCount" }) // unavoidable since Java does not support templates (issue: primitive types) public final class GenericsHelper { private GenericsHelper() { // only static methods are used diff --git a/server-rest/src/main/java/io/opencmw/server/rest/login/LoginController.java b/server-rest/src/main/java/io/opencmw/server/rest/login/LoginController.java index 21210c7e..cdc50ca7 100644 --- a/server-rest/src/main/java/io/opencmw/server/rest/login/LoginController.java +++ b/server-rest/src/main/java/io/opencmw/server/rest/login/LoginController.java @@ -26,6 +26,9 @@ @SuppressWarnings("PMD.FieldNamingConventions") public class LoginController { // NOPMD - nomen est omen private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class); + private static final String HTTP_200_OK = "200"; + private static final String MIME_HTML = "text/html"; + private static final String MIME_JSON = "text/json"; private static final String DEFAULT_USER = "anonymous"; private static final String ENDPOINT_LOGIN = "/login"; private static final String ENDPOINT_LOGOUT = "/logout"; @@ -66,9 +69,9 @@ public class LoginController { // NOPMD - nomen est omen summary = "POST login command", tags = { "LoginController" }, responses = { - @OpenApiResponse(status = "200", content = @OpenApiContent(type = "text/html")) + @OpenApiResponse(status = HTTP_200_OK, content = @OpenApiContent(type = MIME_HTML)) , - @OpenApiResponse(status = "200", content = @OpenApiContent(type = "text/json")) + @OpenApiResponse(status = HTTP_200_OK, content = @OpenApiContent(type = MIME_JSON)) }) private static final Handler handleLoginPost = ctx -> { @@ -101,7 +104,7 @@ public class LoginController { // NOPMD - nomen est omen summary = "POST password change page", tags = { "LoginController" }, responses = { - @OpenApiResponse(status = "200", content = @OpenApiContent(type = "text/html")) + @OpenApiResponse(status = HTTP_200_OK, content = @OpenApiContent(type = MIME_HTML)) }) private static final Handler handleChangePasswordPost = ctx -> { @@ -160,9 +163,9 @@ public class LoginController { // NOPMD - nomen est omen summary = "POST logout command", tags = { "LoginController" }, responses = { - @OpenApiResponse(status = "200", content = @OpenApiContent(type = "text/html")) + @OpenApiResponse(status = HTTP_200_OK, content = @OpenApiContent(type = MIME_HTML)) , - @OpenApiResponse(status = "200", content = @OpenApiContent(type = "text/json")) + @OpenApiResponse(status = HTTP_200_OK, content = @OpenApiContent(type = MIME_JSON)) }) private static final Handler handleLogoutPost = ctx -> { @@ -180,7 +183,7 @@ public class LoginController { // NOPMD - nomen est omen // method = HttpMethod.GET, responses = { - @OpenApiResponse(status = "200", content = @OpenApiContent(type = "text/html")) + @OpenApiResponse(status = HTTP_200_OK, content = @OpenApiContent(type = MIME_HTML)) }) private static final Handler serveLoginPage = ctx -> { @@ -195,7 +198,7 @@ public class LoginController { // NOPMD - nomen est omen summary = "GET serve password change page (HTML-only)", tags = { "LoginController" }, responses = { - @OpenApiResponse(status = "200", content = @OpenApiContent(type = "text/html")) + @OpenApiResponse(status = HTTP_200_OK, content = @OpenApiContent(type = MIME_HTML)) }) private static final Handler servePasswordChangePage = ctx -> { diff --git a/server-rest/src/main/java/io/opencmw/server/rest/util/Property.java b/server-rest/src/main/java/io/opencmw/server/rest/util/Property.java deleted file mode 100644 index ea17a6db..00000000 --- a/server-rest/src/main/java/io/opencmw/server/rest/util/Property.java +++ /dev/null @@ -1,168 +0,0 @@ -package io.opencmw.server.rest.util; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Supplier; - -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import io.javalin.http.Handler; -import io.opencmw.MimeType; -import io.opencmw.server.rest.RestServer; - -/** - * Property handler class -- PROTOTYPE/DRAFT for discussion/evaluation - * - * intention: - * * wrapper around RESTful, CMW, other protocol backends to provide a consistent server-side API - * - * @author rstein - * - * @param GET/SUBSCRIBE data model -- a POJO definition - * @param SET/NOTIFY data model -- a POJO definition - * @param REQ/REP handler (contains connection details, back-end handler (default deprecated), method that are not needed for user-level server-side code, ...) - */ -public class Property { - private static final Logger LOGGER = LoggerFactory.getLogger(Property.class); - private static final String ACCEPT_HEADER = "Accept"; - private final String propertyName; - private final String htmlModelGet; - private final String htmlModelSet; - - public Property(@NotNull final String propertyName, // - @NotNull final String htmlModelGet, @NotNull final Class dataClassPrototypeGet, @NotNull final PropertyHandler userHandlerGet, // NOPMD NOSONAR need 'dataClassPrototypeGet handler in the future - @NotNull final String htmlModelSet, @NotNull final Class dataClassPrototypeSet, @NotNull final PropertyHandler userHandlerSet) { // NOPMD NOSONAR need 'dataClassPrototypeSet and userHandlerSet handler in the future - this.propertyName = propertyName; - this.htmlModelGet = htmlModelGet; - this.htmlModelSet = htmlModelSet; - // parse header and switch between different BINARY, JSON, HTML implementations - // generate MAP -> call MAP handler - // [..] etc. - // parse user form data - // N.B. convert here from String to binary Object types - // if GET/SUBSCRIBE - // launch binary serialiser - // generate MAP -> call MAP handler as above - // launch JSON serialiser - // generate MAP -> call MAP handler as above - final Handler handler = ctx -> { - // parse header and switch between different BINARY, JSON, HTML implementations - final String type = ctx.header(ACCEPT_HEADER); - final String contentType = ctx.req.getContentType(); - LOGGER.atInfo().addArgument(propertyName).addArgument(type).addArgument(contentType).log("property {} handle type {} contentType {}"); - - if (type == null || type.equalsIgnoreCase(MimeType.HTML.toString())) { - final Map model = MessageBundle.baseModel(ctx); - - // generate MAP -> call MAP handler - model.put("property", propertyName); - model.put("selector", "FAIR.SELECTOR.ALL"); - // [..] etc. - Map fromUser = new HashMap<>(); - Map> formMap = ctx.formParamMap(); - for (Entry> entry : formMap.entrySet()) { - // parse user form data - fromUser.put(entry.getKey(), entry.getValue()); - // N.B. convert here from String to binary Object types - } - userHandlerGet.handle(fromUser, model); - // if GET/SUBSCRIBE - ctx.render(htmlModelGet, model); - - } else if (type.equalsIgnoreCase(MimeType.BINARY.toString())) { // NOPMD NOSONAR - // TODO: launch binary serialiser - // generate MAP -> call MAP handler as above - } else if (type.equalsIgnoreCase(MimeType.JSON.toString())) { // NOPMD NOSONAR - // TODO: launch JSON serialiser - // generate MAP -> call MAP handler as above - } - }; - - final CombinedHandler restHandler = new CombinedHandler(handler); - RestServer.getInstance().get(propertyName, restHandler); // handles GET & SUBSCRIBE - RestServer.getInstance().post(propertyName, restHandler); // handles SET - } - - protected String getHtmlModelGet() { - return htmlModelGet; - } - - protected String getHtmlModelSet() { - return htmlModelSet; - } - - protected String getPropertyName() { - return propertyName; - } - - /* - * Option 1: plain old Hash-Maps - * same handler for GET/SET/... - * pro: many JSON/XML/Yaml/Binary serialiser support this - * con: many get('key') calls/data copying) - * - * options: maps could be converted/mapped to POJOs <-> performance penalty due to conversion - * - */ - - public interface ComHandler { - D getData(); - D getData(D myInitialReference); - Supplier getData(String selector); - /* - * open questions: - * * allow sub-sets of data fields in ? - * - check input completeness/format checks -> fail-safe fallback (drop? partial update (favours Maps) - * - interface for partial-SET (and GET?)? -> option of sub-hierarchies - */ - H getHeader(); - } - - /* - * Option 2 - * same or different (based on op) handler for GET/SET/... - * pro: as for Option 1 - * con: as for Option 1 - */ - - public enum Operation { - GET, - SET, - SUBSCRIBE - } - - public interface PropertyGetHandler { // N.B. GET/SUBSCRIBE - void handle(ComHandler requestFomUser, ComHandler replyToUser) throws Exception; // NOPMD NOSONAR user may throw any exception - } - - /* - * Option 3 - * using POJO data and generic header objects - * pro: fast w.r.t. serialisation, no server-side user code obfuscation (work with the same POJO for processing/transmitting) - * con: (how to deal with partial/incomplete user data) - */ - - public interface PropertyHandler { - void handle(Map fromUser, Map toUser) throws Exception; // NOPMD NOSONAR user may throw any exception - } - - public interface PropertyHandlerAlt2 { - void handle(Operation op, Map fromUser, Map toUser) throws Exception; // NOPMD NOSONAR user may throw any exception - } - - public interface PropertyHandlerAlt3 { // N.B. GET/SET/NOTIFY - void handle(ComHandler requestFomUser, ComHandler replyToUser) throws Exception; // NOPMD NOSONAR user may throw any exception - } - - public interface PropertyHandlerAlt3Set { // N.B. SET/NOTIFY - void handle(ComHandler requestFomUser, ComHandler replyToUser) throws Exception; // NOPMD NOSONAR user may throw any exception - } - - public interface PropertyMap extends Map { - Object getData(); - } -} diff --git a/server/src/main/java/io/opencmw/server/MajordomoBroker.java b/server/src/main/java/io/opencmw/server/MajordomoBroker.java index bf5aa882..aa428ade 100644 --- a/server/src/main/java/io/opencmw/server/MajordomoBroker.java +++ b/server/src/main/java/io/opencmw/server/MajordomoBroker.java @@ -54,7 +54,7 @@ * N.B. if registered, a HEARTBEAT challenge will be send that needs to be replied with a READY command/re-registering * */ -@SuppressWarnings({ "PMD.DefaultPackage", "PMD.UseConcurrentHashMap", "PMD.TooManyFields", "PMD.CommentSize" }) // package private explicitly needed for MmiServiceHelper, thread-safe/performance use of HashMap +@SuppressWarnings({ "PMD.DefaultPackage", "PMD.UseConcurrentHashMap", "PMD.TooManyFields", "PMD.CommentSize", "PMD.UseConcurrentHashMap" }) // package private explicitly needed for MmiServiceHelper, thread-safe/performance use of HashMap public class MajordomoBroker extends Thread { public static final byte[] RBAC = new byte[] {}; // TODO: implement RBAC between Majordomo and Worker // ----------------- default service names ----------------------------- @@ -89,14 +89,14 @@ public class MajordomoBroker extends Thread { protected final String dnsAddress; protected final List routerSockets = new NoDuplicatesList<>(); // Sockets for clients & public external workers protected final SortedSet> rbacRoles; - final Map services = new HashMap<>(); // NOPMD known services Map<'service name', Service> - protected final Map workers = new HashMap<>(); // NOPMD known workers Map clients = new HashMap<>(); // NOPMD - protected final Map activeSubscriptions = new HashMap<>(); // NOPMD Map> - protected final Map> routerBasedSubscriptions = new HashMap<>(); // NOPMD Map> - private final AtomicBoolean run = new AtomicBoolean(false); + /* default */ final Map services = new HashMap<>(); // known services Map<'service name', Service> + protected final Map workers = new HashMap<>(); // known workers Map clients = new HashMap<>(); + protected final Map activeSubscriptions = new HashMap<>(); // Map> + protected final Map> routerBasedSubscriptions = new HashMap<>(); // Map> + private final AtomicBoolean run = new AtomicBoolean(false); // NOPMD - nomen est omen private final Deque waiting = new ArrayDeque<>(); // idle workers - final Map dnsCache = new HashMap<>(); // NOPMD + /* default */ final Map dnsCache = new HashMap<>(); // private long heartbeatAt = System.currentTimeMillis() + HEARTBEAT_INTERVAL; // When to send HEARTBEAT private long dnsHeartbeatAt = System.currentTimeMillis() + DNS_TIMEOUT; // When to send a DNS HEARTBEAT @@ -287,7 +287,7 @@ private boolean handleSubscriptionMsg(final ZMsg subMsg) { } @Override - public synchronized void start() { + public void start() { run.set(true); services.forEach((serviceName, service) -> service.internalWorkers.forEach(Thread::start)); super.start(); diff --git a/server/src/main/java/io/opencmw/server/MajordomoWorker.java b/server/src/main/java/io/opencmw/server/MajordomoWorker.java index eed1ac4c..4631f251 100644 --- a/server/src/main/java/io/opencmw/server/MajordomoWorker.java +++ b/server/src/main/java/io/opencmw/server/MajordomoWorker.java @@ -27,8 +27,9 @@ import io.opencmw.serialiser.spi.JsonSerialiser; /** - * More complex MajordomoWorker including de-serialising and re-serialising. - * This implements handlers that are driven by PoJo domain objects. + * MajordomoWorker implementation including de-serialising and re-serialising to domain-objects. + *

+ * This implements GET/SET/NOTIFY handlers that are driven by PoJo domain objects. * * @author rstein *