8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -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;
}
});
}
}

File diff suppressed because it is too large Load diff

View file

@ -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");
}
}

View 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;
}
}
}

View 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;

View file

@ -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));
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View 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();
}
}

View 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);
}

View 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();
}
}

View 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;
}
}

View file

@ -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);
}
}

View 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");
}
}

View 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);
}
}

View file

@ -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);
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -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);
}

View file

@ -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;
}
});
}
}

View file

@ -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);
}