From 792afe0ce8469515d9be0bfe2c644e09953ea28a Mon Sep 17 00:00:00 2001 From: Stefan Feuerhahn Date: Mon, 29 Jun 2020 16:53:50 +0200 Subject: [PATCH] removed code smells detected by IntelliJ and Error Prone SCA, removed the GUI's jcalendar dependency --- build.gradle.kts | 1 - doc/iec61850bean-user-guide.md | 1 - lastconnection.properties | 5 ++ .../java/com/beanit/iec61850bean/Array.java | 3 +- .../iec61850bean/BasicDataAttribute.java | 13 +-- .../com/beanit/iec61850bean/BdaBitString.java | 2 +- .../com/beanit/iec61850bean/BdaEntryTime.java | 2 +- .../com/beanit/iec61850bean/BdaFloat64.java | 19 +++-- .../com/beanit/iec61850bean/BdaQuality.java | 7 +- .../com/beanit/iec61850bean/BdaTimestamp.java | 82 +++++++------------ .../beanit/iec61850bean/BdaUnicodeString.java | 4 +- .../beanit/iec61850bean/BdaVisibleString.java | 10 ++- .../iec61850bean/ClientAssociation.java | 45 +++++----- .../iec61850bean/DataDefinitionResParser.java | 3 +- .../java/com/beanit/iec61850bean/DataSet.java | 13 +-- src/main/java/com/beanit/iec61850bean/Fc.java | 6 -- .../com/beanit/iec61850bean/FcModelNode.java | 9 +- .../com/beanit/iec61850bean/ModelNode.java | 7 +- .../beanit/iec61850bean/ObjectReference.java | 10 ++- .../java/com/beanit/iec61850bean/Rcb.java | 2 +- .../com/beanit/iec61850bean/SclParser.java | 19 +++-- .../iec61850bean/ServerAssociation.java | 28 +++---- .../com/beanit/iec61850bean/ServerModel.java | 9 +- .../com/beanit/iec61850bean/ServerSap.java | 4 +- .../com/beanit/iec61850bean/ServiceError.java | 28 +++---- .../java/com/beanit/iec61850bean/Urcb.java | 13 ++- .../iec61850bean/app/ConsoleClient.java | 2 +- .../iec61850bean/clientgui/BasicDataBind.java | 2 +- .../iec61850bean/clientgui/ClientGui.java | 5 +- .../clientgui/ServerModelParser.java | 8 +- .../clientgui/databind/TextFieldDataBind.java | 2 +- .../clientgui/databind/TimeStampDataBind.java | 71 +++++----------- .../iec61850bean/internal/HexString.java | 4 +- .../internal/cli/ActionProcessor.java | 1 + .../internal/cli/CliParameter.java | 3 - .../internal/cli/FlagCliParameter.java | 2 +- .../internal/cli/ValueCliParameter.java | 2 +- .../internal/scl/AbstractDataAttribute.java | 2 +- .../internal/scl/AbstractElement.java | 4 +- .../internal/scl/AbstractType.java | 2 +- .../internal/util/SequenceNumber.java | 47 +++++++++++ .../com/beanit/josistack/AcseAssociation.java | 75 +++++++---------- .../com/beanit/jositransport/ClientTSap.java | 10 +-- .../com/beanit/jositransport/ServerTSap.java | 10 +-- .../beanit/jositransport/ServerThread.java | 1 + .../com/beanit/jositransport/TConnection.java | 24 +++--- .../integrationtests/ClientServerITest.java | 27 +++--- .../integrationtests/ClientServerITest2.java | 7 +- .../integrationtests/ReportingTest.java | 2 - .../beanit/josistack/SiemensClientITest.java | 2 +- .../jositransport/ClientServerITest.java | 4 +- 51 files changed, 316 insertions(+), 348 deletions(-) create mode 100644 lastconnection.properties create mode 100644 src/main/java/com/beanit/iec61850bean/internal/util/SequenceNumber.java diff --git a/build.gradle.kts b/build.gradle.kts index 80fa8b3..6ab1a2d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -69,7 +69,6 @@ tasks.register("tar") { dependencies { implementation("com.beanit:asn1bean:1.12.0") - implementation("com.toedter:jcalendar:1.4") implementation("org.slf4j:slf4j-api:1.7.25") runtimeOnly("ch.qos.logback:logback-classic:1.2.3") } diff --git a/doc/iec61850bean-user-guide.md b/doc/iec61850bean-user-guide.md index d60c634..aff601e 100644 --- a/doc/iec61850bean-user-guide.md +++ b/doc/iec61850bean-user-guide.md @@ -21,7 +21,6 @@ Besides the IEC61850bean library the folder *build/libs-all/* contains the follo * *logback-core/logback-classic* - an actual logger implementation of the slf4-api. It is used by the console server application to output log information. It can be replaced by a logger of your choice that supports the slf4j API. Like slf4j it is only needed for server implementations. License: EPLv1.0 and LGPLv2.1, http://logback.qos.ch -* *jcalendar* - a calendar library needed by the client GUI. You don't need this dependency if you don't use the client gui. (C)1999-2011 Kai Toedter, License: LGPLv3, http://toedter.com/jcalendar/ ### Console & GUI Applications diff --git a/lastconnection.properties b/lastconnection.properties new file mode 100644 index 0000000..318a532 --- /dev/null +++ b/lastconnection.properties @@ -0,0 +1,5 @@ +#Tue Jun 30 15:11:36 CEST 2020 +tselLocal=0,0 +serverAddress=127.0.0.1 +tselRemote=0,1 +serverPort=10002 diff --git a/src/main/java/com/beanit/iec61850bean/Array.java b/src/main/java/com/beanit/iec61850bean/Array.java index 16fec45..8c9814d 100644 --- a/src/main/java/com/beanit/iec61850bean/Array.java +++ b/src/main/java/com/beanit/iec61850bean/Array.java @@ -20,7 +20,6 @@ import com.beanit.iec61850bean.internal.mms.asn1.Unsigned32; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; /** @@ -81,7 +80,7 @@ public final class Array extends FcModelNode { @Override public List getBasicDataAttributes() { - List subBasicDataAttributes = new LinkedList<>(); + List subBasicDataAttributes = new ArrayList<>(); for (ModelNode item : items) { subBasicDataAttributes.addAll(item.getBasicDataAttributes()); } diff --git a/src/main/java/com/beanit/iec61850bean/BasicDataAttribute.java b/src/main/java/com/beanit/iec61850bean/BasicDataAttribute.java index 3ac7b46..6b10613 100644 --- a/src/main/java/com/beanit/iec61850bean/BasicDataAttribute.java +++ b/src/main/java/com/beanit/iec61850bean/BasicDataAttribute.java @@ -17,7 +17,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; public abstract class BasicDataAttribute extends FcModelNode { @@ -34,10 +33,10 @@ public abstract class BasicDataAttribute extends FcModelNode { boolean qchg; boolean dupd; - List chgRcbs = null; - List dupdRcbs = null; + final List chgRcbs; + final List dupdRcbs; - BasicDataAttribute( + protected BasicDataAttribute( ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) { this.objectReference = objectReference; this.fc = fc; @@ -47,9 +46,13 @@ public abstract class BasicDataAttribute extends FcModelNode { if (dchg) { chgRcbs = new ArrayList<>(); + } else { + chgRcbs = null; } if (dupd) { dupdRcbs = new ArrayList<>(); + } else { + dupdRcbs = null; } } @@ -97,7 +100,7 @@ public abstract class BasicDataAttribute extends FcModelNode { @Override public List getBasicDataAttributes() { - List subBasicDataAttributes = new LinkedList<>(); + List subBasicDataAttributes = new ArrayList<>(); subBasicDataAttributes.add(this); return subBasicDataAttributes; } diff --git a/src/main/java/com/beanit/iec61850bean/BdaBitString.java b/src/main/java/com/beanit/iec61850bean/BdaBitString.java index 12f2576..458a93f 100644 --- a/src/main/java/com/beanit/iec61850bean/BdaBitString.java +++ b/src/main/java/com/beanit/iec61850bean/BdaBitString.java @@ -24,7 +24,7 @@ public abstract class BdaBitString extends BasicDataAttribute { final int maxNumBits; volatile byte[] value; - public BdaBitString( + protected BdaBitString( ObjectReference objectReference, Fc fc, String sAddr, diff --git a/src/main/java/com/beanit/iec61850bean/BdaEntryTime.java b/src/main/java/com/beanit/iec61850bean/BdaEntryTime.java index 73c5bd4..6273318 100644 --- a/src/main/java/com/beanit/iec61850bean/BdaEntryTime.java +++ b/src/main/java/com/beanit/iec61850bean/BdaEntryTime.java @@ -50,7 +50,7 @@ public final class BdaEntryTime extends BasicDataAttribute { (byte) (ms >> 24), (byte) (ms >> 16), (byte) (ms >> 8), - (byte) (ms), + (byte) ms, (byte) (days >> 8), (byte) days }; diff --git a/src/main/java/com/beanit/iec61850bean/BdaFloat64.java b/src/main/java/com/beanit/iec61850bean/BdaFloat64.java index 3221548..4d60704 100644 --- a/src/main/java/com/beanit/iec61850bean/BdaFloat64.java +++ b/src/main/java/com/beanit/iec61850bean/BdaFloat64.java @@ -18,6 +18,7 @@ import com.beanit.iec61850bean.internal.mms.asn1.FloatingPoint; import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription; import com.beanit.iec61850bean.internal.mms.asn1.Unsigned8; import java.nio.ByteBuffer; +import java.util.Arrays; public final class BdaFloat64 extends BasicDataAttribute { @@ -55,14 +56,14 @@ public final class BdaFloat64 extends BasicDataAttribute { return null; } return Double.longBitsToDouble( - ((0xffL & (value[1])) << 56) - | ((0xffL & (value[2])) << 48) - | ((0xffL & (value[3])) << 40) - | ((0xffL & (value[4])) << 32) - | ((0xffL & (value[5])) << 24) - | ((0xffL & (value[6])) << 16) - | ((0xffL & (value[7])) << 8) - | ((0xffL & (value[8])) << 0)); + ((0xffL & value[1]) << 56) + | ((0xffL & value[2]) << 48) + | ((0xffL & value[3]) << 40) + | ((0xffL & value[4]) << 32) + | ((0xffL & value[5]) << 24) + | ((0xffL & value[6]) << 16) + | ((0xffL & value[7]) << 8) + | ((0xffL & value[8]) << 0)); } public void setDouble(Double value) { @@ -126,6 +127,6 @@ public final class BdaFloat64 extends BasicDataAttribute { @Override public String getValueString() { - return "" + value; + return "" + Arrays.toString(value); } } diff --git a/src/main/java/com/beanit/iec61850bean/BdaQuality.java b/src/main/java/com/beanit/iec61850bean/BdaQuality.java index 6acbfef..67c5523 100644 --- a/src/main/java/com/beanit/iec61850bean/BdaQuality.java +++ b/src/main/java/com/beanit/iec61850bean/BdaQuality.java @@ -13,17 +13,12 @@ */ package com.beanit.iec61850bean; -import java.util.ArrayList; - public final class BdaQuality extends BdaBitString { public BdaQuality(ObjectReference objectReference, Fc fc, String sAddr, boolean qchg) { - super(objectReference, fc, sAddr, 13, false, false); + super(objectReference, fc, sAddr, 13, qchg, false); this.qchg = qchg; basicType = BdaType.QUALITY; - if (qchg) { - chgRcbs = new ArrayList<>(); - } setDefault(); } diff --git a/src/main/java/com/beanit/iec61850bean/BdaTimestamp.java b/src/main/java/com/beanit/iec61850bean/BdaTimestamp.java index acb4721..3e328e9 100644 --- a/src/main/java/com/beanit/iec61850bean/BdaTimestamp.java +++ b/src/main/java/com/beanit/iec61850bean/BdaTimestamp.java @@ -17,7 +17,7 @@ import com.beanit.asn1bean.ber.types.BerNull; import com.beanit.iec61850bean.internal.mms.asn1.Data; import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription; import com.beanit.iec61850bean.internal.mms.asn1.UtcTime; -import java.util.Calendar; +import java.time.Instant; import java.util.Date; public final class BdaTimestamp extends BasicDataAttribute { @@ -65,43 +65,6 @@ public final class BdaTimestamp extends BasicDataAttribute { return ((0xff & value[4]) << 16 | (0xff & value[5]) << 8 | (0xff & value[6])); } - public void setDate( - Date date, - boolean leapSecondsKnown, - boolean clockFailure, - boolean clockNotSynchronized, - int timeAccuracy) { - if (value == null) { - value = new byte[8]; - } - - int secondsSinceEpoch = (int) (date.getTime() / 1000L); - int fractionOfSecond = (int) ((date.getTime() % 1000L) / 1000.0 * (1 << 24)); - - int timeQuality = timeAccuracy & 0x1f; - if (leapSecondsKnown) { - timeQuality = timeQuality | 0x80; - } - if (clockFailure) { - timeQuality = timeQuality | 0x40; - } - if (clockNotSynchronized) { - timeQuality = timeQuality | 0x20; - } - - value = - new byte[] { - (byte) ((secondsSinceEpoch >> 24) & 0xff), - (byte) ((secondsSinceEpoch >> 16) & 0xff), - (byte) ((secondsSinceEpoch >> 8) & 0xff), - (byte) (secondsSinceEpoch & 0xff), - (byte) ((fractionOfSecond >> 16) & 0xff), - (byte) ((fractionOfSecond >> 8) & 0xff), - (byte) (fractionOfSecond & 0xff), - (byte) timeQuality - }; - } - @Override public void setValueFrom(BasicDataAttribute bda) { byte[] srcValue = ((BdaTimestamp) bda).getValue(); @@ -111,26 +74,44 @@ public final class BdaTimestamp extends BasicDataAttribute { System.arraycopy(srcValue, 0, value, 0, srcValue.length); } - public Date getDate() { + public Instant getInstant() { if (value == null || value.length == 0) { return null; } long time = getSecondsSinceEpoch() * 1000L + (long) (((float) getFractionOfSecond()) / (1 << 24) * 1000 + 0.5); - return new Date(time); + return Instant.ofEpochMilli(time); } - public void setDate(Date date) { + public void setInstant(Instant instant) { + setInstant(instant, true, false, false, 10); + } + + public void setInstant( + Instant instant, + boolean leapSecondsKnown, + boolean clockFailure, + boolean clockNotSynchronized, + int timeAccuracy) { if (value == null) { value = new byte[8]; } - int secondsSinceEpoch = (int) (date.getTime() / 1000L); - int fractionOfSecond = (int) ((date.getTime() % 1000L) / 1000.0 * (1 << 24)); + int secondsSinceEpoch = (int) (instant.toEpochMilli() / 1000L); + int fractionOfSecond = (int) ((instant.toEpochMilli() % 1000L) / 1000.0 * (1 << 24)); + + int timeQuality = timeAccuracy & 0x1f; + if (leapSecondsKnown) { + timeQuality = timeQuality | 0x80; + } + if (clockFailure) { + timeQuality = timeQuality | 0x40; + } + if (clockNotSynchronized) { + timeQuality = timeQuality | 0x20; + } - // 0x8a = time accuracy of 10 and LeapSecondsKnown = true, ClockFailure - // = false, ClockNotSynchronized = false value = new byte[] { (byte) ((secondsSinceEpoch >> 24) & 0xff), @@ -140,7 +121,7 @@ public final class BdaTimestamp extends BasicDataAttribute { (byte) ((fractionOfSecond >> 16) & 0xff), (byte) ((fractionOfSecond >> 8) & 0xff), (byte) (fractionOfSecond & 0xff), - (byte) 0x8a + (byte) timeQuality }; } @@ -161,9 +142,6 @@ public final class BdaTimestamp extends BasicDataAttribute { * does not take into account the leap seconds that occurred before the initialization of the time * source of the device. * - *

