Merge "Remove dead code related to shutdown hooks."
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index caae4e8..230828d 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -1437,14 +1437,6 @@
name: "org.apache.harmony.tests.java.util.GregorianCalendarTest#test_computeTime"
},
{
- description: "OkHttp tests require SOCKS 5 support. Android PlainSocketImpl implements SOCKS 4",
- bug: 96926,
- names: [
- "com.squareup.okhttp.SocksProxyTest#proxy",
- "com.squareup.okhttp.SocksProxyTest#proxySelector"
- ]
-},
-{
description: "OkHttp tests that fail on Wear devices due to a lack of memory",
bug: 20055487,
names: [
diff --git a/luni/src/test/java/libcore/java/net/URITest.java b/luni/src/test/java/libcore/java/net/URITest.java
index 2c4a06a..edc6577 100644
--- a/luni/src/test/java/libcore/java/net/URITest.java
+++ b/luni/src/test/java/libcore/java/net/URITest.java
@@ -729,13 +729,13 @@
assertEquals("a_b.c.d.net", uri.getHost());
}
- // RFC1034#section-3.5 doesn't permit empty labels in hostnames, but we
- // accepted this prior to N and the behavior is used by some apps. We need
- // to keep the behavior for now for compatibility.
+ // RFC1034#section-3.5 doesn't permit empty labels in hostnames. This was accepted prior to N,
+ // but returns null in later releases.
// http://b/25991669
+ // http://b/29560247
public void testHostWithEmptyLabel() throws Exception {
- assertEquals(".example.com", new URI("http://.example.com/").getHost());
- assertEquals("example..com", new URI("http://example..com/").getHost());
+ assertNull(new URI("http://.example.com/").getHost());
+ assertNull(new URI("http://example..com/").getHost());
}
// Adding a new test? Consider adding an equivalent test to URLTest.java
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index 7c5cc42..7873e99 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -26,11 +26,9 @@
import junit.framework.TestCase;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -94,10 +92,6 @@
import static com.google.mockwebserver.SocketPolicy.FAIL_HANDSHAKE;
import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END;
import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.spy;
public final class URLConnectionTest extends TestCase {
@@ -1979,22 +1973,15 @@
@Override
protected Socket configureSocket(Socket socket) throws IOException {
final int attemptNumber = socketCreationCount[0]++;
- Answer socketConnectAnswer = new Answer() {
- @Override public Object answer(InvocationOnMock invocation)
- throws Throwable {
- int timeoutArg = (int) invocation.getArguments()[1];
- socketConnectTimeouts[attemptNumber] = timeoutArg;
- throw new SocketTimeoutException(
- "Simulated timeout after " + timeoutArg);
+ Socket socketWrapper = new DelegatingSocket(socket) {
+ @Override
+ public void connect(SocketAddress endpoint, int timeout)
+ throws IOException {
+ socketConnectTimeouts[attemptNumber] = timeout;
+ throw new SocketTimeoutException("Simulated timeout after " + timeout);
}
};
-
- Socket socketSpy = spy(socket);
- // Create a partial mock that wraps the actual socket and intercepts the
- // connect(SocketAddress, int) method.
- doAnswer(socketConnectAnswer)
- .when(socketSpy).connect(any(SocketAddress.class), anyInt());
- return socketSpy;
+ return socketWrapper;
}
});
@@ -3153,6 +3140,64 @@
}
/**
+ * A Socket that forwards all calls to public or protected methods, except for those
+ * that Socket inherits from Object, to a delegate.
+ */
+ private static abstract class DelegatingSocket extends Socket {
+ private final Socket delegate;
+
+ public DelegatingSocket(Socket delegate) {
+ if (delegate == null) {
+ throw new NullPointerException();
+ }
+ this.delegate = delegate;
+ }
+
+ @Override public void bind(SocketAddress bindpoint) throws IOException { delegate.bind(bindpoint); }
+ @Override public void close() throws IOException { delegate.close(); }
+ @Override public void connect(SocketAddress endpoint) throws IOException { delegate.connect(endpoint); }
+ @Override public void connect(SocketAddress endpoint, int timeout) throws IOException { delegate.connect(endpoint, timeout); }
+ @Override public SocketChannel getChannel() { return delegate.getChannel(); }
+ @Override public FileDescriptor getFileDescriptor$() { return delegate.getFileDescriptor$(); }
+ @Override public InetAddress getInetAddress() { return delegate.getInetAddress(); }
+ @Override public InputStream getInputStream() throws IOException { return delegate.getInputStream(); }
+ @Override public boolean getKeepAlive() throws SocketException { return delegate.getKeepAlive(); }
+ @Override public InetAddress getLocalAddress() { return delegate.getLocalAddress(); }
+ @Override public int getLocalPort() { return delegate.getLocalPort(); }
+ @Override public SocketAddress getLocalSocketAddress() { return delegate.getLocalSocketAddress(); }
+ @Override public boolean getOOBInline() throws SocketException { return delegate.getOOBInline(); }
+ @Override public OutputStream getOutputStream() throws IOException { return delegate.getOutputStream(); }
+ @Override public int getPort() { return delegate.getPort(); }
+ @Override public int getReceiveBufferSize() throws SocketException { return delegate.getReceiveBufferSize(); }
+ @Override public SocketAddress getRemoteSocketAddress() { return delegate.getRemoteSocketAddress(); }
+ @Override public boolean getReuseAddress() throws SocketException { return delegate.getReuseAddress(); }
+ @Override public int getSendBufferSize() throws SocketException { return delegate.getSendBufferSize(); }
+ @Override public int getSoLinger() throws SocketException { return delegate.getSoLinger(); }
+ @Override public int getSoTimeout() throws SocketException { return delegate.getSoTimeout(); }
+ @Override public boolean getTcpNoDelay() throws SocketException { return delegate.getTcpNoDelay(); }
+ @Override public int getTrafficClass() throws SocketException { return delegate.getTrafficClass(); }
+ @Override public boolean isBound() { return delegate.isBound(); }
+ @Override public boolean isClosed() { return delegate.isClosed(); }
+ @Override public boolean isConnected() { return delegate.isConnected(); }
+ @Override public boolean isInputShutdown() { return delegate.isInputShutdown(); }
+ @Override public boolean isOutputShutdown() { return delegate.isOutputShutdown(); }
+ @Override public void sendUrgentData(int data) throws IOException { delegate.sendUrgentData(data); }
+ @Override public void setKeepAlive(boolean on) throws SocketException { delegate.setKeepAlive(on); }
+ @Override public void setOOBInline(boolean on) throws SocketException { delegate.setOOBInline(on); }
+ @Override public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { delegate.setPerformancePreferences(connectionTime, latency, bandwidth); }
+ @Override public void setReceiveBufferSize(int size) throws SocketException { delegate.setReceiveBufferSize(size); }
+ @Override public void setReuseAddress(boolean on) throws SocketException { delegate.setReuseAddress(on); }
+ @Override public void setSendBufferSize(int size) throws SocketException { delegate.setSendBufferSize(size); }
+ @Override public void setSoLinger(boolean on, int linger) throws SocketException { delegate.setSoLinger(on, linger); }
+ @Override public void setSoTimeout(int timeout) throws SocketException { delegate.setSoTimeout(timeout); }
+ @Override public void setTcpNoDelay(boolean on) throws SocketException { delegate.setTcpNoDelay(on); }
+ @Override public void setTrafficClass(int tc) throws SocketException { delegate.setTrafficClass(tc); }
+ @Override public void shutdownInput() throws IOException { delegate.shutdownInput(); }
+ @Override public void shutdownOutput() throws IOException { delegate.shutdownOutput(); }
+ @Override public String toString() { return delegate.toString(); }
+ }
+
+ /**
* An {@link javax.net.ssl.SSLSocket} that delegates all calls.
*/
private static abstract class DelegatingSSLSocket extends SSLSocket {
diff --git a/ojluni/src/main/java/java/net/DatagramSocket.java b/ojluni/src/main/java/java/net/DatagramSocket.java
index 6d43ad0..6925816 100755
--- a/ojluni/src/main/java/java/net/DatagramSocket.java
+++ b/ojluni/src/main/java/java/net/DatagramSocket.java
@@ -215,9 +215,7 @@
* @see SecurityManager#checkListen
*/
public DatagramSocket() throws SocketException {
- // create a datagram socket.
- createImpl();
- bind(new InetSocketAddress(0));
+ this(new InetSocketAddress(0));
}
/**
@@ -262,7 +260,12 @@
// create a datagram socket.
createImpl();
if (bindaddr != null) {
- bind(bindaddr);
+ try {
+ bind(bindaddr);
+ } finally {
+ if (!isBound())
+ close();
+ }
}
}
@@ -354,6 +357,7 @@
}
// creates a udp socket
impl.create();
+ impl.setDatagramSocket(this);
created = true;
}
diff --git a/ojluni/src/main/java/java/net/DatagramSocketImpl.java b/ojluni/src/main/java/java/net/DatagramSocketImpl.java
index bbabc03..bdee48c 100755
--- a/ojluni/src/main/java/java/net/DatagramSocketImpl.java
+++ b/ojluni/src/main/java/java/net/DatagramSocketImpl.java
@@ -54,6 +54,20 @@
}
/**
+ * The DatagramSocket or MulticastSocket
+ * that owns this impl
+ */
+ DatagramSocket socket;
+
+ void setDatagramSocket(DatagramSocket socket) {
+ this.socket = socket;
+ }
+
+ DatagramSocket getDatagramSocket() {
+ return socket;
+ }
+
+ /**
* Creates a datagram socket.
* @exception SocketException if there is an error in the
* underlying protocol, such as a TCP error.
@@ -239,6 +253,56 @@
return localPort;
}
+ <T> void setOption(SocketOption<T> name, T value) throws IOException {
+ if (name == StandardSocketOptions.SO_SNDBUF) {
+ setOption(SocketOptions.SO_SNDBUF, value);
+ } else if (name == StandardSocketOptions.SO_RCVBUF) {
+ setOption(SocketOptions.SO_RCVBUF, value);
+ } else if (name == StandardSocketOptions.SO_REUSEADDR) {
+ setOption(SocketOptions.SO_REUSEADDR, value);
+ } else if (name == StandardSocketOptions.IP_TOS) {
+ setOption(SocketOptions.IP_TOS, value);
+ } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
+ (getDatagramSocket() instanceof MulticastSocket)) {
+ setOption(SocketOptions.IP_MULTICAST_IF2, value);
+ } else if (name == StandardSocketOptions.IP_MULTICAST_TTL &&
+ (getDatagramSocket() instanceof MulticastSocket)) {
+ if (! (value instanceof Integer)) {
+ throw new IllegalArgumentException("not an integer");
+ }
+ setTimeToLive((Integer)value);
+ } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP &&
+ (getDatagramSocket() instanceof MulticastSocket)) {
+ setOption(SocketOptions.IP_MULTICAST_LOOP, value);
+ } else {
+ throw new UnsupportedOperationException("unsupported option");
+ }
+ }
+
+ <T> T getOption(SocketOption<T> name) throws IOException {
+ if (name == StandardSocketOptions.SO_SNDBUF) {
+ return (T) getOption(SocketOptions.SO_SNDBUF);
+ } else if (name == StandardSocketOptions.SO_RCVBUF) {
+ return (T) getOption(SocketOptions.SO_RCVBUF);
+ } else if (name == StandardSocketOptions.SO_REUSEADDR) {
+ return (T) getOption(SocketOptions.SO_REUSEADDR);
+ } else if (name == StandardSocketOptions.IP_TOS) {
+ return (T) getOption(SocketOptions.IP_TOS);
+ } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
+ (getDatagramSocket() instanceof MulticastSocket)) {
+ return (T) getOption(SocketOptions.IP_MULTICAST_IF2);
+ } else if (name == StandardSocketOptions.IP_MULTICAST_TTL &&
+ (getDatagramSocket() instanceof MulticastSocket)) {
+ Integer ttl = getTimeToLive();
+ return (T)ttl;
+ } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP &&
+ (getDatagramSocket() instanceof MulticastSocket)) {
+ return (T) getOption(SocketOptions.IP_MULTICAST_LOOP);
+ } else {
+ throw new UnsupportedOperationException("unsupported option");
+ }
+ }
+
/**
* Gets the datagram socket file descriptor.
* @return a {@code FileDescriptor} object representing the datagram socket
diff --git a/ojluni/src/main/java/java/net/MulticastSocket.java b/ojluni/src/main/java/java/net/MulticastSocket.java
index c3389e1..9de987c 100755
--- a/ojluni/src/main/java/java/net/MulticastSocket.java
+++ b/ojluni/src/main/java/java/net/MulticastSocket.java
@@ -169,7 +169,12 @@
setReuseAddress(true);
if (bindaddr != null) {
- bind(bindaddr);
+ try {
+ bind(bindaddr);
+ } finally {
+ if (!isBound())
+ close();
+ }
}
}
diff --git a/ojluni/src/main/java/java/net/Socket.java b/ojluni/src/main/java/java/net/Socket.java
index c8bfe95..bdb2114 100755
--- a/ojluni/src/main/java/java/net/Socket.java
+++ b/ojluni/src/main/java/java/net/Socket.java
@@ -431,15 +431,18 @@
createImpl(stream);
if (localAddr != null)
bind(localAddr);
- if (address != null)
- connect(address);
- } catch (IOException e) {
- // Do not call #close, classes that extend this class may do not expect a call
- // to #close coming from the superclass constructor.
- if (impl != null) {
- impl.close();
+ connect(address);
+ } catch (IOException | IllegalArgumentException | SecurityException e) {
+ try {
+ // Do not call #close, classes that extend this class may do not expect a call
+ // to #close coming from the superclass constructor.
+ if (impl != null) {
+ impl.close();
+ }
+ closed = true;
+ } catch (IOException ce) {
+ e.addSuppressed(ce);
}
- closed = true;
throw e;
}
}
diff --git a/ojluni/src/main/java/java/net/SocketImpl.java b/ojluni/src/main/java/java/net/SocketImpl.java
index eeacd64..688ba60 100755
--- a/ojluni/src/main/java/java/net/SocketImpl.java
+++ b/ojluni/src/main/java/java/net/SocketImpl.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -362,4 +362,44 @@
{
/* Not implemented yet */
}
+
+ <T> void setOption(SocketOption<T> name, T value) throws IOException {
+ if (name == StandardSocketOptions.SO_KEEPALIVE) {
+ setOption(SocketOptions.SO_KEEPALIVE, value);
+ } else if (name == StandardSocketOptions.SO_SNDBUF) {
+ setOption(SocketOptions.SO_SNDBUF, value);
+ } else if (name == StandardSocketOptions.SO_RCVBUF) {
+ setOption(SocketOptions.SO_RCVBUF, value);
+ } else if (name == StandardSocketOptions.SO_REUSEADDR) {
+ setOption(SocketOptions.SO_REUSEADDR, value);
+ } else if (name == StandardSocketOptions.SO_LINGER) {
+ setOption(SocketOptions.SO_LINGER, value);
+ } else if (name == StandardSocketOptions.IP_TOS) {
+ setOption(SocketOptions.IP_TOS, value);
+ } else if (name == StandardSocketOptions.TCP_NODELAY) {
+ setOption(SocketOptions.TCP_NODELAY, value);
+ } else {
+ throw new UnsupportedOperationException("unsupported option");
+ }
+ }
+
+ <T> T getOption(SocketOption<T> name) throws IOException {
+ if (name == StandardSocketOptions.SO_KEEPALIVE) {
+ return (T)getOption(SocketOptions.SO_KEEPALIVE);
+ } else if (name == StandardSocketOptions.SO_SNDBUF) {
+ return (T)getOption(SocketOptions.SO_SNDBUF);
+ } else if (name == StandardSocketOptions.SO_RCVBUF) {
+ return (T)getOption(SocketOptions.SO_RCVBUF);
+ } else if (name == StandardSocketOptions.SO_REUSEADDR) {
+ return (T)getOption(SocketOptions.SO_REUSEADDR);
+ } else if (name == StandardSocketOptions.SO_LINGER) {
+ return (T)getOption(SocketOptions.SO_LINGER);
+ } else if (name == StandardSocketOptions.IP_TOS) {
+ return (T)getOption(SocketOptions.IP_TOS);
+ } else if (name == StandardSocketOptions.TCP_NODELAY) {
+ return (T)getOption(SocketOptions.TCP_NODELAY);
+ } else {
+ throw new UnsupportedOperationException("unsupported option");
+ }
+ }
}
diff --git a/ojluni/src/main/java/java/net/SocketSecrets.java b/ojluni/src/main/java/java/net/SocketSecrets.java
new file mode 100644
index 0000000..9772906
--- /dev/null
+++ b/ojluni/src/main/java/java/net/SocketSecrets.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.net;
+
+import java.io.IOException;
+
+class SocketSecrets {
+
+ /* accessed by reflection from jdk.net.Sockets */
+
+ /* obj must be a Socket or ServerSocket */
+
+ private static <T> void setOption(Object obj, SocketOption<T> name, T value) throws IOException {
+ SocketImpl impl;
+
+ if (obj instanceof Socket) {
+ impl = ((Socket)obj).getImpl();
+ } else if (obj instanceof ServerSocket) {
+ impl = ((ServerSocket)obj).getImpl();
+ } else {
+ throw new IllegalArgumentException();
+ }
+ impl.setOption(name, value);
+ }
+
+ private static <T> T getOption(Object obj, SocketOption<T> name) throws IOException {
+ SocketImpl impl;
+
+ if (obj instanceof Socket) {
+ impl = ((Socket)obj).getImpl();
+ } else if (obj instanceof ServerSocket) {
+ impl = ((ServerSocket)obj).getImpl();
+ } else {
+ throw new IllegalArgumentException();
+ }
+ return impl.getOption(name);
+ }
+
+ private static <T> void setOption(DatagramSocket s, SocketOption<T> name, T value) throws IOException {
+ s.getImpl().setOption(name, value);
+ }
+
+ private static <T> T getOption(DatagramSocket s, SocketOption<T> name) throws IOException {
+ return s.getImpl().getOption(name);
+ }
+
+}
diff --git a/ojluni/src/main/java/java/net/URI.java b/ojluni/src/main/java/java/net/URI.java
index a49eeaf..cfeb731 100755
--- a/ojluni/src/main/java/java/net/URI.java
+++ b/ojluni/src/main/java/java/net/URI.java
@@ -3365,19 +3365,7 @@
do {
// domainlabel = alphanum [ *( alphanum | "-" | "_" ) alphanum ]
-
- // RFC1034#section-3.5 doesn't permit empty labels in hostnames, but we accepted
- // this prior to N and the behavior is used by some apps. They're accepted for
- // compatibility but we produce a warning in the log.
- // http://b/25991669
- if (p < n && charAt(p) == '.') {
- java.lang.System.logE("URI " + substring(start, n) + " has empty labels in " +
- "the hostname. This is malformed and will not be accepted" +
- "in future Android releases.");
- q = ++p;
- continue;
- }
-
+ //
// The RFCs don't permit underscores in hostnames, but URI has to because a certain
// large website doesn't seem to care about standards and specs.
// http://code.google.com/p/android/issues/detail?id=37577
diff --git a/ojluni/src/main/java/java/text/BreakIterator.java b/ojluni/src/main/java/java/text/BreakIterator.java
index 548a534..951b852 100755
--- a/ojluni/src/main/java/java/text/BreakIterator.java
+++ b/ojluni/src/main/java/java/text/BreakIterator.java
@@ -222,25 +222,26 @@
*
*/
-public abstract class BreakIterator implements Cloneable {
-
+public abstract class BreakIterator implements Cloneable
+{
/**
* Constructor. BreakIterator is stateless and has no default behavior.
*/
- protected BreakIterator() {
+ protected BreakIterator()
+ {
}
/**
* Create a copy of this iterator
- *
* @return A copy of this
*/
- @Override
- public Object clone() {
+ public Object clone()
+ {
try {
return super.clone();
- } catch (CloneNotSupportedException e) {
- throw new AssertionError(e);
+ }
+ catch (CloneNotSupportedException e) {
+ throw new InternalError();
}
}
@@ -254,7 +255,6 @@
/**
* Returns the first boundary. The iterator's current position is set
* to the first text boundary.
- *
* @return The character index of the first text boundary.
*/
public abstract int first();
@@ -262,7 +262,6 @@
/**
* Returns the last boundary. The iterator's current position is set
* to the last text boundary.
- *
* @return The character index of the last text boundary.
*/
public abstract int last();
@@ -279,10 +278,9 @@
* to the (m + 2)th text boundary. A next(4) call would return
* <code>BreakIterator.DONE</code> and the last text boundary would become the
* new text position.
- *
* @param n which boundary to return. A value of 0
- * does nothing. Negative values move to previous boundaries
- * and positive values move to later boundaries.
+ * does nothing. Negative values move to previous boundaries
+ * and positive values move to later boundaries.
* @return The character index of the nth boundary from the current position
* or <code>BreakIterator.DONE</code> if either first or last text boundary
* has been reached.
@@ -294,7 +292,6 @@
* is the last text boundary, it returns <code>BreakIterator.DONE</code> and
* the iterator's current position is unchanged. Otherwise, the iterator's
* current position is set to the boundary following the current boundary.
- *
* @return The character index of the next text boundary or
* <code>BreakIterator.DONE</code> if the current boundary is the last text
* boundary.
@@ -308,7 +305,6 @@
* is the first text boundary, it returns <code>BreakIterator.DONE</code> and
* the iterator's current position is unchanged. Otherwise, the iterator's
* current position is set to the boundary preceding the current boundary.
- *
* @return The character index of the previous text boundary or
* <code>BreakIterator.DONE</code> if the current boundary is the first text
* boundary.
@@ -322,14 +318,12 @@
* Otherwise, the iterator's current position is set to the returned boundary.
* The value returned is always greater than the offset or the value
* <code>BreakIterator.DONE</code>.
- *
* @param offset the character offset to begin scanning.
* @return The first boundary after the specified offset or
* <code>BreakIterator.DONE</code> if the last text boundary is passed in
* as the offset.
- * @throws IllegalArgumentException if the specified offset is less than
- * the first text boundary or greater than the last text
- * boundary.
+ * @exception IllegalArgumentException if the specified offset is less than
+ * the first text boundary or greater than the last text boundary.
*/
public abstract int following(int offset);
@@ -393,7 +387,6 @@
* <code>BreakIterator.DONE</code> because either first or last text boundary
* has been reached, it returns the first or last text boundary depending on
* which one is reached.
- *
* @return The text boundary returned from the above methods, first or last
* text boundary.
* @see #next()
@@ -408,7 +401,6 @@
/**
* Get the text being scanned
- *
* @return the text being scanned
*/
public abstract CharacterIterator getText();
@@ -416,17 +408,16 @@
/**
* Set a new text string to be scanned. The current scan
* position is reset to first().
- *
* @param newText new text to scan.
*/
- public void setText(String newText) {
+ public void setText(String newText)
+ {
setText(new StringCharacterIterator(newText));
}
/**
* Set a new text for scanning. The current scan
* position is reset to first().
- *
* @param newText new text to scan.
*/
public abstract void setText(CharacterIterator newText);
@@ -435,10 +426,10 @@
* Returns a new <code>BreakIterator</code> instance
* for <a href="#word">word breaks</a>
* for the {@linkplain Locale#getDefault() default locale}.
- *
* @return A break iterator for word breaks
*/
- public static BreakIterator getWordInstance() {
+ public static BreakIterator getWordInstance()
+ {
return getWordInstance(Locale.getDefault());
}
@@ -446,12 +437,12 @@
* Returns a new <code>BreakIterator</code> instance
* for <a href="#word">word breaks</a>
* for the given locale.
- *
* @param locale the desired locale
* @return A break iterator for word breaks
- * @throws NullPointerException if <code>locale</code> is null
+ * @exception NullPointerException if <code>locale</code> is null
*/
- public static BreakIterator getWordInstance(Locale locale) {
+ public static BreakIterator getWordInstance(Locale locale)
+ {
return new IcuIteratorWrapper(
android.icu.text.BreakIterator.getWordInstance(locale));
}
@@ -460,10 +451,10 @@
* Returns a new <code>BreakIterator</code> instance
* for <a href="#line">line breaks</a>
* for the {@linkplain Locale#getDefault() default locale}.
- *
* @return A break iterator for line breaks
*/
- public static BreakIterator getLineInstance() {
+ public static BreakIterator getLineInstance()
+ {
return getLineInstance(Locale.getDefault());
}
@@ -471,12 +462,12 @@
* Returns a new <code>BreakIterator</code> instance
* for <a href="#line">line breaks</a>
* for the given locale.
- *
* @param locale the desired locale
* @return A break iterator for line breaks
- * @throws NullPointerException if <code>locale</code> is null
+ * @exception NullPointerException if <code>locale</code> is null
*/
- public static BreakIterator getLineInstance(Locale locale) {
+ public static BreakIterator getLineInstance(Locale locale)
+ {
return new IcuIteratorWrapper(
android.icu.text.BreakIterator.getLineInstance(locale));
}
@@ -485,10 +476,10 @@
* Returns a new <code>BreakIterator</code> instance
* for <a href="#character">character breaks</a>
* for the {@linkplain Locale#getDefault() default locale}.
- *
* @return A break iterator for character breaks
*/
- public static BreakIterator getCharacterInstance() {
+ public static BreakIterator getCharacterInstance()
+ {
return getCharacterInstance(Locale.getDefault());
}
@@ -496,12 +487,12 @@
* Returns a new <code>BreakIterator</code> instance
* for <a href="#character">character breaks</a>
* for the given locale.
- *
* @param locale the desired locale
* @return A break iterator for character breaks
- * @throws NullPointerException if <code>locale</code> is null
+ * @exception NullPointerException if <code>locale</code> is null
*/
- public static BreakIterator getCharacterInstance(Locale locale) {
+ public static BreakIterator getCharacterInstance(Locale locale)
+ {
return new IcuIteratorWrapper(
android.icu.text.BreakIterator.getCharacterInstance(locale));
}
@@ -510,10 +501,10 @@
* Returns a new <code>BreakIterator</code> instance
* for <a href="#sentence">sentence breaks</a>
* for the {@linkplain Locale#getDefault() default locale}.
- *
* @return A break iterator for sentence breaks
*/
- public static BreakIterator getSentenceInstance() {
+ public static BreakIterator getSentenceInstance()
+ {
return getSentenceInstance(Locale.getDefault());
}
@@ -521,12 +512,12 @@
* Returns a new <code>BreakIterator</code> instance
* for <a href="#sentence">sentence breaks</a>
* for the given locale.
- *
* @param locale the desired locale
* @return A break iterator for sentence breaks
- * @throws NullPointerException if <code>locale</code> is null
+ * @exception NullPointerException if <code>locale</code> is null
*/
- public static BreakIterator getSentenceInstance(Locale locale) {
+ public static BreakIterator getSentenceInstance(Locale locale)
+ {
return new IcuIteratorWrapper(
android.icu.text.BreakIterator.getSentenceInstance(locale));
}
@@ -542,9 +533,10 @@
* instance equal to {@link java.util.Locale#US Locale.US}.
*
* @return An array of locales for which localized
- * <code>BreakIterator</code> instances are available.
+ * <code>BreakIterator</code> instances are available.
*/
- public static synchronized Locale[] getAvailableLocales() {
+ public static synchronized Locale[] getAvailableLocales()
+ {
return android.icu.text.BreakIterator.getAvailableLocales();
}
}
diff --git a/ojluni/src/main/java/java/text/CollationElementIterator.java b/ojluni/src/main/java/java/text/CollationElementIterator.java
index 18fc961..bb99acf 100755
--- a/ojluni/src/main/java/java/text/CollationElementIterator.java
+++ b/ojluni/src/main/java/java/text/CollationElementIterator.java
@@ -101,7 +101,8 @@
* @see RuleBasedCollator
* @author Helena Shih, Laura Werner, Richard Gillam
*/
-public final class CollationElementIterator {
+public final class CollationElementIterator
+{
/**
* Null order which indicates the end of string is reached by the
* cursor.
@@ -118,7 +119,8 @@
* Resets the cursor to the beginning of the string. The next call
* to next() will return the first collation element in the string.
*/
- public void reset() {
+ public void reset()
+ {
icuIterator.reset();
}
@@ -136,7 +138,8 @@
* then call previous(), or call previous() and then call next()), you'll get
* back the same element twice.</p>
*/
- public int next() {
+ public int next()
+ {
return icuIterator.next();
}
@@ -153,62 +156,42 @@
* updates the pointer. This means that when you change direction while
* iterating (i.e., call next() and then call previous(), or call previous()
* and then call next()), you'll get back the same element twice.</p>
- *
* @since 1.2
*/
- public int previous() {
+ public int previous()
+ {
return icuIterator.previous();
}
/**
* Return the primary component of a collation element.
- *
* @param order the collation element
* @return the element's primary component
*/
- public final static int primaryOrder(int order) {
+ public final static int primaryOrder(int order)
+ {
return android.icu.text.CollationElementIterator.primaryOrder(order);
}
-
/**
* Return the secondary component of a collation element.
- *
* @param order the collation element
* @return the element's secondary component
*/
- public final static short secondaryOrder(int order) {
- return (short) android.icu.text.CollationElementIterator.secondaryOrder(order);
+ public final static short secondaryOrder(int order)
+ {
+ return (short) android.icu.text.CollationElementIterator.secondaryOrder(order);
}
-
/**
* Return the tertiary component of a collation element.
- *
* @param order the collation element
* @return the element's tertiary component
*/
- public final static short tertiaryOrder(int order) {
+ public final static short tertiaryOrder(int order)
+ {
return (short) android.icu.text.CollationElementIterator.tertiaryOrder(order);
}
/**
- * Returns the character offset in the original text corresponding to the next
- * collation element. (That is, getOffset() returns the position in the text
- * corresponding to the collation element that will be returned by the next
- * call to next().) This value will always be the index of the FIRST character
- * corresponding to the collation element (a contracting character sequence is
- * when two or more characters all correspond to the same collation element).
- * This means if you do setOffset(x) followed immediately by getOffset(), getOffset()
- * won't necessarily return x.
- *
- * @return The character offset in the original text corresponding to the collation
- * element that will be returned by the next call to next().
- * @since 1.2
- */
- public int getOffset() {
- return icuIterator.getOffset();
- }
-
- /**
* Sets the iterator to point to the collation element corresponding to
* the specified character (the parameter is a CHARACTER offset in the
* original string, not an offset into its corresponding sequence of
@@ -223,40 +206,62 @@
* @param newOffset The new character offset into the original text.
* @since 1.2
*/
- public void setOffset(int newOffset) {
+ public void setOffset(int newOffset)
+ {
icuIterator.setOffset(newOffset);
}
/**
+ * Returns the character offset in the original text corresponding to the next
+ * collation element. (That is, getOffset() returns the position in the text
+ * corresponding to the collation element that will be returned by the next
+ * call to next().) This value will always be the index of the FIRST character
+ * corresponding to the collation element (a contracting character sequence is
+ * when two or more characters all correspond to the same collation element).
+ * This means if you do setOffset(x) followed immediately by getOffset(), getOffset()
+ * won't necessarily return x.
+ *
+ * @return The character offset in the original text corresponding to the collation
+ * element that will be returned by the next call to next().
+ * @since 1.2
+ */
+ public int getOffset()
+ {
+ return icuIterator.getOffset();
+ }
+
+ /**
* Return the maximum length of any expansion sequences that end
* with the specified comparison order.
- *
* @param order a collation order returned by previous or next.
* @return the maximum length of any expansion sequences ending
- * with the specified order.
+ * with the specified order.
* @since 1.2
*/
- public int getMaxExpansion(int order) {
+ public int getMaxExpansion(int order)
+ {
return icuIterator.getMaxExpansion(order);
}
/**
* Set a new string over which to iterate.
*
- * @param source the new source text
+ * @param source the new source text
* @since 1.2
*/
- public void setText(String source) {
+ public void setText(String source)
+ {
icuIterator.setText(source);
}
/**
* Set a new string over which to iterate.
*
- * @param source the new source text.
+ * @param source the new source text.
* @since 1.2
*/
- public void setText(CharacterIterator source) {
+ public void setText(CharacterIterator source)
+ {
icuIterator.setText(source);
}
}
diff --git a/ojluni/src/main/java/java/text/Collator.java b/ojluni/src/main/java/java/text/Collator.java
index e442115..863dfe1 100755
--- a/ojluni/src/main/java/java/text/Collator.java
+++ b/ojluni/src/main/java/java/text/Collator.java
@@ -121,13 +121,13 @@
*/
public abstract class Collator
- implements java.util.Comparator<Object>, Cloneable {
+ implements java.util.Comparator<Object>, Cloneable
+{
/**
* Collator strength value. When set, only PRIMARY differences are
* considered significant during comparison. The assignment of strengths
* to language features is locale dependant. A common example is for
* different base letters ("a" vs "b") to be considered a PRIMARY difference.
- *
* @see java.text.Collator#setStrength
* @see java.text.Collator#getStrength
*/
@@ -138,7 +138,6 @@
* to language features is locale dependant. A common example is for
* different accented forms of the same base letter ("a" vs "\u00E4") to be
* considered a SECONDARY difference.
- *
* @see java.text.Collator#setStrength
* @see java.text.Collator#getStrength
*/
@@ -148,7 +147,6 @@
* considered significant during comparison. The assignment of strengths
* to language features is locale dependant. A common example is for
* case differences ("a" vs "A") to be considered a TERTIARY difference.
- *
* @see java.text.Collator#setStrength
* @see java.text.Collator#getStrength
*/
@@ -172,7 +170,6 @@
* set, accented characters will not be decomposed for collation. This
* is the default setting and provides the fastest collation but
* will only produce correct results for languages that do not use accents.
- *
* @see java.text.Collator#getDecomposition
* @see java.text.Collator#setDecomposition
*/
@@ -188,7 +185,6 @@
* described in
* <a href="http://www.unicode.org/unicode/reports/tr15/tr15-23.html">Unicode
* Technical Report #15</a>.
- *
* @see java.text.Collator#getDecomposition
* @see java.text.Collator#setDecomposition
*/
@@ -208,33 +204,14 @@
* described in
* <a href="http://www.unicode.org/unicode/reports/tr15/tr15-23.html">Unicode
* Technical Report #15</a>.
- *
* @see java.text.Collator#getDecomposition
* @see java.text.Collator#setDecomposition
*/
public final static int FULL_DECOMPOSITION = 2;
- android.icu.text.Collator icuColl;
-
- Collator(android.icu.text.Collator icuColl) {
- this.icuColl = icuColl;
- }
-
- /**
- * Default constructor. This constructor is
- * protected so subclasses can get access to it. Users typically create
- * a Collator sub-class by calling the factory method getInstance.
- *
- * @see java.text.Collator#getInstance
- */
- protected Collator() {
- icuColl = android.icu.text.RuleBasedCollator.getInstance(Locale.getDefault());
- }
-
/**
* Gets the Collator for the current default locale.
* The default locale is determined by java.util.Locale.getDefault.
- *
* @return the Collator for the default locale.(for example, en_US)
* @see java.util.Locale#getDefault
*/
@@ -244,13 +221,14 @@
/**
* Gets the Collator for the desired locale.
- *
* @param desiredLocale the desired locale.
* @return the Collator for the desired locale.
* @see java.util.Locale
* @see java.util.ResourceBundle
*/
- public static synchronized Collator getInstance(Locale desiredLocale) {
+ public static synchronized
+ Collator getInstance(Locale desiredLocale)
+ {
if (desiredLocale == null) {
throw new NullPointerException("locale == null");
}
@@ -259,41 +237,6 @@
}
/**
- * Returns an array of all locales for which the
- * <code>getInstance</code> methods of this class can return
- * localized instances.
- * The returned array represents the union of locales supported
- * by the Java runtime and by installed
- * {@link java.text.spi.CollatorProvider CollatorProvider} implementations.
- * It must contain at least a Locale instance equal to
- * {@link java.util.Locale#US Locale.US}.
- *
- * @return An array of locales for which localized
- * <code>Collator</code> instances are available.
- */
- public static synchronized Locale[] getAvailableLocales() {
- return ICU.getAvailableCollatorLocales();
- }
-
- /**
- * Returns a new collator with the same decomposition mode and
- * strength value as this collator.
- *
- * @return a shallow copy of this collator.
- * @see java.lang.Cloneable
- */
- @Override
- public Object clone() {
- try {
- Collator clone = (Collator) super.clone();
- clone.icuColl = (android.icu.text.Collator) icuColl.clone();
- return clone;
- } catch (CloneNotSupportedException e) {
- throw new AssertionError(e);
- }
- }
-
- /**
* Compares the source string to the target string according to the
* collation rules for this Collator. Returns an integer less than,
* equal to or greater than zero depending on whether the source String is
@@ -304,7 +247,6 @@
* given String will be involved in multiple comparisons, CollationKey.compareTo
* has the best performance. See the Collator class description for an example
* using CollationKeys.
- *
* @param source the source string.
* @param target the target string.
* @return Returns an integer value. Value is less than zero if source is less than
@@ -321,17 +263,18 @@
* to, or greater than the second.
* <p>
* This implementation merely returns
- * <code> compare((String)o1, (String)o2) </code>.
+ * <code> compare((String)o1, (String)o2) </code>.
*
* @return a negative integer, zero, or a positive integer as the
- * first argument is less than, equal to, or greater than the
- * second.
- * @throws ClassCastException the arguments cannot be cast to Strings.
+ * first argument is less than, equal to, or greater than the
+ * second.
+ * @exception ClassCastException the arguments cannot be cast to Strings.
* @see java.util.Comparator
- * @since 1.2
+ * @since 1.2
*/
+ @Override
public int compare(Object o1, Object o2) {
- return compare((String) o1, (String) o2);
+ return compare((String)o1, (String)o2);
}
/**
@@ -339,7 +282,6 @@
* to other CollationKeys. CollationKeys provide better performance than
* Collator.compare when Strings are involved in multiple comparisons.
* See the Collator class description for an example using CollationKeys.
- *
* @param source the string to be transformed into a collation key.
* @return the CollationKey for the given String based on this Collator's collation
* rules. If the source String is null, a null CollationKey is returned.
@@ -351,14 +293,14 @@
/**
* Convenience method for comparing the equality of two strings based on
* this Collator's collation rules.
- *
* @param source the source string to be compared with.
* @param target the target string to be compared with.
* @return true if the strings are equal according to the collation
* rules. false, otherwise.
* @see java.text.Collator#compare
*/
- public boolean equals(String source, String target) {
+ public boolean equals(String source, String target)
+ {
return (compare(source, target) == 0);
}
@@ -366,7 +308,6 @@
* Returns this Collator's strength property. The strength property determines
* the minimum level of difference considered significant during comparison.
* See the Collator class description for an example of use.
- *
* @return this Collator's current strength property.
* @see java.text.Collator#setStrength
* @see java.text.Collator#PRIMARY
@@ -374,7 +315,8 @@
* @see java.text.Collator#TERTIARY
* @see java.text.Collator#IDENTICAL
*/
- public synchronized int getStrength() {
+ public synchronized int getStrength()
+ {
// The value for IDENTICAL in ICU differs from that used in this class.
int value = icuColl.getStrength();
return (value == android.icu.text.Collator.IDENTICAL) ? IDENTICAL : value;
@@ -384,15 +326,14 @@
* Sets this Collator's strength property. The strength property determines
* the minimum level of difference considered significant during comparison.
* See the Collator class description for an example of use.
- *
- * @param newStrength the new strength value.
- * @throws IllegalArgumentException If the new strength value is not one of
- * PRIMARY, SECONDARY, TERTIARY or IDENTICAL.
- * @see Collator#getStrength
- * @see Collator#PRIMARY
- * @see Collator#SECONDARY
- * @see Collator#TERTIARY
- * @see Collator#IDENTICAL
+ * @param newStrength the new strength value.
+ * @see java.text.Collator#getStrength
+ * @see java.text.Collator#PRIMARY
+ * @see java.text.Collator#SECONDARY
+ * @see java.text.Collator#TERTIARY
+ * @see java.text.Collator#IDENTICAL
+ * @exception IllegalArgumentException If the new strength value is not one of
+ * PRIMARY, SECONDARY, TERTIARY or IDENTICAL.
*/
public synchronized void setStrength(int newStrength) {
// The ICU value for IDENTICAL differs from that defined in this class.
@@ -415,33 +356,48 @@
* </UL>
* See the documentation for these three constants for a description
* of their meaning.
- *
* @return the decomposition mode
* @see java.text.Collator#setDecomposition
* @see java.text.Collator#NO_DECOMPOSITION
* @see java.text.Collator#CANONICAL_DECOMPOSITION
* @see java.text.Collator#FULL_DECOMPOSITION
*/
- public synchronized int getDecomposition() {
+ public synchronized int getDecomposition()
+ {
return decompositionMode_ICU_Java(icuColl.getDecomposition());
}
-
/**
* Set the decomposition mode of this Collator. See getDecomposition
* for a description of decomposition mode.
- *
- * @param decompositionMode the new decomposition mode.
- * @throws IllegalArgumentException If the given value is not a valid decomposition
- * mode.
+ * @param decompositionMode the new decomposition mode.
* @see java.text.Collator#getDecomposition
* @see java.text.Collator#NO_DECOMPOSITION
* @see java.text.Collator#CANONICAL_DECOMPOSITION
* @see java.text.Collator#FULL_DECOMPOSITION
+ * @exception IllegalArgumentException If the given value is not a valid decomposition
+ * mode.
*/
public synchronized void setDecomposition(int decompositionMode) {
icuColl.setDecomposition(decompositionMode_Java_ICU(decompositionMode));
}
+ /**
+ * Returns an array of all locales for which the
+ * <code>getInstance</code> methods of this class can return
+ * localized instances.
+ * The returned array represents the union of locales supported
+ * by the Java runtime and by installed
+ * {@link java.text.spi.CollatorProvider CollatorProvider} implementations.
+ * It must contain at least a Locale instance equal to
+ * {@link java.util.Locale#US Locale.US}.
+ *
+ * @return An array of locales for which localized
+ * <code>Collator</code> instances are available.
+ */
+ public static synchronized Locale[] getAvailableLocales() {
+ return ICU.getAvailableCollatorLocales();
+ }
+
private int decompositionMode_Java_ICU(int mode) {
switch (mode) {
case Collator.CANONICAL_DECOMPOSITION:
@@ -466,13 +422,33 @@
}
/**
- * Compares the equality of two Collators.
+ * Returns a new collator with the same decomposition mode and
+ * strength value as this collator.
*
+ * @return a shallow copy of this collator.
+ * @see java.lang.Cloneable
+ */
+ @Override
+ public Object clone()
+ {
+ try {
+ Collator clone = (Collator) super.clone();
+ clone.icuColl = (android.icu.text.Collator) icuColl.clone();
+ return clone;
+ } catch (CloneNotSupportedException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /**
+ * Compares the equality of two Collators.
* @param that the Collator to be compared with this.
* @return true if this Collator is the same as that Collator;
* false otherwise.
*/
- public boolean equals(Object that) {
+ @Override
+ public boolean equals(Object that)
+ {
if (this == that) return true;
if (that == null) return false;
if (getClass() != that.getClass()) return false;
@@ -483,5 +459,23 @@
/**
* Generates the hash code for this Collator.
*/
+ @Override
abstract public int hashCode();
+
+ /**
+ * Default constructor. This constructor is
+ * protected so subclasses can get access to it. Users typically create
+ * a Collator sub-class by calling the factory method getInstance.
+ * @see java.text.Collator#getInstance
+ */
+ protected Collator()
+ {
+ icuColl = android.icu.text.RuleBasedCollator.getInstance(Locale.getDefault());
+ }
+
+ android.icu.text.Collator icuColl;
+
+ Collator(android.icu.text.Collator icuColl) {
+ this.icuColl = icuColl;
+ }
}
diff --git a/ojluni/src/main/java/java/text/RuleBasedCollator.java b/ojluni/src/main/java/java/text/RuleBasedCollator.java
index 3c82624..33c69cb 100755
--- a/ojluni/src/main/java/java/text/RuleBasedCollator.java
+++ b/ojluni/src/main/java/java/text/RuleBasedCollator.java
@@ -53,9 +53,9 @@
* for efficiency (other subclasses may be used for more complex languages) :
* <ol>
* <li>If a special collation rule controlled by a <modifier> is
- * specified it applies to the whole collator object.
+ specified it applies to the whole collator object.
* <li>All non-mentioned characters are at the end of the
- * collation order.
+ * collation order.
* </ol>
*
* <p>
@@ -68,39 +68,39 @@
* </pre>
* The definitions of the rule elements is as follows:
* <UL Type=disc>
- * <LI><strong>Text-Argument</strong>: A text-argument is any sequence of
- * characters, excluding special characters (that is, common
- * whitespace characters [0009-000D, 0020] and rule syntax characters
- * [0021-002F, 003A-0040, 005B-0060, 007B-007E]). If those
- * characters are desired, you can put them in single quotes
- * (e.g. ampersand => '&'). Note that unquoted white space characters
- * are ignored; e.g. <code>b c</code> is treated as <code>bc</code>.
- * <LI><strong>Modifier</strong>: There are currently two modifiers that
- * turn on special collation rules.
- * <UL Type=square>
- * <LI>'@' : Turns on backwards sorting of accents (secondary
- * differences), as in French.
- * <LI>'!' : Turns on Thai/Lao vowel-consonant swapping. If this
- * rule is in force when a Thai vowel of the range
- * \U0E40-\U0E44 precedes a Thai consonant of the range
- * \U0E01-\U0E2E OR a Lao vowel of the range \U0EC0-\U0EC4
- * precedes a Lao consonant of the range \U0E81-\U0EAE then
- * the vowel is placed after the consonant for collation
- * purposes.
- * </UL>
- * <p>'@' : Indicates that accents are sorted backwards, as in French.
- * <LI><strong>Relation</strong>: The relations are the following:
- * <UL Type=square>
- * <LI>'<' : Greater, as a letter difference (primary)
- * <LI>';' : Greater, as an accent difference (secondary)
- * <LI>',' : Greater, as a case difference (tertiary)
- * <LI>'=' : Equal
- * </UL>
- * <LI><strong>Reset</strong>: There is a single reset
- * which is used primarily for contractions and expansions, but which
- * can also be used to add a modification at the end of a set of rules.
- * <p>'&' : Indicates that the next rule follows the position to where
- * the reset text-argument would be sorted.
+ * <LI><strong>Text-Argument</strong>: A text-argument is any sequence of
+ * characters, excluding special characters (that is, common
+ * whitespace characters [0009-000D, 0020] and rule syntax characters
+ * [0021-002F, 003A-0040, 005B-0060, 007B-007E]). If those
+ * characters are desired, you can put them in single quotes
+ * (e.g. ampersand => '&'). Note that unquoted white space characters
+ * are ignored; e.g. <code>b c</code> is treated as <code>bc</code>.
+ * <LI><strong>Modifier</strong>: There are currently two modifiers that
+ * turn on special collation rules.
+ * <UL Type=square>
+ * <LI>'@' : Turns on backwards sorting of accents (secondary
+ * differences), as in French.
+ * <LI>'!' : Turns on Thai/Lao vowel-consonant swapping. If this
+ * rule is in force when a Thai vowel of the range
+ * \U0E40-\U0E44 precedes a Thai consonant of the range
+ * \U0E01-\U0E2E OR a Lao vowel of the range \U0EC0-\U0EC4
+ * precedes a Lao consonant of the range \U0E81-\U0EAE then
+ * the vowel is placed after the consonant for collation
+ * purposes.
+ * </UL>
+ * <p>'@' : Indicates that accents are sorted backwards, as in French.
+ * <LI><strong>Relation</strong>: The relations are the following:
+ * <UL Type=square>
+ * <LI>'<' : Greater, as a letter difference (primary)
+ * <LI>';' : Greater, as an accent difference (secondary)
+ * <LI>',' : Greater, as a case difference (tertiary)
+ * <LI>'=' : Equal
+ * </UL>
+ * <LI><strong>Reset</strong>: There is a single reset
+ * which is used primarily for contractions and expansions, but which
+ * can also be used to add a modification at the end of a set of rules.
+ * <p>'&' : Indicates that the next rule follows the position to where
+ * the reset text-argument would be sorted.
* </UL>
*
* <p>
@@ -166,13 +166,13 @@
* <p>
* The following are errors:
* <UL Type=disc>
- * <LI>A text-argument contains unquoted punctuation symbols
- * (e.g. "a < b-c < d").
- * <LI>A relation or reset character not followed by a text-argument
- * (e.g. "a < ,b").
- * <LI>A reset where the text-argument (or an initial substring of the
- * text-argument) is not already in the sequence.
- * (e.g. "a < b & e < f")
+ * <LI>A text-argument contains unquoted punctuation symbols
+ * (e.g. "a < b-c < d").
+ * <LI>A relation or reset character not followed by a text-argument
+ * (e.g. "a < ,b").
+ * <LI>A reset where the text-argument (or an initial substring of the
+ * text-argument) is not already in the sequence.
+ * (e.g. "a < b & e < f")
* </UL>
* If you produce one of these errors, a <code>RuleBasedCollator</code> throws
* a <code>ParseException</code>.
@@ -180,14 +180,14 @@
* <p><strong>Examples</strong>
* <p>Simple: "< a < b < c < d"
* <p>Norwegian: "< a, A < b, B < c, C < d, D < e, E < f, F
- * < g, G < h, H < i, I < j, J < k, K < l, L
- * < m, M < n, N < o, O < p, P < q, Q < r, R
- * < s, S < t, T < u, U < v, V < w, W < x, X
- * < y, Y < z, Z
- * < \u00E6, \u00C6
- * < \u00F8, \u00D8
- * < \u00E5 = a\u030A, \u00C5 = A\u030A;
- * aa, AA"
+ * < g, G < h, H < i, I < j, J < k, K < l, L
+ * < m, M < n, N < o, O < p, P < q, Q < r, R
+ * < s, S < t, T < u, U < v, V < w, W < x, X
+ * < y, Y < z, Z
+ * < \u00E6, \u00C6
+ * < \u00F8, \u00D8
+ * < \u00E5 = a\u030A, \u00C5 = A\u030A;
+ * aa, AA"
*
* <p>
* To create a <code>RuleBasedCollator</code> object with specialized
@@ -202,15 +202,9 @@
* Or:
* <blockquote>
* <pre>
- * String Norwegian = "< a, A < b, B < c, C < d, D < e, E < f, F < g, G <
- * h,
- * H < i, I" +
- * "< j, J < k, K < l, L < m, M < n, N < o, O < p, P <
- * q,
- * Q < r, R" +
- * "< s, S < t, T < u, U < v, V < w, W < x, X < y, Y <
- * z,
- * Z" +
+ * String Norwegian = "< a, A < b, B < c, C < d, D < e, E < f, F < g, G < h, H < i, I" +
+ * "< j, J < k, K < l, L < m, M < n, N < o, O < p, P < q, Q < r, R" +
+ * "< s, S < t, T < u, U < v, V < w, W < x, X < y, Y < z, Z" +
* "< \u00E6, \u00C6" + // Latin letter ae & AE
* "< \u00F8, \u00D8" + // Latin letter o & O with stroke
* "< \u00E5 = a\u030A," + // Latin letter a with ring above
@@ -278,13 +272,12 @@
* RuleBasedCollator constructor. This takes the table rules and builds
* a collation table out of them. Please see RuleBasedCollator class
* description for more details on the collation rule syntax.
- *
- * @param rules the collation rules to build the collation table from.
- * @throws ParseException A format exception
- * will be thrown if the build process of the rules fails. For
- * example, build rule "a < ? < d" will cause the constructor to
- * throw the ParseException because the '?' is not quoted.
* @see java.util.Locale
+ * @param rules the collation rules to build the collation table from.
+ * @exception ParseException A format exception
+ * will be thrown if the build process of the rules fails. For
+ * example, build rule "a < ? < d" will cause the constructor to
+ * throw the ParseException because the '?' is not quoted.
*/
public RuleBasedCollator(String rules) throws ParseException {
if (rules == null) {
@@ -313,13 +306,13 @@
* @return returns the collation rules that the table collation object
* was created from.
*/
- public String getRules() {
+ public String getRules()
+ {
return collAsICU().getRules();
}
/**
* Return a CollationElementIterator for the given String.
- *
* @see java.text.CollationElementIterator
*/
public CollationElementIterator getCollationElementIterator(String source) {
@@ -331,13 +324,12 @@
/**
* Return a CollationElementIterator for the given String.
- *
* @see java.text.CollationElementIterator
* @since 1.2
*/
public CollationElementIterator getCollationElementIterator(
- CharacterIterator source) {
- if (source == null) {
+ CharacterIterator source) {
+ if (source == null) {
throw new NullPointerException("source == null");
}
return new CollationElementIterator(collAsICU().getCollationElementIterator(source));
@@ -349,9 +341,10 @@
* than, greater than or equal to another string in a language.
* This can be overriden in a subclass.
*
- * @throws NullPointerException if <code>source</code> or <code>target</code> is null.
+ * @exception NullPointerException if <code>source</code> or <code>target</code> is null.
*/
- public synchronized int compare(String source, String target) {
+ public synchronized int compare(String source, String target)
+ {
if (source == null || target == null) {
throw new NullPointerException();
}
@@ -363,7 +356,8 @@
* with CollationKey.compareTo. This overrides java.text.Collator.getCollationKey.
* It can be overriden in a subclass.
*/
- public synchronized CollationKey getCollationKey(String source) {
+ public synchronized CollationKey getCollationKey(String source)
+ {
if (source == null) {
return null;
}
@@ -379,7 +373,6 @@
/**
* Compares the equality of two collation objects.
- *
* @param obj the table-based collation object to be compared with this.
* @return true if the current table-based collation object is the same
* as the table-based collation object obj; false otherwise.
diff --git a/ojluni/src/main/java/java/text/SimpleDateFormat.java b/ojluni/src/main/java/java/text/SimpleDateFormat.java
index b435583..5c01017 100755
--- a/ojluni/src/main/java/java/text/SimpleDateFormat.java
+++ b/ojluni/src/main/java/java/text/SimpleDateFormat.java
@@ -1135,13 +1135,6 @@
}
break;
- case PATTERN_STANDALONE_MONTH: // 'L'
- {
- current = formatMonth(count, value, maxIntCount, buffer, useDateFormatSymbols,
- true /* standalone */);
- break;
- }
-
case PATTERN_MONTH: // 'M'
{
current = formatMonth(count, value, maxIntCount, buffer, useDateFormatSymbols,
@@ -1149,6 +1142,13 @@
break;
}
+ case PATTERN_STANDALONE_MONTH: // 'L'
+ {
+ current = formatMonth(count, value, maxIntCount, buffer, useDateFormatSymbols,
+ true /* standalone */);
+ break;
+ }
+
case PATTERN_HOUR_OF_DAY1: // 'k' 1-based. eg, 23:59 + 1 hour =>> 24:59
if (current == null) {
if (value == 0)
@@ -1159,18 +1159,18 @@
}
break;
- case PATTERN_STANDALONE_DAY_OF_WEEK: // 'c'
- {
- current = formatWeekday(count, value, useDateFormatSymbols, true /* standalone */);
- break;
- }
-
case PATTERN_DAY_OF_WEEK: // 'E'
{
current = formatWeekday(count, value, useDateFormatSymbols, false /* standalone */);
break;
}
+ case PATTERN_STANDALONE_DAY_OF_WEEK: // 'c'
+ {
+ current = formatWeekday(count, value, useDateFormatSymbols, true /* standalone */);
+ break;
+ }
+
case PATTERN_AM_PM: // 'a'
if (useDateFormatSymbols) {
String[] ampm = formatData.getAmPmStrings();
@@ -1929,16 +1929,6 @@
calb.set(field, value);
return pos.index;
- case PATTERN_STANDALONE_MONTH: // 'L'.
- {
- final int idx = parseMonth(text, count, value, start, field, pos,
- useDateFormatSymbols, true /* isStandalone */, calb);
- if (idx > 0) {
- return idx;
- }
- break parsing;
- }
-
case PATTERN_MONTH: // 'M'
{
final int idx = parseMonth(text, count, value, start, field, pos,
@@ -1950,6 +1940,16 @@
break parsing;
}
+ case PATTERN_STANDALONE_MONTH: // 'L'.
+ {
+ final int idx = parseMonth(text, count, value, start, field, pos,
+ useDateFormatSymbols, true /* isStandalone */, calb);
+ if (idx > 0) {
+ return idx;
+ }
+ break parsing;
+ }
+
case PATTERN_HOUR_OF_DAY1: // 'k' 1-based. eg, 23:59 + 1 hour =>> 24:59
if (!isLenient()) {
// Validate the hour value in non-lenient
@@ -1963,6 +1963,16 @@
calb.set(Calendar.HOUR_OF_DAY, value);
return pos.index;
+ case PATTERN_DAY_OF_WEEK: // 'E'
+ {
+ final int idx = parseWeekday(text, start, field, useDateFormatSymbols,
+ false /* standalone */, calb);
+ if (idx > 0) {
+ return idx;
+ }
+ break parsing;
+ }
+
case PATTERN_STANDALONE_DAY_OF_WEEK: // 'c'
{
final int idx = parseWeekday(text, start, field, useDateFormatSymbols,
@@ -1974,18 +1984,6 @@
break parsing;
}
- case PATTERN_DAY_OF_WEEK: // 'E'
- {
- final int idx = parseWeekday(text, start, field, useDateFormatSymbols,
- false /* standalone */, calb);
- if (idx > 0) {
- return idx;
- }
-
- break parsing;
- }
-
-
case PATTERN_AM_PM: // 'a'
if (useDateFormatSymbols) {
if ((index = matchString(text, start, Calendar.AM_PM,
@@ -2146,10 +2144,10 @@
}
if (useFollowingMinusSignAsDelimiter && (value < 0) &&
- (((pos.index < text.length()) &&
- (text.charAt(pos.index) != minusSign)) ||
- ((pos.index == text.length()) &&
- (text.charAt(pos.index - 1) == minusSign)))) {
+ (((pos.index < text.length()) &&
+ (text.charAt(pos.index) != minusSign)) ||
+ ((pos.index == text.length()) &&
+ (text.charAt(pos.index-1) == minusSign)))) {
value = -value;
pos.index--;
}
diff --git a/ojluni/src/main/java/jdk/net/ExtendedSocketOptions.java b/ojluni/src/main/java/jdk/net/ExtendedSocketOptions.java
new file mode 100644
index 0000000..73c67d8
--- /dev/null
+++ b/ojluni/src/main/java/jdk/net/ExtendedSocketOptions.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.net;
+
+import java.net.SocketOption;
+
+/**
+ * Defines extended socket options, beyond those defined in
+ * {@link java.net.StandardSocketOptions}. These options may be platform
+ * specific.
+ */
+//@jdk.Exported
+public final class ExtendedSocketOptions {
+
+ private static class ExtSocketOption<T> implements SocketOption<T> {
+ private final String name;
+ private final Class<T> type;
+ ExtSocketOption(String name, Class<T> type) {
+ this.name = name;
+ this.type = type;
+ }
+ @Override public String name() { return name; }
+ @Override public Class<T> type() { return type; }
+ @Override public String toString() { return name; }
+ }
+
+ private ExtendedSocketOptions() {}
+
+ /**
+ * Service level properties. When a security manager is installed,
+ * setting or getting this option requires a {@link NetworkPermission}
+ * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"}
+ * respectively.
+ */
+ public static final SocketOption<SocketFlow> SO_FLOW_SLA = new
+ ExtSocketOption<SocketFlow>("SO_FLOW_SLA", SocketFlow.class);
+}
diff --git a/ojluni/src/main/java/jdk/net/NetworkPermission.java b/ojluni/src/main/java/jdk/net/NetworkPermission.java
new file mode 100644
index 0000000..420c74f
--- /dev/null
+++ b/ojluni/src/main/java/jdk/net/NetworkPermission.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.net;
+
+import java.security.BasicPermission;
+
+/**
+ * Legacy security code; do not use.
+ */
+
+//@jdk.Exported
+public final class NetworkPermission extends BasicPermission {
+
+ public NetworkPermission(String name) {
+ super("");
+ }
+
+ public NetworkPermission(String name, String actions) {
+ super("", "");
+ }
+}
diff --git a/ojluni/src/main/java/jdk/net/SocketFlow.java b/ojluni/src/main/java/jdk/net/SocketFlow.java
new file mode 100644
index 0000000..a8ca749
--- /dev/null
+++ b/ojluni/src/main/java/jdk/net/SocketFlow.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.net;
+
+import java.lang.annotation.Native;
+
+/**
+ * Represents the service level properties for the platform specific socket
+ * option {@link ExtendedSocketOptions#SO_FLOW_SLA}.
+ * <p>
+ * The priority and bandwidth parameters must be set before
+ * setting the socket option.
+ * <p>
+ * When the {@code SO_FLOW_SLA} option is set then it may not take effect
+ * immediately. If the value of the socket option is obtained with
+ * {@code getOption()} then the status may be returned as {@code INPROGRESS}
+ * until it takes effect. The priority and bandwidth values are only valid when
+ * the status is returned as OK.
+ * <p>
+ * When a security manager is installed, a {@link NetworkPermission}
+ * is required to set or get this option.
+ */
+//@jdk.Exported
+public class SocketFlow {
+
+ private static final int UNSET = -1;
+ @Native public static final int NORMAL_PRIORITY = 1;
+ @Native public static final int HIGH_PRIORITY = 2;
+
+ private int priority = NORMAL_PRIORITY;
+
+ private long bandwidth = UNSET;
+
+ private Status status = Status.NO_STATUS;
+
+ private SocketFlow() {}
+
+ /**
+ * Enumeration of the return values from the SO_FLOW_SLA
+ * socket option. Both setting and getting the option return
+ * one of these statuses, which reflect the state of socket's
+ * flow.
+ */
+// @jdk.Exported
+ public enum Status {
+ /**
+ * Set or get socket option has not been called yet. Status
+ * values can only be retrieved after calling set or get.
+ */
+ NO_STATUS,
+ /**
+ * Flow successfully created.
+ */
+ OK,
+ /**
+ * Caller has no permission to create flow.
+ */
+ NO_PERMISSION,
+ /**
+ * Flow can not be created because socket is not connected.
+ */
+ NOT_CONNECTED,
+ /**
+ * Flow creation not supported for this socket.
+ */
+ NOT_SUPPORTED,
+ /**
+ * A flow already exists with identical attributes.
+ */
+ ALREADY_CREATED,
+ /**
+ * A flow is being created.
+ */
+ IN_PROGRESS,
+ /**
+ * Some other unspecified error.
+ */
+ OTHER
+ }
+
+ /**
+ * Creates a new SocketFlow that can be used to set the SO_FLOW_SLA
+ * socket option and create a socket flow.
+ */
+ public static SocketFlow create() {
+ return new SocketFlow();
+ }
+
+ /**
+ * Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY
+ * HIGH_PRIORITY. If not set, a flow's priority is normal.
+ *
+ * @throws IllegalArgumentException if priority is not NORMAL_PRIORITY or
+ * HIGH_PRIORITY.
+ */
+ public SocketFlow priority(int priority) {
+ if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) {
+ throw new IllegalArgumentException("invalid priority");
+ }
+ this.priority = priority;
+ return this;
+ }
+
+ /**
+ * Sets this SocketFlow's bandwidth. Must be greater than or equal to zero.
+ * A value of zero drops all packets for the socket.
+ *
+ * @throws IllegalArgumentException if bandwidth is less than zero.
+ */
+ public SocketFlow bandwidth(long bandwidth) {
+ if (bandwidth < 0) {
+ throw new IllegalArgumentException("invalid bandwidth");
+ } else {
+ this.bandwidth = bandwidth;
+ }
+ return this;
+ }
+
+ /**
+ * Returns this SocketFlow's priority.
+ */
+ public int priority() {
+ return priority;
+ }
+
+ /**
+ * Returns this SocketFlow's bandwidth.
+ *
+ * @return this SocketFlow's bandwidth, or {@code -1} if status is not OK.
+ */
+ public long bandwidth() {
+ return bandwidth;
+ }
+
+ /**
+ * Returns the Status value of this SocketFlow. NO_STATUS is returned
+ * if the object was not used in a call to set or get the option.
+ */
+ public Status status() {
+ return status;
+ }
+}
diff --git a/ojluni/src/main/java/jdk/net/Sockets.java b/ojluni/src/main/java/jdk/net/Sockets.java
new file mode 100644
index 0000000..1187eb3
--- /dev/null
+++ b/ojluni/src/main/java/jdk/net/Sockets.java
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.net;
+
+import java.net.*;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.lang.reflect.*;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Collections;
+import sun.net.ExtendedOptionsImpl;
+
+/**
+ * Defines static methods to set and get socket options defined by the
+ * {@link java.net.SocketOption} interface. All of the standard options defined
+ * by {@link java.net.Socket}, {@link java.net.ServerSocket}, and
+ * {@link java.net.DatagramSocket} can be set this way, as well as additional
+ * or platform specific options supported by each socket type.
+ * <p>
+ * The {@link #supportedOptions(Class)} method can be called to determine
+ * the complete set of options available (per socket type) on the
+ * current system.
+ * <p>
+ * When a security manager is installed, some non-standard socket options
+ * may require a security permission before being set or get.
+ * The details are specified in {@link ExtendedSocketOptions}. No permission
+ * is required for {@link java.net.StandardSocketOptions}.
+ *
+ * @see java.nio.channels.NetworkChannel
+ */
+//@jdk.Exported
+public class Sockets {
+
+ private final static HashMap<Class<?>,Set<SocketOption<?>>>
+ options = new HashMap<>();
+
+ static {
+ initOptionSets();
+ AccessController.doPrivileged(
+ new java.security.PrivilegedAction<Void>() {
+ public Void run() {
+ initMethods();
+ return null;
+ }
+ }
+ );
+ }
+
+ private static Method siSetOption;
+ private static Method siGetOption;
+ private static Method dsiSetOption;
+ private static Method dsiGetOption;
+
+ private static void initMethods() {
+ try {
+ Class<?> clazz = Class.forName("java.net.SocketSecrets");
+
+ siSetOption = clazz.getDeclaredMethod(
+ "setOption", Object.class,
+ SocketOption.class, Object.class
+ );
+ siSetOption.setAccessible(true);
+
+ siGetOption = clazz.getDeclaredMethod(
+ "getOption", Object.class, SocketOption.class
+ );
+ siGetOption.setAccessible(true);
+
+ dsiSetOption = clazz.getDeclaredMethod(
+ "setOption", DatagramSocket.class,
+ SocketOption.class, Object.class
+ );
+ dsiSetOption.setAccessible(true);
+
+ dsiGetOption = clazz.getDeclaredMethod(
+ "getOption", DatagramSocket.class, SocketOption.class
+ );
+ dsiGetOption.setAccessible(true);
+ } catch (ReflectiveOperationException e) {
+ throw new InternalError(e);
+ }
+ }
+
+ private static <T> void invokeSet(
+ Method method, Object socket,
+ SocketOption<T> option, T value) throws IOException
+ {
+ try {
+ method.invoke(null, socket, option, value);
+ } catch (Exception e) {
+ if (e instanceof InvocationTargetException) {
+ Throwable t = ((InvocationTargetException)e).getTargetException();
+ if (t instanceof IOException) {
+ throw (IOException)t;
+ } else if (t instanceof RuntimeException) {
+ throw (RuntimeException)t;
+ }
+ }
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static <T> T invokeGet(
+ Method method, Object socket, SocketOption<T> option) throws IOException
+ {
+ try {
+ return (T)method.invoke(null, socket, option);
+ } catch (Exception e) {
+ if (e instanceof InvocationTargetException) {
+ Throwable t = ((InvocationTargetException)e).getTargetException();
+ if (t instanceof IOException) {
+ throw (IOException)t;
+ } else if (t instanceof RuntimeException) {
+ throw (RuntimeException)t;
+ }
+ }
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Sockets() {}
+
+ /**
+ * Sets the value of a socket option on a {@link java.net.Socket}
+ *
+ * @param s the socket
+ * @param name The socket option
+ * @param value The value of the socket option. May be null for some
+ * options.
+ *
+ * @throws UnsupportedOperationException if the socket does not support
+ * the option.
+ *
+ * @throws IllegalArgumentException if the value is not valid for
+ * the option.
+ *
+ * @throws IOException if an I/O error occurs, or socket is closed.
+ *
+ * @throws SecurityException if a security manager is set and the
+ * caller does not have any required permission.
+ *
+ * @throws NullPointerException if name is null
+ *
+ * @see java.net.StandardSocketOptions
+ */
+ public static <T> void setOption(Socket s, SocketOption<T> name, T value) throws IOException
+ {
+ if (!isSupported(Socket.class, name)) {
+ throw new UnsupportedOperationException(name.name());
+ }
+ invokeSet(siSetOption, s, name, value);
+ }
+
+ /**
+ * Returns the value of a socket option from a {@link java.net.Socket}
+ *
+ * @param s the socket
+ * @param name The socket option
+ *
+ * @return The value of the socket option.
+ *
+ * @throws UnsupportedOperationException if the socket does not support
+ * the option.
+ *
+ * @throws IOException if an I/O error occurs
+ *
+ * @throws SecurityException if a security manager is set and the
+ * caller does not have any required permission.
+ *
+ * @throws NullPointerException if name is null
+ *
+ * @see java.net.StandardSocketOptions
+ */
+ public static <T> T getOption(Socket s, SocketOption<T> name) throws IOException
+ {
+ if (!isSupported(Socket.class, name)) {
+ throw new UnsupportedOperationException(name.name());
+ }
+ return invokeGet(siGetOption, s, name);
+ }
+
+ /**
+ * Sets the value of a socket option on a {@link java.net.ServerSocket}
+ *
+ * @param s the socket
+ * @param name The socket option
+ * @param value The value of the socket option.
+ *
+ * @throws UnsupportedOperationException if the socket does not support
+ * the option.
+ *
+ * @throws IllegalArgumentException if the value is not valid for
+ * the option.
+ *
+ * @throws IOException if an I/O error occurs
+ *
+ * @throws NullPointerException if name is null
+ *
+ * @throws SecurityException if a security manager is set and the
+ * caller does not have any required permission.
+ *
+ * @see java.net.StandardSocketOptions
+ */
+ public static <T> void setOption(ServerSocket s, SocketOption<T> name, T value) throws IOException
+ {
+ if (!isSupported(ServerSocket.class, name)) {
+ throw new UnsupportedOperationException(name.name());
+ }
+ invokeSet(siSetOption, s, name, value);
+ }
+
+ /**
+ * Returns the value of a socket option from a {@link java.net.ServerSocket}
+ *
+ * @param s the socket
+ * @param name The socket option
+ *
+ * @return The value of the socket option.
+ *
+ * @throws UnsupportedOperationException if the socket does not support
+ * the option.
+ *
+ * @throws IOException if an I/O error occurs
+ *
+ * @throws NullPointerException if name is null
+ *
+ * @throws SecurityException if a security manager is set and the
+ * caller does not have any required permission.
+ *
+ * @see java.net.StandardSocketOptions
+ */
+ public static <T> T getOption(ServerSocket s, SocketOption<T> name) throws IOException
+ {
+ if (!isSupported(ServerSocket.class, name)) {
+ throw new UnsupportedOperationException(name.name());
+ }
+ return invokeGet(siGetOption, s, name);
+ }
+
+ /**
+ * Sets the value of a socket option on a {@link java.net.DatagramSocket}
+ * or {@link java.net.MulticastSocket}
+ *
+ * @param s the socket
+ * @param name The socket option
+ * @param value The value of the socket option.
+ *
+ * @throws UnsupportedOperationException if the socket does not support
+ * the option.
+ *
+ * @throws IllegalArgumentException if the value is not valid for
+ * the option.
+ *
+ * @throws IOException if an I/O error occurs
+ *
+ * @throws NullPointerException if name is null
+ *
+ * @throws SecurityException if a security manager is set and the
+ * caller does not have any required permission.
+ *
+ * @see java.net.StandardSocketOptions
+ */
+ public static <T> void setOption(DatagramSocket s, SocketOption<T> name, T value) throws IOException
+ {
+ if (!isSupported(s.getClass(), name)) {
+ throw new UnsupportedOperationException(name.name());
+ }
+ invokeSet(dsiSetOption, s, name, value);
+ }
+
+ /**
+ * Returns the value of a socket option from a
+ * {@link java.net.DatagramSocket} or {@link java.net.MulticastSocket}
+ *
+ * @param s the socket
+ * @param name The socket option
+ *
+ * @return The value of the socket option.
+ *
+ * @throws UnsupportedOperationException if the socket does not support
+ * the option.
+ *
+ * @throws IOException if an I/O error occurs
+ *
+ * @throws NullPointerException if name is null
+ *
+ * @throws SecurityException if a security manager is set and the
+ * caller does not have any required permission.
+ *
+ * @see java.net.StandardSocketOptions
+ */
+ public static <T> T getOption(DatagramSocket s, SocketOption<T> name) throws IOException
+ {
+ if (!isSupported(s.getClass(), name)) {
+ throw new UnsupportedOperationException(name.name());
+ }
+ return invokeGet(dsiGetOption, s, name);
+ }
+
+ /**
+ * Returns a set of {@link java.net.SocketOption}s supported by the
+ * given socket type. This set may include standard options and also
+ * non standard extended options.
+ *
+ * @param socketType the type of java.net socket
+ *
+ * @throws IllegalArgumentException if socketType is not a valid
+ * socket type from the java.net package.
+ */
+ public static Set<SocketOption<?>> supportedOptions(Class<?> socketType) {
+ Set<SocketOption<?>> set = options.get(socketType);
+ if (set == null) {
+ throw new IllegalArgumentException("unknown socket type");
+ }
+ return set;
+ }
+
+ private static boolean isSupported(Class<?> type, SocketOption<?> option) {
+ Set<SocketOption<?>> options = supportedOptions(type);
+ return options.contains(option);
+ }
+
+ private static void initOptionSets() {
+ boolean flowsupported = ExtendedOptionsImpl.flowSupported();
+
+ // Socket
+
+ Set<SocketOption<?>> set = new HashSet<>();
+ set.add(StandardSocketOptions.SO_KEEPALIVE);
+ set.add(StandardSocketOptions.SO_SNDBUF);
+ set.add(StandardSocketOptions.SO_RCVBUF);
+ set.add(StandardSocketOptions.SO_REUSEADDR);
+ set.add(StandardSocketOptions.SO_LINGER);
+ set.add(StandardSocketOptions.IP_TOS);
+ set.add(StandardSocketOptions.TCP_NODELAY);
+ if (flowsupported) {
+ set.add(ExtendedSocketOptions.SO_FLOW_SLA);
+ }
+ set = Collections.unmodifiableSet(set);
+ options.put(Socket.class, set);
+
+ // ServerSocket
+
+ set = new HashSet<>();
+ set.add(StandardSocketOptions.SO_RCVBUF);
+ set.add(StandardSocketOptions.SO_REUSEADDR);
+ set.add(StandardSocketOptions.IP_TOS);
+ set = Collections.unmodifiableSet(set);
+ options.put(ServerSocket.class, set);
+
+ // DatagramSocket
+
+ set = new HashSet<>();
+ set.add(StandardSocketOptions.SO_SNDBUF);
+ set.add(StandardSocketOptions.SO_RCVBUF);
+ set.add(StandardSocketOptions.SO_REUSEADDR);
+ set.add(StandardSocketOptions.IP_TOS);
+ if (flowsupported) {
+ set.add(ExtendedSocketOptions.SO_FLOW_SLA);
+ }
+ set = Collections.unmodifiableSet(set);
+ options.put(DatagramSocket.class, set);
+
+ // MulticastSocket
+
+ set = new HashSet<>();
+ set.add(StandardSocketOptions.SO_SNDBUF);
+ set.add(StandardSocketOptions.SO_RCVBUF);
+ set.add(StandardSocketOptions.SO_REUSEADDR);
+ set.add(StandardSocketOptions.IP_TOS);
+ set.add(StandardSocketOptions.IP_MULTICAST_IF);
+ set.add(StandardSocketOptions.IP_MULTICAST_TTL);
+ set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
+ if (flowsupported) {
+ set.add(ExtendedSocketOptions.SO_FLOW_SLA);
+ }
+ set = Collections.unmodifiableSet(set);
+ options.put(MulticastSocket.class, set);
+ }
+}
diff --git a/ojluni/src/main/java/jdk/net/package-info.java b/ojluni/src/main/java/jdk/net/package-info.java
new file mode 100644
index 0000000..b05d543
--- /dev/null
+++ b/ojluni/src/main/java/jdk/net/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Platform specific socket options for the {@code java.net} and {@code java.nio.channels}
+ * socket classes.
+ */
+
+@jdk.Exported
+package jdk.net;
diff --git a/ojluni/src/main/java/sun/net/ExtendedOptionsImpl.java b/ojluni/src/main/java/sun/net/ExtendedOptionsImpl.java
new file mode 100644
index 0000000..240f705
--- /dev/null
+++ b/ojluni/src/main/java/sun/net/ExtendedOptionsImpl.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.net;
+
+import java.net.*;
+import jdk.net.*;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.lang.reflect.Field;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Collections;
+
+/**
+ * Contains the native implementation for extended socket options
+ * together with some other static utilities
+ */
+public class ExtendedOptionsImpl {
+
+ static {
+ AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
+ System.loadLibrary("net");
+ return null;
+ });
+ init();
+ }
+
+ private ExtendedOptionsImpl() {}
+
+ public static void checkSetOptionPermission(SocketOption<?> option) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null) {
+ return;
+ }
+ String check = "setOption." + option.name();
+ sm.checkPermission(new NetworkPermission(check));
+ }
+
+ public static void checkGetOptionPermission(SocketOption<?> option) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null) {
+ return;
+ }
+ String check = "getOption." + option.name();
+ sm.checkPermission(new NetworkPermission(check));
+ }
+
+ public static void checkValueType(Object value, Class<?> type) {
+ if (!type.isAssignableFrom(value.getClass())) {
+ String s = "Found: " + value.getClass().toString() + " Expected: "
+ + type.toString();
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ private static native void init();
+
+ /*
+ * Extension native implementations
+ *
+ * SO_FLOW_SLA
+ */
+ // Android-changed: Linux does not support flow operations.
+ public static void setFlowOption(FileDescriptor fd, SocketFlow f) {
+ throw new UnsupportedOperationException("unsupported socket option");
+ }
+
+ public static void getFlowOption(FileDescriptor fd, SocketFlow f) {
+ throw new UnsupportedOperationException("unsupported socket option");
+ }
+
+ public static boolean flowSupported() {
+ return false;
+ }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/AsynchronousSocketChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/AsynchronousSocketChannelImpl.java
index af20709..a106d41 100755
--- a/ojluni/src/main/java/sun/nio/ch/AsynchronousSocketChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/AsynchronousSocketChannelImpl.java
@@ -39,6 +39,7 @@
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import sun.net.NetHooks;
+import sun.net.ExtendedOptionsImpl;
/**
* Base implementation of AsynchronousSocketChannel
@@ -504,6 +505,9 @@
set.add(StandardSocketOptions.SO_KEEPALIVE);
set.add(StandardSocketOptions.SO_REUSEADDR);
set.add(StandardSocketOptions.TCP_NODELAY);
+ if (ExtendedOptionsImpl.flowSupported()) {
+ set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
+ }
return Collections.unmodifiableSet(set);
}
}
diff --git a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
index d1b398fa..c93e82d 100755
--- a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
@@ -33,6 +33,7 @@
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.util.*;
+import sun.net.ExtendedOptionsImpl;
import dalvik.system.BlockGuard;
import sun.net.ResourceManager;
@@ -321,6 +322,9 @@
set.add(StandardSocketOptions.IP_MULTICAST_IF);
set.add(StandardSocketOptions.IP_MULTICAST_TTL);
set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
+ if (ExtendedOptionsImpl.flowSupported()) {
+ set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
+ }
return Collections.unmodifiableSet(set);
}
}
diff --git a/ojluni/src/main/java/sun/nio/ch/Net.java b/ojluni/src/main/java/sun/nio/ch/Net.java
index 99d2629..24ea94c 100755
--- a/ojluni/src/main/java/sun/nio/ch/Net.java
+++ b/ojluni/src/main/java/sun/nio/ch/Net.java
@@ -30,11 +30,13 @@
import java.io.*;
import java.net.*;
+import jdk.net.*;
import java.nio.channels.*;
import java.util.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
+import sun.net.ExtendedOptionsImpl;
class Net { // package-private
@@ -337,6 +339,16 @@
// only simple values supported by this method
Class<?> type = name.type();
+
+ if (type == SocketFlow.class) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA"));
+ }
+ ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value);
+ return;
+ }
+
if (type != Integer.class && type != Boolean.class)
throw new AssertionError("Should not reach here");
@@ -389,6 +401,16 @@
{
Class<?> type = name.type();
+ if (type == SocketFlow.class) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA"));
+ }
+ SocketFlow flow = SocketFlow.create();
+ ExtendedOptionsImpl.getFlowOption(fd, flow);
+ return flow;
+ }
+
// only simple values supported by this method
if (type != Integer.class && type != Boolean.class)
throw new AssertionError("Should not reach here");
diff --git a/ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java
index 453b15b..c73eec5 100755
--- a/ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java
@@ -37,6 +37,7 @@
import dalvik.system.BlockGuard;
import sun.net.NetHooks;
import sun.misc.IoTrace;
+import sun.net.ExtendedOptionsImpl;
/**
* An implementation of SocketChannels
@@ -240,6 +241,9 @@
// additional options required by socket adaptor
set.add(StandardSocketOptions.IP_TOS);
set.add(ExtendedSocketOption.SO_OOBINLINE);
+ if (ExtendedOptionsImpl.flowSupported()) {
+ set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
+ }
return Collections.unmodifiableSet(set);
}
}
diff --git a/ojluni/src/main/native/net_util.h b/ojluni/src/main/native/net_util.h
index 74e8089..2f5cffd 100755
--- a/ojluni/src/main/native/net_util.h
+++ b/ojluni/src/main/native/net_util.h
@@ -40,7 +40,7 @@
#define IPv6 AF_INET6
#define NET_ERROR(env, ex, msg) \
-{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg) }
+{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg); }
#define CHECK_NULL(x) if ((x) == NULL) return;
#define CHECK_NULL_RETURN(x, y) if ((x) == NULL) return y;
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index b5d6cc1..37c010c 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -846,6 +846,7 @@
ojluni/src/main/java/java/util/function/ToLongBiFunction.java \
ojluni/src/main/java/java/util/function/ToLongFunction.java \
ojluni/src/main/java/java/util/function/UnaryOperator.java \
+ ojluni/src/main/java/java/util/function/package-info.java \
ojluni/src/main/java/java/util/jar/Attributes.java \
ojluni/src/main/java/java/util/jar/JarEntry.java \
ojluni/src/main/java/java/util/jar/JarException.java \
@@ -1153,6 +1154,10 @@
ojluni/src/main/java/java/util/spi/LocaleNameProvider.java \
ojluni/src/main/java/java/util/spi/LocaleServiceProvider.java \
ojluni/src/main/java/java/util/spi/TimeZoneNameProvider.java \
+ ojluni/src/main/java/jdk/net/ExtendedSocketOptions.java \
+ ojluni/src/main/java/jdk/net/NetworkPermission.java \
+ ojluni/src/main/java/jdk/net/SocketFlow.java \
+ ojluni/src/main/java/jdk/net/Sockets.java \
ojluni/src/main/java/sun/misc/ASCIICaseInsensitiveComparator.java \
ojluni/src/main/java/sun/misc/BASE64Decoder.java \
ojluni/src/main/java/sun/misc/BASE64Encoder.java \
@@ -1192,6 +1197,7 @@
ojluni/src/main/java/sun/misc/VM.java \
ojluni/src/main/java/sun/net/ApplicationProxy.java \
ojluni/src/main/java/sun/net/ConnectionResetException.java \
+ ojluni/src/main/java/sun/net/ExtendedOptionsImpl.java \
ojluni/src/main/java/sun/net/ftp/FtpClient.java \
ojluni/src/main/java/sun/net/ftp/FtpClientProvider.java \
ojluni/src/main/java/sun/net/ftp/FtpDirEntry.java \