# HG changeset patch # User hseigel # Date 1419704827 18000 # Node ID e1bff46ea1e498304b939d4c2dde3f8c5489e713 # Parent 91f29bdf440be858430da01c444ea09fe45d0cdb# Parent 022799a053fedd52adfc277825b13f3d878194ab Merge diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; +import java.security.ProviderException; + /** * This class represents ciphers in cipher block chaining (CBC) mode. @@ -122,31 +124,31 @@ * *

The input plain text plain, starting at * plainOffset and ending at - * (plainOffset + len - 1), is encrypted. + * (plainOffset + plainLen - 1), is encrypted. * The result is stored in cipher, starting at * cipherOffset. * - *

It is the application's responsibility to make sure that - * plainLen is a multiple of the embedded cipher's block size, - * as any excess bytes are ignored. - * * @param plain the buffer with the input data to be encrypted * @param plainOffset the offset in plain * @param plainLen the length of the input data * @param cipher the buffer for the result * @param cipherOffset the offset in cipher + * @exception ProviderException if len is not + * a multiple of the block size * @return the length of the encrypted data */ int encrypt(byte[] plain, int plainOffset, int plainLen, byte[] cipher, int cipherOffset) { - int i; + if ((plainLen % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } int endIndex = plainOffset + plainLen; for (; plainOffset < endIndex; plainOffset+=blockSize, cipherOffset += blockSize) { - for (i=0; iThe input cipher text cipher, starting at * cipherOffset and ending at - * (cipherOffset + len - 1), is decrypted. + * (cipherOffset + cipherLen - 1), is decrypted. * The result is stored in plain, starting at * plainOffset. * - *

It is the application's responsibility to make sure that - * cipherLen is a multiple of the embedded cipher's block - * size, as any excess bytes are ignored. - * *

It is also the application's responsibility to make sure that * init has been called before this method is called. * (This check is omitted here, to avoid double checking.) @@ -176,23 +174,23 @@ * @param cipherLen the length of the input data * @param plain the buffer for the result * @param plainOffset the offset in plain + * @exception ProviderException if len is not + * a multiple of the block size * @return the length of the decrypted data - * - * @exception IllegalBlockSizeException if input data whose length does - * not correspond to the embedded cipher's block size is passed to the - * embedded cipher */ int decrypt(byte[] cipher, int cipherOffset, int cipherLen, byte[] plain, int plainOffset) { - int i; + if ((cipherLen % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } int endIndex = cipherOffset + cipherLen; for (; cipherOffset < endIndex; cipherOffset += blockSize, plainOffset += blockSize) { embeddedCipher.decryptBlock(cipher, cipherOffset, k, 0); - for (i = 0; i < blockSize; i++) { - plain[i+plainOffset] = (byte)(k[i] ^ r[i]); + for (int i = 0; i < blockSize; i++) { + plain[i + plainOffset] = (byte)(k[i] ^ r[i]); } System.arraycopy(cipher, cipherOffset, r, 0, blockSize); } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java Sat Dec 27 13:27:07 2014 -0500 @@ -708,7 +708,7 @@ len -= blockSize; } // do not count the trailing bytes which do not make up a unit - len = (len > 0 ? (len - (len%unitBytes)) : 0); + len = (len > 0 ? (len - (len % unitBytes)) : 0); // check output buffer capacity if ((output == null) || @@ -747,6 +747,9 @@ int bufferCapacity = buffer.length - buffered; if (bufferCapacity != 0) { temp = Math.min(bufferCapacity, inputConsumed); + if (unitBytes != blockSize) { + temp -= ((buffered + temp) % unitBytes); + } System.arraycopy(input, inputOffset, buffer, buffered, temp); inputOffset += temp; inputConsumed -= temp; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherFeedback.java --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherFeedback.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherFeedback.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; +import java.security.ProviderException; /** * This class represents ciphers in cipher-feedback (CFB) mode. @@ -133,66 +134,72 @@ * *

The input plain text plain, starting at * plainOffset and ending at - * (plainOffset + len - 1), is encrypted. + * (plainOffset + plainLen - 1), is encrypted. * The result is stored in cipher, starting at * cipherOffset. * - *

It is the application's responsibility to make sure that - * plainLen is a multiple of the stream unit size - * numBytes, as any excess bytes are ignored. - * - *

It is also the application's responsibility to make sure that - * init has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * * @param plain the buffer with the input data to be encrypted * @param plainOffset the offset in plain * @param plainLen the length of the input data * @param cipher the buffer for the result * @param cipherOffset the offset in cipher + * @exception ProviderException if plainLen is not + * a multiple of the numBytes * @return the length of the encrypted data */ int encrypt(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset) - { - int i, len; - len = blockSize - numBytes; + byte[] cipher, int cipherOffset) { + if ((plainLen % numBytes) != 0) { + throw new ProviderException("Internal error in input buffering"); + } + + int nShift = blockSize - numBytes; int loopCount = plainLen / numBytes; - int oddBytes = plainLen % numBytes; - if (len == 0) { - for (; loopCount > 0 ; - plainOffset += numBytes, cipherOffset += numBytes, - loopCount--) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i = 0; i < blockSize; i++) - register[i] = cipher[i+cipherOffset] = - (byte)(k[i] ^ plain[i+plainOffset]); + for (; loopCount > 0 ; + plainOffset += numBytes, cipherOffset += numBytes, + loopCount--) { + embeddedCipher.encryptBlock(register, 0, k, 0); + if (nShift != 0) { + System.arraycopy(register, numBytes, register, 0, nShift); + } + for (int i = 0; i < numBytes; i++) { + register[nShift + i] = cipher[i + cipherOffset] = + (byte)(k[i] ^ plain[i + plainOffset]); } - if (oddBytes > 0) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i=0; i 0 ; - plainOffset += numBytes, cipherOffset += numBytes, - loopCount--) { - embeddedCipher.encryptBlock(register, 0, k, 0); - System.arraycopy(register, numBytes, register, 0, len); - for (i=0; iThe input plain text plain, starting at + * plainOffset and ending at + * (plainOffset + plainLen - 1), is encrypted. + * The result is stored in cipher, starting at + * cipherOffset. + * + * @param plain the buffer with the input data to be encrypted + * @param plainOffset the offset in plain + * @param plainLen the length of the input data + * @param cipher the buffer for the result + * @param cipherOffset the offset in cipher + * @return the number of bytes placed into cipher + */ + int encryptFinal(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) { + + int oddBytes = plainLen % numBytes; + int len = encrypt(plain, plainOffset, (plainLen - oddBytes), + cipher, cipherOffset); + plainOffset += len; + cipherOffset += len; + if (oddBytes != 0) { + embeddedCipher.encryptBlock(register, 0, k, 0); + for (int i = 0; i < oddBytes; i++) { + cipher[i + cipherOffset] = + (byte)(k[i] ^ plain[i + plainOffset]); } } return plainLen; @@ -203,17 +210,52 @@ * *

The input cipher text cipher, starting at * cipherOffset and ending at - * (cipherOffset + len - 1), is decrypted. + * (cipherOffset + cipherLen - 1), is decrypted. * The result is stored in plain, starting at * plainOffset. * - *

It is the application's responsibility to make sure that - * cipherLen is a multiple of the stream unit size - * numBytes, as any excess bytes are ignored. + * @param cipher the buffer with the input data to be decrypted + * @param cipherOffset the offset in cipherOffset + * @param cipherLen the length of the input data + * @param plain the buffer for the result + * @param plainOffset the offset in plain + * @exception ProviderException if cipherLen is not + * a multiple of the numBytes + * @return the length of the decrypted data + */ + int decrypt(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) { + if ((cipherLen % numBytes) != 0) { + throw new ProviderException("Internal error in input buffering"); + } + + int nShift = blockSize - numBytes; + int loopCount = cipherLen / numBytes; + + for (; loopCount > 0; + plainOffset += numBytes, cipherOffset += numBytes, + loopCount--) { + embeddedCipher.encryptBlock(register, 0, k, 0); + if (nShift != 0) { + System.arraycopy(register, numBytes, register, 0, nShift); + } + for (int i = 0; i < numBytes; i++) { + register[i + nShift] = cipher[i + cipherOffset]; + plain[i + plainOffset] + = (byte)(cipher[i + cipherOffset] ^ k[i]); + } + } + return cipherLen; + } + + /** + * Performs the last decryption operation. * - *

It is also the application's responsibility to make sure that - * init has been called before this method is called. - * (This check is omitted here, to avoid double checking.) + *

The input cipher text cipher, starting at + * cipherOffset and ending at + * (cipherOffset + cipherLen - 1), is decrypted. + * The result is stored in plain, starting at + * plainOffset. * * @param cipher the buffer with the input data to be decrypted * @param cipherOffset the offset in cipherOffset @@ -222,53 +264,19 @@ * @param plainOffset the offset in plain * @return the length of the decrypted data */ - int decrypt(byte[] cipher, int cipherOffset, int cipherLen, - byte[] plain, int plainOffset) - { - int i, len; - len = blockSize - numBytes; - int loopCount = cipherLen / numBytes; - int oddBytes = cipherLen % numBytes; + int decryptFinal(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) { - if (len == 0) { - for (; loopCount > 0; - plainOffset += numBytes, cipherOffset += numBytes, - loopCount--) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i = 0; i < blockSize; i++) { - register[i] = cipher[i+cipherOffset]; - plain[i+plainOffset] - = (byte)(cipher[i+cipherOffset] ^ k[i]); - } - } - if (oddBytes > 0) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i=0; i 0; - plainOffset += numBytes, cipherOffset += numBytes, - loopCount--) { - embeddedCipher.encryptBlock(register, 0, k, 0); - System.arraycopy(register, numBytes, register, 0, len); - for (i=0; icipher, starting at * cipherOffset. * - *

It is the application's responsibility to make sure that - * plainLen is a multiple of the embedded cipher's block size, - * as any excess bytes are ignored. - * - *

It is also the application's responsibility to make sure that - * init has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * * @param in the buffer with the input data to be encrypted * @param inOffset the offset in plain * @param len the length of the input data @@ -155,30 +148,7 @@ return crypt(in, inOff, len, out, outOff); } - /** - * Performs decryption operation. - * - *

The input cipher text cipher, starting at - * cipherOffset and ending at - * (cipherOffset + len - 1), is decrypted. - * The result is stored in plain, starting at - * plainOffset. - * - *

It is the application's responsibility to make sure that - * cipherLen is a multiple of the embedded cipher's block - * size, as any excess bytes are ignored. - * - *

It is also the application's responsibility to make sure that - * init has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * - * @param in the buffer with the input data to be decrypted - * @param inOff the offset in cipherOffset - * @param len the length of the input data - * @param out the buffer for the result - * @param outOff the offset in plain - * @return the length of the decrypted data - */ + // CTR encrypt and decrypt are identical int decrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { return crypt(in, inOff, len, out, outOff); } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; +import java.security.ProviderException; /** * This class represents ciphers in electronic codebook (ECB) mode. @@ -96,28 +97,24 @@ /** * Performs encryption operation. * - *

The input plain text plain, starting at - * plainOffset and ending at - * (plainOffset + len - 1), is encrypted. - * The result is stored in cipher, starting at - * cipherOffset. - * - *

It is the application's responsibility to make sure that - * plainLen is a multiple of the embedded cipher's block size, - * as any excess bytes are ignored. - * - *

It is also the application's responsibility to make sure that - * init has been called before this method is called. - * (This check is omitted here, to avoid double checking.) + *

The input plain text in, starting at + * inOff and ending at * (inOff + len - 1), + * is encrypted. The result is stored in out, starting at + * outOff. * * @param in the buffer with the input data to be encrypted - * @param inOffset the offset in plain + * @param inOff the offset in plain * @param len the length of the input data * @param out the buffer for the result * @param outOff the offset in cipher + * @exception ProviderException if len is not + * a multiple of the block size * @return the length of the encrypted data */ int encrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { + if ((len % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } for (int i = len; i >= blockSize; i -= blockSize) { embeddedCipher.encryptBlock(in, inOff, out, outOff); inOff += blockSize; @@ -129,28 +126,24 @@ /** * Performs decryption operation. * - *

The input cipher text cipher, starting at - * cipherOffset and ending at - * (cipherOffset + len - 1), is decrypted. - * The result is stored in plain, starting at - * plainOffset. - * - *

It is the application's responsibility to make sure that - * cipherLen is a multiple of the embedded cipher's block - * size, as any excess bytes are ignored. - * - *

It is also the application's responsibility to make sure that - * init has been called before this method is called. - * (This check is omitted here, to avoid double checking.) + *

The input cipher text in, starting at + * inOff and ending at * (inOff + len - 1), + * is decrypted.The result is stored in out, starting at + * outOff. * * @param in the buffer with the input data to be decrypted * @param inOff the offset in cipherOffset * @param len the length of the input data * @param out the buffer for the result * @param outOff the offset in plain + * @exception ProviderException if len is not + * a multiple of the block size * @return the length of the decrypted data */ int decrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { + if ((len % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } for (int i = len; i >= blockSize; i -= blockSize) { embeddedCipher.decryptBlock(in, inOff, out, outOff); inOff += blockSize; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -371,21 +371,19 @@ * and ending at (inOff + len - 1), is encrypted. The result * is stored in out, starting at outOfs. * - *

It is the application's responsibility to make sure that - * len is a multiple of the embedded cipher's block size, - * otherwise, a ProviderException will be thrown. - * - *

It is also the application's responsibility to make sure that - * init has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * * @param in the buffer with the input data to be encrypted * @param inOfs the offset in in * @param len the length of the input data * @param out the buffer for the result * @param outOfs the offset in out + * @exception ProviderException if len is not + * a multiple of the block size + * @return the number of bytes placed into the out buffer */ int encrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) { + if ((len % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } processAAD(); if (len > 0) { gctrPAndC.update(in, inOfs, len, out, outOfs); @@ -398,9 +396,6 @@ /** * Performs encryption operation for the last time. * - *

NOTE: len may not be multiple of the embedded - * cipher's block size for this call. - * * @param in the input buffer with the data to be encrypted * @param inOfs the offset in in * @param len the length of the input data @@ -439,21 +434,19 @@ * is decrypted. The result is stored in out, starting at * outOfs. * - *

It is the application's responsibility to make sure that - * len is a multiple of the embedded cipher's block - * size, as any excess bytes are ignored. - * - *

It is also the application's responsibility to make sure that - * init has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * * @param in the buffer with the input data to be decrypted * @param inOfs the offset in in * @param len the length of the input data * @param out the buffer for the result * @param outOfs the offset in out + * @exception ProviderException if len is not + * a multiple of the block size + * @return the number of bytes placed into the out buffer */ int decrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) { + if ((len % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } processAAD(); if (len > 0) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java Sat Dec 27 13:27:07 2014 -0500 @@ -898,4 +898,20 @@ md.update("Mighty Aphrodite".getBytes("UTF8")); return md; } + + /** + * Probe the first few bytes of the keystore data stream for a valid + * JCEKS keystore encoding. + */ + @Override + public boolean engineProbe(InputStream stream) throws IOException { + DataInputStream dataStream; + if (stream instanceof DataInputStream) { + dataStream = (DataInputStream)stream; + } else { + dataStream = new DataInputStream(stream); + } + + return JCEKS_MAGIC == dataStream.readInt(); + } } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/com/sun/crypto/provider/OutputFeedback.java --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/OutputFeedback.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/OutputFeedback.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; +import java.security.ProviderException; /** * This class represents ciphers in output-feedback (OFB) mode. @@ -132,17 +133,52 @@ * *

The input plain text plain, starting at * plainOffset and ending at - * (plainOffset + len - 1), is encrypted. + * (plainOffset + plainLen - 1), is encrypted. * The result is stored in cipher, starting at * cipherOffset. * - *

It is the application's responsibility to make sure that - * plainLen is a multiple of the stream unit size - * numBytes, as any excess bytes are ignored. + * @param plain the buffer with the input data to be encrypted + * @param plainOffset the offset in plain + * @param plainLen the length of the input data + * @param cipher the buffer for the result + * @param cipherOffset the offset in cipher + * @exception ProviderException if plainLen is not + * a multiple of the numBytes + * @return the length of the encrypted data + */ + int encrypt(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) { + + if ((plainLen % numBytes) != 0) { + throw new ProviderException("Internal error in input buffering"); + } + int nShift = blockSize - numBytes; + int loopCount = plainLen / numBytes; + + for (; loopCount > 0; + plainOffset += numBytes, cipherOffset += numBytes, + loopCount--) { + embeddedCipher.encryptBlock(register, 0, k, 0); + for (int i = 0; i < numBytes; i++) { + cipher[i + cipherOffset] = + (byte)(k[i] ^ plain[i + plainOffset]); + if (nShift != 0) { + System.arraycopy(register, numBytes, register, 0, nShift); + } + System.arraycopy(k, 0, register, nShift, numBytes); + } + } + return plainLen; + } + + /** + * Performs last encryption operation. * - *

It is also the application's responsibility to make sure that - * init has been called before this method is called. - * (This check is omitted here, to avoid double checking.) + *

The input plain text plain, starting at + * plainOffset and ending at + * (plainOffset + plainLen - 1), is encrypted. + * The result is stored in cipher, starting at + * cipherOffset. * * @param plain the buffer with the input data to be encrypted * @param plainOffset the offset in plain @@ -151,82 +187,34 @@ * @param cipherOffset the offset in cipher * @return the length of the encrypted data */ - int encrypt(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset) - { - int i; - int len = blockSize - numBytes; - int loopCount = plainLen / numBytes; + int encryptFinal(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) { int oddBytes = plainLen % numBytes; + int len = encrypt(plain, plainOffset, (plainLen - oddBytes), + cipher, cipherOffset); + plainOffset += len; + cipherOffset += len; - if (len == 0) { - for (; loopCount > 0; - plainOffset += numBytes, cipherOffset += numBytes, - loopCount--) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i=0; i 0) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i=0; i 0; - plainOffset += numBytes, cipherOffset += numBytes, - loopCount--) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i=0; i 0) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i=0; iThe input cipher text cipher, starting at - * cipherOffset and ending at - * (cipherOffset + len - 1), is decrypted. - * The result is stored in plain, starting at - * plainOffset. - * - *

It is the application's responsibility to make sure that - * cipherLen is a multiple of the stream unit size - * numBytes, as any excess bytes are ignored. - * - *

It is also the application's responsibility to make sure that - * init has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * - * @param cipher the buffer with the input data to be decrypted - * @param cipherOffset the offset in cipherOffset - * @param cipherLen the length of the input data - * @param plain the buffer for the result - * @param plainOffset the offset in plain - * @return the length of the decrypted data - */ + // OFB encrypt and decrypt are identical int decrypt(byte[] cipher, int cipherOffset, int cipherLen, - byte[] plain, int plainOffset) - { - // OFB encrypt and decrypt are identical + byte[] plain, int plainOffset) { return encrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); } + + // OFB encrypt and decrypt are identical + int decryptFinal(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) { + // OFB encrypt and decrypt are identical + return encryptFinal(cipher, cipherOffset, cipherLen, plain, plainOffset); + } } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/com/sun/crypto/provider/PCBC.java --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/PCBC.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PCBC.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; +import java.security.ProviderException; + /** * This class represents ciphers in Plaintext Cipher Block Chaining (PCBC) @@ -118,38 +120,36 @@ * *

The input plain text plain, starting at * plainOffset and ending at - * (plainOffset + len - 1), is encrypted. + * (plainOffset + plainLen - 1), is encrypted. * The result is stored in cipher, starting at * cipherOffset. * - *

It is the application's responsibility to make sure that - * plainLen is a multiple of the embedded cipher's block size, - * as any excess bytes are ignored. - * - *

It is also the application's responsibility to make sure that - * init has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * * @param plain the buffer with the input data to be encrypted * @param plainOffset the offset in plain * @param plainLen the length of the input data * @param cipher the buffer for the result * @param cipherOffset the offset in cipher + * @exception ProviderException if plainLen is not + * a multiple of the block size + * @return the length of the encrypted data */ int encrypt(byte[] plain, int plainOffset, int plainLen, byte[] cipher, int cipherOffset) { + if ((plainLen % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } int i; int endIndex = plainOffset + plainLen; for (; plainOffset < endIndex; plainOffset += blockSize, cipherOffset += blockSize) { - for (i=0; iThe input cipher text cipher, starting at * cipherOffset and ending at - * (cipherOffset + len - 1), is decrypted. + * (cipherOffset + cipherLen - 1), is decrypted. * The result is stored in plain, starting at * plainOffset. * - *

It is the application's responsibility to make sure that - * cipherLen is a multiple of the embedded cipher's block - * size, as any excess bytes are ignored. - * - *

It is also the application's responsibility to make sure that - * init has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * * @param cipher the buffer with the input data to be decrypted * @param cipherOffset the offset in cipherOffset * @param cipherLen the length of the input data * @param plain the buffer for the result * @param plainOffset the offset in plain + * @exception ProviderException if cipherLen is not + * a multiple of the block size + * @return the length of the decrypted data */ int decrypt(byte[] cipher, int cipherOffset, int cipherLen, byte[] plain, int plainOffset) { + if ((cipherLen % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } int i; int endIndex = cipherOffset + cipherLen; @@ -189,10 +187,10 @@ embeddedCipher.decryptBlock(cipher, cipherOffset, plain, plainOffset); for (i = 0; i < blockSize; i++) { - plain[i+plainOffset] ^= k[i]; + plain[i + plainOffset] ^= k[i]; } for (i = 0; i < blockSize; i++) { - k[i] = (byte)(plain[i+plainOffset] ^ cipher[i+cipherOffset]); + k[i] = (byte)(plain[i + plainOffset] ^ cipher[i + cipherOffset]); } } return cipherLen; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/java/nio/file/Path.java --- a/jdk/src/java.base/share/classes/java/nio/file/Path.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/java/nio/file/Path.java Sat Dec 27 13:27:07 2014 -0500 @@ -29,6 +29,7 @@ import java.io.IOException; import java.net.URI; import java.util.Iterator; +import java.util.NoSuchElementException; /** * An object that may be used to locate a file in a file system. It will @@ -246,6 +247,12 @@ * "{@code foo/bar}" starts with "{@code foo}" and "{@code foo/bar}". It * does not start with "{@code f}" or "{@code fo}". * + * @implSpec + * The default implementation is equivalent for this path to: + *

{@code
+     *     startsWith(getFileSystem().getPath(other));
+     * }
+ * * @param other * the given path string * @@ -255,7 +262,9 @@ * @throws InvalidPathException * If the path string cannot be converted to a Path. */ - boolean startsWith(String other); + default boolean startsWith(String other) { + return startsWith(getFileSystem().getPath(other)); + } /** * Tests if this path ends with the given path. @@ -294,6 +303,12 @@ * Path}"{@code foo/bar}" with the {@code String} "{@code bar/}" returns * {@code true}. * + * @implSpec + * The default implementation is equivalent for this path to: + *
{@code
+     *     endsWith(getFileSystem().getPath(other));
+     * }
+ * * @param other * the given path string * @@ -303,7 +318,9 @@ * @throws InvalidPathException * If the path string cannot be converted to a Path. */ - boolean endsWith(String other); + default boolean endsWith(String other) { + return endsWith(getFileSystem().getPath(other)); + } /** * Returns a path that is this path with redundant name elements eliminated. @@ -365,6 +382,12 @@ * invoking this method with the path string "{@code gus}" will result in * the {@code Path} "{@code foo/bar/gus}". * + * @implSpec + * The default implementation is equivalent for this path to: + *
{@code
+     *     resolve(getFileSystem().getPath(other));
+     * }
+ * * @param other * the path string to resolve against this path * @@ -375,7 +398,9 @@ * * @see FileSystem#getPath */ - Path resolve(String other); + default Path resolve(String other) { + return resolve(getFileSystem().getPath(other)); + } /** * Resolves the given path against this path's {@link #getParent parent} @@ -389,6 +414,14 @@ * returns this path's parent, or where this path doesn't have a parent, the * empty path. * + * @implSpec + * The default implementation is equivalent for this path to: + *
{@code
+     *     (getParent() == null) ? other : getParent().resolve(other);
+     * }
+ * unless {@code other == null}, in which case a + * {@code NullPointerException} is thrown. + * * @param other * the path to resolve against this path's parent * @@ -396,13 +429,24 @@ * * @see #resolve(Path) */ - Path resolveSibling(Path other); + default Path resolveSibling(Path other) { + if (other == null) + throw new NullPointerException(); + Path parent = getParent(); + return (parent == null) ? other : parent.resolve(other); + } /** * Converts a given path string to a {@code Path} and resolves it against * this path's {@link #getParent parent} path in exactly the manner * specified by the {@link #resolveSibling(Path) resolveSibling} method. * + * @implSpec + * The default implementation is equivalent for this path to: + *
{@code
+     *     resolveSibling(getFileSystem().getPath(other));
+     * }
+ * * @param other * the path string to resolve against this path's parent * @@ -413,7 +457,9 @@ * * @see FileSystem#getPath */ - Path resolveSibling(String other); + default Path resolveSibling(String other) { + return resolveSibling(getFileSystem().getPath(other)); + } /** * Constructs a relative path between this path and a given path. @@ -590,12 +636,28 @@ * File} object returned by this method is {@link #equals equal} to the * original {@code File}. * + * @implSpec + * The default implementation is equivalent for this path to: + *
{@code
+     *     new File(toString());
+     * }
+ * if the {@code FileSystem} which created this {@code Path} is the default + * file system; otherwise an {@code UnsupportedOperationException} is + * thrown. + * * @return a {@code File} object representing this path * * @throws UnsupportedOperationException * if this {@code Path} is not associated with the default provider */ - File toFile(); + default File toFile() { + if (getFileSystem() == FileSystems.getDefault()) { + return new File(toString()); + } else { + throw new UnsupportedOperationException("Path not associated with " + + "default file system."); + } + } // -- watchable -- @@ -681,6 +743,13 @@ * * WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); * + * + * @implSpec + * The default implementation is equivalent for this path to: + *
{@code
+     *     register(watcher, events, new WatchEvent.Modifier[0]);
+     * }
+ * * @param watcher * The watch service to which this object is to be registered * @param events @@ -706,9 +775,10 @@ * method is invoked to check read access to the file. */ @Override - WatchKey register(WatchService watcher, - WatchEvent.Kind... events) - throws IOException; + default WatchKey register(WatchService watcher, + WatchEvent.Kind... events) throws IOException { + return register(watcher, events, new WatchEvent.Modifier[0]); + } // -- Iterable -- @@ -721,10 +791,36 @@ * is the name of the file or directory denoted by this path. The {@link * #getRoot root} component, if present, is not returned by the iterator. * + * @implSpec + * The default implementation returns an {@code Iterator} which, for + * this path, traverses the {@code Path}s returned by + * {@code getName(index)}, where {@code index} ranges from zero to + * {@code getNameCount() - 1}, inclusive. + * * @return an iterator over the name elements of this path. */ @Override - Iterator iterator(); + default Iterator iterator() { + return new Iterator() { + private int i = 0; + + @Override + public boolean hasNext() { + return (i < getNameCount()); + } + + @Override + public Path next() { + if (i < getNameCount()) { + Path result = getName(i); + i++; + return result; + } else { + throw new NoSuchElementException(); + } + } + }; + } // -- compareTo/equals/hashCode -- diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/java/security/KeyStore.java --- a/jdk/src/java.base/share/classes/java/security/KeyStore.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/java/security/KeyStore.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,9 +92,23 @@ * be used (in a variety of formats). * *

Typical ways to request a KeyStore object include + * specifying an existing keystore file, * relying on the default type and providing a specific keystore type. * *

    + *
  • To specify an existing keystore file: + *
    + *    // get keystore password
    + *    char[] password = getPassword();
    + *
    + *    // probe the keystore file and load the keystore entries
    + *    KeyStore ks = KeyStore.getInstance(new File("keyStoreName"), password);
    + *
    + * The system will probe the specified file to determine its keystore type + * and return a keystore implementation with its entries already loaded. + * When this approach is used there is no need to call the keystore's + * {@link #load(java.io.InputStream, char[]) load} method. + * *
  • To rely on the default type: *
      *    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    @@ -110,7 +124,8 @@
      * 
* *

Before a keystore can be accessed, it must be - * {@link #load(java.io.InputStream, char[]) loaded}. + * {@link #load(java.io.InputStream, char[]) loaded} + * (unless it was already loaded during instantiation). *

  *    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
  *
@@ -179,6 +194,7 @@
 
 public class KeyStore {
 
+    private static final Debug kdebug = Debug.getInstance("keystore");
     private static final Debug pdebug =
                         Debug.getInstance("provider", "Provider");
     private static final boolean skipDebug =
@@ -1594,6 +1610,188 @@
     }
 
     /**
+     * Returns a loaded keystore object of the appropriate keystore type.
+     * First the keystore type is determined by probing the specified file.
+     * Then a keystore object is instantiated and loaded using the data from
+     * that file.
+     * A password may be supplied to unlock the keystore data or perform an
+     * integrity check.
+     *
+     * 

+ * This method traverses the list of registered security {@link Providers}, + * starting with the most preferred Provider. + * For each {@link KeyStoreSpi} implementation supported by a Provider, + * it invokes the {@link engineProbe} method to determine if it supports + * the specified keystore. + * A new KeyStore object is returned that encapsulates the KeyStoreSpi + * implementation from the first Provider that supports the specified file. + * + *

Note that the list of registered providers may be retrieved via + * the {@link Security#getProviders() Security.getProviders()} method. + * + * @param file the keystore file + * @param password the keystore password, which may be {@code null} + * + * @return a keystore object loaded with keystore data + * + * @throws KeyStoreException if no Provider supports a KeyStoreSpi + * implementation for the specified keystore file. + * @throws IOException if there is an I/O or format problem with the + * keystore data, if a password is required but not given, + * or if the given password was incorrect. If the error is + * due to a wrong password, the {@link Throwable#getCause cause} + * of the {@code IOException} should be an + * {@code UnrecoverableKeyException}. + * @throws NoSuchAlgorithmException if the algorithm used to check the + * integrity of the keystore cannot be found. + * @throws CertificateException if any of the certificates in the + * keystore could not be loaded. + * @throws IllegalArgumentException if file does not exist or does not + * refer to a normal file. + * @throws NullPointerException if file is {@code null}. + * @throws SecurityException if a security manager exists and its + * {@link java.lang.SecurityManager#checkRead} method denies + * read access to the specified file. + * + * @see Provider + * + * @since 1.9 + */ + public static final KeyStore getInstance(File file, char[] password) + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException { + return getInstance(file, password, null, true); + } + + /** + * Returns a loaded keystore object of the appropriate keystore type. + * First the keystore type is determined by probing the specified file. + * Then a keystore object is instantiated and loaded using the data from + * that file. + * A {@code LoadStoreParameter} may be supplied which specifies how to + * unlock the keystore data or perform an integrity check. + * + *

+ * This method traverses the list of registered security {@link Providers}, + * starting with the most preferred Provider. + * For each {@link KeyStoreSpi} implementation supported by a Provider, + * it invokes the {@link engineProbe} method to determine if it supports + * the specified keystore. + * A new KeyStore object is returned that encapsulates the KeyStoreSpi + * implementation from the first Provider that supports the specified file. + * + *

Note that the list of registered providers may be retrieved via + * the {@link Security#getProviders() Security.getProviders()} method. + * + * @param file the keystore file + * @param param the {@code LoadStoreParameter} that specifies how to load + * the keystore, which may be {@code null} + * + * @return a keystore object loaded with keystore data + * + * @throws KeyStoreException if no Provider supports a KeyStoreSpi + * implementation for the specified keystore file. + * @throws IOException if there is an I/O or format problem with the + * keystore data. If the error is due to an incorrect + * {@code ProtectionParameter} (e.g. wrong password) + * the {@link Throwable#getCause cause} of the + * {@code IOException} should be an + * {@code UnrecoverableKeyException}. + * @throws NoSuchAlgorithmException if the algorithm used to check the + * integrity of the keystore cannot be found. + * @throws CertificateException if any of the certificates in the + * keystore could not be loaded. + * @throws IllegalArgumentException if file does not exist or does not + * refer to a normal file, or if param is not recognized. + * @throws NullPointerException if file is {@code null}. + * @throws SecurityException if a security manager exists and its + * {@link java.lang.SecurityManager#checkRead} method denies + * read access to the specified file. + * + * @see Provider + * + * @since 1.9 + */ + public static final KeyStore getInstance(File file, + LoadStoreParameter param) throws KeyStoreException, IOException, + NoSuchAlgorithmException, CertificateException { + return getInstance(file, null, param, false); + } + + // Used by getInstance(File, char[]) & getInstance(File, LoadStoreParameter) + private static final KeyStore getInstance(File file, char[] password, + LoadStoreParameter param, boolean hasPassword) + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException { + + if (file == null) { + throw new NullPointerException(); + } + + if (file.isFile() == false) { + throw new IllegalArgumentException( + "File does not exist or it does not refer to a normal file: " + + file); + } + + KeyStore keystore = null; + + try (DataInputStream dataStream = + new DataInputStream( + new BufferedInputStream( + new FileInputStream(file)))) { + + dataStream.mark(Integer.MAX_VALUE); + + // Detect the keystore type + for (String type : Security.getAlgorithms("KeyStore")) { + Object[] objs = null; + + try { + objs = Security.getImpl(type, "KeyStore", (String)null); + + KeyStoreSpi impl = (KeyStoreSpi)objs[0]; + if (impl.engineProbe(dataStream)) { + + if (kdebug != null) { + kdebug.println(type + " keystore detected: " + + file); + } + + keystore = new KeyStore(impl, (Provider)objs[1], type); + break; + } + } catch (NoSuchAlgorithmException | NoSuchProviderException e) { + // ignore + if (kdebug != null) { + kdebug.println(type + " not found - " + e); + } + } catch (IOException e) { + // ignore + if (kdebug != null) { + kdebug.println("I/O error in " + file + " - " + e); + } + } + dataStream.reset(); // prepare the stream for the next probe + } + + // Load the keystore data + if (keystore != null) { + if (hasPassword) { + dataStream.reset(); // prepare the stream for loading + keystore.load(dataStream, password); + } else { + keystore.load(param); + } + return keystore; + } + } + + throw new KeyStoreException("Unrecognized keystore format: " + + keystore); + } + + /** * A description of a to-be-instantiated KeyStore object. * *

An instance of this class encapsulates the information needed to @@ -1713,7 +1911,7 @@ * by invoking the CallbackHandler. * *

Subsequent calls to {@link #getKeyStore} return the same object - * as the initial call. If the initial call to failed with a + * as the initial call. If the initial call failed with a * KeyStoreException, subsequent calls also throw a * KeyStoreException. * @@ -1760,6 +1958,50 @@ AccessController.getContext()); } + /** + * Returns a new Builder object. + * + *

The first call to the {@link #getKeyStore} method on the returned + * builder will create a KeyStore using {@code file} to detect the + * keystore type and then call its {@link KeyStore#load load()} method. + * It uses the same algorithm to determine the keystore type as + * described in {@link KeyStore#getInstance(File, LoadStoreParameter)}. + * The {@code inputStream} argument is constructed from {@code file}. + * If {@code protection} is a {@code PasswordProtection}, the password + * is obtained by calling the {@code getPassword} method. + * Otherwise, if {@code protection} is a + * {@code CallbackHandlerProtection}, + * the password is obtained by invoking the CallbackHandler. + * + *

Subsequent calls to {@link #getKeyStore} return the same object + * as the initial call. If the initial call failed with a + * KeyStoreException, subsequent calls also throw a KeyStoreException. + * + *

Calls to {@link #getProtectionParameter getProtectionParameter()} + * will return a {@link KeyStore.PasswordProtection PasswordProtection} + * object encapsulating the password that was used to invoke the + * {@code load} method. + * + *

Note that the {@link #getKeyStore} method is executed + * within the {@link AccessControlContext} of the code invoking this + * method. + * + * @return a new Builder object + * @param file the File that contains the KeyStore data + * @param protection the ProtectionParameter securing the KeyStore data + * @throws NullPointerException if file or protection is null + * @throws IllegalArgumentException if protection is not an instance + * of either PasswordProtection or CallbackHandlerProtection; or + * if file does not exist or does not refer to a normal file + * + * @since 1.9 + */ + public static Builder newInstance(File file, + ProtectionParameter protection) { + + return newInstance("", null, file, protection); + } + private static final class FileBuilder extends Builder { private final String type; @@ -1817,42 +2059,46 @@ } public KeyStore run0() throws Exception { KeyStore ks; - if (provider == null) { - ks = KeyStore.getInstance(type); + char[] password = null; + + // Acquire keystore password + if (protection instanceof PasswordProtection) { + password = + ((PasswordProtection)protection).getPassword(); + keyProtection = protection; } else { - ks = KeyStore.getInstance(type, provider); - } - InputStream in = null; - char[] password = null; - try { - in = new FileInputStream(file); - if (protection instanceof PasswordProtection) { - password = - ((PasswordProtection)protection).getPassword(); - keyProtection = protection; - } else { - CallbackHandler handler = - ((CallbackHandlerProtection)protection) + CallbackHandler handler = + ((CallbackHandlerProtection)protection) .getCallbackHandler(); - PasswordCallback callback = new PasswordCallback - ("Password for keystore " + file.getName(), + PasswordCallback callback = new PasswordCallback + ("Password for keystore " + file.getName(), false); - handler.handle(new Callback[] {callback}); - password = callback.getPassword(); - if (password == null) { - throw new KeyStoreException("No password" + - " provided"); - } - callback.clearPassword(); - keyProtection = new PasswordProtection(password); + handler.handle(new Callback[] {callback}); + password = callback.getPassword(); + if (password == null) { + throw new KeyStoreException("No password" + + " provided"); } - ks.load(in, password); - return ks; - } finally { - if (in != null) { - in.close(); + callback.clearPassword(); + keyProtection = new PasswordProtection(password); + } + + if (type.isEmpty()) { + // Instantiate keystore and load keystore data + ks = KeyStore.getInstance(file, password); + } else { + // Instantiate keystore + if (provider == null) { + ks = KeyStore.getInstance(type); + } else { + ks = KeyStore.getInstance(type, provider); + } + // Load keystore data + try (InputStream in = new FileInputStream(file)) { + ks.load(in, password); } } + return ks; } }; try { @@ -1998,5 +2244,4 @@ return protection; } } - } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java --- a/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -590,4 +590,27 @@ } return false; } + + /** + * Probes the specified input stream to determine whether it contains a + * keystore that is supported by this implementation, or not. + * + *

+ * @implSpec + * This method returns false by default. Keystore implementations should + * override this method to peek at the data stream directly or to use other + * content detection mechanisms. + * + * @param stream the keystore data to be probed + * + * @return true if the keystore data is supported, otherwise false + * + * @throws IOException if there is an I/O problem with the keystore data. + * @throws NullPointerException if stream is {@code null}. + * + * @since 1.9 + */ + public boolean engineProbe(InputStream stream) throws IOException { + return false; + } } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/sun/nio/fs/AbstractPath.java --- a/jdk/src/java.base/share/classes/sun/nio/fs/AbstractPath.java Sat Dec 27 07:09:32 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.nio.fs; - -import java.nio.file.*; -import java.io.File; -import java.io.IOException; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Base implementation class of {@code Path}. - */ - -abstract class AbstractPath implements Path { - protected AbstractPath() { } - - @Override - public final boolean startsWith(String other) { - return startsWith(getFileSystem().getPath(other)); - } - - @Override - public final boolean endsWith(String other) { - return endsWith(getFileSystem().getPath(other)); - } - - @Override - public final Path resolve(String other) { - return resolve(getFileSystem().getPath(other)); - } - - @Override - public final Path resolveSibling(Path other) { - if (other == null) - throw new NullPointerException(); - Path parent = getParent(); - return (parent == null) ? other : parent.resolve(other); - } - - @Override - public final Path resolveSibling(String other) { - return resolveSibling(getFileSystem().getPath(other)); - } - - @Override - public final Iterator iterator() { - return new Iterator() { - private int i = 0; - @Override - public boolean hasNext() { - return (i < getNameCount()); - } - @Override - public Path next() { - if (i < getNameCount()) { - Path result = getName(i); - i++; - return result; - } else { - throw new NoSuchElementException(); - } - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - public final File toFile() { - return new File(toString()); - } - - @Override - public final WatchKey register(WatchService watcher, - WatchEvent.Kind... events) - throws IOException - { - return register(watcher, events, new WatchEvent.Modifier[0]); - } -} diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java --- a/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Sat Dec 27 13:27:07 2014 -0500 @@ -69,6 +69,8 @@ import sun.security.pkcs.ContentInfo; import sun.security.x509.AlgorithmId; import sun.security.pkcs.EncryptedPrivateKeyInfo; +import sun.security.provider.JavaKeyStore.JKS; +import sun.security.util.KeyStoreDelegator; /** @@ -129,6 +131,13 @@ */ public final class PKCS12KeyStore extends KeyStoreSpi { + // special PKCS12 keystore that supports PKCS12 and JKS file formats + public static final class DualFormatPKCS12 extends KeyStoreDelegator { + public DualFormatPKCS12() { + super("PKCS12", PKCS12KeyStore.class, "JKS", JKS.class); + } + } + public static final int VERSION_3 = 3; private static final String[] KEY_PROTECTION_ALGORITHM = { @@ -1053,6 +1062,39 @@ } /** + * Determines if the keystore {@code Entry} for the specified + * {@code alias} is an instance or subclass of the specified + * {@code entryClass}. + * + * @param alias the alias name + * @param entryClass the entry class + * + * @return true if the keystore {@code Entry} for the specified + * {@code alias} is an instance or subclass of the + * specified {@code entryClass}, false otherwise + * + * @since 1.5 + */ + @Override + public boolean + engineEntryInstanceOf(String alias, + Class entryClass) + { + if (entryClass == KeyStore.TrustedCertificateEntry.class) { + return engineIsCertificateEntry(alias); + } + + Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH)); + if (entryClass == KeyStore.PrivateKeyEntry.class) { + return (entry != null && entry instanceof PrivateKeyEntry); + } + if (entryClass == KeyStore.SecretKeyEntry.class) { + return (entry != null && entry instanceof SecretKeyEntry); + } + return false; + } + + /** * Returns the (alias) name of the first keystore entry whose certificate * matches the given certificate. * @@ -1084,7 +1126,7 @@ } else { continue; } - if (certElem.equals(cert)) { + if (certElem != null && certElem.equals(cert)) { return alias; } } @@ -1923,7 +1965,12 @@ safeContentsData = safeContents.getData(); } else if (contentType.equals((Object)ContentInfo.ENCRYPTED_DATA_OID)) { if (password == null) { - continue; + + if (debug != null) { + debug.println("Warning: skipping PKCS#7 encryptedData" + + " content-type - no password was supplied"); + } + continue; } if (debug != null) { @@ -1965,8 +2012,9 @@ password = new char[1]; continue; } - throw new IOException( - "failed to decrypt safe contents entry: " + e, e); + throw new IOException("keystore password was incorrect", + new UnrecoverableKeyException( + "failed to decrypt safe contents entry: " + e)); } } } else { @@ -2284,4 +2332,73 @@ counter++; return (String.valueOf(counter)); } + + /* + * PKCS12 permitted first 24 bytes: + * + * 30 82 -- -- 02 01 03 30 82 -- -- 06 09 2A 86 48 86 F7 0D 01 07 01 A0 8- + * 30 -- 02 01 03 30 -- 06 09 2A 86 48 86 F7 0D 01 07 01 A0 -- 04 -- -- -- + * 30 81 -- 02 01 03 30 81 -- 06 09 2A 86 48 86 F7 0D 01 07 01 A0 81 -- 04 + * 30 82 -- -- 02 01 03 30 81 -- 06 09 2A 86 48 86 F7 0D 01 07 01 A0 81 -- + * 30 83 -- -- -- 02 01 03 30 82 -- -- 06 09 2A 86 48 86 F7 0D 01 07 01 A0 + * 30 83 -- -- -- 02 01 03 30 83 -- -- -- 06 09 2A 86 48 86 F7 0D 01 07 01 + * 30 84 -- -- -- -- 02 01 03 30 83 -- -- -- 06 09 2A 86 48 86 F7 0D 01 07 + * 30 84 -- -- -- -- 02 01 03 30 84 -- -- -- -- 06 09 2A 86 48 86 F7 0D 01 + */ + + private static final long[][] PKCS12_HEADER_PATTERNS = { + { 0x3082000002010330L, 0x82000006092A8648L, 0x86F70D010701A080L }, + { 0x3000020103300006L, 0x092A864886F70D01L, 0x0701A00004000000L }, + { 0x3081000201033081L, 0x0006092A864886F7L, 0x0D010701A0810004L }, + { 0x3082000002010330L, 0x810006092A864886L, 0xF70D010701A08100L }, + { 0x3083000000020103L, 0x3082000006092A86L, 0x4886F70D010701A0L }, + { 0x3083000000020103L, 0x308200000006092AL, 0x864886F70D010701L }, + { 0x3084000000000201L, 0x0330820000000609L, 0x2A864886F70D0107L }, + { 0x3084000000000201L, 0x0330820000000006L, 0x092A864886F70D01L } + }; + + private static final long[][] PKCS12_HEADER_MASKS = { + { 0xFFFF0000FFFFFFFFL, 0xFF0000FFFFFFFFFFL, 0xFFFFFFFFFFFFFFF0L }, + { 0xFF00FFFFFFFF00FFL, 0xFFFFFFFFFFFFFFFFL, 0xFFFFFF00FF000000L }, + { 0xFFFF00FFFFFFFFFFL, 0x00FFFFFFFFFFFFFFL, 0xFFFFFFFFFFFF00FFL }, + { 0xFFFF0000FFFFFFFFL, 0xFF00FFFFFFFFFFFFL, 0xFFFFFFFFFFFFFF00L }, + { 0xFFFF000000FFFFFFL, 0xFFFF0000FFFFFFFFL, 0xFFFFFFFFFFFFFFFFL }, + { 0xFFFF000000FFFFFFL, 0xFFFF000000FFFFFFL, 0xFFFFFFFFFFFFFFFFL }, + { 0xFFFF00000000FFFFL, 0xFFFFFF000000FFFFL, 0xFFFFFFFFFFFFFFFFL }, + { 0xFFFF00000000FFFFL, 0xFFFFFF00000000FFL, 0xFFFFFFFFFFFFFFFFL } + }; + + /** + * Probe the first few bytes of the keystore data stream for a valid + * PKCS12 keystore encoding. + */ + @Override + public boolean engineProbe(InputStream stream) throws IOException { + + DataInputStream dataStream; + if (stream instanceof DataInputStream) { + dataStream = (DataInputStream)stream; + } else { + dataStream = new DataInputStream(stream); + } + + long firstPeek = dataStream.readLong(); + long nextPeek = dataStream.readLong(); + long finalPeek = dataStream.readLong(); + boolean result = false; + + for (int i = 0; i < PKCS12_HEADER_PATTERNS.length; i++) { + if (PKCS12_HEADER_PATTERNS[i][0] == + (firstPeek & PKCS12_HEADER_MASKS[i][0]) && + (PKCS12_HEADER_PATTERNS[i][1] == + (nextPeek & PKCS12_HEADER_MASKS[i][1])) && + (PKCS12_HEADER_PATTERNS[i][2] == + (finalPeek & PKCS12_HEADER_MASKS[i][2]))) { + result = true; + break; + } + } + + return result; + } } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/sun/security/provider/JavaKeyStore.java --- a/jdk/src/java.base/share/classes/sun/security/provider/JavaKeyStore.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/sun/security/provider/JavaKeyStore.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,9 +31,11 @@ import java.security.cert.CertificateFactory; import java.security.cert.CertificateException; import java.util.*; + import sun.misc.IOUtils; - import sun.security.pkcs.EncryptedPrivateKeyInfo; +import sun.security.pkcs12.PKCS12KeyStore; +import sun.security.util.KeyStoreDelegator; /** * This class provides the keystore implementation referred to as "JKS". @@ -49,7 +51,7 @@ * @since 1.2 */ -abstract class JavaKeyStore extends KeyStoreSpi { +public abstract class JavaKeyStore extends KeyStoreSpi { // regular JKS public static final class JKS extends JavaKeyStore { @@ -65,6 +67,13 @@ } } + // special JKS that supports JKS and PKCS12 file formats + public static final class DualFormatJKS extends KeyStoreDelegator { + public DualFormatJKS() { + super("JKS", JKS.class, "PKCS12", PKCS12KeyStore.class); + } + } + private static final int MAGIC = 0xfeedfeed; private static final int VERSION_1 = 0x01; private static final int VERSION_2 = 0x02; @@ -799,4 +808,20 @@ md.update("Mighty Aphrodite".getBytes("UTF8")); return md; } + + /** + * Probe the first few bytes of the keystore data stream for a valid + * JKS keystore encoding. + */ + @Override + public boolean engineProbe(InputStream stream) throws IOException { + DataInputStream dataStream; + if (stream instanceof DataInputStream) { + dataStream = (DataInputStream)stream; + } else { + dataStream = new DataInputStream(stream); + } + + return MAGIC == dataStream.readInt(); + } } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/sun/security/provider/Sun.java --- a/jdk/src/java.base/share/classes/sun/security/provider/Sun.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/sun/security/provider/Sun.java Sat Dec 27 13:27:07 2014 -0500 @@ -40,7 +40,7 @@ private static final String INFO = "SUN " + "(DSA key/parameter generation; DSA signing; SHA-1, MD5 digests; " + - "SecureRandom; X.509 certificates; JKS & DKS keystores; " + + "SecureRandom; X.509 certificates; PKCS12, JKS & DKS keystores; " + "PKIX CertPathValidator; " + "PKIX CertPathBuilder; LDAP, Collection CertStores, JavaPolicy Policy; " + "JavaLoginConfig Configuration)"; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java --- a/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/sun/security/provider/SunEntries.java Sat Dec 27 13:27:07 2014 -0500 @@ -228,7 +228,10 @@ /* * KeyStore */ - map.put("KeyStore.JKS", "sun.security.provider.JavaKeyStore$JKS"); + map.put("KeyStore.PKCS12", + "sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12"); + map.put("KeyStore.JKS", + "sun.security.provider.JavaKeyStore$DualFormatJKS"); map.put("KeyStore.CaseExactJKS", "sun.security.provider.JavaKeyStore$CaseExactJKS"); map.put("KeyStore.DKS", "sun.security.provider.DomainKeyStore$DKS"); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Sat Dec 27 13:27:07 2014 -0500 @@ -124,6 +124,7 @@ private Set> providers = null; private String storetype = null; + private boolean hasStoretypeOption = false; private String srcProviderName = null; private String providerName = null; private String pathlist = null; @@ -483,11 +484,13 @@ } else if (collator.compare(flags, "-storetype") == 0 || collator.compare(flags, "-deststoretype") == 0) { storetype = args[++i]; + hasStoretypeOption = true; } else if (collator.compare(flags, "-srcstorepass") == 0) { srcstorePass = getPass(modifier, args[++i]); passwords.add(srcstorePass); } else if (collator.compare(flags, "-srcstoretype") == 0) { srcstoretype = args[++i]; + hasStoretypeOption = true; } else if (collator.compare(flags, "-srckeypass") == 0) { srckeyPass = getPass(modifier, args[++i]); passwords.add(srckeyPass); @@ -809,36 +812,42 @@ } // Create new keystore - if (providerName == null) { - keyStore = KeyStore.getInstance(storetype); + // Probe for keystore type when filename is available + if (ksfile != null && ksStream != null && providerName == null && + hasStoretypeOption == false) { + keyStore = KeyStore.getInstance(ksfile, storePass); } else { - keyStore = KeyStore.getInstance(storetype, providerName); - } - - /* - * Load the keystore data. - * - * At this point, it's OK if no keystore password has been provided. - * We want to make sure that we can load the keystore data, i.e., - * the keystore data has the right format. If we cannot load the - * keystore, why bother asking the user for his or her password? - * Only if we were able to load the keystore, and no keystore - * password has been provided, will we prompt the user for the - * keystore password to verify the keystore integrity. - * This means that the keystore is loaded twice: first load operation - * checks the keystore format, second load operation verifies the - * keystore integrity. - * - * If the keystore password has already been provided (at the - * command line), however, the keystore is loaded only once, and the - * keystore format and integrity are checked "at the same time". - * - * Null stream keystores are loaded later. - */ - if (!nullStream) { - keyStore.load(ksStream, storePass); - if (ksStream != null) { - ksStream.close(); + if (providerName == null) { + keyStore = KeyStore.getInstance(storetype); + } else { + keyStore = KeyStore.getInstance(storetype, providerName); + } + + /* + * Load the keystore data. + * + * At this point, it's OK if no keystore password has been provided. + * We want to make sure that we can load the keystore data, i.e., + * the keystore data has the right format. If we cannot load the + * keystore, why bother asking the user for his or her password? + * Only if we were able to load the keystore, and no keystore + * password has been provided, will we prompt the user for the + * keystore password to verify the keystore integrity. + * This means that the keystore is loaded twice: first load operation + * checks the keystore format, second load operation verifies the + * keystore integrity. + * + * If the keystore password has already been provided (at the + * command line), however, the keystore is loaded only once, and the + * keystore format and integrity are checked "at the same time". + * + * Null stream keystores are loaded later. + */ + if (!nullStream) { + keyStore.load(ksStream, storePass); + if (ksStream != null) { + ksStream.close(); + } } } @@ -1881,6 +1890,7 @@ boolean isPkcs11 = false; InputStream is = null; + File srcksfile = null; if (P11KEYSTORE.equalsIgnoreCase(srcstoretype) || KeyStoreUtil.isWindowsKeyStore(srcstoretype)) { @@ -1893,7 +1903,7 @@ isPkcs11 = true; } else { if (srcksfname != null) { - File srcksfile = new File(srcksfname); + srcksfile = new File(srcksfname); if (srcksfile.exists() && srcksfile.length() == 0) { throw new Exception(rb.getString ("Source.keystore.file.exists.but.is.empty.") + @@ -1908,10 +1918,16 @@ KeyStore store; try { - if (srcProviderName == null) { - store = KeyStore.getInstance(srcstoretype); + // Probe for keystore type when filename is available + if (srcksfile != null && is != null && srcProviderName == null && + hasStoretypeOption == false) { + store = KeyStore.getInstance(srcksfile, srcstorePass); } else { - store = KeyStore.getInstance(srcstoretype, srcProviderName); + if (srcProviderName == null) { + store = KeyStore.getInstance(srcstoretype); + } else { + store = KeyStore.getInstance(srcstoretype, srcProviderName); + } } if (srcstorePass == null diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/classes/sun/security/util/KeyStoreDelegator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/sun/security/util/KeyStoreDelegator.java Sat Dec 27 13:27:07 2014 -0500 @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.util; + +import java.io.*; +import java.security.*; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.cert.CertificateException; +import java.util.*; + +import sun.security.util.Debug; + +/** + * This class delegates to a primary or secondary keystore implementation. + * + * @since 1.9 + */ + +public class KeyStoreDelegator extends KeyStoreSpi { + + private static final String KEYSTORE_TYPE_COMPAT = "keystore.type.compat"; + private static final Debug debug = Debug.getInstance("keystore"); + + private String primaryType; // the primary keystore's type + private String secondaryType; // the secondary keystore's type + private Class primaryKeyStore; + // the primary keystore's class + private Class secondaryKeyStore; + // the secondary keystore's class + private String type; // the delegate's type + private KeyStoreSpi keystore; // the delegate + private boolean compatModeEnabled = true; + + public KeyStoreDelegator( + String primaryType, + Class primaryKeyStore, + String secondaryType, + Class secondaryKeyStore) { + + // Check whether compatibility mode has been disabled + compatModeEnabled = "true".equalsIgnoreCase( + AccessController.doPrivileged((PrivilegedAction) () -> + Security.getProperty(KEYSTORE_TYPE_COMPAT))); + + if (compatModeEnabled) { + this.primaryType = primaryType; + this.secondaryType = secondaryType; + this.primaryKeyStore = primaryKeyStore; + this.secondaryKeyStore = secondaryKeyStore; + } else { + this.primaryType = primaryType; + this.secondaryType = null; + this.primaryKeyStore = primaryKeyStore; + this.secondaryKeyStore = null; + + if (debug != null) { + debug.println("WARNING: compatibility mode disabled for " + + primaryType + " and " + secondaryType + " keystore types"); + } + } + } + + @Override + public Key engineGetKey(String alias, char[] password) + throws NoSuchAlgorithmException, UnrecoverableKeyException { + return keystore.engineGetKey(alias, password); + } + + @Override + public Certificate[] engineGetCertificateChain(String alias) { + return keystore.engineGetCertificateChain(alias); + } + + @Override + public Certificate engineGetCertificate(String alias) { + return keystore.engineGetCertificate(alias); + } + + @Override + public Date engineGetCreationDate(String alias) { + return keystore.engineGetCreationDate(alias); + } + + @Override + public void engineSetKeyEntry(String alias, Key key, char[] password, + Certificate[] chain) throws KeyStoreException { + keystore.engineSetKeyEntry(alias, key, password, chain); + } + + @Override + public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) + throws KeyStoreException { + keystore.engineSetKeyEntry(alias, key, chain); + } + + @Override + public void engineSetCertificateEntry(String alias, Certificate cert) + throws KeyStoreException { + keystore.engineSetCertificateEntry(alias, cert); + } + + @Override + public void engineDeleteEntry(String alias) throws KeyStoreException { + keystore.engineDeleteEntry(alias); + } + + @Override + public Enumeration engineAliases() { + return keystore.engineAliases(); + } + + @Override + public boolean engineContainsAlias(String alias) { + return keystore.engineContainsAlias(alias); + } + + @Override + public int engineSize() { + return keystore.engineSize(); + } + + @Override + public boolean engineIsKeyEntry(String alias) { + return keystore.engineIsKeyEntry(alias); + } + + @Override + public boolean engineIsCertificateEntry(String alias) { + return keystore.engineIsCertificateEntry(alias); + } + + @Override + public String engineGetCertificateAlias(Certificate cert) { + return keystore.engineGetCertificateAlias(cert); + } + + @Override + public KeyStore.Entry engineGetEntry(String alias, + KeyStore.ProtectionParameter protParam) + throws KeyStoreException, NoSuchAlgorithmException, + UnrecoverableEntryException { + return keystore.engineGetEntry(alias, protParam); + } + + @Override + public void engineSetEntry(String alias, KeyStore.Entry entry, + KeyStore.ProtectionParameter protParam) + throws KeyStoreException { + keystore.engineSetEntry(alias, entry, protParam); + } + + @Override + public boolean engineEntryInstanceOf(String alias, + Class entryClass) { + return keystore.engineEntryInstanceOf(alias, entryClass); + } + + @Override + public void engineStore(OutputStream stream, char[] password) + throws IOException, NoSuchAlgorithmException, CertificateException { + + if (debug != null) { + debug.println("Storing keystore in " + type + " format"); + } + keystore.engineStore(stream, password); + } + + @Override + public void engineLoad(InputStream stream, char[] password) + throws IOException, NoSuchAlgorithmException, CertificateException { + + // A new keystore is always created in the primary keystore format + if (stream == null) { + try { + keystore = primaryKeyStore.newInstance(); + + } catch (InstantiationException | IllegalAccessException e) { + // can safely ignore + } + type = primaryType; + + if (debug != null) { + debug.println("Creating a new keystore in " + type + " format"); + } + keystore.engineLoad(stream, password); + + } else { + // First try the primary keystore then try the secondary keystore + try (InputStream bufferedStream = new BufferedInputStream(stream)) { + bufferedStream.mark(Integer.MAX_VALUE); + + try { + keystore = primaryKeyStore.newInstance(); + type = primaryType; + keystore.engineLoad(bufferedStream, password); + + } catch (Exception e) { + + // incorrect password + if (e instanceof IOException && + e.getCause() instanceof UnrecoverableKeyException) { + throw (IOException)e; + } + + try { + // Ignore secondary keystore when no compatibility mode + if (!compatModeEnabled) { + throw e; + } + + keystore = secondaryKeyStore.newInstance(); + type = secondaryType; + bufferedStream.reset(); + keystore.engineLoad(bufferedStream, password); + + if (debug != null) { + debug.println("WARNING: switching from " + + primaryType + " to " + secondaryType + + " keystore file format has altered the " + + "keystore security level"); + } + + } catch (InstantiationException | + IllegalAccessException e2) { + // can safely ignore + + } catch (IOException | + NoSuchAlgorithmException | + CertificateException e3) { + + // incorrect password + if (e3 instanceof IOException && + e3.getCause() instanceof + UnrecoverableKeyException) { + throw (IOException)e3; + } + // rethrow the outer exception + if (e instanceof IOException) { + throw (IOException)e; + } else if (e instanceof CertificateException) { + throw (CertificateException)e; + } else if (e instanceof NoSuchAlgorithmException) { + throw (NoSuchAlgorithmException)e; + } + } + } + } + + if (debug != null) { + debug.println("Loaded a keystore in " + type + " format"); + } + } + } + + /** + * Probe the first few bytes of the keystore data stream for a valid + * keystore encoding. Only the primary keystore implementation is probed. + */ + @Override + public boolean engineProbe(InputStream stream) throws IOException { + + boolean result = false; + + try { + keystore = primaryKeyStore.newInstance(); + type = primaryType; + result = keystore.engineProbe(stream); + + } catch (Exception e) { + throw new IOException(e); + + } finally { + // reset + if (result == false) { + type = null; + keystore = null; + } + } + + return result; + } +} diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/share/conf/security/java.security --- a/jdk/src/java.base/share/conf/security/java.security Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/share/conf/security/java.security Sat Dec 27 13:27:07 2014 -0500 @@ -183,7 +183,17 @@ # # Default keystore type. # -keystore.type=jks +keystore.type=pkcs12 + +# +# Controls compatibility mode for JKS and PKCS12 keystore types. +# +# When set to 'true', both JKS and PKCS12 keystore types support loading +# keystore files in either JKS or PKCS12 format. When set to 'false' the +# JKS keystore type supports loading only JKS keystore files and the PKCS12 +# keystore type supports loading only PKCS12 keystore files. +# +keystore.type.compat=true # # List of comma-separated packages that start with or equal this string diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java --- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java Sat Dec 27 13:27:07 2014 -0500 @@ -40,9 +40,7 @@ * Solaris/Linux implementation of java.nio.file.Path */ -class UnixPath - extends AbstractPath -{ +class UnixPath implements Path { private static ThreadLocal> encoder = new ThreadLocal>(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java Sat Dec 27 13:27:07 2014 -0500 @@ -41,7 +41,7 @@ * Windows implementation of Path */ -class WindowsPath extends AbstractPath { +class WindowsPath implements Path { // The maximum path that does not require long path prefix. On Windows // the maximum path is 260 minus 1 (NUL) but for directories it is 260 diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxButton.java Sat Dec 27 13:27:07 2014 -0500 @@ -70,6 +70,7 @@ return comboBox == null ? true : comboBox.isEnabled(); } + @SuppressWarnings("deprecation") public boolean isFocusTraversable() { return false; } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java Sat Dec 27 13:27:07 2014 -0500 @@ -303,6 +303,7 @@ } } + @SuppressWarnings("deprecation") public void hide() { final Container parent = getParent(); final Rectangle r = this.getBounds(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java Sat Dec 27 13:27:07 2014 -0500 @@ -2231,6 +2231,7 @@ return total; } + @SuppressWarnings("deprecation") public void layoutContainer(final Container parent) { /* Some of the code in this method deals with changing the * visibility of components to hide and show the contents for the @@ -2725,6 +2726,7 @@ return calculateMaxTabWidth(tabPlacement); } + @SuppressWarnings("deprecation") public void layoutContainer(final Container parent) { /* Some of the code in this method deals with changing the * visibility of components to hide and show the contents for the diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenu.java --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenu.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenu.java Sat Dec 27 13:27:07 2014 -0500 @@ -229,6 +229,7 @@ } @Override + @SuppressWarnings("deprecation") public void addNotify() { synchronized (getTreeLock()) { super.addNotify(); @@ -354,6 +355,7 @@ public void setIndeterminate(boolean indeterminate) { } @Override + @SuppressWarnings("deprecation") public void setToolTipText(final String text) { final MenuComponentPeer peer = getPeer(); if (!(peer instanceof CMenuItem)) return; @@ -363,6 +365,7 @@ } @Override + @SuppressWarnings("deprecation") public void setIcon(final Icon i) { final MenuComponentPeer peer = getPeer(); if (!(peer instanceof CMenuItem)) return; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuBar.java --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuBar.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuBar.java Sat Dec 27 13:27:07 2014 -0500 @@ -246,6 +246,7 @@ fSubmenus.remove(menu); } + @SuppressWarnings("deprecation") public Menu add(final Menu m, final int index) { synchronized (getTreeLock()) { if (m.getParent() != null) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItem.java --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItem.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItem.java Sat Dec 27 13:27:07 2014 -0500 @@ -97,6 +97,7 @@ fMenuItem.removeComponentListener(this); } + @SuppressWarnings("deprecation") static void syncLabelAndKS(MenuItem menuItem, String label, KeyStroke ks) { final MenuComponentPeer peer = menuItem.getPeer(); if (!(peer instanceof CMenuItem)) { @@ -165,6 +166,7 @@ } } + @SuppressWarnings("deprecation") public void setToolTipText(final String text) { final MenuComponentPeer peer = getPeer(); if (!(peer instanceof CMenuItem)) return; @@ -173,6 +175,7 @@ cmi.setToolTipText(text); } + @SuppressWarnings("deprecation") public void setIcon(final Icon i) { final MenuComponentPeer peer = getPeer(); if (!(peer instanceof CMenuItem)) return; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItemCheckbox.java --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItemCheckbox.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenMenuItemCheckbox.java Sat Dec 27 13:27:07 2014 -0500 @@ -57,6 +57,7 @@ } ScreenMenuPropertyListener fPropertyListener; + @SuppressWarnings("deprecation") public void addNotify() { super.addNotify(); @@ -154,6 +155,7 @@ setVisible(false); } + @SuppressWarnings("deprecation") public void setToolTipText(final String text) { final MenuComponentPeer peer = getPeer(); if (!(peer instanceof CMenuItem)) return; @@ -161,6 +163,7 @@ ((CMenuItem)peer).setToolTipText(text); } + @SuppressWarnings("deprecation") public void setIcon(final Icon i) { final MenuComponentPeer peer = getPeer(); if (!(peer instanceof CMenuItem)) return; @@ -205,6 +208,7 @@ } } + @SuppressWarnings("deprecation") public void setIndeterminate(final boolean indeterminate) { final MenuComponentPeer peer = getPeer(); if (peer instanceof CCheckboxMenuItem) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/sun/awt/CGraphicsDevice.java --- a/jdk/src/java.desktop/macosx/classes/sun/awt/CGraphicsDevice.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/sun/awt/CGraphicsDevice.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -202,6 +202,7 @@ return true; } + @SuppressWarnings("deprecation") private static void enterFullScreenExclusive(Window w) { FullScreenCapable peer = (FullScreenCapable)w.getPeer(); if (peer != null) { @@ -209,6 +210,7 @@ } } + @SuppressWarnings("deprecation") private static void exitFullScreenExclusive(Window w) { FullScreenCapable peer = (FullScreenCapable)w.getPeer(); if (peer != null) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java --- a/jdk/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -125,6 +125,7 @@ return fConfig; } + @SuppressWarnings("deprecation") protected void setBounds(int x, int y, int w, int h) { fBounds.reshape(x, y, w, y + h); } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLVolatileSurfaceManager.java --- a/jdk/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLVolatileSurfaceManager.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLVolatileSurfaceManager.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,6 +74,7 @@ * Create a pbuffer-based SurfaceData object (or init the backbuffer * of an existing window if this is a double buffered GraphicsConfig) */ + @SuppressWarnings("deprecation") protected SurfaceData initAcceleratedSurface() { SurfaceData sData = null; Component comp = vImg.getComponent(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java Sat Dec 27 13:27:07 2014 -0500 @@ -1243,6 +1243,7 @@ changeFocusedWindow(activate, null); } + @SuppressWarnings("deprecation") private boolean isOneOfOwnersOf(LWWindowPeer peer) { Window owner = (peer != null ? peer.getTarget().getOwner() : null); while (owner != null) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,6 +88,7 @@ super.startDrag(dsc, cursor, dragImage, dragImageOffset); } + @SuppressWarnings("deprecation") protected void startDrag(Transferable transferable, long[] formats, Map formatMap) { DragGestureEvent trigger = getTrigger(); InputEvent triggerEvent = trigger.getTriggerEvent(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Sat Dec 27 13:27:07 2014 -0500 @@ -46,6 +46,7 @@ show(); } + @SuppressWarnings("deprecation") public void addNotify() { if (getPeer() == null) { LWCToolkit toolkit = (LWCToolkit)Toolkit.getDefaultToolkit(); @@ -60,6 +61,7 @@ public void unregisterAccelerator(AWTKeyStroke stroke) {} + @SuppressWarnings("deprecation") protected long getLayerPtr() { LWWindowPeer peer = (LWWindowPeer)getPeer(); return peer.getLayerPtr(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -385,6 +385,7 @@ // java.awt.Toolkit#getNativeContainer() is not available // from this package + @SuppressWarnings("deprecation") private LWComponentPeer getNearestNativePeer(Component comp) { if (comp==null) return null; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuBar.java --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuBar.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuBar.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ } @Override + @SuppressWarnings("deprecation") public void addHelpMenu(Menu m) { CMenu cMenu = (CMenu)m.getPeer(); nativeSetHelpMenu(getModel(), cMenu.getModel()); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Sat Dec 27 13:27:07 2014 -0500 @@ -190,6 +190,7 @@ nativeSetNSWindowRepresentedFilename(c.getNSWindowPtr(), filename); }} }) { + @SuppressWarnings("deprecation") public CPlatformWindow convertJComponentToTarget(final JRootPane p) { Component root = SwingUtilities.getRoot(p); if (root == null || (LWWindowPeer)root.getPeer() == null) return null; @@ -519,6 +520,7 @@ } @Override // PlatformWindow + @SuppressWarnings("deprecation") public void setVisible(boolean visible) { final long nsWindowPtr = getNSWindowPtr(); @@ -674,6 +676,7 @@ } @Override // PlatformWindow + @SuppressWarnings("deprecation") public void toFront() { final long nsWindowPtr = getNSWindowPtr(); LWCToolkit lwcToolkit = (LWCToolkit) Toolkit.getDefaultToolkit(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java Sat Dec 27 13:27:07 2014 -0500 @@ -68,6 +68,7 @@ updateImage(); } + @SuppressWarnings("deprecation") private CPopupMenu checkAndCreatePopupPeer() { CPopupMenu menuPeer = null; if (popup != null) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java Sat Dec 27 13:27:07 2014 -0500 @@ -78,6 +78,7 @@ * Synthetic event delivery for focus management */ @Override + @SuppressWarnings("deprecation") public void synthesizeWindowActivation(boolean activated) { if (isActive != activated) { isActive = activated; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m Sat Dec 27 13:27:07 2014 -0500 @@ -104,6 +104,67 @@ @implementation AWTWindow_Normal AWT_NS_WINDOW_IMPLEMENTATION + +// Gesture support +- (void)postGesture:(NSEvent *)event as:(jint)type a:(jdouble)a b:(jdouble)b { + AWT_ASSERT_APPKIT_THREAD; + + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject platformWindow = [((AWTWindow *)self.delegate).javaPlatformWindow jObjectWithEnv:env]; + if (platformWindow != NULL) { + // extract the target AWT Window object out of the CPlatformWindow + static JNF_MEMBER_CACHE(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;"); + jobject awtWindow = JNFGetObjectField(env, platformWindow, jf_target); + if (awtWindow != NULL) { + // translate the point into Java coordinates + NSPoint loc = [event locationInWindow]; + loc.y = [self frame].size.height - loc.y; + + // send up to the GestureHandler to recursively dispatch on the AWT event thread + static JNF_CLASS_CACHE(jc_GestureHandler, "com/apple/eawt/event/GestureHandler"); + static JNF_STATIC_MEMBER_CACHE(sjm_handleGestureFromNative, jc_GestureHandler, "handleGestureFromNative", "(Ljava/awt/Window;IDDDD)V"); + JNFCallStaticVoidMethod(env, sjm_handleGestureFromNative, awtWindow, type, (jdouble)loc.x, (jdouble)loc.y, (jdouble)a, (jdouble)b); + (*env)->DeleteLocalRef(env, awtWindow); + } + (*env)->DeleteLocalRef(env, platformWindow); + } +} + +- (void)beginGestureWithEvent:(NSEvent *)event { + [self postGesture:event + as:com_apple_eawt_event_GestureHandler_PHASE + a:-1.0 + b:0.0]; +} + +- (void)endGestureWithEvent:(NSEvent *)event { + [self postGesture:event + as:com_apple_eawt_event_GestureHandler_PHASE + a:1.0 + b:0.0]; +} + +- (void)magnifyWithEvent:(NSEvent *)event { + [self postGesture:event + as:com_apple_eawt_event_GestureHandler_MAGNIFY + a:[event magnification] + b:0.0]; +} + +- (void)rotateWithEvent:(NSEvent *)event { + [self postGesture:event + as:com_apple_eawt_event_GestureHandler_ROTATE + a:[event rotation] + b:0.0]; +} + +- (void)swipeWithEvent:(NSEvent *)event { + [self postGesture:event + as:com_apple_eawt_event_GestureHandler_SWIPE + a:[event deltaX] + b:[event deltaY]]; +} + @end @implementation AWTWindow_Panel AWT_NS_WINDOW_IMPLEMENTATION @@ -399,67 +460,6 @@ } -// Gesture support -- (void)postGesture:(NSEvent *)event as:(jint)type a:(jdouble)a b:(jdouble)b { -AWT_ASSERT_APPKIT_THREAD; - - JNIEnv *env = [ThreadUtilities getJNIEnv]; - jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env]; - if (platformWindow != NULL) { - // extract the target AWT Window object out of the CPlatformWindow - static JNF_MEMBER_CACHE(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;"); - jobject awtWindow = JNFGetObjectField(env, platformWindow, jf_target); - if (awtWindow != NULL) { - // translate the point into Java coordinates - NSPoint loc = [event locationInWindow]; - loc.y = [self.nsWindow frame].size.height - loc.y; - - // send up to the GestureHandler to recursively dispatch on the AWT event thread - static JNF_CLASS_CACHE(jc_GestureHandler, "com/apple/eawt/event/GestureHandler"); - static JNF_STATIC_MEMBER_CACHE(sjm_handleGestureFromNative, jc_GestureHandler, "handleGestureFromNative", "(Ljava/awt/Window;IDDDD)V"); - JNFCallStaticVoidMethod(env, sjm_handleGestureFromNative, awtWindow, type, (jdouble)loc.x, (jdouble)loc.y, (jdouble)a, (jdouble)b); - (*env)->DeleteLocalRef(env, awtWindow); - } - (*env)->DeleteLocalRef(env, platformWindow); - } -} - -- (void)beginGestureWithEvent:(NSEvent *)event { - [self postGesture:event - as:com_apple_eawt_event_GestureHandler_PHASE - a:-1.0 - b:0.0]; -} - -- (void)endGestureWithEvent:(NSEvent *)event { - [self postGesture:event - as:com_apple_eawt_event_GestureHandler_PHASE - a:1.0 - b:0.0]; -} - -- (void)magnifyWithEvent:(NSEvent *)event { - [self postGesture:event - as:com_apple_eawt_event_GestureHandler_MAGNIFY - a:[event magnification] - b:0.0]; -} - -- (void)rotateWithEvent:(NSEvent *)event { - [self postGesture:event - as:com_apple_eawt_event_GestureHandler_ROTATE - a:[event rotation] - b:0.0]; -} - -- (void)swipeWithEvent:(NSEvent *)event { - [self postGesture:event - as:com_apple_eawt_event_GestureHandler_SWIPE - a:[event deltaX] - b:[event deltaY]]; -} - - // NSWindowDelegate methods - (void) _deliverMoveResizeEvent { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,11 @@ #import #import "java_awt_geom_PathIterator.h" -#import "sun_awt_SunHints.h" #import "sun_font_CStrike.h" #import "sun_font_CStrikeDisposer.h" #import "CGGlyphImages.h" #import "CGGlyphOutlines.h" -#import "AWTStrike.h" #import "CoreTextSupport.h" -//#import "jni_util.h" #include "fontscalerdefs.h" /* Use THIS_FILE when it is available. */ @@ -65,10 +62,10 @@ invDevTx.b *= -1; invDevTx.c *= -1; fFontTx = CGAffineTransformConcat(CGAffineTransformConcat(tx, invDevTx), sInverseTX); - fDevTx = CGAffineTransformInvert(invDevTx); + fDevTx = CGAffineTransformInvert(CGAffineTransformConcat(invDevTx, sInverseTX)); // the "font size" is the square root of the determinant of the matrix - fSize = sqrt(abs(fFontTx.a * fFontTx.d - fFontTx.b * fFontTx.c)); + fSize = sqrt(fabs(fFontTx.a * fFontTx.d - fFontTx.b * fFontTx.c)); } return self; } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/com/sun/beans/editors/ColorEditor.java --- a/jdk/src/java.desktop/share/classes/com/sun/beans/editors/ColorEditor.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/com/sun/beans/editors/ColorEditor.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ public class ColorEditor extends Panel implements PropertyEditor { private static final long serialVersionUID = 1781257185164716054L; + @SuppressWarnings("deprecation") public ColorEditor() { setLayout(null); @@ -69,10 +70,12 @@ changeColor(c); } + @SuppressWarnings("deprecation") public Dimension preferredSize() { return new Dimension(ourWidth, 40); } + @SuppressWarnings("deprecation") public boolean keyUp(Event e, int key) { if (e.target == text) { try { @@ -107,6 +110,7 @@ } + @SuppressWarnings("deprecation") public boolean action(Event e, Object arg) { if (e.target == choser) { changeColor(colors[choser.getSelectedIndex()]); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/com/sun/beans/editors/FontEditor.java --- a/jdk/src/java.desktop/share/classes/com/sun/beans/editors/FontEditor.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/com/sun/beans/editors/FontEditor.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ public class FontEditor extends Panel implements java.beans.PropertyEditor { private static final long serialVersionUID = 6732704486002715933L; + @SuppressWarnings("deprecation") public FontEditor() { setLayout(null); @@ -62,6 +63,7 @@ } + @SuppressWarnings("deprecation") public Dimension preferredSize() { return new Dimension(300, 40); } @@ -93,6 +95,7 @@ } } + @SuppressWarnings("deprecation") private void changeFont(Font f) { font = f; if (sample != null) { @@ -124,6 +127,7 @@ font.getStyle() + ", " + font.getSize() + ")"; } + @SuppressWarnings("deprecation") public boolean action(Event e, Object arg) { String family = familyChoser.getSelectedItem(); int style = styles[styleChoser.getSelectedIndex()]; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java Sat Dec 27 13:27:07 2014 -0500 @@ -143,6 +143,7 @@ return map; } + @SuppressWarnings("deprecation") public String getFileName() { JFileChooser fc = getFileChooser(); String typedInName = fileNameTextField != null ? @@ -419,6 +420,7 @@ + @SuppressWarnings("deprecation") protected class SelectionListener implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifDesktopIconUI.java --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifDesktopIconUI.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifDesktopIconUI.java Sat Dec 27 13:27:07 2014 -0500 @@ -245,6 +245,7 @@ e.isPopupTrigger(), MouseEvent.NOBUTTON)); } + @SuppressWarnings("deprecation") public boolean isFocusTraversable() { return false; } @@ -336,6 +337,7 @@ e.getClickCount(), e.isPopupTrigger(), MouseEvent.NOBUTTON )); } + @SuppressWarnings("deprecation") public boolean isFocusTraversable() { return false; } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java Sat Dec 27 13:27:07 2014 -0500 @@ -242,6 +242,7 @@ setBorderPainted(false); } + @SuppressWarnings("deprecation") public boolean isFocusTraversable() { return false; } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsDesktopPaneUI.java --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsDesktopPaneUI.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsDesktopPaneUI.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,6 +60,7 @@ super.installDefaults(); } + @SuppressWarnings("deprecation") protected void installKeyboardActions() { super.installKeyboardActions(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java Sat Dec 27 13:27:07 2014 -0500 @@ -2487,6 +2487,7 @@ /** * Calculates the dialog unit mapping. */ + @SuppressWarnings("deprecation") private void calculateBaseUnits() { // This calculation comes from: // http://support.microsoft.com/default.aspx?scid=kb;EN-US;125681 diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupWindow.java --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupWindow.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupWindow.java Sat Dec 27 13:27:07 2014 -0500 @@ -78,6 +78,7 @@ paint(g); } + @SuppressWarnings("deprecation") public void hide() { super.hide(); /** We need to call removeNotify() here because hide() does @@ -89,6 +90,7 @@ removeNotify(); } + @SuppressWarnings("deprecation") public void show() { super.show(); this.pack(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/XPStyle.java --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/XPStyle.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/XPStyle.java Sat Dec 27 13:27:07 2014 -0500 @@ -700,6 +700,7 @@ setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)); } + @SuppressWarnings("deprecation") public boolean isFocusTraversable() { return false; } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java Sat Dec 27 13:27:07 2014 -0500 @@ -167,9 +167,9 @@ for (int i = 0; i < allchannelnames.length; i++) { if ((channelmask & m) != 0L) { if (i < channelnames.length) { - sb.append(channelnames[i] + " "); + sb.append(channelnames[i]).append(' '); } else { - sb.append(allchannelnames[i] + " "); + sb.append(allchannelnames[i]).append(' '); } } m *= 2L; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/Canvas.java --- a/jdk/src/java.desktop/share/classes/java/awt/Canvas.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/Canvas.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,6 +70,7 @@ } @Override + @SuppressWarnings("deprecation") void setGraphicsConfiguration(GraphicsConfiguration gc) { synchronized(getTreeLock()) { CanvasPeer peer = (CanvasPeer)getPeer(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/Container.java --- a/jdk/src/java.desktop/share/classes/java/awt/Container.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/Container.java Sat Dec 27 13:27:07 2014 -0500 @@ -805,6 +805,7 @@ * to new heavyweight parent. * @since 1.5 */ + @SuppressWarnings("deprecation") private void reparentTraverse(ContainerPeer parentPeer, Container child) { checkTreeLock(); @@ -828,6 +829,7 @@ * Container must be heavyweight. * @since 1.5 */ + @SuppressWarnings("deprecation") private void reparentChild(Component comp) { checkTreeLock(); if (comp == null) { @@ -4189,6 +4191,7 @@ } } + @SuppressWarnings("deprecation") private void recursiveShowHeavyweightChildren() { if (!hasHeavyweightDescendants() || !isVisible()) { return; @@ -4210,6 +4213,7 @@ } } + @SuppressWarnings("deprecation") private void recursiveHideHeavyweightChildren() { if (!hasHeavyweightDescendants()) { return; @@ -4231,6 +4235,7 @@ } } + @SuppressWarnings("deprecation") private void recursiveRelocateHeavyweightChildren(Point origin) { for (int index = 0; index < getComponentCount(); index++) { Component comp = getComponent(index); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/DefaultFocusTraversalPolicy.java --- a/jdk/src/java.desktop/share/classes/java/awt/DefaultFocusTraversalPolicy.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/DefaultFocusTraversalPolicy.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,6 +93,7 @@ * @return true if aComponent meets the above requirements; * false otherwise */ + @SuppressWarnings("deprecation") protected boolean accept(Component aComponent) { if (!(aComponent.isVisible() && aComponent.isDisplayable() && aComponent.isEnabled())) diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java --- a/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java Sat Dec 27 13:27:07 2014 -0500 @@ -796,6 +796,7 @@ * @return true * @see Component#dispatchEvent */ + @SuppressWarnings("deprecation") public boolean dispatchKeyEvent(KeyEvent e) { Component focusOwner = (((AWTEvent)e).isPosted) ? getFocusOwner() : e.getComponent(); @@ -1021,6 +1022,7 @@ } } + @SuppressWarnings("deprecation") private boolean preDispatchKeyEvent(KeyEvent ke) { if (((AWTEvent) ke).isPosted) { Component focusOwner = getFocusOwner(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/Dialog.java --- a/jdk/src/java.desktop/share/classes/java/awt/Dialog.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/Dialog.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -749,6 +749,7 @@ * @see Component#isDisplayable * @see #removeNotify */ + @SuppressWarnings("deprecation") public void addNotify() { synchronized (getTreeLock()) { if (parent != null && parent.getPeer() == null) { @@ -897,6 +898,7 @@ /** * @return true if we actually showed, false if we just called toFront() */ + @SuppressWarnings("deprecation") private boolean conditionalShow(Component toFocus, AtomicLong time) { boolean retval; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/FileDialog.java --- a/jdk/src/java.desktop/share/classes/java/awt/FileDialog.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/FileDialog.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -314,6 +314,7 @@ * Creates the file dialog's peer. The peer allows us to change the look * of the file dialog without changing its functionality. */ + @SuppressWarnings("deprecation") public void addNotify() { synchronized(getTreeLock()) { if (parent != null && parent.getPeer() == null) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/FontMetrics.java --- a/jdk/src/java.desktop/share/classes/java/awt/FontMetrics.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/FontMetrics.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -409,6 +409,7 @@ * @see #charsWidth(char[], int, int) * @see #stringWidth(String) */ + @SuppressWarnings("deprecation") public int bytesWidth(byte data[], int off, int len) { return stringWidth(new String(data, 0, off, len)); } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/Graphics.java --- a/jdk/src/java.desktop/share/classes/java/awt/Graphics.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/Graphics.java Sat Dec 27 13:27:07 2014 -0500 @@ -843,6 +843,7 @@ * @see java.awt.Graphics#drawChars * @see java.awt.Graphics#drawString */ + @SuppressWarnings("deprecation") public void drawBytes(byte data[], int offset, int length, int x, int y) { drawString(new String(data, 0, offset, length), x, y); } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java --- a/jdk/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java Sat Dec 27 13:27:07 2014 -0500 @@ -28,6 +28,7 @@ import java.awt.image.BufferedImage; import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Locale; import sun.font.FontManager; @@ -161,43 +162,38 @@ */ private static boolean getHeadlessProperty() { if (headless == null) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - String nm = System.getProperty("java.awt.headless"); + AccessController.doPrivileged((PrivilegedAction) () -> { + String nm = System.getProperty("java.awt.headless"); - if (nm == null) { - /* No need to ask for DISPLAY when run in a browser */ - if (System.getProperty("javaplugin.version") != null) { - headless = defaultHeadless = Boolean.FALSE; + if (nm == null) { + /* No need to ask for DISPLAY when run in a browser */ + if (System.getProperty("javaplugin.version") != null) { + headless = defaultHeadless = Boolean.FALSE; + } else { + String osName = System.getProperty("os.name"); + if (osName.contains("OS X") && "sun.awt.HToolkit".equals( + System.getProperty("awt.toolkit"))) + { + headless = defaultHeadless = Boolean.TRUE; } else { - String osName = System.getProperty("os.name"); - if (osName.contains("OS X") && "sun.awt.HToolkit".equals( - System.getProperty("awt.toolkit"))) - { - headless = defaultHeadless = Boolean.TRUE; - } else { - headless = defaultHeadless = - Boolean.valueOf(("Linux".equals(osName) || - "SunOS".equals(osName) || - "FreeBSD".equals(osName) || - "NetBSD".equals(osName) || - "OpenBSD".equals(osName) || - "AIX".equals(osName)) && - (System.getenv("DISPLAY") == null)); - } + final String display = System.getenv("DISPLAY"); + headless = defaultHeadless = + ("Linux".equals(osName) || + "SunOS".equals(osName) || + "FreeBSD".equals(osName) || + "NetBSD".equals(osName) || + "OpenBSD".equals(osName) || + "AIX".equals(osName)) && + (display == null || display.trim().isEmpty()); } - } else if (nm.equals("true")) { - headless = Boolean.TRUE; - } else { - headless = Boolean.FALSE; } - return null; - } + } else { + headless = Boolean.valueOf(nm); } - ); + return null; + }); } - return headless.booleanValue(); + return headless; } /** diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java --- a/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java Sat Dec 27 13:27:07 2014 -0500 @@ -3054,6 +3054,7 @@ return (wto != wfrom); } + @SuppressWarnings("deprecation") static Component getHeavyweight(Component comp) { if (comp == null || comp.getPeer() == null) { return null; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/PopupMenu.java --- a/jdk/src/java.desktop/share/classes/java/awt/PopupMenu.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/PopupMenu.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -153,6 +153,7 @@ * parent's hierarchy * @exception RuntimeException if the parent is not showing on screen */ + @SuppressWarnings("deprecation") public void show(Component origin, int x, int y) { // Use localParent for thread safety. MenuContainer localParent = parent; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/ScrollPane.java --- a/jdk/src/java.desktop/share/classes/java/awt/ScrollPane.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/ScrollPane.java Sat Dec 27 13:27:07 2014 -0500 @@ -732,6 +732,7 @@ /** * Invoked when the value of the adjustable has changed. */ + @SuppressWarnings("deprecation") public void adjustmentValueChanged(AdjustmentEvent e) { Adjustable adj = e.getAdjustable(); int value = e.getValue(); @@ -831,6 +832,7 @@ /** * Invoked when the value of the adjustable has changed. */ + @SuppressWarnings("deprecation") public void adjustmentValueChanged(AdjustmentEvent e) { Adjustable adj = e.getAdjustable(); int value = e.getValue(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/SplashScreen.java --- a/jdk/src/java.desktop/share/classes/java/awt/SplashScreen.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/SplashScreen.java Sat Dec 27 13:27:07 2014 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -203,6 +203,7 @@ * @return URL for the current splash screen image file * @throws IllegalStateException if the splash screen has already been closed */ + @SuppressWarnings("deprecation") public URL getImageURL() throws IllegalStateException { synchronized (SplashScreen.class) { checkVisible(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/Window.java --- a/jdk/src/java.desktop/share/classes/java/awt/Window.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/Window.java Sat Dec 27 13:27:07 2014 -0500 @@ -755,6 +755,7 @@ * @see Container#removeNotify * @since 1.0 */ + @SuppressWarnings("deprecation") public void addNotify() { synchronized (getTreeLock()) { Container parent = this.parent; @@ -798,6 +799,7 @@ * @see Component#isDisplayable * @see #setMinimumSize */ + @SuppressWarnings("deprecation") public void pack() { Container parent = this.parent; if (parent != null && parent.getPeer() == null) { @@ -1070,6 +1072,7 @@ } } + @SuppressWarnings("deprecation") static void updateChildFocusableWindowState(Window w) { if (w.getPeer() != null && w.isShowing()) { ((WindowPeer)w.getPeer()).updateFocusableWindowState(); @@ -1157,6 +1160,7 @@ * as reported in javadoc. So we need to implement this functionality even if a * child overrides dispose() in a wrong way without calling super.dispose(). */ + @SuppressWarnings("deprecation") void disposeImpl() { dispose(); if (getPeer() != null) { @@ -3623,6 +3627,7 @@ * * @since 1.7 */ + @SuppressWarnings("deprecation") public void setOpacity(float opacity) { synchronized (getTreeLock()) { if (opacity < 0.0f || opacity > 1.0f) { @@ -3721,6 +3726,7 @@ * * @since 1.7 */ + @SuppressWarnings("deprecation") public void setShape(Shape shape) { synchronized (getTreeLock()) { if (shape != null) { @@ -3838,6 +3844,7 @@ * @see GraphicsConfiguration#isTranslucencyCapable() */ @Override + @SuppressWarnings("deprecation") public void setBackground(Color bgColor) { Color oldBg = getBackground(); super.setBackground(bgColor); @@ -3890,6 +3897,7 @@ return bg != null ? bg.getAlpha() == 255 : true; } + @SuppressWarnings("deprecation") private void updateWindow() { synchronized (getTreeLock()) { WindowPeer peer = (WindowPeer)getPeer(); @@ -4080,6 +4088,7 @@ window.securityWarningHeight = height; } + @SuppressWarnings("deprecation") public void setSecurityWarningPosition(Window window, Point2D point, float alignmentX, float alignmentY) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/datatransfer/StringSelection.java --- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/StringSelection.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/datatransfer/StringSelection.java Sat Dec 27 13:27:07 2014 -0500 @@ -47,6 +47,7 @@ private static final int STRING = 0; private static final int PLAIN_TEXT = 1; + @SuppressWarnings("deprecation") private static final DataFlavor[] flavors = { DataFlavor.stringFlavor, DataFlavor.plainTextFlavor // deprecated diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/datatransfer/SystemFlavorMap.java --- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/SystemFlavorMap.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/datatransfer/SystemFlavorMap.java Sat Dec 27 13:27:07 2014 -0500 @@ -624,6 +624,7 @@ return new ArrayList<>(returnValue); } + @SuppressWarnings("deprecation") private static Set convertMimeTypeToDataFlavors( final String baseType) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java Sat Dec 27 13:27:07 2014 -0500 @@ -499,6 +499,7 @@ * */ + @SuppressWarnings("deprecation") public void addNotify(ComponentPeer peer) { if (peer == componentPeer) return; @@ -690,6 +691,7 @@ * update the geometry of the autoscroll region */ + @SuppressWarnings("deprecation") private void updateRegion() { Insets i = autoScroll.getAutoscrollInsets(); Dimension size = component.getSize(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java --- a/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java Sat Dec 27 13:27:07 2014 -0500 @@ -149,6 +149,7 @@ * or attributes is null, or the initial PrintService is not in the * list of browsable services. */ + @SuppressWarnings("deprecation") public static PrintService printDialog(GraphicsConfiguration gc, int x, int y, PrintService[] services, diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/DebugGraphics.java --- a/jdk/src/java.desktop/share/classes/javax/swing/DebugGraphics.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/DebugGraphics.java Sat Dec 27 13:27:07 2014 -0500 @@ -1453,6 +1453,7 @@ /** Returns a DebugGraphics for use in buffering window. */ + @SuppressWarnings("deprecation") private Graphics debugGraphics() { DebugGraphics debugGraphics; DebugGraphicsInfo info = info(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/GroupLayout.java --- a/jdk/src/java.desktop/share/classes/javax/swing/GroupLayout.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/GroupLayout.java Sat Dec 27 13:27:07 2014 -0500 @@ -1213,15 +1213,15 @@ registerComponents(horizontalGroup, HORIZONTAL); registerComponents(verticalGroup, VERTICAL); } - StringBuffer buffer = new StringBuffer(); - buffer.append("HORIZONTAL\n"); - createSpringDescription(buffer, horizontalGroup, " ", HORIZONTAL); - buffer.append("\nVERTICAL\n"); - createSpringDescription(buffer, verticalGroup, " ", VERTICAL); - return buffer.toString(); + StringBuilder sb = new StringBuilder(); + sb.append("HORIZONTAL\n"); + createSpringDescription(sb, horizontalGroup, " ", HORIZONTAL); + sb.append("\nVERTICAL\n"); + createSpringDescription(sb, verticalGroup, " ", VERTICAL); + return sb.toString(); } - private void createSpringDescription(StringBuffer buffer, Spring spring, + private void createSpringDescription(StringBuilder sb, Spring spring, String indent, int axis) { String origin = ""; String padding = ""; @@ -1239,20 +1239,19 @@ padding = ", userCreated=" + paddingSpring.getUserCreated() + ", matches=" + paddingSpring.getMatchDescription(); } - buffer.append(indent + spring.getClass().getName() + " " + - Integer.toHexString(spring.hashCode()) + " " + - origin + - ", size=" + spring.getSize() + - ", alignment=" + spring.getAlignment() + - " prefs=[" + spring.getMinimumSize(axis) + - " " + spring.getPreferredSize(axis) + - " " + spring.getMaximumSize(axis) + - padding + "]\n"); + sb.append(indent).append(spring.getClass().getName()).append(' ') + .append(Integer.toHexString(spring.hashCode())).append(' ') + .append(origin).append(", size=").append(spring.getSize()) + .append(", alignment=").append(spring.getAlignment()) + .append(" prefs=[").append(spring.getMinimumSize(axis)) + .append(' ').append(spring.getPreferredSize(axis)).append(' ') + .append(spring.getMaximumSize(axis)).append(padding) + .append("]\n"); if (spring instanceof Group) { List springs = ((Group)spring).springs; indent += " "; for (int counter = 0; counter < springs.size(); counter++) { - createSpringDescription(buffer, springs.get(counter), indent, + createSpringDescription(sb, springs.get(counter), indent, axis); } } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/JApplet.java --- a/jdk/src/java.desktop/share/classes/javax/swing/JApplet.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JApplet.java Sat Dec 27 13:27:07 2014 -0500 @@ -243,6 +243,7 @@ * hidden: true * description: The menubar for accessing pulldown menus from this applet. */ + @SuppressWarnings("deprecation") public void setJMenuBar(JMenuBar menuBar) { getRootPane().setMenuBar(menuBar); } @@ -253,6 +254,7 @@ * @return the menubar set on this applet * @see #setJMenuBar */ + @SuppressWarnings("deprecation") public JMenuBar getJMenuBar() { return getRootPane().getMenuBar(); } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/JColorChooser.java --- a/jdk/src/java.desktop/share/classes/javax/swing/JColorChooser.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JColorChooser.java Sat Dec 27 13:27:07 2014 -0500 @@ -133,6 +133,7 @@ * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ + @SuppressWarnings("deprecation") public static Color showDialog(Component component, String title, Color initialColor) throws HeadlessException { @@ -543,17 +544,17 @@ * @return a string representation of this JColorChooser */ protected String paramString() { - StringBuilder chooserPanelsString = new StringBuilder(""); - for (int i=0; itrue * @see java.awt.GraphicsEnvironment#isHeadless */ + @SuppressWarnings("deprecation") public static Object showInputDialog(Component parentComponent, Object message, String title, int messageType, Icon icon, Object[] selectionValues, Object initialSelectionValue) @@ -855,6 +856,7 @@ * true * @see java.awt.GraphicsEnvironment#isHeadless */ + @SuppressWarnings("deprecation") public static int showOptionDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon, Object[] options, Object initialValue) diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java --- a/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java Sat Dec 27 13:27:07 2014 -0500 @@ -333,6 +333,7 @@ * @see #addChangeListener * @see EventListenerList */ + @SuppressWarnings("deprecation") protected void fireStateChanged() { /* --- Begin code to deal with visibility --- */ @@ -949,6 +950,7 @@ * @see #addTab * @see #insertTab */ + @SuppressWarnings("deprecation") public void removeTabAt(int index) { checkIndex(index); @@ -1557,6 +1559,7 @@ * attribute: visualUpdate true * description: The component at the specified tab index. */ + @SuppressWarnings("deprecation") public void setComponentAt(int index, Component component) { Page page = pages.get(index); if (component != page.component) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/JTable.java --- a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java Sat Dec 27 13:27:07 2014 -0500 @@ -5810,6 +5810,7 @@ * where 0 is the first column * @return the Component being edited */ + @SuppressWarnings("deprecation") public Component prepareEditor(TableCellEditor editor, int row, int column) { Object value = getValueAt(row, column); boolean isSelected = isCellSelected(row, column); @@ -8788,6 +8789,7 @@ } } + @SuppressWarnings("deprecation") public boolean isFocusTraversable() { AccessibleContext ac = getCurrentAccessibleContext(); if (ac instanceof AccessibleComponent) { @@ -9640,6 +9642,7 @@ * @see AccessibleState#FOCUSED * @see AccessibleStateSet */ + @SuppressWarnings("deprecation") public boolean isFocusTraversable() { AccessibleContext ac = getCurrentAccessibleContext(); if (ac instanceof AccessibleComponent) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/JViewport.java --- a/jdk/src/java.desktop/share/classes/javax/swing/JViewport.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JViewport.java Sat Dec 27 13:27:07 2014 -0500 @@ -829,6 +829,7 @@ * * @see JComponent#reshape(int, int, int, int) */ + @SuppressWarnings("deprecation") public void reshape(int x, int y, int w, int h) { boolean sizeChanged = (getWidth() != w) || (getHeight() != h); if (sizeChanged) { @@ -1447,6 +1448,7 @@ * Returns true if the component needs to be completely repainted after * a blit and a paint is received. */ + @SuppressWarnings("deprecation") private boolean needsRepaintAfterBlit() { // Find the first heavy weight ancestor. isObscured and // canDetermineObscurity are only appropriate for heavy weights. diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/Popup.java --- a/jdk/src/java.desktop/share/classes/javax/swing/Popup.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/Popup.java Sat Dec 27 13:27:07 2014 -0500 @@ -253,6 +253,7 @@ paint(g); } + @SuppressWarnings("deprecation") public void show() { this.pack(); if (getWidth() > 0 && getHeight() > 0) { diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/ProgressMonitor.java --- a/jdk/src/java.desktop/share/classes/javax/swing/ProgressMonitor.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/ProgressMonitor.java Sat Dec 27 13:27:07 2014 -0500 @@ -260,6 +260,7 @@ * @see #setMaximum * @see #close */ + @SuppressWarnings("deprecation") public void setProgress(int nv) { if (nv >= max) { close(); diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java --- a/jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java Sat Dec 27 13:27:07 2014 -0500 @@ -401,6 +401,7 @@ * * @see JComponent#repaint */ + @SuppressWarnings("deprecation") private void addDirtyRegion0(Container c, int x, int y, int w, int h) { /* Special cases we don't have to bother with. */ diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/SortingFocusTraversalPolicy.java --- a/jdk/src/java.desktop/share/classes/javax/swing/SortingFocusTraversalPolicy.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/SortingFocusTraversalPolicy.java Sat Dec 27 13:27:07 2014 -0500 @@ -195,6 +195,7 @@ return true; } + @SuppressWarnings("deprecation") private void enumerateCycle(Container container, List cycle) { if (!(container.isVisible() && container.isDisplayable())) { return; diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java --- a/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java Sat Dec 27 13:27:07 2014 -0500 @@ -1929,6 +1929,7 @@ public void windowDeactivated(WindowEvent e) { } + @SuppressWarnings("deprecation") public void show() { // This frame can never be shown } diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/UIManager.java --- a/jdk/src/java.desktop/share/classes/javax/swing/UIManager.java Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/UIManager.java Sat Dec 27 13:27:07 2014 -0500 @@ -1436,6 +1436,7 @@ /* * Sets default swing focus traversal policy. */ + @SuppressWarnings("deprecation") private static void maybeInitializeFocusPolicy(JComponent comp) { // Check for JRootPane which indicates that a swing toplevel // is coming, in which case a swing default focus policy diff -r 91f29bdf440b -r e1bff46ea1e4 jdk/src/java.desktop/share/classes/javax/swing/package.html --- a/jdk/src/java.desktop/share/classes/javax/swing/package.html Sat Dec 27 07:09:32 2014 -0800 +++ b/jdk/src/java.desktop/share/classes/javax/swing/package.html Sat Dec 27 13:27:07 2014 -0500 @@ -3,7 +3,7 @@