mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8187443: Forest Consolidation: Move files to unified layout
Reviewed-by: darcy, ihse
This commit is contained in:
parent
270fe13182
commit
3789983e89
56923 changed files with 3 additions and 15727 deletions
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2016, 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 apple.security;
|
||||
|
||||
import java.security.*;
|
||||
import static sun.security.util.SecurityConstants.PROVIDER_VER;
|
||||
|
||||
/**
|
||||
* The Apple Security Provider.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines the Apple provider.
|
||||
*
|
||||
* This provider only exists to provide access to the Apple keychain-based KeyStore implementation
|
||||
*/
|
||||
@SuppressWarnings("serial") // JDK implementation class
|
||||
public final class AppleProvider extends Provider {
|
||||
|
||||
private static final String info = "Apple Provider";
|
||||
|
||||
private static final class ProviderService extends Provider.Service {
|
||||
ProviderService(Provider p, String type, String algo, String cn) {
|
||||
super(p, type, algo, cn, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object newInstance(Object ctrParamObj)
|
||||
throws NoSuchAlgorithmException {
|
||||
String type = getType();
|
||||
if (ctrParamObj != null) {
|
||||
throw new InvalidParameterException
|
||||
("constructorParameter not used with " + type + " engines");
|
||||
}
|
||||
|
||||
String algo = getAlgorithm();
|
||||
try {
|
||||
if (type.equals("KeyStore")) {
|
||||
if (algo.equals("KeychainStore")) {
|
||||
return new KeychainStore();
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new NoSuchAlgorithmException("Error constructing " +
|
||||
type + " for " + algo + " using Apple", ex);
|
||||
}
|
||||
throw new ProviderException("No impl for " + algo +
|
||||
" " + type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public AppleProvider() {
|
||||
/* We are the Apple provider */
|
||||
super("Apple", PROVIDER_VER, info);
|
||||
|
||||
final Provider p = this;
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
putService(new ProviderService(p, "KeyStore",
|
||||
"KeychainStore", "apple.security.KeychainStore"));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
1147
src/java.base/macosx/classes/apple/security/KeychainStore.java
Normal file
1147
src/java.base/macosx/classes/apple/security/KeychainStore.java
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2015, 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.lang;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
class ClassLoaderHelper {
|
||||
|
||||
private ClassLoaderHelper() {}
|
||||
|
||||
/**
|
||||
* Indicates, whether PATH env variable is allowed to contain quoted entries.
|
||||
*/
|
||||
static final boolean allowsQuotedPathElements = false;
|
||||
|
||||
/**
|
||||
* Returns an alternate path name for the given file
|
||||
* such that if the original pathname did not exist, then the
|
||||
* file may be located at the alternate location.
|
||||
* For mac, this replaces the final .dylib suffix with .jnilib
|
||||
*/
|
||||
static File mapAlternativeName(File lib) {
|
||||
String name = lib.toString();
|
||||
int index = name.lastIndexOf('.');
|
||||
if (index < 0) {
|
||||
return null;
|
||||
}
|
||||
return new File(name.substring(0, index) + ".jnilib");
|
||||
}
|
||||
}
|
122
src/java.base/macosx/classes/java/net/DefaultInterface.java
Normal file
122
src/java.base/macosx/classes/java/net/DefaultInterface.java
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 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
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Choose a network interface to be the default for
|
||||
* outgoing IPv6 traffic that does not specify a scope_id (and which needs one).
|
||||
* We choose the first interface that is up and is (in order of preference):
|
||||
* 1. neither loopback nor point to point
|
||||
* 2. point to point
|
||||
* 3. loopback
|
||||
* 4. none.
|
||||
* Platforms that do not require a default interface implement a dummy
|
||||
* that returns null.
|
||||
*/
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.io.IOException;
|
||||
|
||||
class DefaultInterface {
|
||||
|
||||
private static final NetworkInterface defaultInterface =
|
||||
chooseDefaultInterface();
|
||||
|
||||
static NetworkInterface getDefault() {
|
||||
return defaultInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose a default interface. This method returns the first interface that
|
||||
* is both "up" and supports multicast. This method chooses an interface in
|
||||
* order of preference:
|
||||
* 1. neither loopback nor point to point
|
||||
* ( prefer interfaces with dual IP support )
|
||||
* 2. point to point
|
||||
* 3. loopback
|
||||
*
|
||||
* @return the chosen interface or {@code null} if there isn't a suitable
|
||||
* default
|
||||
*/
|
||||
private static NetworkInterface chooseDefaultInterface() {
|
||||
Enumeration<NetworkInterface> nifs;
|
||||
|
||||
try {
|
||||
nifs = NetworkInterface.getNetworkInterfaces();
|
||||
} catch (IOException ignore) {
|
||||
// unable to enumerate network interfaces
|
||||
return null;
|
||||
}
|
||||
|
||||
NetworkInterface preferred = null;
|
||||
NetworkInterface ppp = null;
|
||||
NetworkInterface loopback = null;
|
||||
|
||||
while (nifs.hasMoreElements()) {
|
||||
NetworkInterface ni = nifs.nextElement();
|
||||
try {
|
||||
if (!ni.isUp() || !ni.supportsMulticast())
|
||||
continue;
|
||||
|
||||
boolean ip4 = false, ip6 = false;
|
||||
Enumeration<InetAddress> addrs = ni.getInetAddresses();
|
||||
while (addrs.hasMoreElements()) {
|
||||
InetAddress addr = addrs.nextElement();
|
||||
if (!addr.isAnyLocalAddress()) {
|
||||
if (addr instanceof Inet4Address) {
|
||||
ip4 = true;
|
||||
} else if (addr instanceof Inet6Address) {
|
||||
ip6 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isLoopback = ni.isLoopback();
|
||||
boolean isPPP = ni.isPointToPoint();
|
||||
if (!isLoopback && !isPPP) {
|
||||
// found an interface that is not the loopback or a
|
||||
// point-to-point interface
|
||||
if (preferred == null) {
|
||||
preferred = ni;
|
||||
} else if (ip4 && ip6){
|
||||
return ni;
|
||||
}
|
||||
}
|
||||
if (ppp == null && isPPP)
|
||||
ppp = ni;
|
||||
if (loopback == null && isLoopback)
|
||||
loopback = ni;
|
||||
|
||||
} catch (IOException skip) { }
|
||||
}
|
||||
|
||||
if (preferred != null) {
|
||||
return preferred;
|
||||
} else {
|
||||
return (ppp != null) ? ppp : loopback;
|
||||
}
|
||||
}
|
||||
}
|
26
src/java.base/macosx/classes/module-info.java.extra
Normal file
26
src/java.base/macosx/classes/module-info.java.extra
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2016, 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.
|
||||
*/
|
||||
|
||||
exports jdk.internal.loader to java.desktop;
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 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.nio.ch;
|
||||
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.AsynchronousChannelProvider;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.io.IOException;
|
||||
|
||||
public class BsdAsynchronousChannelProvider
|
||||
extends AsynchronousChannelProvider
|
||||
{
|
||||
private static volatile KQueuePort defaultPort;
|
||||
|
||||
private KQueuePort defaultEventPort() throws IOException {
|
||||
if (defaultPort == null) {
|
||||
synchronized (BsdAsynchronousChannelProvider.class) {
|
||||
if (defaultPort == null) {
|
||||
defaultPort = new KQueuePort(this, ThreadPool.getDefault()).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultPort;
|
||||
}
|
||||
|
||||
public BsdAsynchronousChannelProvider() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory factory)
|
||||
throws IOException
|
||||
{
|
||||
return new KQueuePort(this, ThreadPool.create(nThreads, factory)).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize)
|
||||
throws IOException
|
||||
{
|
||||
return new KQueuePort(this, ThreadPool.wrap(executor, initialSize)).start();
|
||||
}
|
||||
|
||||
private Port toPort(AsynchronousChannelGroup group) throws IOException {
|
||||
if (group == null) {
|
||||
return defaultEventPort();
|
||||
} else {
|
||||
if (!(group instanceof KQueuePort))
|
||||
throw new IllegalChannelGroupException();
|
||||
return (Port)group;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group)
|
||||
throws IOException
|
||||
{
|
||||
return new UnixAsynchronousServerSocketChannelImpl(toPort(group));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group)
|
||||
throws IOException
|
||||
{
|
||||
return new UnixAsynchronousSocketChannelImpl(toPort(group));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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.nio.ch;
|
||||
|
||||
import java.nio.channels.spi.AsynchronousChannelProvider;
|
||||
|
||||
/**
|
||||
* Creates this platform's default AsynchronousChannelProvider
|
||||
*/
|
||||
|
||||
public class DefaultAsynchronousChannelProvider {
|
||||
|
||||
/**
|
||||
* Prevent instantiation.
|
||||
*/
|
||||
private DefaultAsynchronousChannelProvider() { }
|
||||
|
||||
/**
|
||||
* Returns the default AsynchronousChannelProvider.
|
||||
*/
|
||||
public static AsynchronousChannelProvider create() {
|
||||
return new BsdAsynchronousChannelProvider();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2017, 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.nio.ch;
|
||||
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
|
||||
/**
|
||||
* Creates this platform's default SelectorProvider
|
||||
*/
|
||||
|
||||
public class DefaultSelectorProvider {
|
||||
|
||||
/**
|
||||
* Prevent instantiation.
|
||||
*/
|
||||
private DefaultSelectorProvider() { }
|
||||
|
||||
/**
|
||||
* Returns the default SelectorProvider.
|
||||
*/
|
||||
public static SelectorProvider create() {
|
||||
return new KQueueSelectorProvider();
|
||||
}
|
||||
}
|
120
src/java.base/macosx/classes/sun/nio/ch/KQueue.java
Normal file
120
src/java.base/macosx/classes/sun/nio/ch/KQueue.java
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 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
|
||||
* 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.nio.ch;
|
||||
|
||||
import java.io.IOException;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* Provides access to the BSD kqueue facility.
|
||||
*/
|
||||
|
||||
class KQueue {
|
||||
private KQueue() { }
|
||||
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
|
||||
/**
|
||||
* struct kevent {
|
||||
* uintptr_t ident; // identifier for this event, usually the fd
|
||||
* int16_t filter; // filter for event
|
||||
* uint16_t flags; // general flags
|
||||
* uint32_t fflags; // filter-specific flags
|
||||
* intptr_t data; // filter-specific data
|
||||
* void *udata; // opaque user data identifier
|
||||
* };
|
||||
*/
|
||||
private static final int SIZEOF_KQUEUEEVENT = keventSize();
|
||||
private static final int OFFSET_IDENT = identOffset();
|
||||
private static final int OFFSET_FILTER = filterOffset();
|
||||
private static final int OFFSET_FLAGS = flagsOffset();
|
||||
|
||||
// filters
|
||||
static final int EVFILT_READ = -1;
|
||||
static final int EVFILT_WRITE = -2;
|
||||
|
||||
// flags
|
||||
static final int EV_ADD = 0x0001;
|
||||
static final int EV_ONESHOT = 0x0010;
|
||||
static final int EV_CLEAR = 0x0020;
|
||||
|
||||
/**
|
||||
* Allocates a poll array to handle up to {@code count} events.
|
||||
*/
|
||||
static long allocatePollArray(int count) {
|
||||
return unsafe.allocateMemory(count * SIZEOF_KQUEUEEVENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a poll array
|
||||
*/
|
||||
static void freePollArray(long address) {
|
||||
unsafe.freeMemory(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns kevent[i].
|
||||
*/
|
||||
static long getEvent(long address, int i) {
|
||||
return address + (SIZEOF_KQUEUEEVENT*i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file descriptor from a kevent (assuming to be in ident field)
|
||||
*/
|
||||
static int getDescriptor(long address) {
|
||||
return unsafe.getInt(address + OFFSET_IDENT);
|
||||
}
|
||||
|
||||
static int getFilter(long address) {
|
||||
return unsafe.getShort(address + OFFSET_FILTER);
|
||||
}
|
||||
|
||||
static int getFlags(long address) {
|
||||
return unsafe.getShort(address + OFFSET_FLAGS);
|
||||
}
|
||||
|
||||
// -- Native methods --
|
||||
|
||||
private static native int keventSize();
|
||||
|
||||
private static native int identOffset();
|
||||
|
||||
private static native int filterOffset();
|
||||
|
||||
private static native int flagsOffset();
|
||||
|
||||
static native int kqueue() throws IOException;
|
||||
|
||||
static native int keventRegister(int kqpfd, int fd, int filter, int flags);
|
||||
|
||||
static native int keventPoll(int kqpfd, long pollAddress, int nevents)
|
||||
throws IOException;
|
||||
|
||||
static {
|
||||
IOUtil.load();
|
||||
}
|
||||
}
|
211
src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java
Normal file
211
src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* KQueueArrayWrapper.java
|
||||
* Implementation of Selector using FreeBSD / Mac OS X kqueues
|
||||
* Derived from Sun's DevPollArrayWrapper
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/*
|
||||
* struct kevent { // 32-bit 64-bit
|
||||
* uintptr_t ident; // 4 8
|
||||
* short filter; // 2 2
|
||||
* u_short flags; // 2 2
|
||||
* u_int fflags; // 4 4
|
||||
* intptr_t data; // 4 8
|
||||
* void *udata; // 4 8
|
||||
* } // Total: 20 32
|
||||
*
|
||||
* The implementation works in 32-bit and 64-bit world. We do this by calling a
|
||||
* native function that actually sets the sizes and offsets of the fields based
|
||||
* on which mode we're in.
|
||||
*/
|
||||
|
||||
class KQueueArrayWrapper {
|
||||
// kevent filters
|
||||
static short EVFILT_READ;
|
||||
static short EVFILT_WRITE;
|
||||
|
||||
// kevent struct
|
||||
// These fields are now set by initStructSizes in the static initializer.
|
||||
static short SIZEOF_KEVENT;
|
||||
static short FD_OFFSET;
|
||||
static short FILTER_OFFSET;
|
||||
|
||||
// kevent array size
|
||||
static final int NUM_KEVENTS = 128;
|
||||
|
||||
// Are we in a 64-bit VM?
|
||||
static boolean is64bit = false;
|
||||
|
||||
// The kevent array (used for outcoming events only)
|
||||
private AllocatedNativeObject keventArray = null;
|
||||
private long keventArrayAddress;
|
||||
|
||||
// The kqueue fd
|
||||
private int kq = -1;
|
||||
|
||||
// The fd of the interrupt line going out
|
||||
private int outgoingInterruptFD;
|
||||
|
||||
// The fd of the interrupt line coming in
|
||||
private int incomingInterruptFD;
|
||||
|
||||
static {
|
||||
IOUtil.load();
|
||||
initStructSizes();
|
||||
String datamodel =
|
||||
GetPropertyAction.privilegedGetProperty("sun.arch.data.model");
|
||||
is64bit = "64".equals(datamodel);
|
||||
}
|
||||
|
||||
KQueueArrayWrapper() {
|
||||
int allocationSize = SIZEOF_KEVENT * NUM_KEVENTS;
|
||||
keventArray = new AllocatedNativeObject(allocationSize, true);
|
||||
keventArrayAddress = keventArray.address();
|
||||
kq = init();
|
||||
}
|
||||
|
||||
// Used to update file description registrations
|
||||
private static class Update {
|
||||
SelChImpl channel;
|
||||
int events;
|
||||
Update(SelChImpl channel, int events) {
|
||||
this.channel = channel;
|
||||
this.events = events;
|
||||
}
|
||||
}
|
||||
|
||||
private LinkedList<Update> updateList = new LinkedList<Update>();
|
||||
|
||||
void initInterrupt(int fd0, int fd1) {
|
||||
outgoingInterruptFD = fd1;
|
||||
incomingInterruptFD = fd0;
|
||||
register0(kq, fd0, 1, 0);
|
||||
}
|
||||
|
||||
int getReventOps(int index) {
|
||||
int result = 0;
|
||||
int offset = SIZEOF_KEVENT*index + FILTER_OFFSET;
|
||||
short filter = keventArray.getShort(offset);
|
||||
|
||||
// This is all that's necessary based on inspection of usage:
|
||||
// SinkChannelImpl, SourceChannelImpl, DatagramChannelImpl,
|
||||
// ServerSocketChannelImpl, SocketChannelImpl
|
||||
if (filter == EVFILT_READ) {
|
||||
result |= Net.POLLIN;
|
||||
} else if (filter == EVFILT_WRITE) {
|
||||
result |= Net.POLLOUT;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int getDescriptor(int index) {
|
||||
int offset = SIZEOF_KEVENT*index + FD_OFFSET;
|
||||
/* The ident field is 8 bytes in 64-bit world, however the API wants us
|
||||
* to return an int. Hence read the 8 bytes but return as an int.
|
||||
*/
|
||||
if (is64bit) {
|
||||
long fd = keventArray.getLong(offset);
|
||||
assert fd <= Integer.MAX_VALUE;
|
||||
return (int) fd;
|
||||
} else {
|
||||
return keventArray.getInt(offset);
|
||||
}
|
||||
}
|
||||
|
||||
void setInterest(SelChImpl channel, int events) {
|
||||
synchronized (updateList) {
|
||||
// update existing registration
|
||||
updateList.add(new Update(channel, events));
|
||||
}
|
||||
}
|
||||
|
||||
void release(SelChImpl channel) {
|
||||
synchronized (updateList) {
|
||||
// flush any pending updates
|
||||
for (Iterator<Update> it = updateList.iterator(); it.hasNext();) {
|
||||
if (it.next().channel == channel) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// remove
|
||||
register0(kq, channel.getFDVal(), 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void updateRegistrations() {
|
||||
synchronized (updateList) {
|
||||
Update u = null;
|
||||
while ((u = updateList.poll()) != null) {
|
||||
SelChImpl ch = u.channel;
|
||||
if (!ch.isOpen())
|
||||
continue;
|
||||
|
||||
register0(kq, ch.getFDVal(), u.events & Net.POLLIN, u.events & Net.POLLOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void close() throws IOException {
|
||||
if (keventArray != null) {
|
||||
keventArray.free();
|
||||
keventArray = null;
|
||||
}
|
||||
if (kq >= 0) {
|
||||
FileDispatcherImpl.closeIntFD(kq);
|
||||
kq = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int poll(long timeout) {
|
||||
updateRegistrations();
|
||||
int updated = kevent0(kq, keventArrayAddress, NUM_KEVENTS, timeout);
|
||||
return updated;
|
||||
}
|
||||
|
||||
void interrupt() {
|
||||
interrupt(outgoingInterruptFD);
|
||||
}
|
||||
|
||||
private native int init();
|
||||
private static native void initStructSizes();
|
||||
|
||||
private native void register0(int kq, int fd, int read, int write);
|
||||
private native int kevent0(int kq, long keventAddress, int keventCount,
|
||||
long timeout);
|
||||
private static native void interrupt(int fd);
|
||||
}
|
331
src/java.base/macosx/classes/sun/nio/ch/KQueuePort.java
Normal file
331
src/java.base/macosx/classes/sun/nio/ch/KQueuePort.java
Normal file
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 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
|
||||
* 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.nio.ch;
|
||||
|
||||
import java.nio.channels.spi.AsynchronousChannelProvider;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import static sun.nio.ch.KQueue.*;
|
||||
|
||||
/**
|
||||
* AsynchronousChannelGroup implementation based on the BSD kqueue facility.
|
||||
*/
|
||||
|
||||
final class KQueuePort
|
||||
extends Port
|
||||
{
|
||||
// maximum number of events to poll at a time
|
||||
private static final int MAX_KEVENTS_TO_POLL = 512;
|
||||
|
||||
// kqueue file descriptor
|
||||
private final int kqfd;
|
||||
|
||||
// true if kqueue closed
|
||||
private boolean closed;
|
||||
|
||||
// socket pair used for wakeup
|
||||
private final int sp[];
|
||||
|
||||
// number of wakeups pending
|
||||
private final AtomicInteger wakeupCount = new AtomicInteger();
|
||||
|
||||
// address of the poll array passed to kqueue_wait
|
||||
private final long address;
|
||||
|
||||
// encapsulates an event for a channel
|
||||
static class Event {
|
||||
final PollableChannel channel;
|
||||
final int events;
|
||||
|
||||
Event(PollableChannel channel, int events) {
|
||||
this.channel = channel;
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
PollableChannel channel() { return channel; }
|
||||
int events() { return events; }
|
||||
}
|
||||
|
||||
// queue of events for cases that a polling thread dequeues more than one
|
||||
// event
|
||||
private final ArrayBlockingQueue<Event> queue;
|
||||
private final Event NEED_TO_POLL = new Event(null, 0);
|
||||
private final Event EXECUTE_TASK_OR_SHUTDOWN = new Event(null, 0);
|
||||
|
||||
KQueuePort(AsynchronousChannelProvider provider, ThreadPool pool)
|
||||
throws IOException
|
||||
{
|
||||
super(provider, pool);
|
||||
|
||||
// open kqueue
|
||||
this.kqfd = kqueue();
|
||||
|
||||
// create socket pair for wakeup mechanism
|
||||
int[] sv = new int[2];
|
||||
try {
|
||||
socketpair(sv);
|
||||
|
||||
// register one end with kqueue
|
||||
keventRegister(kqfd, sv[0], EVFILT_READ, EV_ADD);
|
||||
} catch (IOException x) {
|
||||
close0(kqfd);
|
||||
throw x;
|
||||
}
|
||||
this.sp = sv;
|
||||
|
||||
// allocate the poll array
|
||||
this.address = allocatePollArray(MAX_KEVENTS_TO_POLL);
|
||||
|
||||
// create the queue and offer the special event to ensure that the first
|
||||
// threads polls
|
||||
this.queue = new ArrayBlockingQueue<Event>(MAX_KEVENTS_TO_POLL);
|
||||
this.queue.offer(NEED_TO_POLL);
|
||||
}
|
||||
|
||||
KQueuePort start() {
|
||||
startThreads(new EventHandlerTask());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release all resources
|
||||
*/
|
||||
private void implClose() {
|
||||
synchronized (this) {
|
||||
if (closed)
|
||||
return;
|
||||
closed = true;
|
||||
}
|
||||
freePollArray(address);
|
||||
close0(sp[0]);
|
||||
close0(sp[1]);
|
||||
close0(kqfd);
|
||||
}
|
||||
|
||||
private void wakeup() {
|
||||
if (wakeupCount.incrementAndGet() == 1) {
|
||||
// write byte to socketpair to force wakeup
|
||||
try {
|
||||
interrupt(sp[1]);
|
||||
} catch (IOException x) {
|
||||
throw new AssertionError(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void executeOnHandlerTask(Runnable task) {
|
||||
synchronized (this) {
|
||||
if (closed)
|
||||
throw new RejectedExecutionException();
|
||||
offerTask(task);
|
||||
wakeup();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void shutdownHandlerTasks() {
|
||||
/*
|
||||
* If no tasks are running then just release resources; otherwise
|
||||
* write to the one end of the socketpair to wakeup any polling threads.
|
||||
*/
|
||||
int nThreads = threadCount();
|
||||
if (nThreads == 0) {
|
||||
implClose();
|
||||
} else {
|
||||
// send interrupt to each thread
|
||||
while (nThreads-- > 0) {
|
||||
wakeup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// invoked by clients to register a file descriptor
|
||||
@Override
|
||||
void startPoll(int fd, int events) {
|
||||
// We use a separate filter for read and write events.
|
||||
// TBD: Measure cost of EV_ONESHOT vs. EV_CLEAR, either will do here.
|
||||
int err = 0;
|
||||
int flags = (EV_ADD|EV_ONESHOT);
|
||||
if ((events & Net.POLLIN) > 0)
|
||||
err = keventRegister(kqfd, fd, EVFILT_READ, flags);
|
||||
if (err == 0 && (events & Net.POLLOUT) > 0)
|
||||
err = keventRegister(kqfd, fd, EVFILT_WRITE, flags);
|
||||
if (err != 0)
|
||||
throw new InternalError("kevent failed: " + err); // should not happen
|
||||
}
|
||||
|
||||
/*
|
||||
* Task to process events from kqueue and dispatch to the channel's
|
||||
* onEvent handler.
|
||||
*
|
||||
* Events are retreived from kqueue in batch and offered to a BlockingQueue
|
||||
* where they are consumed by handler threads. A special "NEED_TO_POLL"
|
||||
* event is used to signal one consumer to re-poll when all events have
|
||||
* been consumed.
|
||||
*/
|
||||
private class EventHandlerTask implements Runnable {
|
||||
private Event poll() throws IOException {
|
||||
try {
|
||||
for (;;) {
|
||||
int n = keventPoll(kqfd, address, MAX_KEVENTS_TO_POLL);
|
||||
/*
|
||||
* 'n' events have been read. Here we map them to their
|
||||
* corresponding channel in batch and queue n-1 so that
|
||||
* they can be handled by other handler threads. The last
|
||||
* event is handled by this thread (and so is not queued).
|
||||
*/
|
||||
fdToChannelLock.readLock().lock();
|
||||
try {
|
||||
while (n-- > 0) {
|
||||
long keventAddress = getEvent(address, n);
|
||||
int fd = getDescriptor(keventAddress);
|
||||
|
||||
// wakeup
|
||||
if (fd == sp[0]) {
|
||||
if (wakeupCount.decrementAndGet() == 0) {
|
||||
// no more wakeups so drain pipe
|
||||
drain1(sp[0]);
|
||||
}
|
||||
|
||||
// queue special event if there are more events
|
||||
// to handle.
|
||||
if (n > 0) {
|
||||
queue.offer(EXECUTE_TASK_OR_SHUTDOWN);
|
||||
continue;
|
||||
}
|
||||
return EXECUTE_TASK_OR_SHUTDOWN;
|
||||
}
|
||||
|
||||
PollableChannel channel = fdToChannel.get(fd);
|
||||
if (channel != null) {
|
||||
int filter = getFilter(keventAddress);
|
||||
int events = 0;
|
||||
if (filter == EVFILT_READ)
|
||||
events = Net.POLLIN;
|
||||
else if (filter == EVFILT_WRITE)
|
||||
events = Net.POLLOUT;
|
||||
|
||||
Event ev = new Event(channel, events);
|
||||
|
||||
// n-1 events are queued; This thread handles
|
||||
// the last one except for the wakeup
|
||||
if (n > 0) {
|
||||
queue.offer(ev);
|
||||
} else {
|
||||
return ev;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
fdToChannelLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// to ensure that some thread will poll when all events have
|
||||
// been consumed
|
||||
queue.offer(NEED_TO_POLL);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
|
||||
Invoker.getGroupAndInvokeCount();
|
||||
final boolean isPooledThread = (myGroupAndInvokeCount != null);
|
||||
boolean replaceMe = false;
|
||||
Event ev;
|
||||
try {
|
||||
for (;;) {
|
||||
// reset invoke count
|
||||
if (isPooledThread)
|
||||
myGroupAndInvokeCount.resetInvokeCount();
|
||||
|
||||
try {
|
||||
replaceMe = false;
|
||||
ev = queue.take();
|
||||
|
||||
// no events and this thread has been "selected" to
|
||||
// poll for more.
|
||||
if (ev == NEED_TO_POLL) {
|
||||
try {
|
||||
ev = poll();
|
||||
} catch (IOException x) {
|
||||
x.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException x) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// handle wakeup to execute task or shutdown
|
||||
if (ev == EXECUTE_TASK_OR_SHUTDOWN) {
|
||||
Runnable task = pollTask();
|
||||
if (task == null) {
|
||||
// shutdown request
|
||||
return;
|
||||
}
|
||||
// run task (may throw error/exception)
|
||||
replaceMe = true;
|
||||
task.run();
|
||||
continue;
|
||||
}
|
||||
|
||||
// process event
|
||||
try {
|
||||
ev.channel().onEvent(ev.events(), isPooledThread);
|
||||
} catch (Error x) {
|
||||
replaceMe = true; throw x;
|
||||
} catch (RuntimeException x) {
|
||||
replaceMe = true; throw x;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// last handler to exit when shutdown releases resources
|
||||
int remaining = threadExit(this, replaceMe);
|
||||
if (remaining == 0 && isShutdown()) {
|
||||
implClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- Native methods --
|
||||
|
||||
private static native void socketpair(int[] sv) throws IOException;
|
||||
|
||||
private static native void interrupt(int fd) throws IOException;
|
||||
|
||||
private static native void drain1(int fd) throws IOException;
|
||||
|
||||
private static native void close0(int fd);
|
||||
|
||||
static {
|
||||
IOUtil.load();
|
||||
}
|
||||
}
|
262
src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java
Normal file
262
src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2015, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* KQueueSelectorImpl.java
|
||||
* Implementation of Selector using FreeBSD / Mac OS X kqueues
|
||||
* Derived from Sun's DevPollSelectorImpl
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.FileDescriptor;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
import java.util.*;
|
||||
|
||||
class KQueueSelectorImpl
|
||||
extends SelectorImpl
|
||||
{
|
||||
// File descriptors used for interrupt
|
||||
protected int fd0;
|
||||
protected int fd1;
|
||||
|
||||
// The kqueue manipulator
|
||||
KQueueArrayWrapper kqueueWrapper;
|
||||
|
||||
// Count of registered descriptors (including interrupt)
|
||||
private int totalChannels;
|
||||
|
||||
// Map from a file descriptor to an entry containing the selection key
|
||||
private HashMap<Integer,MapEntry> fdMap;
|
||||
|
||||
// True if this Selector has been closed
|
||||
private boolean closed = false;
|
||||
|
||||
// Lock for interrupt triggering and clearing
|
||||
private Object interruptLock = new Object();
|
||||
private boolean interruptTriggered = false;
|
||||
|
||||
// used by updateSelectedKeys to handle cases where the same file
|
||||
// descriptor is polled by more than one filter
|
||||
private long updateCount;
|
||||
|
||||
// Used to map file descriptors to a selection key and "update count"
|
||||
// (see updateSelectedKeys for usage).
|
||||
private static class MapEntry {
|
||||
SelectionKeyImpl ski;
|
||||
long updateCount;
|
||||
MapEntry(SelectionKeyImpl ski) {
|
||||
this.ski = ski;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Package private constructor called by factory method in
|
||||
* the abstract superclass Selector.
|
||||
*/
|
||||
KQueueSelectorImpl(SelectorProvider sp) {
|
||||
super(sp);
|
||||
long fds = IOUtil.makePipe(false);
|
||||
fd0 = (int)(fds >>> 32);
|
||||
fd1 = (int)fds;
|
||||
try {
|
||||
kqueueWrapper = new KQueueArrayWrapper();
|
||||
kqueueWrapper.initInterrupt(fd0, fd1);
|
||||
fdMap = new HashMap<>();
|
||||
totalChannels = 1;
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
FileDispatcherImpl.closeIntFD(fd0);
|
||||
} catch (IOException ioe0) {
|
||||
t.addSuppressed(ioe0);
|
||||
}
|
||||
try {
|
||||
FileDispatcherImpl.closeIntFD(fd1);
|
||||
} catch (IOException ioe1) {
|
||||
t.addSuppressed(ioe1);
|
||||
}
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected int doSelect(long timeout)
|
||||
throws IOException
|
||||
{
|
||||
int entries = 0;
|
||||
if (closed)
|
||||
throw new ClosedSelectorException();
|
||||
processDeregisterQueue();
|
||||
try {
|
||||
begin();
|
||||
entries = kqueueWrapper.poll(timeout);
|
||||
} finally {
|
||||
end();
|
||||
}
|
||||
processDeregisterQueue();
|
||||
return updateSelectedKeys(entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the keys whose fd's have been selected by kqueue.
|
||||
* Add the ready keys to the selected key set.
|
||||
* If the interrupt fd has been selected, drain it and clear the interrupt.
|
||||
*/
|
||||
private int updateSelectedKeys(int entries)
|
||||
throws IOException
|
||||
{
|
||||
int numKeysUpdated = 0;
|
||||
boolean interrupted = false;
|
||||
|
||||
// A file descriptor may be registered with kqueue with more than one
|
||||
// filter and so there may be more than one event for a fd. The update
|
||||
// count in the MapEntry tracks when the fd was last updated and this
|
||||
// ensures that the ready ops are updated rather than replaced by a
|
||||
// second or subsequent event.
|
||||
updateCount++;
|
||||
|
||||
for (int i = 0; i < entries; i++) {
|
||||
int nextFD = kqueueWrapper.getDescriptor(i);
|
||||
if (nextFD == fd0) {
|
||||
interrupted = true;
|
||||
} else {
|
||||
MapEntry me = fdMap.get(Integer.valueOf(nextFD));
|
||||
|
||||
// entry is null in the case of an interrupt
|
||||
if (me != null) {
|
||||
int rOps = kqueueWrapper.getReventOps(i);
|
||||
SelectionKeyImpl ski = me.ski;
|
||||
if (selectedKeys.contains(ski)) {
|
||||
// first time this file descriptor has been encountered on this
|
||||
// update?
|
||||
if (me.updateCount != updateCount) {
|
||||
if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
|
||||
numKeysUpdated++;
|
||||
me.updateCount = updateCount;
|
||||
}
|
||||
} else {
|
||||
// ready ops have already been set on this update
|
||||
ski.channel.translateAndUpdateReadyOps(rOps, ski);
|
||||
}
|
||||
} else {
|
||||
ski.channel.translateAndSetReadyOps(rOps, ski);
|
||||
if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
|
||||
selectedKeys.add(ski);
|
||||
numKeysUpdated++;
|
||||
me.updateCount = updateCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (interrupted) {
|
||||
// Clear the wakeup pipe
|
||||
synchronized (interruptLock) {
|
||||
IOUtil.drain(fd0);
|
||||
interruptTriggered = false;
|
||||
}
|
||||
}
|
||||
return numKeysUpdated;
|
||||
}
|
||||
|
||||
|
||||
protected void implClose() throws IOException {
|
||||
if (!closed) {
|
||||
closed = true;
|
||||
|
||||
// prevent further wakeup
|
||||
synchronized (interruptLock) {
|
||||
interruptTriggered = true;
|
||||
}
|
||||
|
||||
FileDispatcherImpl.closeIntFD(fd0);
|
||||
FileDispatcherImpl.closeIntFD(fd1);
|
||||
if (kqueueWrapper != null) {
|
||||
kqueueWrapper.close();
|
||||
kqueueWrapper = null;
|
||||
selectedKeys = null;
|
||||
|
||||
// Deregister channels
|
||||
Iterator<SelectionKey> i = keys.iterator();
|
||||
while (i.hasNext()) {
|
||||
SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
|
||||
deregister(ski);
|
||||
SelectableChannel selch = ski.channel();
|
||||
if (!selch.isOpen() && !selch.isRegistered())
|
||||
((SelChImpl)selch).kill();
|
||||
i.remove();
|
||||
}
|
||||
totalChannels = 0;
|
||||
}
|
||||
fd0 = -1;
|
||||
fd1 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void implRegister(SelectionKeyImpl ski) {
|
||||
if (closed)
|
||||
throw new ClosedSelectorException();
|
||||
int fd = IOUtil.fdVal(ski.channel.getFD());
|
||||
fdMap.put(Integer.valueOf(fd), new MapEntry(ski));
|
||||
totalChannels++;
|
||||
keys.add(ski);
|
||||
}
|
||||
|
||||
|
||||
protected void implDereg(SelectionKeyImpl ski) throws IOException {
|
||||
int fd = ski.channel.getFDVal();
|
||||
fdMap.remove(Integer.valueOf(fd));
|
||||
kqueueWrapper.release(ski.channel);
|
||||
totalChannels--;
|
||||
keys.remove(ski);
|
||||
selectedKeys.remove(ski);
|
||||
deregister((AbstractSelectionKey)ski);
|
||||
SelectableChannel selch = ski.channel();
|
||||
if (!selch.isOpen() && !selch.isRegistered())
|
||||
((SelChImpl)selch).kill();
|
||||
}
|
||||
|
||||
|
||||
public void putEventOps(SelectionKeyImpl ski, int ops) {
|
||||
if (closed)
|
||||
throw new ClosedSelectorException();
|
||||
kqueueWrapper.setInterest(ski.channel, ops);
|
||||
}
|
||||
|
||||
|
||||
public Selector wakeup() {
|
||||
synchronized (interruptLock) {
|
||||
if (!interruptTriggered) {
|
||||
kqueueWrapper.interrupt();
|
||||
interruptTriggered = true;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2012, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* KQueueSelectorProvider.java
|
||||
* Implementation of Selector using FreeBSD / Mac OS X kqueues
|
||||
* Derived from Sun's DevPollSelectorProvider
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
|
||||
public class KQueueSelectorProvider
|
||||
extends SelectorProviderImpl
|
||||
{
|
||||
public AbstractSelector openSelector() throws IOException {
|
||||
return new KQueueSelectorImpl(this);
|
||||
}
|
||||
}
|
88
src/java.base/macosx/classes/sun/nio/fs/BsdFileStore.java
Normal file
88
src/java.base/macosx/classes/sun/nio/fs/BsdFileStore.java
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2012, 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.nio.fs;
|
||||
|
||||
import java.nio.file.attribute.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Bsd implementation of FileStore
|
||||
*/
|
||||
|
||||
class BsdFileStore
|
||||
extends UnixFileStore
|
||||
{
|
||||
BsdFileStore(UnixPath file) throws IOException {
|
||||
super(file);
|
||||
}
|
||||
|
||||
BsdFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException {
|
||||
super(fs, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds, and returns, the mount entry for the file system where the file
|
||||
* resides.
|
||||
*/
|
||||
@Override
|
||||
UnixMountEntry findMountEntry() throws IOException {
|
||||
UnixFileSystem fs = file().getFileSystem();
|
||||
|
||||
// step 1: get realpath
|
||||
UnixPath path = null;
|
||||
try {
|
||||
byte[] rp = UnixNativeDispatcher.realpath(file());
|
||||
path = new UnixPath(fs, rp);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(file());
|
||||
}
|
||||
|
||||
// step 2: find mount point
|
||||
UnixPath parent = path.getParent();
|
||||
while (parent != null) {
|
||||
UnixFileAttributes attrs = null;
|
||||
try {
|
||||
attrs = UnixFileAttributes.get(parent, true);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(parent);
|
||||
}
|
||||
if (attrs.dev() != dev())
|
||||
break;
|
||||
path = parent;
|
||||
parent = parent.getParent();
|
||||
}
|
||||
|
||||
// step 3: lookup mounted file systems
|
||||
byte[] dir = path.asByteArray();
|
||||
for (UnixMountEntry entry: fs.getMountEntries()) {
|
||||
if (Arrays.equals(dir, entry.dir()))
|
||||
return entry;
|
||||
}
|
||||
|
||||
throw new IOException("Mount point not found in fstab");
|
||||
}
|
||||
}
|
104
src/java.base/macosx/classes/sun/nio/fs/BsdFileSystem.java
Normal file
104
src/java.base/macosx/classes/sun/nio/fs/BsdFileSystem.java
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2012, 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.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.security.AccessController;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* Bsd implementation of FileSystem
|
||||
*/
|
||||
|
||||
class BsdFileSystem extends UnixFileSystem {
|
||||
|
||||
BsdFileSystem(UnixFileSystemProvider provider, String dir) {
|
||||
super(provider, dir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WatchService newWatchService()
|
||||
throws IOException
|
||||
{
|
||||
// use polling implementation until we implement a BSD/kqueue one
|
||||
return new PollingWatchService();
|
||||
}
|
||||
|
||||
// lazy initialization of the list of supported attribute views
|
||||
private static class SupportedFileFileAttributeViewsHolder {
|
||||
static final Set<String> supportedFileAttributeViews =
|
||||
supportedFileAttributeViews();
|
||||
private static Set<String> supportedFileAttributeViews() {
|
||||
Set<String> result = new HashSet<String>();
|
||||
result.addAll(standardFileAttributeViews());
|
||||
return Collections.unmodifiableSet(result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> supportedFileAttributeViews() {
|
||||
return SupportedFileFileAttributeViewsHolder.supportedFileAttributeViews;
|
||||
}
|
||||
|
||||
@Override
|
||||
void copyNonPosixAttributes(int ofd, int nfd) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns object to iterate over mount entries
|
||||
*/
|
||||
@Override
|
||||
Iterable<UnixMountEntry> getMountEntries() {
|
||||
ArrayList<UnixMountEntry> entries = new ArrayList<UnixMountEntry>();
|
||||
try {
|
||||
long iter = BsdNativeDispatcher.getfsstat();
|
||||
try {
|
||||
for (;;) {
|
||||
UnixMountEntry entry = new UnixMountEntry();
|
||||
int res = BsdNativeDispatcher.fsstatEntry(iter, entry);
|
||||
if (res < 0)
|
||||
break;
|
||||
entries.add(entry);
|
||||
}
|
||||
} finally {
|
||||
BsdNativeDispatcher.endfsstat(iter);
|
||||
}
|
||||
|
||||
} catch (UnixException x) {
|
||||
// nothing we can do
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
FileStore getFileStore(UnixMountEntry entry) throws IOException {
|
||||
return new BsdFileStore(this, entry);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2012, 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.nio.fs;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Bsd implementation of FileSystemProvider
|
||||
*/
|
||||
|
||||
public class BsdFileSystemProvider extends UnixFileSystemProvider {
|
||||
public BsdFileSystemProvider() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
BsdFileSystem newFileSystem(String dir) {
|
||||
return new BsdFileSystem(this, dir);
|
||||
}
|
||||
|
||||
@Override
|
||||
BsdFileStore getFileStore(UnixPath path) throws IOException {
|
||||
return new BsdFileStore(path);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2012, 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.nio.fs;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* Bsd specific system calls.
|
||||
*/
|
||||
|
||||
class BsdNativeDispatcher extends UnixNativeDispatcher {
|
||||
protected BsdNativeDispatcher() { }
|
||||
|
||||
/**
|
||||
* struct fsstat_iter *getfsstat();
|
||||
*/
|
||||
static native long getfsstat() throws UnixException;
|
||||
|
||||
/**
|
||||
* int fsstatEntry(struct fsstat_iter * iter, UnixMountEntry entry);
|
||||
*/
|
||||
static native int fsstatEntry(long iter, UnixMountEntry entry)
|
||||
throws UnixException;
|
||||
|
||||
/**
|
||||
* void endfsstat(struct fsstat_iter * iter);
|
||||
*/
|
||||
static native void endfsstat(long iter) throws UnixException;
|
||||
|
||||
// initialize field IDs
|
||||
private static native void initIDs();
|
||||
|
||||
static {
|
||||
initIDs();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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.nio.fs;
|
||||
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
|
||||
/**
|
||||
* Creates this platform's default FileSystemProvider.
|
||||
*/
|
||||
|
||||
public class DefaultFileSystemProvider {
|
||||
private DefaultFileSystemProvider() { }
|
||||
|
||||
/**
|
||||
* Returns the default FileSystemProvider.
|
||||
*/
|
||||
public static FileSystemProvider create() {
|
||||
return new MacOSXFileSystemProvider();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2012, 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.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static sun.nio.fs.MacOSXNativeDispatcher.*;
|
||||
|
||||
/**
|
||||
* MacOS implementation of FileSystem
|
||||
*/
|
||||
|
||||
class MacOSXFileSystem extends BsdFileSystem {
|
||||
|
||||
MacOSXFileSystem(UnixFileSystemProvider provider, String dir) {
|
||||
super(provider, dir);
|
||||
}
|
||||
|
||||
// match in unicode canon_eq
|
||||
Pattern compilePathMatchPattern(String expr) {
|
||||
return Pattern.compile(expr, Pattern.CANON_EQ) ;
|
||||
}
|
||||
|
||||
char[] normalizeNativePath(char[] path) {
|
||||
for (char c : path) {
|
||||
if (c > 0x80)
|
||||
return normalizepath(path, kCFStringNormalizationFormD);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
String normalizeJavaPath(String path) {
|
||||
for (int i = 0; i < path.length(); i++) {
|
||||
if (path.charAt(i) > 0x80)
|
||||
return new String(normalizepath(path.toCharArray(),
|
||||
kCFStringNormalizationFormC));
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2015, 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.nio.fs;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.spi.FileTypeDetector;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* MacOSX implementation of FileSystemProvider
|
||||
*/
|
||||
|
||||
public class MacOSXFileSystemProvider extends BsdFileSystemProvider {
|
||||
public MacOSXFileSystemProvider() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
MacOSXFileSystem newFileSystem(String dir) {
|
||||
return new MacOSXFileSystem(this, dir);
|
||||
}
|
||||
|
||||
@Override
|
||||
FileTypeDetector getFileTypeDetector() {
|
||||
Path userMimeTypes = Paths.get(GetPropertyAction
|
||||
.privilegedGetProperty("user.home"), ".mime.types");
|
||||
|
||||
return chain(new MimeTypesFileTypeDetector(userMimeTypes),
|
||||
new UTIFileTypeDetector());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2012, 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.nio.fs;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* MacOSX specific system calls.
|
||||
*/
|
||||
|
||||
class MacOSXNativeDispatcher extends BsdNativeDispatcher {
|
||||
private MacOSXNativeDispatcher() { }
|
||||
|
||||
static final int kCFStringNormalizationFormC = 2;
|
||||
static final int kCFStringNormalizationFormD = 0;
|
||||
static native char[] normalizepath(char[] path, int form);
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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.nio.fs;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* File type detector that uses a file extension to look up its MIME type
|
||||
* via the Apple Uniform Type Identifier interfaces.
|
||||
*/
|
||||
class UTIFileTypeDetector extends AbstractFileTypeDetector {
|
||||
UTIFileTypeDetector() {
|
||||
super();
|
||||
}
|
||||
|
||||
private native String probe0(String fileExtension) throws IOException;
|
||||
|
||||
@Override
|
||||
protected String implProbeContentType(Path path) throws IOException {
|
||||
Path fn = path.getFileName();
|
||||
if (fn == null)
|
||||
return null; // no file name
|
||||
|
||||
String ext = getExtension(fn.toString());
|
||||
if (ext.isEmpty())
|
||||
return null; // no extension
|
||||
|
||||
return probe0(ext);
|
||||
}
|
||||
|
||||
static {
|
||||
AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
System.loadLibrary("nio");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,909 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2016, 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.util.locale.provider;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.text.*;
|
||||
import java.text.spi.DateFormatProvider;
|
||||
import java.text.spi.DateFormatSymbolsProvider;
|
||||
import java.text.spi.DecimalFormatSymbolsProvider;
|
||||
import java.text.spi.NumberFormatProvider;
|
||||
import java.util.Collections;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle.Control;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||
import java.util.spi.CalendarDataProvider;
|
||||
import java.util.spi.CalendarNameProvider;
|
||||
import java.util.spi.CurrencyNameProvider;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
import sun.text.spi.JavaTimeDateTimePatternProvider;
|
||||
import sun.util.spi.CalendarProvider;
|
||||
|
||||
/**
|
||||
* LocaleProviderAdapter implementation for the Mac OS X locale data
|
||||
*
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public class HostLocaleProviderAdapterImpl {
|
||||
|
||||
// per supported locale instances
|
||||
private static final ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> dateFormatPatternsMap =
|
||||
new ConcurrentHashMap<>(2);
|
||||
private static final ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> numberFormatPatternsMap =
|
||||
new ConcurrentHashMap<>(2);
|
||||
private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> dateFormatSymbolsMap =
|
||||
new ConcurrentHashMap<>(2);
|
||||
private static final ConcurrentMap<Locale, SoftReference<DecimalFormatSymbols>> decimalFormatSymbolsMap =
|
||||
new ConcurrentHashMap<>(2);
|
||||
|
||||
// locale categories
|
||||
private static final int CAT_DISPLAY = 0;
|
||||
private static final int CAT_FORMAT = 1;
|
||||
|
||||
// NumberFormat styles
|
||||
private static final int NF_NUMBER = 0;
|
||||
private static final int NF_CURRENCY = 1;
|
||||
private static final int NF_PERCENT = 2;
|
||||
private static final int NF_INTEGER = 3;
|
||||
private static final int NF_MAX = NF_INTEGER;
|
||||
|
||||
// CalendarData value types
|
||||
private static final int CD_FIRSTDAYOFWEEK = 0;
|
||||
private static final int CD_MINIMALDAYSINFIRSTWEEK = 1;
|
||||
|
||||
// Locale/Currency display name types
|
||||
private static final int DN_LOCALE_LANGUAGE = 0;
|
||||
private static final int DN_LOCALE_SCRIPT = 1;
|
||||
private static final int DN_LOCALE_REGION = 2;
|
||||
private static final int DN_LOCALE_VARIANT = 3;
|
||||
private static final int DN_CURRENCY_CODE = 4;
|
||||
private static final int DN_CURRENCY_SYMBOL = 5;
|
||||
|
||||
// TimeZone display name types
|
||||
private static final int DN_TZ_SHORT_STANDARD = 0;
|
||||
private static final int DN_TZ_SHORT_DST = 1;
|
||||
private static final int DN_TZ_LONG_STANDARD = 2;
|
||||
private static final int DN_TZ_LONG_DST = 3;
|
||||
|
||||
private static final Set<Locale> supportedLocaleSet;
|
||||
static {
|
||||
Set<Locale> tmpSet = new HashSet<>();
|
||||
// Assuming the default locales do not include any extensions, so
|
||||
// no stripping is needed here.
|
||||
Locale l = convertMacOSXLocaleToJavaLocale(getDefaultLocale(CAT_FORMAT));
|
||||
tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));
|
||||
l = convertMacOSXLocaleToJavaLocale(getDefaultLocale(CAT_DISPLAY));
|
||||
tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));
|
||||
supportedLocaleSet = Collections.unmodifiableSet(tmpSet);
|
||||
}
|
||||
private static final Locale[] supportedLocale = supportedLocaleSet.toArray(new Locale[0]);
|
||||
|
||||
@SuppressWarnings("fallthrough")
|
||||
private static Locale convertMacOSXLocaleToJavaLocale(String macosxloc) {
|
||||
// MacOSX may return ICU notation, here is the quote from CFLocale doc:
|
||||
// "The corresponding value is a CFString containing the POSIX locale
|
||||
// identifier as used by ICU, such as "ja_JP". If you have a variant
|
||||
// locale or a different currency or calendar, it can be as complex as
|
||||
// "en_US_POSIX@calendar=japanese;currency=EUR" or
|
||||
// "az_Cyrl_AZ@calendar=buddhist;currency=JPY".
|
||||
String[] tmp = macosxloc.split("@");
|
||||
String langTag = tmp[0].replace('_', '-');
|
||||
if (tmp.length > 1) {
|
||||
String[] ext = tmp[1].split(";");
|
||||
for (String keyval : ext) {
|
||||
// We are only interested in "calendar" value for now.
|
||||
if (keyval.startsWith("calendar=")) {
|
||||
String calid = keyval.substring(keyval.indexOf('=')+1);
|
||||
switch (calid) {
|
||||
case "gregorian":
|
||||
langTag += "-u-ca-gregory";
|
||||
break;
|
||||
case "japanese":
|
||||
// Tweak for ja_JP_JP
|
||||
if (tmp[0].equals("ja_JP")) {
|
||||
return JRELocaleConstants.JA_JP_JP;
|
||||
}
|
||||
|
||||
// fall through
|
||||
|
||||
default:
|
||||
langTag += "-u-ca-" + calid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Locale.forLanguageTag(langTag);
|
||||
}
|
||||
|
||||
public static JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider() {
|
||||
return new JavaTimeDateTimePatternProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return getSupportedCalendarLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return isSupportedCalendarLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale) {
|
||||
return toJavaTimeDateTimePattern(calType, getDateTimePattern(dateStyle, timeStyle, locale));
|
||||
|
||||
}
|
||||
|
||||
private String getDateTimePattern(int dateStyle, int timeStyle, Locale locale) {
|
||||
AtomicReferenceArray<String> dateFormatPatterns;
|
||||
SoftReference<AtomicReferenceArray<String>> ref = dateFormatPatternsMap.get(locale);
|
||||
|
||||
if (ref == null || (dateFormatPatterns = ref.get()) == null) {
|
||||
dateFormatPatterns = new AtomicReferenceArray<>(5 * 5);
|
||||
ref = new SoftReference<>(dateFormatPatterns);
|
||||
dateFormatPatternsMap.put(locale, ref);
|
||||
}
|
||||
int index = (dateStyle + 1) * 5 + timeStyle + 1;
|
||||
String pattern = dateFormatPatterns.get(index);
|
||||
if (pattern == null) {
|
||||
String langTag = locale.toLanguageTag();
|
||||
pattern = translateDateFormatLetters(getCalendarID(langTag),
|
||||
getDateTimePatternNative(dateStyle, timeStyle, langTag));
|
||||
if (!dateFormatPatterns.compareAndSet(index, null, pattern)) {
|
||||
pattern = dateFormatPatterns.get(index);
|
||||
}
|
||||
}
|
||||
return pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will convert JRE Date/time Pattern String to JSR310
|
||||
* type Date/Time Pattern
|
||||
*/
|
||||
private String toJavaTimeDateTimePattern(String calendarType, String jrePattern) {
|
||||
int length = jrePattern.length();
|
||||
StringBuilder sb = new StringBuilder(length);
|
||||
boolean inQuote = false;
|
||||
int count = 0;
|
||||
char lastLetter = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
char c = jrePattern.charAt(i);
|
||||
if (c == '\'') {
|
||||
// '' is treated as a single quote regardless of being
|
||||
// in a quoted section.
|
||||
if ((i + 1) < length) {
|
||||
char nextc = jrePattern.charAt(i + 1);
|
||||
if (nextc == '\'') {
|
||||
i++;
|
||||
if (count != 0) {
|
||||
convert(calendarType, lastLetter, count, sb);
|
||||
lastLetter = 0;
|
||||
count = 0;
|
||||
}
|
||||
sb.append("''");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!inQuote) {
|
||||
if (count != 0) {
|
||||
convert(calendarType, lastLetter, count, sb);
|
||||
lastLetter = 0;
|
||||
count = 0;
|
||||
}
|
||||
inQuote = true;
|
||||
} else {
|
||||
inQuote = false;
|
||||
}
|
||||
sb.append(c);
|
||||
continue;
|
||||
}
|
||||
if (inQuote) {
|
||||
sb.append(c);
|
||||
continue;
|
||||
}
|
||||
if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {
|
||||
if (count != 0) {
|
||||
convert(calendarType, lastLetter, count, sb);
|
||||
lastLetter = 0;
|
||||
count = 0;
|
||||
}
|
||||
sb.append(c);
|
||||
continue;
|
||||
}
|
||||
if (lastLetter == 0 || lastLetter == c) {
|
||||
lastLetter = c;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
convert(calendarType, lastLetter, count, sb);
|
||||
lastLetter = c;
|
||||
count = 1;
|
||||
}
|
||||
if (inQuote) {
|
||||
// should not come here.
|
||||
// returning null so that FALLBACK provider will kick in.
|
||||
return null;
|
||||
}
|
||||
if (count != 0) {
|
||||
convert(calendarType, lastLetter, count, sb);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void convert(String calendarType, char letter, int count, StringBuilder sb) {
|
||||
switch (letter) {
|
||||
case 'G':
|
||||
if (calendarType.equals("japanese")) {
|
||||
if (count >= 4) {
|
||||
count = 1;
|
||||
} else {
|
||||
count = 5;
|
||||
}
|
||||
} else if (!calendarType.equals("iso8601")) {
|
||||
// Gregorian calendar is iso8601 for java.time
|
||||
// Adjust the number of 'G's
|
||||
if (count >= 4) {
|
||||
// JRE full -> JavaTime full
|
||||
count = 4;
|
||||
} else {
|
||||
// JRE short -> JavaTime short
|
||||
count = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'y':
|
||||
if (calendarType.equals("japanese") && count >= 4) {
|
||||
// JRE specific "gan-nen" support
|
||||
count = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// JSR 310 and CLDR define 5-letter patterns for narrow text.
|
||||
if (count > 4) {
|
||||
count = 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
appendN(letter, count, sb);
|
||||
}
|
||||
|
||||
private void appendN(char c, int n, StringBuilder sb) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static DateFormatProvider getDateFormatProvider() {
|
||||
return new DateFormatProvider() {
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return getSupportedCalendarLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return isSupportedCalendarLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getDateInstance(int style, Locale locale) {
|
||||
return new SimpleDateFormat(getDateTimePattern(style, -1, locale),
|
||||
getCalendarLocale(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getTimeInstance(int style, Locale locale) {
|
||||
return new SimpleDateFormat(getDateTimePattern(-1, style, locale),
|
||||
getCalendarLocale(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getDateTimeInstance(int dateStyle,
|
||||
int timeStyle, Locale locale) {
|
||||
return new SimpleDateFormat(getDateTimePattern(dateStyle, timeStyle, locale),
|
||||
getCalendarLocale(locale));
|
||||
}
|
||||
|
||||
private String getDateTimePattern(int dateStyle, int timeStyle, Locale locale) {
|
||||
AtomicReferenceArray<String> dateFormatPatterns;
|
||||
SoftReference<AtomicReferenceArray<String>> ref = dateFormatPatternsMap.get(locale);
|
||||
|
||||
if (ref == null || (dateFormatPatterns = ref.get()) == null) {
|
||||
dateFormatPatterns = new AtomicReferenceArray<>(5 * 5);
|
||||
ref = new SoftReference<>(dateFormatPatterns);
|
||||
dateFormatPatternsMap.put(locale, ref);
|
||||
}
|
||||
|
||||
int index = (dateStyle + 1) * 5 + timeStyle + 1;
|
||||
String pattern = dateFormatPatterns.get(index);
|
||||
if (pattern == null) {
|
||||
String langTag = locale.toLanguageTag();
|
||||
pattern = translateDateFormatLetters(getCalendarID(langTag),
|
||||
getDateTimePatternNative(dateStyle, timeStyle, langTag));
|
||||
if (!dateFormatPatterns.compareAndSet(index, null, pattern)) {
|
||||
pattern = dateFormatPatterns.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
return pattern;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static DateFormatSymbolsProvider getDateFormatSymbolsProvider() {
|
||||
return new DateFormatSymbolsProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
if (isSupportedLocale(Locale.getDefault(Locale.Category.FORMAT))) {
|
||||
return supportedLocale;
|
||||
}
|
||||
return new Locale[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
// Only supports the locale with Gregorian calendar
|
||||
Locale base = locale.stripExtensions();
|
||||
if (supportedLocaleSet.contains(base)) {
|
||||
return getCalendarID(locale.toLanguageTag()).equals("gregorian");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormatSymbols getInstance(Locale locale) {
|
||||
DateFormatSymbols dateFormatSymbols;
|
||||
SoftReference<DateFormatSymbols> ref = dateFormatSymbolsMap.get(locale);
|
||||
|
||||
if (ref == null || (dateFormatSymbols = ref.get()) == null) {
|
||||
dateFormatSymbols = new DateFormatSymbols(locale);
|
||||
String langTag = locale.toLanguageTag();
|
||||
dateFormatSymbols.setAmPmStrings(getAmPmStrings(langTag, dateFormatSymbols.getAmPmStrings()));
|
||||
dateFormatSymbols.setEras(getEras(langTag, dateFormatSymbols.getEras()));
|
||||
dateFormatSymbols.setMonths(getMonths(langTag, dateFormatSymbols.getMonths()));
|
||||
dateFormatSymbols.setShortMonths(getShortMonths(langTag, dateFormatSymbols.getShortMonths()));
|
||||
dateFormatSymbols.setWeekdays(getWeekdays(langTag, dateFormatSymbols.getWeekdays()));
|
||||
dateFormatSymbols.setShortWeekdays(getShortWeekdays(langTag, dateFormatSymbols.getShortWeekdays()));
|
||||
ref = new SoftReference<>(dateFormatSymbols);
|
||||
dateFormatSymbolsMap.put(locale, ref);
|
||||
}
|
||||
return (DateFormatSymbols)dateFormatSymbols.clone();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static NumberFormatProvider getNumberFormatProvider() {
|
||||
return new NumberFormatProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return supportedLocale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
// Ignore the extensions for now
|
||||
return supportedLocaleSet.contains(locale.stripExtensions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getCurrencyInstance(Locale locale) {
|
||||
return new DecimalFormat(getNumberPattern(NF_CURRENCY, locale),
|
||||
DecimalFormatSymbols.getInstance(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getIntegerInstance(Locale locale) {
|
||||
return new DecimalFormat(getNumberPattern(NF_INTEGER, locale),
|
||||
DecimalFormatSymbols.getInstance(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getNumberInstance(Locale locale) {
|
||||
return new DecimalFormat(getNumberPattern(NF_NUMBER, locale),
|
||||
DecimalFormatSymbols.getInstance(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getPercentInstance(Locale locale) {
|
||||
return new DecimalFormat(getNumberPattern(NF_PERCENT, locale),
|
||||
DecimalFormatSymbols.getInstance(locale));
|
||||
}
|
||||
|
||||
private String getNumberPattern(int style, Locale locale) {
|
||||
AtomicReferenceArray<String> numberFormatPatterns;
|
||||
SoftReference<AtomicReferenceArray<String>> ref = numberFormatPatternsMap.get(locale);
|
||||
|
||||
if (ref == null || (numberFormatPatterns = ref.get()) == null) {
|
||||
numberFormatPatterns = new AtomicReferenceArray<>(4);
|
||||
ref = new SoftReference<>(numberFormatPatterns);
|
||||
numberFormatPatternsMap.put(locale, ref);
|
||||
}
|
||||
|
||||
String pattern = numberFormatPatterns.get(style);
|
||||
if (pattern == null) {
|
||||
pattern = getNumberPatternNative(style, locale.toLanguageTag());
|
||||
if (!numberFormatPatterns.compareAndSet(style, null, pattern)) {
|
||||
pattern = numberFormatPatterns.get(style);
|
||||
}
|
||||
}
|
||||
|
||||
return pattern;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider() {
|
||||
return new DecimalFormatSymbolsProvider() {
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return supportedLocale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
// Ignore the extensions for now
|
||||
return supportedLocaleSet.contains(locale.stripExtensions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecimalFormatSymbols getInstance(Locale locale) {
|
||||
DecimalFormatSymbols decimalFormatSymbols;
|
||||
SoftReference<DecimalFormatSymbols> ref = decimalFormatSymbolsMap.get(locale);
|
||||
|
||||
if (ref == null || (decimalFormatSymbols = ref.get()) == null) {
|
||||
decimalFormatSymbols = new DecimalFormatSymbols(locale);
|
||||
String langTag = locale.toLanguageTag();
|
||||
|
||||
// DecimalFormatSymbols.setInternationalCurrencySymbol() has
|
||||
// a side effect of setting the currency symbol as well. So
|
||||
// the calling order is relevant here.
|
||||
decimalFormatSymbols.setInternationalCurrencySymbol(getInternationalCurrencySymbol(langTag, decimalFormatSymbols.getInternationalCurrencySymbol()));
|
||||
decimalFormatSymbols.setCurrencySymbol(getCurrencySymbol(langTag, decimalFormatSymbols.getCurrencySymbol()));
|
||||
decimalFormatSymbols.setDecimalSeparator(getDecimalSeparator(langTag, decimalFormatSymbols.getDecimalSeparator()));
|
||||
decimalFormatSymbols.setGroupingSeparator(getGroupingSeparator(langTag, decimalFormatSymbols.getGroupingSeparator()));
|
||||
decimalFormatSymbols.setInfinity(getInfinity(langTag, decimalFormatSymbols.getInfinity()));
|
||||
decimalFormatSymbols.setMinusSign(getMinusSign(langTag, decimalFormatSymbols.getMinusSign()));
|
||||
decimalFormatSymbols.setMonetaryDecimalSeparator(getMonetaryDecimalSeparator(langTag, decimalFormatSymbols.getMonetaryDecimalSeparator()));
|
||||
decimalFormatSymbols.setNaN(getNaN(langTag, decimalFormatSymbols.getNaN()));
|
||||
decimalFormatSymbols.setPercent(getPercent(langTag, decimalFormatSymbols.getPercent()));
|
||||
decimalFormatSymbols.setPerMill(getPerMill(langTag, decimalFormatSymbols.getPerMill()));
|
||||
decimalFormatSymbols.setZeroDigit(getZeroDigit(langTag, decimalFormatSymbols.getZeroDigit()));
|
||||
decimalFormatSymbols.setExponentSeparator(getExponentSeparator(langTag, decimalFormatSymbols.getExponentSeparator()));
|
||||
ref = new SoftReference<>(decimalFormatSymbols);
|
||||
decimalFormatSymbolsMap.put(locale, ref);
|
||||
}
|
||||
return (DecimalFormatSymbols)decimalFormatSymbols.clone();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CalendarDataProvider getCalendarDataProvider() {
|
||||
return new CalendarDataProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return getSupportedCalendarLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return isSupportedCalendarLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirstDayOfWeek(Locale locale) {
|
||||
return getCalendarInt(locale.toLanguageTag(), CD_FIRSTDAYOFWEEK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimalDaysInFirstWeek(Locale locale) {
|
||||
return getCalendarInt(locale.toLanguageTag(), CD_MINIMALDAYSINFIRSTWEEK);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CalendarNameProvider getCalendarNameProvider() {
|
||||
return new CalendarNameProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return getSupportedCalendarLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return isSupportedCalendarLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(String calType, int field, int value,
|
||||
int style, Locale locale) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> getDisplayNames(String calType,
|
||||
int field, int style, Locale locale) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CalendarProvider getCalendarProvider() {
|
||||
return new CalendarProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return getSupportedCalendarLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return isSupportedCalendarLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Calendar getInstance(TimeZone zone, Locale locale) {
|
||||
return new Calendar.Builder()
|
||||
.setLocale(locale)
|
||||
.setCalendarType(getCalendarID(locale.toLanguageTag()))
|
||||
.setTimeZone(zone)
|
||||
.setInstant(System.currentTimeMillis())
|
||||
.build();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CurrencyNameProvider getCurrencyNameProvider() {
|
||||
return new CurrencyNameProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return supportedLocale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
// Ignore the extensions for now
|
||||
return supportedLocaleSet.contains(locale.stripExtensions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(String code, Locale locale) {
|
||||
return getDisplayString(locale.toLanguageTag(), DN_CURRENCY_CODE, code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSymbol(String code, Locale locale) {
|
||||
return getDisplayString(locale.toLanguageTag(), DN_CURRENCY_SYMBOL, code);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static LocaleNameProvider getLocaleNameProvider() {
|
||||
return new LocaleNameProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return supportedLocale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
// Ignore the extensions for now
|
||||
return supportedLocaleSet.contains(locale.stripExtensions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayLanguage(String languageCode, Locale locale) {
|
||||
return getDisplayString(locale.toLanguageTag(), DN_LOCALE_LANGUAGE, languageCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayCountry(String countryCode, Locale locale) {
|
||||
return getDisplayString(locale.toLanguageTag(), DN_LOCALE_REGION, countryCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayScript(String scriptCode, Locale locale) {
|
||||
return getDisplayString(locale.toLanguageTag(), DN_LOCALE_SCRIPT, scriptCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayVariant(String variantCode, Locale locale) {
|
||||
return getDisplayString(locale.toLanguageTag(), DN_LOCALE_VARIANT, variantCode);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static TimeZoneNameProvider getTimeZoneNameProvider() {
|
||||
return new TimeZoneNameProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return supportedLocale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
// Ignore the extensions for now
|
||||
return supportedLocaleSet.contains(locale.stripExtensions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(String ID, boolean daylight, int style, Locale locale) {
|
||||
return getTimeZoneDisplayString(locale.toLanguageTag(), style * 2 + (daylight ? 1 : 0), ID);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Locale[] getSupportedCalendarLocales() {
|
||||
if (supportedLocale.length != 0 &&
|
||||
supportedLocaleSet.contains(Locale.JAPAN) &&
|
||||
isJapaneseCalendar()) {
|
||||
Locale[] sup = new Locale[supportedLocale.length+1];
|
||||
sup[0] = JRELocaleConstants.JA_JP_JP;
|
||||
System.arraycopy(supportedLocale, 0, sup, 1, supportedLocale.length);
|
||||
return sup;
|
||||
}
|
||||
return supportedLocale;
|
||||
}
|
||||
|
||||
private static boolean isSupportedCalendarLocale(Locale locale) {
|
||||
Locale base = locale;
|
||||
|
||||
if (base.hasExtensions() || base.getVariant() != "") {
|
||||
base = new Locale.Builder()
|
||||
.setLocale(locale)
|
||||
.clearExtensions()
|
||||
.build();
|
||||
}
|
||||
|
||||
if (!supportedLocaleSet.contains(base)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String requestedCalType = locale.getUnicodeLocaleType("ca");
|
||||
String nativeCalType =
|
||||
getCalendarID(base.toLanguageTag()).replaceFirst("gregorian", "gregory");
|
||||
|
||||
if (requestedCalType == null) {
|
||||
return Calendar.getAvailableCalendarTypes().contains(nativeCalType);
|
||||
} else {
|
||||
return requestedCalType.equals(nativeCalType);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isJapaneseCalendar() {
|
||||
return getCalendarID("ja-JP").equals("japanese");
|
||||
}
|
||||
|
||||
private static Locale getCalendarLocale(Locale locale) {
|
||||
String nativeCalType = getCalendarID(locale.toLanguageTag())
|
||||
.replaceFirst("gregorian", "gregory");
|
||||
if (Calendar.getAvailableCalendarTypes().contains(nativeCalType)) {
|
||||
return new Locale.Builder()
|
||||
.setLocale(locale)
|
||||
.setUnicodeLocaleKeyword("ca", nativeCalType)
|
||||
.build();
|
||||
} else {
|
||||
return locale;
|
||||
}
|
||||
}
|
||||
|
||||
// The following methods are copied from CLDRConverter build tool.
|
||||
private static String translateDateFormatLetters(String calendarType, String cldrFormat) {
|
||||
String pattern = cldrFormat;
|
||||
int length = pattern.length();
|
||||
boolean inQuote = false;
|
||||
StringBuilder jrePattern = new StringBuilder(length);
|
||||
int count = 0;
|
||||
char lastLetter = 0;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
char c = pattern.charAt(i);
|
||||
|
||||
if (c == '\'') {
|
||||
// '' is treated as a single quote regardless of being
|
||||
// in a quoted section.
|
||||
if ((i + 1) < length) {
|
||||
char nextc = pattern.charAt(i + 1);
|
||||
if (nextc == '\'') {
|
||||
i++;
|
||||
if (count != 0) {
|
||||
convert(calendarType, lastLetter, count, jrePattern);
|
||||
lastLetter = 0;
|
||||
count = 0;
|
||||
}
|
||||
jrePattern.append("''");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!inQuote) {
|
||||
if (count != 0) {
|
||||
convert(calendarType, lastLetter, count, jrePattern);
|
||||
lastLetter = 0;
|
||||
count = 0;
|
||||
}
|
||||
inQuote = true;
|
||||
} else {
|
||||
inQuote = false;
|
||||
}
|
||||
jrePattern.append(c);
|
||||
continue;
|
||||
}
|
||||
if (inQuote) {
|
||||
jrePattern.append(c);
|
||||
continue;
|
||||
}
|
||||
if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {
|
||||
if (count != 0) {
|
||||
convert(calendarType, lastLetter, count, jrePattern);
|
||||
lastLetter = 0;
|
||||
count = 0;
|
||||
}
|
||||
jrePattern.append(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastLetter == 0 || lastLetter == c) {
|
||||
lastLetter = c;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
convert(calendarType, lastLetter, count, jrePattern);
|
||||
lastLetter = c;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
if (count != 0) {
|
||||
convert(calendarType, lastLetter, count, jrePattern);
|
||||
}
|
||||
if (cldrFormat.contentEquals(jrePattern)) {
|
||||
return cldrFormat;
|
||||
}
|
||||
return jrePattern.toString();
|
||||
}
|
||||
|
||||
private static void convert(String calendarType, char cldrLetter, int count, StringBuilder sb) {
|
||||
switch (cldrLetter) {
|
||||
case 'G':
|
||||
if (!calendarType.equals("gregorian")) {
|
||||
// Adjust the number of 'G's for JRE SimpleDateFormat
|
||||
if (count == 5) {
|
||||
// CLDR narrow -> JRE short
|
||||
count = 1;
|
||||
} else if (count == 1) {
|
||||
// CLDR abbr -> JRE long
|
||||
count = 4;
|
||||
}
|
||||
}
|
||||
appendN(cldrLetter, count, sb);
|
||||
break;
|
||||
|
||||
// TODO: support 'c' and 'e' in JRE SimpleDateFormat
|
||||
// Use 'u' and 'E' for now.
|
||||
case 'c':
|
||||
case 'e':
|
||||
switch (count) {
|
||||
case 1:
|
||||
sb.append('u');
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
appendN('E', count, sb);
|
||||
break;
|
||||
case 5:
|
||||
appendN('E', 3, sb);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
case 'V':
|
||||
appendN('z', count, sb);
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
if (count == 4 || count == 5) {
|
||||
sb.append("XXX");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
case 'U':
|
||||
case 'q':
|
||||
case 'Q':
|
||||
case 'l':
|
||||
case 'g':
|
||||
case 'j':
|
||||
case 'A':
|
||||
// Unsupported letter. Just append it within quotes
|
||||
sb.append('\'');
|
||||
sb.append(cldrLetter);
|
||||
sb.append('\'');
|
||||
break;
|
||||
|
||||
default:
|
||||
appendN(cldrLetter, count, sb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void appendN(char c, int n, StringBuilder sb) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
// initialize
|
||||
private static native String getDefaultLocale(int cat);
|
||||
|
||||
// For DateFormatProvider
|
||||
private static native String getDateTimePatternNative(int dateStyle, int timeStyle, String langtag);
|
||||
private static native String getCalendarID(String langTag);
|
||||
|
||||
// For NumberFormatProvider
|
||||
private static native String getNumberPatternNative(int style, String langtag);
|
||||
|
||||
// For DateFormatSymbolsProvider
|
||||
private static native String[] getAmPmStrings(String langTag, String[] ampm);
|
||||
private static native String[] getEras(String langTag, String[] eras);
|
||||
private static native String[] getMonths(String langTag, String[] months);
|
||||
private static native String[] getShortMonths(String langTag, String[] smonths);
|
||||
private static native String[] getWeekdays(String langTag, String[] wdays);
|
||||
private static native String[] getShortWeekdays(String langTag, String[] swdays);
|
||||
|
||||
// For DecimalFormatSymbolsProvider
|
||||
private static native String getCurrencySymbol(String langTag, String currencySymbol);
|
||||
private static native char getDecimalSeparator(String langTag, char decimalSeparator);
|
||||
private static native char getGroupingSeparator(String langTag, char groupingSeparator);
|
||||
private static native String getInfinity(String langTag, String infinity);
|
||||
private static native String getInternationalCurrencySymbol(String langTag, String internationalCurrencySymbol);
|
||||
private static native char getMinusSign(String langTag, char minusSign);
|
||||
private static native char getMonetaryDecimalSeparator(String langTag, char monetaryDecimalSeparator);
|
||||
private static native String getNaN(String langTag, String nan);
|
||||
private static native char getPercent(String langTag, char percent);
|
||||
private static native char getPerMill(String langTag, char perMill);
|
||||
private static native char getZeroDigit(String langTag, char zeroDigit);
|
||||
private static native String getExponentSeparator(String langTag, String exponent);
|
||||
|
||||
// For CalendarDataProvider
|
||||
private static native int getCalendarInt(String langTag, int type);
|
||||
|
||||
// For Locale/CurrencyNameProvider
|
||||
private static native String getDisplayString(String langTag, int key, String value);
|
||||
|
||||
// For TimeZoneNameProvider
|
||||
private static native String getTimeZoneDisplayString(String langTag, int style, String value);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue