This commit is contained in:
Lana Steuck 2010-09-16 11:19:43 -07:00
commit a682d9348d
121 changed files with 8082 additions and 3650 deletions

View File

@ -31,7 +31,7 @@ BUILDDIR = ..
PRODUCT = com
include $(BUILDDIR)/common/Defs.gmk
SUBDIRS = sun
SUBDIRS = sun oracle
include $(BUILDDIR)/common/Subdirs.gmk
all build clean clobber::

View File

@ -0,0 +1,34 @@
#
# Copyright (c) 2010, 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.
#
BUILDDIR = ../..
PRODUCT = oracle
include $(BUILDDIR)/common/Defs.gmk
SUBDIRS = net
include $(BUILDDIR)/common/Subdirs.gmk
all build clean clobber::
$(SUBDIRS-loop)

View File

@ -0,0 +1,39 @@
#
# Copyright (c) 2010, 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.
#
BUILDDIR = ../../..
PRODUCT = oracle
include $(BUILDDIR)/common/Defs.gmk
#
# Files to compile
#
AUTO_FILES_JAVA_DIRS = com/oracle/net
#
# Rules
#
include $(BUILDDIR)/common/Classes.gmk

View File

@ -573,13 +573,13 @@ $(NOT_RT_JAR_LIST): FRC
$(ECHO) "sun/jvmstat/" >> $@
$(ECHO) "sun/nio/cs/ext/" >> $@
$(ECHO) "sun/awt/HKSCS.class" >> $@
$(ECHO) "sun/awt/motif/X11GB2312$Decoder.class" >> $@
$(ECHO) "sun/awt/motif/X11GB2312$Encoder.class" >> $@
$(ECHO) "sun/awt/motif/X11GB2312\$$Decoder.class" >> $@
$(ECHO) "sun/awt/motif/X11GB2312\$$Encoder.class" >> $@
$(ECHO) "sun/awt/motif/X11GB2312.class" >> $@
$(ECHO) "sun/awt/motif/X11GBK$Encoder.class" >> $@
$(ECHO) "sun/awt/motif/X11GBK\$$Encoder.class" >> $@
$(ECHO) "sun/awt/motif/X11GBK.class" >> $@
$(ECHO) "sun/awt/motif/X11KSC5601$Decoder.class" >> $@
$(ECHO) "sun/awt/motif/X11KSC5601$Encoder.class" >> $@
$(ECHO) "sun/awt/motif/X11KSC5601\$$Decoder.class" >> $@
$(ECHO) "sun/awt/motif/X11KSC5601\$$Encoder.class" >> $@
$(ECHO) "sun/awt/motif/X11KSC5601.class" >> $@
$(ECHO) "sun/rmi/rmic/" >> $@
$(ECHO) "sun/tools/asm/" >> $@

View File

@ -91,6 +91,8 @@ SCTPAPI_PKGS = com.sun.nio.sctp
TRACING_PKGS = com.sun.tracing \
com.sun.tracing.dtrace
ORACLENET_PKGS = com.oracle.net
# non-core packages in rt.jar
NON_CORE_PKGS = $(DOMAPI_PKGS) \
$(MGMT_PKGS) \
@ -101,5 +103,6 @@ NON_CORE_PKGS = $(DOMAPI_PKGS) \
$(HTTPSERVER_PKGS) \
$(SMARTCARDIO_PKGS) \
$(TRACING_PKGS) \
$(SCTPAPI_PKGS)
$(SCTPAPI_PKGS) \
$(ORACLENET_PKGS)

View File

@ -39,10 +39,6 @@ FILES_c = \
ResolverConfigurationImpl.c \
DefaultProxySelector.c
ifeq ($(PLATFORM), solaris)
FILES_c += SdpProvider.c
endif
ifeq ($(PLATFORM), linux)
FILES_c += linux_close.c
endif

View File

@ -44,6 +44,8 @@ ifeq ($(PLATFORM), windows)
endif
FILES_c += NTLMAuthSequence.c
FILES_c += NetworkInterface_winXP.c
else
FILES_c += SdpSupport.c
endif
FILES_export = \
@ -84,7 +86,8 @@ endif
#
# Find platform specific native code
#
vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http/ntlm $(PLATFORM_SRC)/native/sun/net/spi
vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http/ntlm \
$(PLATFORM_SRC)/native/sun/net/sdp $(PLATFORM_SRC)/native/sun/net/spi
#
# Include rules

View File