Java {@link Date} and {@link Calendar} objects do handle leap seconds, so this is usually - * true. - * * @return TRUE of the attribute LeapSecondsKnown shall indicate that the value for * SecondSinceEpoch takes into account all leap seconds occurred */ @@ -213,7 +191,7 @@ public final class BdaTimestamp extends BasicDataAttribute { /** Sets Timestamp to current time */ public void setCurrentTime() { - setDate(new Date()); + setInstant(Instant.now()); } @Override @@ -254,11 +232,11 @@ public final class BdaTimestamp extends BasicDataAttribute { @Override public String toString() { - return getReference().toString() + ": " + getDate(); + return getReference().toString() + ": " + getInstant(); } @Override public String getValueString() { - return getDate().toString(); + return getInstant().toString(); } } diff --git a/src/main/java/com/beanit/iec61850bean/BdaUnicodeString.java b/src/main/java/com/beanit/iec61850bean/BdaUnicodeString.java index e43a492..914268a 100644 --- a/src/main/java/com/beanit/iec61850bean/BdaUnicodeString.java +++ b/src/main/java/com/beanit/iec61850bean/BdaUnicodeString.java @@ -13,6 +13,8 @@ */ package com.beanit.iec61850bean; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.beanit.iec61850bean.internal.mms.asn1.Data; import com.beanit.iec61850bean.internal.mms.asn1.Integer32; import com.beanit.iec61850bean.internal.mms.asn1.MMSString; @@ -108,6 +110,6 @@ public final class BdaUnicodeString extends BasicDataAttribute { if (value == null) { return getReference().toString() + ": null"; } - return getReference().toString() + ": " + new String(value); + return getReference().toString() + ": " + new String(value, UTF_8); } } diff --git a/src/main/java/com/beanit/iec61850bean/BdaVisibleString.java b/src/main/java/com/beanit/iec61850bean/BdaVisibleString.java index 67ff496..5aa052f 100644 --- a/src/main/java/com/beanit/iec61850bean/BdaVisibleString.java +++ b/src/main/java/com/beanit/iec61850bean/BdaVisibleString.java @@ -13,6 +13,8 @@ */ package com.beanit.iec61850bean; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.beanit.asn1bean.ber.types.string.BerVisibleString; import com.beanit.iec61850bean.internal.mms.asn1.Data; import com.beanit.iec61850bean.internal.mms.asn1.Integer32; @@ -49,7 +51,7 @@ public final class BdaVisibleString extends BasicDataAttribute { } public void setValue(String value) { - setValue(value.getBytes()); + setValue(value.getBytes(UTF_8)); } @Override @@ -66,7 +68,7 @@ public final class BdaVisibleString extends BasicDataAttribute { } public String getStringValue() { - return new String(value); + return new String(value, UTF_8); } @Override @@ -118,11 +120,11 @@ public final class BdaVisibleString extends BasicDataAttribute { if (value.length == 0 || value[0] == (byte) 0) { return getReference().toString() + ": ''"; } - return getReference().toString() + ": " + new String(value); + return getReference().toString() + ": " + new String(value, UTF_8); } @Override public String getValueString() { - return new String(value); + return new String(value, UTF_8); } } diff --git a/src/main/java/com/beanit/iec61850bean/ClientAssociation.java b/src/main/java/com/beanit/iec61850bean/ClientAssociation.java index 6e1865e..ce82a87 100644 --- a/src/main/java/com/beanit/iec61850bean/ClientAssociation.java +++ b/src/main/java/com/beanit/iec61850bean/ClientAssociation.java @@ -13,6 +13,8 @@ */ package com.beanit.iec61850bean; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream; import com.beanit.asn1bean.ber.types.BerInteger; import com.beanit.asn1bean.ber.types.BerNull; @@ -75,12 +77,11 @@ import java.io.IOException; import java.net.InetAddress; import java.nio.ByteBuffer; import java.text.ParseException; +import java.time.Instant; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; -import java.util.Date; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; @@ -429,6 +430,7 @@ public final class ClientAssociation { decodedResponsePdu = incomingResponses.poll(responseTimeout, TimeUnit.MILLISECONDS); } } catch (InterruptedException e) { + // TODO can this ever be interrupted? } if (decodedResponsePdu == null) { @@ -661,7 +663,7 @@ public final class ClientAssociation { } private List retrieveLogicalNodeNames(String ld) throws ServiceError, IOException { - List lns = new LinkedList<>(); + List lns = new ArrayList<>(); String continueAfterRef = ""; do { ConfirmedServiceRequest serviceRequest = @@ -669,7 +671,7 @@ public final class ClientAssociation { ConfirmedServiceResponse confirmedServiceResponse = encodeWriteReadDecode(serviceRequest); continueAfterRef = decodeGetDirectoryResponse(confirmedServiceResponse, lns); - } while (continueAfterRef != ""); + } while (!continueAfterRef.isEmpty()); return lns; } @@ -684,16 +686,16 @@ public final class ClientAssociation { objectClass.setBasicObjectClass(new BerInteger(2)); } - GetNameListRequest getNameListRequest = null; + GetNameListRequest getNameListRequest; ObjectScope objectScopeChoiceType = new ObjectScope(); - objectScopeChoiceType.setDomainSpecific(new Identifier(ldRef.getBytes())); + objectScopeChoiceType.setDomainSpecific(new Identifier(ldRef.getBytes(UTF_8))); getNameListRequest = new GetNameListRequest(); getNameListRequest.setObjectClass(objectClass); getNameListRequest.setObjectScope(objectScopeChoiceType); - if (continueAfter != "") { - getNameListRequest.setContinueAfter(new Identifier(continueAfter.getBytes())); + if (!continueAfter.isEmpty()) { + getNameListRequest.setContinueAfter(new Identifier(continueAfter.getBytes(UTF_8))); } ConfirmedServiceRequest confirmedServiceRequest = new ConfirmedServiceRequest(); @@ -756,8 +758,8 @@ public final class ClientAssociation { private ConfirmedServiceRequest constructGetDataDefinitionRequest(ObjectReference lnRef) { ObjectName.DomainSpecific domainSpec = new ObjectName.DomainSpecific(); - domainSpec.setDomainID(new Identifier(lnRef.get(0).getBytes())); - domainSpec.setItemID(new Identifier(lnRef.get(1).getBytes())); + domainSpec.setDomainID(new Identifier(lnRef.get(0).getBytes(UTF_8))); + domainSpec.setItemID(new Identifier(lnRef.get(1).getBytes(UTF_8))); ObjectName objectName = new ObjectName(); objectName.setDomainSpecific(domainSpec); @@ -856,7 +858,7 @@ public final class ClientAssociation { */ public List getFileDirectory(String directoryName) throws ServiceError, IOException { - List files = new LinkedList<>(); + List files = new ArrayList<>(); boolean moreFollows = true; @@ -866,7 +868,7 @@ public final class ClientAssociation { FileDirectoryRequest fileDirectoryRequest = new FileDirectoryRequest(); - BerGraphicString berGraphicString = new BerGraphicString(directoryName.getBytes()); + BerGraphicString berGraphicString = new BerGraphicString(directoryName.getBytes(UTF_8)); FileName fileSpecification = new FileName(); fileSpecification.getBerGraphicString().add(berGraphicString); @@ -878,7 +880,7 @@ public final class ClientAssociation { continueAfterSpecification .getBerGraphicString() - .add(new BerGraphicString(continueAfter.getBytes())); + .add(new BerGraphicString(continueAfter.getBytes(UTF_8))); fileDirectoryRequest.setContinueAfter(continueAfterSpecification); } @@ -910,7 +912,7 @@ public final class ClientAssociation { public void deleteFile(String filename) throws ServiceError, IOException { FileDeleteRequest fileDeleteRequest = new FileDeleteRequest(); - fileDeleteRequest.getBerGraphicString().add(new BerGraphicString(filename.getBytes())); + fileDeleteRequest.getBerGraphicString().add(new BerGraphicString(filename.getBytes(UTF_8))); ConfirmedServiceRequest confirmedServiceRequest = new ConfirmedServiceRequest(); confirmedServiceRequest.setFileDelete(fileDeleteRequest); @@ -929,7 +931,7 @@ public final class ClientAssociation { FileOpenRequest fileOpenRequest = new FileOpenRequest(); FileName fileSpecification = new FileName(); - fileSpecification.getBerGraphicString().add(new BerGraphicString(filename.getBytes())); + fileSpecification.getBerGraphicString().add(new BerGraphicString(filename.getBytes(UTF_8))); fileOpenRequest.setFileName(fileSpecification); fileOpenRequest.setInitialPosition(new Unsigned32(0)); @@ -1229,7 +1231,7 @@ public final class ClientAssociation { private ConfirmedServiceRequest constructGetDataSetDirectoryRequest( Identifier dsId, LogicalDevice ld) throws ServiceError { ObjectName.DomainSpecific domainSpecificObjectName = new ObjectName.DomainSpecific(); - domainSpecificObjectName.setDomainID(new Identifier(ld.getName().getBytes())); + domainSpecificObjectName.setDomainID(new Identifier(ld.getName().getBytes(UTF_8))); domainSpecificObjectName.setItemID(dsId); GetNamedVariableListAttributesRequest dataSetObj = new GetNamedVariableListAttributesRequest(); @@ -1720,7 +1722,7 @@ public final class ClientAssociation { String dataSetRef = null; if (optFlds.isDataSetName()) { - dataSetRef = (listRes.get(index++).getSuccess().getVisibleString().toString()); + dataSetRef = listRes.get(index++).getSuccess().getVisibleString().toString(); } else { for (Urcb urcb : serverModel.getUrcbs()) { if ((urcb.getRptId() != null && urcb.getRptId().getStringValue().equals(rptId)) @@ -1755,7 +1757,7 @@ public final class ClientAssociation { Boolean bufOvfl = null; if (optFlds.isBufferOverflow()) { - bufOvfl = (listRes.get(index++).getSuccess().getBool().value); + bufOvfl = listRes.get(index++).getSuccess().getBool().value; } BdaOctetString entryId = null; @@ -1915,7 +1917,7 @@ public final class ClientAssociation { } ((BdaInt8U) oper.getChild("ctlNum")).setValue((short) 1); - ((BdaTimestamp) oper.getChild("T")).setDate(new Date(System.currentTimeMillis())); + ((BdaTimestamp) oper.getChild("T")).setInstant(Instant.now()); setDataValues(oper); } @@ -2008,6 +2010,7 @@ public final class ClientAssociation { try { incomingResponses.put(decodedResponsePdu); } catch (InterruptedException e) { + // TODO can this ever be interrupted? } } } @@ -2025,6 +2028,7 @@ public final class ClientAssociation { try { incomingResponses.put(decodedResponsePdu); } catch (InterruptedException e) { + // TODO can this ever be interrupted? } } } @@ -2043,6 +2047,7 @@ public final class ClientAssociation { try { incomingResponses.put(decodedResponsePdu); } catch (InterruptedException e) { + // TODO can this ever be interrupted? } } } @@ -2082,6 +2087,7 @@ public final class ClientAssociation { try { incomingResponses.put(mmsPdu); } catch (InterruptedException e1) { + // TODO can this ever be interrupted? } } } @@ -2108,6 +2114,7 @@ public final class ClientAssociation { try { incomingResponses.put(mmsPdu); } catch (InterruptedException e1) { + // TODO can this ever be interrupted? } } } diff --git a/src/main/java/com/beanit/iec61850bean/DataDefinitionResParser.java b/src/main/java/com/beanit/iec61850bean/DataDefinitionResParser.java index 90c0931..e9ee458 100644 --- a/src/main/java/com/beanit/iec61850bean/DataDefinitionResParser.java +++ b/src/main/java/com/beanit/iec61850bean/DataDefinitionResParser.java @@ -20,7 +20,6 @@ import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription.Structure.Compo import com.beanit.iec61850bean.internal.mms.asn1.TypeSpecification; import java.util.ArrayList; import java.util.Collection; -import java.util.LinkedList; import java.util.List; final class DataDefinitionResParser { @@ -46,7 +45,7 @@ final class DataDefinitionResParser { Components structure = typeSpec.getStructure().getComponents(); - List fcDataObjects = new LinkedList<>(); + List fcDataObjects = new ArrayList<>(); Fc fc; for (TypeDescription.Structure.Components.SEQUENCE fcComponent : structure.getSEQUENCE()) { diff --git a/src/main/java/com/beanit/iec61850bean/DataSet.java b/src/main/java/com/beanit/iec61850bean/DataSet.java index 4b23e1f..7ca483d 100644 --- a/src/main/java/com/beanit/iec61850bean/DataSet.java +++ b/src/main/java/com/beanit/iec61850bean/DataSet.java @@ -13,13 +13,14 @@ */ package com.beanit.iec61850bean; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.beanit.iec61850bean.internal.mms.asn1.Identifier; import com.beanit.iec61850bean.internal.mms.asn1.ObjectName; import java.util.ArrayList; import java.util.EnumMap; import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -42,7 +43,7 @@ public final class DataSet implements Iterable { + dataSetReference + " is invalid. Must either start with @ or contain a slash."); } - this.members = new LinkedList<>(); + this.members = new ArrayList<>(); this.dataSetReference = dataSetReference; this.deletable = deletable; @@ -105,7 +106,7 @@ public final class DataSet implements Iterable { } public List getBasicDataAttributes() { - List subBasicDataAttributes = new LinkedList<>(); + List subBasicDataAttributes = new ArrayList<>(); for (ModelNode member : members) { subBasicDataAttributes.addAll(member.getBasicDataAttributes()); } @@ -120,7 +121,7 @@ public final class DataSet implements Iterable { if (dataSetReference.charAt(0) == '@') { mmsObjectName = new ObjectName(); - mmsObjectName.setAaSpecific(new Identifier(dataSetReference.getBytes())); + mmsObjectName.setAaSpecific(new Identifier(dataSetReference.getBytes(UTF_8))); return mmsObjectName; } @@ -129,8 +130,8 @@ public final class DataSet implements Iterable { String itemID = dataSetReference.substring(slash + 1).replace('.', '$'); ObjectName.DomainSpecific domainSpecificObjectName = new ObjectName.DomainSpecific(); - domainSpecificObjectName.setDomainID(new Identifier(domainID.getBytes())); - domainSpecificObjectName.setItemID(new Identifier(itemID.getBytes())); + domainSpecificObjectName.setDomainID(new Identifier(domainID.getBytes(UTF_8))); + domainSpecificObjectName.setItemID(new Identifier(itemID.getBytes(UTF_8))); mmsObjectName = new ObjectName(); mmsObjectName.setDomainSpecific(domainSpecificObjectName); diff --git a/src/main/java/com/beanit/iec61850bean/Fc.java b/src/main/java/com/beanit/iec61850bean/Fc.java index a8b8052..fd8ff9c 100644 --- a/src/main/java/com/beanit/iec61850bean/Fc.java +++ b/src/main/java/com/beanit/iec61850bean/Fc.java @@ -51,12 +51,6 @@ public enum Fc { /** Buffered Reporting */ BR; - /* - * * @param fc - * - * @return - */ - public static Fc fromString(String fc) { try { return Fc.valueOf(fc); diff --git a/src/main/java/com/beanit/iec61850bean/FcModelNode.java b/src/main/java/com/beanit/iec61850bean/FcModelNode.java index 6a2d523..e414979 100644 --- a/src/main/java/com/beanit/iec61850bean/FcModelNode.java +++ b/src/main/java/com/beanit/iec61850bean/FcModelNode.java @@ -13,6 +13,8 @@ */ package com.beanit.iec61850bean; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.beanit.iec61850bean.internal.mms.asn1.AlternateAccess; import com.beanit.iec61850bean.internal.mms.asn1.AlternateAccessSelection; import com.beanit.iec61850bean.internal.mms.asn1.AlternateAccessSelection.SelectAccess; @@ -151,7 +153,7 @@ public abstract class FcModelNode extends ModelNode { } BasicIdentifier subIndexReference = - new BasicIdentifier(postArrayIndexItemId.toString().getBytes()); + new BasicIdentifier(postArrayIndexItemId.toString().getBytes(UTF_8)); AlternateAccessSelection.SelectAccess subIndexReferenceSelectAccess = new AlternateAccessSelection.SelectAccess(); @@ -220,8 +222,9 @@ public abstract class FcModelNode extends ModelNode { } ObjectName.DomainSpecific domainSpecificObjectName = new ObjectName.DomainSpecific(); - domainSpecificObjectName.setDomainID(new Identifier(objectReference.get(0).getBytes())); - domainSpecificObjectName.setItemID(new Identifier(preArrayIndexItemId.toString().getBytes())); + domainSpecificObjectName.setDomainID(new Identifier(objectReference.get(0).getBytes(UTF_8))); + domainSpecificObjectName.setItemID( + new Identifier(preArrayIndexItemId.toString().getBytes(UTF_8))); ObjectName objectName = new ObjectName(); objectName.setDomainSpecific(domainSpecificObjectName); diff --git a/src/main/java/com/beanit/iec61850bean/ModelNode.java b/src/main/java/com/beanit/iec61850bean/ModelNode.java index 5c89d5f..4aed617 100644 --- a/src/main/java/com/beanit/iec61850bean/ModelNode.java +++ b/src/main/java/com/beanit/iec61850bean/ModelNode.java @@ -13,6 +13,8 @@ */ package com.beanit.iec61850bean; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.beanit.iec61850bean.internal.mms.asn1.Data; import com.beanit.iec61850bean.internal.mms.asn1.Identifier; import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription; @@ -22,7 +24,6 @@ import com.beanit.iec61850bean.internal.mms.asn1.TypeSpecification; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -111,7 +112,7 @@ public abstract class ModelNode implements Iterable { * node. */ public List getBasicDataAttributes() { - List subBasicDataAttributes = new LinkedList<>(); + List subBasicDataAttributes = new ArrayList<>(); for (ModelNode child : children.values()) { subBasicDataAttributes.addAll(child.getBasicDataAttributes()); } @@ -160,7 +161,7 @@ public abstract class ModelNode implements Iterable { TypeDescription.Structure.Components.SEQUENCE component = new TypeDescription.Structure.Components.SEQUENCE(); - component.setComponentName(new Identifier(child.getName().getBytes())); + component.setComponentName(new Identifier(child.getName().getBytes(UTF_8))); component.setComponentType(typeSpecification); structComponents.add(component); diff --git a/src/main/java/com/beanit/iec61850bean/ObjectReference.java b/src/main/java/com/beanit/iec61850bean/ObjectReference.java index 7069301..a2a0742 100644 --- a/src/main/java/com/beanit/iec61850bean/ObjectReference.java +++ b/src/main/java/com/beanit/iec61850bean/ObjectReference.java @@ -13,8 +13,8 @@ */ package com.beanit.iec61850bean; +import java.util.ArrayList; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; /** ObjectReference syntax: LDName/LNName.DOName[.Name[. ...]] */ @@ -34,7 +34,11 @@ public final class ObjectReference implements Iterable { this.objectReference = objectReference; } - /** @return Returns name part of the reference. */ + /** + * Returns name part of the reference. + * + * @return the name + */ public String getName() { if (nodeNames == null) { parseForNameList(); @@ -107,7 +111,7 @@ public final class ObjectReference implements Iterable { private void parseForNameList() { - nodeNames = new LinkedList<>(); + nodeNames = new ArrayList<>(); int lastDelim = -1; int nextDelim = objectReference.indexOf('/'); diff --git a/src/main/java/com/beanit/iec61850bean/Rcb.java b/src/main/java/com/beanit/iec61850bean/Rcb.java index 11c50d8..fc3db99 100644 --- a/src/main/java/com/beanit/iec61850bean/Rcb.java +++ b/src/main/java/com/beanit/iec61850bean/Rcb.java @@ -19,7 +19,7 @@ public abstract class Rcb extends FcDataObject { DataSet dataSet; - public Rcb(ObjectReference objectReference, Fc fc, List children) { + protected Rcb(ObjectReference objectReference, Fc fc, List children) { super(objectReference, fc, children); } diff --git a/src/main/java/com/beanit/iec61850bean/SclParser.java b/src/main/java/com/beanit/iec61850bean/SclParser.java index 8b3ff7a..adc5a10 100644 --- a/src/main/java/com/beanit/iec61850bean/SclParser.java +++ b/src/main/java/com/beanit/iec61850bean/SclParser.java @@ -13,6 +13,8 @@ */ package com.beanit.iec61850bean; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.beanit.iec61850bean.internal.scl.AbstractDataAttribute; import com.beanit.iec61850bean.internal.scl.Bda; import com.beanit.iec61850bean.internal.scl.Da; @@ -31,7 +33,6 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilderFactory; @@ -175,7 +176,7 @@ public class SclParser { if (namedItem == null) { throw new SclParseException("AccessPoint has no name attribute!"); } - String name = namedItem.getNodeValue(); + // TODO save this name? serverSap = new ServerSap(102, 0, null, server, null); break; @@ -590,7 +591,7 @@ public class SclParser { new ObjectReference(reportObjRef.toString() + ".RptID"), fc, "", 129, false, false); attribute = rcbNodeAttributes.getNamedItem("rptID"); if (attribute != null) { - rptId.setValue(attribute.getNodeValue().getBytes()); + rptId.setValue(attribute.getNodeValue().getBytes(UTF_8)); } else { rptId.setValue(reportObjRef.toString()); } @@ -615,7 +616,7 @@ public class SclParser { if (attribute != null) { String nodeValue = attribute.getNodeValue(); String dataSetName = parentRef + "$" + nodeValue; - datSet.setValue(dataSetName.getBytes()); + datSet.setValue(dataSetName.getBytes(UTF_8)); } children.add(datSet); @@ -760,14 +761,14 @@ public class SclParser { Map> subFCDataMap = new LinkedHashMap<>(); for (Fc fc : Fc.values()) { - subFCDataMap.put(fc, new LinkedList()); + subFCDataMap.put(fc, new ArrayList<>()); } for (ModelNode childNode : childNodes) { subFCDataMap.get(((FcModelNode) childNode).getFc()).add((FcModelNode) childNode); } - List fcDataObjects = new LinkedList<>(); + List fcDataObjects = new ArrayList<>(); ObjectReference objectReference = new ObjectReference(ref); for (Fc fc : Fc.values()) { @@ -1002,7 +1003,7 @@ public class SclParser { dchg, dupd); if (val != null) { - bda.setValue(val.getBytes()); + bda.setValue(val.getBytes(UTF_8)); } return bda; } else if (bType.startsWith("Unicode")) { @@ -1015,7 +1016,7 @@ public class SclParser { dchg, dupd); if (val != null) { - bda.setValue(val.getBytes()); + bda.setValue(val.getBytes(UTF_8)); } return bda; } else if (bType.startsWith("Octet")) { @@ -1099,7 +1100,7 @@ public class SclParser { BdaVisibleString bda = new BdaVisibleString(new ObjectReference(ref), fc, sAddr, 129, dchg, dupd); if (val != null) { - bda.setValue(val.getBytes()); + bda.setValue(val.getBytes(UTF_8)); } return bda; } else { diff --git a/src/main/java/com/beanit/iec61850bean/ServerAssociation.java b/src/main/java/com/beanit/iec61850bean/ServerAssociation.java index ffde1af..dde88d3 100644 --- a/src/main/java/com/beanit/iec61850bean/ServerAssociation.java +++ b/src/main/java/com/beanit/iec61850bean/ServerAssociation.java @@ -13,6 +13,8 @@ */ package com.beanit.iec61850bean; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream; import com.beanit.asn1bean.ber.types.BerInteger; import com.beanit.asn1bean.ber.types.BerNull; @@ -73,7 +75,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.concurrent.Executors; @@ -286,7 +287,7 @@ final class ServerAssociation { getNameListRequest.getObjectClass().getBasicObjectClass().longValue(); if (basicObjectClass == 9) { logger.debug("Got a GetServerDirectory (MMS GetNameList[DOMAIN]) request"); - response = handleGetServerDirectoryRequest(getNameListRequest); + response = handleGetServerDirectoryRequest(); } else if (basicObjectClass == 0) { logger.debug("Got a Get{LD|LN}Directory (MMS GetNameList[NAMED_VARIABLE]) request"); response = handleGetDirectoryRequest(getNameListRequest); @@ -417,7 +418,7 @@ final class ServerAssociation { private MMSpdu listenForMmsRequest(AcseAssociation acseAssociation) { while (true) { - MMSpdu mmsRequestPdu = null; + MMSpdu mmsRequestPdu; byte[] buffer; pduBuffer.clear(); try { @@ -494,7 +495,7 @@ final class ServerAssociation { default: errClass.setOthers(new BerInteger(e.getErrorCode())); } - com.beanit.iec61850bean.internal.mms.asn1.ServiceError asn1ServiceError = null; + com.beanit.iec61850bean.internal.mms.asn1.ServiceError asn1ServiceError; asn1ServiceError = new com.beanit.iec61850bean.internal.mms.asn1.ServiceError(); asn1ServiceError.setErrorClass(errClass); @@ -510,14 +511,13 @@ final class ServerAssociation { return mmsPdu; } - private GetNameListResponse handleGetServerDirectoryRequest(GetNameListRequest getNameListRequest) - throws ServiceError { + private GetNameListResponse handleGetServerDirectoryRequest() throws ServiceError { ListOfIdentifier listOfIdentifier = new ListOfIdentifier(); List identifiers = listOfIdentifier.getIdentifier(); for (ModelNode ld : serverModel) { - identifiers.add(new Identifier(ld.getName().getBytes())); + identifiers.add(new Identifier(ld.getName().getBytes(UTF_8))); } GetNameListResponse getNameListResponse = new GetNameListResponse(); @@ -564,7 +564,7 @@ final class ServerAssociation { insertRef = false; } - List mmsReferences = new LinkedList<>(); + List mmsReferences = new ArrayList<>(); for (ModelNode logicalNodeMn : logicalDevice) { LogicalNode logicalNode = (LogicalNode) logicalNodeMn; @@ -598,9 +598,9 @@ final class ServerAssociation { break; } - Identifier identifier = null; + Identifier identifier; - identifier = new Identifier(mmsReference.getBytes()); + identifier = new Identifier(mmsReference.getBytes(UTF_8)); identifiers.add(identifier); identifierSize += mmsReference.length() + 2; @@ -773,7 +773,7 @@ final class ServerAssociation { TypeDescription.Structure.Components.SEQUENCE structComponent = new TypeDescription.Structure.Components.SEQUENCE(); - structComponent.setComponentName(new Identifier(child.getName().getBytes())); + structComponent.setComponentName(new Identifier(child.getName().getBytes(UTF_8))); structComponent.setComponentType(typeSpecification); doStructComponents.add(structComponent); } @@ -825,7 +825,7 @@ final class ServerAssociation { TypeDescription.Structure.Components.SEQUENCE doStructComponent = new TypeDescription.Structure.Components.SEQUENCE(); - doStructComponent.setComponentName(new Identifier(child.getName().getBytes())); + doStructComponent.setComponentName(new Identifier(child.getName().getBytes(UTF_8))); doStructComponent.setComponentType(typeSpecification); doStructComponents.add(doStructComponent); @@ -842,7 +842,7 @@ final class ServerAssociation { TypeDescription.Structure.Components.SEQUENCE structCom = new TypeDescription.Structure.Components.SEQUENCE(); - structCom.setComponentName(new Identifier(mmsFc.getBytes())); + structCom.setComponentName(new Identifier(mmsFc.getBytes(UTF_8))); structCom.setComponentType(typeSpecification); structComponents.add(structCom); @@ -1513,7 +1513,7 @@ final class ServerAssociation { logger.info("maxMMSPduSize reached"); break; } - identifiers.add(new Identifier(dsRef.getBytes())); + identifiers.add(new Identifier(dsRef.getBytes(UTF_8))); identifierSize += dsRef.length() + 2; } else { if (dsRef.equals(continueAfter)) { diff --git a/src/main/java/com/beanit/iec61850bean/ServerModel.java b/src/main/java/com/beanit/iec61850bean/ServerModel.java index 34fd3b6..9a4f59f 100644 --- a/src/main/java/com/beanit/iec61850bean/ServerModel.java +++ b/src/main/java/com/beanit/iec61850bean/ServerModel.java @@ -22,7 +22,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -116,7 +115,7 @@ public final class ServerModel extends ModelNode { List getDataSetNames(String ldName) { // TODO make thread save - List dataSetNames = new LinkedList<>(); + List dataSetNames = new ArrayList<>(); for (String dataSetRef : dataSets.keySet()) { if (dataSetRef.startsWith(ldName)) { dataSetNames.add(dataSetRef.substring(dataSetRef.indexOf('/') + 1).replace('.', '$')); @@ -135,7 +134,7 @@ public final class ServerModel extends ModelNode { } /** - * @param dataSetReference + * @param dataSetReference the data set reference * @return returns the DataSet that was removed, null if no DataSet with the given reference was * found or the data set is not deletable. */ @@ -266,9 +265,9 @@ public final class ServerModel extends ModelNode { * Returns the subModelNode that is referenced by the given VariableDef. Return null in case the * referenced ModelNode is not found. * - * @param variableDef + * @param variableDef the variableDef * @return the subModelNode that is referenced by the given VariableDef - * @throws ServiceError + * @throws ServiceError if an error occurs */ FcModelNode getNodeFromVariableDef(VariableDefs.SEQUENCE variableDef) throws ServiceError { diff --git a/src/main/java/com/beanit/iec61850bean/ServerSap.java b/src/main/java/com/beanit/iec61850bean/ServerSap.java index c125b72..9ca5c7a 100644 --- a/src/main/java/com/beanit/iec61850bean/ServerSap.java +++ b/src/main/java/com/beanit/iec61850bean/ServerSap.java @@ -39,10 +39,10 @@ public final class ServerSap { final ServerModel serverModel; byte[] servicesSupportedCalled = new byte[] {(byte) 0xee, 0x1c, 0, 0, 0x04, 0x08, 0, 0, 0x79, (byte) 0xef, 0x18}; - byte[] cbbBitString = {(byte) (0xfb), 0x00}; + byte[] cbbBitString = {(byte) 0xfb, 0x00}; ServerEventListener serverEventListener; Timer timer; - List associations = new ArrayList<>(); + final List associations = new ArrayList<>(); boolean listening = false; private int proposedMaxMmsPduSize = 65000; private int proposedMaxServOutstandingCalling = 5; diff --git a/src/main/java/com/beanit/iec61850bean/ServiceError.java b/src/main/java/com/beanit/iec61850bean/ServiceError.java index 16ea81a..2f99d7f 100644 --- a/src/main/java/com/beanit/iec61850bean/ServiceError.java +++ b/src/main/java/com/beanit/iec61850bean/ServiceError.java @@ -44,22 +44,26 @@ public final class ServiceError extends Exception { private final int errorCode; public ServiceError(int errorCode) { - super("Error code=" + errorCode); - this.errorCode = errorCode; + this(errorCode, "", null); } public ServiceError(int errorCode, String s) { - super(s); - this.errorCode = errorCode; + this(errorCode, s, null); } public ServiceError(int errorCode, Throwable cause) { - super(cause); - this.errorCode = errorCode; + this(errorCode, "", cause); } public ServiceError(int errorCode, String s, Throwable cause) { - super(s, cause); + super( + "Service error: " + + getErrorName(errorCode) + + "(" + + errorCode + + ")" + + (s.isEmpty() ? "" : (" " + s)), + cause); this.errorCode = errorCode; } @@ -115,14 +119,4 @@ public final class ServiceError extends Exception { public int getErrorCode() { return errorCode; } - - @Override - public String toString() { - String message = getLocalizedMessage(); - String result = getClass().getName() + ": " + getErrorName(errorCode) + "(" + errorCode + ")"; - if (message != null) { - result += ": " + message; - } - return result; - } } diff --git a/src/main/java/com/beanit/iec61850bean/Urcb.java b/src/main/java/com/beanit/iec61850bean/Urcb.java index 6ad5f8a..9d00e4c 100644 --- a/src/main/java/com/beanit/iec61850bean/Urcb.java +++ b/src/main/java/com/beanit/iec61850bean/Urcb.java @@ -13,6 +13,8 @@ */ package com.beanit.iec61850bean; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.beanit.asn1bean.ber.types.BerBitString; import com.beanit.iec61850bean.internal.mms.asn1.AccessResult; import com.beanit.iec61850bean.internal.mms.asn1.Data; @@ -213,7 +215,7 @@ public class Urcb extends Rcb { if (integrity || gi) { for (int i = 0; i < dataSetSize; i++) { - inclusionStringArray[i / 8] |= 1 << (7 - i % 8); + inclusionStringArray[i / 8] = (byte) (inclusionStringArray[i / 8] | 1 << (7 - i % 8)); } BerBitString inclusionString = new BerBitString(inclusionStringArray, dataSetSize); @@ -251,7 +253,8 @@ public class Urcb extends Rcb { int index = 0; for (FcModelNode dataSetMember : dataSet) { if (membersToBeReported.get(dataSetMember) != null) { - inclusionStringArray[index / 8] |= 1 << (7 - index % 8); + inclusionStringArray[index / 8] = + (byte) (inclusionStringArray[index / 8] | 1 << (7 - index % 8)); } index++; } @@ -289,18 +292,14 @@ public class Urcb extends Rcb { } ObjectName objectName = new ObjectName(); - objectName.setVmdSpecific(new Identifier("RPT".getBytes())); + objectName.setVmdSpecific(new Identifier("RPT".getBytes(UTF_8))); VariableAccessSpecification varAccSpec = new VariableAccessSpecification(); varAccSpec.setVariableListName(objectName); - // null, - // new ObjectName(new Identifier("RPT".getBytes()), null, null)); InformationReport infoReport = new InformationReport(); infoReport.setVariableAccessSpecification(varAccSpec); infoReport.setListOfAccessResult(listOfAccessResult); - // varAccSpec, - // new InformationReport.ListOfAccessResult(listOfAccessResult)); UnconfirmedService unconfirmedService = new UnconfirmedService(); unconfirmedService.setInformationReport(infoReport); diff --git a/src/main/java/com/beanit/iec61850bean/app/ConsoleClient.java b/src/main/java/com/beanit/iec61850bean/app/ConsoleClient.java index 30249bd..a8cb403 100644 --- a/src/main/java/com/beanit/iec61850bean/app/ConsoleClient.java +++ b/src/main/java/com/beanit/iec61850bean/app/ConsoleClient.java @@ -342,7 +342,7 @@ public class ConsoleClient { System.out.print( "Set the trigger options (data change, data update, quality change, interity, GI):"); String triggerOptionsString = actionProcessor.getReader().readLine(); - String[] triggerOptionsStrings = triggerOptionsString.split(","); + String[] triggerOptionsStrings = triggerOptionsString.split(",", -1); BdaTriggerConditions triggerOptions = urcb.getTrgOps(); triggerOptions.setDataChange( Boolean.parseBoolean(triggerOptionsStrings[0])); diff --git a/src/main/java/com/beanit/iec61850bean/clientgui/BasicDataBind.java b/src/main/java/com/beanit/iec61850bean/clientgui/BasicDataBind.java index c4d77e4..e99f24c 100644 --- a/src/main/java/com/beanit/iec61850bean/clientgui/BasicDataBind.java +++ b/src/main/java/com/beanit/iec61850bean/clientgui/BasicDataBind.java @@ -23,7 +23,7 @@ public abstract class BasicDataBind { private JComponent valueField; - public BasicDataBind(E data, BdaType type) { + protected BasicDataBind(E data, BdaType type) { if (data.getBasicType() != type) { throw new IllegalArgumentException(data.getName() + " is no " + type); } diff --git a/src/main/java/com/beanit/iec61850bean/clientgui/ClientGui.java b/src/main/java/com/beanit/iec61850bean/clientgui/ClientGui.java index 25a02e2..a981eca 100644 --- a/src/main/java/com/beanit/iec61850bean/clientgui/ClientGui.java +++ b/src/main/java/com/beanit/iec61850bean/clientgui/ClientGui.java @@ -105,8 +105,8 @@ public class ClientGui extends JFrame implements ActionListener, TreeSelectionLi if (in != null) { in.close(); } - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException ignored) { + // there is nothing that can be done if closing fails } } @@ -350,6 +350,7 @@ public class ClientGui extends JFrame implements ActionListener, TreeSelectionLi out.close(); } } catch (IOException e) { + // nothing meaningful can be done if closing fails } } diff --git a/src/main/java/com/beanit/iec61850bean/clientgui/ServerModelParser.java b/src/main/java/com/beanit/iec61850bean/clientgui/ServerModelParser.java index 2f493a2..e904391 100644 --- a/src/main/java/com/beanit/iec61850bean/clientgui/ServerModelParser.java +++ b/src/main/java/com/beanit/iec61850bean/clientgui/ServerModelParser.java @@ -24,7 +24,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import javax.swing.tree.TreeNode; @@ -85,7 +84,7 @@ public class ServerModelParser { } childMap.get(child.getName()).add(((FcModelNode) child).getFc()); } - for (Entry> childEntry : childMap.entrySet()) { + for (Map.Entry> childEntry : childMap.entrySet()) { addFunctionalConstraintObject(treeLN, node, childEntry.getKey(), childEntry.getValue()); } } @@ -95,7 +94,7 @@ public class ServerModelParser { parent.add(treeDS); Collection children = node.getMembers(); for (ModelNode child : children) { - addFunctionalConstraintObject(treeDS, node, child); + addFunctionalConstraintObject(treeDS, child); } } @@ -110,8 +109,7 @@ public class ServerModelParser { } } - private void addFunctionalConstraintObject( - DataSetTreeNode parent, DataSet parentNode, ModelNode node) { + private void addFunctionalConstraintObject(DataSetTreeNode parent, ModelNode node) { DataObjectTreeNode treeFCDO = new DataObjectTreeNode(node.getReference().toString(), node); parent.add(treeFCDO); if (node.getChildren() != null) { diff --git a/src/main/java/com/beanit/iec61850bean/clientgui/databind/TextFieldDataBind.java b/src/main/java/com/beanit/iec61850bean/clientgui/databind/TextFieldDataBind.java index 7f7aeba..4b4e7a3 100644 --- a/src/main/java/com/beanit/iec61850bean/clientgui/databind/TextFieldDataBind.java +++ b/src/main/java/com/beanit/iec61850bean/clientgui/databind/TextFieldDataBind.java @@ -29,7 +29,7 @@ public abstract class TextFieldDataBind extends Ba private final DocumentFilter filter; protected JTextField inputField; - public TextFieldDataBind(E data, BdaType type, AbstractFilter filter) { + TextFieldDataBind(E data, BdaType type, AbstractFilter filter) { super(data, type); this.filter = filter; } diff --git a/src/main/java/com/beanit/iec61850bean/clientgui/databind/TimeStampDataBind.java b/src/main/java/com/beanit/iec61850bean/clientgui/databind/TimeStampDataBind.java index 9736a42..d193463 100644 --- a/src/main/java/com/beanit/iec61850bean/clientgui/databind/TimeStampDataBind.java +++ b/src/main/java/com/beanit/iec61850bean/clientgui/databind/TimeStampDataBind.java @@ -15,69 +15,36 @@ package com.beanit.iec61850bean.clientgui.databind; import com.beanit.iec61850bean.BdaTimestamp; import com.beanit.iec61850bean.BdaType; -import com.beanit.iec61850bean.clientgui.BasicDataBind; -import com.toedter.calendar.JDateChooser; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.util.Date; -import javax.swing.Box; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.JSpinner; -import javax.swing.SpinnerDateModel; +import java.time.Instant; +import java.time.format.DateTimeParseException; -public class TimeStampDataBind extends BasicDataBind { +public class TimeStampDataBind extends TextFieldDataBind { - private static final Dimension DATECHOOSERDIMENSION = new Dimension(120, 20); - - private JDateChooser dateChooser; - private JSpinner timeSpinner; + private static final TimestampFilter FILTER = new TimestampFilter(); public TimeStampDataBind(BdaTimestamp data) { - super(data, BdaType.TIMESTAMP); - } - - @Override - protected JComponent init() { - dateChooser = new JDateChooser(); - dateChooser.setDateFormatString("dd-MM-yyyy"); - dateChooser.setPreferredSize(DATECHOOSERDIMENSION); - timeSpinner = new JSpinner(new SpinnerDateModel()); - JSpinner.DateEditor timeEditor = new JSpinner.DateEditor(timeSpinner, "HH:mm:ss"); - timeSpinner.setEditor(timeEditor); - - Date d = data.getDate(); - if (d == null) { - d = new Date(0); - } - dateChooser.setDate(d); - timeSpinner.setValue(d); - - JPanel dateTimePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); - dateTimePanel.add(dateChooser); - dateTimePanel.add(Box.createRigidArea(new Dimension(5, 0))); - dateTimePanel.add(timeSpinner); - return dateTimePanel; + super(data, BdaType.TIMESTAMP, FILTER); } @Override protected void resetImpl() { - Date d = data.getDate(); - if (d == null) { - d = new Date(0); - } - dateChooser.setDate(d); - timeSpinner.setValue(d); + inputField.setText(data.getInstant().toString()); } - @SuppressWarnings("deprecation") @Override protected void writeImpl() { - Date newDate = dateChooser.getDate(); - Date timeValues = (Date) timeSpinner.getValue(); - newDate.setHours(timeValues.getHours()); - newDate.setMinutes(timeValues.getMinutes()); - newDate.setSeconds(timeValues.getSeconds()); - data.setDate(newDate); + data.setInstant(Instant.parse(inputField.getText())); + } + + private static class TimestampFilter extends AbstractFilter { + @Override + protected boolean test(String text) { + try { + Instant.parse(text); + return true; + } catch (DateTimeParseException e) { + return false; + } + } } } diff --git a/src/main/java/com/beanit/iec61850bean/internal/HexString.java b/src/main/java/com/beanit/iec61850bean/internal/HexString.java index e83c3d8..0636370 100644 --- a/src/main/java/com/beanit/iec61850bean/internal/HexString.java +++ b/src/main/java/com/beanit/iec61850bean/internal/HexString.java @@ -45,7 +45,7 @@ public class HexString { * @return the hex string */ public static String fromInt(int i) { - byte[] bytes = new byte[] {(byte) (i >> 24), (byte) (i >> 16), (byte) (i >> 8), (byte) (i)}; + byte[] bytes = new byte[] {(byte) (i >> 24), (byte) (i >> 16), (byte) (i >> 8), (byte) i}; return fromBytes(bytes); } @@ -65,7 +65,7 @@ public class HexString { (byte) (l >> 24), (byte) (l >> 16), (byte) (l >> 8), - (byte) (l) + (byte) l }; return fromBytes(bytes); } diff --git a/src/main/java/com/beanit/iec61850bean/internal/cli/ActionProcessor.java b/src/main/java/com/beanit/iec61850bean/internal/cli/ActionProcessor.java index bb8d146..a20b9ca 100644 --- a/src/main/java/com/beanit/iec61850bean/internal/cli/ActionProcessor.java +++ b/src/main/java/com/beanit/iec61850bean/internal/cli/ActionProcessor.java @@ -125,6 +125,7 @@ public class ActionProcessor { try { reader.close(); } catch (IOException ignored) { + // if closing fails there is nothing meaningful that can be done } } } diff --git a/src/main/java/com/beanit/iec61850bean/internal/cli/CliParameter.java b/src/main/java/com/beanit/iec61850bean/internal/cli/CliParameter.java index 3d92a1c..8170f73 100644 --- a/src/main/java/com/beanit/iec61850bean/internal/cli/CliParameter.java +++ b/src/main/java/com/beanit/iec61850bean/internal/cli/CliParameter.java @@ -26,17 +26,14 @@ public abstract class CliParameter { optional = builder.optional; } - /** @return the name */ public String getName() { return name; } - /** @return the description */ public String getDescription() { return description; } - /** @return the optional */ public boolean isOptional() { return optional; } diff --git a/src/main/java/com/beanit/iec61850bean/internal/cli/FlagCliParameter.java b/src/main/java/com/beanit/iec61850bean/internal/cli/FlagCliParameter.java index 84e57b0..dc01286 100644 --- a/src/main/java/com/beanit/iec61850bean/internal/cli/FlagCliParameter.java +++ b/src/main/java/com/beanit/iec61850bean/internal/cli/FlagCliParameter.java @@ -41,7 +41,7 @@ public class FlagCliParameter extends CliParameter { } @Override - int parse(String[] args, int i) throws CliParseException { + int parse(String[] args, int i) { selected = true; return 1; } diff --git a/src/main/java/com/beanit/iec61850bean/internal/cli/ValueCliParameter.java b/src/main/java/com/beanit/iec61850bean/internal/cli/ValueCliParameter.java index 6f08d31..c20351b 100644 --- a/src/main/java/com/beanit/iec61850bean/internal/cli/ValueCliParameter.java +++ b/src/main/java/com/beanit/iec61850bean/internal/cli/ValueCliParameter.java @@ -15,7 +15,7 @@ package com.beanit.iec61850bean.internal.cli; abstract class ValueCliParameter extends CliParameter { - String parameterName; + final String parameterName; ValueCliParameter(CliParameterBuilder builder, String parameterName) { super(builder); diff --git a/src/main/java/com/beanit/iec61850bean/internal/scl/AbstractDataAttribute.java b/src/main/java/com/beanit/iec61850bean/internal/scl/AbstractDataAttribute.java index 445f878..11852d2 100644 --- a/src/main/java/com/beanit/iec61850bean/internal/scl/AbstractDataAttribute.java +++ b/src/main/java/com/beanit/iec61850bean/internal/scl/AbstractDataAttribute.java @@ -28,7 +28,7 @@ public abstract class AbstractDataAttribute extends AbstractElement { private String type = null; /* conditional - if bType = "Enum" or "Struct" */ private int count = 0; /* optional - number of array elements */ - public AbstractDataAttribute(Node xmlNode) throws SclParseException { + AbstractDataAttribute(Node xmlNode) throws SclParseException { super(xmlNode); NamedNodeMap attributes = xmlNode.getAttributes(); diff --git a/src/main/java/com/beanit/iec61850bean/internal/scl/AbstractElement.java b/src/main/java/com/beanit/iec61850bean/internal/scl/AbstractElement.java index ee90eaa..5f78cc8 100644 --- a/src/main/java/com/beanit/iec61850bean/internal/scl/AbstractElement.java +++ b/src/main/java/com/beanit/iec61850bean/internal/scl/AbstractElement.java @@ -22,12 +22,12 @@ public abstract class AbstractElement { private String name = null; private String desc = null; - public AbstractElement(String name, String desc) { + AbstractElement(String name, String desc) { this.name = name; this.desc = desc; } - public AbstractElement(Node xmlNode) throws SclParseException { + AbstractElement(Node xmlNode) throws SclParseException { NamedNodeMap attributes = xmlNode.getAttributes(); Node node = attributes.getNamedItem("name"); diff --git a/src/main/java/com/beanit/iec61850bean/internal/scl/AbstractType.java b/src/main/java/com/beanit/iec61850bean/internal/scl/AbstractType.java index 7320637..63d12ec 100644 --- a/src/main/java/com/beanit/iec61850bean/internal/scl/AbstractType.java +++ b/src/main/java/com/beanit/iec61850bean/internal/scl/AbstractType.java @@ -22,7 +22,7 @@ public abstract class AbstractType { // attributes not needed: desc - public AbstractType(Node xmlNode) throws SclParseException { + AbstractType(Node xmlNode) throws SclParseException { Node idNode = xmlNode.getAttributes().getNamedItem("id"); if (idNode == null) { throw new SclParseException("Required attribute \"id\" not found!"); diff --git a/src/main/java/com/beanit/iec61850bean/internal/util/SequenceNumber.java b/src/main/java/com/beanit/iec61850bean/internal/util/SequenceNumber.java new file mode 100644 index 0000000..a486286 --- /dev/null +++ b/src/main/java/com/beanit/iec61850bean/internal/util/SequenceNumber.java @@ -0,0 +1,47 @@ +/* + * Copyright 2019 beanit + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package com.beanit.iec61850bean.internal.util; + +public class SequenceNumber { + + private final int maxValue; + private final int minValue; + private int value; + + public SequenceNumber(int initValue, int minValue, int maxValue) { + assert (initValue >= minValue) && (initValue <= maxValue); + this.minValue = minValue; + this.maxValue = maxValue; + this.value = initValue; + } + + public static int getIncrement(int value, int minValue, int maxValue) { + assert (value >= minValue) && (value <= maxValue); + if (value == maxValue) { + return minValue; + } else { + return ++value; + } + } + + public int getAndIncrement() { + int oldValue = value; + if (value == maxValue) { + value = minValue; + } else { + ++value; + } + return oldValue; + } +} diff --git a/src/main/java/com/beanit/josistack/AcseAssociation.java b/src/main/java/com/beanit/josistack/AcseAssociation.java index 8360a03..8c3edd6 100644 --- a/src/main/java/com/beanit/josistack/AcseAssociation.java +++ b/src/main/java/com/beanit/josistack/AcseAssociation.java @@ -13,6 +13,8 @@ */ package com.beanit.josistack; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream; import com.beanit.asn1bean.ber.types.BerAny; import com.beanit.asn1bean.ber.types.BerInteger; @@ -55,7 +57,6 @@ import java.net.InetAddress; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeoutException; @@ -289,7 +290,9 @@ public final class AcseAssociation { public void accept(ByteBuffer payload) throws IOException { BerAny anyPayload = - new BerAny(Arrays.copyOfRange(payload.array(), payload.position(), payload.limit())); + new BerAny( + Arrays.copyOfRange( + payload.array(), payload.arrayOffset() + payload.position(), payload.limit())); Myexternal.Encoding encoding = new Myexternal.Encoding(); encoding.setSingleASN1Type(anyPayload); @@ -328,9 +331,9 @@ public final class AcseAssociation { reverseOStream.reset(); cpaPPdu.encode(reverseOStream, true); - List ssduList = new LinkedList<>(); - List ssduOffsets = new LinkedList<>(); - List ssduLengths = new LinkedList<>(); + List ssduList = new ArrayList<>(); + List ssduOffsets = new ArrayList<>(); + List ssduLengths = new ArrayList<>(); ssduList.add(reverseOStream.buffer); ssduOffsets.add(reverseOStream.index + 1); @@ -405,7 +408,7 @@ public final class AcseAssociation { sduAcceptHeader[idx++] = (byte) 0xc1; // Parameter length - sduAcceptHeader[idx++] = (byte) ssduLength; + sduAcceptHeader[idx] = (byte) ssduLength; ssdu.add(0, sduAcceptHeader); ssduOffsets.add(0, 0); @@ -420,20 +423,6 @@ public final class AcseAssociation { return returnBuffer; } - /** - * Starts an Application Association by sending an association request and waiting for an - * association accept message - * - * @param payload payload that can be sent with the association request - * @param port - * @param address - * @param tSAP - * @param aeQualifierCalling - * @param aeQualifierCalled - * @param apTitleCalling - * @param apTitleCalled - * @throws IOException - */ void startAssociation( ByteBuffer payload, InetAddress address, @@ -450,7 +439,7 @@ public final class AcseAssociation { int aeQualifierCalled, int aeQualifierCalling) throws IOException { - if (connected == true) { + if (connected) { throw new IOException(); } @@ -466,7 +455,9 @@ public final class AcseAssociation { Myexternal.Encoding encoding = new Myexternal.Encoding(); encoding.setSingleASN1Type( - new BerAny(Arrays.copyOfRange(payload.array(), payload.position(), payload.limit()))); + new BerAny( + Arrays.copyOfRange( + payload.array(), payload.arrayOffset() + payload.position(), payload.limit()))); Myexternal myExternal = new Myexternal(); myExternal.setDirectReference(directReference); @@ -485,7 +476,8 @@ public final class AcseAssociation { new ACSERequirements(new byte[] {(byte) 0x02, (byte) 0x07, (byte) 0x80}); mechanism_name = default_mechanism_name; authentication_value = new AuthenticationValue(); - authentication_value.setCharstring(new BerGraphicString(authenticationParameter.getBytes())); + authentication_value.setCharstring( + new BerGraphicString(authenticationParameter.getBytes(UTF_8))); } AARQApdu aarq = new AARQApdu(); @@ -521,16 +513,15 @@ public final class AcseAssociation { reverseOStream.reset(); cpType.encode(reverseOStream, true); - List ssduList = new LinkedList<>(); - List ssduOffsets = new LinkedList<>(); - List ssduLengths = new LinkedList<>(); + List ssduList = new ArrayList<>(); + List ssduOffsets = new ArrayList<>(); + List ssduLengths = new ArrayList<>(); ssduList.add(reverseOStream.buffer); ssduOffsets.add(reverseOStream.index + 1); ssduLengths.add(reverseOStream.buffer.length - (reverseOStream.index + 1)); - ByteBuffer res = null; - res = + ByteBuffer res = startSConnection( ssduList, ssduOffsets, @@ -546,12 +537,6 @@ public final class AcseAssociation { associateResponseAPDU = decodePConResponse(res); } - /** - * Starts a session layer connection, sends a CONNECT (CN), waits for a ACCEPT (AC) and throws an - * IOException if not successful - * - * @throws IOException - */ private ByteBuffer startSConnection( List ssduList, List ssduOffsets, @@ -564,7 +549,7 @@ public final class AcseAssociation { byte[] sSelRemote, byte[] sSelLocal) throws IOException { - if (connected == true) { + if (connected) { throw new IOException(); } @@ -639,7 +624,7 @@ public final class AcseAssociation { // Parameter type: Session user data (193) spduHeader[idx++] = (byte) 0xc1; // Parameter length - spduHeader[idx++] = (byte) (ssduLength & 0xff); + spduHeader[idx] = (byte) (ssduLength & 0xff); // write session user data ssduList.add(0, spduHeader); @@ -658,7 +643,6 @@ public final class AcseAssociation { } catch (TimeoutException e) { throw new IOException("ResponseTimeout waiting for connection response.", e); } - idx = 0; // read ISO 8327-1 Header // SPDU Type: ACCEPT (14) @@ -774,8 +758,8 @@ public final class AcseAssociation { public void send(ByteBuffer payload) throws IOException { List ssduList = new ArrayList<>(); - List ssduOffsets = new LinkedList<>(); - List ssduLengths = new LinkedList<>(); + List ssduOffsets = new ArrayList<>(); + List ssduLengths = new ArrayList<>(); encodePresentationLayer(payload, ssduList, ssduOffsets, ssduLengths); @@ -791,11 +775,13 @@ public final class AcseAssociation { List ssduLengths) throws IOException { PDVList pdv_list = new PDVList(); - pdv_list.setPresentationContextIdentifier(new PresentationContextIdentifier(3l)); + pdv_list.setPresentationContextIdentifier(new PresentationContextIdentifier(3L)); PDVList.PresentationDataValues presentationDataValues = new PDVList.PresentationDataValues(); presentationDataValues.setSingleASN1Type( - new BerAny(Arrays.copyOfRange(payload.array(), payload.position(), payload.limit()))); + new BerAny( + Arrays.copyOfRange( + payload.array(), payload.arrayOffset() + payload.position(), payload.limit()))); pdv_list.setPresentationDataValues(presentationDataValues); FullyEncodedData fully_encoded_data = new FullyEncodedData(); @@ -814,8 +800,7 @@ public final class AcseAssociation { } private void encodeSessionLayer( - List ssduList, List ssduOffsets, List ssduLengths) - throws IOException { + List ssduList, List ssduOffsets, List ssduLengths) { byte[] spduHeader = new byte[4]; // --write iso 8327-1 Header-- @@ -847,7 +832,7 @@ public final class AcseAssociation { */ public byte[] receive(ByteBuffer pduBuffer) throws DecodingException, IOException, TimeoutException { - if (connected == false) { + if (!connected) { throw new IllegalStateException("ACSE Association not connected"); } tConnection.receive(pduBuffer); @@ -937,7 +922,7 @@ public final class AcseAssociation { } ByteBuffer listenForCn(ByteBuffer pduBuffer) throws IOException, TimeoutException { - if (connected == true) { + if (connected) { throw new IllegalStateException("ACSE Association is already connected"); } int parameter; diff --git a/src/main/java/com/beanit/jositransport/ClientTSap.java b/src/main/java/com/beanit/jositransport/ClientTSap.java index 5777de4..a318541 100644 --- a/src/main/java/com/beanit/jositransport/ClientTSap.java +++ b/src/main/java/com/beanit/jositransport/ClientTSap.java @@ -97,16 +97,16 @@ public final class ClientTSap { /** * Set the maxTPDUSize. The default maxTPduSize is 65531 (see RFC 1006). * - * @param maxTPduSizeParam The maximum length is equal to 2^(maxTPduSizeParam) octets. Note that + * @param maxTPDUSizeParam The maximum length is equal to 2^(maxTPDUSizeParam) octets. Note that * the actual TSDU size that can be transfered is equal to TPduSize-3. Default is 65531 octets - * (see RFC 1006), 7 <= maxTPduSizeParam <= 16, needs to be set before listening or + * (see RFC 1006), 7 <= maxTPDUSizeParam <= 16, needs to be set before listening or * connecting */ - public void setMaxTPDUSizeParam(int maxTPduSizeParam) { - if (maxTPduSizeParam < 7 || maxTPduSizeParam > 16) { + public void setMaxTPDUSizeParam(int maxTPDUSizeParam) { + if (maxTPDUSizeParam < 7 || maxTPDUSizeParam > 16) { throw new IllegalArgumentException("maxTPDUSizeParam is out of bound"); } - this.maxTPDUSizeParam = maxTPduSizeParam; + this.maxTPDUSizeParam = maxTPDUSizeParam; } /** diff --git a/src/main/java/com/beanit/jositransport/ServerTSap.java b/src/main/java/com/beanit/jositransport/ServerTSap.java index 4db0cde..50859ea 100644 --- a/src/main/java/com/beanit/jositransport/ServerTSap.java +++ b/src/main/java/com/beanit/jositransport/ServerTSap.java @@ -186,19 +186,19 @@ public class ServerTSap { /** * Set the maxTPDUSize. The default maxTPduSize is 65531 (see RFC 1006). * - * @param maxTPduSizeParam The maximum length is equal to 2^(maxTPduSizeParam) octets. Note that + * @param maxTPDUSizeParam The maximum length is equal to 2^(maxTPDUSizeParam) octets. Note that * the actual TSDU size that can be transfered is equal to TPduSize-3. Default is 65531 octets - * (see RFC 1006), 7 <= maxTPduSizeParam <= 16, needs to be set before listening or + * (see RFC 1006), 7 <= maxTPDUSizeParam <= 16, needs to be set before listening or * connecting */ - public void setMaxTPDUSizeParam(int maxTPduSizeParam) { + public void setMaxTPDUSizeParam(int maxTPDUSizeParam) { if (started == true) { throw new RuntimeException("Trying to set parameter although server has started."); } - if (maxTPduSizeParam < 7 || maxTPduSizeParam > 16) { + if (maxTPDUSizeParam < 7 || maxTPDUSizeParam > 16) { throw new IllegalArgumentException("maxTPDUSizeParam is out of bound"); } - this.maxTPDUSizeParam = maxTPduSizeParam; + this.maxTPDUSizeParam = maxTPDUSizeParam; } TConnectionListener getConnectionListener() { diff --git a/src/main/java/com/beanit/jositransport/ServerThread.java b/src/main/java/com/beanit/jositransport/ServerThread.java index 8a58e34..02567e6 100644 --- a/src/main/java/com/beanit/jositransport/ServerThread.java +++ b/src/main/java/com/beanit/jositransport/ServerThread.java @@ -106,6 +106,7 @@ final class ServerThread extends Thread { try { serverSocket.close(); } catch (IOException e) { + // there is nothing meaningful to be done when closing fails } } } diff --git a/src/main/java/com/beanit/jositransport/TConnection.java b/src/main/java/com/beanit/jositransport/TConnection.java index b0194d3..8cd6e71 100644 --- a/src/main/java/com/beanit/jositransport/TConnection.java +++ b/src/main/java/com/beanit/jositransport/TConnection.java @@ -13,6 +13,7 @@ */ package com.beanit.jositransport; +import com.beanit.iec61850bean.internal.util.SequenceNumber; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; @@ -28,9 +29,8 @@ import java.util.concurrent.TimeoutException; public final class TConnection { - // private static final Logger logger = LoggerFactory.getLogger(TConnection.class); - - private static Integer connectionCounter = 0; + // some servers do not like srcRef 0 + private static final SequenceNumber connectionCounter = new SequenceNumber(1, 1, 65519); private final Socket socket; private final DataOutputStream os; private final DataInputStream is; @@ -59,13 +59,8 @@ public final class TConnection { os = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); is = new DataInputStream(new BufferedInputStream(socket.getInputStream())); - synchronized (socket) { - connectionCounter++; - connectionCounter %= 65520; - if (connectionCounter == 0) { - connectionCounter = 1; // some servers do not like srcRef 0 - } - srcRef = connectionCounter; + synchronized (connectionCounter) { + srcRef = connectionCounter.getAndIncrement(); } this.messageTimeout = messageTimeout; @@ -82,7 +77,7 @@ public final class TConnection { * According to the norm a syntax error in the CR should be followed by an ER. This implementation * does not send an ER because it seems unnecessary. * - * @throws IOException + * @throws IOException if an error occurs */ void listenForCR() throws IOException { @@ -234,7 +229,7 @@ public final class TConnection { /** * Starts a connection, sends a CR, waits for a CC and throws an IOException if not successful * - * @throws IOException + * @throws IOException if an error occurs */ void startConnection() throws IOException { @@ -632,7 +627,8 @@ public final class TConnection { os.write(0x00); os.flush(); - } catch (IOException e) { + } catch (IOException ignored) { + // io exceptions while disconnecting can be ignored } finally { close(); } @@ -646,10 +642,12 @@ public final class TConnection { // will also close socket os.close(); } catch (Exception e) { + // there is nothing meaningful to be done if closing fails } try { is.close(); } catch (Exception e) { + // there is nothing meaningful to be done if closing fails } if (serverThread != null) { serverThread.connectionClosedSignal(); diff --git a/src/test/java/com/beanit/iec61850bean/integrationtests/ClientServerITest.java b/src/test/java/com/beanit/iec61850bean/integrationtests/ClientServerITest.java index 49f15d8..3508fe1 100644 --- a/src/test/java/com/beanit/iec61850bean/integrationtests/ClientServerITest.java +++ b/src/test/java/com/beanit/iec61850bean/integrationtests/ClientServerITest.java @@ -13,6 +13,7 @@ */ package com.beanit.iec61850bean.integrationtests; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -150,12 +151,12 @@ public class ClientServerITest extends Thread implements ServerEventListener, Cl namePlateVendor = (BdaVisibleString) serverModel.findModelNode("ied1lDevice1/LLN0.NamPlt.vendor", Fc.DC); - namePlateVendor.setValue("Fraunhofer ISE".getBytes()); + namePlateVendor.setValue("beanit".getBytes(UTF_8)); clientAssociation.setDataValues(namePlateVendor); namePlateVendor.setDefault(); clientAssociation.getDataValues(namePlateVendor); - assertEquals("Fraunhofer ISE", new String(namePlateVendor.getValue())); + assertEquals("beanit", new String(namePlateVendor.getValue(), UTF_8)); // -------------Test DataSets-Start--------------------- @@ -197,7 +198,7 @@ public class ClientServerITest extends Thread implements ServerEventListener, Cl assertNull(serviceError); } - assertTrue("Fraunhofer ISE".equals(new String(namePlateVendor.getValue()))); + assertTrue("beanit".equals(new String(namePlateVendor.getValue(), UTF_8))); clientAssociation.deleteDataSet(nonPersistentDataSet); @@ -258,11 +259,7 @@ public class ClientServerITest extends Thread implements ServerEventListener, Cl // clientAssociation.close(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } + Thread.sleep(1000); clientAssociation2.getDataValues(sbo2); assertEquals(sbo2.getStringValue(), "success"); @@ -274,11 +271,7 @@ public class ClientServerITest extends Thread implements ServerEventListener, Cl clientAssociation2.close(); - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } + Thread.sleep(100); clientAssociation.getDataValues(sbo); assertEquals(sbo.getStringValue(), "success"); @@ -448,7 +441,7 @@ public class ClientServerITest extends Thread implements ServerEventListener, Cl } @Override - public void serverStoppedListening(ServerSap serverSAP) { + public void serverStoppedListening(ServerSap serverSap) { // TODO Auto-generated method stub } @@ -473,7 +466,7 @@ public class ClientServerITest extends Thread implements ServerEventListener, Cl totWBdas.add(q); totWBdas.add(t); - float totWMagVal = 0.0f; + double totWMagVal = 0.0f; q.setValidity(BdaQuality.Validity.GOOD); // for (int i = 0; i < 500000; i++) { @@ -481,7 +474,7 @@ public class ClientServerITest extends Thread implements ServerEventListener, Cl totWMagVal += 1.0; System.out.println("setting totWmag to: " + totWMagVal); - totWMag.setFloat(totWMagVal); + totWMag.setFloat((float) totWMagVal); t.setCurrentTime(); if (q.getValidity() == Validity.GOOD) { @@ -493,7 +486,9 @@ public class ClientServerITest extends Thread implements ServerEventListener, Cl try { Thread.sleep(4000); } catch (InterruptedException e) { + // is not interrupted } + serverSap.setValues(totWBdas); // // Run the garbage collector diff --git a/src/test/java/com/beanit/iec61850bean/integrationtests/ClientServerITest2.java b/src/test/java/com/beanit/iec61850bean/integrationtests/ClientServerITest2.java index 2e2a191..4e28bb3 100644 --- a/src/test/java/com/beanit/iec61850bean/integrationtests/ClientServerITest2.java +++ b/src/test/java/com/beanit/iec61850bean/integrationtests/ClientServerITest2.java @@ -45,8 +45,6 @@ public class ClientServerITest2 extends Thread implements ServerEventListener, C // Get the Java runtime public static Runtime runtime = Runtime.getRuntime(); private static int numReports = 0; - private static int numSuccess = 0; - private static int numAssociationClosed = 0; int port = 54322; String host = "127.0.0.1"; ClientSap clientSap = new ClientSap(); @@ -154,7 +152,7 @@ public class ClientServerITest2 extends Thread implements ServerEventListener, C } @Override - public void serverStoppedListening(ServerSap serverSAP) { + public void serverStoppedListening(ServerSap serverSap) { // TODO Auto-generated method stub } @@ -239,13 +237,10 @@ public class ClientServerITest2 extends Thread implements ServerEventListener, C assertTrue(reasons.get(0).isIntegrity()); assertTrue(reasons.get(1).isIntegrity()); } - - numSuccess++; } @Override public void associationClosed(IOException e) { System.out.println("Association closed!"); - numAssociationClosed++; } } diff --git a/src/test/java/com/beanit/iec61850bean/integrationtests/ReportingTest.java b/src/test/java/com/beanit/iec61850bean/integrationtests/ReportingTest.java index b2dc5ec..2b4ff54 100644 --- a/src/test/java/com/beanit/iec61850bean/integrationtests/ReportingTest.java +++ b/src/test/java/com/beanit/iec61850bean/integrationtests/ReportingTest.java @@ -47,8 +47,6 @@ public class ReportingTest implements ClientEventListener { private static final String CREATED_DATASET_REFERENCE = "ied1lDevice1/LLN0$datasetnew"; private static final String CHANGING_SERVER_DA_REFERENCE_1 = "ied1lDevice1/MMXU1.W.phsA.cVal.mag.f"; - private static final String CHANGING_SERVER_DA_REFERENCE_2 = - "ied1lDevice1/DSCH1.SchdAbsTm.sptestval1"; private static final int PORT = 54321; private static final String ICD_FILE = "src/test/resources/iec61850bean-sample01.icd"; private static final String URCB1_REFERENCE = "ied1lDevice1/LLN0.urcb101"; diff --git a/src/test/java/com/beanit/josistack/SiemensClientITest.java b/src/test/java/com/beanit/josistack/SiemensClientITest.java index d808ea4..f22a7cb 100644 --- a/src/test/java/com/beanit/josistack/SiemensClientITest.java +++ b/src/test/java/com/beanit/josistack/SiemensClientITest.java @@ -283,7 +283,7 @@ public class SiemensClientITest { serverAcseSAP.stopListening(); } - public class SampleServer implements AcseAssociationListener { + public static class SampleServer implements AcseAssociationListener { @Override public void serverStoppedListeningIndication(IOException e) { diff --git a/src/test/java/com/beanit/jositransport/ClientServerITest.java b/src/test/java/com/beanit/jositransport/ClientServerITest.java index 8e13562..80a8b0d 100644 --- a/src/test/java/com/beanit/jositransport/ClientServerITest.java +++ b/src/test/java/com/beanit/jositransport/ClientServerITest.java @@ -60,7 +60,7 @@ public class ClientServerITest { ClientTSap tSAP = new ClientTSap(); tSAP.setMaxTPDUSizeParam(7); - TConnection tConnection = null; + TConnection tConnection; tConnection = tSAP.connectTo(address, port); @@ -399,7 +399,7 @@ public class ClientServerITest { return C; } - public class SampleServer implements TConnectionListener { + public static class SampleServer implements TConnectionListener { @Override public void connectionIndication(TConnection tConnection) {