Mercurial > hg > release > icedtea7-forest-2.6 > jdk
changeset 8305:388d34a2e45c jdk7u67-b31
Merge
author | alitvinov |
---|---|
date | Thu, 31 Jul 2014 15:54:03 +0400 |
parents | 0666a58a7e58 (current diff) 59fb46b98fff (diff) |
children | de2b809bb959 |
files | .hgtags src/macosx/classes/sun/lwawt/macosx/CMouseInfoPeer.java |
diffstat | 45 files changed, 2119 insertions(+), 679 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Tue Jul 29 17:50:39 2014 +0100 +++ b/.hgtags Thu Jul 31 15:54:03 2014 +0400 @@ -408,6 +408,9 @@ 88f1bf248cc520e0bf7ef17bc862f87aab958373 jdk7u55-b31 b83f5194edf23b752fe2c0a9be361455f87196df jdk7u55-b32 01a4cd03a6c85abb62eb5d1c2b5bf7d2f544c04e jdk7u55-b33 +3f54f8a387c1a908c07106b685183b19a5fc1064 jdk7u55-b34 +2cdc52ec4813abe38b4e52ae9c9f0ff5dcc87faa jdk7u55-b35 +6845d311ff990d422f9376d37e3e82d5d06bff3f jdk7u55-b36 db5a29c812ee25c34ce9cd97de6e0dae284a4e34 jdk7u60-b00 def34c4a798678c424786a8f0d0508e90185958d jdk7u60-b01 ff67c89658525e8903fb870861ed3645befd6bc5 jdk7u60-b02 @@ -429,6 +432,10 @@ e484202d9a4104840d758a21b2bba1250e766343 jdk7u60-b18 c220d329a78161f79df73048ed55db91f538e3b7 jdk7u65-b01 7190843ddaf4f3ad158c3071be0f4ca42a5802dc jdk7u60-b19 +8dc56d0f3e860658619eaa57d10fb1a4182d71cd jdk7u60-b30 +feac9624a1e1ffebe09a19ae351d88e3ef98c441 jdk7u60-b31 +fb40615ef352e03ee94c0682a6ca0a0e6a33a70b jdk7u60-b32 +9cfcdeeecfac66004cb5bbb2c5bba5c57e170539 jdk7u60-b33 a42a3bb22f6991d8f6a30e4f1782ad620c40eb65 jdk7u65-b02 756071871d61e1ca410c63a3f1c4dabcc51a90df jdk7u65-b03 bac16c82c14a35d1e9d3c4d0bd317dbbb296f34e jdk7u65-b04 @@ -450,4 +457,6 @@ ba6cef21c369076be97dd8133fd4a158cd486bd8 jdk7u65-b19 c3a56021fc22f886106f123d4f25b385ac6b79d7 jdk7u65-b32 8b9d926bd35adceb99f244b7b068fedb0f220f03 jdk7u65-b20 +7b47a34063e94e1ab5636b11231d33fae92754c9 jdk7u65-b31 +4cb63f8ca9ee8c60d6f3d0051b69acc8392bd8de jdk7u65-b33 5cf343beab2ce73d299d4f1a8f3b95892f9fd818 jdk7u67-b01
--- a/make/sun/lwawt/FILES_export_macosx.gmk Tue Jul 29 17:50:39 2014 +0100 +++ b/make/sun/lwawt/FILES_export_macosx.gmk Thu Jul 31 15:54:03 2014 +0400 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 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 @@ -141,7 +141,6 @@ sun/lwawt/macosx/CMenuBar.java \ sun/lwawt/macosx/CMenuComponent.java \ sun/lwawt/macosx/CMenuItem.java \ - sun/lwawt/macosx/CMouseInfoPeer.java \ sun/lwawt/macosx/CPlatformView.java \ sun/lwawt/macosx/CPlatformWindow.java \ sun/lwawt/macosx/CPlatformComponent.java \
--- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java Thu Jul 31 15:54:03 2014 +0400 @@ -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 @@ -89,10 +89,15 @@ private volatile int windowState = Frame.NORMAL; + // check that the mouse is over the window + private volatile boolean isMouseOver = false; + // A peer where the last mouse event came to. Used by cursor manager to + // find the component under cursor + private static volatile LWComponentPeer lastCommonMouseEventPeer = null; + // A peer where the last mouse event came to. Used to generate - // MOUSE_ENTERED/EXITED notifications and by cursor manager to - // find the component under cursor - private static volatile LWComponentPeer lastMouseEventPeer = null; + // MOUSE_ENTERED/EXITED notifications + private volatile LWComponentPeer lastMouseEventPeer; // Peers where all dragged/released events should come to, // depending on what mouse button is being dragged according to Cocoa @@ -773,59 +778,62 @@ Rectangle r = getBounds(); // findPeerAt() expects parent coordinates LWComponentPeer targetPeer = findPeerAt(r.x + x, r.y + y); - LWWindowPeer lastWindowPeer = - (lastMouseEventPeer != null) ? lastMouseEventPeer.getWindowPeerOrSelf() : null; - LWWindowPeer curWindowPeer = - (targetPeer != null) ? targetPeer.getWindowPeerOrSelf() : null; if (id == MouseEvent.MOUSE_EXITED) { - // Sometimes we may get MOUSE_EXITED after lastMouseEventPeer is switched - // to a peer from another window. So we must first check if this peer is - // the same as lastWindowPeer - if (lastWindowPeer == this) { - if (isEnabled()) { + isMouseOver = false; + if (lastMouseEventPeer != null) { + if (lastMouseEventPeer.isEnabled()) { Point lp = lastMouseEventPeer.windowToLocal(x, y, - lastWindowPeer); + this); Component target = lastMouseEventPeer.getTarget(); postMouseEnteredExitedEvent(target, MouseEvent.MOUSE_EXITED, when, modifiers, lp, screenX, screenY, clickCount, popupTrigger, button); } + + // Sometimes we may get MOUSE_EXITED after lastCommonMouseEventPeer is switched + // to a peer from another window. So we must first check if this peer is + // the same as lastWindowPeer + if (lastCommonMouseEventPeer != null && lastCommonMouseEventPeer.getWindowPeerOrSelf() == this) { + lastCommonMouseEventPeer = null; + } lastMouseEventPeer = null; } + } else if (id == MouseEvent.MOUSE_ENTERED) { + isMouseOver = true; + if (targetPeer != null) { + if (targetPeer.isEnabled()) { + Point lp = targetPeer.windowToLocal(x, y, this); + Component target = targetPeer.getTarget(); + postMouseEnteredExitedEvent(target, MouseEvent.MOUSE_ENTERED, when, modifiers, lp, + screenX, screenY, clickCount, popupTrigger, button); + } + lastCommonMouseEventPeer = targetPeer; + lastMouseEventPeer = targetPeer; + } } else { - if (targetPeer != lastMouseEventPeer) { - // lastMouseEventPeer may be null if mouse was out of Java windows - if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) { - // Sometimes, MOUSE_EXITED is not sent by delegate (or is sent a bit - // later), in which case lastWindowPeer is another window - if (lastWindowPeer != this) { - Point oldp = lastMouseEventPeer.windowToLocal(x, y, lastWindowPeer); - // Additionally translate from this to lastWindowPeer coordinates - Rectangle lr = lastWindowPeer.getBounds(); - oldp.x += r.x - lr.x; - oldp.y += r.y - lr.y; - Component target = lastMouseEventPeer.getTarget(); - postMouseEnteredExitedEvent(target, MouseEvent.MOUSE_EXITED, - when, modifiers, oldp, - screenX, screenY, clickCount, popupTrigger, button); - } else { - Point oldp = lastMouseEventPeer.windowToLocal(x, y, this); - Component target = lastMouseEventPeer.getTarget(); - postMouseEnteredExitedEvent(target, MouseEvent.MOUSE_EXITED, - when, modifiers, oldp, - screenX, screenY, clickCount, popupTrigger, button); - } - } - lastMouseEventPeer = targetPeer; - if (targetPeer != null && targetPeer.isEnabled() && id != MouseEvent.MOUSE_ENTERED) { - Point newp = targetPeer.windowToLocal(x, y, curWindowPeer); - Component target = targetPeer.getTarget(); - postMouseEnteredExitedEvent(target, MouseEvent.MOUSE_ENTERED, - when, modifiers, newp, - screenX, screenY, clickCount, popupTrigger, button); - } + PlatformWindow topmostPlatformWindow = + platformWindow.getTopmostPlatformWindowUnderMouse(); + + LWWindowPeer topmostWindowPeer = + topmostPlatformWindow != null ? topmostPlatformWindow.getPeer() : null; + + // topmostWindowPeer == null condition is added for the backword + // compatibility with applets. It can be removed when the + // getTopmostPlatformWindowUnderMouse() method will be properly + // implemented i CPlatformEmbeddedFrame class + if (topmostWindowPeer == this || topmostWindowPeer == null) { + generateMouseEnterExitEventsForComponents(when, button, x, y, + screenX, screenY, modifiers, clickCount, popupTrigger, + targetPeer); + } else { + LWComponentPeer topmostTargetPeer = + topmostWindowPeer != null ? topmostWindowPeer.findPeerAt(r.x + x, r.y + y) : null; + topmostWindowPeer.generateMouseEnterExitEventsForComponents(when, button, x, y, + screenX, screenY, modifiers, clickCount, popupTrigger, + topmostTargetPeer); } + // TODO: fill "bdata" member of AWTEvent int eventButtonMask = (button > 0)? MouseEvent.getMaskForButton(button) : 0; @@ -875,19 +883,13 @@ // mouseClickButtons is updated below, after MOUSE_CLICK is sent } - // check if we receive mouseEvent from outside the window's bounds - // it can be either mouseDragged or mouseReleased - if (curWindowPeer == null) { - //TODO This can happen if this window is invisible. this is correct behavior in this case? - curWindowPeer = this; - } if (targetPeer == null) { //TODO This can happen if this window is invisible. this is correct behavior in this case? targetPeer = this; } - Point lp = targetPeer.windowToLocal(x, y, curWindowPeer); + Point lp = targetPeer.windowToLocal(x, y, this); if (targetPeer.isEnabled()) { if (id == MouseEvent.MOUSE_ENTERED || id == MouseEvent.MOUSE_EXITED) { postMouseEnteredExitedEvent(targetPeer.getTarget(), id, @@ -918,6 +920,33 @@ notifyUpdateCursor(); } + private void generateMouseEnterExitEventsForComponents(long when, + int button, int x, int y, int screenX, int screenY, + int modifiers, int clickCount, boolean popupTriger, + LWComponentPeer targetPeer) { + if (!isMouseOver || targetPeer == lastMouseEventPeer) { + return; + } + + // Generate Mouse Exit for components + if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) { + Point oldp = lastMouseEventPeer.windowToLocal(x, y, this); + Component target = lastMouseEventPeer.getTarget(); + postMouseEnteredExitedEvent(target, MouseEvent.MOUSE_EXITED, when, modifiers, + oldp, screenX, screenY, clickCount, popupTriger, button); + } + lastCommonMouseEventPeer = targetPeer; + lastMouseEventPeer = targetPeer; + + // Genrate Mouse Enter for Componetns + if (targetPeer != null && targetPeer.isEnabled()) { + Point newp = targetPeer.windowToLocal(x, y, this); + Component target = targetPeer.getTarget(); + postMouseEnteredExitedEvent(target, MouseEvent.MOUSE_ENTERED, when, modifiers, + newp, screenX, screenY, clickCount, popupTriger, button); + } + } + private void postMouseEnteredExitedEvent( Component target, int id, long when, int modifiers, Point loc, int xAbs, int yAbs, @@ -1198,11 +1227,11 @@ } public static LWWindowPeer getWindowUnderCursor() { - return lastMouseEventPeer != null ? lastMouseEventPeer.getWindowPeerOrSelf() : null; + return lastCommonMouseEventPeer != null ? lastCommonMouseEventPeer.getWindowPeerOrSelf() : null; } public static LWComponentPeer<?, ?> getPeerUnderCursor() { - return lastMouseEventPeer; + return lastCommonMouseEventPeer; } /*
--- a/src/macosx/classes/sun/lwawt/PlatformWindow.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/macosx/classes/sun/lwawt/PlatformWindow.java Thu Jul 31 15:54:03 2014 +0400 @@ -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 @@ -118,6 +118,8 @@ public void setAlwaysOnTop(boolean value); + public PlatformWindow getTopmostPlatformWindowUnderMouse(); + public void updateFocusableWindowState(); public boolean rejectFocusRequest(CausedFocusEvent.Cause cause);
--- a/src/macosx/classes/sun/lwawt/macosx/CMouseInfoPeer.java Tue Jul 29 17:50:39 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 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.lwawt.macosx; - -import java.awt.Window; -import sun.lwawt.LWMouseInfoPeer; -import sun.lwawt.LWWindowPeer; - -public class CMouseInfoPeer extends LWMouseInfoPeer -{ - //If a new window is to appear under the cursor, - //we get wrong window. - //This is a workaround for macosx. - @Override - public boolean isWindowUnderMouse(Window w) { - if (w == null) { - return false; - } - - return ((LWWindowPeer)w.getPeer()).getPlatformWindow().isUnderMouse(); - } -}
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java Thu Jul 31 15:54:03 2014 +0400 @@ -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 @@ -151,6 +151,11 @@ @Override public void setAlwaysOnTop(boolean value) {} + // This method should be properly implemented for applets. + // It returns null just as a stub. + @Override + public PlatformWindow getTopmostPlatformWindowUnderMouse() { return null; } + @Override public void updateFocusableWindowState() {}
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Thu Jul 31 15:54:03 2014 +0400 @@ -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 @@ -61,8 +61,9 @@ private static native void nativeSetNSWindowMinimizedIcon(long nsWindowPtr, long nsImage); private static native void nativeSetNSWindowRepresentedFilename(long nsWindowPtr, String representedFilename); private static native void nativeSetEnabled(long nsWindowPtr, boolean isEnabled); - private static native void nativeSynthesizeMouseEnteredExitedEvents(long nsWindowPtr); + private static native void nativeSynthesizeMouseEnteredExitedEvents(); private static native void nativeDispose(long nsWindowPtr); + private static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse(); // Loger to report issues happened during execution but that do not affect functionality private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow"); @@ -593,7 +594,7 @@ } } - nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr); + nativeSynthesizeMouseEnteredExitedEvents(); // Configure stuff #2 updateFocusabilityForAutoRequestFocus(true); @@ -738,6 +739,9 @@ setStyleBits(ALWAYS_ON_TOP, isAlwaysOnTop); } + public PlatformWindow getTopmostPlatformWindowUnderMouse() { + return CPlatformWindow.nativeGetTopmostPlatformWindowUnderMouse(); + } @Override public void setOpacity(float opacity) { CWrapper.NSWindow.setAlphaValue(getNSWindowPtr(), opacity); @@ -830,7 +834,7 @@ throw new RuntimeException("Unknown window state: " + windowState); } - nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr); + nativeSynthesizeMouseEnteredExitedEvents(); // NOTE: the SWP.windowState field gets updated to the newWindowState // value when the native notification comes to us
--- a/src/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java Thu Jul 31 15:54:03 2014 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 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 @@ -148,6 +148,11 @@ } @Override + public PlatformWindow getTopmostPlatformWindowUnderMouse() { + return null; + } + + @Override public void updateFocusableWindowState() { }
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Jul 31 15:54:03 2014 +0400 @@ -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 @@ -300,11 +300,6 @@ } @Override - protected MouseInfoPeer createMouseInfoPeerImpl() { - return new CMouseInfoPeer(); - } - - @Override protected int getScreenHeight() { return GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice().getDefaultConfiguration().getBounds().height;
--- a/src/macosx/native/sun/awt/AWTView.h Tue Jul 29 17:50:39 2014 +0100 +++ b/src/macosx/native/sun/awt/AWTView.h Thu Jul 31 15:54:03 2014 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 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 @@ -33,8 +33,8 @@ @private jobject m_cPlatformView; - // Handler for the tracking rect needed for Enter/Exit events management. - NSTrackingRectTag rolloverTrackingRectTag; + // Handler for the tracking area needed for Enter/Exit events management. + NSTrackingArea* rolloverTrackingArea; // TODO: NSMenu *contextualMenu; @@ -61,7 +61,7 @@ - (id) initWithRect:(NSRect) rect platformView:(jobject)cPlatformView windowLayer:(CALayer*)windowLayer; - (void) deliverJavaMouseEvent: (NSEvent *) event; -- (void) resetTrackingRect; +- (void) resetTrackingArea; - (void) deliverJavaKeyEventHelper: (NSEvent *) event; - (jobject) awtComponent:(JNIEnv *)env;
--- a/src/macosx/native/sun/awt/AWTView.m Tue Jul 29 17:50:39 2014 +0100 +++ b/src/macosx/native/sun/awt/AWTView.m Thu Jul 31 15:54:03 2014 +0400 @@ -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 @@ -82,6 +82,7 @@ fPAHNeedsToSelect = NO; mouseIsOver = NO; + [self resetTrackingArea]; if (windowLayer != nil) { self.cglLayer = windowLayer; @@ -149,7 +150,7 @@ [[self window] makeFirstResponder: self]; }]; if ([self window] != NULL) { - [self resetTrackingRect]; + [self resetTrackingArea]; } } @@ -380,30 +381,31 @@ JNFCallVoidMethod(env, m_cPlatformView, jm_deliverMouseEvent, jEvent); } - -- (void) clearTrackingRect { - if (rolloverTrackingRectTag > 0) { - [self removeTrackingRect:rolloverTrackingRectTag]; - rolloverTrackingRectTag = 0; +- (void) resetTrackingArea { + if (rolloverTrackingArea != nil) { + [self removeTrackingArea:rolloverTrackingArea]; + [rolloverTrackingArea release]; } -} + + int options = (NSTrackingActiveAlways | NSTrackingMouseEnteredAndExited | + NSTrackingMouseMoved | NSTrackingEnabledDuringMouseDrag); -- (void) resetTrackingRect { - [self clearTrackingRect]; - rolloverTrackingRectTag = [self addTrackingRect:[self visibleRect] - owner:self - userData:NULL - assumeInside:NO]; + rolloverTrackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] + options:options + owner:self + userInfo:nil + ]; + [self addTrackingArea:rolloverTrackingArea]; } - (void)updateTrackingAreas { [super updateTrackingAreas]; - [self resetTrackingRect]; + [self resetTrackingArea]; } - (void) resetCursorRects { [super resetCursorRects]; - [self resetTrackingRect]; + [self resetTrackingArea]; } -(void) deliverJavaKeyEventHelper: (NSEvent *) event {
--- a/src/macosx/native/sun/awt/AWTWindow.m Tue Jul 29 17:50:39 2014 +0100 +++ b/src/macosx/native/sun/awt/AWTWindow.m Thu Jul 31 15:54:03 2014 +0400 @@ -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 @@ -314,10 +314,8 @@ return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]]; } -// checks that this window is under the mouse cursor and this point is not overlapped by others windows -- (BOOL) isTopmostWindowUnderMouse { - - int currentWinID = [self.nsWindow windowNumber]; +// return id for the topmost window under mouse ++ (NSInteger) getTopmostWindowUnderMouseID { NSRect screenRect = [[NSScreen mainScreen] frame]; NSPoint nsMouseLocation = [NSEvent mouseLocation]; @@ -327,51 +325,75 @@ for (NSDictionary *window in windows) { - int layer = [[window objectForKey:(id)kCGWindowLayer] intValue]; + NSInteger layer = [[window objectForKey:(id)kCGWindowLayer] integerValue]; if (layer == 0) { - int winID = [[window objectForKey:(id)kCGWindowNumber] intValue]; CGRect rect; CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect); if (CGRectContainsPoint(rect, cgMouseLocation)) { - return currentWinID == winID; - } else if (currentWinID == winID) { - return NO; + return [[window objectForKey:(id)kCGWindowNumber] integerValue]; } } } - return NO; + return -1; +} + +// checks that this window is under the mouse cursor and this point is not overlapped by other windows +- (BOOL) isTopmostWindowUnderMouse { + return [self.nsWindow windowNumber] == [AWTWindow getTopmostWindowUnderMouseID]; } -- (void) synthesizeMouseEnteredExitedEvents { ++ (AWTWindow *) getTopmostWindowUnderMouse { + NSEnumerator *windowEnumerator = [[NSApp windows] objectEnumerator]; + NSWindow *window; - int eventType = 0; - BOOL isUnderMouse = [self isTopmostWindowUnderMouse]; - BOOL mouseIsOver = [[self.nsWindow contentView] mouseIsOver]; + NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID]; - if (isUnderMouse && !mouseIsOver) { - eventType = NSMouseEntered; - } else if (!isUnderMouse && mouseIsOver) { - eventType = NSMouseExited; - } else { - return; + while ((window = [windowEnumerator nextObject]) != nil) { + if ([window windowNumber] == topmostWindowUnderMouseID) { + BOOL isAWTWindow = [AWTWindow isAWTWindow: window]; + return isAWTWindow ? (AWTWindow *) [window delegate] : nil; + } } + return nil; +} + ++ (void) synthesizeMouseEnteredExitedEvents:(NSWindow*)window withType:(NSEventType)eventType { NSPoint screenLocation = [NSEvent mouseLocation]; - NSPoint windowLocation = [self.nsWindow convertScreenToBase: screenLocation]; + NSPoint windowLocation = [window convertScreenToBase: screenLocation]; int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask; NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType location: windowLocation modifierFlags: modifierFlags timestamp: 0 - windowNumber: [self.nsWindow windowNumber] + windowNumber: [window windowNumber] context: nil eventNumber: 0 trackingNumber: 0 userData: nil ]; - [[self.nsWindow contentView] deliverJavaMouseEvent: mouseEvent]; + [[window contentView] deliverJavaMouseEvent: mouseEvent]; +} + ++(void) synthesizeMouseEnteredExitedEventsForAllWindows { + NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID]; + NSArray *windows = [NSApp windows]; + NSWindow *window; + + NSEnumerator *windowEnumerator = [windows objectEnumerator]; + while ((window = [windowEnumerator nextObject]) != nil) { + if ([AWTWindow isAWTWindow: window]) { + BOOL isUnderMouse = ([window windowNumber] == topmostWindowUnderMouseID); + BOOL mouseIsOver = [[window contentView] mouseIsOver]; + if (isUnderMouse && !mouseIsOver) { + [AWTWindow synthesizeMouseEnteredExitedEvents: window withType:NSMouseEntered]; + } else if (!isUnderMouse && mouseIsOver) { + [AWTWindow synthesizeMouseEnteredExitedEvents: window withType:NSMouseExited]; + } + } + } } + (NSNumber *) getNSWindowDisplayID_AppKitThread:(NSWindow *)window { @@ -979,7 +1001,7 @@ // (this will also re-enable screen updates, which were disabled above) // TODO: send PaintEvent - [window synthesizeMouseEnteredExitedEvents]; + [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows]; }]; JNF_COCOA_EXIT(env); @@ -1158,19 +1180,40 @@ /* * Class: sun_lwawt_macosx_CPlatformWindow + * Method: nativeGetTopMostWindowUnderMouse + * Signature: (J)V + */ +JNIEXPORT jobject +JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnderMouse +(JNIEnv *env, jclass clazz) +{ + jobject topmostWindowUnderMouse = nil; + + JNF_COCOA_ENTER(env); + AWT_ASSERT_APPKIT_THREAD; + + AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse]; + if (awtWindow != nil) { + topmostWindowUnderMouse = [awtWindow.javaPlatformWindow jObject]; + } + + JNF_COCOA_EXIT(env); + + return topmostWindowUnderMouse; +} + +/* + * Class: sun_lwawt_macosx_CPlatformWindow * Method: nativeSynthesizeMouseEnteredExitedEvents * Signature: (J)V */ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents -(JNIEnv *env, jclass clazz, jlong windowPtr) +(JNIEnv *env, jclass clazz) { JNF_COCOA_ENTER(env); - NSWindow *nsWindow = OBJC(windowPtr); [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ - AWTWindow *window = (AWTWindow*)[nsWindow delegate]; - - [window synthesizeMouseEnteredExitedEvents]; + [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows]; }]; JNF_COCOA_EXIT(env);
--- a/src/share/classes/com/sun/crypto/provider/RSACipher.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/com/sun/crypto/provider/RSACipher.java Thu Jul 31 15:54:03 2014 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -39,6 +39,8 @@ import sun.security.rsa.*; import sun.security.jca.Providers; +import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; +import sun.security.util.KeyUtil; /** * RSA cipher implementation. Supports RSA en/decryption and signing/verifying @@ -91,8 +93,8 @@ // padding object private RSAPadding padding; - // cipher parameter for OAEP padding - private OAEPParameterSpec spec = null; + // cipher parameter for OAEP padding and TLS RSA premaster secret + private AlgorithmParameterSpec spec = null; // buffer for the data private byte[] buffer; @@ -110,6 +112,9 @@ // hash algorithm for OAEP private String oaepHashAlgorithm = "SHA-1"; + // the source of randomness + private SecureRandom random; + public RSACipher() { paddingType = PAD_PKCS1; } @@ -175,7 +180,7 @@ // see JCE spec protected AlgorithmParameters engineGetParameters() { - if (spec != null) { + if (spec != null && spec instanceof OAEPParameterSpec) { try { AlgorithmParameters params = AlgorithmParameters.getInstance("OAEP", "SunJCE"); @@ -278,8 +283,13 @@ buffer = new byte[n]; } else if (paddingType == PAD_PKCS1) { if (params != null) { - throw new InvalidAlgorithmParameterException - ("Parameters not supported"); + if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) { + throw new InvalidAlgorithmParameterException( + "Parameters not supported"); + } + + spec = params; + this.random = random; // for TLS RSA premaster secret } int blockType = (mode <= MODE_DECRYPT) ? RSAPadding.PAD_BLOCKTYPE_2 : RSAPadding.PAD_BLOCKTYPE_1; @@ -295,19 +305,18 @@ throw new InvalidKeyException ("OAEP cannot be used to sign or verify signatures"); } - OAEPParameterSpec myParams; if (params != null) { if (!(params instanceof OAEPParameterSpec)) { throw new InvalidAlgorithmParameterException ("Wrong Parameters for OAEP Padding"); } - myParams = (OAEPParameterSpec) params; + spec = params; } else { - myParams = new OAEPParameterSpec(oaepHashAlgorithm, "MGF1", + spec = new OAEPParameterSpec(oaepHashAlgorithm, "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); } padding = RSAPadding.getInstance(RSAPadding.PAD_OAEP_MGF1, n, - random, myParams); + random, (OAEPParameterSpec)spec); if (encrypt) { int k = padding.getMaxDataSize(); buffer = new byte[k]; @@ -422,17 +431,40 @@ if (wrappedKey.length > buffer.length) { throw new InvalidKeyException("Key is too long for unwrapping"); } + + boolean isTlsRsaPremasterSecret = + algorithm.equals("TlsRsaPremasterSecret"); + Exception failover = null; + byte[] encoded = null; + update(wrappedKey, 0, wrappedKey.length); try { - byte[] encoded = doFinal(); - return ConstructKeys.constructKey(encoded, algorithm, type); + encoded = doFinal(); } catch (BadPaddingException e) { - // should not occur - throw new InvalidKeyException("Unwrapping failed", e); + if (isTlsRsaPremasterSecret) { + failover = e; + } else { + throw new InvalidKeyException("Unwrapping failed", e); + } } catch (IllegalBlockSizeException e) { // should not occur, handled with length check above throw new InvalidKeyException("Unwrapping failed", e); } + + if (isTlsRsaPremasterSecret) { + if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) { + throw new IllegalStateException( + "No TlsRsaPremasterSecretParameterSpec specified"); + } + + // polish the TLS premaster secret + encoded = KeyUtil.checkTlsPreMasterSecretKey( + ((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(), + ((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(), + random, encoded, (failover != null)); + } + + return ConstructKeys.constructKey(encoded, algorithm, type); } // see JCE spec @@ -440,5 +472,4 @@ RSAKey rsaKey = RSAKeyFactory.toRSAKey(key); return rsaKey.getModulus().bitLength(); } - }
--- a/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/com/sun/crypto/provider/TlsRsaPremasterSecretGenerator.java Thu Jul 31 15:54:03 2014 +0400 @@ -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 @@ -56,7 +56,7 @@ protected void engineInit(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { - if (params instanceof TlsRsaPremasterSecretParameterSpec == false) { + if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) { throw new InvalidAlgorithmParameterException(MSG); } this.spec = (TlsRsaPremasterSecretParameterSpec)params; @@ -67,21 +67,20 @@ throw new InvalidParameterException(MSG); } + // Only can be used in client side to generate TLS RSA premaster secret. protected SecretKey engineGenerateKey() { if (spec == null) { throw new IllegalStateException( "TlsRsaPremasterSecretGenerator must be initialized"); } - byte[] b = spec.getEncodedSecret(); - if (b == null) { - if (random == null) { - random = new SecureRandom(); - } - b = new byte[48]; - random.nextBytes(b); - b[0] = (byte)spec.getMajorVersion(); - b[1] = (byte)spec.getMinorVersion(); + + if (random == null) { + random = new SecureRandom(); } + byte[] b = new byte[48]; + random.nextBytes(b); + b[0] = (byte)spec.getMajorVersion(); + b[1] = (byte)spec.getMinorVersion(); return new SecretKeySpec(b, "TlsRsaPremasterSecret"); }
--- a/src/share/classes/java/io/ObjectOutputStream.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/java/io/ObjectOutputStream.java Thu Jul 31 15:54:03 2014 +0400 @@ -1254,7 +1254,7 @@ } bout.setBlockDataMode(true); - if (isCustomSubclass()) { + if (cl != null && isCustomSubclass()) { ReflectUtil.checkPackageAccess(cl); } annotateProxyClass(cl); @@ -1283,7 +1283,7 @@ Class cl = desc.forClass(); bout.setBlockDataMode(true); - if (isCustomSubclass()) { + if (cl != null && isCustomSubclass()) { ReflectUtil.checkPackageAccess(cl); } annotateClass(cl);
--- a/src/share/classes/java/lang/Class.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/java/lang/Class.java Thu Jul 31 15:54:03 2014 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -2338,44 +2338,110 @@ } /** + * Atomic operations support. + */ + private static class Atomic { + // initialize Unsafe machinery here, since we need to call Class.class instance method + // and have to avoid calling it in the static initializer of the Class class... + private static final Unsafe unsafe = Unsafe.getUnsafe(); + // offset of Class.reflectionData instance field + private static final long reflectionDataOffset; + // offset of Class.annotationType instance field + private static final long annotationTypeOffset; + + static { + Field[] fields = Class.class.getDeclaredFields0(false); // bypass caches + reflectionDataOffset = objectFieldOffset(fields, "reflectionData"); + annotationTypeOffset = objectFieldOffset(fields, "annotationType"); + } + + private static long objectFieldOffset(Field[] fields, String fieldName) { + Field field = searchFields(fields, fieldName); + if (field == null) { + throw new Error("No " + fieldName + " field found in java.lang.Class"); + } + return unsafe.objectFieldOffset(field); + } + + static <T> boolean casReflectionData(Class<?> clazz, + SoftReference<ReflectionData<T>> oldData, + SoftReference<ReflectionData<T>> newData) { + return unsafe.compareAndSwapObject(clazz, reflectionDataOffset, oldData, newData); + } + + static <T> boolean casAnnotationType(Class<?> clazz, + AnnotationType oldType, + AnnotationType newType) { + return unsafe.compareAndSwapObject(clazz, annotationTypeOffset, oldType, newType); + } + } + + /** * Reflection support. */ // Caches for certain reflective results private static boolean useCaches = true; - private volatile transient SoftReference<Field[]> declaredFields; - private volatile transient SoftReference<Field[]> publicFields; - private volatile transient SoftReference<Method[]> declaredMethods; - private volatile transient SoftReference<Method[]> publicMethods; - private volatile transient SoftReference<Constructor<T>[]> declaredConstructors; - private volatile transient SoftReference<Constructor<T>[]> publicConstructors; - // Intermediate results for getFields and getMethods - private volatile transient SoftReference<Field[]> declaredPublicFields; - private volatile transient SoftReference<Method[]> declaredPublicMethods; + + // reflection data that might get invalidated when JVM TI RedefineClasses() is called + static class ReflectionData<T> { + volatile Field[] declaredFields; + volatile Field[] publicFields; + volatile Method[] declaredMethods; + volatile Method[] publicMethods; + volatile Constructor<T>[] declaredConstructors; + volatile Constructor<T>[] publicConstructors; + // Intermediate results for getFields and getMethods + volatile Field[] declaredPublicFields; + volatile Method[] declaredPublicMethods; + // Value of classRedefinedCount when we created this ReflectionData instance + final int redefinedCount; + + ReflectionData(int redefinedCount) { + this.redefinedCount = redefinedCount; + } + } + + private volatile transient SoftReference<ReflectionData<T>> reflectionData; // Incremented by the VM on each call to JVM TI RedefineClasses() // that redefines this class or a superclass. private volatile transient int classRedefinedCount = 0; - // Value of classRedefinedCount when we last cleared the cached values - // that are sensitive to class redefinition. - private volatile transient int lastRedefinedCount = 0; + // Lazily create and cache ReflectionData + private ReflectionData<T> reflectionData() { + SoftReference<ReflectionData<T>> reflectionData = this.reflectionData; + int classRedefinedCount = this.classRedefinedCount; + ReflectionData<T> rd; + if (useCaches && + reflectionData != null && + (rd = reflectionData.get()) != null && + rd.redefinedCount == classRedefinedCount) { + return rd; + } + // else no SoftReference or cleared SoftReference or stale ReflectionData + // -> create and replace new instance + return newReflectionData(reflectionData, classRedefinedCount); + } - // Clears cached values that might possibly have been obsoleted by - // a class redefinition. - private void clearCachesOnClassRedefinition() { - if (lastRedefinedCount != classRedefinedCount) { - declaredFields = publicFields = declaredPublicFields = null; - declaredMethods = publicMethods = declaredPublicMethods = null; - declaredConstructors = publicConstructors = null; - annotations = declaredAnnotations = null; + private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData, + int classRedefinedCount) { + if (!useCaches) return null; - // Use of "volatile" (and synchronization by caller in the case - // of annotations) ensures that no thread sees the update to - // lastRedefinedCount before seeing the caches cleared. - // We do not guard against brief windows during which multiple - // threads might redundantly work to fill an empty cache. - lastRedefinedCount = classRedefinedCount; + while (true) { + ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount); + // try to CAS it... + if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) { + return rd; + } + // else retry + oldReflectionData = this.reflectionData; + classRedefinedCount = this.classRedefinedCount; + if (oldReflectionData != null && + (rd = oldReflectionData.get()) != null && + rd.redefinedCount == classRedefinedCount) { + return rd; + } } } @@ -2403,7 +2469,7 @@ } // Annotations handling - private native byte[] getRawAnnotations(); + native byte[] getRawAnnotations(); native ConstantPool getConstantPool(); @@ -2418,27 +2484,19 @@ // via ReflectionFactory.copyField. private Field[] privateGetDeclaredFields(boolean publicOnly) { checkInitted(); - Field[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicOnly) { - if (declaredPublicFields != null) { - res = declaredPublicFields.get(); - } - } else { - if (declaredFields != null) { - res = declaredFields.get(); - } - } + Field[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = publicOnly ? rd.declaredPublicFields : rd.declaredFields; if (res != null) return res; } // No cached value available; request value from VM res = Reflection.filterFields(this, getDeclaredFields0(publicOnly)); - if (useCaches) { + if (rd != null) { if (publicOnly) { - declaredPublicFields = new SoftReference<>(res); + rd.declaredPublicFields = res; } else { - declaredFields = new SoftReference<>(res); + rd.declaredFields = res; } } return res; @@ -2449,12 +2507,10 @@ // via ReflectionFactory.copyField. private Field[] privateGetPublicFields(Set<Class<?>> traversedInterfaces) { checkInitted(); - Field[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicFields != null) { - res = publicFields.get(); - } + Field[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = rd.publicFields; if (res != null) return res; } @@ -2487,8 +2543,8 @@ res = new Field[fields.size()]; fields.toArray(res); - if (useCaches) { - publicFields = new SoftReference<>(res); + if (rd != null) { + rd.publicFields = res; } return res; } @@ -2511,18 +2567,10 @@ // instead be copied via ReflectionFactory.copyConstructor. private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) { checkInitted(); - Constructor<T>[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicOnly) { - if (publicConstructors != null) { - res = publicConstructors.get(); - } - } else { - if (declaredConstructors != null) { - res = declaredConstructors.get(); - } - } + Constructor<T>[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = publicOnly ? rd.publicConstructors : rd.declaredConstructors; if (res != null) return res; } // No cached value available; request value from VM @@ -2531,11 +2579,11 @@ } else { res = getDeclaredConstructors0(publicOnly); } - if (useCaches) { + if (rd != null) { if (publicOnly) { - publicConstructors = new SoftReference<>(res); + rd.publicConstructors = res; } else { - declaredConstructors = new SoftReference<>(res); + rd.declaredConstructors = res; } } return res; @@ -2552,27 +2600,19 @@ // via ReflectionFactory.copyMethod. private Method[] privateGetDeclaredMethods(boolean publicOnly) { checkInitted(); - Method[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicOnly) { - if (declaredPublicMethods != null) { - res = declaredPublicMethods.get(); - } - } else { - if (declaredMethods != null) { - res = declaredMethods.get(); - } - } + Method[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods; if (res != null) return res; } // No cached value available; request value from VM res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly)); - if (useCaches) { + if (rd != null) { if (publicOnly) { - declaredPublicMethods = new SoftReference<>(res); + rd.declaredPublicMethods = res; } else { - declaredMethods = new SoftReference<>(res); + rd.declaredMethods = res; } } return res; @@ -2674,12 +2714,10 @@ // via ReflectionFactory.copyMethod. private Method[] privateGetPublicMethods() { checkInitted(); - Method[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicMethods != null) { - res = publicMethods.get(); - } + Method[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = rd.publicMethods; if (res != null) return res; } @@ -2727,8 +2765,8 @@ methods.addAllIfNotPresent(inheritedMethods); methods.compactAndTrim(); res = methods.getArray(); - if (useCaches) { - publicMethods = new SoftReference<>(res); + if (rd != null) { + rd.publicMethods = res; } return res; } @@ -2738,7 +2776,7 @@ // Helpers for fetchers of one field, method, or constructor // - private Field searchFields(Field[] fields, String name) { + private static Field searchFields(Field[] fields, String name) { String internedName = name.intern(); for (int i = 0; i < fields.length; i++) { if (fields[i].getName() == internedName) { @@ -2756,7 +2794,7 @@ // of Field objects which have to be created for the common // case where the field being requested is declared in the // class which is being queried. - Field res = null; + Field res; // Search declared public fields if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { return res; @@ -2808,7 +2846,7 @@ // number of Method objects which have to be created for the // common case where the method being requested is declared in // the class which is being queried. - Method res = null; + Method res; // Search declared public methods if ((res = searchMethods(privateGetDeclaredMethods(true), name, @@ -3209,9 +3247,20 @@ // Annotations cache private transient Map<Class<? extends Annotation>, Annotation> annotations; private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; + // Value of classRedefinedCount when we last cleared the cached annotations and declaredAnnotations fields + private transient int lastAnnotationsRedefinedCount = 0; + + // Clears cached values that might possibly have been obsoleted by + // a class redefinition. + private void clearAnnotationCachesOnClassRedefinition() { + if (lastAnnotationsRedefinedCount != classRedefinedCount) { + annotations = declaredAnnotations = null; + lastAnnotationsRedefinedCount = classRedefinedCount; + } + } private synchronized void initAnnotationsIfNecessary() { - clearCachesOnClassRedefinition(); + clearAnnotationCachesOnClassRedefinition(); if (annotations != null) return; declaredAnnotations = AnnotationParser.parseAnnotations( @@ -3233,10 +3282,11 @@ // Annotation types cache their internal (AnnotationType) form - private AnnotationType annotationType; + @SuppressWarnings("UnusedDeclaration") + private volatile transient AnnotationType annotationType; - void setAnnotationType(AnnotationType type) { - annotationType = type; + boolean casAnnotationType(AnnotationType oldType, AnnotationType newType) { + return Atomic.casAnnotationType(this, oldType, newType); } AnnotationType getAnnotationType() {
--- a/src/share/classes/java/lang/System.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/java/lang/System.java Thu Jul 31 15:54:03 2014 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -1178,12 +1178,15 @@ public sun.reflect.ConstantPool getConstantPool(Class klass) { return klass.getConstantPool(); } - public void setAnnotationType(Class klass, AnnotationType type) { - klass.setAnnotationType(type); + public boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType) { + return klass.casAnnotationType(oldType, newType); } public AnnotationType getAnnotationType(Class klass) { return klass.getAnnotationType(); } + public byte[] getRawClassAnnotations(Class<?> klass) { + return klass.getRawAnnotations(); + } public <E extends Enum<E>> E[] getEnumConstantsShared(Class<E> klass) { return klass.getEnumConstantsShared();
--- a/src/share/classes/javax/crypto/JceSecurity.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/javax/crypto/JceSecurity.java Thu Jul 31 15:54:03 2014 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, 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 @@ -216,26 +216,28 @@ private static final Map codeBaseCacheRef = new WeakHashMap(); /* - * Retuns the CodeBase for the given class. + * Returns the CodeBase for the given class. */ static URL getCodeBase(final Class clazz) { - URL url = (URL)codeBaseCacheRef.get(clazz); - if (url == null) { - url = (URL)AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - ProtectionDomain pd = clazz.getProtectionDomain(); - if (pd != null) { - CodeSource cs = pd.getCodeSource(); - if (cs != null) { - return cs.getLocation(); + synchronized (codeBaseCacheRef) { + URL url = (URL)codeBaseCacheRef.get(clazz); + if (url == null) { + url = (URL)AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ProtectionDomain pd = clazz.getProtectionDomain(); + if (pd != null) { + CodeSource cs = pd.getCodeSource(); + if (cs != null) { + return cs.getLocation(); + } } + return NULL_URL; } - return NULL_URL; - } - }); - codeBaseCacheRef.put(clazz, url); + }); + codeBaseCacheRef.put(clazz, url); + } + return (url == NULL_URL) ? null : url; } - return (url == NULL_URL) ? null : url; } private static void setupJurisdictionPolicies() throws Exception {
--- a/src/share/classes/sun/awt/image/ByteBandedRaster.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/awt/image/ByteBandedRaster.java Thu Jul 31 15:54:03 2014 +0400 @@ -755,10 +755,22 @@ + scanlineStride); } - for (int i = 0; i < data.length; i++) { - if (scanlineStride > data[i].length) { - throw new RasterFormatException("Incorrect scanline stride: " - + scanlineStride); + if ((long)minX - sampleModelTranslateX < 0 || + (long)minY - sampleModelTranslateY < 0) { + + throw new RasterFormatException("Incorrect origin/translate: (" + + minX + ", " + minY + ") / (" + + sampleModelTranslateX + ", " + sampleModelTranslateY + ")"); + } + + + if (height > 1 || minY - sampleModelTranslateY > 0) { + // buffer should contain at least one scanline + for (int i = 0; i < data.length; i++) { + if (scanlineStride > data[i].length) { + throw new RasterFormatException("Incorrect scanline stride: " + + scanlineStride); + } } }
--- a/src/share/classes/sun/awt/image/ByteComponentRaster.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/awt/image/ByteComponentRaster.java Thu Jul 31 15:54:03 2014 +0400 @@ -885,15 +885,31 @@ } } + if ((long)minX - sampleModelTranslateX < 0 || + (long)minY - sampleModelTranslateY < 0) { + + throw new RasterFormatException("Incorrect origin/translate: (" + + minX + ", " + minY + ") / (" + + sampleModelTranslateX + ", " + sampleModelTranslateY + ")"); + } + // we can be sure that width and height are greater than 0 if (scanlineStride < 0 || - scanlineStride > (Integer.MAX_VALUE / height) || - scanlineStride > data.length) + scanlineStride > (Integer.MAX_VALUE / height)) { // integer overflow throw new RasterFormatException("Incorrect scanline stride: " + scanlineStride); } + + if (height > 1 || minY - sampleModelTranslateY > 0) { + // buffer should contain at least one scanline + if (scanlineStride > data.length) { + throw new RasterFormatException("Incorrect scanline stride: " + + scanlineStride); + } + } + int lastScanOffset = (height - 1) * scanlineStride; if (pixelStride < 0 ||
--- a/src/share/classes/sun/awt/image/BytePackedRaster.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/awt/image/BytePackedRaster.java Thu Jul 31 15:54:03 2014 +0400 @@ -1386,13 +1386,28 @@ throw new RasterFormatException("Invalid raster dimension"); } + if ((long)minX - sampleModelTranslateX < 0 || + (long)minY - sampleModelTranslateY < 0) { + + throw new RasterFormatException("Incorrect origin/translate: (" + + minX + ", " + minY + ") / (" + + sampleModelTranslateX + ", " + sampleModelTranslateY + ")"); + } + if (scanlineStride < 0 || - scanlineStride > (Integer.MAX_VALUE / height) || - scanlineStride > data.length) + scanlineStride > (Integer.MAX_VALUE / height)) { throw new RasterFormatException("Invalid scanline stride"); } + if (height > 1 || minY - sampleModelTranslateY > 0) { + // buffer should contain at least one scanline + if (scanlineStride > data.length) { + throw new RasterFormatException("Incorrect scanline stride: " + + scanlineStride); + } + } + int lastbit = (dataBitOffset + (height-1) * scanlineStride * 8 + (width-1) * pixelBitStride
--- a/src/share/classes/sun/awt/image/IntegerComponentRaster.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/awt/image/IntegerComponentRaster.java Thu Jul 31 15:54:03 2014 +0400 @@ -654,15 +654,31 @@ ") must be >= 0"); } + if ((long)minX - sampleModelTranslateX < 0 || + (long)minY - sampleModelTranslateY < 0) { + + throw new RasterFormatException("Incorrect origin/translate: (" + + minX + ", " + minY + ") / (" + + sampleModelTranslateX + ", " + sampleModelTranslateY + ")"); + } + // we can be sure that width and height are greater than 0 if (scanlineStride < 0 || - scanlineStride > (Integer.MAX_VALUE / height) || - scanlineStride > data.length) + scanlineStride > (Integer.MAX_VALUE / height)) { // integer overflow throw new RasterFormatException("Incorrect scanline stride: " + scanlineStride); } + + if (height > 1 || minY - sampleModelTranslateY > 0) { + // buffer should contain at least one scanline + if (scanlineStride > data.length) { + throw new RasterFormatException("Incorrect scanline stride: " + + scanlineStride); + } + } + int lastScanOffset = (height - 1) * scanlineStride; if (pixelStride < 0 ||
--- a/src/share/classes/sun/awt/image/ShortBandedRaster.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/awt/image/ShortBandedRaster.java Thu Jul 31 15:54:03 2014 +0400 @@ -754,10 +754,21 @@ + scanlineStride); } - for (int i = 0; i < data.length; i++) { - if (scanlineStride > data[i].length) { - throw new RasterFormatException("Incorrect scanline stride: " - + scanlineStride); + if ((long)minX - sampleModelTranslateX < 0 || + (long)minY - sampleModelTranslateY < 0) { + + throw new RasterFormatException("Incorrect origin/translate: (" + + minX + ", " + minY + ") / (" + + sampleModelTranslateX + ", " + sampleModelTranslateY + ")"); + } + + if (height > 1 || minY - sampleModelTranslateY > 0) { + // buffer should contain at least one scanline + for (int i = 0; i < data.length; i++) { + if (scanlineStride > data[i].length) { + throw new RasterFormatException("Incorrect scanline stride: " + + scanlineStride); + } } }
--- a/src/share/classes/sun/awt/image/ShortComponentRaster.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/awt/image/ShortComponentRaster.java Thu Jul 31 15:54:03 2014 +0400 @@ -819,15 +819,31 @@ } } + if ((long)minX - sampleModelTranslateX < 0 || + (long)minY - sampleModelTranslateY < 0) { + + throw new RasterFormatException("Incorrect origin/translate: (" + + minX + ", " + minY + ") / (" + + sampleModelTranslateX + ", " + sampleModelTranslateY + ")"); + } + // we can be sure that width and height are greater than 0 if (scanlineStride < 0 || - scanlineStride > (Integer.MAX_VALUE / height) || - scanlineStride > data.length) + scanlineStride > (Integer.MAX_VALUE / height)) { // integer overflow throw new RasterFormatException("Incorrect scanline stride: " + scanlineStride); } + + if (height > 1 || minY - sampleModelTranslateY > 0) { + // buffer should contain at least one scanline + if (scanlineStride > data.length) { + throw new RasterFormatException("Incorrect scanline stride: " + + scanlineStride); + } + } + int lastScanOffset = (height - 1) * scanlineStride; if (pixelStride < 0 ||
--- a/src/share/classes/sun/misc/JavaLangAccess.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/misc/JavaLangAccess.java Thu Jul 31 15:54:03 2014 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -35,10 +35,10 @@ ConstantPool getConstantPool(Class klass); /** - * Set the AnnotationType instance corresponding to this class. + * Compare-And-Swap the AnnotationType instance corresponding to this class. * (This method only applies to annotation types.) */ - void setAnnotationType(Class klass, AnnotationType annotationType); + boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType); /** * Get the AnnotationType instance corresponding to this class. @@ -47,6 +47,12 @@ AnnotationType getAnnotationType(Class klass); /** + * Get the array of bytes that is the class-file representation + * of this Class' annotations. + */ + byte[] getRawClassAnnotations(Class<?> klass); + + /** * Returns the elements of an enum class or null if the * Class object does not represent an enum type; * the result is uncloned, cached, and shared by all callers.
--- a/src/share/classes/sun/reflect/annotation/AnnotationParser.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/reflect/annotation/AnnotationParser.java Thu Jul 31 15:54:03 2014 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -67,7 +67,35 @@ return Collections.emptyMap(); try { - return parseAnnotations2(rawAnnotations, constPool, container); + return parseAnnotations2(rawAnnotations, constPool, container, null); + } catch(BufferUnderflowException e) { + throw new AnnotationFormatError("Unexpected end of annotations."); + } catch(IllegalArgumentException e) { + // Type mismatch in constant pool + throw new AnnotationFormatError(e); + } + } + + /** + * Like {@link #parseAnnotations(byte[], sun.reflect.ConstantPool, Class)} + * with an additional parameter {@code selectAnnotationClasses} which selects the + * annotation types to parse (other than selected are quickly skipped).<p> + * This method is only used to parse select meta annotations in the construction + * phase of {@link AnnotationType} instances to prevent infinite recursion. + * + * @param selectAnnotationClasses an array of annotation types to select when parsing + */ + @SafeVarargs + static Map<Class<? extends Annotation>, Annotation> parseSelectAnnotations( + byte[] rawAnnotations, + ConstantPool constPool, + Class<?> container, + Class<? extends Annotation> ... selectAnnotationClasses) { + if (rawAnnotations == null) + return Collections.emptyMap(); + + try { + return parseAnnotations2(rawAnnotations, constPool, container, selectAnnotationClasses); } catch(BufferUnderflowException e) { throw new AnnotationFormatError("Unexpected end of annotations."); } catch(IllegalArgumentException e) { @@ -79,22 +107,23 @@ private static Map<Class<? extends Annotation>, Annotation> parseAnnotations2( byte[] rawAnnotations, ConstantPool constPool, - Class<?> container) { + Class<?> container, + Class<? extends Annotation>[] selectAnnotationClasses) { Map<Class<? extends Annotation>, Annotation> result = new LinkedHashMap<Class<? extends Annotation>, Annotation>(); ByteBuffer buf = ByteBuffer.wrap(rawAnnotations); int numAnnotations = buf.getShort() & 0xFFFF; for (int i = 0; i < numAnnotations; i++) { - Annotation a = parseAnnotation(buf, constPool, container, false); + Annotation a = parseAnnotation2(buf, constPool, container, false, selectAnnotationClasses); if (a != null) { Class<? extends Annotation> klass = a.annotationType(); - AnnotationType type = AnnotationType.getInstance(klass); - if (type.retention() == RetentionPolicy.RUNTIME) - if (result.put(klass, a) != null) + if (AnnotationType.getInstance(klass).retention() == RetentionPolicy.RUNTIME && + result.put(klass, a) != null) { throw new AnnotationFormatError( "Duplicate annotation for class: "+klass+": " + a); } } + } return result; } @@ -191,6 +220,15 @@ ConstantPool constPool, Class<?> container, boolean exceptionOnMissingAnnotationClass) { + return parseAnnotation2(buf, constPool, container, exceptionOnMissingAnnotationClass, null); + } + + @SuppressWarnings("unchecked") + private static Annotation parseAnnotation2(ByteBuffer buf, + ConstantPool constPool, + Class<?> container, + boolean exceptionOnMissingAnnotationClass, + Class<? extends Annotation>[] selectAnnotationClasses) { int typeIndex = buf.getShort() & 0xFFFF; Class<? extends Annotation> annotationClass = null; String sig = "[unknown]"; @@ -216,6 +254,10 @@ skipAnnotation(buf, false); return null; } + if (selectAnnotationClasses != null && !contains(selectAnnotationClasses, annotationClass)) { + skipAnnotation(buf, false); + return null; + } AnnotationType type = null; try { type = AnnotationType.getInstance(annotationClass); @@ -791,6 +833,17 @@ skipMemberValue(buf); } + /** + * Searches for given {@code element} in given {@code array} by identity. + * Returns {@code true} if found {@code false} if not. + */ + private static boolean contains(Object[] array, Object element) { + for (Object e : array) + if (e == element) + return true; + return false; + } + /* * This method converts the annotation map returned by the parseAnnotations() * method to an array. It is called by Field.getDeclaredAnnotations(),
--- a/src/share/classes/sun/reflect/annotation/AnnotationType.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/reflect/annotation/AnnotationType.java Thu Jul 31 15:54:03 2014 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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,6 +25,8 @@ package sun.reflect.annotation; +import sun.misc.JavaLangAccess; + import java.lang.annotation.*; import java.lang.reflect.*; import java.util.*; @@ -45,29 +47,28 @@ * types. This matches the return value that must be used for a * dynamic proxy, allowing for a simple isInstance test. */ - private final Map<String, Class<?>> memberTypes = new HashMap<String,Class<?>>(); + private final Map<String, Class<?>> memberTypes; /** * Member name -> default value mapping. */ - private final Map<String, Object> memberDefaults = - new HashMap<String, Object>(); + private final Map<String, Object> memberDefaults; /** - * Member name -> Method object mapping. This (and its assoicated + * Member name -> Method object mapping. This (and its associated * accessor) are used only to generate AnnotationTypeMismatchExceptions. */ - private final Map<String, Method> members = new HashMap<String, Method>(); + private final Map<String, Method> members; /** * The retention policy for this annotation type. */ - private RetentionPolicy retention = RetentionPolicy.RUNTIME;; + private final RetentionPolicy retention; /** * Whether this annotation type is inherited. */ - private boolean inherited = false; + private final boolean inherited; /** * Returns an AnnotationType instance for the specified annotation type. @@ -75,13 +76,20 @@ * @throw IllegalArgumentException if the specified class object for * does not represent a valid annotation type */ - public static synchronized AnnotationType getInstance( + public static AnnotationType getInstance( Class<? extends Annotation> annotationClass) { - AnnotationType result = sun.misc.SharedSecrets.getJavaLangAccess(). - getAnnotationType(annotationClass); - if (result == null) - result = new AnnotationType((Class<? extends Annotation>) annotationClass); + JavaLangAccess jla = sun.misc.SharedSecrets.getJavaLangAccess(); + AnnotationType result = jla.getAnnotationType(annotationClass); // volatile read + if (result == null) { + result = new AnnotationType(annotationClass); + // try to CAS the AnnotationType: null -> result + if (!jla.casAnnotationType(annotationClass, null, result)) { + // somebody was quicker -> read it's result + result = jla.getAnnotationType(annotationClass); + assert result != null; + } + } return result; } @@ -105,6 +113,9 @@ } }); + memberTypes = new HashMap<String,Class<?>>(methods.length+1, 1.0f); + memberDefaults = new HashMap<String, Object>(0); + members = new HashMap<String, Method>(methods.length+1, 1.0f); for (Method method : methods) { if (method.getParameterTypes().length != 0) @@ -117,20 +128,27 @@ Object defaultValue = method.getDefaultValue(); if (defaultValue != null) memberDefaults.put(name, defaultValue); - - members.put(name, method); } - sun.misc.SharedSecrets.getJavaLangAccess(). - setAnnotationType(annotationClass, this); - // Initialize retention, & inherited fields. Special treatment // of the corresponding annotation types breaks infinite recursion. if (annotationClass != Retention.class && annotationClass != Inherited.class) { - Retention ret = annotationClass.getAnnotation(Retention.class); + JavaLangAccess jla = sun.misc.SharedSecrets.getJavaLangAccess(); + Map<Class<? extends Annotation>, Annotation> metaAnnotations = + AnnotationParser.parseSelectAnnotations( + jla.getRawClassAnnotations(annotationClass), + jla.getConstantPool(annotationClass), + annotationClass, + Retention.class, Inherited.class + ); + Retention ret = (Retention) metaAnnotations.get(Retention.class); retention = (ret == null ? RetentionPolicy.CLASS : ret.value()); - inherited = annotationClass.isAnnotationPresent(Inherited.class); + inherited = metaAnnotations.containsKey(Inherited.class); + } + else { + retention = RetentionPolicy.RUNTIME; + inherited = false; } } @@ -205,11 +223,10 @@ * For debugging. */ public String toString() { - StringBuffer s = new StringBuffer("Annotation Type:" + "\n"); - s.append(" Member types: " + memberTypes + "\n"); - s.append(" Member defaults: " + memberDefaults + "\n"); - s.append(" Retention policy: " + retention + "\n"); - s.append(" Inherited: " + inherited); - return s.toString(); + return "Annotation Type:\n" + + " Member types: " + memberTypes + "\n" + + " Member defaults: " + memberDefaults + "\n" + + " Retention policy: " + retention + "\n" + + " Inherited: " + inherited; } }
--- a/src/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/security/internal/spec/TlsRsaPremasterSecretParameterSpec.java Thu Jul 31 15:54:03 2014 +0400 @@ -26,11 +26,11 @@ package sun.security.internal.spec; import java.security.spec.AlgorithmParameterSpec; +import java.security.AccessController; +import java.security.PrivilegedAction; /** - * Parameters for SSL/TLS RSA Premaster secret generation. - * This class is used by SSL/TLS client to initialize KeyGenerators of the - * type "TlsRsaPremasterSecret". + * Parameters for SSL/TLS RSA premaster secret. * * <p>Instances of this class are immutable. * @@ -43,90 +43,108 @@ public class TlsRsaPremasterSecretParameterSpec implements AlgorithmParameterSpec { - private final int majorVersion; - private final int minorVersion; - private final byte[] encodedSecret; + /* + * The TLS spec says that the version in the RSA premaster secret must + * be the maximum version supported by the client (i.e. the version it + * requested in its client hello version). However, we (and other + * implementations) used to send the active negotiated version. The + * system property below allows to toggle the behavior. + */ + private final static String PROP_NAME = + "com.sun.net.ssl.rsaPreMasterSecretFix"; - /** - * Constructs a new TlsRsaPremasterSecretParameterSpec. - * <P> - * The version numbers will be placed inside the premaster secret to - * detect version rollbacks attacks as described in the TLS specification. - * Note that they do not indicate the protocol version negotiated for - * the handshake. - * - * @param majorVersion the major number of the protocol version - * @param minorVersion the minor number of the protocol version - * - * @throws IllegalArgumentException if minorVersion or majorVersion are - * negative or larger than 255 + /* + * Default is "false" (old behavior) for compatibility reasons in + * SSLv3/TLSv1. Later protocols (TLSv1.1+) do not use this property. */ - public TlsRsaPremasterSecretParameterSpec(int majorVersion, - int minorVersion) { - this.majorVersion = - TlsMasterSecretParameterSpec.checkVersion(majorVersion); - this.minorVersion = - TlsMasterSecretParameterSpec.checkVersion(minorVersion); - this.encodedSecret = null; - } + private final static boolean rsaPreMasterSecretFix = + AccessController.doPrivileged(new PrivilegedAction<Boolean>() { + public Boolean run() { + String value = System.getProperty(PROP_NAME); + if (value != null && value.equalsIgnoreCase("true")) { + return Boolean.TRUE; + } + + return Boolean.FALSE; + } + }); + + private final int clientVersion; + private final int serverVersion; /** * Constructs a new TlsRsaPremasterSecretParameterSpec. - * <P> - * The version numbers will be placed inside the premaster secret to - * detect version rollbacks attacks as described in the TLS specification. - * Note that they do not indicate the protocol version negotiated for - * the handshake. - * <P> - * Usually, the encoded secret key is a random number that acts as - * dummy pre_master_secret to avoid vulnerabilities described by - * section 7.4.7.1, RFC 5246. * - * @param majorVersion the major number of the protocol version - * @param minorVersion the minor number of the protocol version - * @param encodedSecret the encoded secret key + * @param clientVersion the version of the TLS protocol by which the + * client wishes to communicate during this session + * @param serverVersion the negotiated version of the TLS protocol which + * contains the lower of that suggested by the client in the client + * hello and the highest supported by the server. * - * @throws IllegalArgumentException if minorVersion or majorVersion are - * negative or larger than 255, or encodedSecret is not exactly 48 bytes. + * @throws IllegalArgumentException if clientVersion or serverVersion are + * negative or larger than (2^16 - 1) */ - public TlsRsaPremasterSecretParameterSpec(int majorVersion, - int minorVersion, byte[] encodedSecret) { - this.majorVersion = - TlsMasterSecretParameterSpec.checkVersion(majorVersion); - this.minorVersion = - TlsMasterSecretParameterSpec.checkVersion(minorVersion); + public TlsRsaPremasterSecretParameterSpec( + int clientVersion, int serverVersion) { + + this.clientVersion = checkVersion(clientVersion); + this.serverVersion = checkVersion(serverVersion); + } - if (encodedSecret == null || encodedSecret.length != 48) { - throw new IllegalArgumentException( - "Encoded secret is not exactly 48 bytes"); - } - this.encodedSecret = encodedSecret.clone(); + /** + * Returns the version of the TLS protocol by which the client wishes to + * communicate during this session. + * + * @return the version of the TLS protocol in ClientHello message + */ + public int getClientVersion() { + return clientVersion; } /** - * Returns the major version. + * Returns the negotiated version of the TLS protocol which contains the + * lower of that suggested by the client in the client hello and the + * highest supported by the server. * - * @return the major version. + * @return the negotiated version of the TLS protocol in ServerHello message */ - public int getMajorVersion() { - return majorVersion; + public int getServerVersion() { + return serverVersion; } /** - * Returns the minor version. + * Returns the major version used in RSA premaster secret. * - * @return the minor version. + * @return the major version used in RSA premaster secret. */ - public int getMinorVersion() { - return minorVersion; + public int getMajorVersion() { + if (rsaPreMasterSecretFix || clientVersion >= 0x0302) { + // 0x0302: TLSv1.1 + return (clientVersion >>> 8) & 0xFF; + } + + return (serverVersion >>> 8) & 0xFF; } /** - * Returns the encoded secret. + * Returns the minor version used in RSA premaster secret. * - * @return the encoded secret, may be null if no encoded secret. + * @return the minor version used in RSA premaster secret. */ - public byte[] getEncodedSecret() { - return encodedSecret == null ? null : encodedSecret.clone(); + public int getMinorVersion() { + if (rsaPreMasterSecretFix || clientVersion >= 0x0302) { + // 0x0302: TLSv1.1 + return clientVersion & 0xFF; + } + + return serverVersion & 0xFF; + } + + private int checkVersion(int version) { + if ((version < 0) || (version > 0xFFFF)) { + throw new IllegalArgumentException( + "Version must be between 0 and 65,535"); + } + return version; } }
--- a/src/share/classes/sun/security/pkcs11/P11RSACipher.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/security/pkcs11/P11RSACipher.java Thu Jul 31 15:54:03 2014 +0400 @@ -37,6 +37,8 @@ import static sun.security.pkcs11.TemplateManager.*; import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; +import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; +import sun.security.util.KeyUtil; /** * RSA Cipher implementation class. We currently only support @@ -102,6 +104,12 @@ // maximum output size. this is the length of the key private int outputSize; + // cipher parameter for TLS RSA premaster secret + private AlgorithmParameterSpec spec = null; + + // the source of randomness + private SecureRandom random; + P11RSACipher(Token token, String algorithm, long mechanism) throws PKCS11Exception { super(); @@ -165,8 +173,12 @@ AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { if (params != null) { - throw new InvalidAlgorithmParameterException - ("Parameters not supported"); + if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) { + throw new InvalidAlgorithmParameterException( + "Parameters not supported"); + } + spec = params; + this.random = random; // for TLS RSA premaster secret } implInit(opmode, key); } @@ -176,8 +188,8 @@ SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { if (params != null) { - throw new InvalidAlgorithmParameterException - ("Parameters not supported"); + throw new InvalidAlgorithmParameterException( + "Parameters not supported"); } implInit(opmode, key); } @@ -452,21 +464,101 @@ protected Key engineUnwrap(byte[] wrappedKey, String algorithm, int type) throws InvalidKeyException, NoSuchAlgorithmException { - // XXX implement unwrap using C_Unwrap() for all keys - implInit(Cipher.DECRYPT_MODE, p11Key); - if (wrappedKey.length > maxInputSize) { - throw new InvalidKeyException("Key is too long for unwrapping"); + boolean isTlsRsaPremasterSecret = + algorithm.equals("TlsRsaPremasterSecret"); + Exception failover = null; + + SecureRandom secureRandom = random; + if (secureRandom == null && isTlsRsaPremasterSecret) { + secureRandom = new SecureRandom(); } - implUpdate(wrappedKey, 0, wrappedKey.length); - try { - byte[] encoded = doFinal(); + + // Should C_Unwrap be preferred for non-TLS RSA premaster secret? + if (token.supportsRawSecretKeyImport()) { + // XXX implement unwrap using C_Unwrap() for all keys + implInit(Cipher.DECRYPT_MODE, p11Key); + if (wrappedKey.length > maxInputSize) { + throw new InvalidKeyException("Key is too long for unwrapping"); + } + + byte[] encoded = null; + implUpdate(wrappedKey, 0, wrappedKey.length); + try { + encoded = doFinal(); + } catch (BadPaddingException e) { + if (isTlsRsaPremasterSecret) { + failover = e; + } else { + throw new InvalidKeyException("Unwrapping failed", e); + } + } catch (IllegalBlockSizeException e) { + // should not occur, handled with length check above + throw new InvalidKeyException("Unwrapping failed", e); + } + + if (isTlsRsaPremasterSecret) { + if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) { + throw new IllegalStateException( + "No TlsRsaPremasterSecretParameterSpec specified"); + } + + // polish the TLS premaster secret + TlsRsaPremasterSecretParameterSpec psps = + (TlsRsaPremasterSecretParameterSpec)spec; + encoded = KeyUtil.checkTlsPreMasterSecretKey( + psps.getClientVersion(), psps.getServerVersion(), + secureRandom, encoded, (failover != null)); + } + return ConstructKeys.constructKey(encoded, algorithm, type); - } catch (BadPaddingException e) { - // should not occur - throw new InvalidKeyException("Unwrapping failed", e); - } catch (IllegalBlockSizeException e) { - // should not occur, handled with length check above - throw new InvalidKeyException("Unwrapping failed", e); + } else { + Session s = null; + SecretKey secretKey = null; + try { + try { + s = token.getObjSession(); + long keyType = CKK_GENERIC_SECRET; + CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { + new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY), + new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType), + }; + attributes = token.getAttributes( + O_IMPORT, CKO_SECRET_KEY, keyType, attributes); + long keyID = token.p11.C_UnwrapKey(s.id(), + new CK_MECHANISM(mechanism), p11Key.keyID, + wrappedKey, attributes); + secretKey = P11Key.secretKey(s, keyID, + algorithm, 48 << 3, attributes); + } catch (PKCS11Exception e) { + if (isTlsRsaPremasterSecret) { + failover = e; + } else { + throw new InvalidKeyException("unwrap() failed", e); + } + } + + if (isTlsRsaPremasterSecret) { + byte[] replacer = new byte[48]; + if (failover == null) { + // Does smart compiler dispose this operation? + secureRandom.nextBytes(replacer); + } + + TlsRsaPremasterSecretParameterSpec psps = + (TlsRsaPremasterSecretParameterSpec)spec; + + // Please use the tricky failover and replacer byte array + // as the parameters so that smart compiler won't dispose + // the unused variable . + secretKey = polishPreMasterSecretKey(token, s, + failover, replacer, secretKey, + psps.getClientVersion(), psps.getServerVersion()); + } + + return secretKey; + } finally { + token.releaseSession(s); + } } } @@ -475,6 +567,34 @@ int n = P11KeyFactory.convertKey(token, key, algorithm).length(); return n; } + + private static SecretKey polishPreMasterSecretKey( + Token token, Session session, + Exception failover, byte[] replacer, SecretKey secretKey, + int clientVersion, int serverVersion) { + + if (failover != null) { + CK_VERSION version = new CK_VERSION( + (clientVersion >>> 8) & 0xFF, clientVersion & 0xFF); + try { + CK_ATTRIBUTE[] attributes = token.getAttributes( + O_GENERATE, CKO_SECRET_KEY, + CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]); + long keyID = token.p11.C_GenerateKey(session.id(), + // new CK_MECHANISM(CKM_TLS_PRE_MASTER_KEY_GEN, version), + new CK_MECHANISM(CKM_SSL3_PRE_MASTER_KEY_GEN, version), + attributes); + return P11Key.secretKey(session, + keyID, "TlsRsaPremasterSecret", 48 << 3, attributes); + } catch (PKCS11Exception e) { + throw new ProviderException( + "Could not generate premaster secret", e); + } + } + + return secretKey; + } + } final class ConstructKeys {
--- a/src/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java Thu Jul 31 15:54:03 2014 +0400 @@ -73,7 +73,7 @@ protected void engineInit(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { - if (params instanceof TlsRsaPremasterSecretParameterSpec == false) { + if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) { throw new InvalidAlgorithmParameterException(MSG); } this.spec = (TlsRsaPremasterSecretParameterSpec)params; @@ -83,38 +83,32 @@ throw new InvalidParameterException(MSG); } + // Only can be used in client side to generate TLS RSA premaster secret. protected SecretKey engineGenerateKey() { if (spec == null) { throw new IllegalStateException ("TlsRsaPremasterSecretGenerator must be initialized"); } - byte[] b = spec.getEncodedSecret(); - if (b == null) { - CK_VERSION version = new CK_VERSION( + CK_VERSION version = new CK_VERSION( spec.getMajorVersion(), spec.getMinorVersion()); - Session session = null; - try { - session = token.getObjSession(); - CK_ATTRIBUTE[] attributes = token.getAttributes( - O_GENERATE, CKO_SECRET_KEY, - CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]); - long keyID = token.p11.C_GenerateKey(session.id(), - new CK_MECHANISM(mechanism, version), attributes); - SecretKey key = P11Key.secretKey(session, - keyID, "TlsRsaPremasterSecret", 48 << 3, attributes); - return key; - } catch (PKCS11Exception e) { - throw new ProviderException( - "Could not generate premaster secret", e); - } finally { - token.releaseSession(session); - } + Session session = null; + try { + session = token.getObjSession(); + CK_ATTRIBUTE[] attributes = token.getAttributes( + O_GENERATE, CKO_SECRET_KEY, + CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]); + long keyID = token.p11.C_GenerateKey(session.id(), + new CK_MECHANISM(mechanism, version), attributes); + SecretKey key = P11Key.secretKey(session, + keyID, "TlsRsaPremasterSecret", 48 << 3, attributes); + return key; + } catch (PKCS11Exception e) { + throw new ProviderException( + "Could not generate premaster secret", e); + } finally { + token.releaseSession(session); } - - // Won't worry, the TlsRsaPremasterSecret will be soon converted to - // TlsMasterSecret. - return new SecretKeySpec(b, "TlsRsaPremasterSecret"); } }
--- a/src/share/classes/sun/security/pkcs11/Token.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/security/pkcs11/Token.java Thu Jul 31 15:54:03 2014 +0400 @@ -35,6 +35,7 @@ import sun.security.jca.JCAUtil; import sun.security.pkcs11.wrapper.*; +import static sun.security.pkcs11.TemplateManager.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; /** @@ -121,6 +122,9 @@ private final static CK_MECHANISM_INFO INVALID_MECH = new CK_MECHANISM_INFO(0, 0, 0); + // flag indicating whether the token supports raw secret key material import + private Boolean supportsRawSecretKeyImport; + Token(SunPKCS11 provider) throws PKCS11Exception { this.provider = provider; this.removable = provider.removable; @@ -159,6 +163,36 @@ return writeProtected; } + // return whether the token supports raw secret key material import + boolean supportsRawSecretKeyImport() { + if (supportsRawSecretKeyImport == null) { + SecureRandom random = JCAUtil.getSecureRandom(); + byte[] encoded = new byte[48]; + random.nextBytes(encoded); + + CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[3]; + attributes[0] = new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY); + attributes[1] = new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_GENERIC_SECRET); + attributes[2] = new CK_ATTRIBUTE(CKA_VALUE, encoded); + + Session session = null; + try { + attributes = getAttributes(O_IMPORT, + CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes); + session = getObjSession(); + long keyID = p11.C_CreateObject(session.id(), attributes); + + supportsRawSecretKeyImport = Boolean.TRUE; + } catch (PKCS11Exception e) { + supportsRawSecretKeyImport = Boolean.FALSE; + } finally { + releaseSession(session); + } + } + + return supportsRawSecretKeyImport; + } + // return whether we are logged in // uses cached result if current. session is optional and may be null boolean isLoggedIn(Session session) throws PKCS11Exception {
--- a/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java Thu Jul 31 15:54:03 2014 +0400 @@ -50,23 +50,6 @@ */ final class RSAClientKeyExchange extends HandshakeMessage { - /** - * The TLS spec says that the version in the RSA premaster secret must - * be the maximum version supported by the client (i.e. the version it - * requested in its client hello version). However, we (and other - * implementations) used to send the active negotiated version. The - * system property below allows to toggle the behavior. - */ - private final static String PROP_NAME = - "com.sun.net.ssl.rsaPreMasterSecretFix"; - - /* - * Default is "false" (old behavior) for compatibility reasons in - * SSLv3/TLSv1. Later protocols (TLSv1.1+) do not use this property. - */ - private final static boolean rsaPreMasterSecretFix = - Debug.getBooleanProperty(PROP_NAME, false); - /* * The following field values were encrypted with the server's public * key (or temp key from server key exchange msg) and are presented @@ -90,22 +73,12 @@ } this.protocolVersion = protocolVersion; - int major, minor; - - if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) { - major = maxVersion.major; - minor = maxVersion.minor; - } else { - major = protocolVersion.major; - minor = protocolVersion.minor; - } - try { String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ? "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); KeyGenerator kg = JsseJce.getKeyGenerator(s); - kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor), - generator); + kg.init(new TlsRsaPremasterSecretParameterSpec( + maxVersion.v, protocolVersion.v), generator); preMaster = kg.generateKey(); Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); @@ -140,18 +113,17 @@ } } - Exception failover = null; - byte[] encoded = null; try { Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); // Cannot generate key here, please don't use Cipher.UNWRAP_MODE! - cipher.init(Cipher.DECRYPT_MODE, privateKey); - encoded = cipher.doFinal(encrypted); - } catch (BadPaddingException bpe) { - failover = bpe; - encoded = null; - } catch (IllegalBlockSizeException ibse) { - // the message it too big to process with RSA + cipher.init(Cipher.UNWRAP_MODE, privateKey, + new TlsRsaPremasterSecretParameterSpec( + maxVersion.v, currentVersion.v), + generator); + preMaster = (SecretKey)cipher.unwrap(encrypted, + "TlsRsaPremasterSecret", Cipher.SECRET_KEY); + } catch (InvalidKeyException ibk) { + // the message is too big to process with RSA throw new SSLProtocolException( "Unable to process PreMasterSecret, may be too big"); } catch (Exception e) { @@ -162,124 +134,6 @@ } throw new RuntimeException("Could not generate dummy secret", e); } - - // polish the premaster secret - preMaster = polishPreMasterSecretKey( - currentVersion, maxVersion, generator, encoded, failover); - } - - /** - * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246, - * treating incorrectly formatted message blocks and/or mismatched - * version numbers in a manner indistinguishable from correctly - * formatted RSA blocks. - * - * RFC 5246 describes the approach as : - * - * 1. Generate a string R of 48 random bytes - * - * 2. Decrypt the message to recover the plaintext M - * - * 3. If the PKCS#1 padding is not correct, or the length of message - * M is not exactly 48 bytes: - * pre_master_secret = R - * else If ClientHello.client_version <= TLS 1.0, and version - * number check is explicitly disabled: - * premaster secret = M - * else If M[0..1] != ClientHello.client_version: - * premaster secret = R - * else: - * premaster secret = M - * - * Note that #2 has completed before the call of this method. - */ - private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion, - ProtocolVersion clientHelloVersion, SecureRandom generator, - byte[] encoded, Exception failoverException) { - - this.protocolVersion = clientHelloVersion; - if (generator == null) { - generator = new SecureRandom(); - } - byte[] random = new byte[48]; - generator.nextBytes(random); - - if (failoverException == null && encoded != null) { - // check the length - if (encoded.length != 48) { - if (debug != null && Debug.isOn("handshake")) { - System.out.println( - "incorrect length of premaster secret: " + - encoded.length); - } - - return generatePreMasterSecret( - clientHelloVersion, random, generator); - } - - if (clientHelloVersion.major != encoded[0] || - clientHelloVersion.minor != encoded[1]) { - - if (clientHelloVersion.v <= ProtocolVersion.TLS10.v && - currentVersion.major == encoded[0] && - currentVersion.minor == encoded[1]) { - /* - * For compatibility, we maintain the behavior that the - * version in pre_master_secret can be the negotiated - * version for TLS v1.0 and SSL v3.0. - */ - this.protocolVersion = currentVersion; - } else { - if (debug != null && Debug.isOn("handshake")) { - System.out.println("Mismatching Protocol Versions, " + - "ClientHello.client_version is " + - clientHelloVersion + - ", while PreMasterSecret.client_version is " + - ProtocolVersion.valueOf(encoded[0], encoded[1])); - } - - encoded = random; - } - } - - return generatePreMasterSecret( - clientHelloVersion, encoded, generator); - } - - if (debug != null && Debug.isOn("handshake") && - failoverException != null) { - System.out.println("Error decrypting premaster secret:"); - failoverException.printStackTrace(System.out); - } - - return generatePreMasterSecret(clientHelloVersion, random, generator); - } - - // generate a premaster secret with the specified version number - private static SecretKey generatePreMasterSecret( - ProtocolVersion version, byte[] encodedSecret, - SecureRandom generator) { - - if (debug != null && Debug.isOn("handshake")) { - System.out.println("Generating a random fake premaster secret"); - } - - try { - String s = ((version.v >= ProtocolVersion.TLS12.v) ? - "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); - KeyGenerator kg = JsseJce.getKeyGenerator(s); - kg.init(new TlsRsaPremasterSecretParameterSpec( - version.major, version.minor, encodedSecret), generator); - return kg.generateKey(); - } catch (InvalidAlgorithmParameterException | - NoSuchAlgorithmException iae) { - // unlikely to happen, otherwise, must be a provider exception - if (debug != null && Debug.isOn("handshake")) { - System.out.println("RSA premaster secret generation error:"); - iae.printStackTrace(System.out); - } - throw new RuntimeException("Could not generate dummy secret", iae); - } } @Override
--- a/src/share/classes/sun/security/util/KeyUtil.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/share/classes/sun/security/util/KeyUtil.java Thu Jul 31 15:54:03 2014 +0400 @@ -32,6 +32,7 @@ import java.security.interfaces.ECKey; import java.security.interfaces.RSAKey; import java.security.interfaces.DSAKey; +import java.security.SecureRandom; import java.security.spec.KeySpec; import javax.crypto.SecretKey; import javax.crypto.interfaces.DHKey; @@ -157,6 +158,79 @@ } /** + * Check the format of TLS PreMasterSecret. + * <P> + * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246, + * treating incorrectly formatted message blocks and/or mismatched + * version numbers in a manner indistinguishable from correctly + * formatted RSA blocks. + * + * RFC 5246 describes the approach as : + * + * 1. Generate a string R of 48 random bytes + * + * 2. Decrypt the message to recover the plaintext M + * + * 3. If the PKCS#1 padding is not correct, or the length of message + * M is not exactly 48 bytes: + * pre_master_secret = R + * else If ClientHello.client_version <= TLS 1.0, and version + * number check is explicitly disabled: + * premaster secret = M + * else If M[0..1] != ClientHello.client_version: + * premaster secret = R + * else: + * premaster secret = M + * + * Note that #2 should have completed before the call to this method. + * + * @param clientVersion the version of the TLS protocol by which the + * client wishes to communicate during this session + * @param serverVersion the negotiated version of the TLS protocol which + * contains the lower of that suggested by the client in the client + * hello and the highest supported by the server. + * @param encoded the encoded key in its "RAW" encoding format + * @param isFailover whether or not the previous decryption of the + * encrypted PreMasterSecret message run into problem + * @return the polished PreMasterSecret key in its "RAW" encoding format + */ + public static byte[] checkTlsPreMasterSecretKey( + int clientVersion, int serverVersion, SecureRandom random, + byte[] encoded, boolean isFailOver) { + + if (random == null) { + random = new SecureRandom(); + } + byte[] replacer = new byte[48]; + random.nextBytes(replacer); + + if (!isFailOver && (encoded != null)) { + // check the length + if (encoded.length != 48) { + // private, don't need to clone the byte array. + return replacer; + } + + int encodedVersion = + ((encoded[0] & 0xFF) << 8) | (encoded[1] & 0xFF); + if (clientVersion != encodedVersion) { + if (clientVersion > 0x0301 || // 0x0301: TLSv1 + serverVersion != encodedVersion) { + encoded = replacer; + } // Otherwise, For compatibility, we maintain the behavior + // that the version in pre_master_secret can be the + // negotiated version for TLS v1.0 and SSL v3.0. + } + + // private, don't need to clone the byte array. + return encoded; + } + + // private, don't need to clone the byte array. + return replacer; + } + + /** * Returns whether the Diffie-Hellman public key is valid or not. * * Per RFC 2631 and NIST SP800-56A, the following algorithm is used to
--- a/src/windows/classes/sun/security/mscapi/RSACipher.java Tue Jul 29 17:50:39 2014 +0100 +++ b/src/windows/classes/sun/security/mscapi/RSACipher.java Thu Jul 31 15:54:03 2014 +0400 @@ -35,6 +35,8 @@ import javax.crypto.spec.*; import sun.security.rsa.RSAKeyFactory; +import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; +import sun.security.util.KeyUtil; /** * RSA cipher implementation using the Microsoft Crypto API. @@ -92,9 +94,16 @@ // the public key, if we were initialized using a public key private sun.security.mscapi.Key publicKey; + // the private key, if we were initialized using a private key private sun.security.mscapi.Key privateKey; + // cipher parameter for TLS RSA premaster secret + private AlgorithmParameterSpec spec = null; + + // the source of randomness + private SecureRandom random; + public RSACipher() { paddingType = PAD_PKCS1; } @@ -155,8 +164,12 @@ throws InvalidKeyException, InvalidAlgorithmParameterException { if (params != null) { - throw new InvalidAlgorithmParameterException - ("Parameters not supported"); + if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) { + throw new InvalidAlgorithmParameterException( + "Parameters not supported"); + } + spec = params; + this.random = random; // for TLS RSA premaster secret } init(opmode, key); } @@ -356,39 +369,47 @@ } // see JCE spec - protected java.security.Key engineUnwrap(byte[] wrappedKey, String algorithm, + protected java.security.Key engineUnwrap(byte[] wrappedKey, + String algorithm, int type) throws InvalidKeyException, NoSuchAlgorithmException { if (wrappedKey.length > buffer.length) { throw new InvalidKeyException("Key is too long for unwrapping"); } - update(wrappedKey, 0, wrappedKey.length); - try { - byte[] encoding = doFinal(); - - switch (type) { - case Cipher.PUBLIC_KEY: - return constructPublicKey(encoding, algorithm); - - case Cipher.PRIVATE_KEY: - return constructPrivateKey(encoding, algorithm); + boolean isTlsRsaPremasterSecret = + algorithm.equals("TlsRsaPremasterSecret"); + Exception failover = null; + byte[] encoded = null; - case Cipher.SECRET_KEY: - return constructSecretKey(encoding, algorithm); - - default: - throw new InvalidKeyException("Unknown key type " + type); + update(wrappedKey, 0, wrappedKey.length); + try { + encoded = doFinal(); + } catch (BadPaddingException e) { + if (isTlsRsaPremasterSecret) { + failover = e; + } else { + throw new InvalidKeyException("Unwrapping failed", e); } - - } catch (BadPaddingException e) { - // should not occur - throw new InvalidKeyException("Unwrapping failed", e); - } catch (IllegalBlockSizeException e) { // should not occur, handled with length check above throw new InvalidKeyException("Unwrapping failed", e); } + + if (isTlsRsaPremasterSecret) { + if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) { + throw new IllegalStateException( + "No TlsRsaPremasterSecretParameterSpec specified"); + } + + // polish the TLS premaster secret + encoded = KeyUtil.checkTlsPreMasterSecretKey( + ((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(), + ((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(), + random, encoded, (failover != null)); + } + + return constructKey(encoded, algorithm, type); } // see JCE spec @@ -452,6 +473,22 @@ return new SecretKeySpec(encodedKey, encodedKeyAlgorithm); } + private static Key constructKey(byte[] encodedKey, + String encodedKeyAlgorithm, + int keyType) throws InvalidKeyException, NoSuchAlgorithmException { + + switch (keyType) { + case Cipher.PUBLIC_KEY: + return constructPublicKey(encodedKey, encodedKeyAlgorithm); + case Cipher.PRIVATE_KEY: + return constructPrivateKey(encodedKey, encodedKeyAlgorithm); + case Cipher.SECRET_KEY: + return constructSecretKey(encodedKey, encodedKeyAlgorithm); + default: + throw new InvalidKeyException("Unknown key type " + keyType); + } + } + /* * Encrypt/decrypt a data buffer using Microsoft Crypto API with HCRYPTKEY. * It expects and returns ciphertext data in big-endian form.
--- a/test/com/sun/crypto/provider/TLS/TestPremaster.java Tue Jul 29 17:50:39 2014 +0100 +++ b/test/com/sun/crypto/provider/TLS/TestPremaster.java Thu Jul 31 15:54:03 2014 +0400 @@ -33,6 +33,7 @@ import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; +import java.util.Formatter; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; @@ -52,27 +53,51 @@ System.out.println("OK: " + e); } - test(kg, 3, 0); - test(kg, 3, 1); - test(kg, 3, 2); - test(kg, 4, 0); + int[] protocolVersions = {0x0300, 0x0301, 0x0302, 0x0400}; + for (int clientVersion : protocolVersions) { + for (int serverVersion : protocolVersions) { + test(kg, clientVersion, serverVersion); + if (serverVersion >= clientVersion) { + break; + } + } + } System.out.println("Done."); } - private static void test(KeyGenerator kg, int major, int minor) - throws Exception { + private static void test(KeyGenerator kg, + int clientVersion, int serverVersion) throws Exception { - kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor)); + System.out.printf( + "Testing RSA pre-master secret key generation between " + + "client (0x%04X) and server(0x%04X)%n", + clientVersion, serverVersion); + kg.init(new TlsRsaPremasterSecretParameterSpec( + clientVersion, serverVersion)); + SecretKey key = kg.generateKey(); byte[] encoded = key.getEncoded(); - if (encoded.length != 48) { - throw new Exception("length: " + encoded.length); - } - if ((encoded[0] != major) || (encoded[1] != minor)) { - throw new Exception("version mismatch: " + encoded[0] + - "." + encoded[1]); - } - System.out.println("OK: " + major + "." + minor); + if (encoded != null) { // raw key material may be not extractable + if (encoded.length != 48) { + throw new Exception("length: " + encoded.length); + } + int v = versionOf(encoded[0], encoded[1]); + if (clientVersion != v) { + if (serverVersion != v || clientVersion >= 0x0302) { + throw new Exception(String.format( + "version mismatch: (0x%04X) rather than (0x%04X) " + + "is used in pre-master secret", v, clientVersion)); + } + System.out.printf("Use compatible version (0x%04X)%n", v); + } + System.out.println("Passed, version matches!"); + } else { + System.out.println("Raw key material is not extractable"); + } + } + + private static int versionOf(int major, int minor) { + return ((major & 0xFF) << 8) | (minor & 0xFF); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Mouse/EnterExitEvents/DragWindowTest.java Thu Jul 31 15:54:03 2014 +0400 @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2005, 2006, 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. + * + * 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. + */ + +/* + * @test + * @bug 7154048 + * @summary Window created under a mouse does not receive mouse enter event. + * Mouse Entered/Exited events are wrongly generated during dragging the window + * from one component to another + * @library ../../regtesthelpers + * @build Util + * @author alexandr.scherbatiy area=awt.event + * @run main DragWindowTest + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +import java.util.concurrent.*; +import sun.awt.SunToolkit; + +import test.java.awt.regtesthelpers.Util; + +public class DragWindowTest { + + private static volatile int dragWindowMouseEnteredCount = 0; + private static volatile int dragWindowMouseReleasedCount = 0; + private static volatile int buttonMouseEnteredCount = 0; + private static volatile int labelMouseReleasedCount = 0; + private static MyDragWindow dragWindow; + private static JLabel label; + private static JButton button; + + public static void main(String[] args) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + Point pointToClick = Util.invokeOnEDT(new Callable<Point>() { + + @Override + public Point call() throws Exception { + return getCenterPoint(label); + } + }); + + + robot.mouseMove(pointToClick.x, pointToClick.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + toolkit.realSync(); + + if (dragWindowMouseEnteredCount != 1) { + throw new RuntimeException("No MouseEntered event on Drag Window!"); + } + + Point pointToDrag = Util.invokeOnEDT(new Callable<Point>() { + + @Override + public Point call() throws Exception { + button.addMouseListener(new ButtonMouseListener()); + return getCenterPoint(button); + } + }); + + robot.mouseMove(pointToDrag.x, pointToDrag.y); + toolkit.realSync(); + + if (buttonMouseEnteredCount != 0) { + throw new RuntimeException("Extra MouseEntered event on button!"); + } + + robot.mouseRelease(InputEvent.BUTTON1_MASK); + toolkit.realSync(); + + if (labelMouseReleasedCount != 1) { + throw new RuntimeException("No MouseReleased event on label!"); + } + + } + + private static Point getCenterPoint(Component comp) { + Point p = comp.getLocationOnScreen(); + Rectangle rect = comp.getBounds(); + return new Point(p.x + rect.width / 2, p.y + rect.height / 2); + } + + private static void createAndShowGUI() { + + JFrame frame = new JFrame("Main Frame"); + frame.setSize(300, 200); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + label = new JLabel("Label"); + + LabelMouseListener listener = new LabelMouseListener(frame); + label.addMouseListener(listener); + label.addMouseMotionListener(listener); + + button = new JButton("Button"); + Panel panel = new Panel(new BorderLayout()); + + panel.add(label, BorderLayout.NORTH); + panel.add(button, BorderLayout.CENTER); + + frame.getContentPane().add(panel); + frame.setVisible(true); + + } + + private static Point getAbsoluteLocation(MouseEvent e) { + return new Point(e.getXOnScreen(), e.getYOnScreen()); + } + + static class MyDragWindow extends Window { + + static int d = 30; + + public MyDragWindow(Window parent, Point location) { + super(parent); + setSize(150, 150); + setVisible(true); + JPanel panel = new JPanel(); + add(panel); + setLocation(location.x - d, location.y - d); + addMouseListener(new DragWindowMouseListener()); + } + + void dragTo(Point point) { + setLocation(point.x - d, point.y - d); + } + } + + static class LabelMouseListener extends MouseAdapter { + + Point origin; + Window parent; + + public LabelMouseListener(Window parent) { + this.parent = parent; + } + + @Override + public void mousePressed(MouseEvent e) { + if (dragWindow == null) { + dragWindow = new MyDragWindow(parent, getAbsoluteLocation(e)); + } else { + dragWindow.setVisible(true); + dragWindow.dragTo(getAbsoluteLocation(e)); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + labelMouseReleasedCount++; + if (dragWindow != null) { + dragWindow.setVisible(false); + } + } + + public void mouseDragged(MouseEvent e) { + if (dragWindow != null) { + dragWindow.dragTo(getAbsoluteLocation(e)); + } + } + } + + static class DragWindowMouseListener extends MouseAdapter { + + @Override + public void mouseEntered(MouseEvent e) { + dragWindowMouseEnteredCount++; + } + + @Override + public void mouseReleased(MouseEvent e) { + dragWindowMouseReleasedCount++; + } + } + + static class ButtonMouseListener extends MouseAdapter { + + @Override + public void mouseEntered(MouseEvent e) { + buttonMouseEnteredCount++; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithOverlay.java Thu Jul 31 15:54:03 2014 +0400 @@ -0,0 +1,108 @@ +/* + * 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. + * + * 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. + */ + +import test.java.awt.regtesthelpers.Util; + +import javax.swing.*; +import java.awt.*; +import java.util.concurrent.atomic.AtomicReference; + +/** + * @test + * @bug 8012026 + * @summary Component.getMousePosition() does not work in an applet on MacOS + * @author Petr Pchelko + * @library ../../regtesthelpers + * @build Util + * @compile GetMousePositionWithOverlay.java + * @run main/othervm GetMousePositionWithOverlay + */ + +public class GetMousePositionWithOverlay { + + static Frame backFrame; + static Frame frontFrame; + + public static void main(String[] args) throws Throwable { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + constructTestUI(); + } + }); + Util.waitForIdle(null); + + Robot r = new Robot(); + Util.pointOnComp(frontFrame, r); + Util.waitForIdle(null); + + Point pos = getMousePosition(backFrame); + if (pos != null) { + throw new RuntimeException("Test failed. Mouse position should be null but was" + pos); + } + + pos = getMousePosition(frontFrame); + if (pos == null) { + throw new RuntimeException("Test failed. Mouse position should not be null"); + } + + r.mouseMove(189, 189); + Util.waitForIdle(null); + + pos = getMousePosition(backFrame); + if (pos == null) { + throw new RuntimeException("Test failed. Mouse position should not be null"); + } + } finally { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + backFrame.dispose(); + frontFrame.dispose(); + } + }); + } + } + + private static Point getMousePosition(final Component component) throws Exception { + final AtomicReference<Point> pos = new AtomicReference<Point>(); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + pos.set(component.getMousePosition()); + } + }); + return pos.get(); + } + + private static void constructTestUI() { + backFrame = new Frame(); + backFrame.setBounds(100, 100, 100, 100); + backFrame.setVisible(true); + + frontFrame = new Frame(); + frontFrame.setBounds(120, 120, 60, 60); + frontFrame.setVisible(true); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java Thu Jul 31 15:54:03 2014 +0400 @@ -0,0 +1,111 @@ +/* + * 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. + * + * 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. + */ + +import test.java.awt.regtesthelpers.Util; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; + +/** + * @test + * @bug 8012026 + * @summary Component.getMousePosition() does not work in an applet on MacOS + * @author Petr Pchelko + * @library ../../regtesthelpers + * @build Util + * @compile GetMousePositionWithPopup.java + * @run main/othervm GetMousePositionWithPopup + */ + +public class GetMousePositionWithPopup { + + private static Frame frame1; + private static Frame frame2; + + public static void main(String[] args) throws Exception { + try { + Robot r = Util.createRobot(); + r.mouseMove(0, 0); + Util.waitForIdle(null); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + constructTestUI(); + } + }); + + Util.waitForIdle(null); + r.mouseMove(149, 149); + Util.waitForIdle(null); + r.mouseMove(150, 150); + Util.waitForIdle(null); + + } finally { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + frame1.dispose(); + frame2.dispose(); + } + }); + } + } + + private static void constructTestUI() { + frame1 = new Frame(); + frame1.setBounds(100, 100, 100, 100); + frame1.addMouseMotionListener(new MouseMotionAdapter() { + + private boolean shown = false; + + @Override + public void mouseMoved(MouseEvent e) { + if (shown) { + return; + } + + shown = true; + + frame2 = new Frame(); + frame2.setBounds(120, 120, 120, 120); + frame2.setVisible(true); + + Point positionInFrame2 = frame2.getMousePosition(); + if (positionInFrame2.x != 30 || positionInFrame2.y != 30) { + throw new RuntimeException("Wrong position reported. Should be [30, 30] but was [" + + positionInFrame2.x + ", " + positionInFrame2.y + "]"); + } + + Point positionInFrame1 = frame1.getMousePosition(); + if (positionInFrame1 != null) { + throw new RuntimeException("Wrong position reported. Should be null"); + } + + } + }); + frame1.setVisible(true); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/unresolvableObjectStreamClass/UnresolvableObjectStreamClass.java Thu Jul 31 15:54:03 2014 +0400 @@ -0,0 +1,68 @@ +/* + * 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. + * + * 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. + */ + +/* @test + * @bug 8039396 + * @run main UnresolvableObjectStreamClass serialize + * @clean MySerializable + * @run main UnresolvableObjectStreamClass deserialize + * + * @summary NPE when writing a class descriptor object to a custom + * ObjectOutputStream + */ + +import java.io.*; + +public class UnresolvableObjectStreamClass { + public static void main(String[] args) throws Throwable { + if (args.length > 0 && args[0].equals("serialize")) { + try (FileOutputStream fos = new FileOutputStream("temp1.ser"); + ObjectOutputStream oos = new ObjectOutputStream(fos)) { + ObjectStreamClass osc = + ObjectStreamClass.lookup(MySerializable.class); + oos.writeObject(osc); + } + } else if (args.length > 0 && args[0].equals("deserialize")) { + try (FileInputStream fis = new FileInputStream("temp1.ser"); + ObjectInputStream ois = new ObjectInputStream(fis); + FileOutputStream fos = new FileOutputStream("temp2.ser"); + ObjectOutputStream oos = new ObjectOutputStream(fos) { + /*must be subclassed*/}) { + ObjectStreamClass osc = (ObjectStreamClass)ois.readObject(); + // serialize it again + try { + oos.writeObject(osc); + } catch (NullPointerException e) { + throw new RuntimeException("Failed to write" + + " unresolvable ObjectStreamClass", e); + } + } + } else { + throw new RuntimeException("The command line option must be" + + " one of: serialize or deserialize"); + } + } +} + +class MySerializable implements Serializable { +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/annotation/AnnotationType/AnnotationTypeDeadlockTest.java Thu Jul 31 15:54:03 2014 +0400 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 7122142 + * @summary Test deadlock situation when recursive annotations are parsed + */ + +import java.lang.annotation.Retention; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +public class AnnotationTypeDeadlockTest { + + @Retention(RUNTIME) + @AnnB + public @interface AnnA { + } + + @Retention(RUNTIME) + @AnnA + public @interface AnnB { + } + + static class Task extends Thread { + final CountDownLatch prepareLatch; + final AtomicInteger goLatch; + final Class<?> clazz; + + Task(CountDownLatch prepareLatch, AtomicInteger goLatch, Class<?> clazz) { + super(clazz.getSimpleName()); + setDaemon(true); // in case it deadlocks + this.prepareLatch = prepareLatch; + this.goLatch = goLatch; + this.clazz = clazz; + } + + @Override + public void run() { + prepareLatch.countDown(); // notify we are prepared + while (goLatch.get() > 0); // spin-wait before go + clazz.getDeclaredAnnotations(); + } + } + + public static void main(String[] args) throws Exception { + CountDownLatch prepareLatch = new CountDownLatch(2); + AtomicInteger goLatch = new AtomicInteger(1); + Task taskA = new Task(prepareLatch, goLatch, AnnA.class); + Task taskB = new Task(prepareLatch, goLatch, AnnB.class); + taskA.start(); + taskB.start(); + // wait until both threads start-up + prepareLatch.await(); + // let them go + goLatch.set(0); + // obtain ThreadMXBean + ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); + // wait for threads to finish or dead-lock + while (taskA.isAlive() || taskB.isAlive()) { + // attempt to join threads + taskA.join(500L); + taskB.join(500L); + // detect dead-lock + long[] deadlockedIds = threadBean.findMonitorDeadlockedThreads(); + if (deadlockedIds != null && deadlockedIds.length > 0) { + StringBuilder sb = new StringBuilder("deadlock detected:\n\n"); + for (ThreadInfo ti : threadBean.getThreadInfo(deadlockedIds, Integer.MAX_VALUE)) { + sb.append(ti); + } + throw new IllegalStateException(sb.toString()); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/annotation/AnnotationType/AnnotationTypeRuntimeAssumptionTest.java Thu Jul 31 15:54:03 2014 +0400 @@ -0,0 +1,187 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 7122142 + * @summary Test consistent parsing of ex-RUNTIME annotations that + * were changed and separately compiled to have CLASS retention + */ + +import sun.misc.IOUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import static java.lang.annotation.RetentionPolicy.CLASS; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * This test simulates a situation where there are two mutually recursive + * {@link RetentionPolicy#RUNTIME RUNTIME} annotations {@link AnnA_v1 AnnA_v1} + * and {@link AnnB AnnB} and then the first is changed to have + * {@link RetentionPolicy#CLASS CLASS} retention and separately compiled. + * When {@link AnnA_v1 AnnA_v1} annotation is looked-up on {@link AnnB AnnB} + * it still appears to have {@link RetentionPolicy#RUNTIME RUNTIME} retention. + */ +public class AnnotationTypeRuntimeAssumptionTest { + + @Retention(RUNTIME) + @AnnB + public @interface AnnA_v1 { + } + + // An alternative version of AnnA_v1 with CLASS retention instead. + // Used to simulate separate compilation (see AltClassLoader below). + @Retention(CLASS) + @AnnB + public @interface AnnA_v2 { + } + + @Retention(RUNTIME) + @AnnA_v1 + public @interface AnnB { + } + + @AnnA_v1 + public static class TestTask implements Runnable { + @Override + public void run() { + AnnA_v1 ann1 = getDeclaredAnnotation(TestTask.class, AnnA_v1.class); + if (ann1 != null) { + throw new IllegalStateException( + "@" + ann1.annotationType().getSimpleName() + + " found on: " + TestTask.class.getName() + + " should not be visible at runtime"); + } + AnnA_v1 ann2 = getDeclaredAnnotation(AnnB.class, AnnA_v1.class); + if (ann2 != null) { + throw new IllegalStateException( + "@" + ann2.annotationType().getSimpleName() + + " found on: " + AnnB.class.getName() + + " should not be visible at runtime"); + } + } + + private static <A extends Annotation> A getDeclaredAnnotation(Class<?> clazz, Class<A> annotationClass) { + for (Annotation ann : clazz.getDeclaredAnnotations()) { + if (ann.annotationType() == annotationClass) { + return annotationClass.cast(ann); + } + } + return null; + } + } + + public static void main(String[] args) throws Exception { + ClassLoader altLoader = new AltClassLoader( + AnnotationTypeRuntimeAssumptionTest.class.getClassLoader()); + + Runnable altTask = (Runnable) Class.forName( + TestTask.class.getName(), + true, + altLoader).newInstance(); + + altTask.run(); + } + + /** + * A ClassLoader implementation that loads alternative implementations of + * classes. If class name ends with "_v1" it locates instead a class with + * name ending with "_v2" and loads that class instead. + */ + static class AltClassLoader extends ClassLoader { + AltClassLoader(ClassLoader parent) { + super(parent); + } + + @Override + protected Class<?> loadClass(String name, boolean resolve) + throws ClassNotFoundException { + if (name.indexOf('.') < 0) { // root package is our class + synchronized (getClassLoadingLock(name)) { + // First, check if the class has already been loaded + Class<?> c = findLoadedClass(name); + if (c == null) { + c = findClass(name); + } + if (resolve) { + resolveClass(c); + } + return c; + } + } + else { // not our class + return super.loadClass(name, resolve); + } + } + + @Override + protected Class<?> findClass(String name) + throws ClassNotFoundException { + // special class name -> replace it with alternative name + if (name.endsWith("_v1")) { + String altName = name.substring(0, name.length() - 3) + "_v2"; + String altPath = altName.replace('.', '/').concat(".class"); + try (InputStream is = getResourceAsStream(altPath)) { + if (is != null) { + byte[] bytes = IOUtils.readFully(is, -1, true); + // patch class bytes to contain original name + for (int i = 0; i < bytes.length - 2; i++) { + if (bytes[i] == '_' && + bytes[i + 1] == 'v' && + bytes[i + 2] == '2') { + bytes[i + 2] = '1'; + } + } + return defineClass(name, bytes, 0, bytes.length); + } + else { + throw new ClassNotFoundException(name); + } + } + catch (IOException e) { + throw new ClassNotFoundException(name, e); + } + } + else { // not special class name -> just load the class + String path = name.replace('.', '/').concat(".class"); + try (InputStream is = getResourceAsStream(path)) { + if (is != null) { + byte[] bytes = IOUtils.readFully(is, -1, true); + return defineClass(name, bytes, 0, bytes.length); + } + else { + throw new ClassNotFoundException(name); + } + } + catch (IOException e) { + throw new ClassNotFoundException(name, e); + } + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/awt/image/bug8038000.java Thu Jul 31 15:54:03 2014 +0400 @@ -0,0 +1,153 @@ +/* + * 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. + * + * 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. + */ + +/** + * @test + * @bug 8038000 + * + * @summary Verifies that we could create different type of Rasters with height 1 + * and strideline which exceeds raster width. + * Also checks that a set of RasterOp work correctly with such kind of Rasters. + * + * @run main bug8038000 + */ + +import java.awt.*; +import java.awt.color.ColorSpace; +import java.awt.geom.AffineTransform; +import java.awt.image.*; +import java.util.Arrays; + +public class bug8038000 { + + public static void main(String[] args) throws Exception { + new bug8038000().checkOps(); + + // No exceptions - Passed + } + + private void checkOps() throws Exception { + + RasterOp[] ops = new RasterOp[] { + new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_sRGB), + ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB), null), + new AffineTransformOp(AffineTransform.getScaleInstance(1, 1.1), null) + }; + + + for (RasterOp op: ops) { + // Banded rasters + checkOp(Raster.createBandedRaster(DataBuffer.TYPE_BYTE, 10, 1, 10, + new int[] {0, 1, 2}, new int[]{2,1,0}, null), + Raster.createBandedRaster(DataBuffer.TYPE_BYTE, 10, 1, 1001, + new int[] {0, 1, 2}, new int[]{2,1,0}, null), op); + checkOp(Raster.createBandedRaster(DataBuffer.TYPE_USHORT, 10, 1, 10, + new int[] {0, 1, 2}, new int[]{2,1,0}, null), + Raster.createBandedRaster(DataBuffer.TYPE_USHORT, 10, 1, 1001, + new int[] {0, 1, 2}, new int[]{2,1,0}, null), op); + checkOp(Raster.createBandedRaster(DataBuffer.TYPE_INT, 10, 1, 10, + new int[] {0, 1, 2}, new int[]{2,1,0}, null), + Raster.createBandedRaster(DataBuffer.TYPE_INT, 10, 1, 1001, + new int[] {0, 1, 2}, new int[]{2,1,0}, null), op); + + // Interleaved rasters + checkOp(Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + 10, 1, 30, 3, new int[]{0, 1, 2}, null), + Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + 10, 1, 1001, 3, new int[]{0, 1, 2}, null), + op); + + checkOp(Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, + 10, 1, 30, 3, new int[]{0, 1, 2}, null), + Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, + 10, 1, 1001, 3, new int[]{0, 1, 2}, null), + op); + + // Packed rasters + checkOp(Raster.createPackedRaster(new DataBufferByte(10), 10, 1, 10, + new int[] {0x01, 0x02, 0x04}, null), + Raster.createPackedRaster(new DataBufferByte(10), 10, 1, 2000, + new int[] {0x01, 0x02, 0x04}, null), + op); + checkOp(Raster.createPackedRaster(new DataBufferInt(10), 10, 1, 10, + new int[] {0xff0000, 0x00ff00, 0x0000ff}, null), + Raster.createPackedRaster(new DataBufferInt(10), 10, 1, 20, + new int[] {0xff0000, 0x00ff00, 0x0000ff}, null), + op); + + } + } + + /** + * Takes two identical rasters (identical with the exception of scanline stride) + * fills their pixels with identical data, applies the RasterOp to both rasters + * and checks that the result is the same + */ + private void checkOp(WritableRaster wr1, WritableRaster wr2, RasterOp op) { + System.out.println("Checking " + op + " with rasters: \n " + wr1 + + "\n " + wr2); + try { + WritableRaster r1 = op.filter(fillRaster(wr1), null); + WritableRaster r2 = op.filter(fillRaster(wr2), null); + compareRasters(r1, r2); + } catch (ImagingOpException e) { + System.out.println(" Skip: Op is not supported: " + e); + } + } + + private WritableRaster fillRaster(WritableRaster wr) { + int c = 0; + for(int x = wr.getMinX(); x < wr.getMinX() + wr.getWidth(); x++) { + for(int y = wr.getMinY(); y < wr.getMinY() + wr.getHeight(); y++) { + for (int b = 0; b < wr.getNumBands(); b++) { + wr.setSample(x, y, b, c++); + } + } + } + return wr; + } + + private void compareRasters(Raster r1, Raster r2) { + Rectangle bounds = r1.getBounds(); + if (!bounds.equals(r2.getBounds())) { + throw new RuntimeException("Bounds differ."); + } + + if (r1.getNumBands() != r2.getNumBands()) { + throw new RuntimeException("Bands differ."); + } + + int[] b1 = new int[r1.getNumBands()]; + int[] b2 = new int[r1.getNumBands()]; + + for (int x = (int) bounds.getX(); x < bounds.getMaxX(); x++) { + for (int y = (int) bounds.getY(); y < bounds.getMaxY(); y++) { + r1.getPixel(x,y, b1); + r2.getPixel(x,y, b2); + if (!Arrays.equals(b1, b2)) { + throw new RuntimeException("Pixels differ."); + } + } + } + } +}
--- a/test/sun/security/pkcs11/fips/CipherTest.java Tue Jul 29 17:50:39 2014 +0100 +++ b/test/sun/security/pkcs11/fips/CipherTest.java Thu Jul 31 15:54:03 2014 +0400 @@ -458,8 +458,21 @@ return false; } + // No ECDH-capable certificate in key store. May restructure + // this in the future. + if (cipherSuite.contains("ECDHE_ECDSA") || + cipherSuite.contains("ECDH_ECDSA") || + cipherSuite.contains("ECDH_RSA")) { + System.out.println("Skipping unsupported test for " + + cipherSuite + " of " + protocol); + return false; + } + // skip SSLv2Hello protocol - if (protocol.equals("SSLv2Hello")) { + // + // skip TLSv1.2 protocol, we have not implement "SunTls12Prf" and + // SunTls12RsaPremasterSecret in SunPKCS11 provider + if (protocol.equals("SSLv2Hello") || protocol.equals("TLSv1.2")) { System.out.println("Skipping unsupported test for " + cipherSuite + " of " + protocol); return false;
--- a/test/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java Tue Jul 29 17:50:39 2014 +0100 +++ b/test/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java Thu Jul 31 15:54:03 2014 +0400 @@ -23,7 +23,7 @@ /* * @test - * @bug 6313675 6323647 + * @bug 6313675 6323647 8028192 * @summary Verify that all ciphersuites work in FIPS mode * @library .. * @ignore JSSE supported cipher suites are changed with CR 6916074, @@ -44,9 +44,13 @@ return; } - if ("sparc".equals(System.getProperty("os.arch")) == false) { - // we have not updated other platforms with the proper NSS libraries yet - System.out.println("Test currently works only on solaris-sparc, skipping"); + String arch = System.getProperty("os.arch"); + if (!("sparc".equals(arch) || "sparcv9".equals(arch))) { + // we have not updated other platforms with the proper NSS + // libraries yet + System.out.println( + "Test currently works only on solaris-sparc " + + "and solaris-sparcv9. Skipping on " + arch); return; }
--- a/test/sun/security/pkcs11/tls/TestPremaster.java Tue Jul 29 17:50:39 2014 +0100 +++ b/test/sun/security/pkcs11/tls/TestPremaster.java Thu Jul 31 15:54:03 2014 +0400 @@ -34,6 +34,7 @@ import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; +import java.util.Formatter; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; @@ -59,27 +60,51 @@ System.out.println("OK: " + e); } - test(kg, 3, 0); - test(kg, 3, 1); - test(kg, 3, 2); - test(kg, 4, 0); + int[] protocolVersions = {0x0300, 0x0301, 0x0302, 0x0400}; + for (int clientVersion : protocolVersions) { + for (int serverVersion : protocolVersions) { + test(kg, clientVersion, serverVersion); + if (serverVersion >= clientVersion) { + break; + } + } + } System.out.println("Done."); } - private static void test(KeyGenerator kg, int major, int minor) - throws Exception { + private static void test(KeyGenerator kg, + int clientVersion, int serverVersion) throws Exception { - kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor)); + System.out.printf( + "Testing RSA pre-master secret key generation between " + + "client (0x%04X) and server(0x%04X)%n", + clientVersion, serverVersion); + kg.init(new TlsRsaPremasterSecretParameterSpec( + clientVersion, serverVersion)); SecretKey key = kg.generateKey(); byte[] encoded = key.getEncoded(); - if (encoded.length != 48) { - throw new Exception("length: " + encoded.length); - } - if ((encoded[0] != major) || (encoded[1] != minor)) { - throw new Exception("version mismatch: " + encoded[0] + - "." + encoded[1]); - } - System.out.println("OK: " + major + "." + minor); + if (encoded != null) { // raw key material may be not extractable + if (encoded.length != 48) { + throw new Exception("length: " + encoded.length); + } + int v = versionOf(encoded[0], encoded[1]); + if (clientVersion != v) { + if (serverVersion != v || clientVersion >= 0x0302) { + throw new Exception(String.format( + "version mismatch: (0x%04X) rather than (0x%04X) " + + "is used in pre-master secret", v, clientVersion)); + } + System.out.printf("Use compatible version (0x%04X)%n", v); + } + System.out.println("Passed, version matches!"); + } else { + System.out.println("Raw key material is not extractable"); + } } + + private static int versionOf(int major, int minor) { + return ((major & 0xFF) << 8) | (minor & 0xFF); + } + }