diff --git a/junixsocket-common/pom.xml b/junixsocket-common/pom.xml index 7caaab6d5..b3547c49c 100644 --- a/junixsocket-common/pom.xml +++ b/junixsocket-common/pom.xml @@ -85,5 +85,11 @@ ${project.version} test + + + org.codehaus.mojo + animal-sniffer-annotations + provided + diff --git a/junixsocket-common/src/main/java/module-info.java b/junixsocket-common/src/main/java/module-info.java index b4101a0c4..4d024ea9a 100644 --- a/junixsocket-common/src/main/java/module-info.java +++ b/junixsocket-common/src/main/java/module-info.java @@ -2,6 +2,7 @@ * The common junixsocket classes. */ // NOPMD -- https://github.com/pmd/pmd/issues/4620 +@SuppressWarnings("module") module org.newsclub.net.unix { exports org.newsclub.net.unix; @@ -9,4 +10,5 @@ requires static java.rmi; requires static transitive com.kohlschutter.annotations.compiletime; requires static org.eclipse.jdt.annotation; + requires static animal.sniffer.annotations; } diff --git a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFOutputStream.java b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFOutputStream.java index 9764aeae1..9c84b61f1 100644 --- a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFOutputStream.java +++ b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFOutputStream.java @@ -21,11 +21,14 @@ import java.io.InputStream; import java.io.OutputStream; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; + /** * An {@link OutputStream} for {@link AFSocket}, etc. * * @author Christian Kohlschütter */ +@IgnoreJRERequirement // see src/main/java8 public abstract class AFOutputStream extends OutputStream implements FileDescriptorAccess { AFOutputStream() { super(); diff --git a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSYSTEMSocketAddress.java b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSYSTEMSocketAddress.java index 9678cce2c..354238ed8 100644 --- a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSYSTEMSocketAddress.java +++ b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSYSTEMSocketAddress.java @@ -358,7 +358,7 @@ public static AFSYSTEMSocketAddress of(URI uri, int overridePort) throws SocketE for (String p : host.split("\\.")) { int v; try { - v = Integer.parseUnsignedInt(p); + v = parseUnsignedInt(p, 10); } catch (NumberFormatException e) { throw (SocketException) new SocketException("Unsupported URI: " + uri).initCause(e); } @@ -396,7 +396,7 @@ public URI toURI(String scheme, URI template) throws IOException { ByteBuffer bb = ByteBuffer.wrap(getBytes()); StringBuilder sb = new StringBuilder(); while (bb.remaining() > 0) { - sb.append(Integer.toUnsignedString(bb.getInt())); + sb.append(toUnsignedString(bb.getInt())); if (bb.remaining() > 0) { sb.append('.'); } diff --git a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSelector.java b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSelector.java index 1507a648f..433aac740 100644 --- a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSelector.java +++ b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSelector.java @@ -31,6 +31,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Iterator; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -41,9 +42,10 @@ final class AFSelector extends AbstractSelector { private final ByteBuffer pipeMsgWakeUp = ByteBuffer.allocate(1); private final ByteBuffer pipeMsgReceiveBuffer = ByteBuffer.allocateDirect(256); - private final Set keysRegistered = ConcurrentHashMap.newKeySet(); + private final Map keysRegistered = new ConcurrentHashMap<>(); + private final Set keysRegisteredKeySet = keysRegistered.keySet(); private final Set keysRegisteredPublic = Collections.unmodifiableSet( - keysRegistered); + keysRegisteredKeySet); private final Set selectedKeysSet = new HashSet<>(); private final Set selectedKeysPublic = new UngrowableSet<>(selectedKeysSet); @@ -62,7 +64,7 @@ protected SelectionKey register(AbstractSelectableChannel ch, int ops, Object at AFSelectionKey key = new AFSelectionKey(this, ch, ops, att); synchronized (this) { pollFd = null; - keysRegistered.add(key); + keysRegistered.put(key, Boolean.TRUE); } return key; } @@ -193,7 +195,7 @@ private synchronized void setOpsReady(PollFd pfd) { @SuppressWarnings({"resource", "PMD.CognitiveComplexity"}) private PollFd initPollFd(PollFd existingPollFd) throws IOException { synchronized (this) { - for (Iterator it = keysRegistered.iterator(); it.hasNext();) { + for (Iterator it = keysRegisteredKeySet.iterator(); it.hasNext();) { AFSelectionKey key = it.next(); if (!key.getAFCore().fd.valid() || key.hasOpInvalid()) { key.cancelNoRemove(); @@ -209,7 +211,7 @@ private PollFd initPollFd(PollFd existingPollFd) throws IOException { (existingPollFd.keys.length - 1) == keysRegistered.size()) { boolean needsUpdate = false; int i = 1; - for (AFSelectionKey key : keysRegistered) { + for (AFSelectionKey key : keysRegisteredKeySet) { if (existingPollFd.keys[i] != key || !key.isValid()) { // NOPMD needsUpdate = true; break; @@ -225,7 +227,7 @@ private PollFd initPollFd(PollFd existingPollFd) throws IOException { } int keysToPoll = keysRegistered.size(); - for (AFSelectionKey key : keysRegistered) { + for (AFSelectionKey key : keysRegisteredKeySet) { if (!key.isValid()) { keysToPoll--; } @@ -240,7 +242,7 @@ private PollFd initPollFd(PollFd existingPollFd) throws IOException { ops[0] = SelectionKey.OP_READ; int i = 1; - for (AFSelectionKey key : keysRegistered) { + for (AFSelectionKey key : keysRegisteredKeySet) { if (!key.isValid()) { continue; } diff --git a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSocketAddress.java b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSocketAddress.java index 278f00037..4109a1644 100644 --- a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSocketAddress.java +++ b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSocketAddress.java @@ -906,4 +906,64 @@ private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeUTF(addressFamily == null ? "undefined" : addressFamily.getJuxString()); } + + /** + * Returns a string representation of the argument as an unsigned decimal value. + *