@ -88,9 +88,10 @@ SUNWprivate_1.1 {
Java_java_net_PlainDatagramSocketImpl_setTimeToLive;
Java_sun_net_dns_ResolverConfigurationImpl_localDomain0;
Java_sun_net_dns_ResolverConfigurationImpl_fallbackDomain0;
Java_sun_net_sdp_SdpSupport_convert0;
Java_sun_net_sdp_SdpSupport_create0;
Java_sun_net_spi_DefaultProxySelector_init;
Java_sun_net_spi_DefaultProxySelector_getSystemProxy;
Java_sun_net_spi_SdpProvider_convert;
NET_AllocSockaddr;
NET_SockaddrToInetAddress;
NET_SockaddrEqualsInetAddress;

View File

@ -83,6 +83,7 @@ FILES_src = \
java/nio/file/ClosedFileSystemException.java \
java/nio/file/ClosedWatchServiceException.java \
java/nio/file/CopyOption.java \
java/nio/file/DirectoryIteratorException.java \
java/nio/file/DirectoryNotEmptyException.java \
java/nio/file/DirectoryStream.java \
java/nio/file/FileAlreadyExistsException.java \
@ -199,6 +200,7 @@ FILES_src = \
sun/nio/ch/PipeImpl.java \
sun/nio/ch/PollArrayWrapper.java \
sun/nio/ch/Reflect.java \
sun/nio/ch/Secrets.java \
sun/nio/ch/SelectionKeyImpl.java \
sun/nio/ch/SelectorImpl.java \
sun/nio/ch/SelectorProviderImpl.java \

View File

@ -89,7 +89,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_IOUtil_drain;
Java_sun_nio_ch_IOUtil_fdVal;
Java_sun_nio_ch_IOUtil_initIDs;
Java_sun_nio_ch_IOUtil_initPipe;
Java_sun_nio_ch_IOUtil_makePipe;
Java_sun_nio_ch_IOUtil_randomBytes;
Java_sun_nio_ch_IOUtil_setfdVal;
Java_sun_nio_ch_NativeThread_current;

View File

@ -76,7 +76,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_IOUtil_drain;
Java_sun_nio_ch_IOUtil_fdVal;
Java_sun_nio_ch_IOUtil_initIDs;
Java_sun_nio_ch_IOUtil_initPipe;
Java_sun_nio_ch_IOUtil_makePipe;
Java_sun_nio_ch_IOUtil_randomBytes;
Java_sun_nio_ch_IOUtil_setfdVal;
Java_sun_nio_ch_NativeThread_current;

View File

@ -53,6 +53,7 @@ FILES_java = \
sun/net/ftp/FtpProtocolException.java \
sun/net/ftp/impl/FtpClient.java \
sun/net/ftp/impl/DefaultFtpClientProvider.java \
sun/net/sdp/SdpSupport.java \
sun/net/spi/DefaultProxySelector.java \
sun/net/spi/nameservice/NameServiceDescriptor.java \
sun/net/spi/nameservice/NameService.java \
@ -136,8 +137,6 @@ FILES_java = \
ifeq ($(PLATFORM), windows)
FILES_java += sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java
endif
ifeq ($(PLATFORM), solaris)
FILES_java += sun/net/spi/SdpProvider.java
else
FILES_java += sun/net/sdp/SdpProvider.java
endif

View File

@ -712,19 +712,19 @@ SetModulesBootClassPath(const char *jrepath)
struct stat statbuf;
/* return if jre/lib/rt.jar exists */
sprintf(pathname, "%s%slib%srt.jar", jrepath, separator, separator);
JLI_Snprintf(pathname, sizeof(pathname), "%s%slib%srt.jar", jrepath, separator, separator);
if (stat(pathname, &statbuf) == 0) {
return;
}
/* return if jre/classes exists */
sprintf(pathname, "%s%sclasses", jrepath, separator);
JLI_Snprintf(pathname, sizeof(pathname), "%s%sclasses", jrepath, separator);
if (stat(pathname, &statbuf) == 0) {
return;
}
/* modularized jre */
sprintf(pathname, "%s%slib%s*", jrepath, separator, separator);
JLI_Snprintf(pathname, sizeof(pathname), "%s%slib%s*", jrepath, separator, separator);
s = (char *) JLI_WildcardExpandClasspath(pathname);
def = JLI_MemAlloc(sizeof(format)
- 2 /* strlen("%s") */
@ -1624,11 +1624,8 @@ ReadKnownVMs(const char *jrepath, const char * arch, jboolean speculative)
if (JLI_IsTraceLauncher()) {
start = CounterGet();
}
JLI_StrCpy(jvmCfgName, jrepath);
JLI_StrCat(jvmCfgName, FILESEP "lib" FILESEP);
JLI_StrCat(jvmCfgName, arch);
JLI_StrCat(jvmCfgName, FILESEP "jvm.cfg");
JLI_Snprintf(jvmCfgName, sizeof(jvmCfgName), "%s%slib%s%s%sjvm.cfg",
jrepath, FILESEP, FILESEP, arch, FILESEP);
jvmCfg = fopen(jvmCfgName, "r");
if (jvmCfg == NULL) {

View File

@ -0,0 +1,201 @@
/*
* Copyright (c) 2010, 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 com.oracle.net;
import java.net.Socket;
import java.net.ServerSocket;
import java.net.SocketImpl;
import java.net.SocketImplFactory;
import java.net.SocketException;
import java.nio.channels.SocketChannel;
import java.nio.channels.ServerSocketChannel;
import java.io.IOException;
import java.io.FileDescriptor;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.lang.reflect.Constructor;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.InvocationTargetException;
import sun.net.sdp.SdpSupport;
/**
* This class consists exclusively of static methods that Sockets or Channels to
* sockets that support the InfiniBand Sockets Direct Protocol (SDP).
*/
public final class Sdp {
private Sdp() { }
/**
* The package-privage ServerSocket(SocketImpl) constructor
*/
private static final Constructor<ServerSocket> serverSocketCtor;
static {
try {
serverSocketCtor = (Constructor<ServerSocket>)
ServerSocket.class.getDeclaredConstructor(SocketImpl.class);
setAccessible(serverSocketCtor);
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
}
/**
* The package-private SdpSocketImpl() constructor
*/
private static final Constructor<SocketImpl> socketImplCtor;
static {
try {
Class<?> cl = Class.forName("java.net.SdpSocketImpl", true, null);
socketImplCtor = (Constructor<SocketImpl>)cl.getDeclaredConstructor();
setAccessible(socketImplCtor);
} catch (ClassNotFoundException e) {
throw new AssertionError(e);
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
}
private static void setAccessible(final AccessibleObject o) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
o.setAccessible(true);
return null;
}
});
}
/**
* SDP enabled Socket.
*/
private static class SdpSocket extends Socket {
SdpSocket(SocketImpl impl) throws SocketException {
super(impl);
}
}
/**
* Creates a SDP enabled SocketImpl
*/
private static SocketImpl createSocketImpl() {
try {
return socketImplCtor.newInstance();
} catch (InstantiationException x) {
throw new AssertionError(x);
} catch (IllegalAccessException x) {
throw new AssertionError(x);
} catch (InvocationTargetException x) {
throw new AssertionError(x);
}
}
/**
* Creates an unconnected and unbound SDP socket. The {@code Socket} is
* associated with a {@link java.net.SocketImpl} of the system-default type.
*
* @return a new Socket
*
* @throws UnsupportedOperationException
* If SDP is not supported
* @throws IOException
* If an I/O error occurs
*/
public static Socket openSocket() throws IOException {
SocketImpl impl = createSocketImpl();
return new SdpSocket(impl);
}
/**
* Creates an unbound SDP server socket. The {@code ServerSocket} is
* associated with a {@link java.net.SocketImpl} of the system-default type.
*
* @return a new ServerSocket
*
* @throws UnsupportedOperationException
* If SDP is not supported
* @throws IOException
* If an I/O error occurs
*/
public static ServerSocket openServerSocket() throws IOException {
// create ServerSocket via package-private constructor
SocketImpl impl = createSocketImpl();
try {
return serverSocketCtor.newInstance(impl);
} catch (IllegalAccessException x) {
throw new AssertionError(x);
} catch (InstantiationException x) {
throw new AssertionError(x);
} catch (InvocationTargetException x) {
Throwable cause = x.getCause();
if (cause instanceof IOException)
throw (IOException)cause;
if (cause instanceof RuntimeException)
throw (RuntimeException)cause;
throw new RuntimeException(x);
}
}
/**
* Opens a socket channel to a SDP socket.
*
* <p> The channel will be associated with the system-wide default
* {@link java.nio.channels.spi.SelectorProvider SelectorProvider}.
*
* @return a new SocketChannel
*
* @throws UnsupportedOperationException
* If SDP is not supported or not supported by the default selector
* provider
* @throws IOException
* If an I/O error occurs.
*/
public static SocketChannel openSocketChannel() throws IOException {
FileDescriptor fd = SdpSupport.createSocket();
return sun.nio.ch.Secrets.newSocketChannel(fd);
}
/**
* Opens a socket channel to a SDP socket.
*
* <p> The channel will be associated with the system-wide default
* {@link java.nio.channels.spi.SelectorProvider SelectorProvider}.
*
* @return a new ServerSocketChannel
*
* @throws UnsupportedOperationException
* If SDP is not supported or not supported by the default selector
* provider
* @throws IOException
* If an I/O error occurs
*/
public static ServerSocketChannel openServerSocketChannel()
throws IOException
{
FileDescriptor fd = SdpSupport.createSocket();
return sun.nio.ch.Secrets.newServerSocketChannel(fd);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -518,7 +518,7 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern
setReadOnly(true);
setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
setEscapeProcessing(true);
setTypeMap(null);
//setTypeMap(null);
checkTransactionalWriter();
//Instantiating the vector for MatchColumns
@ -679,7 +679,10 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern
} else if (obj instanceof Clob) {
obj = new SerialClob((Clob)obj);
} else if (obj instanceof java.sql.Array) {
obj = new SerialArray((java.sql.Array)obj, map);
if(map != null)
obj = new SerialArray((java.sql.Array)obj, map);
else
obj = new SerialArray((java.sql.Array)obj);
}
((Row)currentRow).initColumnObject(i, obj);
@ -762,7 +765,7 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern
if( conn != null){
// JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
// must be implemented, therefore, the previous fix for 5055528 is being backed out
dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
}
}
@ -6322,6 +6325,7 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern
crs.RowSetMD = RowSetMD;
crs.numRows = 1;
crs.cursorPos = 0;
crs.setTypeMap(this.getTypeMap());
// make sure we don't get someone playing with these
// %%% is this now necessary ???
@ -10114,7 +10118,7 @@ a
* during the deserialization process
*
*/
protected void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
@ -10125,5 +10129,15 @@ a
}
}
static final long serialVersionUID =1884577171200622428L;
//------------------------- JDBC 4.1 -----------------------------------
public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
throw new SQLFeatureNotSupportedException("Not supported yet.");
}
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
throw new SQLFeatureNotSupportedException("Not supported yet.");
}
static final long serialVersionUID =1884577171200622428L;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -1746,5 +1746,23 @@ public class FilteredRowSetImpl extends WebRowSetImpl implements Serializable, C
onInsertRow = false;
super.insertRow();
}
static final long serialVersionUID = 6178454588413509360L;
/**
* This method re populates the resBundle
* during the deserialization process
*
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID = 6178454588413509360L;
} // end FilteredRowSetImpl class

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, 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
@ -153,4 +153,5 @@ public class JdbcRowSetResourceBundle implements Serializable {
return propResBundle.handleGetObject(key);
}
static final long serialVersionUID = 436199386225359954L;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -127,6 +127,11 @@ public class JoinRowSetImpl extends WebRowSetImpl implements JoinRowSet {
strMatchKey = null;
supportedJOINs =
new boolean[] {false, true, false, false, false};
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
@ -4306,5 +4311,22 @@ public class JoinRowSetImpl extends WebRowSetImpl implements JoinRowSet {
return crsInternal.createCopySchema();
}
static final long serialVersionUID = -5590501621560008453L;
/**
* This method re populates the resBundle
* during the deserialization process
*
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID = -5590501621560008453L;
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2010, 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 com.sun.rowset;
import java.sql.SQLException;
import javax.sql.rowset.CachedRowSet;
import javax.sql.rowset.FilteredRowSet;
import javax.sql.rowset.JdbcRowSet;
import javax.sql.rowset.JoinRowSet;
import javax.sql.rowset.WebRowSet;
import javax.sql.rowset.RowSetFactory;
/**
* This is the implementation specific class for the
* <code>javax.sql.rowset.spi.RowSetFactory</code>. This is the platform
* default implementation for the Java SE platform.
*
* @author Lance Andersen
*
*
* @version 1.7
*/
public final class RowSetFactoryImpl implements RowSetFactory {
public CachedRowSet createCachedRowSet() throws SQLException {
return new com.sun.rowset.CachedRowSetImpl();
}
public FilteredRowSet createFilteredRowSet() throws SQLException {
return new com.sun.rowset.FilteredRowSetImpl();
}
public JdbcRowSet createJdbcRowSet() throws SQLException {
return new com.sun.rowset.JdbcRowSetImpl();
}
public JoinRowSet createJoinRowSet() throws SQLException {
return new com.sun.rowset.JoinRowSetImpl();
}
public WebRowSet createWebRowSet() throws SQLException {
return new com.sun.rowset.WebRowSetImpl();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -103,6 +103,12 @@ public class WebRowSetImpl extends CachedRowSetImpl implements WebRowSet {
*/
public WebRowSetImpl(Hashtable env) throws SQLException {
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
if ( env == null) {
throw new SQLException(resBundle.handleGetObject("webrowsetimpl.nullhash").toString());
}
@ -263,5 +269,23 @@ public class WebRowSetImpl extends CachedRowSetImpl implements WebRowSet {
this.writeXml(oStream);
}
static final long serialVersionUID = -8771775154092422943L;
/**
* This method re populates the resBundle
* during the deserialization process
*
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID = -8771775154092422943L;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -490,4 +490,17 @@ public class CachedRowSetReader implements RowSetReader, Serializable {
startPosition = pos;
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID =5049738185801363801L;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -31,7 +31,13 @@ import java.util.*;
import java.io.*;
import com.sun.rowset.*;
import java.text.MessageFormat;
import javax.sql.rowset.*;
import javax.sql.rowset.serial.SQLInputImpl;
import javax.sql.rowset.serial.SerialArray;
import javax.sql.rowset.serial.SerialBlob;
import javax.sql.rowset.serial.SerialClob;
import javax.sql.rowset.serial.SerialStruct;
import javax.sql.rowset.spi.*;
@ -53,6 +59,7 @@ import javax.sql.rowset.spi.*;
* Standard JDBC RowSet implementations provide an object instance of this
* writer by invoking the <code>SyncProvider.getRowSetWriter()</code> method.
*
* @version 0.2
* @author Jonathan Bruce
* @see javax.sql.rowset.spi.SyncProvider
* @see javax.sql.rowset.spi.SyncFactory
@ -508,10 +515,11 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable {
ResultSet rs = null;
rs = pstmt.executeQuery();
if (rs.next() == true) {
ResultSetMetaData rsmd = rs.getMetaData();
if (rs.next()) {
if (rs.next()) {
/** More than one row conflict.
/** More than one row conflict.
* If rs has only one row we are able to
* uniquely identify the row where update
* have to happen else if more than one
@ -528,7 +536,7 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable {
// we require the record in rs to be used.
// rs.close();
// pstmt.close();
rs.first();
rs.first();
// how many fields need to be updated
int colsNotChanged = 0;
@ -552,6 +560,49 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable {
orig = origVals.getObject(i);
curr = crs.getObject(i);
rsval = rs.getObject(i);
/*
* the following block creates equivalent objects
* that would have been created if this rs is populated
* into a CachedRowSet so that comparison of the column values
* from the ResultSet and CachedRowSet are possible
*/
Map map = (crs.getTypeMap() == null)?con.getTypeMap():crs.getTypeMap();
if (rsval instanceof Struct) {
Struct s = (Struct)rsval;
// look up the class in the map
Class c = null;
c = (Class)map.get(s.getSQLTypeName());
if (c != null) {
// create new instance of the class
SQLData obj = null;
try {
obj = (SQLData)c.newInstance();
} catch (java.lang.InstantiationException ex) {
throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
ex.getMessage()));
} catch (java.lang.IllegalAccessException ex) {
throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
ex.getMessage()));
}
// get the attributes from the struct
Object attribs[] = s.getAttributes(map);
// create the SQLInput "stream"
SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
// read the values...
obj.readSQL(sqlInput, s.getSQLTypeName());
rsval = obj;
}
} else if (rsval instanceof SQLData) {
rsval = new SerialStruct((SQLData)rsval, map);
} else if (rsval instanceof Blob) {
rsval = new SerialBlob((Blob)rsval);
} else if (rsval instanceof Clob) {
rsval = new SerialClob((Clob)rsval);
} else if (rsval instanceof java.sql.Array) {
rsval = new SerialArray((java.sql.Array)rsval, map);
}
// reset boolNull if it had been set
boolNull = true;
@ -669,6 +720,9 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable {
}
} //end for
rs.close();
pstmt.close();
this.crsResolve.insertRow();
this.crsResolve.moveToCurrentRow();
@ -1179,11 +1233,22 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable {
private void buildKeyDesc(CachedRowSet crs) throws SQLException {
keyCols = crs.getKeyColumns();
ResultSetMetaData resultsetmd = crs.getMetaData();
if (keyCols == null || keyCols.length == 0) {
keyCols = new int[callerColumnCount];
for (int i = 0; i < keyCols.length; ) {
keyCols[i] = ++i;
ArrayList<Integer> listKeys = new ArrayList<Integer>();
for (int i = 0; i < callerColumnCount; i++ ) {
if(resultsetmd.getColumnType(i+1) != java.sql.Types.CLOB &&
resultsetmd.getColumnType(i+1) != java.sql.Types.STRUCT &&
resultsetmd.getColumnType(i+1) != java.sql.Types.SQLXML &&
resultsetmd.getColumnType(i+1) != java.sql.Types.BLOB &&
resultsetmd.getColumnType(i+1) != java.sql.Types.ARRAY &&
resultsetmd.getColumnType(i+1) != java.sql.Types.OTHER )
listKeys.add(i+1);
}
keyCols = new int[listKeys.size()];
for (int i = 0; i < listKeys.size(); i++ )
keyCols[i] = listKeys.get(i);
}
params = new Object[keyCols.length];
}
@ -1359,4 +1424,17 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable {
}
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID =-8506030970299413976L;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -157,4 +157,23 @@ public class InsertRow extends BaseRow implements Serializable, Cloneable {
origVals[idx - 1] = val;
markColInserted(idx - 1);
}
/**
* This method re populates the resBundle
* during the deserialization process
*
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID = 1066099658102869344L;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2010, 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
@ -35,6 +35,7 @@ import javax.sql.rowset.spi.*;
import com.sun.rowset.*;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* There will be two sets of data which will be maintained by the rowset at the
@ -4837,4 +4838,23 @@ public class SyncResolverImpl extends CachedRowSetImpl implements SyncResolver {
throws SQLException {
throw new UnsupportedOperationException("Operation not yet supported");
}
/**
* This method re populates the resBundle
* during the deserialization process
*
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID = -3345004441725080251L;
} //end class

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -216,4 +216,22 @@ public class WebRowSetXmlReader implements XmlReader, Serializable {
public void readData(RowSetInternal caller) {
}
/**
* This method re populates the resBundle
* during the deserialization process
*
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID = -9127058392819008014L;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -663,4 +663,23 @@ public class WebRowSetXmlWriter implements XmlWriter, Serializable {
return s;
}
/**
* This method re populates the resBundle
* during the deserialization process
*
*/
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID = 7163134986189677641L;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -245,4 +245,18 @@ public final class RIOptimisticProvider extends SyncProvider implements Serializ
public String getVendor() {
return this.vendorName;
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Default state initialization happens here
ois.defaultReadObject();
// Initialization of transient Res Bundle happens here .
try {
resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
} catch(IOException ioe) {
throw new RuntimeException(ioe);
}
}
static final long serialVersionUID =-3143367176751761936L;
}

View File

@ -0,0 +1,212 @@
/*
* Copyright (c) 2010, 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 com.sun.security.ntlm;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
/**
* The NTLM client. Not multi-thread enabled.<p>
* Example:
* <pre>
* Client client = new Client(null, "host", "dummy",
* "REALM", "t0pSeCr3t".toCharArray());
* byte[] type1 = client.type1();
* // Send type1 to server and receive response as type2
* byte[] type3 = client.type3(type2, nonce);
* // Send type3 to server
* </pre>
*/
public final class Client extends NTLM {
final private String hostname;
final private String username;
private String domain; // might be updated by Type 2 msg
private byte[] pw1, pw2;
/**
* Creates an NTLM Client instance.
* @param version the NTLM version to use, which can be:
* <ul>
* <li>LM/NTLM: Original NTLM v1
* <li>LM: Original NTLM v1, LM only
* <li>NTLM: Original NTLM v1, NTLM only
* <li>NTLM2: NTLM v1 with Client Challenge
* <li>LMv2/NTLMv2: NTLM v2
* <li>LMv2: NTLM v2, LM only
* <li>NTLMv2: NTLM v2, NTLM only
* </ul>
* If null, "LMv2/NTLMv2" will be used.
* @param hostname hostname of the client, can be null
* @param username username to be authenticated, must not be null
* @param domain domain of {@code username}, can be null
* @param password password for {@code username}, must not be not null.
* This method does not make any modification to this parameter, it neither
* needs to access the content of this parameter after this method call,
* so you are free to modify or nullify this parameter after this call.
* @throws NullPointerException if {@code username} or {@code password} is null.
* @throws NTLMException if {@code version} is illegal
*/
public Client(String version, String hostname, String username,
String domain, char[] password) throws NTLMException {
super(version);
if ((username == null || password == null)) {
throw new NullPointerException("username/password cannot be null");
}
this.hostname = hostname;
this.username = username;
this.domain = domain;
this.pw1 = getP1(password);
this.pw2 = getP2(password);
debug("NTLM Client: (h,u,t,version(v)) = (%s,%s,%s,%s(%s))\n",
hostname, username, domain, version, v.toString());
}
/**
* Generates the Type 1 message
* @return the message generated
*/
public byte[] type1() {
Writer p = new Writer(1, 32);
int flags = 0x8203;
if (hostname != null) {
flags |= 0x2000;
}
if (domain != null) {
flags |= 0x1000;
}
if (v != Version.NTLM) {
flags |= 0x80000;
}
p.writeInt(12, flags);
p.writeSecurityBuffer(24, hostname, false);
p.writeSecurityBuffer(16, domain, false);
debug("NTLM Client: Type 1 created\n");
debug(p.getBytes());
return p.getBytes();
}
/**
* Generates the Type 3 message
* @param type2 the responding Type 2 message from server, must not be null
* @param nonce random 8-byte array to be used in message generation,
* must not be null except for original NTLM v1
* @return the message generated
* @throws NullPointerException if {@code type2} or {@code nonce} is null
* for NTLM v1.
* @throws NTLMException if the incoming message is invalid
*/
public byte[] type3(byte[] type2, byte[] nonce) throws NTLMException {
if (type2 == null || (v != Version.NTLM && nonce == null)) {
throw new NullPointerException("type2 and nonce cannot be null");
}
debug("NTLM Client: Type 2 received\n");
debug(type2);
Reader r = new Reader(type2);
byte[] challenge = r.readBytes(24, 8);
int inputFlags = r.readInt(20);
boolean unicode = (inputFlags & 1) == 1;
String domainFromServer = r.readSecurityBuffer(12, unicode);
if (domainFromServer != null) {
domain = domainFromServer;
}
if (domain == null) {
throw new NTLMException(NTLMException.NO_DOMAIN_INFO,
"No domain info");
}
int flags = 0x88200 | (inputFlags & 3);
Writer p = new Writer(3, 64);
byte[] lm = null, ntlm = null;
p.writeSecurityBuffer(28, domain, unicode);
p.writeSecurityBuffer(36, username, unicode);
p.writeSecurityBuffer(44, hostname, unicode);
if (v == Version.NTLM) {
byte[] lmhash = calcLMHash(pw1);
byte[] nthash = calcNTHash(pw2);
if (writeLM) lm = calcResponse (lmhash, challenge);
if (writeNTLM) ntlm = calcResponse (nthash, challenge);
} else if (v == Version.NTLM2) {
byte[] nthash = calcNTHash(pw2);
lm = ntlm2LM(nonce);
ntlm = ntlm2NTLM(nthash, nonce, challenge);
} else {
byte[] nthash = calcNTHash(pw2);
if (writeLM) lm = calcV2(nthash,
username.toUpperCase(Locale.US)+domain, nonce, challenge);
if (writeNTLM) {
byte[] alist = type2.length > 48 ?
r.readSecurityBuffer(40) : new byte[0];
byte[] blob = new byte[32+alist.length];
System.arraycopy(new byte[]{1,1,0,0,0,0,0,0}, 0, blob, 0, 8);
// TS
byte[] time = BigInteger.valueOf(new Date().getTime())
.add(new BigInteger("11644473600000"))
.multiply(BigInteger.valueOf(10000))
.toByteArray();
for (int i=0; i<time.length; i++) {
blob[8+time.length-i-1] = time[i];
}
System.arraycopy(nonce, 0, blob, 16, 8);
System.arraycopy(new byte[]{0,0,0,0}, 0, blob, 24, 4);
System.arraycopy(alist, 0, blob, 28, alist.length);
System.arraycopy(new byte[]{0,0,0,0}, 0,
blob, 28+alist.length, 4);
ntlm = calcV2(nthash, username.toUpperCase(Locale.US)+domain,
blob, challenge);
}
}
p.writeSecurityBuffer(12, lm);
p.writeSecurityBuffer(20, ntlm);
p.writeSecurityBuffer(52, new byte[0]);
p.writeInt(60, flags);
debug("NTLM Client: Type 3 created\n");
debug(p.getBytes());
return p.getBytes();
}
/**
* Returns the domain value provided by server after the authentication
* is complete, or the domain value provided by the client before it.
* @return the domain
*/
public String getDomain() {
return domain;
}
/**
* Disposes any password-derived information.
*/
public void dispose() {
Arrays.fill(pw1, (byte)0);
Arrays.fill(pw2, (byte)0);
}
}

View File

@ -0,0 +1,426 @@
/*
* Copyright (c) 2010, 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 com.sun.security.ntlm;
import static com.sun.security.ntlm.Version.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;
/**
* NTLM authentication implemented according to MS-NLMP, version 12.1
* @since 1.7
*/
class NTLM {
private final SecretKeyFactory fac;
private final Cipher cipher;
private final MessageDigest md4;
private final Mac hmac;
private final MessageDigest md5;
private static final boolean DEBUG =
System.getProperty("ntlm.debug") != null;
final Version v;
final boolean writeLM;
final boolean writeNTLM;
protected NTLM(String version) throws NTLMException {
if (version == null) version = "LMv2/NTLMv2";
switch (version) {
case "LM": v = NTLM; writeLM = true; writeNTLM = false; break;
case "NTLM": v = NTLM; writeLM = false; writeNTLM = true; break;
case "LM/NTLM": v = NTLM; writeLM = writeNTLM = true; break;
case "NTLM2": v = NTLM2; writeLM = writeNTLM = true; break;
case "LMv2": v = NTLMv2; writeLM = true; writeNTLM = false; break;
case "NTLMv2": v = NTLMv2; writeLM = false; writeNTLM = true; break;
case "LMv2/NTLMv2": v = NTLMv2; writeLM = writeNTLM = true; break;
default: throw new NTLMException(NTLMException.BAD_VERSION,
"Unknown version " + version);
}
try {
fac = SecretKeyFactory.getInstance ("DES");
cipher = Cipher.getInstance ("DES/ECB/NoPadding");
md4 = sun.security.provider.MD4.getInstance();
hmac = Mac.getInstance("HmacMD5");
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchPaddingException e) {
throw new AssertionError();
} catch (NoSuchAlgorithmException e) {
throw new AssertionError();
}
}
/**
* Prints out a formatted string, called in various places inside then NTLM
* implementation for debugging/logging purposes. When the system property
* "ntlm.debug" is set, <code>System.out.printf(format, args)</code> is
* called. This method is designed to be overridden by child classes to
* match their own debugging/logging mechanisms.
* @param format a format string
* @param args the arguments referenced by <code>format</code>
* @see java.io.PrintStream#printf(java.lang.String, java.lang.Object[])
*/
public void debug(String format, Object... args) {
if (DEBUG) {
System.out.printf(format, args);
}
}
/**
* Prints out the content of a byte array, called in various places inside
* the NTLM implementation for debugging/logging purposes. When the system
* property "ntlm.debug" is set, the hexdump of the array is printed into
* System.out. This method is designed to be overridden by child classes to
* match their own debugging/logging mechanisms.
* @param bytes the byte array to print out
*/
public void debug(byte[] bytes) {
if (DEBUG) {
try {
new sun.misc.HexDumpEncoder().encodeBuffer(bytes, System.out);
} catch (IOException ioe) {
// Impossible
}
}
}
/**
* Reading an NTLM packet
*/
static class Reader {
private final byte[] internal;
Reader(byte[] data) {
internal = data;
}
int readInt(int offset) throws NTLMException {
try {
return internal[offset] & 0xff +
(internal[offset+1] & 0xff << 8) +
(internal[offset+2] & 0xff << 16) +
(internal[offset+3] & 0xff << 24);
} catch (ArrayIndexOutOfBoundsException ex) {
throw new NTLMException(NTLMException.PACKET_READ_ERROR,
"Input message incorrect size");
}
}
int readShort(int offset) throws NTLMException {
try {
return internal[offset] & 0xff +
(internal[offset+1] & 0xff << 8);
} catch (ArrayIndexOutOfBoundsException ex) {
throw new NTLMException(NTLMException.PACKET_READ_ERROR,
"Input message incorrect size");
}
}
byte[] readBytes(int offset, int len) throws NTLMException {
try {
return Arrays.copyOfRange(internal, offset, offset + len);
} catch (ArrayIndexOutOfBoundsException ex) {
throw new NTLMException(NTLMException.PACKET_READ_ERROR,
"Input message incorrect size");
}
}
byte[] readSecurityBuffer(int offset) throws NTLMException {
int pos = readInt(offset+4);
if (pos == 0) return null;
try {
return Arrays.copyOfRange(
internal, pos, pos + readShort(offset));
} catch (ArrayIndexOutOfBoundsException ex) {
throw new NTLMException(NTLMException.PACKET_READ_ERROR,
"Input message incorrect size");
}
}
String readSecurityBuffer(int offset, boolean unicode)
throws NTLMException {
byte[] raw = readSecurityBuffer(offset);
try {
return raw == null ? null : new String(
raw, unicode ? "UnicodeLittleUnmarked" : "ISO8859_1");
} catch (UnsupportedEncodingException ex) {
throw new NTLMException(NTLMException.PACKET_READ_ERROR,
"Invalid input encoding");
}
}
}
/**
* Writing an NTLM packet
*/
static class Writer {
private byte[] internal; // buffer
private int current; // current written content interface buffer
/**
* Starts writing a NTLM packet
* @param type NEGOTIATE || CHALLENGE || AUTHENTICATE
* @param len the base length, without security buffers
*/
Writer(int type, int len) {
assert len < 256;
internal = new byte[256];
current = len;
System.arraycopy (
new byte[] {'N','T','L','M','S','S','P',0,(byte)type},
0, internal, 0, 9);
}
void writeShort(int offset, int number) {
internal[offset] = (byte)(number);
internal[offset+1] = (byte)(number >> 8);
}
void writeInt(int offset, int number) {
internal[offset] = (byte)(number);
internal[offset+1] = (byte)(number >> 8);
internal[offset+2] = (byte)(number >> 16);
internal[offset+3] = (byte)(number >> 24);
}
void writeBytes(int offset, byte[] data) {
System.arraycopy(data, 0, internal, offset, data.length);
}
void writeSecurityBuffer(int offset, byte[] data) {
if (data == null) {
writeShort(offset+4, current);
} else {
int len = data.length;
if (current + len > internal.length) {
internal = Arrays.copyOf(internal, current + len + 256);
}
writeShort(offset, len);
writeShort(offset+2, len);
writeShort(offset+4, current);
System.arraycopy(data, 0, internal, current, len);
current += len;
}
}
void writeSecurityBuffer(int offset, String str, boolean unicode) {
try {
writeSecurityBuffer(offset, str == null ? null : str.getBytes(
unicode ? "UnicodeLittleUnmarked" : "ISO8859_1"));
} catch (UnsupportedEncodingException ex) {
assert false;
}
}
byte[] getBytes() {
return Arrays.copyOf(internal, current);
}
}
// LM/NTLM
/* Convert a 7 byte array to an 8 byte array (for a des key with parity)
* input starts at offset off
*/
byte[] makeDesKey (byte[] input, int off) {
int[] in = new int [input.length];
for (int i=0; i<in.length; i++ ) {
in[i] = input[i]<0 ? input[i]+256: input[i];
}
byte[] out = new byte[8];
out[0] = (byte)in[off+0];
out[1] = (byte)(((in[off+0] << 7) & 0xFF) | (in[off+1] >> 1));
out[2] = (byte)(((in[off+1] << 6) & 0xFF) | (in[off+2] >> 2));
out[3] = (byte)(((in[off+2] << 5) & 0xFF) | (in[off+3] >> 3));
out[4] = (byte)(((in[off+3] << 4) & 0xFF) | (in[off+4] >> 4));
out[5] = (byte)(((in[off+4] << 3) & 0xFF) | (in[off+5] >> 5));
out[6] = (byte)(((in[off+5] << 2) & 0xFF) | (in[off+6] >> 6));
out[7] = (byte)((in[off+6] << 1) & 0xFF);
return out;
}
byte[] calcLMHash (byte[] pwb) {
byte[] magic = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
byte[] pwb1 = new byte [14];
int len = pwb.length;
if (len > 14)
len = 14;
System.arraycopy (pwb, 0, pwb1, 0, len); /* Zero padded */
try {
DESKeySpec dks1 = new DESKeySpec (makeDesKey (pwb1, 0));
DESKeySpec dks2 = new DESKeySpec (makeDesKey (pwb1, 7));
SecretKey key1 = fac.generateSecret (dks1);
SecretKey key2 = fac.generateSecret (dks2);
cipher.init (Cipher.ENCRYPT_MODE, key1);
byte[] out1 = cipher.doFinal (magic, 0, 8);
cipher.init (Cipher.ENCRYPT_MODE, key2);
byte[] out2 = cipher.doFinal (magic, 0, 8);
byte[] result = new byte [21];
System.arraycopy (out1, 0, result, 0, 8);
System.arraycopy (out2, 0, result, 8, 8);
return result;
} catch (InvalidKeyException ive) {
// Will not happen, all key material are 8 bytes
assert false;
} catch (InvalidKeySpecException ikse) {
// Will not happen, we only feed DESKeySpec to DES factory
assert false;
} catch (IllegalBlockSizeException ibse) {
// Will not happen, we encrypt 8 bytes
assert false;
} catch (BadPaddingException bpe) {
// Will not happen, this is encryption
assert false;
}
return null; // will not happen, we returned already
}
byte[] calcNTHash (byte[] pw) {
byte[] out = md4.digest (pw);
byte[] result = new byte [21];
System.arraycopy (out, 0, result, 0, 16);
return result;
}
/* key is a 21 byte array. Split it into 3 7 byte chunks,
* Convert each to 8 byte DES keys, encrypt the text arg with
* each key and return the three results in a sequential []
*/
byte[] calcResponse (byte[] key, byte[] text) {
try {
assert key.length == 21;
DESKeySpec dks1 = new DESKeySpec(makeDesKey(key, 0));
DESKeySpec dks2 = new DESKeySpec(makeDesKey(key, 7));
DESKeySpec dks3 = new DESKeySpec(makeDesKey(key, 14));
SecretKey key1 = fac.generateSecret(dks1);
SecretKey key2 = fac.generateSecret(dks2);
SecretKey key3 = fac.generateSecret(dks3);
cipher.init(Cipher.ENCRYPT_MODE, key1);
byte[] out1 = cipher.doFinal(text, 0, 8);
cipher.init(Cipher.ENCRYPT_MODE, key2);
byte[] out2 = cipher.doFinal(text, 0, 8);
cipher.init(Cipher.ENCRYPT_MODE, key3);
byte[] out3 = cipher.doFinal(text, 0, 8);
byte[] result = new byte[24];
System.arraycopy(out1, 0, result, 0, 8);
System.arraycopy(out2, 0, result, 8, 8);
System.arraycopy(out3, 0, result, 16, 8);
return result;
} catch (IllegalBlockSizeException ex) { // None will happen
assert false;
} catch (BadPaddingException ex) {
assert false;
} catch (InvalidKeySpecException ex) {
assert false;
} catch (InvalidKeyException ex) {
assert false;
}
return null;
}
// LMv2/NTLMv2
byte[] hmacMD5(byte[] key, byte[] text) {
try {
SecretKeySpec skey =
new SecretKeySpec(Arrays.copyOf(key, 16), "HmacMD5");
hmac.init(skey);
return hmac.doFinal(text);
} catch (InvalidKeyException ex) {
assert false;
} catch (RuntimeException e) {
assert false;
}
return null;
}
byte[] calcV2(byte[] nthash, String text, byte[] blob, byte[] challenge) {
try {
byte[] ntlmv2hash = hmacMD5(nthash,
text.getBytes("UnicodeLittleUnmarked"));
byte[] cn = new byte[blob.length+8];
System.arraycopy(challenge, 0, cn, 0, 8);
System.arraycopy(blob, 0, cn, 8, blob.length);
byte[] result = new byte[16+blob.length];
System.arraycopy(hmacMD5(ntlmv2hash, cn), 0, result, 0, 16);
System.arraycopy(blob, 0, result, 16, blob.length);
return result;
} catch (UnsupportedEncodingException ex) {
assert false;
}
return null;
}
// NTLM2 LM/NTLM
static byte[] ntlm2LM(byte[] nonce) {
return Arrays.copyOf(nonce, 24);
}
byte[] ntlm2NTLM(byte[] ntlmHash, byte[] nonce, byte[] challenge) {
byte[] b = Arrays.copyOf(challenge, 16);
System.arraycopy(nonce, 0, b, 8, 8);
byte[] sesshash = Arrays.copyOf(md5.digest(b), 8);
return calcResponse(ntlmHash, sesshash);
}
// Password in ASCII and UNICODE
static byte[] getP1(char[] password) {
try {
return new String(password).toUpperCase().getBytes("ISO8859_1");
} catch (UnsupportedEncodingException ex) {
return null;
}
}
static byte[] getP2(char[] password) {
try {
return new String(password).getBytes("UnicodeLittleUnmarked");
} catch (UnsupportedEncodingException ex) {
return null;
}
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2010, 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 com.sun.security.ntlm;
import java.security.GeneralSecurityException;
/**
* An NTLM-related Exception
*/
public final class NTLMException extends GeneralSecurityException {
/**
* If the incoming packet is invalid.
*/
public final static int PACKET_READ_ERROR = 1;
/**
* If the client cannot get a domain value from the server and the
* caller has not provided one.
*/
public final static int NO_DOMAIN_INFO = 2;
/**
* If the domain provided by the client does not match the one received
* from server.
*/
//public final static int DOMAIN_UNMATCH = 3;
/**
* If the client name is not found on server's user database.
*/
public final static int USER_UNKNOWN = 3;
/**
* If authentication fails.
*/
public final static int AUTH_FAILED = 4;
/**
* If an illegal version string is provided.
*/
public final static int BAD_VERSION = 5;
private int errorCode;
/**
* Constructs an NTLMException object.
* @param errorCode the error code, which can be retrieved by
* the {@link #errorCode() } method.
* @param msg the string message, which can be retrived by
* the {@link Exception#getMessage() } method.
*/
public NTLMException(int errorCode, String msg) {
super(msg);
this.errorCode = errorCode;
}
/**
* Returns the error code associated with this NTLMException.
* @return the error code
*/
public int errorCode() {
return errorCode;
}
}

View File

@ -0,0 +1,205 @@
/*
* Copyright (c) 2010, 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 com.sun.security.ntlm;
import java.util.Arrays;
import java.util.Locale;
/**
* The NTLM server, not multi-thread enabled.<p>
* Example:
* <pre>
* Server server = new Server(null, "REALM") {
* public char[] getPassword(String ntdomain, String username) {
* switch (username) {
* case "dummy": return "t0pSeCr3t".toCharArray();
* case "guest": return "".toCharArray();
* default: return null;
* }
* }
* };
* // Receive client request as type1
* byte[] type2 = server.type2(type1, nonce);
* // Send type2 to client and receive type3
* verify(type3, nonce);
* </pre>
*/
public abstract class Server extends NTLM {
final private String domain;
final private boolean allVersion;
/**
* Creates a Server instance.
* @param version the NTLM version to use, which can be:
* <ul>
* <li>NTLM: Original NTLM v1
* <li>NTLM2: NTLM v1 with Client Challenge
* <li>NTLMv2: NTLM v2
* </ul>
* If null, all versions will be supported. Please note that unless NTLM2
* is selected, authentication succeeds if one of LM (or LMv2) or
* NTLM (or NTLMv2) is verified.
* @param domain the domain, must not be null
* @throws NullPointerException if {@code domain} is null.
*/
public Server(String version, String domain) throws NTLMException {
super(version);
if (domain == null) {
throw new NullPointerException("domain cannot be null");
}
this.allVersion = (version == null);
this.domain = domain;
debug("NTLM Server: (t,version) = (%s,%s)\n", domain, version);
}
/**
* Generates the Type 2 message
* @param type1 the Type1 message received, must not be null
* @param nonce the random 8-byte array to be used in message generation,
* must not be null
* @return the message generated
* @throws NullPointerException if type1 or nonce is null
* @throws NTLMException if the incoming message is invalid
*/
public byte[] type2(byte[] type1, byte[] nonce) {
if (nonce == null) {
throw new NullPointerException("nonce cannot be null");
}
debug("NTLM Server: Type 1 received\n");
if (type1 != null) debug(type1);
Writer p = new Writer(2, 32);
int flags = 0x80205;
p.writeSecurityBuffer(12, domain, true);
p.writeInt(20, flags);
p.writeBytes(24, nonce);
debug("NTLM Server: Type 2 created\n");
debug(p.getBytes());
return p.getBytes();
}
/**
* Verifies the Type3 message received from client and returns
* various negotiated information.
* @param type3 the incoming Type3 message from client, must not be null
* @param nonce the same nonce provided in {@link #type2}, must not be null
* @return username and hostname of the client in a byte array
* @throws NullPointerException if {@code type3} or {@code nonce} is null
* @throws NTLMException if the incoming message is invalid
*/
public String[] verify(byte[] type3, byte[] nonce)
throws NTLMException {
if (type3 == null || nonce == null) {
throw new NullPointerException("type1 or nonce cannot be null");
}
debug("NTLM Server: Type 3 received\n");
if (type3 != null) debug(type3);
Reader r = new Reader(type3);
String username = r.readSecurityBuffer(36, true);
String hostname = r.readSecurityBuffer(44, true);
String incomingDomain = r.readSecurityBuffer(28, true);
/*if (incomingDomain != null && !incomingDomain.equals(domain)) {
throw new NTLMException(NTLMException.DOMAIN_UNMATCH,
"Wrong domain: " + incomingDomain +
" vs " + domain); // Needed?
}*/
boolean verified = false;
char[] password = getPassword(domain, username);
if (password == null) {
throw new NTLMException(NTLMException.USER_UNKNOWN,
"Unknown user");
}
byte[] incomingLM = r.readSecurityBuffer(12);
byte[] incomingNTLM = r.readSecurityBuffer(20);
if (!verified && (allVersion || v == Version.NTLM)) {
if (incomingLM.length > 0) {
byte[] pw1 = getP1(password);
byte[] lmhash = calcLMHash(pw1);
byte[] lmresponse = calcResponse (lmhash, nonce);
if (Arrays.equals(lmresponse, incomingLM)) {
verified = true;
}
}
if (incomingNTLM.length > 0) {
byte[] pw2 = getP2(password);
byte[] nthash = calcNTHash(pw2);
byte[] ntresponse = calcResponse (nthash, nonce);
if (Arrays.equals(ntresponse, incomingNTLM)) {
verified = true;
}
}
debug("NTLM Server: verify using NTLM: " + verified + "\n");
}
if (!verified && (allVersion || v == Version.NTLM2)) {
byte[] pw2 = getP2(password);
byte[] nthash = calcNTHash(pw2);
byte[] clientNonce = Arrays.copyOf(incomingLM, 8);
byte[] ntlmresponse = ntlm2NTLM(nthash, clientNonce, nonce);
if (Arrays.equals(incomingNTLM, ntlmresponse)) {
verified = true;
}
debug("NTLM Server: verify using NTLM2: " + verified + "\n");
}
if (!verified && (allVersion || v == Version.NTLMv2)) {
byte[] pw2 = getP2(password);
byte[] nthash = calcNTHash(pw2);
if (incomingLM.length > 0) {
byte[] clientNonce = Arrays.copyOfRange(
incomingLM, 16, incomingLM.length);
byte[] lmresponse = calcV2(nthash,
username.toUpperCase(Locale.US)+incomingDomain,
clientNonce, nonce);
if (Arrays.equals(lmresponse, incomingLM)) {
verified = true;
}
}
if (incomingNTLM.length > 0) {
byte[] clientBlob = Arrays.copyOfRange(
incomingNTLM, 16, incomingNTLM.length);
byte[] ntlmresponse = calcV2(nthash,
username.toUpperCase(Locale.US)+incomingDomain,
clientBlob, nonce);
if (Arrays.equals(ntlmresponse, incomingNTLM)) {
verified = true;
}
}
debug("NTLM Server: verify using NTLMv2: " + verified + "\n");
}
if (!verified) {
throw new NTLMException(NTLMException.AUTH_FAILED,
"None of LM and NTLM verified");
}
return new String[] {username, hostname};
}
/**
* Retrieves the password for a given user. This method should be
* overridden in a concrete class.
* @param domain can be null
* @param username must not be null
* @return the password for the user, or null if unknown
*/
public abstract char[] getPassword(String domain, String username);
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2010, 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 com.sun.security.ntlm;
enum Version {
NTLM, NTLM2, NTLMv2
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -35,10 +35,12 @@ import java.security.PrivilegedAction;
* - CRAM-MD5
* - DIGEST-MD5
* - GSSAPI/Kerberos v5
* - NTLM
* And server support for
* - CRAM-MD5
* - DIGEST-MD5
* - GSSAPI/Kerberos v5
* - NTLM
*/
public final class Provider extends java.security.Provider {
@ -47,8 +49,8 @@ public final class Provider extends java.security.Provider {
private static final String info = "Sun SASL provider" +
"(implements client mechanisms for: " +
"DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5;" +
" server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5)";
"DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5, NTLM;" +
" server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5, NTLM)";
public Provider() {
super("SunSASL", 1.7d, info);
@ -58,6 +60,8 @@ public final class Provider extends java.security.Provider {
// Client mechanisms
put("SaslClientFactory.DIGEST-MD5",
"com.sun.security.sasl.digest.FactoryImpl");
put("SaslClientFactory.NTLM",
"com.sun.security.sasl.ntlm.FactoryImpl");
put("SaslClientFactory.GSSAPI",
"com.sun.security.sasl.gsskerb.FactoryImpl");
@ -75,6 +79,8 @@ public final class Provider extends java.security.Provider {
"com.sun.security.sasl.gsskerb.FactoryImpl");
put("SaslServerFactory.DIGEST-MD5",
"com.sun.security.sasl.digest.FactoryImpl");
put("SaslServerFactory.NTLM",
"com.sun.security.sasl.ntlm.FactoryImpl");
return null;
}
});

View File

@ -0,0 +1,119 @@
/*
* Copyright (c) 2010, 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 com.sun.security.sasl.ntlm;
import java.util.Map;
import javax.security.sasl.*;
import javax.security.auth.callback.CallbackHandler;
import com.sun.security.sasl.util.PolicyUtils;
/**
* Client and server factory for NTLM SASL client/server mechanisms.
* See NTLMClient and NTLMServer for input requirements.
*
* @since 1.7
*/
public final class FactoryImpl implements SaslClientFactory,
SaslServerFactory{
private static final String myMechs[] = { "NTLM" };
private static final int mechPolicies[] = {
PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS
};
/**
* Empty constructor.
*/
public FactoryImpl() {
}
/**
* Returns a new instance of the NTLM SASL client mechanism.
* Argument checks are performed in SaslClient's constructor.
* @returns a new SaslClient ; otherwise null if unsuccessful.
* @throws SaslException If there is an error creating the NTLM
* SASL client.
*/
public SaslClient createSaslClient(String[] mechs,
String authorizationId, String protocol, String serverName,
Map<String,?> props, CallbackHandler cbh)
throws SaslException {
for (int i=0; i<mechs.length; i++) {
if (mechs[i].equals("NTLM") &&
PolicyUtils.checkPolicy(mechPolicies[0], props)) {
return new NTLMClient(mechs[i], authorizationId,
protocol, serverName, props, cbh);
}
}
return null;
}
/**
* Returns a new instance of the NTLM SASL server mechanism.
* Argument checks are performed in SaslServer's constructor.
* @returns a new SaslServer ; otherwise null if unsuccessful.
* @throws SaslException If there is an error creating the NTLM
* SASL server.
*/
public SaslServer createSaslServer(String mech,
String protocol, String serverName, Map<String,?> props, CallbackHandler cbh)
throws SaslException {
if (mech.equals("NTLM") &&
PolicyUtils.checkPolicy(mechPolicies[0], props)) {
if (props != null) {
String qop = (String)props.get(Sasl.QOP);
if (qop != null && !qop.equals("auth")) {
throw new SaslException("NTLM only support auth");
}
}
if (cbh == null) {
throw new SaslException(
"Callback handler with support for AuthorizeCallback, "+
"RealmCallback, NameCallback, and PasswordCallback " +
"required");
}
return new NTLMServer(mech, protocol, serverName, props, cbh);
}
return null;
}
/**
* Returns the authentication mechanisms that this factory can produce.
*
* @returns String[] {"NTLM"} if policies in env match those of this
* factory.
*/
public String[] getMechanismNames(Map<String,?> env) {
return PolicyUtils.filterMechs(myMechs, mechPolicies, env);
}
}

View File

@ -0,0 +1,231 @@
/*
* Copyright (c) 2010, 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 com.sun.security.sasl.ntlm;
import com.sun.security.ntlm.Client;
import com.sun.security.ntlm.NTLMException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Random;
import javax.security.auth.callback.Callback;
import javax.security.sasl.*;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
/**
* Required callbacks:
* - RealmCallback
* handle can provide domain info for authentication, optional
* - NameCallback
* handler must enter username to use for authentication
* - PasswordCallback
* handler must enter password for username to use for authentication
*
* Environment properties that affect behavior of implementation:
*
* javax.security.sasl.qop
* String, quality of protection; only "auth" is accepted, default "auth"
*
* com.sun.security.sasl.ntlm.version
* String, name a specific version to use; can be:
* LM/NTLM: Original NTLM v1
* LM: Original NTLM v1, LM only
* NTLM: Original NTLM v1, NTLM only
* NTLM2: NTLM v1 with Client Challenge
* LMv2/NTLMv2: NTLM v2
* LMv2: NTLM v2, LM only
* NTLMv2: NTLM v2, NTLM only
* If not specified, use system property "ntlm.version". If
* still not specified, use default value "LMv2/NTLMv2".
*
* com.sun.security.sasl.ntlm.random
* java.util.Random, the nonce source to be used in NTLM v2 or NTLM v1 with
* Client Challenge. Default null, an internal java.util.Random object
* will be used
*
* Negotiated Properties:
*
* javax.security.sasl.qop
* Always "auth"
*
* com.sun.security.sasl.html.domain
* The domain for the user, provided by the server
*
* @see <a href="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</a>
* - Simple Authentication and Security Layer (SASL)
*
*/
final class NTLMClient implements SaslClient {
private static final String NTLM_VERSION =
"com.sun.security.sasl.ntlm.version";
private static final String NTLM_RANDOM =
"com.sun.security.sasl.ntlm.random";
private final static String NTLM_DOMAIN =
"com.sun.security.sasl.ntlm.domain";
private final static String NTLM_HOSTNAME =
"com.sun.security.sasl.ntlm.hostname";
private final Client client;
private final String mech;
private final Random random;
private int step = 0; // 0-start,1-nego,2-auth,3-done
/**
* @param mech non-null
* @param authorizationId can be null or empty and ignored
* @param protocol non-null for Sasl, useless for NTLM
* @param serverName non-null for Sasl, but can be null for NTLM
* @param props can be null
* @param cbh can be null for Sasl, but will throw NPE for NTLM
* @throws SaslException
*/
NTLMClient(String mech, String authzid, String protocol, String serverName,
Map props, CallbackHandler cbh) throws SaslException {
this.mech = mech;
String version = null;
Random rtmp = null;
String hostname = null;
if (props != null) {
String qop = (String)props.get(Sasl.QOP);
if (qop != null && !qop.equals("auth")) {
throw new SaslException("NTLM only support auth");
}
version = (String)props.get(NTLM_VERSION);
rtmp = (Random)props.get(NTLM_RANDOM);
hostname = (String)props.get(NTLM_HOSTNAME);
}
this.random = rtmp != null ? rtmp : new Random();
if (version == null) {
version = System.getProperty("ntlm.version");
}
RealmCallback dcb = (serverName != null && !serverName.isEmpty())?
new RealmCallback("Realm: ", serverName) :
new RealmCallback("Realm: ");
NameCallback ncb = (authzid != null && !authzid.isEmpty()) ?
new NameCallback("User name: ", authzid) :
new NameCallback("User name: ");
PasswordCallback pcb =
new PasswordCallback("Password: ", false);
try {
cbh.handle(new Callback[] {dcb, ncb, pcb});
} catch (UnsupportedCallbackException e) {
throw new SaslException("NTLM: Cannot perform callback to " +
"acquire realm, username or password", e);
} catch (IOException e) {
throw new SaslException(
"NTLM: Error acquiring realm, username or password", e);
}
if (hostname == null) {
try {
hostname = InetAddress.getLocalHost().getCanonicalHostName();
} catch (UnknownHostException e) {
hostname = "localhost";
}
}
try {
client = new Client(version, hostname,
ncb.getName(),
dcb.getText(),
pcb.getPassword());
} catch (NTLMException ne) {
throw new SaslException(
"NTLM: Invalid version string: " + version, ne);
}
}
@Override
public String getMechanismName() {
return mech;
}
@Override
public boolean isComplete() {
return step >= 2;
}
@Override
public byte[] unwrap(byte[] incoming, int offset, int len)
throws SaslException {
throw new UnsupportedOperationException("Not supported.");
}
@Override
public byte[] wrap(byte[] outgoing, int offset, int len)
throws SaslException {
throw new UnsupportedOperationException("Not supported.");
}
@Override
public Object getNegotiatedProperty(String propName) {
if (propName.equals(Sasl.QOP)) {
return "auth";
} else if (propName.equals(NTLM_DOMAIN)) {
return client.getDomain();
} else {
return null;
}
}
@Override
public void dispose() throws SaslException {
client.dispose();
}
@Override
public boolean hasInitialResponse() {
return true;
}
@Override
public byte[] evaluateChallenge(byte[] challenge) throws SaslException {
step++;
if (step == 1) {
return client.type1();
} else {
try {
byte[] nonce = new byte[8];
random.nextBytes(nonce);
return client.type3(challenge, nonce);
} catch (NTLMException ex) {
throw new SaslException("Type3 creation failed", ex);
}
}
}
}

View File

@ -0,0 +1,226 @@
/*
* Copyright (c) 2010, 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 com.sun.security.sasl.ntlm;
import com.sun.security.ntlm.NTLMException;
import com.sun.security.ntlm.Server;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Map;
import java.util.Random;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.sasl.*;
/**
* Required callbacks:
* - RealmCallback
* used as key by handler to fetch password, optional
* - NameCallback
* used as key by handler to fetch password
* - PasswordCallback
* handler must enter password for username/realm supplied
*
* Environment properties that affect the implementation:
*
* javax.security.sasl.qop
* String, quality of protection; only "auth" is accepted, default "auth"
*
* com.sun.security.sasl.ntlm.version
* String, name a specific version to accept:
* LM/NTLM: Original NTLM v1
* LM: Original NTLM v1, LM only
* NTLM: Original NTLM v1, NTLM only
* NTLM2: NTLM v1 with Client Challenge
* LMv2/NTLMv2: NTLM v2
* LMv2: NTLM v2, LM only
* NTLMv2: NTLM v2, NTLM only
* If not specified, use system property "ntlm.version". If also
* not specfied, all versions are accepted.
*
* com.sun.security.sasl.ntlm.domain
* String, the domain of the server, default is server name (fqdn parameter)
*
* com.sun.security.sasl.ntlm.random
* java.util.Random, the nonce source. Default null, an internal
* java.util.Random object will be used
*
* Negotiated Properties:
*
* javax.security.sasl.qop
* Always "auth"
*
* com.sun.security.sasl.ntlm.hostname
* The hostname for the user, provided by the client
*
*/
final class NTLMServer implements SaslServer {
private final static String NTLM_VERSION =
"com.sun.security.sasl.ntlm.version";
private final static String NTLM_DOMAIN =
"com.sun.security.sasl.ntlm.domain";
private final static String NTLM_HOSTNAME =
"com.sun.security.sasl.ntlm.hostname";
private static final String NTLM_RANDOM =
"com.sun.security.sasl.ntlm.random";
private final Random random;
private final Server server;
private byte[] nonce;
private int step = 0;
private String authzId;
private final String mech;
private String hostname;
/**
* @param mech not null
* @param protocol not null for Sasl, ignored in NTLM
* @param serverName not null for Sasl, can be null in NTLM. If non-null,
* might be used as domain if not provided in props
* @param props can be null
* @param cbh can be null for Sasl, but will throw NPE in auth for NTLM
* @throws SaslException
*/
NTLMServer(String mech, String protocol, String serverName,
Map props, final CallbackHandler cbh) throws SaslException {
this.mech = mech;
String version = null;
String domain = null;
Random rtmp = null;
if (props != null) {
domain = (String) props.get(NTLM_DOMAIN);
version = (String)props.get(NTLM_VERSION);
rtmp = (Random)props.get(NTLM_RANDOM);
}
random = rtmp != null ? rtmp : new Random();
if (version == null) {
version = System.getProperty("ntlm.version");
}
if (domain == null) {
domain = serverName;
}
if (domain == null) {
throw new NullPointerException("Domain must be provided as"
+ " the serverName argument or in props");
}
try {
server = new Server(version, domain) {
public char[] getPassword(String ntdomain, String username) {
try {
RealmCallback rcb = new RealmCallback(
"Domain: ", ntdomain);
NameCallback ncb = new NameCallback(
"Name: ", username);
PasswordCallback pcb = new PasswordCallback(
"Password: ", false);
cbh.handle(new Callback[] { rcb, ncb, pcb });
char[] passwd = pcb.getPassword();
pcb.clearPassword();
return passwd;
} catch (IOException ioe) {
return null;
} catch (UnsupportedCallbackException uce) {
return null;
}
}
};
} catch (NTLMException ne) {
throw new SaslException(
"NTLM: Invalid version string: " + version, ne);
}
nonce = new byte[8];
}
@Override
public String getMechanismName() {
return mech;
}
@Override
public byte[] evaluateResponse(byte[] response) throws SaslException {
try {
step++;
if (step == 1) {
random.nextBytes(nonce);
return server.type2(response, nonce);
} else {
String[] out = server.verify(response, nonce);
authzId = out[0];
hostname = out[1];
return null;
}
} catch (GeneralSecurityException ex) {
throw new SaslException("", ex);
}
}
@Override
public boolean isComplete() {
return step >= 2;
}
@Override
public String getAuthorizationID() {
return authzId;
}
@Override
public byte[] unwrap(byte[] incoming, int offset, int len)
throws SaslException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public byte[] wrap(byte[] outgoing, int offset, int len)
throws SaslException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Object getNegotiatedProperty(String propName) {
if (propName.equals(Sasl.QOP)) {
return "auth";
} else if (propName.equals(NTLM_HOSTNAME)) {
return hostname;
} else {
return null;
}
}
@Override
public void dispose() throws SaslException {
return;
}
}

View File

@ -34,8 +34,8 @@ package java.lang;
public interface AutoCloseable {
/**
* Close this resource, relinquishing any underlying resources.
* This method is invoked automatically by the automatic resource
* management block construct.
* This method is invoked automatically by the {@code
* try}-with-resources statement.
*
* <p>Classes implementing this method are strongly encouraged to
* be declared to throw more specific exceptions (or no exception

View File

@ -823,7 +823,7 @@ public abstract class ClassLoader {
* </tt></blockquote>
*
* @param name
* The expected <a href="#name">binary name</a. of the class, or
* The expected <a href="#name">binary name</a>. of the class, or
* <tt>null</tt> if not known
*
* @param b

View File

@ -189,7 +189,9 @@ public class Object {
* specific cloning operation. First, if the class of this object does
* not implement the interface {@code Cloneable}, then a
* {@code CloneNotSupportedException} is thrown. Note that all arrays
* are considered to implement the interface {@code Cloneable}.
* are considered to implement the interface {@code Cloneable} and that
* the return type of the {@code clone} method of an array type {@code T[]}
* is {@code T[]} where T is any reference or primitive type.
* Otherwise, this method creates a new instance of the class of this
* object and initializes all its fields with exactly the contents of
* the corresponding fields of this object, as if by assignment; the

View File

@ -498,8 +498,8 @@ public class Throwable implements Serializable {
* }
* </pre>
* As of release 7, the platform supports the notion of
* <i>suppressed exceptions</i> (in conjunction with automatic
* resource management blocks). Any exceptions that were
* <i>suppressed exceptions</i> (in conjunction with the {@code
* try}-with-resources statement). Any exceptions that were
* suppressed in order to deliver an exception are printed out
* beneath the stack trace. The format of this information
* depends on the implementation, but the following example may be
@ -805,7 +805,7 @@ public class Throwable implements Serializable {
/**
* Adds the specified exception to the list of exceptions that
* were suppressed, typically by the automatic resource management
* were suppressed, typically by the {@code try}-with-resources
* statement, in order to deliver this exception.
*
* <p>Note that when one exception {@linkplain
@ -839,7 +839,7 @@ public class Throwable implements Serializable {
/**
* Returns an array containing all of the exceptions that were
* suppressed, typically by the automatic resource management
* suppressed, typically by the {@code try}-with-resources
* statement, in order to deliver this exception.
*
* @return an array containing all of the exceptions that were

View File

@ -166,8 +166,7 @@ public final
/**
* Returns the name of this constructor, as a string. This is
* always the same as the simple name of the constructor's declaring
* class.
* the binary name of the constructor's declaring class.
*/
public String getName() {
return getDeclaringClass().getName();

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.IOException;
import java.io.FileDescriptor;
import sun.net.sdp.SdpSupport;
/**
* SocketImpl that supports the SDP protocol
*/
class SdpSocketImpl extends PlainSocketImpl {
SdpSocketImpl() { }
@Override
protected void create(boolean stream) throws IOException {
if (!stream)
throw new UnsupportedOperationException("Must be a stream socket");
fd = SdpSupport.createSocket();
if (socket != null)
socket.setCreated();
if (serverSocket != null)
serverSocket.setCreated();
}
}

View File

@ -68,6 +68,15 @@ class ServerSocket implements java.io.Closeable {
*/
private boolean oldImpl = false;
/**
* Package-private constructor to create a ServerSocket associated with
* the given SocketImpl.
*/
ServerSocket(SocketImpl impl) {
this.impl = impl;
impl.setServerSocket(this);
}
/**
* Creates an unbound server socket.
*

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2010, 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.nio.file;
import java.util.ConcurrentModificationException;
import java.util.Objects;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.InvalidObjectException;
/**
* Runtime exception thrown if an I/O error is encountered when iterating over
* the entries in a directory. The I/O error is retrieved as an {@link
* IOException} using the {@link #getCause() getCause()} method.
*
* @since 1.7
* @see DirectoryStream
*/
public final class DirectoryIteratorException
extends ConcurrentModificationException
{
private static final long serialVersionUID = -6012699886086212874L;
/**
* Constructs an instance of this class.
*
* @param cause
* the {@code IOException} that caused the directory iteration
* to fail
*
* @throws NullPointerException
* if the cause is {@code null}
*/
public DirectoryIteratorException(IOException cause) {
super(Objects.nonNull(cause));
}
/**
* Returns the cause of this exception.
*
* @return the cause
*/
@Override
public IOException getCause() {
return (IOException)super.getCause();
}
/**
* Called to read the object from a stream.
*
* @throws InvalidObjectException
* if the object is invalid or has a cause that is not
* an {@code IOException}
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
s.defaultReadObject();
Throwable cause = super.getCause();
if (!(cause instanceof IOException))
throw new InvalidObjectException("Cause must be an IOException");
}
}

View File

@ -31,60 +31,84 @@ import java.io.IOException;
/**
* An object to iterate over the entries in a directory. A directory stream
* allows for convenient use of the for-each construct:
* allows for the convenient use of the for-each construct to iterate over a
* directory.
*
* <p> <b> While {@code DirectoryStream} extends {@code Iterable}, it is not a
* general-purpose {@code Iterable} as it supports only a single {@code
* Iterator}; invoking the {@link #iterator iterator} method to obtain a second
* or subsequent iterator throws {@code IllegalStateException}. </b>
*
* <p> An important property of the directory stream's {@code Iterator} is that
* its {@link Iterator#hasNext() hasNext} method is guaranteed to read-ahead by
* at least one element. If {@code hasNext} method returns {@code true}, and is
* followed by a call to the {@code next} method, it is guaranteed that the
* {@code next} method will not throw an exception due to an I/O error, or
* because the stream has been {@link #close closed}. The {@code Iterator} does
* not support the {@link Iterator#remove remove} operation.
*
* <p> A {@code DirectoryStream} is opened upon creation and is closed by
* invoking the {@code close} method. Closing a directory stream releases any
* resources associated with the stream. Failure to close the stream may result
* in a resource leak. The try-with-resources statement provides a useful
* construct to ensure that the stream is closed:
* <pre>
* Path dir = ...
* DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream();
* try {
* try (DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream()) {
* for (Path entry: stream) {
* ..
* ...
* }
* } finally {
* stream.close();
* }
* </pre>
*
* <p><b> A {@code DirectoryStream} is not a general-purpose {@code Iterable}.
* While this interface extends {@code Iterable}, the {@code iterator} method
* may only be invoked once to obtain the iterator; a second, or subsequent,
* call to the {@code iterator} method throws {@code IllegalStateException}. </b>
*
* <p> A {@code DirectoryStream} is opened upon creation and is closed by
* invoking the {@link #close close} method. Closing the directory stream
* releases any resources associated with the stream. Once a directory stream
* is closed, all further method invocations on the iterator throw {@link
* java.util.ConcurrentModificationException} with cause {@link
* ClosedDirectoryStreamException}.
* <p> Once a directory stream is closed, then further access to the directory,
* using the {@code Iterator}, behaves as if the end of stream has been reached.
* Due to read-ahead, the {@code Iterator} may return one or more elements
* after the directory stream has been closed. Once these buffered elements
* have been read, then subsequent calls to the {@code hasNext} method returns
* {@code false}, and subsequent calls to the {@code next} method will throw
* {@code NoSuchElementException}.
*
* <p> A directory stream is not required to be <i>asynchronously closeable</i>.
* If a thread is blocked on the directory stream's iterator reading from the
* directory, and another thread invokes the {@code close} method, then the
* second thread may block until the read operation is complete.
*
* <p> The {@link Iterator#hasNext() hasNext} and {@link Iterator#next() next}
* methods can encounter an I/O error when iterating over the directory in which
* case {@code ConcurrentModificationException} is thrown with cause
* {@link java.io.IOException}. The {@code hasNext} method is guaranteed to
* read-ahead by at least one element. This means that if the {@code hasNext}
* method returns {@code true} and is followed by a call to the {@code next}
* method then it is guaranteed not to fail with a {@code
* ConcurrentModificationException}.
* <p> If an I/O error is encountered when accessing the directory then it
* causes the {@code Iterator}'s {@code hasNext} or {@code next} methods to
* throw {@link DirectoryIteratorException} with the {@link IOException} as the
* cause. As stated above, the {@code hasNext} method is guaranteed to
* read-ahead by at least one element. This means that if {@code hasNext} method
* returns {@code true}, and is followed by a call to the {@code next} method,
* then it is guaranteed that the {@code next} method will not fail with a
* {@code DirectoryIteratorException}.
*
* <p> The elements returned by the iterator are in no specific order. Some file
* systems maintain special links to the directory itself and the directory's
* parent directory. Entries representing these links are not returned by the
* iterator.
*
* <p> The iterator's {@link Iterator#remove() remove} method removes the
* directory entry for the last element returned by the iterator, as if by
* invoking the {@link Path#delete delete} method. If an I/O error or
* security exception occurs then {@code ConcurrentModificationException} is
* thrown with the cause.
*
* <p> The iterator is <i>weakly consistent</i>. It is thread safe but does not
* freeze the directory while iterating, so it may (or may not) reflect updates
* to the directory that occur after the {@code DirectoryStream} is created.
*
* <p> <b>Usage Examples:</b>
* Suppose we want a list of the source files in a directory. This example uses
* both the for-each and try-with-resources constructs.
* <pre>
* List&lt;Path&gt; listSourceFiles(Path dir) throws IOException {
* List&lt;Path&gt; result = new ArrayList&lt;Path&gt;();
* try (DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream("*.{c,h,cpp,hpp,java}")) {
* for (Path entry: stream) {
* result.add(entry);
* }
* } catch (DirectoryIteratorException ex) {
* // I/O error encounted during the iteration, the cause is an IOException
* throw ex.getCause();
* }
* return result;
* }
* </pre>
* @param <T> The type of element returned by the iterator
*
* @since 1.7

View File

@ -984,11 +984,11 @@ public abstract class Path
* directory.
*
* <p> Where the filter terminates due to an uncaught error or runtime
* exception then it is propogated to the iterator's {@link Iterator#hasNext()
* exception then it is propagated to the {@link Iterator#hasNext()
* hasNext} or {@link Iterator#next() next} method. Where an {@code
* IOException} is thrown, it is propogated as a {@link
* java.util.ConcurrentModificationException} with the {@code
* IOException} as the cause.
* IOException} is thrown, it results in the {@code hasNext} or {@code
* next} method throwing a {@link DirectoryIteratorException} with the
* {@code IOException} as the cause.
*
* <p> When an implementation supports operations on entries in the
* directory that execute in a race-free manner then the returned directory

View File

@ -47,15 +47,6 @@ import java.io.IOException;
* newDirectoryStream} method will be a {@code SecureDirectoryStream} and must
* be cast to that type in order to invoke the methods defined by this interface.
*
* <p> As specified by {@code DirectoryStream}, the iterator's {@link
* java.util.Iterator#remove() remove} method removes the directory entry for
* the last element returned by the iterator. In the case of a {@code
* SecureDirectoryStream} the {@code remove} method behaves as if by invoking
* the {@link #deleteFile deleteFile} or {@link #deleteDirectory deleteDirectory}
* methods defined by this interface. The {@code remove} may require to examine
* the file to determine if the file is a directory, and consequently, it may
* not be atomic with respect to other file system operations.
*
* <p> In the case of the default {@link java.nio.file.spi.FileSystemProvider
* provider}, and a security manager is set, then the permission checks are
* performed using the path obtained by resolving the given relative path

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, 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
@ -2436,4 +2436,64 @@ public interface CallableStatement extends PreparedStatement {
*/
void setNClob(String parameterName, Reader reader)
throws SQLException;
//------------------------- JDBC 4.1 -----------------------------------
/**
*<p>Returns an object representing the value of OUT parameter
* {@code parameterIndex} and will convert from the
* SQL type of the parameter to the requested Java data type, if the
* conversion is supported. If the conversion is not
* supported or null is specified for the type, a
* <code>SQLException</code> is thrown.
*<p>
* At a minimum, an implementation must support the conversions defined in
* Appendix B, Table B-3 and conversion of appropriate user defined SQL
* types to a Java type which implements {@code SQLData}, or {@code Struct}.
* Additional conversions may be supported and are vendor defined.
*
* @param parameterIndex the first parameter is 1, the second is 2, and so on
* @param type Class representing the Java data type to convert the
* designated parameter to.
* @return an instance of {@code type} holding the OUT parameter value
* @throws SQLException if conversion is not supported, type is null or
* another error occurs. The getCause() method of the
* exception may provide a more detailed exception, for example, if
* a conversion error occurs
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since 1.7
*/
public <T> T getObject(int parameterIndex, Class<T> type) throws SQLException;
/**
*<p>Returns an object representing the value of OUT parameter
* {@code parameterName} and will convert from the
* SQL type of the parameter to the requested Java data type, if the
* conversion is supported. If the conversion is not
* supported or null is specified for the type, a
* <code>SQLException</code> is thrown.
*<p>
* At a minimum, an implementation must support the conversions defined in
* Appendix B, Table B-3 and conversion of appropriate user defined SQL
* types to a Java type which implements {@code SQLData}, or {@code Struct}.
* Additional conversions may be supported and are vendor defined.
*
* @param parameterName the name of the parameter
* @param type Class representing the Java data type to convert
* the designated parameter to.
* @return an instance of {@code type} holding the OUT parameter
* value
* @throws SQLException if conversion is not supported, type is null or
* another error occurs. The getCause() method of the
* exception may provide a more detailed exception, for example, if
* a conversion error occurs
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since 1.7
*/
public <T> T getObject(String parameterName, Class<T> type) throws SQLException;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, 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
@ -26,6 +26,7 @@
package java.sql;
import java.util.Properties;
import java.util.concurrent.Executor;
/**
* <P>A connection (session) with a specific
@ -38,7 +39,7 @@ import java.util.Properties;
* information is obtained with the <code>getMetaData</code> method.
*
* <P><B>Note:</B> When configuring a <code>Connection</code>, JDBC applications
* should use the appropritate <code>Connection</code> method such as
* should use the appropriate <code>Connection</code> method such as
* <code>setAutoCommit</code> or <code>setTransactionIsolation</code>.
* Applications should not invoke SQL commands directly to change the connection's
* configuration when there is a JDBC method available. By default a <code>Connection</code> object is in
@ -80,7 +81,7 @@ import java.util.Properties;
* @see ResultSet
* @see DatabaseMetaData
*/
public interface Connection extends Wrapper {
public interface Connection extends Wrapper, AutoCloseable {
/**
* Creates a <code>Statement</code> object for sending
@ -347,6 +348,13 @@ public interface Connection extends Wrapper {
* <P>
* If the driver does not support catalogs, it will
* silently ignore this request.
* <p>
* Calling {@code setCatalog} has no effect on previously created or prepared
* {@code Statement} objects. It is implementation defined whether a DBMS
* prepare operation takes place immediately when the {@code Connection}
* method {@code prepareStatement} or {@code prepareCall} is invoked.
* For maximum portability, {@code setCatalog} should be called before a
* {@code Statement} is created or prepared.
*
* @param catalog the name of a catalog (subspace in this
* <code>Connection</code> object's database) in which to work
@ -598,7 +606,17 @@ public interface Connection extends Wrapper {
* <code>Connection</code> object.
* Unless the application has added an entry, the type map returned
* will be empty.
*
* <p>
* You must invoke <code>setTypeMap</code> after making changes to the
* <code>Map</code> object returned from
* <code>getTypeMap</code> as a JDBC driver may create an internal
* copy of the <code>Map</code> object passed to <code>setTypeMap</code>:
* <p>
* <pre>
* Map&lt;String,Class&lt;?&gt;&gt; myMap = con.getTypeMap();
* myMap.put("mySchemaName.ATHLETES", Athletes.class);
* con.setTypeMap(myMap);
* </pre>
* @return the <code>java.util.Map</code> object associated
* with this <code>Connection</code> object
* @exception SQLException if a database access error occurs
@ -614,7 +632,16 @@ public interface Connection extends Wrapper {
* Installs the given <code>TypeMap</code> object as the type map for
* this <code>Connection</code> object. The type map will be used for the
* custom mapping of SQL structured types and distinct types.
*
*<p>
* You must set the the values for the <code>TypeMap</code> prior to
* callng <code>setMap</code> as a JDBC driver may create an internal copy
* of the <code>TypeMap</code>:
* <p>
* <pre>
* Map myMap&lt;String,Class&lt;?&gt;&gt; = new HashMap&lt;String,Class&lt;?&gt;&gt;();
* myMap.put("mySchemaName.ATHLETES", Athletes.class);
* con.setTypeMap(myMap);
* </pre>
* @param map the <code>java.util.Map</code> object to install
* as the replacement for this <code>Connection</code>
* object's default type map
@ -1274,4 +1301,186 @@ SQLException;
*/
Struct createStruct(String typeName, Object[] attributes)
throws SQLException;
//--------------------------JDBC 4.1 -----------------------------
/**
* Sets the given schema name to access.
* <P>
* If the driver does not support schemas, it will
* silently ignore this request.
* <p>
* Calling {@code setSchema} has no effect on previously created or prepared
* {@code Statement} objects. It is implementation defined whether a DBMS
* prepare operation takes place immediately when the {@code Connection}
* method {@code prepareStatement} or {@code prepareCall} is invoked.
* For maximum portability, {@code setSchema} should be called before a
* {@code Statement} is created or prepared.
*
* @param schema the name of a schema in which to work
* @exception SQLException if a database access error occurs
* or this method is called on a closed connection
* @see #getSchema
* @since 1.7
*/
void setSchema(String schema) throws SQLException;
/**
* Retrieves this <code>Connection</code> object's current schema name.
*
* @return the current schema name or <code>null</code> if there is none
* @exception SQLException if a database access error occurs
* or this method is called on a closed connection
* @see #setSchema
* @since 1.7
*/
String getSchema() throws SQLException;
/**
* Terminates an open connection. Calling <code>abort</code> results in:
* <ul>
* <li>The connection marked as closed
* <li>Closes any physical connection to the database
* <li>Releases resources used by the connection
* <li>Insures that any thread that is currently accessing the connection
* will either progress to completion or throw an <code>SQLException</code>.
* </ul>
* <p>
* Calling <code>abort</code> marks the connection closed and releases any
* resources. Calling <code>abort</code> on a closed connection is a
* no-op.
* <p>
* It is possible that the aborting and releasing of the resources that are
* held by the connection can take an extended period of time. When the
* <code>abort</code> method returns, the connection will have been marked as
* closed and the <code>Executor</code> that was passed as a parameter to abort
* may still be executing tasks to release resources.
* <p>
* This method checks to see that there is an <code>SQLPermission</code>
* object before allowing the method to proceed. If a
* <code>SecurityManager</code> exists and its
* <code>checkPermission</code> method denies calling <code>abort</code>,
* this method throws a
* <code>java.lang.SecurityException</code>.
* @param executor The <code>Executor</code> implementation which will
* be used by <code>abort</code>.
* @throws java.sql.SQLException if a database access error occurs or
* the {@code executor} is {@code null},
* @throws java.lang.SecurityException if a security manager exists and its
* <code>checkPermission</code> method denies calling <code>abort</code>
* @see SecurityManager#checkPermission
* @see Executor
* @since 1.7
*/
void abort(Executor executor) throws SQLException;
/**
*
* Sets the maximum period a <code>Connection</code> or
* objects created from the <code>Connection</code>
* will wait for the database to reply to any one request. If any
* request remains unanswered, the waiting method will
* return with a <code>SQLException</code>, and the <code>Connection</code>
* or objects created from the <code>Connection</code> will be marked as
* closed. Any subsequent use of
* the objects, with the exception of the <code>close</code>,
* <code>isClosed</code> or <code>Connection.isValid</code>
* methods, will result in a <code>SQLException</code>.
* <p>
* <b>Note</b>: This method is intended to address a rare but serious
* condition where network partitions can cause threads issuing JDBC calls
* to hang uninterruptedly in socket reads, until the OS TCP-TIMEOUT
* (typically 10 minutes). This method is related to the
* {@link #abort abort() } method which provides an administrator
* thread a means to free any such threads in cases where the
* JDBC connection is accessible to the administrator thread.
* The <code>setNetworkTimeout</code> method will cover cases where
* there is no administrator thread, or it has no access to the
* connection. This method is severe in it's effects, and should be
* given a high enough value so it is never triggered before any more
* normal timeouts, such as transaction timeouts.
* <p>
* JDBC driver implementations may also choose to support the
* {@code setNetworkTimeout} method to impose a limit on database
* response time, in environments where no network is present.
* <p>
* Drivers may internally implement some or all of their API calls with
* multiple internal driver-database transmissions, and it is left to the
* driver implementation to determine whether the limit will be
* applied always to the response to the API call, or to any
* single request made during the API call.
* <p>
*
* This method can be invoked more than once, such as to set a limit for an
* area of JDBC code, and to reset to the default on exit from this area.
* Invocation of this method has no impact on already outstanding
* requests.
* <p>
* The {@code Statement.setQueryTimeout()} timeout value is independent of the
* timeout value specified in {@code setNetworkTimeout}. If the query timeout
* expires before the network timeout then the
* statement execution will be canceled. If the network is still
* active the result will be that both the statement and connection
* are still usable. However if the network timeout expires before
* the query timeout or if the statement timeout fails due to network
* problems, the connection will be marked as closed, any resources held by
* the connection will be released and both the connection and
* statement will be unusable.
*<p>
* When the driver determines that the {@code setNetworkTimeout} timeout
* value has expired, the JDBC driver marks the connection
* closed and releases any resources held by the connection.
* <p>
*
* This method checks to see that there is an <code>SQLPermission</code>
* object before allowing the method to proceed. If a
* <code>SecurityManager</code> exists and its
* <code>checkPermission</code> method denies calling
* <code>setNetworkTimeout</code>, this method throws a
* <code>java.lang.SecurityException</code>.
*
* @param executor The <code>Executor</code> implementation which will
* be used by <code>setNetworkTimeout</code>.
* @param milliseconds The time in milliseconds to wait for the database
* operation
* to complete. If the JDBC driver does not support milliseconds, the
* JDBC driver will round the value up to the nearest second. If the
* timeout period expires before the operation
* completes, a SQLException will be thrown.
* A value of 0 indicates that there is not timeout for database operations.
* @throws java.sql.SQLException if a database access error occurs, this
* method is called on a closed connection,
* the {@code executor} is {@code null},
* or the value specified for <code>seconds</code> is less than 0.
* @throws java.lang.SecurityException if a security manager exists and its
* <code>checkPermission</code> method denies calling
* <code>setNetworkTimeout</code>.
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see SecurityManager#checkPermission
* @see Statement#setQueryTimeout
* @see #getNetworkTimeout
* @see #abort
* @see Executor
* @since 1.7
*/
void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException;
/**
* Retrieves the number of milliseconds the driver will
* wait for a database request to complete.
* If the limit is exceeded, a
* <code>SQLException</code> is thrown.
*
* @return the current timeout limit in milliseconds; zero means there is
* no limit
* @throws SQLException if a database access error occurs or
* this method is called on a closed <code>Connection</code>
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @see #setNetworkTimeout
* @since 1.7
*/
int getNetworkTimeout() throws SQLException;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, 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
@ -1342,10 +1342,10 @@ public interface DatabaseMetaData extends Wrapper {
* defined.
* <LI><B>IS_NULLABLE</B> String => ISO rules are used to determine the nullability for a column.
* <UL>
* <LI> YES --- if the parameter can include NULLs
* <LI> NO --- if the parameter cannot include NULLs
* <LI> YES --- if the column can include NULLs
* <LI> NO --- if the column cannot include NULLs
* <LI> empty string --- if the nullability for the
* parameter is unknown
* column is unknown
* </UL>
* <LI><B>SPECIFIC_NAME</B> String => the name which uniquely identifies this procedure within its schema.
* </OL>
@ -1610,17 +1610,17 @@ public interface DatabaseMetaData extends Wrapper {
* (starting at 1)
* <LI><B>IS_NULLABLE</B> String => ISO rules are used to determine the nullability for a column.
* <UL>
* <LI> YES --- if the parameter can include NULLs
* <LI> NO --- if the parameter cannot include NULLs
* <LI> YES --- if the column can include NULLs
* <LI> NO --- if the column cannot include NULLs
* <LI> empty string --- if the nullability for the
* parameter is unknown
* column is unknown
* </UL>
* <LI><B>SCOPE_CATLOG</B> String => catalog of table that is the scope
* <LI><B>SCOPE_CATALOG</B> String => catalog of table that is the scope
* of a reference attribute (<code>null</code> if DATA_TYPE isn't REF)
* <LI><B>SCOPE_SCHEMA</B> String => schema of table that is the scope
* of a reference attribute (<code>null</code> if the DATA_TYPE isn't REF)
* <LI><B>SCOPE_TABLE</B> String => table name that this the scope
* of a reference attribure (<code>null</code> if the DATA_TYPE isn't REF)
* of a reference attribute (<code>null</code> if the DATA_TYPE isn't REF)
* <LI><B>SOURCE_DATA_TYPE</B> short => source type of a distinct type or user-generated
* Ref type, SQL type from java.sql.Types (<code>null</code> if DATA_TYPE
* isn't DISTINCT or user-generated REF)
@ -1629,11 +1629,16 @@ public interface DatabaseMetaData extends Wrapper {
* <LI> YES --- if the column is auto incremented
* <LI> NO --- if the column is not auto incremented
* <LI> empty string --- if it cannot be determined whether the column is auto incremented
* parameter is unknown
* </UL>
* <LI><B>IS_GENERATEDCOLUMN</B> String => Indicates whether this is a generated column
* <UL>
* <LI> YES --- if this a generated column
* <LI> NO --- if this not a generated column
* <LI> empty string --- if it cannot be determined whether this is a generated column
* </UL>
* </OL>
*
* <p>The COLUMN_SIZE column the specified column size for the given column.
* <p>The COLUMN_SIZE column specifies the column size for the given column.
* For numeric data, this is the maximum precision. For character data, this is the length in characters.
* For datetime datatypes, this is the length in characters of the String representation (assuming the
* maximum allowed precision of the fractional seconds component). For binary data, this is the length in bytes. For the ROWID datatype,
@ -3186,7 +3191,7 @@ public interface DatabaseMetaData extends Wrapper {
* Retrieves whether this database supports statement pooling.
*
* @return <code>true</code> if so; <code>false</code> otherwise
* @throws SQLExcpetion if a database access error occurs
* @throws SQLException if a database access error occurs
* @since 1.4
*/
boolean supportsStatementPooling() throws SQLException;
@ -3568,4 +3573,83 @@ public interface DatabaseMetaData extends Wrapper {
*/
int functionReturnsTable = 2;
//--------------------------JDBC 4.1 -----------------------------
/**
* Retrieves a description of the pseudo or hidden columns available
* in a given table within the specified catalog and schema.
* Pseudo or hidden columns may not always be stored within
* a table and are not visible in a ResultSet unless they are
* specified in the query's outermost SELECT list. Pseudo or hidden
* columns may not necessarily be able to be modified. If there are
* no pseudo or hidden columns, an empty ResultSet is returned.
*
* <P>Only column descriptions matching the catalog, schema, table
* and column name criteria are returned. They are ordered by
* <code>TABLE_CAT</code>,<code>TABLE_SCHEM</code>, <code>TABLE_NAME</code>
* and <code>COLUMN_NAME</code>.
*
* <P>Each column description has the following columns:
* <OL>
* <LI><B>TABLE_CAT</B> String => table catalog (may be <code>null</code>)
* <LI><B>TABLE_SCHEM</B> String => table schema (may be <code>null</code>)
* <LI><B>TABLE_NAME</B> String => table name
* <LI><B>COLUMN_NAME</B> String => column name
* <LI><B>DATA_TYPE</B> int => SQL type from java.sql.Types
* <LI><B>COLUMN_SIZE</B> int => column size.
* <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits. Null is returned for data types where
* DECIMAL_DIGITS is not applicable.
* <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
* <LI><B>COLUMN_USAGE</B> String => The allowed usage for the column. The
* value returned will correspond to the enum name returned by {@link PseudoColumnUsage#name PseudoColumnUsage.name()}
* <LI><B>REMARKS</B> String => comment describing column (may be <code>null</code>)
* <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
* maximum number of bytes in the column
* <LI><B>IS_NULLABLE</B> String => ISO rules are used to determine the nullability for a column.
* <UL>
* <LI> YES --- if the column can include NULLs
* <LI> NO --- if the column cannot include NULLs
* <LI> empty string --- if the nullability for the column is unknown
* </UL>
* </OL>
*
* <p>The COLUMN_SIZE column specifies the column size for the given column.
* For numeric data, this is the maximum precision. For character data, this is the length in characters.
* For datetime datatypes, this is the length in characters of the String representation (assuming the
* maximum allowed precision of the fractional seconds component). For binary data, this is the length in bytes. For the ROWID datatype,
* this is the length in bytes. Null is returned for data types where the
* column size is not applicable.
*
* @param catalog a catalog name; must match the catalog name as it
* is stored in the database; "" retrieves those without a catalog;
* <code>null</code> means that the catalog name should not be used to narrow
* the search
* @param schemaPattern a schema name pattern; must match the schema name
* as it is stored in the database; "" retrieves those without a schema;
* <code>null</code> means that the schema name should not be used to narrow
* the search
* @param tableNamePattern a table name pattern; must match the
* table name as it is stored in the database
* @param columnNamePattern a column name pattern; must match the column
* name as it is stored in the database
* @return <code>ResultSet</code> - each row is a column description
* @exception SQLException if a database access error occurs
* @see PseudoColumnUsage
* @since 1.7
*/
ResultSet getPseudoColumns(String catalog, String schemaPattern,
String tableNamePattern, String columnNamePattern)
throws SQLException;
/**
* Retrieves whether a generated key will always be returned if the column
* name(s) or indexe(s) specified for the auto generated key column(s)
* are valid and the statement succeeds. The key that is returned may or
* may not be based on the column(s) for the auto generated key.
* Consult your JDBC driver documentation for additional details.
* @return <code>true</code> if so; <code>false</code> otherwise
* @exception SQLException if a database access error occurs
* @since 1.7
*/
boolean generatedKeyAlwaysReturned() throws SQLException;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, 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
@ -96,11 +96,12 @@ public class Date extends java.util.Date {
* a <code>Date</code> value.
*
* @param s a <code>String</code> object representing a date in
* in the format "yyyy-mm-dd"
* in the format "yyyy-[m]m-[d]d". The leading zero for <code>mm</code>
* and <code>dd</code> may also be omitted.
* @return a <code>java.sql.Date</code> object representing the
* given date
* @throws IllegalArgumentException if the date given is not in the
* JDBC date escape format (yyyy-mm-dd)
* JDBC date escape format (yyyy-[m]m-[d]d)
*/
public static Date valueOf(String s) {
final int YEAR_LENGTH = 4;
@ -123,8 +124,9 @@ public class Date extends java.util.Date {
String yyyy = s.substring(0, firstDash);
String mm = s.substring(firstDash + 1, secondDash);
String dd = s.substring(secondDash + 1);
if (yyyy.length() == YEAR_LENGTH && mm.length() == MONTH_LENGTH &&
dd.length() == DAY_LENGTH) {
if (yyyy.length() == YEAR_LENGTH &&
(mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
(dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
int year = Integer.parseInt(yyyy);
int month = Integer.parseInt(mm);
int day = Integer.parseInt(dd);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, 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
@ -25,6 +25,8 @@
package java.sql;
import java.util.logging.Logger;
/**
* The interface that every driver class must implement.
* <P>The Java SQL framework allows for multiple database drivers.
@ -150,4 +152,19 @@ public interface Driver {
* otherwise
*/
boolean jdbcCompliant();
//------------------------- JDBC 4.1 -----------------------------------
/**
* Return the parent Logger of all the Loggers used by this driver. This
* should be the Logger farthest from the root Logger that is
* still an ancestor of all of the Loggers used by this driver. Configuring
* this Logger will affect all of the log messages generated by the driver.
* In the worst case, this may be the root Logger.
*
* @return the parent Logger for this driver
* @throws SQLFeatureNotSupportedException if the driver does not use <code>java.util.logging<code>.
* @since 1.7
*/
public Logger getParentLogger() throws SQLFeatureNotSupportedException;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, 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
@ -69,6 +69,10 @@ public interface PreparedStatement extends Statement {
* @exception SQLException if a database access error occurs;
* this method is called on a closed <code>PreparedStatement</code> or the SQL
* statement does not return a <code>ResultSet</code> object
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
*/
ResultSet executeQuery() throws SQLException;
@ -82,8 +86,11 @@ public interface PreparedStatement extends Statement {
* or (2) 0 for SQL statements that return nothing
* @exception SQLException if a database access error occurs;
* this method is called on a closed <code>PreparedStatement</code>
* or the SQL
* statement returns a <code>ResultSet</code> object
* or the SQL statement returns a <code>ResultSet</code> object
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
*/
int executeUpdate() throws SQLException;
@ -463,6 +470,10 @@ public interface PreparedStatement extends Statement {
* @exception SQLException if a database access error occurs;
* this method is called on a closed <code>PreparedStatement</code>
* or an argument is supplied to this method
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
* @see Statement#execute
* @see Statement#getResultSet
* @see Statement#getUpdateCount
@ -1208,4 +1219,5 @@ public interface PreparedStatement extends Statement {
void setNClob(int parameterIndex, Reader reader)
throws SQLException;
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2010, 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.sql;
/**
* Enumeration for pseudo/hidden column usage.
*
* @since 1.7
* @see DatabaseMetaData#getPseudoColumns
*/
public enum PseudoColumnUsage {
/**
* The pseudo/hidden column may only be used in a SELECT list.
*/
SELECT_LIST_ONLY,
/**
* The pseudo/hidden column may only be used in a WHERE clause.
*/
WHERE_CLAUSE_ONLY,
/**
* There are no restrictions on the usage of the pseudo/hidden columns.
*/
NO_USAGE_RESTRICTIONS,
/**
* The usage of the pseudo/hidden column cannot be determined.
*/
USAGE_UNKNOWN
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, 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
@ -145,7 +145,7 @@ import java.io.InputStream;
* @see ResultSetMetaData
*/
public interface ResultSet extends Wrapper {
public interface ResultSet extends Wrapper, AutoCloseable {
/**
* Moves the cursor froward one row from its current position.
@ -1187,6 +1187,9 @@ public interface ResultSet extends Wrapper {
* cursor on the last row; calling the method <code>absolute(-2)</code>
* moves the cursor to the next-to-last row, and so on.
*
* <p>If the row number specified is zero, the cursor is moved to
* before the first row.
*
* <p>An attempt to position the cursor beyond the first/last row in
* the result set leaves the cursor before the first row or after
* the last row.
@ -1196,9 +1199,10 @@ public interface ResultSet extends Wrapper {
* is the same as calling <code>last()</code>.
*
* @param row the number of the row to which the cursor should move.
* A positive number indicates the row number counting from the
* beginning of the result set; a negative number indicates the
* row number counting from the end of the result set
* A value of zero indicates that the cursor will be positioned
* before the first row; a positive number indicates the row number
* counting from the beginning of the result set; a negative number
* indicates the row number counting from the end of the result set
* @return <code>true</code> if the cursor is moved to a position in this
* <code>ResultSet</code> object;
* <code>false</code> if the cursor is before the first row or after the
@ -2529,7 +2533,7 @@ public interface ResultSet extends Wrapper {
* @exception SQLException if the columnLabel is not valid;
* if a database access error occurs
* or this method is called on a closed result set
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since 1.2
*/
@ -4072,4 +4076,64 @@ public interface ResultSet extends Wrapper {
*/
void updateNClob(String columnLabel, Reader reader) throws SQLException;
//------------------------- JDBC 4.1 -----------------------------------
/**
*<p>Retrieves the value of the designated column in the current row
* of this <code>ResultSet</code> object and will convert from the
* SQL type of the column to the requested Java data type, if the
* conversion is supported. If the conversion is not
* supported or null is specified for the type, a
* <code>SQLException</code> is thrown.
*<p>
* At a minimum, an implementation must support the conversions defined in
* Appendix B, Table B-3 and conversion of appropriate user defined SQL
* types to a Java type which implements {@code SQLData}, or {@code Struct}.
* Additional conversions may be supported and are vendor defined.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param type Class representing the Java data type to convert the designated
* column to.
* @return an instance of {@code type} holding the column value
* @throws SQLException if conversion is not supported, type is null or
* another error occurs. The getCause() method of the
* exception may provide a more detailed exception, for example, if
* a conversion error occurs
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since 1.7
*/
public <T> T getObject(int columnIndex, Class<T> type) throws SQLException;
/**
*<p>Retrieves the value of the designated column in the current row
* of this <code>ResultSet</code> object and will convert from the
* SQL type of the column to the requested Java data type, if the
* conversion is supported. If the conversion is not
* supported or null is specified for the type, a
* <code>SQLException</code> is thrown.
*<p>
* At a minimum, an implementation must support the conversions defined in
* Appendix B, Table B-3 and conversion of appropriate user defined SQL
* types to a Java type which implements {@code SQLData}, or {@code Struct}.
* Additional conversions may be supported and are vendor defined.
*
* @param columnLabel the label for the column specified with the SQL AS clause.
* If the SQL AS clause was not specified, then the label is the name
* of the column
* @param type Class representing the Java data type to convert the designated
* column to.
* @return an instance of {@code type} holding the column value
* @throws SQLException if conversion is not supported, type is null or
* another error occurs. The getCause() method of the
* exception may provide a more detailed exception, for example, if
* a conversion error occurs
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
* @since 1.7
*/
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, 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
@ -26,10 +26,13 @@
package java.sql;
/**
* The subclass of {@link SQLException} thrown when the SQLState class value is '<i>22</i>'. This indicates
* various data errors, including but not limited to not-allowed conversion, division by 0
* and invalid arguments to functions.
*
* The subclass of {@link SQLException} thrown when the SQLState class value
* is '<i>22</i>', or under vendor-specified conditions. This indicates
* various data errors, including but not limited to data conversion errors,
* division by 0, and invalid arguments to functions.
* <p>
* Please consult your driver vendor documentation for the vendor-specified
* conditions for which this <code>Exception</code> may be thrown.
* @since 1.6
*/
public class SQLDataException extends SQLNonTransientException {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, 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
@ -26,9 +26,13 @@
package java.sql;
/**
* The subclass of {@link SQLException} thrown when the SQLState class value is '<i>23</i>'. This indicates that an integrity
* The subclass of {@link SQLException} thrown when the SQLState class value
* is '<i>23</i>', or under vendor-specified conditions.
* This indicates that an integrity
* constraint (foreign key, primary key or unique key) has been violated.
*
* <p>
* Please consult your driver vendor documentation for the vendor-specified
* conditions for which this <code>Exception</code> may be thrown.
* @since 1.6
*/
public class SQLIntegrityConstraintViolationException extends SQLNonTransientException {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, 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
@ -26,9 +26,13 @@
package java.sql;
/**
* The subclass of {@link SQLException} thrown when the SQLState class value is '<i>28</i>'. This indicated that the
* authorization credentials presented during connection establishment are not valid.
*
* The subclass of {@link SQLException} thrown when the SQLState class value
* is '<i>28</i>', or under vendor-specified conditions. This indicates that
* the authorization credentials presented during connection establishment
* are not valid.
* <p>
* Please consult your driver vendor documentation for the vendor-specified
* conditions for which this <code>Exception</code> may be thrown.
* @since 1.6
*/
public class SQLInvalidAuthorizationSpecException extends SQLNonTransientException {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, 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
@ -26,11 +26,13 @@
package java.sql;
/**
* <P> The subclass of {@link SQLException} thrown for the SQLState
* class value '<i>08</i>', representing
* that the connection operation that failed will not succeed when
* The subclass of {@link SQLException} thrown for the SQLState
* class value '<i>08</i>', or under vendor-specified conditions. This
* indicates that the connection operation that failed will not succeed if
* the operation is retried without the cause of the failure being corrected.
* <p>
* Please consult your driver vendor documentation for the vendor-specified
* conditions for which this <code>Exception</code> may be thrown.
* @since 1.6
*/
public class SQLNonTransientConnectionException extends java.sql.SQLNonTransientException {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2010, 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
@ -30,9 +30,14 @@ import java.security.*;
/**
* The permission for which the <code>SecurityManager</code> will check
* when code that is running in an applet calls the
* <code>DriverManager.setLogWriter</code> method or the
* <code>DriverManager.setLogStream</code> (deprecated) method.
* when code that is running in an applet, or an application with a
* <code>SecurityManager</code> enabled, calls the
* <code>DriverManager.setLogWriter</code> method,
* <code>DriverManager.setLogStream</code> (deprecated) method,
* {@code SyncFactory.setJNDIContext} method,
* {@code SyncFactory.setLogger} method,
* {@code Connection.setNetworktimeout} method,
* or the <code>Connection.abort</code> method.
* If there is no <code>SQLPermission</code> object, these methods
* throw a <code>java.lang.SecurityException</code> as a runtime exception.
* <P>
@ -48,7 +53,6 @@ import java.security.*;
* but <code>*loadLibrary</code> or <code>a*b</code> is not valid.
* <P>
* The following table lists all the possible <code>SQLPermission</code> target names.
* Currently, the only name allowed is <code>setLog</code>.
* The table gives a description of what the permission allows
* and a discussion of the risks of granting code the permission.
* <P>
@ -67,9 +71,33 @@ import java.security.*;
* The contents of the log may contain usernames and passwords,
* SQL statements, and SQL data.</td>
* </tr>
* <tr>
* <td>callAbort</td>
* <td>Allows the invocation of the {@code Connection} method
* {@code abort}</td>
* <td>Permits an application to terminate a physical connection to a
* database.</td>
* </tr>
* <tr>
* <td>setSyncFactory</td>
* <td>Allows the invocation of the {@code SyncFactory} methods
* {@code setJNDIContext} and {@code setLogger}</td>
* <td>Permits an application to specify the JNDI context from which the
* {@code SyncProvider} implementations can be retrieved from and the logging
* object to be used by the{@codeSyncProvider} implementation.</td>
* </tr>
*
* <tr>
* <td>setNetworkTimeout</td>
* <td>Allows the invocation of the {@code Connection} method
* {@code setNetworkTimeout}</td>
* <td>Permits an application to specify the maximum period a
* <code>Connection</code> or
* objects created from the <code>Connection</code>
* will wait for the database to reply to any one request.</td>
* </tr>
* </table>
*
*<p>
* The person running an applet decides what permissions to allow
* and will run the <code>Policy Tool</code> to create an
* <code>SQLPermission</code> in a policy file. A programmer does

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, 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
@ -26,9 +26,12 @@
package java.sql;
/**
* The subclass of {@link SQLException} thrown when the SQLState class value is '<i>42</i>'. This indicates that the
* The subclass of {@link SQLException} thrown when the SQLState class value
* is '<i>42</i>', or under vendor-specified conditions. This indicates that the
* in-progress query has violated SQL syntax rules.
*
* <p>
* Please consult your driver vendor documentation for the vendor-specified
* conditions for which this <code>Exception</code> may be thrown.
* @since 1.6
*/
public class SQLSyntaxErrorException extends SQLNonTransientException {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, 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
@ -26,10 +26,13 @@
package java.sql;
/**
* The subclass of {@link SQLException} thrown when the SQLState class value is '<i>40</i>'. This indicates that the
* current statement was automatically rolled back by the database becuase of deadlock or other
* transaction serialization failures.
*
* The subclass of {@link SQLException} thrown when the SQLState class value
* is '<i>40</i>', or under vendor-specified conditions. This indicates that the
* current statement was automatically rolled back by the database because
* of deadlock or other transaction serialization failures.
* <p>
* Please consult your driver vendor documentation for the vendor-specified
* conditions for which this <code>Exception</code> may be thrown.
* @since 1.6
*/
public class SQLTransactionRollbackException extends SQLTransientException {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, 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
@ -27,11 +27,12 @@ package java.sql;
/**
* The subclass of {@link SQLException} for the SQLState class
* value '<i>08</i>', representing
* that the connection operation that failed might be able to succeed when
* value '<i>08</i>', or under vendor-specified conditions. This indicates
* that the connection operation that failed might be able to succeed if
* the operation is retried without any application-level changes.
*<p>
*
* <p>
* Please consult your driver vendor documentation for the vendor-specified
* conditions for which this <code>Exception</code> may be thrown.
* @since 1.6
*/
public class SQLTransientConnectionException extends java.sql.SQLTransientException {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, 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
@ -40,20 +40,27 @@ package java.sql;
* @see Connection#createStatement
* @see ResultSet
*/
public interface Statement extends Wrapper {
public interface Statement extends Wrapper, AutoCloseable {
/**
* Executes the given SQL statement, which returns a single
* <code>ResultSet</code> object.
*
*<p>
* <strong>Note:</strong>This method cannot be called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>.
* @param sql an SQL statement to be sent to the database, typically a
* static SQL <code>SELECT</code> statement
* @return a <code>ResultSet</code> object that contains the data produced
* by the given query; never <code>null</code>
* @exception SQLException if a database access error occurs,
* this method is called on a closed <code>Statement</code> or the given
* this method is called on a closed <code>Statement</code>, the given
* SQL statement produces anything other than a single
* <code>ResultSet</code> object
* <code>ResultSet</code> object, the method is called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
*/
ResultSet executeQuery(String sql) throws SQLException;
@ -61,7 +68,9 @@ public interface Statement extends Wrapper {
* Executes the given SQL statement, which may be an <code>INSERT</code>,
* <code>UPDATE</code>, or <code>DELETE</code> statement or an
* SQL statement that returns nothing, such as an SQL DDL statement.
*
*<p>
* <strong>Note:</strong>This method cannot be called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>.
* @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
* <code>DELETE</code>; or an SQL statement that returns nothing,
* such as a DDL statement.
@ -70,8 +79,13 @@ public interface Statement extends Wrapper {
* or (2) 0 for SQL statements that return nothing
*
* @exception SQLException if a database access error occurs,
* this method is called on a closed <code>Statement</code> or the given
* SQL statement produces a <code>ResultSet</code> object
* this method is called on a closed <code>Statement</code>, the given
* SQL statement produces a <code>ResultSet</code> object, the method is called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
*/
int executeUpdate(String sql) throws SQLException;
@ -198,11 +212,21 @@ public interface Statement extends Wrapper {
/**
* Sets the number of seconds the driver will wait for a
* <code>Statement</code> object to execute to the given number of seconds.
* If the limit is exceeded, an <code>SQLException</code> is thrown. A JDBC
* driver must apply this limit to the <code>execute</code>,
* <code>executeQuery</code> and <code>executeUpdate</code> methods. JDBC driver
* implementations may also apply this limit to <code>ResultSet</code> methods
*By default there is no limit on the amount of time allowed for a running
* statement to complete. If the limit is exceeded, an
* <code>SQLTimeoutException</code> is thrown.
* A JDBC driver must apply this limit to the <code>execute</code>,
* <code>executeQuery</code> and <code>executeUpdate</code> methods.
* <p>
* <strong>Note:</strong> JDBC driver implementations may also apply this
* limit to {@code ResultSet} methods
* (consult your driver vendor documentation for details).
* <p>
* <strong>Note:</strong> In the case of {@code Statement} batching, it is
* implementation defined as to whether the time-out is applied to
* individual SQL commands added via the {@code addBatch} method or to
* the entire batch of SQL commands invoked by the {@code executeBatch}
* method (consult your driver vendor documentation for details).
*
* @param seconds the new query timeout limit in seconds; zero means
* there is no limit
@ -300,13 +324,21 @@ public interface Statement extends Wrapper {
* <code>getResultSet</code> or <code>getUpdateCount</code>
* to retrieve the result, and <code>getMoreResults</code> to
* move to any subsequent result(s).
*
* <p>
*<strong>Note:</strong>This method cannot be called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>.
* @param sql any SQL statement
* @return <code>true</code> if the first result is a <code>ResultSet</code>
* object; <code>false</code> if it is an update count or there are
* no results
* @exception SQLException if a database access error occurs or
* this method is called on a closed <code>Statement</code>
* @exception SQLException if a database access error occurs,
* this method is called on a closed <code>Statement</code>,
* the method is called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
* @see #getResultSet
* @see #getUpdateCount
* @see #getMoreResults
@ -465,12 +497,14 @@ public interface Statement extends Wrapper {
* <code>Statement</code> object. The commands in this list can be
* executed as a batch by calling the method <code>executeBatch</code>.
* <P>
*
*<strong>Note:</strong>This method cannot be called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>.
* @param sql typically this is a SQL <code>INSERT</code> or
* <code>UPDATE</code> statement
* @exception SQLException if a database access error occurs,
* this method is called on a closed <code>Statement</code> or the
* driver does not support batch updates
* this method is called on a closed <code>Statement</code>, the
* driver does not support batch updates, the method is called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>
* @see #executeBatch
* @see DatabaseMetaData#supportsBatchUpdates
* @since 1.2
@ -536,7 +570,10 @@ public interface Statement extends Wrapper {
* driver does not support batch statements. Throws {@link BatchUpdateException}
* (a subclass of <code>SQLException</code>) if one of the commands sent to the
* database fails to execute properly or attempts to return a result set.
*
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
*
* @see #addBatch
* @see DatabaseMetaData#supportsBatchUpdates
@ -678,7 +715,9 @@ public interface Statement extends Wrapper {
* flag if the SQL statement
* is not an <code>INSERT</code> statement, or an SQL statement able to return
* auto-generated keys (the list of such statements is vendor-specific).
*
*<p>
* <strong>Note:</strong>This method cannot be called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>.
* @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
* <code>DELETE</code>; or an SQL statement that returns nothing,
* such as a DDL statement.
@ -693,10 +732,15 @@ public interface Statement extends Wrapper {
*
* @exception SQLException if a database access error occurs,
* this method is called on a closed <code>Statement</code>, the given
* SQL statement returns a <code>ResultSet</code> object, or
* the given constant is not one of those allowed
* SQL statement returns a <code>ResultSet</code> object,
* the given constant is not one of those allowed, the method is called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method with a constant of Statement.RETURN_GENERATED_KEYS
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
* @since 1.4
*/
int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException;
@ -709,7 +753,9 @@ public interface Statement extends Wrapper {
* available. The driver will ignore the array if the SQL statement
* is not an <code>INSERT</code> statement, or an SQL statement able to return
* auto-generated keys (the list of such statements is vendor-specific).
*
*<p>
* <strong>Note:</strong>This method cannot be called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>.
* @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
* <code>DELETE</code>; or an SQL statement that returns nothing,
* such as a DDL statement.
@ -721,10 +767,15 @@ public interface Statement extends Wrapper {
*
* @exception SQLException if a database access error occurs,
* this method is called on a closed <code>Statement</code>, the SQL
* statement returns a <code>ResultSet</code> object, or the
* second argument supplied to this method is not an <code>int</code> array
* whose elements are valid column indexes
* statement returns a <code>ResultSet</code> object,the second argument
* supplied to this method is not an
* <code>int</code> array whose elements are valid column indexes, the method is called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
* @since 1.4
*/
int executeUpdate(String sql, int columnIndexes[]) throws SQLException;
@ -737,7 +788,9 @@ public interface Statement extends Wrapper {
* available. The driver will ignore the array if the SQL statement
* is not an <code>INSERT</code> statement, or an SQL statement able to return
* auto-generated keys (the list of such statements is vendor-specific).
*
*<p>
* <strong>Note:</strong>This method cannot be called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>.
* @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
* <code>DELETE</code>; or an SQL statement that returns nothing,
* such as a DDL statement.
@ -748,11 +801,15 @@ public interface Statement extends Wrapper {
* that return nothing
* @exception SQLException if a database access error occurs,
* this method is called on a closed <code>Statement</code>, the SQL
* statement returns a <code>ResultSet</code> object, or the
* statement returns a <code>ResultSet</code> object, the
* second argument supplied to this method is not a <code>String</code> array
* whose elements are valid column names
*
* whose elements are valid column names, the method is called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
* @since 1.4
*/
int executeUpdate(String sql, String columnNames[]) throws SQLException;
@ -776,7 +833,9 @@ public interface Statement extends Wrapper {
* <code>getResultSet</code> or <code>getUpdateCount</code>
* to retrieve the result, and <code>getMoreResults</code> to
* move to any subsequent result(s).
*
*<p>
*<strong>Note:</strong>This method cannot be called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>.
* @param sql any SQL statement
* @param autoGeneratedKeys a constant indicating whether auto-generated
* keys should be made available for retrieval using the method
@ -787,12 +846,18 @@ public interface Statement extends Wrapper {
* object; <code>false</code> if it is an update count or there are
* no results
* @exception SQLException if a database access error occurs,
* this method is called on a closed <code>Statement</code> or the second
* this method is called on a closed <code>Statement</code>, the second
* parameter supplied to this method is not
* <code>Statement.RETURN_GENERATED_KEYS</code> or
* <code>Statement.NO_GENERATED_KEYS</code>.
* <code>Statement.NO_GENERATED_KEYS</code>,
* the method is called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method with a constant of Statement.RETURN_GENERATED_KEYS
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
* @see #getResultSet
* @see #getUpdateCount
* @see #getMoreResults
@ -823,7 +888,9 @@ public interface Statement extends Wrapper {
* <code>getResultSet</code> or <code>getUpdateCount</code>
* to retrieve the result, and <code>getMoreResults</code> to
* move to any subsequent result(s).
*
*<p>
* <strong>Note:</strong>This method cannot be called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>.
* @param sql any SQL statement
* @param columnIndexes an array of the indexes of the columns in the
* inserted row that should be made available for retrieval by a
@ -832,10 +899,15 @@ public interface Statement extends Wrapper {
* object; <code>false</code> if it is an update count or there
* are no results
* @exception SQLException if a database access error occurs,
* this method is called on a closed <code>Statement</code> or the
* this method is called on a closed <code>Statement</code>, the
* elements in the <code>int</code> array passed to this method
* are not valid column indexes
* are not valid column indexes, the method is called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
* @see #getResultSet
* @see #getUpdateCount
* @see #getMoreResults
@ -865,7 +937,9 @@ public interface Statement extends Wrapper {
* <code>getResultSet</code> or <code>getUpdateCount</code>
* to retrieve the result, and <code>getMoreResults</code> to
* move to any subsequent result(s).
*
*<p>
* <strong>Note:</strong>This method cannot be called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>.
* @param sql any SQL statement
* @param columnNames an array of the names of the columns in the inserted
* row that should be made available for retrieval by a call to the
@ -874,10 +948,15 @@ public interface Statement extends Wrapper {
* object; <code>false</code> if it is an update count or there
* are no more results
* @exception SQLException if a database access error occurs,
* this method is called on a closed <code>Statement</code> or the
* this method is called on a closed <code>Statement</code>,the
* elements of the <code>String</code> array passed to this
* method are not valid column names
* method are not valid column names, the method is called on a
* <code>PreparedStatement</code> or <code>CallableStatement</code>
* @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method
* @throws SQLTimeoutException when the driver has determined that the
* timeout value that was specified by the {@code setQueryTimeout}
* method has been exceeded and has at least attempted to cancel
* the currently running {@code Statement}
* @see #getResultSet
* @see #getUpdateCount
* @see #getMoreResults
@ -951,4 +1030,34 @@ public interface Statement extends Wrapper {
boolean isPoolable()
throws SQLException;
//--------------------------JDBC 4.1 -----------------------------
/**
* Specifies that this {@code Statement} will be closed when all its
* dependent result sets are closed. If execution of the {@code Statement}
* does not produce any result sets, this method has no effect.
* <p>
* <strong>Note:</strong> Multiple calls to {@code closeOnCompletion} do
* not toggle the effect on this {@code Statement}. However, a call to
* {@code closeOnCompletion} does effect both the subsequent execution of
* statements, and statements that currently have open, dependent,
* result sets.
*
* @throws SQLException if this method is called on a closed
* {@code Statement}
* @since 1.7
*/
public void closeOnCompletion() throws SQLException;
/**
* Returns a value indicating whether this {@code Statement} will be
* closed when all dependent objects such as resultsets are closed.
* @return {@code true} if the {@code Statement} will be closed when all
* of its dependent objects are closed; {@code false} otherwise
* @throws SQLException if this method is called on a closed
* {@code Statement}
* @since 1.7
*/
public boolean isCloseOnCompletion() throws SQLException;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, 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
@ -155,19 +155,26 @@ public class Timestamp extends java.util.Date {
* Converts a <code>String</code> object in JDBC timestamp escape format to a
* <code>Timestamp</code> value.
*
* @param s timestamp in format <code>yyyy-mm-dd hh:mm:ss[.f...]</code>. The
* fractional seconds may be omitted.
* @param s timestamp in format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>. The
* fractional seconds may be omitted. The leading zero for <code>mm</code>
* and <code>dd</code> may also be omitted.
*
* @return corresponding <code>Timestamp</code> value
* @exception java.lang.IllegalArgumentException if the given argument
* does not have the format <code>yyyy-mm-dd hh:mm:ss[.f...]</code>
* does not have the format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>
*/
public static Timestamp valueOf(String s) {
final int YEAR_LENGTH = 4;
final int MONTH_LENGTH = 2;
final int DAY_LENGTH = 2;
final int MAX_MONTH = 12;
final int MAX_DAY = 31;
String date_s;
String time_s;
String nanos_s;
int year;
int month;
int day;
int year = 0;
int month = 0;
int day = 0;
int hour;
int minute;
int second;
@ -182,17 +189,9 @@ public class Timestamp extends java.util.Date {
String zeros = "000000000";
String delimiterDate = "-";
String delimiterTime = ":";
StringTokenizer stringTokeninzerDate;
StringTokenizer stringTokeninzerTime;
if (s == null) throw new java.lang.IllegalArgumentException("null string");
int counterD = 0;
int intDate[] = {4,2,2};
int counterT = 0;
int intTime[] = {2,2,12};
// Split the string into date and time components
s = s.trim();
dividingSpace = s.indexOf(' ');
@ -203,30 +202,6 @@ public class Timestamp extends java.util.Date {
throw new java.lang.IllegalArgumentException(formatError);
}
stringTokeninzerTime = new StringTokenizer(time_s, delimiterTime);
stringTokeninzerDate = new StringTokenizer(date_s, delimiterDate);
while(stringTokeninzerDate.hasMoreTokens()) {
String tokenDate = stringTokeninzerDate.nextToken();
if(tokenDate.length() != intDate[counterD] ) {
throw new java.lang.IllegalArgumentException(formatError);
}
counterD++;
}
/*
//Commenting this portion out for checking of time
while(stringTokeninzerTime.hasMoreTokens()) {
String tokenTime = stringTokeninzerTime.nextToken();
if (counterT < 2 && tokenTime.length() != intTime[counterT] ) {
throw new java.lang.IllegalArgumentException(formatError);
}
counterT++;
}
*/
// Parse the date
firstDash = date_s.indexOf('-');
secondDash = date_s.indexOf('-', firstDash+1);
@ -239,14 +214,24 @@ public class Timestamp extends java.util.Date {
period = time_s.indexOf('.', secondColon+1);
// Convert the date
if ((firstDash > 0) && (secondDash > 0) &&
(secondDash < date_s.length()-1)) {
year = Integer.parseInt(date_s.substring(0, firstDash)) - 1900;
month =
Integer.parseInt(date_s.substring
(firstDash+1, secondDash)) - 1;
day = Integer.parseInt(date_s.substring(secondDash+1));
} else {
boolean parsedDate = false;
if ((firstDash > 0) && (secondDash > 0) && (secondDash < date_s.length() - 1)) {
String yyyy = date_s.substring(0, firstDash);
String mm = date_s.substring(firstDash + 1, secondDash);
String dd = date_s.substring(secondDash + 1);
if (yyyy.length() == YEAR_LENGTH &&
(mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
(dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
year = Integer.parseInt(yyyy);
month = Integer.parseInt(mm);
day = Integer.parseInt(dd);
if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
parsedDate = true;
}
}
}
if (! parsedDate) {
throw new java.lang.IllegalArgumentException(formatError);
}
@ -272,10 +257,10 @@ public class Timestamp extends java.util.Date {
second = Integer.parseInt(time_s.substring(secondColon+1));
}
} else {
throw new java.lang.IllegalArgumentException();
throw new java.lang.IllegalArgumentException(formatError);
}
return new Timestamp(year, month, day, hour, minute, second, a_nanos);
return new Timestamp(year - 1900, month - 1, day, hour, minute, second, a_nanos);
}
/**
@ -502,14 +487,10 @@ public class Timestamp extends java.util.Date {
/**
* Compares this <code>Timestamp</code> object to the given
* <code>Date</code>, which must be a <code>Timestamp</code>
* object. If the argument is not a <code>Timestamp</code> object,
* this method throws a <code>ClassCastException</code> object.
* (<code>Timestamp</code> objects are
* comparable only to other <code>Timestamp</code> objects.)
* <code>Date</code> object.
*
* @param o the <code>Date</code> to be compared, which must be a
* <code>Timestamp</code> object
* @param o the <code>Date</code> to be compared to
* this <code>Timestamp</code> object
* @return the value <code>0</code> if this <code>Timestamp</code> object
* and the given object are equal; a value less than <code>0</code>
* if this <code>Timestamp</code> object is before the given argument;

View File

@ -49,9 +49,9 @@ package java.util;
* <p>Note that fail-fast behavior cannot be guaranteed as it is, generally
* speaking, impossible to make any hard guarantees in the presence of
* unsynchronized concurrent modification. Fail-fast operations
* throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
* throw {@code ConcurrentModificationException} on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: <i><tt>ConcurrentModificationException</tt>
* exception for its correctness: <i>{@code ConcurrentModificationException}
* should be used only to detect bugs.</i>
*
* @author Josh Bloch
@ -77,7 +77,7 @@ public class ConcurrentModificationException extends RuntimeException {
}
/**
* Constructs a <tt>ConcurrentModificationException</tt> with the
* Constructs a {@code ConcurrentModificationException} with the
* specified detail message.
*
* @param message the detail message pertaining to this exception.
@ -85,4 +85,39 @@ public class ConcurrentModificationException extends RuntimeException {
public ConcurrentModificationException(String message) {
super(message);
}
/**
* Constructs a new exception with the specified cause and a detail
* message of {@code (cause==null ? null : cause.toString())} (which
* typically contains the class and detail message of {@code cause}.
*
* @param cause the cause (which is saved for later retrieval by the
* {@link Throwable#getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.7
*/
public ConcurrentModificationException(Throwable cause) {
super(cause);
}
/**
* Constructs a new exception with the specified detail message and
* cause.
*
* <p>Note that the detail message associated with <code>cause</code> is
* <i>not</i> automatically incorporated in this exception's detail
* message.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link Throwable#getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link Throwable#getCause()} method). (A {@code null} value
* is permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.7
*/
public ConcurrentModificationException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -912,9 +912,13 @@ class Properties extends Hashtable<Object,Object> {
*
* <p>The specified stream remains open after this method returns.
*
* @param os the output stream on which to emit the XML document.
* @param comment a description of the property list, or <code>null</code>
* if no comment is desired.
* @param os the output stream on which to emit the XML document.
* @param comment a description of the property list, or <code>null</code>
* if no comment is desired.
* @param encoding the name of a supported
* <a href="../lang/package-summary.html#charenc">
* character encoding</a>
*
* @throws IOException if writing to the specified output stream
* results in an <tt>IOException</tt>.
* @throws NullPointerException if <code>os</code> is <code>null</code>,

File diff suppressed because it is too large Load Diff

View File

@ -91,10 +91,7 @@ import java.util.WeakHashMap;
* results of a task is {@link #join}, but there are several variants:
* The {@link Future#get} methods support interruptible and/or timed
* waits for completion and report results using {@code Future}
* conventions. Method {@link #helpJoin} enables callers to actively
* execute other tasks while awaiting joins, which is sometimes more
* efficient but only applies when all subtasks are known to be
* strictly tree-structured. Method {@link #invoke} is semantically
* conventions. Method {@link #invoke} is semantically
* equivalent to {@code fork(); join()} but always attempts to begin
* execution in the current thread. The "<em>quiet</em>" forms of
* these methods do not extract results or report exceptions. These
@ -130,7 +127,7 @@ import java.util.WeakHashMap;
* ForkJoinTasks (as may be determined using method {@link
* #inForkJoinPool}). Attempts to invoke them in other contexts
* result in exceptions or errors, possibly including
* ClassCastException.
* {@code ClassCastException}.
*
* <p>Most base support methods are {@code final}, to prevent
* overriding of implementations that are intrinsically tied to the
@ -152,9 +149,8 @@ import java.util.WeakHashMap;
*
* <p>This class provides {@code adapt} methods for {@link Runnable}
* and {@link Callable}, that may be of use when mixing execution of
* {@code ForkJoinTasks} with other kinds of tasks. When all tasks
* are of this form, consider using a pool in
* {@linkplain ForkJoinPool#setAsyncMode async mode}.
* {@code ForkJoinTasks} with other kinds of tasks. When all tasks are
* of this form, consider using a pool constructed in <em>asyncMode</em>.
*
* <p>ForkJoinTasks are {@code Serializable}, which enables them to be
* used in extensions such as remote execution frameworks. It is
@ -166,33 +162,43 @@ import java.util.WeakHashMap;
*/
public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
/**
* Run control status bits packed into a single int to minimize
* footprint and to ensure atomicity (via CAS). Status is
* initially zero, and takes on nonnegative values until
* completed, upon which status holds COMPLETED. CANCELLED, or
* EXCEPTIONAL, which use the top 3 bits. Tasks undergoing
* blocking waits by other threads have SIGNAL_MASK bits set --
* bit 15 for external (nonFJ) waits, and the rest a count of
* waiting FJ threads. (This representation relies on
* ForkJoinPool max thread limits). Completion of a stolen task
* with SIGNAL_MASK bits set awakens waiter via notifyAll. Even
* though suboptimal for some purposes, we use basic builtin
* wait/notify to take advantage of "monitor inflation" in JVMs
* that we would otherwise need to emulate to avoid adding further
* per-task bookkeeping overhead. Note that bits 16-28 are
* currently unused. Also value 0x80000000 is available as spare
* completion value.
/*
* See the internal documentation of class ForkJoinPool for a
* general implementation overview. ForkJoinTasks are mainly
* responsible for maintaining their "status" field amidst relays
* to methods in ForkJoinWorkerThread and ForkJoinPool. The
* methods of this class are more-or-less layered into (1) basic
* status maintenance (2) execution and awaiting completion (3)
* user-level methods that additionally report results. This is
* sometimes hard to see because this file orders exported methods
* in a way that flows well in javadocs. In particular, most
* join mechanics are in method quietlyJoin, below.
*/
/*
* The status field holds run control status bits packed into a
* single int to minimize footprint and to ensure atomicity (via
* CAS). Status is initially zero, and takes on nonnegative
* values until completed, upon which status holds value
* NORMAL, CANCELLED, or EXCEPTIONAL. Tasks undergoing blocking
* waits by other threads have the SIGNAL bit set. Completion of
* a stolen task with SIGNAL set awakens any waiters via
* notifyAll. Even though suboptimal for some purposes, we use
* basic builtin wait/notify to take advantage of "monitor
* inflation" in JVMs that we would otherwise need to emulate to
* avoid adding further per-task bookkeeping overhead. We want
* these monitors to be "fat", i.e., not use biasing or thin-lock
* techniques, so use some odd coding idioms that tend to avoid
* them.
*/
/** The run status of this task */
volatile int status; // accessed directly by pool and workers
static final int COMPLETION_MASK = 0xe0000000;
static final int NORMAL = 0xe0000000; // == mask
static final int CANCELLED = 0xc0000000;
static final int EXCEPTIONAL = 0xa0000000;
static final int SIGNAL_MASK = 0x0000ffff;
static final int INTERNAL_SIGNAL_MASK = 0x00007fff;
static final int EXTERNAL_SIGNAL = 0x00008000; // top bit of low word
private static final int NORMAL = -1;
private static final int CANCELLED = -2;
private static final int EXCEPTIONAL = -3;
private static final int SIGNAL = 1;
/**
* Table of exceptions thrown by tasks, to enable reporting by
@ -206,176 +212,94 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
Collections.synchronizedMap
(new WeakHashMap<ForkJoinTask<?>, Throwable>());
// within-package utilities
// Maintaining completion status
/**
* Gets current worker thread, or null if not a worker thread.
*/
static ForkJoinWorkerThread getWorker() {
Thread t = Thread.currentThread();
return ((t instanceof ForkJoinWorkerThread) ?
(ForkJoinWorkerThread) t : null);
}
final boolean casStatus(int cmp, int val) {
return UNSAFE.compareAndSwapInt(this, statusOffset, cmp, val);
}
/**
* Workaround for not being able to rethrow unchecked exceptions.
*/
static void rethrowException(Throwable ex) {
if (ex != null)
UNSAFE.throwException(ex);
}
// Setting completion status
/**
* Marks completion and wakes up threads waiting to join this task.
* Marks completion and wakes up threads waiting to join this task,
* also clearing signal request bits.
*
* @param completion one of NORMAL, CANCELLED, EXCEPTIONAL
*/
final void setCompletion(int completion) {
ForkJoinPool pool = getPool();
if (pool != null) {
int s; // Clear signal bits while setting completion status
do {} while ((s = status) >= 0 && !casStatus(s, completion));
if ((s & SIGNAL_MASK) != 0) {
if ((s &= INTERNAL_SIGNAL_MASK) != 0)
pool.updateRunningCount(s);
synchronized (this) { notifyAll(); }
private void setCompletion(int completion) {
int s;
while ((s = status) >= 0) {
if (UNSAFE.compareAndSwapInt(this, statusOffset, s, completion)) {
if (s != 0)
synchronized (this) { notifyAll(); }
break;
}
}
else
externallySetCompletion(completion);
}
/**
* Version of setCompletion for non-FJ threads. Leaves signal
* bits for unblocked threads to adjust, and always notifies.
* Records exception and sets exceptional completion.
*
* @return status on exit
*/
private void externallySetCompletion(int completion) {
int s;
do {} while ((s = status) >= 0 &&
!casStatus(s, (s & SIGNAL_MASK) | completion));
synchronized (this) { notifyAll(); }
private void setExceptionalCompletion(Throwable rex) {
exceptionMap.put(this, rex);
setCompletion(EXCEPTIONAL);
}
/**
* Sets status to indicate normal completion.
* Blocks a worker thread until completion. Called only by
* pool. Currently unused -- pool-based waits use timeout
* version below.
*/
final void setNormalCompletion() {
// Try typical fast case -- single CAS, no signal, not already done.
// Manually expand casStatus to improve chances of inlining it
if (!UNSAFE.compareAndSwapInt(this, statusOffset, 0, NORMAL))
setCompletion(NORMAL);
}
// internal waiting and notification
/**
* Performs the actual monitor wait for awaitDone.
*/
private void doAwaitDone() {
// Minimize lock bias and in/de-flation effects by maximizing
// chances of waiting inside sync
try {
while (status >= 0)
synchronized (this) { if (status >= 0) wait(); }
} catch (InterruptedException ie) {
onInterruptedWait();
}
}
/**
* Performs the actual timed monitor wait for awaitDone.
*/
private void doAwaitDone(long startTime, long nanos) {
synchronized (this) {
final void internalAwaitDone() {
int s; // the odd construction reduces lock bias effects
while ((s = status) >= 0) {
try {
while (status >= 0) {
long nt = nanos - (System.nanoTime() - startTime);
if (nt <= 0)
break;
wait(nt / 1000000, (int) (nt % 1000000));
synchronized(this) {
if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL))
wait();
}
} catch (InterruptedException ie) {
onInterruptedWait();
cancelIfTerminating();
}
}
}
// Awaiting completion
/**
* Sets status to indicate there is joiner, then waits for join,
* surrounded with pool notifications.
* Blocks a worker thread until completed or timed out. Called
* only by pool.
*
* @return status upon exit
* @return status on exit
*/
private int awaitDone(ForkJoinWorkerThread w,
boolean maintainParallelism) {
ForkJoinPool pool = (w == null) ? null : w.pool;
final int internalAwaitDone(long millis) {
int s;
while ((s = status) >= 0) {
if (casStatus(s, (pool == null) ? s|EXTERNAL_SIGNAL : s+1)) {
if (pool == null || !pool.preJoin(this, maintainParallelism))
doAwaitDone();
if (((s = status) & INTERNAL_SIGNAL_MASK) != 0)
adjustPoolCountsOnUnblock(pool);
break;
}
}
return s;
}
/**
* Timed version of awaitDone
*
* @return status upon exit
*/
private int awaitDone(ForkJoinWorkerThread w, long nanos) {
ForkJoinPool pool = (w == null) ? null : w.pool;
int s;
while ((s = status) >= 0) {
if (casStatus(s, (pool == null) ? s|EXTERNAL_SIGNAL : s+1)) {
long startTime = System.nanoTime();
if (pool == null || !pool.preJoin(this, false))
doAwaitDone(startTime, nanos);
if ((s = status) >= 0) {
adjustPoolCountsOnCancelledWait(pool);
s = status;
if ((s = status) >= 0) {
try {
synchronized(this) {
if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL))
wait(millis, 0);
}
if (s < 0 && (s & INTERNAL_SIGNAL_MASK) != 0)
adjustPoolCountsOnUnblock(pool);
break;
} catch (InterruptedException ie) {
cancelIfTerminating();
}
s = status;
}
return s;
}
/**
* Notifies pool that thread is unblocked. Called by signalled
* threads when woken by non-FJ threads (which is atypical).
* Blocks a non-worker-thread until completion.
*/
private void adjustPoolCountsOnUnblock(ForkJoinPool pool) {
private void externalAwaitDone() {
int s;
do {} while ((s = status) < 0 && !casStatus(s, s & COMPLETION_MASK));
if (pool != null && (s &= INTERNAL_SIGNAL_MASK) != 0)
pool.updateRunningCount(s);
}
/**
* Notifies pool to adjust counts on cancelled or timed out wait.
*/
private void adjustPoolCountsOnCancelledWait(ForkJoinPool pool) {
if (pool != null) {
int s;
while ((s = status) >= 0 && (s & INTERNAL_SIGNAL_MASK) != 0) {
if (casStatus(s, s - 1)) {
pool.updateRunningCount(1);
while ((s = status) >= 0) {
synchronized(this) {
if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)){
boolean interrupted = false;
while (status >= 0) {
try {
wait();
} catch (InterruptedException ie) {
interrupted = true;
}
}
if (interrupted)
Thread.currentThread().interrupt();
break;
}
}
@ -383,153 +307,19 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
}
/**
* Handles interruptions during waits.
*/
private void onInterruptedWait() {
ForkJoinWorkerThread w = getWorker();
if (w == null)
Thread.currentThread().interrupt(); // re-interrupt
else if (w.isTerminating())
cancelIgnoringExceptions();
// else if FJworker, ignore interrupt
}
// Recording and reporting exceptions
private void setDoneExceptionally(Throwable rex) {
exceptionMap.put(this, rex);
setCompletion(EXCEPTIONAL);
}
/**
* Throws the exception associated with status s.
*
* @throws the exception
*/
private void reportException(int s) {
if ((s &= COMPLETION_MASK) < NORMAL) {
if (s == CANCELLED)
throw new CancellationException();
else
rethrowException(exceptionMap.get(this));
}
}
/**
* Returns result or throws exception using j.u.c.Future conventions.
* Only call when {@code isDone} known to be true or thread known
* to be interrupted.
*/
private V reportFutureResult()
throws InterruptedException, ExecutionException {
if (Thread.interrupted())
throw new InterruptedException();
int s = status & COMPLETION_MASK;
if (s < NORMAL) {
Throwable ex;
if (s == CANCELLED)
throw new CancellationException();
if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
throw new ExecutionException(ex);
}
return getRawResult();
}
/**
* Returns result or throws exception using j.u.c.Future conventions
* with timeouts.
*/
private V reportTimedFutureResult()
throws InterruptedException, ExecutionException, TimeoutException {
if (Thread.interrupted())
throw new InterruptedException();
Throwable ex;
int s = status & COMPLETION_MASK;
if (s == NORMAL)
return getRawResult();
else if (s == CANCELLED)
throw new CancellationException();
else if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
throw new ExecutionException(ex);
else
throw new TimeoutException();
}
// internal execution methods
/**
* Calls exec, recording completion, and rethrowing exception if
* encountered. Caller should normally check status before calling.
*
* @return true if completed normally
*/
private boolean tryExec() {
try { // try block must contain only call to exec
if (!exec())
return false;
} catch (Throwable rex) {
setDoneExceptionally(rex);
rethrowException(rex);
return false; // not reached
}
setNormalCompletion();
return true;
}
/**
* Main execution method used by worker threads. Invokes
* base computation unless already complete.
* Unless done, calls exec and records status if completed, but
* doesn't wait for completion otherwise. Primary execution method
* for ForkJoinWorkerThread.
*/
final void quietlyExec() {
if (status >= 0) {
try {
if (!exec())
return;
} catch (Throwable rex) {
setDoneExceptionally(rex);
try {
if (status < 0 || !exec())
return;
}
setNormalCompletion();
}
}
/**
* Calls exec(), recording but not rethrowing exception.
* Caller should normally check status before calling.
*
* @return true if completed normally
*/
private boolean tryQuietlyInvoke() {
try {
if (!exec())
return false;
} catch (Throwable rex) {
setDoneExceptionally(rex);
return false;
setExceptionalCompletion(rex);
return;
}
setNormalCompletion();
return true;
}
/**
* Cancels, ignoring any exceptions it throws.
*/
final void cancelIgnoringExceptions() {
try {
cancel(false);
} catch (Throwable ignore) {
}
}
/**
* Main implementation of helpJoin
*/
private int busyJoin(ForkJoinWorkerThread w) {
int s;
ForkJoinTask<?> t;
while ((s = status) >= 0 && (t = w.scanWhileJoining(this)) != null)
t.quietlyExec();
return (s >= 0) ? awaitDone(w, false) : s; // block if no work
setCompletion(NORMAL); // must be outside try block
}
// public methods
@ -567,34 +357,41 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
* @return the computed result
*/
public final V join() {
ForkJoinWorkerThread w = getWorker();
if (w == null || status < 0 || !w.unpushTask(this) || !tryExec())
reportException(awaitDone(w, true));
quietlyJoin();
Throwable ex;
if (status < NORMAL && (ex = getException()) != null)
UNSAFE.throwException(ex);
return getRawResult();
}
/**
* Commences performing this task, awaits its completion if
* necessary, and return its result, or throws an (unchecked)
* exception if the underlying computation did so.
* necessary, and returns its result, or throws an (unchecked)
* {@code RuntimeException} or {@code Error} if the underlying
* computation did so.
*
* @return the computed result
*/
public final V invoke() {
if (status >= 0 && tryExec())
return getRawResult();
else
return join();
quietlyInvoke();
Throwable ex;
if (status < NORMAL && (ex = getException()) != null)
UNSAFE.throwException(ex);
return getRawResult();
}
/**
* Forks the given tasks, returning when {@code isDone} holds for
* each task or an (unchecked) exception is encountered, in which
* case the exception is rethrown. If either task encounters an
* exception, the other one may be, but is not guaranteed to be,
* cancelled. If both tasks throw an exception, then this method
* throws one of them. The individual status of each task may be
* checked using {@link #getException()} and related methods.
* case the exception is rethrown. If more than one task
* encounters an exception, then this method throws any one of
* these exceptions. If any task encounters an exception, the
* other may be cancelled. However, the execution status of
* individual tasks is not guaranteed upon exceptional return. The
* status of each task may be obtained using {@link
* #getException()} and related methods to check if they have been
* cancelled, completed normally or exceptionally, or left
* unprocessed.
*
* <p>This method may be invoked only from within {@code
* ForkJoinTask} computations (as may be determined using method
@ -615,12 +412,14 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
/**
* Forks the given tasks, returning when {@code isDone} holds for
* each task or an (unchecked) exception is encountered, in which
* case the exception is rethrown. If any task encounters an
* exception, others may be, but are not guaranteed to be,
* cancelled. If more than one task encounters an exception, then
* this method throws any one of these exceptions. The individual
* status of each task may be checked using {@link #getException()}
* and related methods.
* case the exception is rethrown. If more than one task
* encounters an exception, then this method throws any one of
* these exceptions. If any task encounters an exception, others
* may be cancelled. However, the execution status of individual
* tasks is not guaranteed upon exceptional return. The status of
* each task may be obtained using {@link #getException()} and
* related methods to check if they have been cancelled, completed
* normally or exceptionally, or left unprocessed.
*
* <p>This method may be invoked only from within {@code
* ForkJoinTask} computations (as may be determined using method
@ -644,7 +443,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
t.fork();
else {
t.quietlyInvoke();
if (ex == null)
if (ex == null && t.status < NORMAL)
ex = t.getException();
}
}
@ -655,26 +454,27 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
t.cancel(false);
else {
t.quietlyJoin();
if (ex == null)
if (ex == null && t.status < NORMAL)
ex = t.getException();
}
}
}
if (ex != null)
rethrowException(ex);
UNSAFE.throwException(ex);
}
/**
* Forks all tasks in the specified collection, returning when
* {@code isDone} holds for each task or an (unchecked) exception
* is encountered. If any task encounters an exception, others
* may be, but are not guaranteed to be, cancelled. If more than
* one task encounters an exception, then this method throws any
* one of these exceptions. The individual status of each task
* may be checked using {@link #getException()} and related
* methods. The behavior of this operation is undefined if the
* specified collection is modified while the operation is in
* progress.
* is encountered, in which case the exception is rethrown. If
* more than one task encounters an exception, then this method
* throws any one of these exceptions. If any task encounters an
* exception, others may be cancelled. However, the execution
* status of individual tasks is not guaranteed upon exceptional
* return. The status of each task may be obtained using {@link
* #getException()} and related methods to check if they have been
* cancelled, completed normally or exceptionally, or left
* unprocessed.
*
* <p>This method may be invoked only from within {@code
* ForkJoinTask} computations (as may be determined using method
@ -706,7 +506,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
t.fork();
else {
t.quietlyInvoke();
if (ex == null)
if (ex == null && t.status < NORMAL)
ex = t.getException();
}
}
@ -717,13 +517,13 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
t.cancel(false);
else {
t.quietlyJoin();
if (ex == null)
if (ex == null && t.status < NORMAL)
ex = t.getException();
}
}
}
if (ex != null)
rethrowException(ex);
UNSAFE.throwException(ex);
return tasks;
}
@ -753,7 +553,35 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
*/
public boolean cancel(boolean mayInterruptIfRunning) {
setCompletion(CANCELLED);
return (status & COMPLETION_MASK) == CANCELLED;
return status == CANCELLED;
}
/**
* Cancels, ignoring any exceptions thrown by cancel. Used during
* worker and pool shutdown. Cancel is spec'ed not to throw any
* exceptions, but if it does anyway, we have no recourse during
* shutdown, so guard against this case.
*/
final void cancelIgnoringExceptions() {
try {
cancel(false);
} catch (Throwable ignore) {
}
}
/**
* Cancels if current thread is a terminating worker thread,
* ignoring any exceptions thrown by cancel.
*/
final void cancelIfTerminating() {
Thread t = Thread.currentThread();
if ((t instanceof ForkJoinWorkerThread) &&
((ForkJoinWorkerThread) t).isTerminating()) {
try {
cancel(false);
} catch (Throwable ignore) {
}
}
}
public final boolean isDone() {
@ -761,7 +589,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
}
public final boolean isCancelled() {
return (status & COMPLETION_MASK) == CANCELLED;
return status == CANCELLED;
}
/**
@ -770,7 +598,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
* @return {@code true} if this task threw an exception or was cancelled
*/
public final boolean isCompletedAbnormally() {
return (status & COMPLETION_MASK) < NORMAL;
return status < NORMAL;
}
/**
@ -781,7 +609,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
* exception and was not cancelled
*/
public final boolean isCompletedNormally() {
return (status & COMPLETION_MASK) == NORMAL;
return status == NORMAL;
}
/**
@ -792,7 +620,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
* @return the exception, or {@code null} if none
*/
public final Throwable getException() {
int s = status & COMPLETION_MASK;
int s = status;
return ((s >= NORMAL) ? null :
(s == CANCELLED) ? new CancellationException() :
exceptionMap.get(this));
@ -813,20 +641,21 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
* thrown will be a {@code RuntimeException} with cause {@code ex}.
*/
public void completeExceptionally(Throwable ex) {
setDoneExceptionally((ex instanceof RuntimeException) ||
(ex instanceof Error) ? ex :
new RuntimeException(ex));
setExceptionalCompletion((ex instanceof RuntimeException) ||
(ex instanceof Error) ? ex :
new RuntimeException(ex));
}
/**
* Completes this task, and if not already aborted or cancelled,
* returning a {@code null} result upon {@code join} and related
* operations. This method may be used to provide results for
* asynchronous tasks, or to provide alternative handling for
* tasks that would not otherwise complete normally. Its use in
* other situations is discouraged. This method is
* overridable, but overridden versions must invoke {@code super}
* implementation to maintain guarantees.
* returning the given value as the result of subsequent
* invocations of {@code join} and related operations. This method
* may be used to provide results for asynchronous tasks, or to
* provide alternative handling for tasks that would not otherwise
* complete normally. Its use in other situations is
* discouraged. This method is overridable, but overridden
* versions must invoke {@code super} implementation to maintain
* guarantees.
*
* @param value the result value for this task
*/
@ -834,97 +663,151 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
try {
setRawResult(value);
} catch (Throwable rex) {
setDoneExceptionally(rex);
setExceptionalCompletion(rex);
return;
}
setNormalCompletion();
setCompletion(NORMAL);
}
public final V get() throws InterruptedException, ExecutionException {
ForkJoinWorkerThread w = getWorker();
if (w == null || status < 0 || !w.unpushTask(this) || !tryQuietlyInvoke())
awaitDone(w, true);
return reportFutureResult();
quietlyJoin();
if (Thread.interrupted())
throw new InterruptedException();
int s = status;
if (s < NORMAL) {
Throwable ex;
if (s == CANCELLED)
throw new CancellationException();
if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
throw new ExecutionException(ex);
}
return getRawResult();
}
public final V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
Thread t = Thread.currentThread();
ForkJoinPool pool;
if (t instanceof ForkJoinWorkerThread) {
ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
if (status >= 0 && w.unpushTask(this))
quietlyExec();
pool = w.pool;
}
else
pool = null;
/*
* Timed wait loop intermixes cases for FJ (pool != null) and
* non FJ threads. For FJ, decrement pool count but don't try
* for replacement; increment count on completion. For non-FJ,
* deal with interrupts. This is messy, but a little less so
* than is splitting the FJ and nonFJ cases.
*/
boolean interrupted = false;
boolean dec = false; // true if pool count decremented
long nanos = unit.toNanos(timeout);
ForkJoinWorkerThread w = getWorker();
if (w == null || status < 0 || !w.unpushTask(this) || !tryQuietlyInvoke())
awaitDone(w, nanos);
return reportTimedFutureResult();
}
/**
* Possibly executes other tasks until this task {@link #isDone is
* done}, then returns the result of the computation. This method
* may be more efficient than {@code join}, but is only applicable
* when there are no potential dependencies between continuation
* of the current task and that of any other task that might be
* executed while helping. (This usually holds for pure
* divide-and-conquer tasks).
*
* <p>This method may be invoked only from within {@code
* ForkJoinTask} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
*
* @return the computed result
*/
public final V helpJoin() {
ForkJoinWorkerThread w = (ForkJoinWorkerThread) Thread.currentThread();
if (status < 0 || !w.unpushTask(this) || !tryExec())
reportException(busyJoin(w));
for (;;) {
if (pool == null && Thread.interrupted()) {
interrupted = true;
break;
}
int s = status;
if (s < 0)
break;
if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)) {
long startTime = System.nanoTime();
long nt; // wait time
while (status >= 0 &&
(nt = nanos - (System.nanoTime() - startTime)) > 0) {
if (pool != null && !dec)
dec = pool.tryDecrementRunningCount();
else {
long ms = nt / 1000000;
int ns = (int) (nt % 1000000);
try {
synchronized(this) {
if (status >= 0)
wait(ms, ns);
}
} catch (InterruptedException ie) {
if (pool != null)
cancelIfTerminating();
else {
interrupted = true;
break;
}
}
}
}
break;
}
}
if (pool != null && dec)
pool.incrementRunningCount();
if (interrupted)
throw new InterruptedException();
int es = status;
if (es != NORMAL) {
Throwable ex;
if (es == CANCELLED)
throw new CancellationException();
if (es == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
throw new ExecutionException(ex);
throw new TimeoutException();
}
return getRawResult();
}
/**
* Possibly executes other tasks until this task {@link #isDone is
* done}. This method may be useful when processing collections
* of tasks when some have been cancelled or otherwise known to
* have aborted.
*
* <p>This method may be invoked only from within {@code
* ForkJoinTask} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
*/
public final void quietlyHelpJoin() {
if (status >= 0) {
ForkJoinWorkerThread w =
(ForkJoinWorkerThread) Thread.currentThread();
if (!w.unpushTask(this) || !tryQuietlyInvoke())
busyJoin(w);
}
}
/**
* Joins this task, without returning its result or throwing an
* Joins this task, without returning its result or throwing its
* exception. This method may be useful when processing
* collections of tasks when some have been cancelled or otherwise
* known to have aborted.
*/
public final void quietlyJoin() {
if (status >= 0) {
ForkJoinWorkerThread w = getWorker();
if (w == null || !w.unpushTask(this) || !tryQuietlyInvoke())
awaitDone(w, true);
Thread t;
if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
if (status >= 0) {
if (w.unpushTask(this)) {
boolean completed;
try {
completed = exec();
} catch (Throwable rex) {
setExceptionalCompletion(rex);
return;
}
if (completed) {
setCompletion(NORMAL);
return;
}
}
w.joinTask(this);
}
}
else
externalAwaitDone();
}
/**
* Commences performing this task and awaits its completion if
* necessary, without returning its result or throwing an
* exception. This method may be useful when processing
* collections of tasks when some have been cancelled or otherwise
* known to have aborted.
* necessary, without returning its result or throwing its
* exception.
*/
public final void quietlyInvoke() {
if (status >= 0 && !tryQuietlyInvoke())
quietlyJoin();
if (status >= 0) {
boolean completed;
try {
completed = exec();
} catch (Throwable rex) {
setExceptionalCompletion(rex);
return;
}
if (completed)
setCompletion(NORMAL);
else
quietlyJoin();
}
}
/**
@ -956,7 +839,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
* pre-constructed trees of subtasks in loops.
*/
public void reinitialize() {
if ((status & COMPLETION_MASK) == EXCEPTIONAL)
if (status == EXCEPTIONAL)
exceptionMap.remove(this);
status = 0;
}
@ -1246,7 +1129,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
private static final long serialVersionUID = -7721805057305804111L;
/**
* Saves the state to a stream.
* Saves the state to a stream (that is, serializes it).
*
* @serialData the current run status and the exception thrown
* during execution, or {@code null} if none
@ -1259,18 +1142,16 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
}
/**
* Reconstitutes the instance from a stream.
* Reconstitutes the instance from a stream (that is, deserializes it).
*
* @param s the stream
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
status &= ~INTERNAL_SIGNAL_MASK; // clear internal signal counts
status |= EXTERNAL_SIGNAL; // conservatively set external signal
Object ex = s.readObject();
if (ex != null)
setDoneExceptionally((Throwable) ex);
setExceptionalCompletion((Throwable) ex);
}
// Unsafe mechanics

View File

@ -42,6 +42,7 @@ import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.concurrent.locks.LockSupport;
/**
* An unbounded {@link TransferQueue} based on linked nodes.
* This queue orders elements FIFO (first-in-first-out) with respect
@ -233,24 +234,6 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
* additional GC bookkeeping ("write barriers") that are sometimes
* more costly than the writes themselves because of contention).
*
* Removal of interior nodes (due to timed out or interrupted
* waits, or calls to remove(x) or Iterator.remove) can use a
* scheme roughly similar to that described in Scherer, Lea, and
* Scott's SynchronousQueue. Given a predecessor, we can unsplice
* any node except the (actual) tail of the queue. To avoid
* build-up of cancelled trailing nodes, upon a request to remove
* a trailing node, it is placed in field "cleanMe" to be
* unspliced upon the next call to unsplice any other node.
* Situations needing such mechanics are not common but do occur
* in practice; for example when an unbounded series of short
* timed calls to poll repeatedly time out but never otherwise
* fall off the list because of an untimed call to take at the
* front of the queue. Note that maintaining field cleanMe does
* not otherwise much impact garbage retention even if never
* cleared by some other call because the held node will
* eventually either directly or indirectly lead to a self-link
* once off the list.
*
* *** Overview of implementation ***
*
* We use a threshold-based approach to updates, with a slack
@ -266,15 +249,10 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
* per-thread one available, but even ThreadLocalRandom is too
* heavy for these purposes.
*
* With such a small slack threshold value, it is rarely
* worthwhile to augment this with path short-circuiting; i.e.,
* unsplicing nodes between head and the first unmatched node, or
* similarly for tail, rather than advancing head or tail
* proper. However, it is used (in awaitMatch) immediately before
* a waiting thread starts to block, as a final bit of helping at
* a point when contention with others is extremely unlikely
* (since if other threads that could release it are operating,
* then the current thread wouldn't be blocking).
* With such a small slack threshold value, it is not worthwhile
* to augment this with path short-circuiting (i.e., unsplicing
* interior nodes) except in the case of cancellation/removal (see
* below).
*
* We allow both the head and tail fields to be null before any
* nodes are enqueued; initializing upon first append. This
@ -356,6 +334,70 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
* versa) compared to their predecessors receive additional
* chained spins, reflecting longer paths typically required to
* unblock threads during phase changes.
*
*
* ** Unlinking removed interior nodes **
*
* In addition to minimizing garbage retention via self-linking
* described above, we also unlink removed interior nodes. These
* may arise due to timed out or interrupted waits, or calls to
* remove(x) or Iterator.remove. Normally, given a node that was
* at one time known to be the predecessor of some node s that is
* to be removed, we can unsplice s by CASing the next field of
* its predecessor if it still points to s (otherwise s must
* already have been removed or is now offlist). But there are two
* situations in which we cannot guarantee to make node s
* unreachable in this way: (1) If s is the trailing node of list
* (i.e., with null next), then it is pinned as the target node
* for appends, so can only be removed later after other nodes are
* appended. (2) We cannot necessarily unlink s given a
* predecessor node that is matched (including the case of being
* cancelled): the predecessor may already be unspliced, in which
* case some previous reachable node may still point to s.
* (For further explanation see Herlihy & Shavit "The Art of
* Multiprocessor Programming" chapter 9). Although, in both
* cases, we can rule out the need for further action if either s
* or its predecessor are (or can be made to be) at, or fall off
* from, the head of list.
*
* Without taking these into account, it would be possible for an
* unbounded number of supposedly removed nodes to remain
* reachable. Situations leading to such buildup are uncommon but
* can occur in practice; for example when a series of short timed
* calls to poll repeatedly time out but never otherwise fall off
* the list because of an untimed call to take at the front of the
* queue.
*
* When these cases arise, rather than always retraversing the
* entire list to find an actual predecessor to unlink (which
* won't help for case (1) anyway), we record a conservative
* estimate of possible unsplice failures (in "sweepVotes").
* We trigger a full sweep when the estimate exceeds a threshold
* ("SWEEP_THRESHOLD") indicating the maximum number of estimated
* removal failures to tolerate before sweeping through, unlinking
* cancelled nodes that were not unlinked upon initial removal.
* We perform sweeps by the thread hitting threshold (rather than
* background threads or by spreading work to other threads)
* because in the main contexts in which removal occurs, the
* caller is already timed-out, cancelled, or performing a
* potentially O(n) operation (e.g. remove(x)), none of which are
* time-critical enough to warrant the overhead that alternatives
* would impose on other threads.
*
* Because the sweepVotes estimate is conservative, and because
* nodes become unlinked "naturally" as they fall off the head of
* the queue, and because we allow votes to accumulate even while
* sweeps are in progress, there are typically significantly fewer
* such nodes than estimated. Choice of a threshold value
* balances the likelihood of wasted effort and contention, versus
* providing a worst-case bound on retention of interior nodes in
* quiescent queues. The value defined below was chosen
* empirically to balance these under various timeout scenarios.
*
* Note that we cannot self-link unlinked interior nodes during
* sweeps. However, the associated garbage chains terminate when
* some successor ultimately falls off the head of the list and is
* self-linked.
*/
/** True if on multiprocessor */
@ -381,12 +423,20 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
*/
private static final int CHAINED_SPINS = FRONT_SPINS >>> 1;
/**
* The maximum number of estimated removal failures (sweepVotes)
* to tolerate before sweeping through the queue unlinking
* cancelled nodes that were not unlinked upon initial
* removal. See above for explanation. The value must be at least
* two to avoid useless sweeps when removing trailing nodes.
*/
static final int SWEEP_THRESHOLD = 32;
/**
* Queue nodes. Uses Object, not E, for items to allow forgetting
* them after use. Relies heavily on Unsafe mechanics to minimize
* unnecessary ordering constraints: Writes that intrinsically
* precede or follow CASes use simple relaxed forms. Other
* cleanups use releasing/lazy writes.
* unnecessary ordering constraints: Writes that are intrinsically
* ordered wrt other accesses or CASes use simple relaxed forms.
*/
static final class Node {
final boolean isData; // false if this is a request node
@ -400,13 +450,13 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
}
final boolean casItem(Object cmp, Object val) {
// assert cmp == null || cmp.getClass() != Node.class;
// assert cmp == null || cmp.getClass() != Node.class;
return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
}
/**
* Creates a new node. Uses relaxed write because item can only
* be seen if followed by CAS.
* Constructs a new node. Uses relaxed write because item can
* only be seen after publication via casNext.
*/
Node(Object item, boolean isData) {
UNSAFE.putObject(this, itemOffset, item); // relaxed write
@ -422,13 +472,17 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
}
/**
* Sets item to self (using a releasing/lazy write) and waiter
* to null, to avoid garbage retention after extracting or
* cancelling.
* Sets item to self and waiter to null, to avoid garbage
* retention after matching or cancelling. Uses relaxed writes
* because order is already constrained in the only calling
* contexts: item is forgotten only after volatile/atomic
* mechanics that extract items. Similarly, clearing waiter
* follows either CAS or return from park (if ever parked;
* else we don't care).
*/
final void forgetContents() {
UNSAFE.putOrderedObject(this, itemOffset, this);
UNSAFE.putOrderedObject(this, waiterOffset, null);
UNSAFE.putObject(this, itemOffset, this);
UNSAFE.putObject(this, waiterOffset, null);
}
/**
@ -462,7 +516,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
* Tries to artificially match a data node -- used by remove.
*/
final boolean tryMatchData() {
// assert isData;
// assert isData;
Object x = item;
if (x != null && x != this && casItem(x, null)) {
LockSupport.unpark(waiter);
@ -486,12 +540,12 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
/** head of the queue; null until first enqueue */
transient volatile Node head;
/** predecessor of dangling unspliceable node */
private transient volatile Node cleanMe; // decl here reduces contention
/** tail of the queue; null until first append */
private transient volatile Node tail;
/** The number of apparent failures to unsplice removed nodes */
private transient volatile int sweepVotes;
// CAS methods for fields
private boolean casTail(Node cmp, Node val) {
return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
@ -501,8 +555,8 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
}
private boolean casCleanMe(Node cmp, Node val) {
return UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val);
private boolean casSweepVotes(int cmp, int val) {
return UNSAFE.compareAndSwapInt(this, sweepVotesOffset, cmp, val);
}
/*
@ -515,7 +569,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
@SuppressWarnings("unchecked")
static <E> E cast(Object item) {
// assert item == null || item.getClass() != Node.class;
// assert item == null || item.getClass() != Node.class;
return (E) item;
}
@ -544,10 +598,8 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
break;
if (p.casItem(item, e)) { // match
for (Node q = p; q != h;) {
Node n = q.next; // update head by 2
if (n != null) // unless singleton
q = n;
if (head == h && casHead(h, q)) {
Node n = q.next; // update by 2 unless singleton
if (head == h && casHead(h, n == null? q : n)) {
h.forgetNext();
break;
} // advance and retry
@ -632,12 +684,12 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
for (;;) {
Object item = s.item;
if (item != e) { // matched
// assert item != s;
// assert item != s;
s.forgetContents(); // avoid garbage
return this.<E>cast(item);
}
if ((w.isInterrupted() || (timed && nanos <= 0)) &&
s.casItem(e, s)) { // cancel
s.casItem(e, s)) { // cancel
unsplice(pred, s);
return e;
}
@ -647,9 +699,8 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
randomYields = ThreadLocalRandom.current();
}
else if (spins > 0) { // spin
if (--spins == 0)
shortenHeadPath(); // reduce slack before blocking
else if (randomYields.nextInt(CHAINED_SPINS) == 0)
--spins;
if (randomYields.nextInt(CHAINED_SPINS) == 0)
Thread.yield(); // occasionally yield
}
else if (s.waiter == null) {
@ -663,8 +714,6 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
}
else {
LockSupport.park(this);
s.waiter = null;
spins = -1; // spin if front upon wakeup
}
}
}
@ -685,27 +734,6 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
return 0;
}
/**
* Tries (once) to unsplice nodes between head and first unmatched
* or trailing node; failing on contention.
*/
private void shortenHeadPath() {
Node h, hn, p, q;
if ((p = h = head) != null && h.isMatched() &&
(q = hn = h.next) != null) {
Node n;
while ((n = q.next) != q) {
if (n == null || !q.isMatched()) {
if (hn != q && h.next == hn)
h.casNext(hn, q);
break;
}
p = q;
q = n;
}
}
}
/* -------------- Traversal methods -------------- */
/**
@ -818,7 +846,8 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
public final void remove() {
Node p = lastRet;
if (p == null) throw new IllegalStateException();
findAndRemoveDataNode(lastPred, p);
if (p.tryMatchData())
unsplice(lastPred, p);
}
}
@ -828,99 +857,68 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
* Unsplices (now or later) the given deleted/cancelled node with
* the given predecessor.
*
* @param pred predecessor of node to be unspliced
* @param pred a node that was at one time known to be the
* predecessor of s, or null or s itself if s is/was at head
* @param s the node to be unspliced
*/
private void unsplice(Node pred, Node s) {
s.forgetContents(); // clear unneeded fields
final void unsplice(Node pred, Node s) {
s.forgetContents(); // forget unneeded fields
/*
* At any given time, exactly one node on list cannot be
* unlinked -- the last inserted node. To accommodate this, if
* we cannot unlink s, we save its predecessor as "cleanMe",
* processing the previously saved version first. Because only
* one node in the list can have a null next, at least one of
* node s or the node previously saved can always be
* processed, so this always terminates.
* See above for rationale. Briefly: if pred still points to
* s, try to unlink s. If s cannot be unlinked, because it is
* trailing node or pred might be unlinked, and neither pred
* nor s are head or offlist, add to sweepVotes, and if enough
* votes have accumulated, sweep.
*/
if (pred != null && pred != s) {
while (pred.next == s) {
Node oldpred = (cleanMe == null) ? null : reclean();
Node n = s.next;
if (n != null) {
if (n != s)
pred.casNext(s, n);
break;
if (pred != null && pred != s && pred.next == s) {
Node n = s.next;
if (n == null ||
(n != s && pred.casNext(s, n) && pred.isMatched())) {
for (;;) { // check if at, or could be, head
Node h = head;
if (h == pred || h == s || h == null)
return; // at head or list empty
if (!h.isMatched())
break;
Node hn = h.next;
if (hn == null)
return; // now empty
if (hn != h && casHead(h, hn))
h.forgetNext(); // advance head
}
if (oldpred == pred || // Already saved
((oldpred == null || oldpred.next == s) &&
casCleanMe(oldpred, pred))) {
break;
if (pred.next != pred && s.next != s) { // recheck if offlist
for (;;) { // sweep now if enough votes
int v = sweepVotes;
if (v < SWEEP_THRESHOLD) {
if (casSweepVotes(v, v + 1))
break;
}
else if (casSweepVotes(v, 0)) {
sweep();
break;
}
}
}
}
}
}
/**
* Tries to unsplice the deleted/cancelled node held in cleanMe
* that was previously uncleanable because it was at tail.
*
* @return current cleanMe node (or null)
* Unlinks matched (typically cancelled) nodes encountered in a
* traversal from head.
*/
private Node reclean() {
/*
* cleanMe is, or at one time was, predecessor of a cancelled
* node s that was the tail so could not be unspliced. If it
* is no longer the tail, try to unsplice if necessary and
* make cleanMe slot available. This differs from similar
* code in unsplice() because we must check that pred still
* points to a matched node that can be unspliced -- if not,
* we can (must) clear cleanMe without unsplicing. This can
* loop only due to contention.
*/
Node pred;
while ((pred = cleanMe) != null) {
Node s = pred.next;
Node n;
if (s == null || s == pred || !s.isMatched())
casCleanMe(pred, null); // already gone
else if ((n = s.next) != null) {
if (n != s)
pred.casNext(s, n);
casCleanMe(pred, null);
}
else
private void sweep() {
for (Node p = head, s, n; p != null && (s = p.next) != null; ) {
if (!s.isMatched())
// Unmatched nodes are never self-linked
p = s;
else if ((n = s.next) == null) // trailing node is pinned
break;
}
return pred;
}
/**
* Main implementation of Iterator.remove(). Finds
* and unsplices the given data node.
*
* @param possiblePred possible predecessor of s
* @param s the node to remove
*/
final void findAndRemoveDataNode(Node possiblePred, Node s) {
// assert s.isData;
if (s.tryMatchData()) {
if (possiblePred != null && possiblePred.next == s)
unsplice(possiblePred, s); // was actual predecessor
else {
for (Node pred = null, p = head; p != null; ) {
if (p == s) {
unsplice(pred, p);
break;
}
if (p.isUnmatchedRequest())
break;
pred = p;
if ((p = p.next) == pred) { // stale
pred = null;
p = head;
}
}
}
else if (s == n) // stale
// No need to also check for p == s, since that implies s == n
p = head;
else
p.casNext(s, n);
}
}
@ -1158,7 +1156,11 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
* @return {@code true} if this queue contains no elements
*/
public boolean isEmpty() {
return firstOfMode(true) == null;
for (Node p = head; p != null; p = succ(p)) {
if (!p.isMatched())
return !p.isData;
}
return true;
}
public boolean hasWaitingConsumer() {
@ -1252,8 +1254,8 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
objectFieldOffset(UNSAFE, "head", LinkedTransferQueue.class);
private static final long tailOffset =
objectFieldOffset(UNSAFE, "tail", LinkedTransferQueue.class);
private static final long cleanMeOffset =
objectFieldOffset(UNSAFE, "cleanMe", LinkedTransferQueue.class);
private static final long sweepVotesOffset =
objectFieldOffset(UNSAFE, "sweepVotes", LinkedTransferQueue.class);
static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
String field, Class<?> klazz) {
@ -1266,5 +1268,4 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
throw error;
}
}
}

View File

@ -898,7 +898,7 @@ public class Phaser {
boolean doWait() {
if (thread != null) {
try {
ForkJoinPool.managedBlock(this, false);
ForkJoinPool.managedBlock(this);
} catch (InterruptedException ie) {
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, 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
@ -27,6 +27,8 @@ package javax.sql;
import java.sql.SQLException;
import java.io.PrintWriter;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
/**
* Interface that defines the methods which are common between <code>DataSource</code>,
@ -35,79 +37,93 @@ import java.io.PrintWriter;
*/
public interface CommonDataSource {
/**
* <p>Retrieves the log writer for this <code>DataSource</code>
* object.
*
* <p>The log writer is a character output stream to which all logging
* and tracing messages for this data source will be
* printed. This includes messages printed by the methods of this
* object, messages printed by methods of other objects manufactured
* by this object, and so on. Messages printed to a data source
* specific log writer are not printed to the log writer associated
* with the <code>java.sql.DriverManager</code> class. When a
* <code>DataSource</code> object is
* created, the log writer is initially null; in other words, the
* default is for logging to be disabled.
*
* @return the log writer for this data source or null if
* logging is disabled
* @exception java.sql.SQLException if a database access error occurs
* @see #setLogWriter
* @since 1.4
*/
java.io.PrintWriter getLogWriter() throws SQLException;
/**
* <p>Retrieves the log writer for this <code>DataSource</code>
* object.
*
* <p>The log writer is a character output stream to which all logging
* and tracing messages for this data source will be
* printed. This includes messages printed by the methods of this
* object, messages printed by methods of other objects manufactured
* by this object, and so on. Messages printed to a data source
* specific log writer are not printed to the log writer associated
* with the <code>java.sql.DriverManager</code> class. When a
* <code>DataSource</code> object is
* created, the log writer is initially null; in other words, the
* default is for logging to be disabled.
*
* @return the log writer for this data source or null if
* logging is disabled
* @exception java.sql.SQLException if a database access error occurs
* @see #setLogWriter
* @since 1.4
*/
java.io.PrintWriter getLogWriter() throws SQLException;
/**
* <p>Sets the log writer for this <code>DataSource</code>
* object to the given <code>java.io.PrintWriter</code> object.
*
* <p>The log writer is a character output stream to which all logging
* and tracing messages for this data source will be
* printed. This includes messages printed by the methods of this
* object, messages printed by methods of other objects manufactured
* by this object, and so on. Messages printed to a data source-
* specific log writer are not printed to the log writer associated
* with the <code>java.sql.DriverManager</code> class. When a
* <code>DataSource</code> object is created the log writer is
* initially null; in other words, the default is for logging to be
* disabled.
*
* @param out the new log writer; to disable logging, set to null
* @exception SQLException if a database access error occurs
* @see #getLogWriter
* @since 1.4
*/
void setLogWriter(java.io.PrintWriter out) throws SQLException;
/**
* <p>Sets the log writer for this <code>DataSource</code>
* object to the given <code>java.io.PrintWriter</code> object.
*
* <p>The log writer is a character output stream to which all logging
* and tracing messages for this data source will be
* printed. This includes messages printed by the methods of this
* object, messages printed by methods of other objects manufactured
* by this object, and so on. Messages printed to a data source-
* specific log writer are not printed to the log writer associated
* with the <code>java.sql.DriverManager</code> class. When a
* <code>DataSource</code> object is created the log writer is
* initially null; in other words, the default is for logging to be
* disabled.
*
* @param out the new log writer; to disable logging, set to null
* @exception SQLException if a database access error occurs
* @see #getLogWriter
* @since 1.4
*/
void setLogWriter(java.io.PrintWriter out) throws SQLException;
/**
* <p>Sets the maximum time in seconds that this data source will wait
* while attempting to connect to a database. A value of zero
* specifies that the timeout is the default system timeout
* if there is one; otherwise, it specifies that there is no timeout.
* When a <code>DataSource</code> object is created, the login timeout is
* initially zero.
*
* @param seconds the data source login time limit
* @exception SQLException if a database access error occurs.
* @see #getLoginTimeout
* @since 1.4
*/
void setLoginTimeout(int seconds) throws SQLException;
/**
* <p>Sets the maximum time in seconds that this data source will wait
* while attempting to connect to a database. A value of zero
* specifies that the timeout is the default system timeout
* if there is one; otherwise, it specifies that there is no timeout.
* When a <code>DataSource</code> object is created, the login timeout is
* initially zero.
*
* @param seconds the data source login time limit
* @exception SQLException if a database access error occurs.
* @see #getLoginTimeout
* @since 1.4
*/
void setLoginTimeout(int seconds) throws SQLException;
/**
* Gets the maximum time in seconds that this data source can wait
* while attempting to connect to a database. A value of zero
* means that the timeout is the default system timeout
* if there is one; otherwise, it means that there is no timeout.
* When a <code>DataSource</code> object is created, the login timeout is
* initially zero.
*
* @return the data source login time limit
* @exception SQLException if a database access error occurs.
* @see #setLoginTimeout
* @since 1.4
*/
int getLoginTimeout() throws SQLException;
/**
* Gets the maximum time in seconds that this data source can wait
* while attempting to connect to a database. A value of zero
* means that the timeout is the default system timeout
* if there is one; otherwise, it means that there is no timeout.
* When a <code>DataSource</code> object is created, the login timeout is
* initially zero.
*
* @return the data source login time limit
* @exception SQLException if a database access error occurs.
* @see #setLoginTimeout
* @since 1.4
*/
int getLoginTimeout() throws SQLException;
//------------------------- JDBC 4.1 -----------------------------------
/**
* Return the parent Logger of all the Loggers used by this data source. This
* should be the Logger farthest from the root Logger that is
* still an ancestor of all of the Loggers used by this data source. Configuring
* this Logger will affect all of the log messages generated by the data source.
* In the worst case, this may be the root Logger.
*
* @return the parent Logger for this data source
* @throws SQLFeatureNotSupportedException if the data source does not use <code>java.util.logging<code>.
* @since 1.7
*/
public Logger getParentLogger() throws SQLFeatureNotSupportedException;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -644,10 +644,10 @@ public interface CachedRowSet extends RowSet, Joinable {
* of <code>execute</code> that takes a <code>ResultSet</code> object.
*
* @param data the <code>ResultSet</code> object containing the data
* to be read into this <code>CachedRowSet</code> object
* to be read into this <code>CachedRowSet</code> object
* @throws SQLException if a null <code>ResultSet</code> object is supplied
* or this <code>CachedRowSet</code> object cannot
* retrieve the associated <code>ResultSetMetaData</code> object
* or this <code>CachedRowSet</code> object cannot
* retrieve the associated <code>ResultSetMetaData</code> object
* @see #execute
* @see java.sql.ResultSet
* @see java.sql.ResultSetMetaData
@ -674,10 +674,10 @@ public interface CachedRowSet extends RowSet, Joinable {
* to commit outstanding updates, those updates are lost.
*
* @param conn a standard JDBC <code>Connection</code> object with valid
* properties
* properties
* @throws SQLException if an invalid <code>Connection</code> object is supplied
* or an error occurs in establishing the connection to the
* data source
* or an error occurs in establishing the connection to the
* data source
* @see #populate
* @see java.sql.Connection
*/
@ -736,8 +736,8 @@ public interface CachedRowSet extends RowSet, Joinable {
*
* @throws SQLException if the cursor is on the insert row
* @throws SyncProviderException if the underlying
* synchronization provider's writer fails to write the updates
* back to the data source
* synchronization provider's writer fails to write the updates
* back to the data source
* @see #acceptChanges(java.sql.Connection)
* @see javax.sql.RowSetWriter
* @see javax.sql.rowset.spi.SyncFactory
@ -807,8 +807,8 @@ public interface CachedRowSet extends RowSet, Joinable {
* @param con a standard JDBC <code>Connection</code> object
* @throws SQLException if the cursor is on the insert row
* @throws SyncProviderException if the underlying
* synchronization provider's writer fails to write the updates
* back to the data source
* synchronization provider's writer fails to write the updates
* back to the data source
* @see #acceptChanges()
* @see javax.sql.RowSetWriter
* @see javax.sql.rowset.spi.SyncFactory
@ -867,7 +867,7 @@ public interface CachedRowSet extends RowSet, Joinable {
* the rowset's Java VM resources.
*
* @throws SQLException if an error occurs flushing the contents of this
* <code>CachedRowSet</code> object
* <code>CachedRowSet</code> object
* @see javax.sql.RowSetListener#rowSetChanged
* @see java.sql.ResultSet#close
*/
@ -948,9 +948,9 @@ public interface CachedRowSet extends RowSet, Joinable {
*
* @param idx an <code>int</code> identifying the column to be checked for updates
* @return <code>true</code> if the designated column has been visibly updated;
* <code>false</code> otherwise
* <code>false</code> otherwise
* @throws SQLException if the cursor is on the insert row, before the first row,
* or after the last row
* or after the last row
* @see java.sql.DatabaseMetaData#updatesAreDetected
*/
public boolean columnUpdated(int idx) throws SQLException;
@ -963,9 +963,9 @@ public interface CachedRowSet extends RowSet, Joinable {
* @param columnName a <code>String</code> object giving the name of the
* column to be checked for updates
* @return <code>true</code> if the column has been visibly updated;
* <code>false</code> otherwise
* <code>false</code> otherwise
* @throws SQLException if the cursor is on the insert row, before the first row,
* or after the last row
* or after the last row
* @see java.sql.DatabaseMetaData#updatesAreDetected
*/
public boolean columnUpdated(String columnName) throws SQLException;
@ -1003,7 +1003,7 @@ public interface CachedRowSet extends RowSet, Joinable {
* <P>
*
* @return a <code>Collection</code> object that contains the values in
* each row in this <code>CachedRowSet</code> object
* each row in this <code>CachedRowSet</code> object
* @throws SQLException if an error occurs generating the collection
* @see #toCollection(int)
* @see #toCollection(String)
@ -1030,10 +1030,10 @@ public interface CachedRowSet extends RowSet, Joinable {
* @param column an <code>int</code> indicating the column whose values
* are to be represented in a <code>Collection</code> object
* @return a <code>Collection</code> object that contains the values
* stored in the specified column of this <code>CachedRowSet</code>
* object
* stored in the specified column of this <code>CachedRowSet</code>
* object
* @throws SQLException if an error occurs generating the collection or
* an invalid column id is provided
* an invalid column id is provided
* @see #toCollection
* @see #toCollection(String)
*/
@ -1059,10 +1059,10 @@ public interface CachedRowSet extends RowSet, Joinable {
* @param column a <code>String</code> object giving the name of the
* column whose values are to be represented in a collection
* @return a <code>Collection</code> object that contains the values
* stored in the specified column of this <code>CachedRowSet</code>
* object
* stored in the specified column of this <code>CachedRowSet</code>
* object
* @throws SQLException if an error occurs generating the collection or
* an invalid column id is provided
* an invalid column id is provided
* @see #toCollection
* @see #toCollection(int)
*/
@ -1100,7 +1100,7 @@ public interface CachedRowSet extends RowSet, Joinable {
* @return the <code>SyncProvider</code> object that was set when the rowset
* was instantiated, or if none was was set, the default provider
* @throws SQLException if an error occurs while returning the
* <code>SyncProvider</code> object
* <code>SyncProvider</code> object
* @see #setSyncProvider
*/
public SyncProvider getSyncProvider() throws SQLException;
@ -1127,7 +1127,7 @@ public interface CachedRowSet extends RowSet, Joinable {
* @param provider a <code>String</code> object giving the fully qualified class
* name of a <code>SyncProvider</code> implementation
* @throws SQLException if an error occurs while attempting to reset the
* <code>SyncProvider</code> implementation
* <code>SyncProvider</code> implementation
* @see #getSyncProvider
*/
public void setSyncProvider(String provider) throws SQLException;
@ -1152,9 +1152,9 @@ public interface CachedRowSet extends RowSet, Joinable {
* object to the rowset.
*
* @param md a <code>RowSetMetaData</code> object containing
* metadata about the columns in this <code>CachedRowSet</code> object
* metadata about the columns in this <code>CachedRowSet</code> object
* @throws SQLException if invalid metadata is supplied to the
* rowset
* rowset
*/
public void setMetaData(RowSetMetaData md) throws SQLException;
@ -1183,7 +1183,7 @@ public interface CachedRowSet extends RowSet, Joinable {
* @return a <code>ResultSet</code> object that contains the original value for
* this <code>CachedRowSet</code> object
* @throws SQLException if an error occurs producing the
* <code>ResultSet</code> object
* <code>ResultSet</code> object
*/
public ResultSet getOriginal() throws SQLException;
@ -1217,7 +1217,7 @@ public interface CachedRowSet extends RowSet, Joinable {
* A call to <code>setOriginalRow</code> is irreversible.
*
* @throws SQLException if there is no current row or an error is
* encountered resetting the contents of the original row
* encountered resetting the contents of the original row
* @see #getOriginalRow
*/
public void setOriginalRow() throws SQLException;
@ -1326,7 +1326,7 @@ public interface CachedRowSet extends RowSet, Joinable {
* as this <code>CachedRowSet</code> object and that has a cursor over
* the same data
* @throws SQLException if an error occurs or cloning is not
* supported in the underlying platform
* supported in the underlying platform
* @see javax.sql.RowSetEvent
* @see javax.sql.RowSetListener
*/
@ -1344,10 +1344,10 @@ public interface CachedRowSet extends RowSet, Joinable {
* established must be maintained.
*
* @return a new <code>RowSet</code> object that is a deep copy
* of this <code>CachedRowSet</code> object and is
* completely independent of this <code>CachedRowSet</code> object
* of this <code>CachedRowSet</code> object and is
* completely independent of this <code>CachedRowSet</code> object
* @throws SQLException if an error occurs in generating the copy of
* the of this <code>CachedRowSet</code> object
* the of this <code>CachedRowSet</code> object
* @see #createShared
* @see #createCopySchema
* @see #createCopyNoConstraints
@ -1396,10 +1396,10 @@ public interface CachedRowSet extends RowSet, Joinable {
* in the copy.
*
* @return a new <code>CachedRowSet</code> object that is a deep copy
* of this <code>CachedRowSet</code> object and is
* completely independent of this <code>CachedRowSet</code> object
* of this <code>CachedRowSet</code> object and is
* completely independent of this <code>CachedRowSet</code> object
* @throws SQLException if an error occurs in generating the copy of
* the of this <code>CachedRowSet</code> object
* the of this <code>CachedRowSet</code> object
* @see #createCopy
* @see #createShared
* @see #createCopySchema
@ -1445,7 +1445,7 @@ public interface CachedRowSet extends RowSet, Joinable {
* @return <code>true</code> if deleted rows are visible;
* <code>false</code> otherwise
* @throws SQLException if a rowset implementation is unable to
* to determine whether rows marked for deletion are visible
* to determine whether rows marked for deletion are visible
* @see #setShowDeleted
*/
public boolean getShowDeleted() throws SQLException;
@ -1467,7 +1467,7 @@ public interface CachedRowSet extends RowSet, Joinable {
* @param b <code>true</code> if deleted rows should be shown;
* <code>false</code> otherwise
* @exception SQLException if a rowset implementation is unable to
* to reset whether deleted rows should be visible
* to reset whether deleted rows should be visible
* @see #getShowDeleted
*/
public void setShowDeleted(boolean b) throws SQLException;
@ -1523,9 +1523,12 @@ public interface CachedRowSet extends RowSet, Joinable {
* set to false, the changes will <b>not</b> be committed until one of the
* <code>CachedRowSet</code> interface transaction methods is called.
*
* @deprecated Because this field is final (it is part of an interface),
* its value cannot be changed.
* @see #commit
* @see #rollback
*/
@Deprecated
public static final boolean COMMIT_ON_ACCEPT_CHANGES = true;
/**
@ -1562,10 +1565,10 @@ public interface CachedRowSet extends RowSet, Joinable {
* @param startRow the position in the <code>ResultSet</code> from where to start
* populating the records in this <code>CachedRowSet</code>
* @param rs the <code>ResultSet</code> object containing the data
* to be read into this <code>CachedRowSet</code> object
* to be read into this <code>CachedRowSet</code> object
* @throws SQLException if a null <code>ResultSet</code> object is supplied
* or this <code>CachedRowSet</code> object cannot
* retrieve the associated <code>ResultSetMetaData</code> object
* or this <code>CachedRowSet</code> object cannot
* retrieve the associated <code>ResultSetMetaData</code> object
* @see #execute
* @see #populate(ResultSet)
* @see java.sql.ResultSet
@ -1620,3 +1623,4 @@ public interface CachedRowSet extends RowSet, Joinable {
public boolean previousPage() throws SQLException;
}

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2010, 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 javax.sql.rowset;
import java.sql.SQLException;
/**
* An interface that defines the implementation of a factory that is used
* to obtain different types of {@code RowSet} implementations.
*
* @author Lance Andersen
* @since 1.7
*/
public interface RowSetFactory{
/**
* <p>Creates a new instance of a CachedRowSet.</p>
*
* @return A new instance of a CachedRowSet.
*
* @throws SQLException if a CachedRowSet cannot
* be created.
*
* @since 1.7
*/
public CachedRowSet createCachedRowSet() throws SQLException;
/**
* <p>Creates a new instance of a FilteredRowSet.</p>
*
* @return A new instance of a FilteredRowSet.
*
* @throws SQLException if a FilteredRowSet cannot
* be created.
*
* @since 1.7
*/
public FilteredRowSet createFilteredRowSet() throws SQLException;
/**
* <p>Creates a new instance of a JdbcRowSet.</p>
*
* @return A new instance of a JdbcRowSet.
*
* @throws SQLException if a JdbcRowSet cannot
* be created.
*
* @since 1.7
*/
public JdbcRowSet createJdbcRowSet() throws SQLException;
/**
* <p>Creates a new instance of a JoinRowSet.</p>
*
* @return A new instance of a JoinRowSet.
*
* @throws SQLException if a JoinRowSet cannot
* be created.
*
* @since 1.7
*/
public JoinRowSet createJoinRowSet() throws SQLException;
/**
* <p>Creates a new instance of a WebRowSet.</p>
*
* @return A new instance of a WebRowSet.
*
* @throws SQLException if a WebRowSet cannot
* be created.
*
* @since 1.7
*/
public WebRowSet createWebRowSet() throws SQLException;
}

View File

@ -0,0 +1,305 @@
/*
* Copyright (c) 2010, 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 javax.sql.rowset;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.sql.SQLException;
import java.util.ServiceLoader;
import javax.sql.rowset.RowSetFactory;
/**
* A factory API that enables applications to obtain a
* {@code RowSetFactory} implementation that can be used to create different
* types of {@code RowSet} implementations.
* <p>
* Example:
* </p>
* <pre>
* RowSetFactory aFactory = RowSetProvider.newFactory();
* CachedRowSet crs = aFactory.createCachedRowSet();
* ...
* RowSetFactory rsf = RowSetProvider.newFactory("com.sun.rowset.RowSetFactoryImpl", null);
* WebRowSet wrs = rsf.createWebRowSet();
* </pre>
*<p>
* Tracing of this class may be enabled by setting the System property
* {@code javax.sql.rowset.RowSetFactory.debug} to any value but {@code false}.
* </p>
*
* @author Lance Andersen
* @since 1.7
*/
public class RowSetProvider {
private static final String ROWSET_DEBUG_PROPERTY = "javax.sql.rowset.RowSetProvider.debug";
private static final String ROWSET_FACTORY_IMPL = "com.sun.rowset.RowSetFactoryImpl";
private static final String ROWSET_FACTORY_NAME = "javax.sql.rowset.RowSetFactory";
/**
* Internal debug flag.
*/
private static boolean debug = true;
static {
// Check to see if the debug property is set
String val = getSystemProperty(ROWSET_DEBUG_PROPERTY);
// Allow simply setting the prop to turn on debug
debug = val != null && !"false".equals(val);
}
protected RowSetProvider () {
}
/**
* <p>Creates a new instance of a <code>RowSetFactory</code>
* implementation. This method uses the following
* look up order to determine
* the <code>RowSetFactory</code> implementation class to load:</p>
* <ul>
* <li>
* The System property {@code javax.sql.rowset.RowsetFactory}. For example:
* <ul>
* <li>
* -Djavax.sql.rowset.RowsetFactory=com.sun.rowset.RowSetFactoryImpl
* </li>
* </ul>
* <li>
* The ServiceLocator API. The ServiceLocator API will look
* for a classname in the file
* {@code META-INF/services/javax.sql.rowset.RowSetFactory}
* in jars available to the runtime. For example, to have the the RowSetFactory
* implementation {@code com.sun.rowset.RowSetFactoryImpl } loaded, the
* entry in {@code META-INF/services/javax.sql.rowset.RowSetFactory} would be:
* <ul>
* <li>
* {@code com.sun.rowset.RowSetFactoryImpl }
* </li>
* </ul>
* </li>
* <li>
* Platform default <code>RowSetFactory</code> instance.
* </li>
* </ul>
*
* <p>Once an application has obtained a reference to a {@code RowSetFactory},
* it can use the factory to obtain RowSet instances.</p>
*
* @return New instance of a <code>RowSetFactory</code>
*
* @throws SQLException if the default factory class cannot be loaded,
* instantiated. The cause will be set to actual Exception
*
* @see ServiceLoader
* @since 1.7
*/
public static RowSetFactory newFactory()
throws SQLException {
// Use the system property first
RowSetFactory factory = null;
String factoryClassName = null;
try {
trace("Checking for Rowset System Property...");
factoryClassName = getSystemProperty(ROWSET_FACTORY_NAME);
if (factoryClassName != null) {
trace("Found system property, value=" + factoryClassName);
factory = (RowSetFactory) getFactoryClass(factoryClassName, null, true).newInstance();
}
} catch (ClassNotFoundException e) {
throw new SQLException(
"RowSetFactory: " + factoryClassName + " not found", e);
} catch (Exception e) {
throw new SQLException(
"RowSetFactory: " + factoryClassName + " could not be instantiated: " + e,
e);
}
// Check to see if we found the RowSetFactory via a System property
if (factory == null) {
// If the RowSetFactory is not found via a System Property, now
// look it up via the ServiceLoader API and if not found, use the
// Java SE default.
factory = loadViaServiceLoader();
factory =
factory == null ? newFactory(ROWSET_FACTORY_IMPL, null) : factory;
}
return (factory);
}
/**
* <p>Creates a new instance of a <code>RowSetFactory</code> from the
* specified factory class name.
* This function is useful when there are multiple providers in the classpath.
* It gives more control to the application as it can specify which provider
* should be loaded.</p>
*
* <p>Once an application has obtained a reference to a <code>RowSetFactory</code>
* it can use the factory to obtain RowSet instances.</p>
*
* @param factoryClassName fully qualified factory class name that
* provides an implementation of <code>javax.sql.rowset.RowSetFactory</code>.
*
* @param cl <code>ClassLoader</code> used to load the factory
* class. If <code>null</code> current <code>Thread</code>'s context
* classLoader is used to load the factory class.
*
* @return New instance of a <code>RowSetFactory</code>
*
* @throws SQLException if <code>factoryClassName</code> is
* <code>null</code>, or the factory class cannot be loaded, instantiated.
*
* @see #newFactory()
*
* @since 1.7
*/
public static RowSetFactory newFactory(String factoryClassName, ClassLoader cl)
throws SQLException {
trace("***In newInstance()");
try {
Class providerClass = getFactoryClass(factoryClassName, cl, false);
RowSetFactory instance = (RowSetFactory) providerClass.newInstance();
if (debug) {
trace("Created new instance of " + providerClass +
" using ClassLoader: " + cl);
}
return instance;
} catch (ClassNotFoundException x) {
throw new SQLException(
"Provider " + factoryClassName + " not found", x);
} catch (Exception x) {
throw new SQLException(
"Provider " + factoryClassName + " could not be instantiated: " + x,
x);
}
}
/*
* Returns the class loader to be used.
* @return The ClassLoader to use.
*
*/
static private ClassLoader getContextClassLoader() throws SecurityException {
return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
ClassLoader cl = null;
cl = Thread.currentThread().getContextClassLoader();
if (cl == null) {
cl = ClassLoader.getSystemClassLoader();
}
return cl;
}
});
}
/**
* Attempt to load a class using the class loader supplied. If that fails
* and fall back is enabled, the current (i.e. bootstrap) class loader is
* tried.
*
* If the class loader supplied is <code>null</code>, first try using the
* context class loader followed by the current class loader.
* @return The class which was loaded
*/
static private Class getFactoryClass(String factoryClassName, ClassLoader cl,
boolean doFallback) throws ClassNotFoundException {
try {
if (cl == null) {
cl = getContextClassLoader();
if (cl == null) {
throw new ClassNotFoundException();
} else {
return cl.loadClass(factoryClassName);
}
} else {
return cl.loadClass(factoryClassName);
}
} catch (ClassNotFoundException e) {
if (doFallback) {
// Use current class loader
return Class.forName(factoryClassName, true, RowSetFactory.class.getClassLoader());
} else {
throw e;
}
}
}
/**
* Use the ServiceLoader mechanism to load the default RowSetFactory
* @return default RowSetFactory Implementation
*/
static private RowSetFactory loadViaServiceLoader() {
RowSetFactory theFactory = null;
trace("***in loadViaServiceLoader()");
for (RowSetFactory factory : ServiceLoader.load(javax.sql.rowset.RowSetFactory.class)) {
trace(" Loading done by the java.util.ServiceLoader :" + factory.getClass().getName());
theFactory = factory;
break;
}
return theFactory;
}
/**
* Returns the requested System Property. If a {@code SecurityException}
* occurs, just return NULL
* @param propName - System property to retreive
* @return The System property value or NULL if the property does not exist
* or a {@code SecurityException} occurs.
*/
static private String getSystemProperty(final String propName) {
String property = null;
try {
property = (String) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return System.getProperty(propName);
}
});
} catch (SecurityException se) {
if (debug) {
se.printStackTrace();
}
}
return property;
}
/**
* Debug routine which will output tracing if the System Property
* -Djavax.sql.rowset.RowSetFactory.debug is set
* @param msg - The debug message to display
*/
private static void trace(String msg) {
if (debug) {
System.err.println("###RowSets: " + msg);
}
}
}

View File

@ -5,7 +5,7 @@
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<!--
Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2003, 2010, 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
@ -78,7 +78,7 @@ object provides a fully updatable and scrollable tabular
data structure as defined in the JDBC 3.0 specification.
<p>
<li><a href="CachedRowSet.html">
<b><code>CachedRowSet</code><sup><font size=-2>TM></font></sup</b></a>
<b><code>CachedRowSet</code>&trade;</b></a>
- A <tt>CachedRowSet</tt> object is a JavaBeans<sup><font size=-2>TM</font></sup>
component that is scrollable, updatable, serializable, and generally disconnected from
the source of its data. A <tt>CachedRowSet</tt> object
@ -148,7 +148,12 @@ href="spi/package-summary.html">javax.sql.rowset.spi</a> package for guidelines
on <a href="spi/SyncProvider.html"><code>SyncProvider</code></a> implementations.
<p>
<ul>
<li><b>3.1 Role of the <code>BaseRowSet</code> Class</b>
<li><b>3.1 Constructor</b>
<p>
All <code>RowSet</code> implementations <strong>must</strong> provide a
no-argument constructor.
</li>
<li><b>3.2 Role of the <code>BaseRowSet</code> Class</b>
<p>
A compliant JDBC <code>RowSet</code> implementation <b>must</b> implement one or more
standard interfaces specified in this package and and <b>may</b> extend the
@ -215,7 +220,7 @@ by compliant implementations.<br>
</table>
</blockquote>
<p>
<li><b>3.2 Connected RowSet Requirements</b>
<li><b>3.3 Connected RowSet Requirements</b>
<p>
The <code>JdbcRowSet</code> describes a <code>RowSet</code> object that <b>must</b> always
be connected to the originating data source. Implementations of the <code>JdbcRowSet</code>
@ -229,7 +234,7 @@ supply their needs by virtue of the presence of an underlying updatable and scro
<p>
<li>
<b>3.3 Disconnected RowSet Requirements</b>
<b>3.4 Disconnected RowSet Requirements</b>
<p>
A disconnected <code>RowSet</code> object, such as a <code>CachedRowSet</code> object,
<b>should</b> delegate
@ -244,7 +249,7 @@ synchronization is required. A disconnected <code>RowSet</code> object should
therefore ensure that no
extraneous references remain on the <code>Connection</code> object.
<p>
<li><b>3.4 Role of RowSetMetaDataImpl</b>
<li><b>3.5 Role of RowSetMetaDataImpl</b>
<p>
The <code>RowsetMetaDataImpl</code> class is a utility class that provides an implementation of the
<a href="../RowSetMetaData.html">RowSetMetaData</a> interface, supplying standard setter
@ -252,7 +257,7 @@ method implementations for metadata for both connected and disconnected
<code>RowSet</code> objects. All implementations are free to use this standard
implementation but are not required to do so.
<p>
<li><b>3.5 RowSetWarning Class</b>
<li><b>3.6 RowSetWarning Class</b>
<p>
The <code>RowSetWarning</code> class provides warnings that can be set
on <code>RowSet</code> implementations.
@ -270,7 +275,7 @@ on it, and so on until there are no more warnings.
<P>
<li><b>3.6 The Joinable Interface</b>
<li><b>3.7 The Joinable Interface</b>
<P>
The <code>Joinable</code> interface provides both connected and disconnected
<code>RowSet</code> objects with the capability to be added to a
@ -278,7 +283,14 @@ The <code>Joinable</code> interface provides both connected and disconnected
A <code>RowSet</code> object that has implemented the <code>Joinable</code>
interface can set a match column, retrieve a match column, or unset a match column.
A <code>JoinRowSet</code> object can then use the <code>RowSet</code> object's
match column as a basis for adding the <code>RowSet</code> object.
match column as a basis for adding the <code>RowSet</code> object.
</li>
<li><b>3.8 The RowSetFactory Interface</b>
<p>
A <code>RowSetFactory</code> implementation <strong>must</strong>
be provided.
</li>
</ul>
<h3><a name="relspec">4.0 Related Specifications</a></h3>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -25,13 +25,6 @@
package javax.sql.rowset.spi;
import java.util.Map;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Vector;
import java.util.Properties;
import java.util.Collection;
import java.util.StringTokenizer;
import java.util.logging.*;
import java.util.*;
@ -216,68 +209,64 @@ public class SyncFactory {
* Having a private constructor guarantees that no more than
* one <code>SyncProvider</code> object can exist at a time.
*/
private SyncFactory() {};
private SyncFactory() {
}
/**
* The standard property-id for a synchronization provider implementation
* name.
*/
public static String ROWSET_SYNC_PROVIDER =
"rowset.provider.classname";
public static final String ROWSET_SYNC_PROVIDER =
"rowset.provider.classname";
/**
* The standard property-id for a synchronization provider implementation
* vendor name.
*/
public static String ROWSET_SYNC_VENDOR =
"rowset.provider.vendor";
public static final String ROWSET_SYNC_VENDOR =
"rowset.provider.vendor";
/**
* The standard property-id for a synchronization provider implementation
* version tag.
*/
public static String ROWSET_SYNC_PROVIDER_VERSION =
"rowset.provider.version";
public static final String ROWSET_SYNC_PROVIDER_VERSION =
"rowset.provider.version";
/**
* The standard resource file name.
*/
private static String ROWSET_PROPERTIES = "rowset.properties";
/**
* The RI Optimistic Provider.
*/
private static String default_provider =
"com.sun.rowset.providers.RIOptimisticProvider";
"com.sun.rowset.providers.RIOptimisticProvider";
/**
* Permission required to invoke setJNDIContext and setLogger
*/
private static final SQLPermission SET_SYNCFACTORY_PERMISSION =
new SQLPermission("setSyncFactory");
/**
* The initial JNDI context where <code>SyncProvider</code> implementations can
* be stored and from which they can be invoked.
*/
private static Context ic;
/**
* The <code>Logger</code> object to be used by the <code>SyncFactory</code>.
*/
private static Logger rsLogger;
/**
*
*/
private static Level rsLevel;
/**
* The registry of available <code>SyncProvider</code> implementations.
* See section 2.0 of the class comment for <code>SyncFactory</code> for an
* explanation of how a provider can be added to this registry.
*/
private static Hashtable implementations;
/**
* Internal sync object used to maintain the SPI as a singleton
*/
private static Object logSync = new Object();
/**
* Internal PrintWriter field for logging facility
*/
@ -311,7 +300,7 @@ public class SyncFactory {
* @see #setJNDIContext
*/
public static synchronized void registerProvider(String providerID)
throws SyncFactoryException {
throws SyncFactoryException {
ProviderImpl impl = new ProviderImpl();
impl.setClassname(providerID);
@ -325,29 +314,29 @@ public class SyncFactory {
*
* @return the <code>SyncFactory</code> instance
*/
public static SyncFactory getSyncFactory(){
public static SyncFactory getSyncFactory() {
// This method uses the Singleton Design Pattern
// with Double-Checked Locking Pattern for
// 1. Creating single instance of the SyncFactory
// 2. Make the class thread safe, so that at one time
// only one thread enters the synchronized block
// to instantiate.
// This method uses the Singleton Design Pattern
// with Double-Checked Locking Pattern for
// 1. Creating single instance of the SyncFactory
// 2. Make the class thread safe, so that at one time
// only one thread enters the synchronized block
// to instantiate.
// if syncFactory object is already there
// don't go into synchronized block and return
// that object.
// else go into synchronized block
// if syncFactory object is already there
// don't go into synchronized block and return
// that object.
// else go into synchronized block
if(syncFactory == null){
synchronized(SyncFactory.class) {
if(syncFactory == null){
if (syncFactory == null) {
synchronized (SyncFactory.class) {
if (syncFactory == null) {
syncFactory = new SyncFactory();
} //end if
} //end synchronized block
} //end if
return syncFactory;
}
} //end synchronized block
} //end if
return syncFactory;
}
/**
* Removes the designated currently registered synchronization provider from the
@ -358,13 +347,12 @@ public class SyncFactory {
* unregister a SyncProvider implementation that was not registered.
*/
public static synchronized void unregisterProvider(String providerID)
throws SyncFactoryException {
throws SyncFactoryException {
initMapIfNecessary();
if (implementations.containsKey(providerID)) {
implementations.remove(providerID);
}
}
private static String colon = ":";
private static String strFileSep = "/";
@ -395,7 +383,7 @@ public class SyncFactory {
* Dependent on application
*/
String strRowsetProperties = System.getProperty("rowset.properties");
if ( strRowsetProperties != null) {
if (strRowsetProperties != null) {
// Load user's implementation of SyncProvider
// here. -Drowset.properties=/abc/def/pqr.txt
ROWSET_PROPERTIES = strRowsetProperties;
@ -407,8 +395,8 @@ public class SyncFactory {
* Always available
*/
ROWSET_PROPERTIES = "javax" + strFileSep + "sql" +
strFileSep + "rowset" + strFileSep +
"rowset.properties";
strFileSep + "rowset" + strFileSep +
"rowset.properties";
// properties.load(
// ClassLoader.getSystemResourceAsStream(ROWSET_PROPERTIES));
@ -417,7 +405,7 @@ public class SyncFactory {
properties.load(cl.getResourceAsStream(ROWSET_PROPERTIES));
parseProperties(properties);
// removed else, has properties should sum together
// removed else, has properties should sum together
} catch (FileNotFoundException e) {
throw new SyncFactoryException("Cannot locate properties file: " + e);
@ -447,18 +435,15 @@ public class SyncFactory {
}
}
}
/**
* The internal boolean switch that indicates whether a JNDI
* context has been established or not.
*/
private static boolean jndiCtxEstablished = false;
/**
* The internal debug switch.
*/
private static boolean debug = false;
/**
* Internal registry count for the number of providers contained in the
* registry.
@ -475,9 +460,9 @@ public class SyncFactory {
String key = null;
String[] propertyNames = null;
for (Enumeration e = p.propertyNames(); e.hasMoreElements() ;) {
for (Enumeration e = p.propertyNames(); e.hasMoreElements();) {
String str = (String)e.nextElement();
String str = (String) e.nextElement();
int w = str.length();
@ -491,7 +476,7 @@ public class SyncFactory {
propertyNames = getPropertyNames(false);
} else {
// property index has been set.
propertyNames = getPropertyNames(true, str.substring(w-1));
propertyNames = getPropertyNames(true, str.substring(w - 1));
}
key = p.getProperty(propertyNames[0]);
@ -515,17 +500,17 @@ public class SyncFactory {
* overloaded property names that contain indexes.
*/
private static String[] getPropertyNames(boolean append,
String propertyIndex) {
String propertyIndex) {
String dot = ".";
String[] propertyNames =
new String[] {SyncFactory.ROWSET_SYNC_PROVIDER,
SyncFactory.ROWSET_SYNC_VENDOR,
SyncFactory.ROWSET_SYNC_PROVIDER_VERSION};
new String[]{SyncFactory.ROWSET_SYNC_PROVIDER,
SyncFactory.ROWSET_SYNC_VENDOR,
SyncFactory.ROWSET_SYNC_PROVIDER_VERSION};
if (append) {
for (int i = 0; i < propertyNames.length; i++) {
propertyNames[i] = propertyNames[i] +
dot +
propertyIndex;
dot +
propertyIndex;
}
return propertyNames;
} else {
@ -549,15 +534,21 @@ public class SyncFactory {
*
* @param providerID the unique identifier of the provider
* @return a <code>SyncProvider</code> implementation
* @throws SyncFactoryException If the SyncProvider cannot be found or
* @throws SyncFactoryException If the SyncProvider cannot be found,
* the providerID is {@code null}, or
* some error was encountered when trying to invoke this provider.
*/
public static SyncProvider getInstance(String providerID)
throws SyncFactoryException {
throws SyncFactoryException {
if(providerID == null) {
throw new SyncFactoryException("The providerID cannot be null");
}
initMapIfNecessary(); // populate HashTable
initJNDIContext(); // check JNDI context for any additional bindings
ProviderImpl impl = (ProviderImpl)implementations.get(providerID);
ProviderImpl impl = (ProviderImpl) implementations.get(providerID);
if (impl == null) {
// Requested SyncProvider is unavailable. Return default provider.
@ -575,11 +566,10 @@ public class SyncFactory {
* this SyncFactory and try to laod the SyncProvider class from
* there.
**/
c = Class.forName(providerID, true, cl);
if (c != null) {
return (SyncProvider)c.newInstance();
return (SyncProvider) c.newInstance();
} else {
return new com.sun.rowset.providers.RIOptimisticProvider();
}
@ -592,6 +582,7 @@ public class SyncFactory {
throw new SyncFactoryException("ClassNotFoundException: " + e.getMessage());
}
}
/**
* Returns an Enumeration of currently registered synchronization
* providers. A <code>RowSet</code> implementation may use any provider in
@ -605,7 +596,7 @@ public class SyncFactory {
* providers that are registered with this Factory
*/
public static Enumeration<SyncProvider> getRegisteredProviders()
throws SyncFactoryException {
throws SyncFactoryException {
initMapIfNecessary();
// return a collection of classnames
// of type SyncProvider
@ -618,10 +609,26 @@ public class SyncFactory {
* <code>SyncProvider</code> implementations can log their events to
* this object and the application can retrieve a handle to this
* object using the <code>getLogger</code> method.
* <p>
* This method checks to see that there is an {@code SQLPermission}
* object which grants the permission {@code setSyncFactory}
* before allowing the method to succeed. If a
* {@code SecurityManager} exists and its
* {@code checkPermission} method denies calling {@code setLogger},
* this method throws a
* {@code java.lang.SecurityException}.
*
* @param logger A Logger object instance
* @throws java.lang.SecurityException if a security manager exists and its
* {@code checkPermission} method denies calling {@code setLogger}
* @see SecurityManager#checkPermission
*/
public static void setLogger(Logger logger) {
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
sec.checkPermission(SET_SYNCFACTORY_PERMISSION);
}
rsLogger = logger;
}
@ -631,14 +638,28 @@ public class SyncFactory {
* <code>SyncProvider</code> implementations can log their events
* to this object and the application can retrieve a handle to this
* object using the <code>getLogger</code> method.
* <p>
* This method checks to see that there is an {@code SQLPermission}
* object which grants the permission {@code setSyncFactory}
* before allowing the method to succeed. If a
* {@code SecurityManager} exists and its
* {@code checkPermission} method denies calling {@code setLogger},
* this method throws a
* {@code java.lang.SecurityException}.
*
* @param logger a Logger object instance
* @param level a Level object instance indicating the degree of logging
* required
* @throws java.lang.SecurityException if a security manager exists and its
* {@code checkPermission} method denies calling {@code setLogger}
* @see SecurityManager#checkPermission
*/
public static void setLogger(Logger logger, Level level) {
// singleton
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
sec.checkPermission(SET_SYNCFACTORY_PERMISSION);
}
rsLogger = logger;
rsLogger.setLevel(level);
}
@ -651,27 +672,42 @@ public class SyncFactory {
*/
public static Logger getLogger() throws SyncFactoryException {
// only one logger per session
if(rsLogger == null){
throw new SyncFactoryException("(SyncFactory) : No logger has been set");
if (rsLogger == null) {
throw new SyncFactoryException("(SyncFactory) : No logger has been set");
}
return rsLogger;
}
/**
* Sets the initial JNDI context from which SyncProvider implementations
* can be retrieved from a JNDI namespace
*
* @param ctx a valid JNDI context
* @throws SyncFactoryException if the supplied JNDI context is null
*/
/**
* Sets the initial JNDI context from which SyncProvider implementations
* can be retrieved from a JNDI namespace
* <p>
* This method checks to see that there is an {@code SQLPermission}
* object which grants the permission {@code setSyncFactory}
* before allowing the method to succeed. If a
* {@code SecurityManager} exists and its
* {@code checkPermission} method denies calling {@code setJNDIContext},
* this method throws a
* {@code java.lang.SecurityException}.
*
* @param ctx a valid JNDI context
* @throws SyncFactoryException if the supplied JNDI context is null
* @throws java.lang.SecurityException if a security manager exists and its
* {@code checkPermission} method denies calling {@code setJNDIContext}
* @see SecurityManager#checkPermission
*/
public static void setJNDIContext(javax.naming.Context ctx)
throws SyncFactoryException {
throws SyncFactoryException {
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
sec.checkPermission(SET_SYNCFACTORY_PERMISSION);
}
if (ctx == null) {
throw new SyncFactoryException("Invalid JNDI context supplied");
}
ic = ctx;
jndiCtxEstablished = true;
}
}
/**
* Controls JNDI context intialization.
@ -689,7 +725,7 @@ public class SyncFactory {
throw new SyncFactoryException("SPI: NamingException: " + e.getExplanation());
} catch (Exception e) {
e.printStackTrace();
throw new SyncFactoryException("SPI: Exception: " + e.getMessage());
throw new SyncFactoryException("SPI: Exception: " + e.getMessage());
}
}
}
@ -720,7 +756,7 @@ public class SyncFactory {
* bindings have been enumerated.
*/
private static void enumerateBindings(NamingEnumeration bindings,
Properties properties) throws NamingException {
Properties properties) throws NamingException {
boolean syncProviderObj = false; // move to parameters ?
@ -729,21 +765,21 @@ public class SyncFactory {
Object elementObj = null;
String element = null;
while (bindings.hasMore()) {
bd = (Binding)bindings.next();
bd = (Binding) bindings.next();
element = bd.getName();
elementObj = bd.getObject();
if (!(ic.lookup(element) instanceof Context)) {
// skip directories/sub-contexts
if (ic.lookup(element) instanceof SyncProvider) {
// skip directories/sub-contexts
if (ic.lookup(element) instanceof SyncProvider) {
syncProviderObj = true;
}
}
}
if (syncProviderObj) {
SyncProvider sync = (SyncProvider)elementObj;
SyncProvider sync = (SyncProvider) elementObj;
properties.put(SyncFactory.ROWSET_SYNC_PROVIDER,
sync.getProviderID());
sync.getProviderID());
syncProviderObj = false; // reset
}
@ -756,142 +792,136 @@ public class SyncFactory {
}
}
/**
* Internal class that defines the lazy reference construct for each registered
* SyncProvider implementation.
/**
* Internal class that defines the lazy reference construct for each registered
* SyncProvider implementation.
*/
class ProviderImpl extends SyncProvider {
private String className = null;
private String vendorName = null;
private String ver = null;
private int index;
public void setClassname(String classname) {
className = classname;
}
public String getClassname() {
return className;
}
public void setVendor(String vendor) {
vendorName = vendor;
}
public String getVendor() {
return vendorName;
}
public void setVersion(String providerVer) {
ver = providerVer;
}
public String getVersion() {
return ver;
}
public void setIndex(int i) {
index = i;
}
public int getIndex() {
return index;
}
public int getDataSourceLock() throws SyncProviderException {
int dsLock = 0;
try {
dsLock = SyncFactory.getInstance(className).getDataSourceLock();
} catch (SyncFactoryException sfEx) {
throw new SyncProviderException(sfEx.getMessage());
}
return dsLock;
}
public int getProviderGrade() {
int grade = 0;
try {
grade = SyncFactory.getInstance(className).getProviderGrade();
} catch (SyncFactoryException sfEx) {
//
}
return grade;
}
public String getProviderID() {
return className;
}
/*
public javax.sql.RowSetInternal getRowSetInternal() {
try
{
return SyncFactory.getInstance(className).getRowSetInternal();
} catch(SyncFactoryException sfEx) {
//
}
}
*/
class ProviderImpl extends SyncProvider {
private String className = null;
private String vendorName = null;
private String ver = null;
private int index;
public javax.sql.RowSetReader getRowSetReader() {
public void setClassname(String classname) {
className = classname;
RowSetReader rsReader = null;
try {
rsReader = SyncFactory.getInstance(className).getRowSetReader();
} catch (SyncFactoryException sfEx) {
//
}
public String getClassname() {
return className;
}
return rsReader;
public void setVendor(String vendor) {
vendorName = vendor;
}
}
public String getVendor() {
return vendorName;
}
public void setVersion(String providerVer) {
ver = providerVer;
}
public String getVersion() {
return ver;
}
public void setIndex(int i) {
index = i;
}
public int getIndex() {
return index;
}
public int getDataSourceLock() throws SyncProviderException {
int dsLock = 0;
try
{
dsLock = SyncFactory.getInstance(className).getDataSourceLock();
} catch(SyncFactoryException sfEx) {
throw new SyncProviderException(sfEx.getMessage());
}
return dsLock;
}
public int getProviderGrade() {
int grade = 0;
try
{
grade = SyncFactory.getInstance(className).getProviderGrade();
} catch(SyncFactoryException sfEx) {
//
}
return grade;
}
public String getProviderID() {
return className;
}
/*
public javax.sql.RowSetInternal getRowSetInternal() {
try
{
return SyncFactory.getInstance(className).getRowSetInternal();
} catch(SyncFactoryException sfEx) {
//
}
}
*/
public javax.sql.RowSetReader getRowSetReader() {
RowSetReader rsReader = null;;
try
{
rsReader = SyncFactory.getInstance(className).getRowSetReader();
} catch(SyncFactoryException sfEx) {
//
}
return rsReader;
}
public javax.sql.RowSetWriter getRowSetWriter() {
public javax.sql.RowSetWriter getRowSetWriter() {
RowSetWriter rsWriter = null;
try
{
rsWriter = SyncFactory.getInstance(className).getRowSetWriter();
} catch(SyncFactoryException sfEx) {
//
}
return rsWriter;
}
public void setDataSourceLock(int param)
throws SyncProviderException {
try
{
SyncFactory.getInstance(className).setDataSourceLock(param);
} catch(SyncFactoryException sfEx) {
throw new SyncProviderException(sfEx.getMessage());
}
try {
rsWriter = SyncFactory.getInstance(className).getRowSetWriter();
} catch (SyncFactoryException sfEx) {
//
}
public int supportsUpdatableView() {
return rsWriter;
}
public void setDataSourceLock(int param)
throws SyncProviderException {
try {
SyncFactory.getInstance(className).setDataSourceLock(param);
} catch (SyncFactoryException sfEx) {
throw new SyncProviderException(sfEx.getMessage());
}
}
public int supportsUpdatableView() {
int view = 0;
try
{
view = SyncFactory.getInstance(className).supportsUpdatableView();
} catch(SyncFactoryException sfEx) {
//
}
return view;
}
try {
view = SyncFactory.getInstance(className).supportsUpdatableView();
} catch (SyncFactoryException sfEx) {
//
}
return view;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, 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
@ -344,7 +344,7 @@ public abstract class SyncProvider {
* source without checking the validity of any data.
*
*/
public static int GRADE_NONE = 1;
public static final int GRADE_NONE = 1;
/**
* Indicates a low level optimistic synchronization grade with
@ -354,7 +354,7 @@ public abstract class SyncProvider {
* returning this grade will check only rows that have changed.
*
*/
public static int GRADE_CHECK_MODIFIED_AT_COMMIT = 2;
public static final int GRADE_CHECK_MODIFIED_AT_COMMIT = 2;
/**
* Indicates a high level optimistic synchronization grade with
@ -364,7 +364,7 @@ public abstract class SyncProvider {
* returning this grade will check all rows, including rows that have not
* changed.
*/
public static int GRADE_CHECK_ALL_AT_COMMIT = 3;
public static final int GRADE_CHECK_ALL_AT_COMMIT = 3;
/**
* Indicates a pessimistic synchronization grade with
@ -374,7 +374,7 @@ public abstract class SyncProvider {
* implementation returning this grade will lock the row in the originating
* data source.
*/
public static int GRADE_LOCK_WHEN_MODIFIED = 4;
public static final int GRADE_LOCK_WHEN_MODIFIED = 4;
/**
* Indicates the most pessimistic synchronization grade with
@ -384,47 +384,47 @@ public abstract class SyncProvider {
* table affected by the original statement used to populate a
* <code>RowSet</code> object.
*/
public static int GRADE_LOCK_WHEN_LOADED = 5;
public static final int GRADE_LOCK_WHEN_LOADED = 5;
/**
* Indicates that no locks remain on the originating data source. This is the default
* lock setting for all <code>SyncProvider</code> implementations unless
* otherwise directed by a <code>RowSet</code> object.
*/
public static int DATASOURCE_NO_LOCK = 1;
public static final int DATASOURCE_NO_LOCK = 1;
/**
* Indicates that a lock is placed on the rows that are touched by the original
* SQL statement used to populate the <code>RowSet</code> object
* that is using this <code>SyncProvider</code> object.
*/
public static int DATASOURCE_ROW_LOCK = 2;
public static final int DATASOURCE_ROW_LOCK = 2;
/**
* Indicates that a lock is placed on all tables that are touched by the original
* SQL statement used to populate the <code>RowSet</code> object
* that is using this <code>SyncProvider</code> object.
*/
public static int DATASOURCE_TABLE_LOCK = 3;
public static final int DATASOURCE_TABLE_LOCK = 3;
/**
* Indicates that a lock is placed on the entire data source that is the source of
* data for the <code>RowSet</code> object
* that is using this <code>SyncProvider</code> object.
*/
public static int DATASOURCE_DB_LOCK = 4;
public static final int DATASOURCE_DB_LOCK = 4;
/**
* Indicates that a <code>SyncProvider</code> implementation
* supports synchronization between a <code>RowSet</code> object and
* the SQL <code>VIEW</code> used to populate it.
*/
public static int UPDATABLE_VIEW_SYNC = 5;
public static final int UPDATABLE_VIEW_SYNC = 5;
/**
* Indicates that a <code>SyncProvider</code> implementation
* does <B>not</B> support synchronization between a <code>RowSet</code>
* object and the SQL <code>VIEW</code> used to populate it.
*/
public static int NONUPDATABLE_VIEW_SYNC = 6;
public static final int NONUPDATABLE_VIEW_SYNC = 6;
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.net.sdp;
import java.io.IOException;
import java.io.FileDescriptor;
import java.security.AccessController;
import sun.misc.SharedSecrets;
import sun.misc.JavaIOFileDescriptorAccess;
/**
* This class defines methods for creating SDP sockets or "converting" existing
* file descriptors, referencing (unbound) TCP sockets, to SDP.
*/
public final class SdpSupport {
private static final String os = AccessController
.doPrivileged(new sun.security.action.GetPropertyAction("os.name"));
private static final boolean isSupported = (os.equals("SunOS") || (os.equals("Linux")));
private static final JavaIOFileDescriptorAccess fdAccess =
SharedSecrets.getJavaIOFileDescriptorAccess();
private SdpSupport() { }
/**
* Creates a SDP socket, returning file descriptor referencing the socket.
*/
public static FileDescriptor createSocket() throws IOException {
if (!isSupported)
throw new UnsupportedOperationException("SDP not supported on this platform");
int fdVal = create0();
FileDescriptor fd = new FileDescriptor();
fdAccess.set(fd, fdVal);
return fd;
}
/**
* Converts an existing file descriptor, that references an unbound TCP socket,
* to SDP.
*/
public static void convertSocket(FileDescriptor fd) throws IOException {
if (!isSupported)
throw new UnsupportedOperationException("SDP not supported on this platform");
int fdVal = fdAccess.get(fd);
convert0(fdVal);
}
private static native int create0() throws IOException;
private static native void convert0(int fd) throws IOException;
static {
AccessController.doPrivileged(
new sun.security.action.LoadLibraryAction("net"));
}
}

View File

@ -545,6 +545,8 @@ public class FileChannelImpl
long position, long count)
throws IOException
{
if (!src.readable)
throw new NonReadableChannelException();
synchronized (src.positionLock) {
long pos = src.position();
long max = Math.min(count, src.size() - pos);

View File

@ -319,7 +319,12 @@ class IOUtil {
static native boolean randomBytes(byte[] someBytes);
static native void initPipe(int[] fda, boolean blocking);
/**
* Returns two file descriptors for a pipe encoded in a long.
* The read end of the pipe is returned in the high 32 bits,
* while the write end is returned in the low 32 bits.
*/
static native long makePipe(boolean blocking);
static native boolean drain(int fd) throws IOException;

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2010, 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.SocketChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.io.FileDescriptor;
import java.io.IOException;
/**
* Provides access to implementation private constructors and methods.
*/
public final class Secrets {
private Secrets() { }
private static SelectorProvider provider() {
SelectorProvider p = SelectorProvider.provider();
if (!(p instanceof SelectorProviderImpl))
throw new UnsupportedOperationException();
return p;
}
public static SocketChannel newSocketChannel(FileDescriptor fd) {
try {
return new SocketChannelImpl(provider(), fd, false);
} catch (IOException ioe) {
throw new AssertionError(ioe);
}
}
public static ServerSocketChannel newServerSocketChannel(FileDescriptor fd) {
try {
return new ServerSocketChannelImpl(provider(), fd, false);
} catch (IOException ioe) {
throw new AssertionError(ioe);
}
}
}

View File

@ -80,21 +80,24 @@ class ServerSocketChannelImpl
// -- End of fields protected by stateLock
public ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
super(sp);
this.fd = Net.serverSocket(true);
this.fdVal = IOUtil.fdVal(fd);
this.state = ST_INUSE;
}
public ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd)
ServerSocketChannelImpl(SelectorProvider sp,
FileDescriptor fd,
boolean bound)
throws IOException
{
super(sp);
this.fd = fd;
this.fdVal = IOUtil.fdVal(fd);
this.state = ST_INUSE;
localAddress = Net.localAddress(fd);
if (bound)
localAddress = Net.localAddress(fd);
}
public ServerSocket socket() {

View File

@ -103,6 +103,19 @@ class SocketChannelImpl
this.state = ST_UNCONNECTED;
}
SocketChannelImpl(SelectorProvider sp,
FileDescriptor fd,
boolean bound)
throws IOException
{
super(sp);
this.fd = fd;
this.fdVal = IOUtil.fdVal(fd);
this.state = ST_UNCONNECTED;
if (bound)
this.localAddress = Net.localAddress(fd);
}
// Constructor for sockets obtained from server sockets
//
SocketChannelImpl(SelectorProvider sp,

View File

@ -4231,7 +4231,10 @@ class SQLPerm extends Perm {
super("SQLPermission",
"java.sql.SQLPermission",
new String[] {
"setLog"
"setLog",
"callAbort",
"setSyncFactory",
"setNetworkTimeout",
},
null);
}

View File

@ -535,7 +535,7 @@ jboolean
GetApplicationHome(char *buf, jint bufsize)
{
if (execname != NULL) {
JLI_StrNCpy(buf, execname, bufsize-1);
JLI_Snprintf(buf, bufsize, "%s", execname);
buf[bufsize-1] = '\0';
} else {
return JNI_FALSE;

View File

@ -39,6 +39,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;
import java.security.AccessController;
import static java.security.AccessController.doPrivileged;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
@ -94,14 +95,13 @@ final class UNIXProcess extends Process {
private final static ThreadGroup group = getRootThreadGroup();
private static ThreadGroup getRootThreadGroup() {
return AccessController.doPrivileged
(new PrivilegedAction<ThreadGroup> () {
public ThreadGroup run() {
ThreadGroup root = Thread.currentThread().getThreadGroup();
while (root.getParent() != null)
root = root.getParent();
return root;
}});
return doPrivileged(new PrivilegedAction<ThreadGroup> () {
public ThreadGroup run() {
ThreadGroup root = Thread.currentThread().getThreadGroup();
while (root.getParent() != null)
root = root.getParent();
return root;
}});
}
public Thread newThread(Runnable grimReaper) {
@ -117,8 +117,12 @@ final class UNIXProcess extends Process {
/**
* The thread pool of "process reaper" daemon threads.
*/
private static final Executor processReaperExecutor
= Executors.newCachedThreadPool(new ProcessReaperThreadFactory());
private static final Executor processReaperExecutor =
doPrivileged(new PrivilegedAction<Executor>() {
public Executor run() {
return Executors.newCachedThreadPool
(new ProcessReaperThreadFactory());
}});
UNIXProcess(final byte[] prog,
final byte[] argBlock, final int argc,
@ -136,8 +140,7 @@ final class UNIXProcess extends Process {
redirectErrorStream);
try {
AccessController.doPrivileged
(new PrivilegedExceptionAction<Void>() {
doPrivileged(new PrivilegedExceptionAction<Void>() {
public Void run() throws IOException {
initStreams(fds);
return null;

View File

@ -73,28 +73,7 @@ public final class NetHooks {
* be changed to use the ServiceLoader facility to allow the deployment of
* other providers.
*/
private static Provider loadProvider(final String cn) {
return AccessController
.doPrivileged(new PrivilegedAction<Provider>() {
@Override public Provider run() {
Class<Provider> c;
try {
c = (Class<Provider>)Class.forName(cn, true, null);
} catch (ClassNotFoundException x) {
return null;
}
try {
return c.newInstance();
} catch (IllegalAccessException x) {
throw new AssertionError(x);
} catch (InstantiationException x) {
throw new AssertionError(x);
}
}});
}
private static final Provider provider = AccessController
.doPrivileged(new GetPropertyAction("os.name")).equals("SunOS") ?
loadProvider("sun.net.spi.SdpProvider") : null;
private static final Provider provider = new sun.net.sdp.SdpProvider();
/**
* Invoke prior to binding a TCP socket.
@ -104,8 +83,7 @@ public final class NetHooks {
int port)
throws IOException
{
if (provider != null)
provider.implBeforeTcpBind(fdObj, address, port);
provider.implBeforeTcpBind(fdObj, address, port);
}
/**
@ -116,7 +94,6 @@ public final class NetHooks {
int port)
throws IOException
{
if (provider != null)
provider.implBeforeTcpConnect(fdObj, address, port);
provider.implBeforeTcpConnect(fdObj, address, port);
}
}

View File

@ -23,7 +23,7 @@
* questions.
*/
package sun.net.spi;
package sun.net.sdp;
import sun.net.NetHooks;
import java.net.InetAddress;
@ -34,9 +34,10 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintStream;
import java.security.AccessController;
import sun.misc.SharedSecrets;
import sun.misc.JavaIOFileDescriptorAccess;
import sun.net.sdp.SdpSupport;
import sun.security.action.GetPropertyAction;
/**
* A NetHooks provider that converts sockets from the TCP to SDP protocol prior
@ -44,9 +45,6 @@ import sun.misc.JavaIOFileDescriptorAccess;
*/
public class SdpProvider extends NetHooks.Provider {
private static final JavaIOFileDescriptorAccess fdAccess =
SharedSecrets.getJavaIOFileDescriptorAccess();
// maximum port
private static final int MAX_PORT = 65535;
@ -59,7 +57,8 @@ public class SdpProvider extends NetHooks.Provider {
public SdpProvider() {
// if this property is not defined then there is nothing to do.
String file = System.getProperty("com.sun.sdp.conf");
String file = AccessController.doPrivileged(
new GetPropertyAction("com.sun.sdp.conf"));
if (file == null) {
this.enabled = false;
this.rules = null;
@ -78,7 +77,8 @@ public class SdpProvider extends NetHooks.Provider {
// check if debugging is enabled
PrintStream out = null;
String logfile = System.getProperty("com.sun.sdp.debug");
String logfile = AccessController.doPrivileged(
new GetPropertyAction("com.sun.sdp.debug"));
if (logfile != null) {
out = System.out;
if (logfile.length() > 0) {
@ -297,8 +297,7 @@ public class SdpProvider extends NetHooks.Provider {
boolean matched = false;
for (Rule rule: rules) {
if (rule.match(action, address, port)) {
int fd = fdAccess.get(fdObj);
convert(fd);
SdpSupport.convertSocket(fdObj);
matched = true;
break;
}
@ -333,7 +332,4 @@ public class SdpProvider extends NetHooks.Provider {
if (enabled)
convertTcpToSdpIfMatch(fdObj, Action.CONNECT, address, port);
}
// -- native methods --
private static native void convert(int fd) throws IOException;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2010, 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
@ -25,20 +25,14 @@
package sun.net.www.protocol.http.ntlm;
import com.sun.security.ntlm.Client;
import com.sun.security.ntlm.NTLMException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.PasswordAuthentication;
import java.net.UnknownHostException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import sun.net.www.HeaderParser;
import sun.net.www.protocol.http.AuthenticationInfo;
@ -72,14 +66,8 @@ import sun.net.www.protocol.http.HttpURLConnection;
*/
public class NTLMAuthentication extends AuthenticationInfo {
private static final long serialVersionUID = -2403849171106437142L;
private static final long serialVersionUID = 170L;
private byte[] type1;
private byte[] type3;
private SecretKeyFactory fac;
private Cipher cipher;
private MessageDigest md4;
private String hostname;
private static String defaultDomain; /* Domain to use if not specified by user */
@ -94,53 +82,28 @@ public class NTLMAuthentication extends AuthenticationInfo {
}
private void init0() {
type1 = new byte[256];
type3 = new byte[256];
System.arraycopy (new byte[] {'N','T','L','M','S','S','P',0,1}, 0, type1, 0, 9);
type1[12] = (byte) 3;
type1[13] = (byte) 0xb2;
type1[28] = (byte) 0x20;
System.arraycopy (new byte[] {'N','T','L','M','S','S','P',0,3}, 0, type3, 0, 9);
type3[12] = (byte) 0x18;
type3[14] = (byte) 0x18;
type3[20] = (byte) 0x18;
type3[22] = (byte) 0x18;
type3[32] = (byte) 0x40;
type3[60] = (byte) 1;
type3[61] = (byte) 0x82;
try {
hostname = java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<String>() {
public String run() {
String localhost;
try {
localhost = InetAddress.getLocalHost().getHostName().toUpperCase();
} catch (UnknownHostException e) {
localhost = "localhost";
}
return localhost;
hostname = java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<String>() {
public String run() {
String localhost;
try {
localhost = InetAddress.getLocalHost().getHostName().toUpperCase();
} catch (UnknownHostException e) {
localhost = "localhost";
}
});
int x = hostname.indexOf ('.');
if (x != -1) {
hostname = hostname.substring (0, x);
return localhost;
}
fac = SecretKeyFactory.getInstance ("DES");
cipher = Cipher.getInstance ("DES/ECB/NoPadding");
md4 = sun.security.provider.MD4.getInstance();
} catch (NoSuchPaddingException e) {
assert false;
} catch (NoSuchAlgorithmException e) {
assert false;
});
int x = hostname.indexOf ('.');
if (x != -1) {
hostname = hostname.substring (0, x);
}
};
PasswordAuthentication pw;
String username;
String ntdomain;
String password;
Client client;
/**
* Create a NTLMAuthentication:
* Username may be specified as domain<BACKSLASH>username in the application Authenticator.
@ -156,6 +119,9 @@ public class NTLMAuthentication extends AuthenticationInfo {
}
private void init (PasswordAuthentication pw) {
String username;
String ntdomain;
char[] password;
this.pw = pw;
String s = pw.getUserName();
int i = s.indexOf ('\\');
@ -166,8 +132,19 @@ public class NTLMAuthentication extends AuthenticationInfo {
ntdomain = s.substring (0, i).toUpperCase();
username = s.substring (i+1);
}
password = new String (pw.getPassword());
password = pw.getPassword();
init0();
try {
client = new Client(System.getProperty("ntlm.version"), hostname,
username, ntdomain, password);
} catch (NTLMException ne) {
try {
client = new Client(null, hostname, username, ntdomain, password);
} catch (NTLMException ne2) {
// Will never happen
throw new AssertionError("Really?");
}
}
}
/**
@ -240,181 +217,26 @@ public class NTLMAuthentication extends AuthenticationInfo {
}
}
private void copybytes (byte[] dest, int destpos, String src, String enc) {
try {
byte[] x = src.getBytes(enc);
System.arraycopy (x, 0, dest, destpos, x.length);
} catch (UnsupportedEncodingException e) {
assert false;
}
}
private String buildType1Msg () {
int dlen = ntdomain.length();
type1[16]= (byte) (dlen % 256);
type1[17]= (byte) (dlen / 256);
type1[18] = type1[16];
type1[19] = type1[17];
int hlen = hostname.length();
type1[24]= (byte) (hlen % 256);
type1[25]= (byte) (hlen / 256);
type1[26] = type1[24];
type1[27] = type1[25];
copybytes (type1, 32, hostname, "ISO8859_1");
copybytes (type1, hlen+32, ntdomain, "ISO8859_1");
type1[20] = (byte) ((hlen+32) % 256);
type1[21] = (byte) ((hlen+32) / 256);
byte[] msg = new byte [32 + hlen + dlen];
System.arraycopy (type1, 0, msg, 0, 32 + hlen + dlen);
byte[] msg = client.type1();
String result = "NTLM " + (new B64Encoder()).encode (msg);
return result;
}
/* Convert a 7 byte array to an 8 byte array (for a des key with parity)
* input starts at offset off
*/
private byte[] makeDesKey (byte[] input, int off) {
int[] in = new int [input.length];
for (int i=0; i<in.length; i++ ) {
in[i] = input[i]<0 ? input[i]+256: input[i];
}
byte[] out = new byte[8];
out[0] = (byte)in[off+0];
out[1] = (byte)(((in[off+0] << 7) & 0xFF) | (in[off+1] >> 1));
out[2] = (byte)(((in[off+1] << 6) & 0xFF) | (in[off+2] >> 2));
out[3] = (byte)(((in[off+2] << 5) & 0xFF) | (in[off+3] >> 3));
out[4] = (byte)(((in[off+3] << 4) & 0xFF) | (in[off+4] >> 4));
out[5] = (byte)(((in[off+4] << 3) & 0xFF) | (in[off+5] >> 5));
out[6] = (byte)(((in[off+5] << 2) & 0xFF) | (in[off+6] >> 6));
out[7] = (byte)((in[off+6] << 1) & 0xFF);
return out;
}
private byte[] calcLMHash () throws GeneralSecurityException {
byte[] magic = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
byte[] pwb = password.toUpperCase ().getBytes();
byte[] pwb1 = new byte [14];
int len = password.length();
if (len > 14)
len = 14;
System.arraycopy (pwb, 0, pwb1, 0, len); /* Zero padded */
DESKeySpec dks1 = new DESKeySpec (makeDesKey (pwb1, 0));
DESKeySpec dks2 = new DESKeySpec (makeDesKey (pwb1, 7));
SecretKey key1 = fac.generateSecret (dks1);
SecretKey key2 = fac.generateSecret (dks2);
cipher.init (Cipher.ENCRYPT_MODE, key1);
byte[] out1 = cipher.doFinal (magic, 0, 8);
cipher.init (Cipher.ENCRYPT_MODE, key2);
byte[] out2 = cipher.doFinal (magic, 0, 8);
byte[] result = new byte [21];
System.arraycopy (out1, 0, result, 0, 8);
System.arraycopy (out2, 0, result, 8, 8);
return result;
}
private byte[] calcNTHash () throws GeneralSecurityException {
byte[] pw = null;
try {
pw = password.getBytes ("UnicodeLittleUnmarked");
} catch (UnsupportedEncodingException e) {
assert false;
}
byte[] out = md4.digest (pw);
byte[] result = new byte [21];
System.arraycopy (out, 0, result, 0, 16);
return result;
}
/* key is a 21 byte array. Split it into 3 7 byte chunks,
* Convert each to 8 byte DES keys, encrypt the text arg with
* each key and return the three results in a sequential []
*/
private byte[] calcResponse (byte[] key, byte[] text)
throws GeneralSecurityException {
assert key.length == 21;
DESKeySpec dks1 = new DESKeySpec (makeDesKey (key, 0));
DESKeySpec dks2 = new DESKeySpec (makeDesKey (key, 7));
DESKeySpec dks3 = new DESKeySpec (makeDesKey (key, 14));
SecretKey key1 = fac.generateSecret (dks1);
SecretKey key2 = fac.generateSecret (dks2);
SecretKey key3 = fac.generateSecret (dks3);
cipher.init (Cipher.ENCRYPT_MODE, key1);
byte[] out1 = cipher.doFinal (text, 0, 8);
cipher.init (Cipher.ENCRYPT_MODE, key2);
byte[] out2 = cipher.doFinal (text, 0, 8);
cipher.init (Cipher.ENCRYPT_MODE, key3);
byte[] out3 = cipher.doFinal (text, 0, 8);
byte[] result = new byte [24];
System.arraycopy (out1, 0, result, 0, 8);
System.arraycopy (out2, 0, result, 8, 8);
System.arraycopy (out3, 0, result, 16, 8);
return result;
}
private String buildType3Msg (String challenge) throws GeneralSecurityException,
IOException {
/* First decode the type2 message to get the server nonce */
/* nonce is located at type2[24] for 8 bytes */
byte[] type2 = (new sun.misc.BASE64Decoder()).decodeBuffer (challenge);
byte[] nonce = new byte [8];
System.arraycopy (type2, 24, nonce, 0, 8);
int ulen = username.length()*2;
type3[36] = type3[38] = (byte) (ulen % 256);
type3[37] = type3[39] = (byte) (ulen / 256);
int dlen = ntdomain.length()*2;
type3[28] = type3[30] = (byte) (dlen % 256);
type3[29] = type3[31] = (byte) (dlen / 256);
int hlen = hostname.length()*2;
type3[44] = type3[46] = (byte) (hlen % 256);
type3[45] = type3[47] = (byte) (hlen / 256);
int l = 64;
copybytes (type3, l, ntdomain, "UnicodeLittleUnmarked");
type3[32] = (byte) (l % 256);
type3[33] = (byte) (l / 256);
l += dlen;
copybytes (type3, l, username, "UnicodeLittleUnmarked");
type3[40] = (byte) (l % 256);
type3[41] = (byte) (l / 256);
l += ulen;
copybytes (type3, l, hostname, "UnicodeLittleUnmarked");
type3[48] = (byte) (l % 256);
type3[49] = (byte) (l / 256);
l += hlen;
byte[] lmhash = calcLMHash();
byte[] lmresponse = calcResponse (lmhash, nonce);
byte[] nthash = calcNTHash();
byte[] ntresponse = calcResponse (nthash, nonce);
System.arraycopy (lmresponse, 0, type3, l, 24);
type3[16] = (byte) (l % 256);
type3[17] = (byte) (l / 256);
l += 24;
System.arraycopy (ntresponse, 0, type3, l, 24);
type3[24] = (byte) (l % 256);
type3[25] = (byte) (l / 256);
l += 24;
type3[56] = (byte) (l % 256);
type3[57] = (byte) (l / 256);
byte[] msg = new byte [l];
System.arraycopy (type3, 0, msg, 0, l);
byte[] nonce = new byte[8];
new java.util.Random().nextBytes(nonce);
byte[] msg = client.type3(type2, nonce);
String result = "NTLM " + (new B64Encoder()).encode (msg);
return result;
}
}
class B64Encoder extends sun.misc.BASE64Encoder {
/* to force it to to the entire encoding in one line */
protected int bytesPerLine () {

View File

@ -65,10 +65,9 @@ class DevPollSelectorImpl
*/
DevPollSelectorImpl(SelectorProvider sp) {
super(sp);
int[] fdes = new int[2];
IOUtil.initPipe(fdes, false);
fd0 = fdes[0];
fd1 = fdes[1];
long pipeFds = IOUtil.makePipe(false);
fd0 = (int) (pipeFds >>> 32);
fd1 = (int) pipeFds;
pollWrapper = new DevPollArrayWrapper();
pollWrapper.initInterrupt(fd0, fd1);
fdToKey = new HashMap<Integer,SelectionKeyImpl>();
@ -147,7 +146,7 @@ class DevPollSelectorImpl
selectedKeys = null;
// Deregister channels
Iterator i = keys.iterator();
Iterator<SelectionKey> i = keys.iterator();
while (i.hasNext()) {
SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
deregister(ski);

View File

@ -62,10 +62,9 @@ class EPollSelectorImpl
*/
EPollSelectorImpl(SelectorProvider sp) {
super(sp);
int[] fdes = new int[2];
IOUtil.initPipe(fdes, false);
fd0 = fdes[0];
fd1 = fdes[1];
long pipeFds = IOUtil.makePipe(false);
fd0 = (int) (pipeFds >>> 32);
fd1 = (int) pipeFds;
pollWrapper = new EPollArrayWrapper();
pollWrapper.initInterrupt(fd0, fd1);
fdToKey = new HashMap<Integer,SelectionKeyImpl>();
@ -144,7 +143,7 @@ class EPollSelectorImpl
selectedKeys = null;
// Deregister channels
Iterator i = keys.iterator();
Iterator<SelectionKey> i = keys.iterator();
while (i.hasNext()) {
SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
deregister(ski);

View File

@ -96,7 +96,7 @@ class InheritedChannel {
FileDescriptor fd)
throws IOException
{
super(sp, fd);
super(sp, fd, true);
}
protected void implCloseSelectableChannel() throws IOException {

View File

@ -39,13 +39,14 @@ class PipeImpl
private final SinkChannel sink;
PipeImpl(SelectorProvider sp) {
int[] fdes = new int[2];
IOUtil.initPipe(fdes, true);
long pipeFds = IOUtil.makePipe(true);
int readFd = (int) (pipeFds >>> 32);
int writeFd = (int) pipeFds;
FileDescriptor sourcefd = new FileDescriptor();
IOUtil.setfdVal(sourcefd, fdes[0]);
IOUtil.setfdVal(sourcefd, readFd);
source = new SourceChannelImpl(sp, sourcefd);
FileDescriptor sinkfd = new FileDescriptor();
IOUtil.setfdVal(sinkfd, fdes[1]);
IOUtil.setfdVal(sinkfd, writeFd);
sink = new SinkChannelImpl(sp, sinkfd);
}

View File

@ -54,10 +54,9 @@ class PollSelectorImpl
*/
PollSelectorImpl(SelectorProvider sp) {
super(sp, 1, 1);
int[] fdes = new int[2];
IOUtil.initPipe(fdes, false);
fd0 = fdes[0];
fd1 = fdes[1];
long pipeFds = IOUtil.makePipe(false);
fd0 = (int) (pipeFds >>> 32);
fd1 = (int) pipeFds;
pollWrapper = new PollArrayWrapper(INIT_CAP);
pollWrapper.initInterrupt(fd0, fd1);
channelArray = new SelectionKeyImpl[INIT_CAP];

View File

@ -27,7 +27,6 @@ package sun.nio.fs;
import java.nio.file.*;
import java.util.Iterator;
import java.util.ConcurrentModificationException;
import java.util.NoSuchElementException;
import java.util.concurrent.locks.*;
import java.io.IOException;
@ -139,9 +138,6 @@ class UnixDirectoryStream
// next entry to return
private Path nextEntry;
// previous entry returned by next method (needed by remove method)
private Path prevEntry;
UnixDirectoryIterator(DirectoryStream<Path> stream) {
atEof = false;
this.stream = stream;
@ -168,24 +164,19 @@ class UnixDirectoryStream
// prevent close while reading
readLock().lock();
try {
if (isClosed)
throwAsConcurrentModificationException(new
ClosedDirectoryStreamException());
try {
if (isOpen()) {
nameAsBytes = readdir(dp);
} catch (UnixException x) {
try {
x.rethrowAsIOException(dir);
} catch (IOException ioe) {
throwAsConcurrentModificationException(ioe);
}
}
} catch (UnixException x) {
IOException ioe = x.asIOException(dir);
throw new DirectoryIteratorException(ioe);
} finally {
readLock().unlock();
}
// EOF
if (nameAsBytes == null) {
atEof = true;
return null;
}
@ -198,7 +189,7 @@ class UnixDirectoryStream
if (filter == null || filter.accept(entry))
return entry;
} catch (IOException ioe) {
throwAsConcurrentModificationException(ioe);
throw new DirectoryIteratorException(ioe);
}
}
}
@ -206,66 +197,28 @@ class UnixDirectoryStream
@Override
public synchronized boolean hasNext() {
if (nextEntry == null && !atEof) {
if (nextEntry == null && !atEof)
nextEntry = readNextEntry();
// at EOF?
if (nextEntry == null)
atEof = true;
}
return nextEntry != null;
}
@Override
public synchronized Path next() {
if (nextEntry == null) {
if (!atEof) {
nextEntry = readNextEntry();
}
if (nextEntry == null) {
atEof = true;
throw new NoSuchElementException();
}
Path result;
if (nextEntry == null && !atEof) {
result = readNextEntry();
} else {
result = nextEntry;
nextEntry = null;
}
prevEntry = nextEntry;
nextEntry = null;
return prevEntry;
if (result == null)
throw new NoSuchElementException();
return result;
}
@Override
public void remove() {
if (isClosed) {
throwAsConcurrentModificationException(new
ClosedDirectoryStreamException());
}
Path entry;
synchronized (this) {
if (prevEntry == null)
throw new IllegalStateException("No previous entry to remove");
entry = prevEntry;
prevEntry = null;
}
// use (race-free) unlinkat if available
try {
if (stream instanceof UnixSecureDirectoryStream) {
((UnixSecureDirectoryStream)stream)
.implDelete(entry.getName(), false, 0);
} else {
entry.delete();
}
} catch (IOException ioe) {
throwAsConcurrentModificationException(ioe);
} catch (SecurityException se) {
throwAsConcurrentModificationException(se);
}
throw new UnsupportedOperationException();
}
}
private static void throwAsConcurrentModificationException(Throwable t) {
ConcurrentModificationException cme = new ConcurrentModificationException();
cme.initCause(t);
throw cme;
}
}

View File

@ -166,7 +166,7 @@ class UnixSecureDirectoryStream
* Deletes file/directory in this directory. Works in a race-free manner
* when invoked with flags.
*/
void implDelete(Path obj, boolean haveFlags, int flags)
private void implDelete(Path obj, boolean haveFlags, int flags)
throws IOException
{
UnixPath file = getName(obj);

View File

@ -25,9 +25,16 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#if defined(__solaris__) && !defined(PROTO_SDP)
#define PROTO_SDP 257
#if defined(__solaris__)
#if !defined(PROTO_SDP)
#define PROTO_SDP 257
#endif
#elif defined(__linux__)
#if !defined(AF_INET_SDP)
#define AF_INET_SDP 27
#endif
#endif
#include "jni.h"
@ -40,20 +47,61 @@
} while((_result == -1) && (errno == EINTR)); \
} while(0)
JNIEXPORT void JNICALL
Java_sun_net_spi_SdpProvider_convert(JNIEnv *env, jclass cls, jint fd)
/**
* Creates a SDP socket.
*/
static int create(JNIEnv* env)
{
#ifdef PROTO_SDP
#ifdef AF_INET6
int s;
#if defined(__solaris__)
#ifdef AF_INET6
int domain = ipv6_available() ? AF_INET6 : AF_INET;
#else
#else
int domain = AF_INET;
#endif
s = socket(domain, SOCK_STREAM, PROTO_SDP);
#elif defined(__linux__)
/**
* IPv6 not supported by SDP on Linux
*/
if (ipv6_available()) {
JNU_ThrowIOException(env, "IPv6 not supported");
return;
}
s = socket(AF_INET_SDP, SOCK_STREAM, 0);
#else
/* not supported on other platforms at this time */
s = -1;
errno = EPROTONOSUPPORT;
#endif
int s = socket(domain, SOCK_STREAM, PROTO_SDP);
if (s < 0) {
if (s < 0)
JNU_ThrowIOExceptionWithLastError(env, "socket");
} else {
int arg, len, res;
return s;
}
/**
* Creates a SDP socket, returning file descriptor referencing the socket.
*/
JNIEXPORT jint JNICALL
Java_sun_net_sdp_SdpSupport_create0(JNIEnv *env, jclass cls)
{
return create(env);
}
/**
* Converts an existing file descriptor, that references an unbound TCP socket,
* to SDP.
*/
JNIEXPORT void JNICALL
Java_sun_net_sdp_SdpSupport_convert0(JNIEnv *env, jclass cls, int fd)
{
int s = create(env);
if (s >= 0) {
socklen_t len;
int arg, res;
struct linger linger;
/* copy socket options that are relevant to SDP */
@ -72,7 +120,4 @@ Java_sun_net_spi_SdpProvider_convert(JNIEnv *env, jclass cls, jint fd)
JNU_ThrowIOExceptionWithLastError(env, "dup2");
RESTARTABLE(close(s), res);
}
#else
JNU_ThrowInternalError(env, "should not reach here");
#endif
}

Some files were not shown because too many files have changed in this diff Show More