+ * Works like {@link Integer#toUnsignedString(int)}; added to allow execution on Java 1.7. + * + * @param i The value. + * @return The string. + */ + protected static String toUnsignedString(int i) { + return Long.toString(toUnsignedLong(i)); + } + + /** + * Returns a string representation of the first argument as an unsigned integer value in the radix + * specified by the second argument; added to allow execution on Java 1.7. + * + * @param i The value. + * @param radix The radix. + * @return The string. + */ + protected static String toUnsignedString(int i, int radix) { + return Long.toUnsignedString(toUnsignedLong(i), radix); + } + + private static long toUnsignedLong(long x) { + return x & 0xffffffffL; + } + + /** + * Parses the string argument as an unsigned integer in the radix specified by the second + * argument. Works like {@link Integer#parseUnsignedInt(String, int)}; added to allow execution on + * Java 1.7. + * + * @param s The string. + * @param radix The radix. + * @return The integer. + * @throws NumberFormatException on parse error. + */ + protected static int parseUnsignedInt(String s, int radix) throws NumberFormatException { + if (s == null || s.isEmpty()) { + throw new NumberFormatException("Cannot parse null or empty string"); + } + + int len = s.length(); + if (s.startsWith("-")) { + throw new NumberFormatException("Illegal leading minus sign on unsigned string " + s); + } + + if (len <= 5 || (radix == 10 && len <= 9)) { + return Integer.parseInt(s, radix); + } else { + long ell = Long.parseLong(s, radix); + if ((ell & 0xffff_ffff_0000_0000L) == 0) { + return (int) ell; + } else { + throw new NumberFormatException("String value exceeds " + "range of unsigned int: " + s); + } + } + } } diff --git a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFTIPCSocketAddress.java b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFTIPCSocketAddress.java index 2a5ec519f..a06f6f918 100644 --- a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFTIPCSocketAddress.java +++ b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFTIPCSocketAddress.java @@ -171,8 +171,8 @@ public static final class AddressType extends NamedInteger { private AddressType(int id) { super(id); - this.ds = (a, b, c) -> ":" + Integer.toUnsignedString(a) + ":" + Integer.toUnsignedString(b) - + ":" + Integer.toUnsignedString(c); + this.ds = (a, b, c) -> ":" + toUnsignedString(a) + ":" + toUnsignedString(b) + ":" + + toUnsignedString(c); } private AddressType(String name, int id, DebugStringProvider ds) { @@ -431,9 +431,9 @@ public static AFTIPCSocketAddress ofTopologyService() throws SocketException { private static int parseUnsignedInt(String v) { if (v.startsWith("0x")) { - return Integer.parseUnsignedInt(v.substring(2), 16); + return parseUnsignedInt(v.substring(2), 16); } else { - return Integer.parseUnsignedInt(v); + return parseUnsignedInt(v, 10); } } @@ -686,9 +686,9 @@ protected Set uriSchemes() { private String toTipcInt(int v) { if (v < 0) { - return "0x" + Integer.toUnsignedString(v, 16); + return "0x" + toUnsignedString(v, 16); } else { - return Integer.toUnsignedString(v); + return toUnsignedString(v); } } diff --git a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFVSOCKSocketAddress.java b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFVSOCKSocketAddress.java index d9cc795e8..afd39270b 100644 --- a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFVSOCKSocketAddress.java +++ b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFVSOCKSocketAddress.java @@ -518,7 +518,7 @@ public URI toURI(String scheme, URI template) throws IOException { portStr = "any"; break; default: - portStr = Integer.toUnsignedString(port); + portStr = toUnsignedString(port); break; } @@ -540,7 +540,7 @@ public URI toURI(String scheme, URI template) throws IOException { cidStr = "host"; break; default: - cidStr = Integer.toUnsignedString(cid); + cidStr = toUnsignedString(cid); break; } @@ -551,11 +551,11 @@ public URI toURI(String scheme, URI template) throws IOException { private static int parseInt(String v) { if (v.startsWith("0x")) { - return Integer.parseUnsignedInt(v.substring(2), 16); + return parseUnsignedInt(v.substring(2), 16); } else if (v.startsWith("-")) { return Integer.parseInt(v); } else { - return Integer.parseUnsignedInt(v); + return parseUnsignedInt(v, 10); } } diff --git a/junixsocket-common/src/main/java/org/newsclub/net/unix/CleanableState.java b/junixsocket-common/src/main/java/org/newsclub/net/unix/CleanableState.java index b3db5d71f..4e7cf73ca 100644 --- a/junixsocket-common/src/main/java/org/newsclub/net/unix/CleanableState.java +++ b/junixsocket-common/src/main/java/org/newsclub/net/unix/CleanableState.java @@ -21,6 +21,8 @@ import java.io.IOException; import java.lang.ref.Cleaner; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; + /** * This wrapper (along with the Java 8-specific counterpart in src/main/java8) allows us to * implement cleanup logic for objects that are garbage-collectable/no longer reachable. @@ -49,6 +51,7 @@ * * @author Christian Kohlschütter */ +@IgnoreJRERequirement // see src/main/java8 abstract class CleanableState implements Closeable { private static final Cleaner CLEANER = Cleaner.create(); private final Cleaner.Cleanable cleanable; diff --git a/junixsocket-common/src/main/java/org/newsclub/net/unix/DatagramSocketShim.java b/junixsocket-common/src/main/java/org/newsclub/net/unix/DatagramSocketShim.java index f9619357d..862e435b4 100644 --- a/junixsocket-common/src/main/java/org/newsclub/net/unix/DatagramSocketShim.java +++ b/junixsocket-common/src/main/java/org/newsclub/net/unix/DatagramSocketShim.java @@ -22,6 +22,9 @@ import java.net.DatagramSocketImpl; import java.net.SocketOption; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; + +@IgnoreJRERequirement // see src/main/java8 abstract class DatagramSocketShim extends DatagramSocket { protected DatagramSocketShim(DatagramSocketImpl impl) { diff --git a/junixsocket-common/src/main/java/org/newsclub/net/unix/PathUtil.java b/junixsocket-common/src/main/java/org/newsclub/net/unix/PathUtil.java index 6ff8144d3..0b3d4cf25 100644 --- a/junixsocket-common/src/main/java/org/newsclub/net/unix/PathUtil.java +++ b/junixsocket-common/src/main/java/org/newsclub/net/unix/PathUtil.java @@ -21,11 +21,14 @@ import java.nio.file.FileSystems; import java.nio.file.Path; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; + /** * Some {@link Path}-related helper methods. * * @author Christian Kohlschütter */ +@IgnoreJRERequirement // see src/main/java8 final class PathUtil { private PathUtil() { throw new IllegalStateException("No instances"); diff --git a/junixsocket-common/src/main/java/org/newsclub/net/unix/SocketAddressUtil.java b/junixsocket-common/src/main/java/org/newsclub/net/unix/SocketAddressUtil.java index 2cfcb493c..5569023c3 100644 --- a/junixsocket-common/src/main/java/org/newsclub/net/unix/SocketAddressUtil.java +++ b/junixsocket-common/src/main/java/org/newsclub/net/unix/SocketAddressUtil.java @@ -21,11 +21,14 @@ import java.net.SocketException; import java.net.UnixDomainSocketAddress; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; + /** * {@link SocketAddress}-related helper methods. * * @author Christian Kohlschütter */ +@IgnoreJRERequirement // see src/main/java15 final class SocketAddressUtil { private SocketAddressUtil() { throw new IllegalStateException("No instances");