--- a/jdk/make/java/java/FILES_c.gmk Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/make/java/java/FILES_c.gmk Wed Apr 17 02:53:02 2013 -0700
@@ -48,7 +48,6 @@
Proxy.c \
RandomAccessFile.c \
RandomAccessFile_md.c \
- ResourceBundle.c \
Runtime.c \
SecurityManager.c \
Shutdown.c \
--- a/jdk/make/java/java/mapfile-vers Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/make/java/java/mapfile-vers Wed Apr 17 02:53:02 2013 -0700
@@ -134,7 +134,6 @@
Java_java_lang_ClassLoader_00024NativeLibrary_load;
Java_java_lang_ClassLoader_00024NativeLibrary_unload;
Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib;
- Java_java_lang_ClassLoader_getCaller;
Java_java_lang_ClassLoader_registerNatives;
Java_java_lang_Compiler_registerNatives;
Java_java_lang_Double_longBitsToDouble;
@@ -233,7 +232,6 @@
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2;
Java_java_security_AccessController_getStackAccessControlContext;
Java_java_security_AccessController_getInheritedAccessControlContext;
- Java_java_util_ResourceBundle_getClassContext;
Java_java_util_TimeZone_getSystemTimeZoneID;
Java_java_util_TimeZone_getSystemGMTOffsetID;
Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8;
--- a/jdk/make/java/java/reorder-i586 Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/make/java/java/reorder-i586 Wed Apr 17 02:53:02 2013 -0700
@@ -73,7 +73,6 @@
# Test Sleep
# Test IntToString
# Test LoadToolkit
-text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess;
--- a/jdk/make/java/java/reorder-sparc Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/make/java/java/reorder-sparc Wed Apr 17 02:53:02 2013 -0700
@@ -78,7 +78,6 @@
# Test Sleep
# Test IntToString
# Test LoadToolkit
-text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess;
--- a/jdk/make/java/java/reorder-sparcv9 Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/make/java/java/reorder-sparcv9 Wed Apr 17 02:53:02 2013 -0700
@@ -74,7 +74,6 @@
# Test Sleep
# Test IntToString
# Test LoadToolkit
-text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess;
--- a/jdk/make/sun/font/FILES_c.gmk Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/make/sun/font/FILES_c.gmk Wed Apr 17 02:53:02 2013 -0700
@@ -106,7 +106,21 @@
OpenTypeLayoutEngine.cpp \
ThaiLayoutEngine.cpp \
ScriptAndLanguageTags.cpp \
- FontInstanceAdapter.cpp
+ FontInstanceAdapter.cpp \
+ ContextualGlyphInsertionProc2.cpp \
+ ContextualGlyphSubstProc2.cpp \
+ GXLayoutEngine2.cpp \
+ IndicRearrangementProcessor2.cpp \
+ LigatureSubstProc2.cpp \
+ MorphTables2.cpp \
+ NonContextualGlyphSubstProc2.cpp \
+ SegmentArrayProcessor2.cpp \
+ SegmentSingleProcessor2.cpp \
+ SimpleArrayProcessor2.cpp \
+ SingleTableProcessor2.cpp \
+ StateTableProcessor2.cpp \
+ SubtableProcessor2.cpp \
+ TrimmedArrayProcessor2.cpp
ifeq ($(PLATFORM),windows)
--- a/jdk/makefiles/mapfiles/libjava/mapfile-vers Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/makefiles/mapfiles/libjava/mapfile-vers Wed Apr 17 02:53:02 2013 -0700
@@ -134,7 +134,6 @@
Java_java_lang_ClassLoader_00024NativeLibrary_load;
Java_java_lang_ClassLoader_00024NativeLibrary_unload;
Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib;
- Java_java_lang_ClassLoader_getCaller;
Java_java_lang_ClassLoader_registerNatives;
Java_java_lang_Compiler_registerNatives;
Java_java_lang_Double_longBitsToDouble;
@@ -233,7 +232,6 @@
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2;
Java_java_security_AccessController_getStackAccessControlContext;
Java_java_security_AccessController_getInheritedAccessControlContext;
- Java_java_util_ResourceBundle_getClassContext;
Java_java_util_TimeZone_getSystemTimeZoneID;
Java_java_util_TimeZone_getSystemGMTOffsetID;
Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8;
--- a/jdk/makefiles/mapfiles/libjava/reorder-sparc Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/makefiles/mapfiles/libjava/reorder-sparc Wed Apr 17 02:53:02 2013 -0700
@@ -78,7 +78,6 @@
# Test Sleep
# Test IntToString
# Test LoadToolkit
-text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess;
--- a/jdk/makefiles/mapfiles/libjava/reorder-sparcv9 Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/makefiles/mapfiles/libjava/reorder-sparcv9 Wed Apr 17 02:53:02 2013 -0700
@@ -74,7 +74,6 @@
# Test Sleep
# Test IntToString
# Test LoadToolkit
-text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess;
--- a/jdk/makefiles/mapfiles/libjava/reorder-x86 Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/makefiles/mapfiles/libjava/reorder-x86 Wed Apr 17 02:53:02 2013 -0700
@@ -73,7 +73,6 @@
# Test Sleep
# Test IntToString
# Test LoadToolkit
-text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess;
--- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed Apr 17 02:53:02 2013 -0700
@@ -170,7 +170,7 @@
setTitle(((Dialog) getTarget()).getTitle());
}
- setAlwaysOnTop(getTarget().isAlwaysOnTop());
+ updateAlwaysOnTopState();
updateMinimumSize();
final Shape shape = getTarget().getShape();
@@ -357,8 +357,8 @@
}
@Override
- public void setAlwaysOnTop(boolean value) {
- platformWindow.setAlwaysOnTop(value);
+ public void updateAlwaysOnTopState() {
+ platformWindow.setAlwaysOnTop(getTarget().isAlwaysOnTop());
}
@Override
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CFileDialog.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CFileDialog.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -180,7 +180,7 @@
}
@Override
- public void setAlwaysOnTop(boolean alwaysOnTop) {
+ public void updateAlwaysOnTopState() {
}
@Override
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -87,7 +87,7 @@
}
// 1.6 peer method
- public void setAlwaysOnTop(boolean value) {
+ public void updateAlwaysOnTopState() {
// no-op, since we just show the native print dialog
}
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java Wed Apr 17 02:53:02 2013 -0700
@@ -243,12 +243,17 @@
* sending warnings to listeners.
*/
protected void warningOccurred(int code) {
- if ((code < 0) || (code > MAX_WARNING)){
- throw new InternalError("Invalid warning index");
+ cbLock.lock();
+ try {
+ if ((code < 0) || (code > MAX_WARNING)){
+ throw new InternalError("Invalid warning index");
+ }
+ processWarningOccurred
+ ("com.sun.imageio.plugins.jpeg.JPEGImageReaderResources",
+ Integer.toString(code));
+ } finally {
+ cbLock.unlock();
}
- processWarningOccurred
- ("com.sun.imageio.plugins.jpeg.JPEGImageReaderResources",
- Integer.toString(code));
}
/**
@@ -265,7 +270,12 @@
* library warnings from being printed to stderr.
*/
protected void warningWithMessage(String msg) {
- processWarningOccurred(msg);
+ cbLock.lock();
+ try {
+ processWarningOccurred(msg);
+ } finally {
+ cbLock.unlock();
+ }
}
public void setInput(Object input,
@@ -274,18 +284,55 @@
{
setThreadLock();
try {
+ cbLock.check();
+
super.setInput(input, seekForwardOnly, ignoreMetadata);
this.ignoreMetadata = ignoreMetadata;
resetInternalState();
iis = (ImageInputStream) input; // Always works
- setSource(structPointer, iis);
+ setSource(structPointer);
} finally {
clearThreadLock();
}
}
- private native void setSource(long structPointer,
- ImageInputStream source);
+ /**
+ * This method is called from native code in order to fill
+ * native input buffer.
+ *
+ * We block any attempt to change the reading state during this
+ * method, in order to prevent a corruption of the native decoder
+ * state.
+ *
+ * @return number of bytes read from the stream.
+ */
+ private int readInputData(byte[] buf, int off, int len) throws IOException {
+ cbLock.lock();
+ try {
+ return iis.read(buf, off, len);
+ } finally {
+ cbLock.unlock();
+ }
+ }
+
+ /**
+ * This method is called from the native code in order to
+ * skip requested number of bytes in the input stream.
+ *
+ * @param n
+ * @return
+ * @throws IOException
+ */
+ private long skipInputBytes(long n) throws IOException {
+ cbLock.lock();
+ try {
+ return iis.skipBytes(n);
+ } finally {
+ cbLock.unlock();
+ }
+ }
+
+ private native void setSource(long structPointer);
private void checkTablesOnly() throws IOException {
if (debug) {
@@ -337,6 +384,8 @@
public int getNumImages(boolean allowSearch) throws IOException {
setThreadLock();
try { // locked thread
+ cbLock.check();
+
return getNumImagesOnThread(allowSearch);
} finally {
clearThreadLock();
@@ -536,8 +585,13 @@
if (debug) {
System.out.println("pushing back " + num + " bytes");
}
- iis.seek(iis.getStreamPosition()-num);
- // The buffer is clear after this, so no need to set haveSeeked.
+ cbLock.lock();
+ try {
+ iis.seek(iis.getStreamPosition()-num);
+ // The buffer is clear after this, so no need to set haveSeeked.
+ } finally {
+ cbLock.unlock();
+ }
}
/**
@@ -644,7 +698,12 @@
* Ignore this profile.
*/
iccCS = null;
- warningOccurred(WARNING_IGNORE_INVALID_ICC);
+ cbLock.lock();
+ try {
+ warningOccurred(WARNING_IGNORE_INVALID_ICC);
+ } finally {
+ cbLock.unlock();
+ }
}
}
}
@@ -653,6 +712,7 @@
setThreadLock();
try {
if (currentImage != imageIndex) {
+ cbLock.check();
readHeader(imageIndex, true);
}
return width;
@@ -665,6 +725,7 @@
setThreadLock();
try {
if (currentImage != imageIndex) {
+ cbLock.check();
readHeader(imageIndex, true);
}
return height;
@@ -693,6 +754,8 @@
setThreadLock();
try {
if (currentImage != imageIndex) {
+ cbLock.check();
+
readHeader(imageIndex, true);
}
@@ -716,6 +779,7 @@
private Iterator getImageTypesOnThread(int imageIndex)
throws IOException {
if (currentImage != imageIndex) {
+ cbLock.check();
readHeader(imageIndex, true);
}
@@ -931,6 +995,7 @@
setThreadLock();
try {
if (!tablesOnlyChecked) {
+ cbLock.check();
checkTablesOnly();
}
return streamMetadata;
@@ -951,6 +1016,8 @@
return imageMetadata;
}
+ cbLock.check();
+
gotoImage(imageIndex);
imageMetadata = new JPEGMetadata(false, false, iis, this);
@@ -967,6 +1034,7 @@
throws IOException {
setThreadLock();
try {
+ cbLock.check();
try {
readInternal(imageIndex, param, false);
} catch (RuntimeException e) {
@@ -1196,58 +1264,63 @@
}
target.setRect(destROI.x, destROI.y + y, raster);
- processImageUpdate(image,
- destROI.x, destROI.y+y,
- raster.getWidth(), 1,
- 1, 1,
- destinationBands);
- if ((y > 0) && (y%progInterval == 0)) {
- int height = target.getHeight()-1;
- float percentOfPass = ((float)y)/height;
- if (progressive) {
- if (knownPassCount != UNKNOWN) {
- processImageProgress((pass + percentOfPass)*100.0F
- / knownPassCount);
- } else if (maxProgressivePass != Integer.MAX_VALUE) {
- // Use the range of allowed progressive passes
- processImageProgress((pass + percentOfPass)*100.0F
- / (maxProgressivePass - minProgressivePass + 1));
+ cbLock.lock();
+ try {
+ processImageUpdate(image,
+ destROI.x, destROI.y+y,
+ raster.getWidth(), 1,
+ 1, 1,
+ destinationBands);
+ if ((y > 0) && (y%progInterval == 0)) {
+ int height = target.getHeight()-1;
+ float percentOfPass = ((float)y)/height;
+ if (progressive) {
+ if (knownPassCount != UNKNOWN) {
+ processImageProgress((pass + percentOfPass)*100.0F
+ / knownPassCount);
+ } else if (maxProgressivePass != Integer.MAX_VALUE) {
+ // Use the range of allowed progressive passes
+ processImageProgress((pass + percentOfPass)*100.0F
+ / (maxProgressivePass - minProgressivePass + 1));
+ } else {
+ // Assume there are a minimum of MIN_ESTIMATED_PASSES
+ // and that there is always one more pass
+ // Compute the percentage as the percentage at the end
+ // of the previous pass, plus the percentage of this
+ // pass scaled to be the percentage of the total remaining,
+ // assuming a minimum of MIN_ESTIMATED_PASSES passes and
+ // that there is always one more pass. This is monotonic
+ // and asymptotic to 1.0, which is what we need.
+ int remainingPasses = // including this one
+ Math.max(2, MIN_ESTIMATED_PASSES-pass);
+ int totalPasses = pass + remainingPasses-1;
+ progInterval = Math.max(height/20*totalPasses,
+ totalPasses);
+ if (y%progInterval == 0) {
+ percentToDate = previousPassPercentage +
+ (1.0F - previousPassPercentage)
+ * (percentOfPass)/remainingPasses;
+ if (debug) {
+ System.out.print("pass= " + pass);
+ System.out.print(", y= " + y);
+ System.out.print(", progInt= " + progInterval);
+ System.out.print(", % of pass: " + percentOfPass);
+ System.out.print(", rem. passes: "
+ + remainingPasses);
+ System.out.print(", prev%: "
+ + previousPassPercentage);
+ System.out.print(", %ToDate: " + percentToDate);
+ System.out.print(" ");
+ }
+ processImageProgress(percentToDate*100.0F);
+ }
+ }
} else {
- // Assume there are a minimum of MIN_ESTIMATED_PASSES
- // and that there is always one more pass
- // Compute the percentage as the percentage at the end
- // of the previous pass, plus the percentage of this
- // pass scaled to be the percentage of the total remaining,
- // assuming a minimum of MIN_ESTIMATED_PASSES passes and
- // that there is always one more pass. This is monotonic
- // and asymptotic to 1.0, which is what we need.
- int remainingPasses = // including this one
- Math.max(2, MIN_ESTIMATED_PASSES-pass);
- int totalPasses = pass + remainingPasses-1;
- progInterval = Math.max(height/20*totalPasses,
- totalPasses);
- if (y%progInterval == 0) {
- percentToDate = previousPassPercentage +
- (1.0F - previousPassPercentage)
- * (percentOfPass)/remainingPasses;
- if (debug) {
- System.out.print("pass= " + pass);
- System.out.print(", y= " + y);
- System.out.print(", progInt= " + progInterval);
- System.out.print(", % of pass: " + percentOfPass);
- System.out.print(", rem. passes: "
- + remainingPasses);
- System.out.print(", prev%: "
- + previousPassPercentage);
- System.out.print(", %ToDate: " + percentToDate);
- System.out.print(" ");
- }
- processImageProgress(percentToDate*100.0F);
- }
+ processImageProgress(percentOfPass * 100.0F);
}
- } else {
- processImageProgress(percentOfPass * 100.0F);
}
+ } finally {
+ cbLock.unlock();
}
}
@@ -1260,33 +1333,58 @@
}
private void passStarted (int pass) {
- this.pass = pass;
- previousPassPercentage = percentToDate;
- processPassStarted(image,
- pass,
- minProgressivePass,
- maxProgressivePass,
- 0, 0,
- 1,1,
- destinationBands);
+ cbLock.lock();
+ try {
+ this.pass = pass;
+ previousPassPercentage = percentToDate;
+ processPassStarted(image,
+ pass,
+ minProgressivePass,
+ maxProgressivePass,
+ 0, 0,
+ 1,1,
+ destinationBands);
+ } finally {
+ cbLock.unlock();
+ }
}
private void passComplete () {
- processPassComplete(image);
+ cbLock.lock();
+ try {
+ processPassComplete(image);
+ } finally {
+ cbLock.unlock();
+ }
}
void thumbnailStarted(int thumbnailIndex) {
- processThumbnailStarted(currentImage, thumbnailIndex);
+ cbLock.lock();
+ try {
+ processThumbnailStarted(currentImage, thumbnailIndex);
+ } finally {
+ cbLock.unlock();
+ }
}
// Provide access to protected superclass method
void thumbnailProgress(float percentageDone) {
- processThumbnailProgress(percentageDone);
+ cbLock.lock();
+ try {
+ processThumbnailProgress(percentageDone);
+ } finally {
+ cbLock.unlock();
+ }
}
// Provide access to protected superclass method
void thumbnailComplete() {
- processThumbnailComplete();
+ cbLock.lock();
+ try {
+ processThumbnailComplete();
+ } finally {
+ cbLock.unlock();
+ }
}
/**
@@ -1310,6 +1408,11 @@
public void abort() {
setThreadLock();
try {
+ /**
+ * NB: we do not check the call back lock here,
+ * we allow to abort the reader any time.
+ */
+
super.abort();
abortRead(structPointer);
} finally {
@@ -1332,6 +1435,7 @@
setThreadLock();
Raster retval = null;
try {
+ cbLock.check();
/*
* This could be further optimized by not resetting the dest.
* offset and creating a translated raster in readInternal()
@@ -1371,6 +1475,8 @@
public int getNumThumbnails(int imageIndex) throws IOException {
setThreadLock();
try {
+ cbLock.check();
+
getImageMetadata(imageIndex); // checks iis state for us
// Now check the jfif segments
JFIFMarkerSegment jfif =
@@ -1391,6 +1497,8 @@
throws IOException {
setThreadLock();
try {
+ cbLock.check();
+
if ((thumbnailIndex < 0)
|| (thumbnailIndex >= getNumThumbnails(imageIndex))) {
throw new IndexOutOfBoundsException("No such thumbnail");
@@ -1409,6 +1517,8 @@
throws IOException {
setThreadLock();
try {
+ cbLock.check();
+
if ((thumbnailIndex < 0)
|| (thumbnailIndex >= getNumThumbnails(imageIndex))) {
throw new IndexOutOfBoundsException("No such thumbnail");
@@ -1428,6 +1538,8 @@
throws IOException {
setThreadLock();
try {
+ cbLock.check();
+
if ((thumbnailIndex < 0)
|| (thumbnailIndex >= getNumThumbnails(imageIndex))) {
throw new IndexOutOfBoundsException("No such thumbnail");
@@ -1468,6 +1580,7 @@
public void reset() {
setThreadLock();
try {
+ cbLock.check();
super.reset();
} finally {
clearThreadLock();
@@ -1479,6 +1592,8 @@
public void dispose() {
setThreadLock();
try {
+ cbLock.check();
+
if (structPointer != 0) {
disposerRecord.dispose();
structPointer = 0;
@@ -1540,6 +1655,36 @@
theThread = null;
}
}
+
+ private CallBackLock cbLock = new CallBackLock();
+
+ private static class CallBackLock {
+
+ private State lockState;
+
+ CallBackLock() {
+ lockState = State.Unlocked;
+ }
+
+ void check() {
+ if (lockState != State.Unlocked) {
+ throw new IllegalStateException("Access to the reader is not allowed");
+ }
+ }
+
+ private void lock() {
+ lockState = State.Locked;
+ }
+
+ private void unlock() {
+ lockState = State.Unlocked;
+ }
+
+ private static enum State {
+ Unlocked,
+ Locked
+ }
+ }
}
/**
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java Wed Apr 17 02:53:02 2013 -0700
@@ -183,8 +183,7 @@
return null;
}
});
- initWriterIDs(ImageOutputStream.class,
- JPEGQTable.class,
+ initWriterIDs(JPEGQTable.class,
JPEGHuffmanTable.class);
}
@@ -200,11 +199,13 @@
public void setOutput(Object output) {
setThreadLock();
try {
+ cbLock.check();
+
super.setOutput(output); // validates output
resetInternalState();
ios = (ImageOutputStream) output; // so this will always work
// Set the native destination
- setDest(structPointer, ios);
+ setDest(structPointer);
} finally {
clearThreadLock();
}
@@ -359,6 +360,8 @@
ImageWriteParam param) throws IOException {
setThreadLock();
try {
+ cbLock.check();
+
writeOnThread(streamMetadata, image, param);
} finally {
clearThreadLock();
@@ -1082,13 +1085,18 @@
haveMetadata,
restartInterval);
- if (aborted) {
- processWriteAborted();
- } else {
- processImageComplete();
+ cbLock.lock();
+ try {
+ if (aborted) {
+ processWriteAborted();
+ } else {
+ processImageComplete();
+ }
+
+ ios.flush();
+ } finally {
+ cbLock.unlock();
}
-
- ios.flush();
currentImage++; // After a successful write
}
@@ -1096,6 +1104,8 @@
throws IOException {
setThreadLock();
try {
+ cbLock.check();
+
prepareWriteSequenceOnThread(streamMetadata);
} finally {
clearThreadLock();
@@ -1175,6 +1185,8 @@
throws IOException {
setThreadLock();
try {
+ cbLock.check();
+
if (sequencePrepared == false) {
throw new IllegalStateException("sequencePrepared not called!");
}
@@ -1188,6 +1200,8 @@
public void endWriteSequence() throws IOException {
setThreadLock();
try {
+ cbLock.check();
+
if (sequencePrepared == false) {
throw new IllegalStateException("sequencePrepared not called!");
}
@@ -1200,6 +1214,10 @@
public synchronized void abort() {
setThreadLock();
try {
+ /**
+ * NB: we do not check the call back lock here, we allow to abort
+ * the reader any time.
+ */
super.abort();
abortWrite(structPointer);
} finally {
@@ -1223,6 +1241,8 @@
public void reset() {
setThreadLock();
try {
+ cbLock.check();
+
super.reset();
} finally {
clearThreadLock();
@@ -1232,6 +1252,8 @@
public void dispose() {
setThreadLock();
try {
+ cbLock.check();
+
if (structPointer != 0) {
disposerRecord.dispose();
structPointer = 0;
@@ -1251,13 +1273,18 @@
* sending warnings to listeners.
*/
void warningOccurred(int code) {
- if ((code < 0) || (code > MAX_WARNING)){
- throw new InternalError("Invalid warning index");
+ cbLock.lock();
+ try {
+ if ((code < 0) || (code > MAX_WARNING)){
+ throw new InternalError("Invalid warning index");
+ }
+ processWarningOccurred
+ (currentImage,
+ "com.sun.imageio.plugins.jpeg.JPEGImageWriterResources",
+ Integer.toString(code));
+ } finally {
+ cbLock.unlock();
}
- processWarningOccurred
- (currentImage,
- "com.sun.imageio.plugins.jpeg.JPEGImageWriterResources",
- Integer.toString(code));
}
/**
@@ -1274,21 +1301,41 @@
* library warnings from being printed to stderr.
*/
void warningWithMessage(String msg) {
- processWarningOccurred(currentImage, msg);
+ cbLock.lock();
+ try {
+ processWarningOccurred(currentImage, msg);
+ } finally {
+ cbLock.unlock();
+ }
}
void thumbnailStarted(int thumbnailIndex) {
- processThumbnailStarted(currentImage, thumbnailIndex);
+ cbLock.lock();
+ try {
+ processThumbnailStarted(currentImage, thumbnailIndex);
+ } finally {
+ cbLock.unlock();
+ }
}
// Provide access to protected superclass method
void thumbnailProgress(float percentageDone) {
- processThumbnailProgress(percentageDone);
+ cbLock.lock();
+ try {
+ processThumbnailProgress(percentageDone);
+ } finally {
+ cbLock.unlock();
+ }
}
// Provide access to protected superclass method
void thumbnailComplete() {
- processThumbnailComplete();
+ cbLock.lock();
+ try {
+ processThumbnailComplete();
+ } finally {
+ cbLock.unlock();
+ }
}
///////// End of Package-access API
@@ -1615,16 +1662,14 @@
////////////// Native methods and callbacks
/** Sets up static native structures. */
- private static native void initWriterIDs(Class iosClass,
- Class qTableClass,
+ private static native void initWriterIDs(Class qTableClass,
Class huffClass);
/** Sets up per-writer native structure and returns a pointer to it. */
private native long initJPEGImageWriter();
/** Sets up native structures for output stream */
- private native void setDest(long structPointer,
- ImageOutputStream ios);
+ private native void setDest(long structPointer);
/**
* Returns <code>true</code> if the write was aborted.
@@ -1749,7 +1794,12 @@
}
raster.setRect(sourceLine);
if ((y > 7) && (y%8 == 0)) { // Every 8 scanlines
- processImageProgress((float) y / (float) sourceHeight * 100.0F);
+ cbLock.lock();
+ try {
+ processImageProgress((float) y / (float) sourceHeight * 100.0F);
+ } finally {
+ cbLock.unlock();
+ }
}
}
@@ -1777,6 +1827,25 @@
}
}
+ /**
+ * This method is called from native code in order to write encoder
+ * output to the destination.
+ *
+ * We block any attempt to change the writer state during this
+ * method, in order to prevent a corruption of the native encoder
+ * state.
+ */
+ private void writeOutputData(byte[] data, int offset, int len)
+ throws IOException
+ {
+ cbLock.lock();
+ try {
+ ios.write(data, offset, len);
+ } finally {
+ cbLock.unlock();
+ }
+ }
+
private Thread theThread = null;
private int theLockCount = 0;
@@ -1811,4 +1880,34 @@
theThread = null;
}
}
+
+ private CallBackLock cbLock = new CallBackLock();
+
+ private static class CallBackLock {
+
+ private State lockState;
+
+ CallBackLock() {
+ lockState = State.Unlocked;
+ }
+
+ void check() {
+ if (lockState != State.Unlocked) {
+ throw new IllegalStateException("Access to the writer is not allowed");
+ }
+ }
+
+ private void lock() {
+ lockState = State.Locked;
+ }
+
+ private void unlock() {
+ lockState = State.Unlocked;
+ }
+
+ private static enum State {
+ Unlocked,
+ Locked
+ }
+ }
}
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -32,6 +32,7 @@
import java.io.ObjectInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
import java.security.Permission;
import java.util.Map;
import java.util.logging.Level;
@@ -213,7 +214,6 @@
Object moi;
-
// ------------------------------
// ------------------------------
Constructor<?> cons = findConstructor(theClass, null);
@@ -224,6 +224,7 @@
// Instantiate the new object
try {
ReflectUtil.checkPackageAccess(theClass);
+ ensureClassAccess(theClass);
moi= cons.newInstance();
} catch (InvocationTargetException e) {
// Wrap the exception.
@@ -270,7 +271,6 @@
checkMBeanPermission(theClass, null, null, "instantiate");
// Instantiate the new object
-
// ------------------------------
// ------------------------------
final Class<?>[] tab;
@@ -300,6 +300,7 @@
}
try {
ReflectUtil.checkPackageAccess(theClass);
+ ensureClassAccess(theClass);
moi = cons.newInstance(params);
}
catch (NoSuchMethodError error) {
@@ -741,4 +742,13 @@
sm.checkPermission(perm);
}
}
+
+ private static void ensureClassAccess(Class clazz)
+ throws IllegalAccessException
+ {
+ int mod = clazz.getModifiers();
+ if (!Modifier.isPublic(mod)) {
+ throw new IllegalAccessException("Class is not public and can't be instantiated");
+ }
+ }
}
--- a/jdk/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java Wed Apr 17 02:53:02 2013 -0700
@@ -56,7 +56,7 @@
// from simultaneous creation and destruction
// reduces possibility of deadlock, compared to
// synchronizing to the class instance
- private Object traRecLock = new Object();
+ private final Object traRecLock = new Object();
// DEVICE ATTRIBUTES
@@ -474,7 +474,7 @@
This is necessary for Receivers retrieved via MidiSystem.getReceiver()
(which opens the device implicitely).
*/
- protected abstract class AbstractReceiver implements MidiDeviceReceiver {
+ abstract class AbstractReceiver implements MidiDeviceReceiver {
private boolean open = true;
@@ -483,24 +483,24 @@
Receiver. Therefore, subclasses should not override this method.
Instead, they should implement implSend().
*/
- public synchronized void send(MidiMessage message, long timeStamp) {
- if (open) {
- implSend(message, timeStamp);
- } else {
+ @Override
+ public final synchronized void send(final MidiMessage message,
+ final long timeStamp) {
+ if (!open) {
throw new IllegalStateException("Receiver is not open");
}
+ implSend(message, timeStamp);
}
-
- protected abstract void implSend(MidiMessage message, long timeStamp);
-
+ abstract void implSend(MidiMessage message, long timeStamp);
/** Close the Receiver.
* Here, the call to the magic method closeInternal() takes place.
* Therefore, subclasses that override this method must call
* 'super.close()'.
*/
- public void close() {
+ @Override
+ public final void close() {
open = false;
synchronized (AbstractMidiDevice.this.traRecLock) {
AbstractMidiDevice.this.getReceiverList().remove(this);
@@ -508,11 +508,12 @@
AbstractMidiDevice.this.closeInternal(this);
}
- public MidiDevice getMidiDevice() {
+ @Override
+ public final MidiDevice getMidiDevice() {
return AbstractMidiDevice.this;
}
- protected boolean isOpen() {
+ final boolean isOpen() {
return open;
}
--- a/jdk/src/share/classes/com/sun/media/sound/FastShortMessage.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/com/sun/media/sound/FastShortMessage.java Wed Apr 17 02:53:02 2013 -0700
@@ -32,7 +32,7 @@
*
* @author Florian Bomers
*/
-class FastShortMessage extends ShortMessage {
+final class FastShortMessage extends ShortMessage {
private int packedMsg;
public FastShortMessage(int packedMsg) throws InvalidMidiDataException {
--- a/jdk/src/share/classes/com/sun/media/sound/FastSysexMessage.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/com/sun/media/sound/FastSysexMessage.java Wed Apr 17 02:53:02 2013 -0700
@@ -32,7 +32,7 @@
*
* @author Florian Bomers
*/
-class FastSysexMessage extends SysexMessage {
+final class FastSysexMessage extends SysexMessage {
FastSysexMessage(byte[] data) throws InvalidMidiDataException {
super(data);
--- a/jdk/src/share/classes/com/sun/media/sound/MidiOutDevice.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/com/sun/media/sound/MidiOutDevice.java Wed Apr 17 02:53:02 2013 -0700
@@ -103,9 +103,9 @@
class MidiOutReceiver extends AbstractReceiver {
- protected void implSend(MidiMessage message, long timeStamp) {
- int length = message.getLength();
- int status = message.getStatus();
+ void implSend(final MidiMessage message, final long timeStamp) {
+ final int length = message.getLength();
+ final int status = message.getStatus();
if (length <= 3 && status != 0xF0 && status != 0xF7) {
int packedMsg;
if (message instanceof ShortMessage) {
@@ -140,11 +140,15 @@
}
nSendShortMessage(id, packedMsg, timeStamp);
} else {
+ final byte[] data;
if (message instanceof FastSysexMessage) {
- nSendLongMessage(id, ((FastSysexMessage) message).getReadOnlyMessage(),
- length, timeStamp);
+ data = ((FastSysexMessage) message).getReadOnlyMessage();
} else {
- nSendLongMessage(id, message.getMessage(), length, timeStamp);
+ data = message.getMessage();
+ }
+ final int dataLength = Math.min(length, data.length);
+ if (dataLength > 0) {
+ nSendLongMessage(id, data, dataLength, timeStamp);
}
}
}
--- a/jdk/src/share/classes/com/sun/media/sound/RealTimeSequencer.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/com/sun/media/sound/RealTimeSequencer.java Wed Apr 17 02:53:02 2013 -0700
@@ -1026,7 +1026,7 @@
class SequencerReceiver extends AbstractReceiver {
- protected void implSend(MidiMessage message, long timeStamp) {
+ void implSend(MidiMessage message, long timeStamp) {
if (recording) {
long tickPos = 0;
--- a/jdk/src/share/classes/java/awt/Window.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/awt/Window.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -2234,7 +2234,7 @@
WindowPeer peer = (WindowPeer)this.peer;
synchronized(getTreeLock()) {
if (peer != null) {
- peer.setAlwaysOnTop(alwaysOnTop);
+ peer.updateAlwaysOnTopState();
}
}
}
--- a/jdk/src/share/classes/java/awt/peer/WindowPeer.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/awt/peer/WindowPeer.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -53,15 +53,14 @@
void toBack();
/**
- * Sets if the window should always stay on top of all other windows or
- * not.
+ * Updates the window's always-on-top state.
+ * Sets if the window should always stay
+ * on top of all other windows or not.
*
- * @param alwaysOnTop if the window should always stay on top of all other
- * windows or not
- *
+ * @see Window#getAlwaysOnTop()
* @see Window#setAlwaysOnTop(boolean)
*/
- void setAlwaysOnTop(boolean alwaysOnTop);
+ void updateAlwaysOnTopState();
/**
* Updates the window's focusable state.
--- a/jdk/src/share/classes/java/beans/ThreadGroupContext.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/beans/ThreadGroupContext.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@
import com.sun.beans.finder.PropertyEditorFinder;
import java.awt.GraphicsEnvironment;
-import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
@@ -42,7 +41,7 @@
*/
final class ThreadGroupContext {
- private static final Map<ThreadGroup, ThreadGroupContext> contexts = new WeakHashMap<>();
+ private static final WeakIdentityMap<ThreadGroupContext> contexts = new WeakIdentityMap<>();
/**
* Returns the appropriate {@code AppContext} for the caller,
@@ -69,6 +68,8 @@
private BeanInfoFinder beanInfoFinder;
private PropertyEditorFinder propertyEditorFinder;
+ private ThreadGroupContext() {
+ }
boolean isDesignTime() {
return this.isDesignTime;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/beans/WeakIdentityMap.java Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,181 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.beans;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+/**
+ * Hash table based mapping, which uses weak references to store keys
+ * and reference-equality in place of object-equality to compare them.
+ * An entry will automatically be removed when its key is no longer
+ * in ordinary use. Both null values and the null key are supported.
+ *
+ * @see java.util.IdentityHashMap
+ * @see java.util.WeakHashMap
+ */
+final class WeakIdentityMap<T> {
+
+ private static final int MAXIMUM_CAPACITY = 1 << 30; // it MUST be a power of two
+ private static final Object NULL = new Object(); // special object for null key
+
+ private final ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
+
+ private Entry<T>[] table = newTable(1<<3); // table's length MUST be a power of two
+ private int threshold = 6; // the next size value at which to resize
+ private int size = 0; // the number of key-value mappings
+
+ public T get(Object key) {
+ removeStaleEntries();
+ if (key == null) {
+ key = NULL;
+ }
+ int hash = key.hashCode();
+ int index = getIndex(this.table, hash);
+ for (Entry<T> entry = this.table[index]; entry != null; entry = entry.next) {
+ if (entry.isMatched(key, hash)) {
+ return entry.value;
+ }
+ }
+ return null;
+ }
+
+ public T put(Object key, T value) {
+ removeStaleEntries();
+ if (key == null) {
+ key = NULL;
+ }
+ int hash = key.hashCode();
+ int index = getIndex(this.table, hash);
+ for (Entry<T> entry = this.table[index]; entry != null; entry = entry.next) {
+ if (entry.isMatched(key, hash)) {
+ T oldValue = entry.value;
+ entry.value = value;
+ return oldValue;
+ }
+ }
+ this.table[index] = new Entry<T>(key, hash, value, this.queue, this.table[index]);
+ if (++this.size >= this.threshold) {
+ if (this.table.length == MAXIMUM_CAPACITY) {
+ this.threshold = Integer.MAX_VALUE;
+ }
+ else {
+ removeStaleEntries();
+ Entry<T>[] table = newTable(this.table.length * 2);
+ transfer(this.table, table);
+
+ // If ignoring null elements and processing ref queue caused massive
+ // shrinkage, then restore old table. This should be rare, but avoids
+ // unbounded expansion of garbage-filled tables.
+ if (this.size >= this.threshold / 2) {
+ this.table = table;
+ this.threshold *= 2;
+ }
+ else {
+ transfer(table, this.table);
+ }
+ }
+ }
+ return null;
+ }
+
+ private void removeStaleEntries() {
+ for (Object ref = this.queue.poll(); ref != null; ref = this.queue.poll()) {
+ @SuppressWarnings("unchecked")
+ Entry<T> entry = (Entry<T>) ref;
+ int index = getIndex(this.table, entry.hash);
+
+ Entry<T> prev = this.table[index];
+ Entry<T> current = prev;
+ while (current != null) {
+ Entry<T> next = current.next;
+ if (current == entry) {
+ if (prev == entry) {
+ this.table[index] = next;
+ }
+ else {
+ prev.next = next;
+ }
+ entry.value = null; // Help GC
+ entry.next = null; // Help GC
+ this.size--;
+ break;
+ }
+ prev = current;
+ current = next;
+ }
+ }
+ }
+
+ private void transfer(Entry<T>[] oldTable, Entry<T>[] newTable) {
+ for (int i = 0; i < oldTable.length; i++) {
+ Entry<T> entry = oldTable[i];
+ oldTable[i] = null;
+ while (entry != null) {
+ Entry<T> next = entry.next;
+ Object key = entry.get();
+ if (key == null) {
+ entry.value = null; // Help GC
+ entry.next = null; // Help GC
+ this.size--;
+ }
+ else {
+ int index = getIndex(newTable, entry.hash);
+ entry.next = newTable[index];
+ newTable[index] = entry;
+ }
+ entry = next;
+ }
+ }
+ }
+
+
+ @SuppressWarnings("unchecked")
+ private Entry<T>[] newTable(int length) {
+ return (Entry<T>[]) new Entry<?>[length];
+ }
+
+ private static int getIndex(Entry<?>[] table, int hash) {
+ return hash & (table.length - 1);
+ }
+
+ private static class Entry<T> extends WeakReference<Object> {
+ private final int hash;
+ private T value;
+ private Entry<T> next;
+
+ Entry(Object key, int hash, T value, ReferenceQueue<Object> queue, Entry<T> next) {
+ super(key, queue);
+ this.hash = hash;
+ this.value = value;
+ this.next = next;
+ }
+
+ boolean isMatched(Object key, int hash) {
+ return (this.hash == hash) && (key == get());
+ }
+ }
+}
--- a/jdk/src/share/classes/java/io/ObjectInputStream.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/io/ObjectInputStream.java Wed Apr 17 02:53:02 2013 -0700
@@ -41,6 +41,7 @@
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import static java.io.ObjectStreamClass.processQueue;
+import sun.reflect.misc.ReflectUtil;
/**
* An ObjectInputStream deserializes primitive data and objects previously
@@ -1519,6 +1520,12 @@
}
}
+ private boolean isCustomSubclass() {
+ // Return true if this class is a custom subclass of ObjectInputStream
+ return getClass().getClassLoader()
+ != ObjectInputStream.class.getClassLoader();
+ }
+
/**
* Reads in and returns class descriptor for a dynamic proxy class. Sets
* passHandle to proxy class descriptor's assigned handle. If proxy class
@@ -1548,6 +1555,15 @@
try {
if ((cl = resolveProxyClass(ifaces)) == null) {
resolveEx = new ClassNotFoundException("null class");
+ } else if (!Proxy.isProxyClass(cl)) {
+ throw new InvalidClassException("Not a proxy");
+ } else {
+ // ReflectUtil.checkProxyPackageAccess makes a test
+ // equivalent to isCustomSubclass so there's no need
+ // to condition this call to isCustomSubclass == true here.
+ ReflectUtil.checkProxyPackageAccess(
+ getClass().getClassLoader(),
+ cl.getInterfaces());
}
} catch (ClassNotFoundException ex) {
resolveEx = ex;
@@ -1589,9 +1605,12 @@
Class<?> cl = null;
ClassNotFoundException resolveEx = null;
bin.setBlockDataMode(true);
+ final boolean checksRequired = isCustomSubclass();
try {
if ((cl = resolveClass(readDesc)) == null) {
resolveEx = new ClassNotFoundException("null class");
+ } else if (checksRequired) {
+ ReflectUtil.checkPackageAccess(cl);
}
} catch (ClassNotFoundException ex) {
resolveEx = ex;
--- a/jdk/src/share/classes/java/lang/Class.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Class.java Wed Apr 17 02:53:02 2013 -0700
@@ -53,6 +53,7 @@
import java.util.HashMap;
import java.util.Objects;
import sun.misc.Unsafe;
+import sun.reflect.CallerSensitive;
import sun.reflect.ConstantPool;
import sun.reflect.Reflection;
import sun.reflect.ReflectionFactory;
@@ -250,9 +251,11 @@
* by this method fails
* @exception ClassNotFoundException if the class cannot be located
*/
+ @CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
- return forName0(className, true, ClassLoader.getCallerClassLoader());
+ return forName0(className, true,
+ ClassLoader.getClassLoader(Reflection.getCallerClass()));
}
@@ -317,6 +320,7 @@
* @see java.lang.ClassLoader
* @since 1.2
*/
+ @CallerSensitive
public static Class<?> forName(String name, boolean initialize,
ClassLoader loader)
throws ClassNotFoundException
@@ -324,7 +328,7 @@
if (sun.misc.VM.isSystemDomainLoader(loader)) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- ClassLoader ccl = ClassLoader.getCallerClassLoader();
+ ClassLoader ccl = ClassLoader.getClassLoader(Reflection.getCallerClass());
if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
sm.checkPermission(
SecurityConstants.GET_CLASSLOADER_PERMISSION);
@@ -386,18 +390,14 @@
* </ul>
*
*/
+ @CallerSensitive
public T newInstance()
throws InstantiationException, IllegalAccessException
{
if (System.getSecurityManager() != null) {
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false);
+ checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
}
- return newInstance0();
- }
- private T newInstance0()
- throws InstantiationException, IllegalAccessException
- {
// NOTE: the following code may not be strictly correct under
// the current Java memory model.
@@ -432,7 +432,7 @@
// Security check (same as in java.lang.reflect.Constructor)
int modifiers = tmpConstructor.getModifiers();
if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
- Class<?> caller = Reflection.getCallerClass(3);
+ Class<?> caller = Reflection.getCallerClass();
if (newInstanceCallerCache != caller) {
Reflection.ensureMemberAccess(caller, this, null, modifiers);
newInstanceCallerCache = caller;
@@ -674,16 +674,14 @@
* @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission
*/
+ @CallerSensitive
public ClassLoader getClassLoader() {
ClassLoader cl = getClassLoader0();
if (cl == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- ClassLoader ccl = ClassLoader.getCallerClassLoader();
- if (ClassLoader.needsClassLoaderPermissionCheck(ccl, cl)) {
- sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
- }
+ ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
}
return cl;
}
@@ -1392,11 +1390,9 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Class<?>[] getClasses() {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false);
+ checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
// Privileged so this implementation can look at DECLARED classes,
// something the caller might not have privilege to do. The code here
@@ -1467,11 +1463,9 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Field[] getFields() throws SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
+ checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyFields(privateGetPublicFields(null));
}
@@ -1518,11 +1512,9 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Method[] getMethods() throws SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
+ checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyMethods(privateGetPublicMethods());
}
@@ -1567,11 +1559,9 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Constructor<?>[] getConstructors() throws SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
+ checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyConstructors(privateGetDeclaredConstructors(true));
}
@@ -1625,12 +1615,10 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Field getField(String name)
throws NoSuchFieldException, SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
+ checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
Field field = getField0(name);
if (field == null) {
throw new NoSuchFieldException(name);
@@ -1710,12 +1698,10 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
+ checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
Method method = getMethod0(name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
@@ -1764,12 +1750,10 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Constructor<T> getConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
+ checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return getConstructor0(parameterTypes, Member.PUBLIC);
}
@@ -1807,11 +1791,9 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Class<?>[] getDeclaredClasses() throws SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), false);
+ checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false);
return getDeclaredClasses0();
}
@@ -1851,11 +1833,9 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Field[] getDeclaredFields() throws SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
+ checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyFields(privateGetDeclaredFields(false));
}
@@ -1899,11 +1879,9 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
+ checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyMethods(privateGetDeclaredMethods(false));
}
@@ -1944,11 +1922,9 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
+ checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyConstructors(privateGetDeclaredConstructors(false));
}
@@ -1987,12 +1963,10 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Field getDeclaredField(String name)
throws NoSuchFieldException, SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
+ checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
Field field = searchFields(privateGetDeclaredFields(false), name);
if (field == null) {
throw new NoSuchFieldException(name);
@@ -2042,12 +2016,10 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
+ checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
@@ -2092,12 +2064,10 @@
*
* @since JDK1.1
*/
+ @CallerSensitive
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
- // be very careful not to change the stack depth of this
- // checkMemberAccess call for security reasons
- // see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
+ checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return getConstructor0(parameterTypes, Member.DECLARED);
}
@@ -2255,23 +2225,40 @@
*/
static native Class<?> getPrimitiveClass(String name);
+ private static boolean isCheckMemberAccessOverridden(SecurityManager smgr) {
+ if (smgr.getClass() == SecurityManager.class) return false;
+
+ Class<?>[] paramTypes = new Class<?>[] {Class.class, int.class};
+ return smgr.getClass().getMethod0("checkMemberAccess", paramTypes).
+ getDeclaringClass() != SecurityManager.class;
+ }
/*
* Check if client is allowed to access members. If access is denied,
* throw a SecurityException.
*
- * Be very careful not to change the stack depth of this checkMemberAccess
- * call for security reasons.
- * See java.lang.SecurityManager.checkMemberAccess.
- *
* <p> Default policy: allow all clients access with normal Java access
* control.
*/
- private void checkMemberAccess(int which, ClassLoader ccl, boolean checkProxyInterfaces) {
- SecurityManager s = System.getSecurityManager();
+ private void checkMemberAccess(int which, Class<?> caller, boolean checkProxyInterfaces) {
+ final SecurityManager s = System.getSecurityManager();
if (s != null) {
- s.checkMemberAccess(this, which);
- ClassLoader cl = getClassLoader0();
+ final ClassLoader ccl = ClassLoader.getClassLoader(caller);
+ final ClassLoader cl = getClassLoader0();
+ if (!isCheckMemberAccessOverridden(s)) {
+ // Inlined SecurityManager.checkMemberAccess
+ if (which != Member.PUBLIC) {
+ if (ccl != cl) {
+ s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
+ }
+ }
+ } else {
+ // Don't refactor; otherwise break the stack depth for
+ // checkMemberAccess of subclasses of SecurityManager as specified.
+ s.checkMemberAccess(this, which);
+ }
+
+
if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
String name = this.getName();
int i = name.lastIndexOf('.');
--- a/jdk/src/share/classes/java/lang/ClassLoader.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java Wed Apr 17 02:53:02 2013 -0700
@@ -55,6 +55,7 @@
import sun.misc.Resource;
import sun.misc.URLClassPath;
import sun.misc.VM;
+import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;
@@ -1159,11 +1160,6 @@
return java.util.Collections.emptyEnumeration();
}
- // index 0: java.lang.ClassLoader.class
- // index 1: the immediate caller of index 0.
- // index 2: the immediate caller of index 1.
- private static native Class<? extends ClassLoader> getCaller(int index);
-
/**
* Registers the caller as parallel capable.</p>
* The registration succeeds if and only if all of the following
@@ -1179,8 +1175,11 @@
*
* @since 1.7
*/
+ @CallerSensitive
protected static boolean registerAsParallelCapable() {
- return ParallelLoaders.register(getCaller(1));
+ Class<? extends ClassLoader> callerClass =
+ Reflection.getCallerClass().asSubclass(ClassLoader.class);
+ return ParallelLoaders.register(callerClass);
}
/**
@@ -1340,15 +1339,13 @@
*
* @since 1.2
*/
+ @CallerSensitive
public final ClassLoader getParent() {
if (parent == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- ClassLoader ccl = getCallerClassLoader();
- if (needsClassLoaderPermissionCheck(ccl, this)) {
- sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
- }
+ checkClassLoaderPermission(this, Reflection.getCallerClass());
}
return parent;
}
@@ -1408,6 +1405,7 @@
*
* @revised 1.4
*/
+ @CallerSensitive
public static ClassLoader getSystemClassLoader() {
initSystemClassLoader();
if (scl == null) {
@@ -1415,10 +1413,7 @@
}
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- ClassLoader ccl = getCallerClassLoader();
- if (needsClassLoaderPermissionCheck(ccl, scl)) {
- sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
- }
+ checkClassLoaderPermission(scl, Reflection.getCallerClass());
}
return scl;
}
@@ -1471,8 +1466,8 @@
// class loader 'from' is same as class loader 'to' or an ancestor
// of 'to'. The class loader in a system domain can access
// any class loader.
- static boolean needsClassLoaderPermissionCheck(ClassLoader from,
- ClassLoader to)
+ private static boolean needsClassLoaderPermissionCheck(ClassLoader from,
+ ClassLoader to)
{
if (from == to)
return false;
@@ -1483,13 +1478,8 @@
return !to.isAncestor(from);
}
- // Returns the invoker's class loader, or null if none.
- // NOTE: This must always be invoked when there is exactly one intervening
- // frame from the core libraries on the stack between this method's
- // invocation and the desired invoker.
- static ClassLoader getCallerClassLoader() {
- // NOTE use of more generic Reflection.getCallerClass()
- Class<?> caller = Reflection.getCallerClass(3);
+ // Returns the class's class loader, or null if none.
+ static ClassLoader getClassLoader(Class<?> caller) {
// This can be null if the VM is requesting it
if (caller == null) {
return null;
@@ -1498,6 +1488,17 @@
return caller.getClassLoader0();
}
+ static void checkClassLoaderPermission(ClassLoader cl, Class<?> caller) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ // caller can be null if the VM is requesting it
+ ClassLoader ccl = getClassLoader(caller);
+ if (needsClassLoaderPermissionCheck(ccl, cl)) {
+ sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
+ }
+ }
+ }
+
// The class loader for the system
// @GuardedBy("ClassLoader.class")
private static ClassLoader scl;
--- a/jdk/src/share/classes/java/lang/Package.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Package.java Wed Apr 17 02:53:02 2013 -0700
@@ -49,6 +49,8 @@
import java.util.Iterator;
import sun.net.www.ParseUtil;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
import java.lang.annotation.Annotation;
@@ -273,8 +275,9 @@
* @return the package of the requested name. It may be null if no package
* information is available from the archive or codebase.
*/
+ @CallerSensitive
public static Package getPackage(String name) {
- ClassLoader l = ClassLoader.getCallerClassLoader();
+ ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
if (l != null) {
return l.getPackage(name);
} else {
@@ -294,8 +297,9 @@
* @return a new array of packages known to the callers {@code ClassLoader}
* instance. An zero length array is returned if none are known.
*/
+ @CallerSensitive
public static Package[] getPackages() {
- ClassLoader l = ClassLoader.getCallerClassLoader();
+ ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
if (l != null) {
return l.getPackages();
} else {
--- a/jdk/src/share/classes/java/lang/ProcessBuilder.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/ProcessBuilder.java Wed Apr 17 02:53:02 2013 -0700
@@ -30,6 +30,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
+import java.security.AccessControlException;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
@@ -1024,13 +1025,24 @@
redirects,
redirectErrorStream);
} catch (IOException e) {
+ String exceptionInfo = ": " + e.getMessage();
+ Throwable cause = e;
+ if (security != null) {
+ // Can not disclose the fail reason for read-protected files.
+ try {
+ security.checkRead(prog);
+ } catch (AccessControlException ace) {
+ exceptionInfo = "";
+ cause = ace;
+ }
+ }
// It's much easier for us to create a high-quality error
// message than the low-level C code which found the problem.
throw new IOException(
"Cannot run program \"" + prog + "\""
+ (dir == null ? "" : " (in directory \"" + dir + "\")")
- + ": " + e.getMessage(),
- e);
+ + exceptionInfo,
+ cause);
}
}
}
--- a/jdk/src/share/classes/java/lang/Runtime.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Runtime.java Wed Apr 17 02:53:02 2013 -0700
@@ -27,6 +27,8 @@
import java.io.*;
import java.util.StringTokenizer;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
/**
* Every Java application has a single instance of class
@@ -790,8 +792,9 @@
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkLink(java.lang.String)
*/
+ @CallerSensitive
public void load(String filename) {
- load0(System.getCallerClass(), filename);
+ load0(Reflection.getCallerClass(), filename);
}
synchronized void load0(Class<?> fromClass, String filename) {
@@ -850,8 +853,9 @@
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkLink(java.lang.String)
*/
+ @CallerSensitive
public void loadLibrary(String libname) {
- loadLibrary0(System.getCallerClass(), libname);
+ loadLibrary0(Reflection.getCallerClass(), libname);
}
synchronized void loadLibrary0(Class<?> fromClass, String libname) {
--- a/jdk/src/share/classes/java/lang/SecurityManager.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/SecurityManager.java Wed Apr 17 02:53:02 2013 -0700
@@ -36,10 +36,10 @@
import java.net.NetPermission;
import java.util.Hashtable;
import java.net.InetAddress;
-import java.lang.reflect.Member;
import java.lang.reflect.*;
import java.net.URL;
+import sun.reflect.CallerSensitive;
import sun.security.util.SecurityConstants;
/**
@@ -1679,6 +1679,7 @@
* @since JDK1.1
* @see #checkPermission(java.security.Permission) checkPermission
*/
+ @CallerSensitive
public void checkMemberAccess(Class<?> clazz, int which) {
if (clazz == null) {
throw new NullPointerException("class can't be null");
--- a/jdk/src/share/classes/java/lang/System.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/System.java Wed Apr 17 02:53:02 2013 -0700
@@ -35,6 +35,7 @@
import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider;
import sun.nio.ch.Interruptible;
+import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;
import sun.reflect.annotation.AnnotationType;
@@ -1072,8 +1073,9 @@
* @see java.lang.Runtime#load(java.lang.String)
* @see java.lang.SecurityManager#checkLink(java.lang.String)
*/
+ @CallerSensitive
public static void load(String filename) {
- Runtime.getRuntime().load0(getCallerClass(), filename);
+ Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
}
/**
@@ -1107,8 +1109,9 @@
* @see java.lang.Runtime#loadLibrary(java.lang.String)
* @see java.lang.SecurityManager#checkLink(java.lang.String)
*/
+ @CallerSensitive
public static void loadLibrary(String libname) {
- Runtime.getRuntime().loadLibrary0(getCallerClass(), libname);
+ Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
}
/**
@@ -1245,10 +1248,4 @@
}
});
}
-
- /* returns the class of the caller. */
- static Class<?> getCallerClass() {
- // NOTE use of more generic Reflection.getCallerClass()
- return Reflection.getCallerClass(3);
- }
}
--- a/jdk/src/share/classes/java/lang/Thread.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Thread.java Wed Apr 17 02:53:02 2013 -0700
@@ -37,6 +37,8 @@
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.LockSupport;
import sun.nio.ch.Interruptible;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;
@@ -1443,15 +1445,14 @@
*
* @since 1.2
*/
+ @CallerSensitive
public ClassLoader getContextClassLoader() {
if (contextClassLoader == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- ClassLoader ccl = ClassLoader.getCallerClassLoader();
- if (ClassLoader.needsClassLoaderPermissionCheck(ccl, contextClassLoader)) {
- sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
- }
+ ClassLoader.checkClassLoaderPermission(contextClassLoader,
+ Reflection.getCallerClass());
}
return contextClassLoader;
}
--- a/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java Wed Apr 17 02:53:02 2013 -0700
@@ -709,7 +709,9 @@
InvokerBytecodeGenerator.maybeDump(className, classFile);
Class<? extends BoundMethodHandle> bmhClass =
//UNSAFE.defineAnonymousClass(BoundMethodHandle.class, classFile, null).asSubclass(BoundMethodHandle.class);
- UNSAFE.defineClass(className, classFile, 0, classFile.length).asSubclass(BoundMethodHandle.class);
+ UNSAFE.defineClass(className, classFile, 0, classFile.length,
+ BoundMethodHandle.class.getClassLoader(), null)
+ .asSubclass(BoundMethodHandle.class);
UNSAFE.ensureClassInitialized(bmhClass);
return bmhClass;
--- a/jdk/src/share/classes/java/lang/invoke/MemberName.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MemberName.java Wed Apr 17 02:53:02 2013 -0700
@@ -391,10 +391,11 @@
// private flags, not part of RECOGNIZED_MODIFIERS:
static final int
- IS_METHOD = MN_IS_METHOD, // method (not constructor)
- IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
- IS_FIELD = MN_IS_FIELD, // field
- IS_TYPE = MN_IS_TYPE; // nested type
+ IS_METHOD = MN_IS_METHOD, // method (not constructor)
+ IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
+ IS_FIELD = MN_IS_FIELD, // field
+ IS_TYPE = MN_IS_TYPE, // nested type
+ CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
@@ -430,6 +431,10 @@
public boolean isPackage() {
return !testAnyFlags(ALL_ACCESS);
}
+ /** Query whether this member has a CallerSensitive annotation. */
+ public boolean isCallerSensitive() {
+ return testAllFlags(CALLER_SENSITIVE);
+ }
/** Utility method to query whether this member is accessible from a given lookup class. */
public boolean isAccessibleFrom(Class<?> lookupClass) {
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Apr 17 02:53:02 2013 -0700
@@ -34,6 +34,8 @@
import sun.invoke.util.ValueConversions;
import sun.invoke.util.VerifyType;
import sun.invoke.util.Wrapper;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
import static java.lang.invoke.LambdaForm.*;
import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
@@ -891,9 +893,11 @@
}
}
+ @CallerSensitive
private static boolean checkCallerClass(Class<?> expected, Class<?> expected2) {
- final int FRAME_COUNT_ARG = 2; // [0] Reflection [1] BindCaller [2] Expected
- Class<?> actual = sun.reflect.Reflection.getCallerClass(FRAME_COUNT_ARG);
+ // This method is called via MH_checkCallerClass and so it's
+ // correct to ask for the immediate caller here.
+ Class<?> actual = Reflection.getCallerClass();
if (actual != expected && actual != expected2)
throw new InternalError("found "+actual.getName()+", expected "+expected.getName()
+(expected == expected2 ? "" : ", or else "+expected2.getName()));
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java Wed Apr 17 02:53:02 2013 -0700
@@ -26,7 +26,6 @@
package java.lang.invoke;
import java.lang.invoke.MethodHandles.Lookup;
-import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandleStatics.*;
@@ -34,7 +33,7 @@
/**
* The JVM interface for the method handles package is all here.
- * This is an interface internal and private to an implemetantion of JSR 292.
+ * This is an interface internal and private to an implementation of JSR 292.
* <em>This class is not part of the JSR 292 standard.</em>
* @author jrose
*/
@@ -101,6 +100,7 @@
MN_IS_CONSTRUCTOR = 0x00020000, // constructor
MN_IS_FIELD = 0x00040000, // field
MN_IS_TYPE = 0x00080000, // nested type
+ MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected
MN_REFERENCE_KIND_SHIFT = 24, // refKind
MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
// The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers:
@@ -391,129 +391,24 @@
* I.e., does it call Reflection.getCallerClass or a similer method
* to ask about the identity of its caller?
*/
- // FIXME: Replace this pattern match by an annotation @sun.reflect.CallerSensitive.
static boolean isCallerSensitive(MemberName mem) {
if (!mem.isInvocable()) return false; // fields are not caller sensitive
+
+ return mem.isCallerSensitive() || canBeCalledVirtual(mem);
+ }
+
+ static boolean canBeCalledVirtual(MemberName mem) {
+ assert(mem.isInvocable());
Class<?> defc = mem.getDeclaringClass();
switch (mem.getName()) {
- case "doPrivileged":
- case "doPrivilegedWithCombiner":
- return defc == java.security.AccessController.class;
case "checkMemberAccess":
return canBeCalledVirtual(mem, java.lang.SecurityManager.class);
- case "getUnsafe":
- return defc == sun.misc.Unsafe.class;
- case "lookup":
- return defc == java.lang.invoke.MethodHandles.class;
- case "findStatic":
- case "findVirtual":
- case "findConstructor":
- case "findSpecial":
- case "findGetter":
- case "findSetter":
- case "findStaticGetter":
- case "findStaticSetter":
- case "bind":
- case "unreflect":
- case "unreflectSpecial":
- case "unreflectConstructor":
- case "unreflectGetter":
- case "unreflectSetter":
- return defc == java.lang.invoke.MethodHandles.Lookup.class;
- case "invoke":
- return defc == java.lang.reflect.Method.class;
- case "get":
- case "getBoolean":
- case "getByte":
- case "getChar":
- case "getShort":
- case "getInt":
- case "getLong":
- case "getFloat":
- case "getDouble":
- case "set":
- case "setBoolean":
- case "setByte":
- case "setChar":
- case "setShort":
- case "setInt":
- case "setLong":
- case "setFloat":
- case "setDouble":
- return defc == java.lang.reflect.Field.class;
- case "newInstance":
- if (defc == java.lang.reflect.Constructor.class) return true;
- if (defc == java.lang.Class.class) return true;
- break;
- case "forName":
- case "getClassLoader":
- case "getClasses":
- case "getFields":
- case "getMethods":
- case "getConstructors":
- case "getDeclaredClasses":
- case "getDeclaredFields":
- case "getDeclaredMethods":
- case "getDeclaredConstructors":
- case "getField":
- case "getMethod":
- case "getConstructor":
- case "getDeclaredField":
- case "getDeclaredMethod":
- case "getDeclaredConstructor":
- return defc == java.lang.Class.class;
- case "getConnection":
- case "getDriver":
- case "getDrivers":
- case "deregisterDriver":
- return defc == getClass("java.sql.DriverManager");
- case "newUpdater":
- if (defc == java.util.concurrent.atomic.AtomicIntegerFieldUpdater.class) return true;
- if (defc == java.util.concurrent.atomic.AtomicLongFieldUpdater.class) return true;
- if (defc == java.util.concurrent.atomic.AtomicReferenceFieldUpdater.class) return true;
- break;
case "getContextClassLoader":
return canBeCalledVirtual(mem, java.lang.Thread.class);
- case "getPackage":
- case "getPackages":
- return defc == java.lang.Package.class;
- case "getParent":
- case "getSystemClassLoader":
- return defc == java.lang.ClassLoader.class;
- case "load":
- case "loadLibrary":
- if (defc == java.lang.Runtime.class) return true;
- if (defc == java.lang.System.class) return true;
- break;
- case "getCallerClass":
- if (defc == sun.reflect.Reflection.class) return true;
- if (defc == java.lang.System.class) return true;
- break;
- case "getCallerClassLoader":
- return defc == java.lang.ClassLoader.class;
- case "registerAsParallelCapable":
- return canBeCalledVirtual(mem, java.lang.ClassLoader.class);
- case "getProxyClass":
- case "newProxyInstance":
- return defc == java.lang.reflect.Proxy.class;
- case "asInterfaceInstance":
- return defc == java.lang.invoke.MethodHandleProxies.class;
- case "getBundle":
- case "clearCache":
- return defc == java.util.ResourceBundle.class;
}
return false;
}
- // avoid static dependency to a class in other modules
- private static Class<?> getClass(String cn) {
- try {
- return Class.forName(cn, false,
- MethodHandleNatives.class.getClassLoader());
- } catch (ClassNotFoundException e) {
- throw new InternalError(e);
- }
- }
static boolean canBeCalledVirtual(MemberName symbolicRef, Class<?> definingClass) {
Class<?> symbolicRefClass = symbolicRef.getDeclaringClass();
if (symbolicRefClass == definingClass) return true;
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java Wed Apr 17 02:53:02 2013 -0700
@@ -30,6 +30,7 @@
import java.security.PrivilegedAction;
import sun.invoke.WrapperInstance;
import java.util.ArrayList;
+import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
@@ -137,14 +138,14 @@
// entry points, must be covered by hand-written or automatically
// generated adapter classes.
//
+ @CallerSensitive
public static
<T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
throw new IllegalArgumentException("not a public interface: "+intfc.getName());
final MethodHandle mh;
if (System.getSecurityManager() != null) {
- final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller
- final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
+ final Class<?> caller = Reflection.getCallerClass();
final ClassLoader ccl = caller != null ? caller.getClassLoader() : null;
ReflectUtil.checkProxyPackageAccess(ccl, intfc);
mh = ccl != null ? bindCaller(target, caller) : target;
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Wed Apr 17 02:53:02 2013 -0700
@@ -26,13 +26,17 @@
package java.lang.invoke;
import java.lang.reflect.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
import sun.invoke.util.ValueConversions;
import sun.invoke.util.VerifyAccess;
import sun.invoke.util.Wrapper;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
+import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
+import sun.security.util.SecurityConstants;
import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
@@ -65,8 +69,9 @@
* This lookup object is a <em>capability</em> which may be delegated to trusted agents.
* Do not store it in place where untrusted code can access it.
*/
+ @CallerSensitive
public static Lookup lookup() {
- return new Lookup();
+ return new Lookup(Reflection.getCallerClass());
}
/**
@@ -416,20 +421,13 @@
* for method handle creation.
* Must be called by from a method in this package,
* which in turn is called by a method not in this package.
- * <p>
- * Also, don't make it private, lest javac interpose
- * an access$N method.
*/
- Lookup() {
- this(getCallerClassAtEntryPoint(false), ALL_MODES);
+ Lookup(Class<?> lookupClass) {
+ this(lookupClass, ALL_MODES);
// make sure we haven't accidentally picked up a privileged class:
checkUnprivilegedlookupClass(lookupClass);
}
- Lookup(Class<?> lookupClass) {
- this(lookupClass, ALL_MODES);
- }
-
private Lookup(Class<?> lookupClass, int allowedModes) {
this.lookupClass = lookupClass;
this.allowedModes = allowedModes;
@@ -554,20 +552,6 @@
}
}
- /* Obtain the external caller class, when called from Lookup.<init> or a first-level subroutine. */
- private static Class<?> getCallerClassAtEntryPoint(boolean inSubroutine) {
- final int CALLER_DEPTH = 4;
- // Stack for the constructor entry point (inSubroutine=false):
- // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint,
- // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller
- // The stack is slightly different for a subroutine of a Lookup.find* method:
- // 2: Lookup.*, 3: Lookup.find*.*, 4: caller
- // Note: This should be the only use of getCallerClass in this file.
- assert(Reflection.getCallerClass(CALLER_DEPTH-2) == Lookup.class);
- assert(Reflection.getCallerClass(CALLER_DEPTH-1) == (inSubroutine ? Lookup.class : MethodHandles.class));
- return Reflection.getCallerClass(CALLER_DEPTH);
- }
-
/**
* Produces a method handle for a static method.
* The type of the method handle will be that of the method.
@@ -594,12 +578,14 @@
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
*/
+ @CallerSensitive
public
MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type);
- checkSecurityManager(refc, method); // stack walk magic: do not refactor
- Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor
- return getDirectMethod(REF_invokeStatic, refc, method, callerClass);
+ Class<?> callerClass = Reflection.getCallerClass();
+ checkSecurityManager(refc, method, callerClass);
+ return getDirectMethod(REF_invokeStatic, refc, method,
+ findBoundCallerClass(method, callerClass));
}
/**
@@ -645,6 +631,7 @@
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
*/
+ @CallerSensitive
public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
if (refc == MethodHandle.class) {
MethodHandle mh = findVirtualForMH(name, type);
@@ -652,9 +639,10 @@
}
byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
MemberName method = resolveOrFail(refKind, refc, name, type);
- checkSecurityManager(refc, method); // stack walk magic: do not refactor
- Class<?> callerClass = findBoundCallerClass(method);
- return getDirectMethod(refKind, refc, method, callerClass);
+ Class<?> callerClass = Reflection.getCallerClass();
+ checkSecurityManager(refc, method, callerClass);
+ return getDirectMethod(refKind, refc, method,
+ findBoundCallerClass(method, callerClass));
}
private MethodHandle findVirtualForMH(String name, MethodType type) {
// these names require special lookups because of the implicit MethodType argument
@@ -691,10 +679,11 @@
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
*/
+ @CallerSensitive
public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
String name = "<init>";
MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
- checkSecurityManager(refc, ctor); // stack walk magic: do not refactor
+ checkSecurityManager(refc, ctor, Reflection.getCallerClass());
return getDirectConstructor(refc, ctor);
}
@@ -732,14 +721,16 @@
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
*/
+ @CallerSensitive
public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
checkSpecialCaller(specialCaller);
Lookup specialLookup = this.in(specialCaller);
MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type);
- checkSecurityManager(refc, method); // stack walk magic: do not refactor
- Class<?> callerClass = findBoundCallerClass(method);
- return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, callerClass);
+ Class<?> callerClass = Reflection.getCallerClass();
+ checkSecurityManager(refc, method, callerClass);
+ return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method,
+ findBoundCallerClass(method, callerClass));
}
/**
@@ -759,9 +750,10 @@
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
*/
+ @CallerSensitive
public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(REF_getField, refc, name, type);
- checkSecurityManager(refc, field); // stack walk magic: do not refactor
+ checkSecurityManager(refc, field, Reflection.getCallerClass());
return getDirectField(REF_getField, refc, field);
}
@@ -782,9 +774,10 @@
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
*/
+ @CallerSensitive
public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(REF_putField, refc, name, type);
- checkSecurityManager(refc, field); // stack walk magic: do not refactor
+ checkSecurityManager(refc, field, Reflection.getCallerClass());
return getDirectField(REF_putField, refc, field);
}
@@ -804,9 +797,10 @@
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
*/
+ @CallerSensitive
public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(REF_getStatic, refc, name, type);
- checkSecurityManager(refc, field); // stack walk magic: do not refactor
+ checkSecurityManager(refc, field, Reflection.getCallerClass());
return getDirectField(REF_getStatic, refc, field);
}
@@ -826,9 +820,10 @@
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
*/
+ @CallerSensitive
public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(REF_putStatic, refc, name, type);
- checkSecurityManager(refc, field); // stack walk magic: do not refactor
+ checkSecurityManager(refc, field, Reflection.getCallerClass());
return getDirectField(REF_putStatic, refc, field);
}
@@ -878,12 +873,14 @@
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
*/
+ @CallerSensitive
public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
Class<? extends Object> refc = receiver.getClass(); // may get NPE
MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type);
- checkSecurityManager(refc, method); // stack walk magic: do not refactor
- Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor
- MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, callerClass);
+ Class<?> callerClass = Reflection.getCallerClass();
+ checkSecurityManager(refc, method, callerClass);
+ MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method,
+ findBoundCallerClass(method, callerClass));
return mh.bindReceiver(receiver).setVarargs(method);
}
@@ -908,13 +905,14 @@
* is set and {@code asVarargsCollector} fails
* @throws NullPointerException if the argument is null
*/
+ @CallerSensitive
public MethodHandle unreflect(Method m) throws IllegalAccessException {
MemberName method = new MemberName(m);
byte refKind = method.getReferenceKind();
if (refKind == REF_invokeSpecial)
refKind = REF_invokeVirtual;
assert(method.isMethod());
- Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor
+ Class<?> callerClass = findBoundCallerClass(method, Reflection.getCallerClass());
Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this;
return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass);
}
@@ -940,12 +938,13 @@
* is set and {@code asVarargsCollector} fails
* @throws NullPointerException if any argument is null
*/
+ @CallerSensitive
public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
checkSpecialCaller(specialCaller);
Lookup specialLookup = this.in(specialCaller);
MemberName method = new MemberName(m, true);
assert(method.isMethod());
- Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor
+ Class<?> callerClass = findBoundCallerClass(method, Reflection.getCallerClass());
// ignore m.isAccessible: this is a new kind of access
return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass);
}
@@ -1050,20 +1049,35 @@
* If this lookup object has private access, then the caller class is the lookupClass.
* Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual).
* This is the same caller class as is used by checkSecurityManager.
- * This function performs stack walk magic: do not refactor it.
*/
- Class<?> findBoundCallerClass(MemberName m) {
+ Class<?> findBoundCallerClass(MemberName m, Class<?> callerAtEntryPoint) {
Class<?> callerClass = null;
if (MethodHandleNatives.isCallerSensitive(m)) {
// Do not refactor this to a more "logical" place, since it is stack walk magic.
// Note that this is the same expression as in Step 2 below in checkSecurityManager.
callerClass = ((allowedModes & PRIVATE) != 0
? lookupClass // for strong access modes, no extra check
- // next line does stack walk magic; do not refactor:
- : getCallerClassAtEntryPoint(true));
+ : callerAtEntryPoint);
}
return callerClass;
}
+
+ /**
+ * Determine whether a security manager has an overridden
+ * SecurityManager.checkMemberAccess method.
+ */
+ private boolean isCheckMemberAccessOverridden(SecurityManager sm) {
+ final Class<? extends SecurityManager> cls = sm.getClass();
+ if (cls == SecurityManager.class) return false;
+
+ try {
+ return cls.getMethod("checkMemberAccess", Class.class, int.class).
+ getDeclaringClass() != SecurityManager.class;
+ } catch (NoSuchMethodException e) {
+ throw new InternalError("should not reach here");
+ }
+ }
+
/**
* Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>.
* Determines a trustable caller class to compare with refc, the symbolic reference class.
@@ -1071,46 +1085,55 @@
* Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual).
* This function performs stack walk magic: do not refactor it.
*/
- void checkSecurityManager(Class<?> refc, MemberName m) {
+ void checkSecurityManager(Class<?> refc, MemberName m, Class<?> caller) {
SecurityManager smgr = System.getSecurityManager();
if (smgr == null) return;
if (allowedModes == TRUSTED) return;
+
+ final boolean overridden = isCheckMemberAccessOverridden(smgr);
// Step 1:
- smgr.checkMemberAccess(refc, Member.PUBLIC);
+ {
+ // Default policy is to allow Member.PUBLIC; no need to check
+ // permission if SecurityManager is the default implementation
+ final int which = Member.PUBLIC;
+ final Class<?> clazz = refc;
+ if (overridden) {
+ // Don't refactor; otherwise break the stack depth for
+ // checkMemberAccess of subclasses of SecurityManager as specified.
+ smgr.checkMemberAccess(clazz, which);
+ }
+ }
+
// Step 2:
Class<?> callerClass = ((allowedModes & PRIVATE) != 0
? lookupClass // for strong access modes, no extra check
- // next line does stack walk magic; do not refactor:
- : getCallerClassAtEntryPoint(true));
+ : caller);
if (!VerifyAccess.classLoaderIsAncestor(lookupClass, refc) ||
(callerClass != lookupClass &&
!VerifyAccess.classLoaderIsAncestor(callerClass, refc)))
smgr.checkPackageAccess(VerifyAccess.getPackageName(refc));
+
// Step 3:
if (m.isPublic()) return;
Class<?> defc = m.getDeclaringClass();
- smgr.checkMemberAccess(defc, Member.DECLARED); // STACK WALK HERE
+ {
+ // Inline SecurityManager.checkMemberAccess
+ final int which = Member.DECLARED;
+ final Class<?> clazz = defc;
+ if (!overridden) {
+ if (caller.getClassLoader() != clazz.getClassLoader()) {
+ smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
+ }
+ } else {
+ // Don't refactor; otherwise break the stack depth for
+ // checkMemberAccess of subclasses of SecurityManager as specified.
+ smgr.checkMemberAccess(clazz, which);
+ }
+ }
+
// Step 4:
if (defc != refc)
smgr.checkPackageAccess(VerifyAccess.getPackageName(defc));
-
- // Comment from SM.checkMemberAccess, where which=DECLARED:
- /*
- * stack depth of 4 should be the caller of one of the
- * methods in java.lang.Class that invoke checkMember
- * access. The stack should look like:
- *
- * someCaller [3]
- * java.lang.Class.someReflectionAPI [2]
- * java.lang.Class.checkMemberAccess [1]
- * SecurityManager.checkMemberAccess [0]
- *
- */
- // For us it is this stack:
- // someCaller [3]
- // Lookup.findSomeMember [2]
- // Lookup.checkSecurityManager [1]
- // SecurityManager.checkMemberAccess [0]
}
void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
@@ -1237,6 +1260,30 @@
checkMethod(refKind, refc, method);
if (method.isMethodHandleInvoke())
return fakeMethodHandleInvoke(method);
+
+ Class<?> refcAsSuper;
+ if (refKind == REF_invokeSpecial &&
+ refc != lookupClass() &&
+ refc != (refcAsSuper = lookupClass().getSuperclass()) &&
+ refc.isAssignableFrom(lookupClass())) {
+ assert(!method.getName().equals("<init>")); // not this code path
+ // Per JVMS 6.5, desc. of invokespecial instruction:
+ // If the method is in a superclass of the LC,
+ // and if our original search was above LC.super,
+ // repeat the search (symbolic lookup) from LC.super.
+ // FIXME: MemberName.resolve should handle this instead.
+ MemberName m2 = new MemberName(refcAsSuper,
+ method.getName(),
+ method.getMethodType(),
+ REF_invokeSpecial);
+ m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull());
+ if (m2 == null) throw new InternalError(method.toString());
+ method = m2;
+ refc = refcAsSuper;
+ // redo basic checks
+ checkMethod(refKind, refc, method);
+ }
+
MethodHandle mh = DirectMethodHandle.make(refKind, refc, method);
mh = maybeBindCaller(method, mh, callerClass);
mh = mh.setVarargs(method);
--- a/jdk/src/share/classes/java/lang/ref/Finalizer.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/ref/Finalizer.java Wed Apr 17 02:53:02 2013 -0700
@@ -38,9 +38,9 @@
*/
static native void invokeFinalizeMethod(Object o) throws Throwable;
- static private ReferenceQueue queue = new ReferenceQueue();
- static private Finalizer unfinalized = null;
- static private Object lock = new Object();
+ private static ReferenceQueue queue = new ReferenceQueue();
+ private static Finalizer unfinalized = null;
+ private static final Object lock = new Object();
private Finalizer
next = null,
@@ -142,7 +142,11 @@
/* Called by Runtime.runFinalization() */
static void runFinalization() {
forkSecondaryFinalizer(new Runnable() {
+ private volatile boolean running;
public void run() {
+ if (running)
+ return;
+ running = true;
for (;;) {
Finalizer f = (Finalizer)queue.poll();
if (f == null) break;
@@ -155,7 +159,11 @@
/* Invoked by java.lang.Shutdown */
static void runAllFinalizers() {
forkSecondaryFinalizer(new Runnable() {
+ private volatile boolean running;
public void run() {
+ if (running)
+ return;
+ running = true;
for (;;) {
Finalizer f;
synchronized (lock) {
@@ -168,10 +176,14 @@
}
private static class FinalizerThread extends Thread {
+ private volatile boolean running;
FinalizerThread(ThreadGroup g) {
super(g, "Finalizer");
}
public void run() {
+ if (running)
+ return;
+ running = true;
for (;;) {
try {
Finalizer f = (Finalizer)queue.remove();
--- a/jdk/src/share/classes/java/lang/reflect/Constructor.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/Constructor.java Wed Apr 17 02:53:02 2013 -0700
@@ -25,6 +25,7 @@
package java.lang.reflect;
+import sun.reflect.CallerSensitive;
import sun.reflect.ConstructorAccessor;
import sun.reflect.Reflection;
import sun.reflect.generics.repository.ConstructorRepository;
@@ -392,14 +393,14 @@
* @exception ExceptionInInitializerError if the initialization provoked
* by this method fails.
*/
+ @CallerSensitive
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- Class<?> caller = Reflection.getCallerClass(2);
-
+ Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
--- a/jdk/src/share/classes/java/lang/reflect/Field.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/Field.java Wed Apr 17 02:53:02 2013 -0700
@@ -25,6 +25,7 @@
package java.lang.reflect;
+import sun.reflect.CallerSensitive;
import sun.reflect.FieldAccessor;
import sun.reflect.Reflection;
import sun.reflect.generics.repository.FieldRepository;
@@ -376,9 +377,16 @@
* @exception ExceptionInInitializerError if the initialization provoked
* by this method fails.
*/
+ @CallerSensitive
public Object get(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
return getFieldAccessor(obj).get(obj);
}
@@ -404,9 +412,16 @@
* by this method fails.
* @see Field#get
*/
+ @CallerSensitive
public boolean getBoolean(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
return getFieldAccessor(obj).getBoolean(obj);
}
@@ -432,9 +447,16 @@
* by this method fails.
* @see Field#get
*/
+ @CallerSensitive
public byte getByte(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
return getFieldAccessor(obj).getByte(obj);
}
@@ -462,9 +484,16 @@
* by this method fails.
* @see Field#get
*/
+ @CallerSensitive
public char getChar(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
return getFieldAccessor(obj).getChar(obj);
}
@@ -492,9 +521,16 @@
* by this method fails.
* @see Field#get
*/
+ @CallerSensitive
public short getShort(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
return getFieldAccessor(obj).getShort(obj);
}
@@ -522,9 +558,16 @@
* by this method fails.
* @see Field#get
*/
+ @CallerSensitive
public int getInt(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
return getFieldAccessor(obj).getInt(obj);
}
@@ -552,9 +595,16 @@
* by this method fails.
* @see Field#get
*/
+ @CallerSensitive
public long getLong(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
return getFieldAccessor(obj).getLong(obj);
}
@@ -582,9 +632,16 @@
* by this method fails.
* @see Field#get
*/
+ @CallerSensitive
public float getFloat(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
return getFieldAccessor(obj).getFloat(obj);
}
@@ -612,9 +669,16 @@
* by this method fails.
* @see Field#get
*/
+ @CallerSensitive
public double getDouble(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
return getFieldAccessor(obj).getDouble(obj);
}
@@ -684,9 +748,16 @@
* @exception ExceptionInInitializerError if the initialization provoked
* by this method fails.
*/
+ @CallerSensitive
public void set(Object obj, Object value)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
getFieldAccessor(obj).set(obj, value);
}
@@ -714,9 +785,16 @@
* by this method fails.
* @see Field#set
*/
+ @CallerSensitive
public void setBoolean(Object obj, boolean z)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
getFieldAccessor(obj).setBoolean(obj, z);
}
@@ -744,9 +822,16 @@
* by this method fails.
* @see Field#set
*/
+ @CallerSensitive
public void setByte(Object obj, byte b)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
getFieldAccessor(obj).setByte(obj, b);
}
@@ -774,9 +859,16 @@
* by this method fails.
* @see Field#set
*/
+ @CallerSensitive
public void setChar(Object obj, char c)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
getFieldAccessor(obj).setChar(obj, c);
}
@@ -804,9 +896,16 @@
* by this method fails.
* @see Field#set
*/
+ @CallerSensitive
public void setShort(Object obj, short s)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
getFieldAccessor(obj).setShort(obj, s);
}
@@ -834,9 +933,16 @@
* by this method fails.
* @see Field#set
*/
+ @CallerSensitive
public void setInt(Object obj, int i)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
getFieldAccessor(obj).setInt(obj, i);
}
@@ -864,9 +970,16 @@
* by this method fails.
* @see Field#set
*/
+ @CallerSensitive
public void setLong(Object obj, long l)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
getFieldAccessor(obj).setLong(obj, l);
}
@@ -894,9 +1007,16 @@
* by this method fails.
* @see Field#set
*/
+ @CallerSensitive
public void setFloat(Object obj, float f)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
getFieldAccessor(obj).setFloat(obj, f);
}
@@ -924,20 +1044,26 @@
* by this method fails.
* @see Field#set
*/
+ @CallerSensitive
public void setDouble(Object obj, double d)
throws IllegalArgumentException, IllegalAccessException
{
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
+ }
+ }
getFieldAccessor(obj).setDouble(obj, d);
}
- // Convenience routine which performs security checks
+ // security check is done before calling this method
private FieldAccessor getFieldAccessor(Object obj)
throws IllegalAccessException
{
- doSecurityCheck(obj);
boolean ov = override;
- FieldAccessor a = (ov)? overrideFieldAccessor : fieldAccessor;
- return (a != null)? a : acquireFieldAccessor(ov);
+ FieldAccessor a = (ov) ? overrideFieldAccessor : fieldAccessor;
+ return (a != null) ? a : acquireFieldAccessor(ov);
}
// NOTE that there is no synchronization used here. It is correct
@@ -982,19 +1108,6 @@
}
}
- // NOTE: be very careful if you change the stack depth of this
- // routine. The depth of the "getCallerClass" call is hardwired so
- // that the compiler can have an easier time if this gets inlined.
- private void doSecurityCheck(Object obj) throws IllegalAccessException {
- if (!override) {
- if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- Class<?> caller = Reflection.getCallerClass(4);
-
- checkAccess(caller, clazz, obj, modifiers);
- }
- }
- }
-
/**
* @throws NullPointerException {@inheritDoc}
* @since 1.5
--- a/jdk/src/share/classes/java/lang/reflect/Method.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/Method.java Wed Apr 17 02:53:02 2013 -0700
@@ -25,6 +25,7 @@
package java.lang.reflect;
+import sun.reflect.CallerSensitive;
import sun.reflect.MethodAccessor;
import sun.reflect.Reflection;
import sun.reflect.generics.repository.MethodRepository;
@@ -472,14 +473,14 @@
* @exception ExceptionInInitializerError if the initialization
* provoked by this method fails.
*/
+ @CallerSensitive
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- Class<?> caller = Reflection.getCallerClass(1);
-
+ Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
--- a/jdk/src/share/classes/java/lang/reflect/Proxy.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java Wed Apr 17 02:53:02 2013 -0700
@@ -39,6 +39,8 @@
import java.util.List;
import java.util.WeakHashMap;
import sun.misc.ProxyGenerator;
+import sun.misc.VM;
+import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
import sun.security.util.SecurityConstants;
@@ -408,28 +410,21 @@
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}
*/
+ @CallerSensitive
public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces)
throws IllegalArgumentException
{
- return getProxyClass0(loader, interfaces); // stack walk magic: do not refactor
- }
-
- private static void checkProxyLoader(ClassLoader ccl,
- ClassLoader loader)
- {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- if (loader == null && ccl != null) {
- if (!ProxyAccessHelper.allowNullLoader) {
- sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
- }
- }
+ checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
}
+
+ return getProxyClass0(loader, interfaces);
}
/*
- * Generate a proxy class (caller-sensitive).
+ * Check permissions required to create a Proxy class.
*
* To define a proxy class, it performs the access checks as in
* Class.forName (VM will invoke ClassLoader.checkPackageAccess):
@@ -446,17 +441,28 @@
* will throw IllegalAccessError when the generated proxy class is
* being defined via the defineClass0 method.
*/
- private static Class<?> getProxyClass0(ClassLoader loader,
- Class<?>... interfaces) {
+ private static void checkProxyAccess(Class<?> caller,
+ ClassLoader loader,
+ Class<?>... interfaces)
+ {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller
- final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
- final ClassLoader ccl = caller.getClassLoader();
- checkProxyLoader(ccl, loader);
+ ClassLoader ccl = caller.getClassLoader();
+ if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
+ if (!ProxyAccessHelper.allowNullLoader) {
+ sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
+ }
+ }
ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
}
+ }
+ /**
+ * Generate a proxy class. Must call the checkProxyAccess method
+ * to perform permission checks before calling this.
+ */
+ private static Class<?> getProxyClass0(ClassLoader loader,
+ Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
@@ -698,6 +704,7 @@
* if the invocation handler, {@code h}, is
* {@code null}
*/
+ @CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
@@ -707,10 +714,15 @@
throw new NullPointerException();
}
+ final SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
+ }
+
/*
* Look up or generate the designated proxy class.
*/
- Class<?> cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor
+ Class<?> cl = getProxyClass0(loader, interfaces);
/*
* Invoke its constructor with the designated invocation handler.
@@ -718,7 +730,6 @@
try {
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
- SecurityManager sm = System.getSecurityManager();
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
// create proxy instance with doPrivilege as the proxy class may
// implement non-public interfaces that requires a special permission
--- a/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Wed Apr 17 02:53:02 2013 -0700
@@ -122,7 +122,7 @@
* not connected already.
*/
protected void disconnect() {
- disconnect0(connectedAddress.family);
+ disconnect0(connectedAddress.holder().getFamily());
connected = false;
connectedAddress = null;
connectedPort = -1;
--- a/jdk/src/share/classes/java/net/Inet4Address.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/net/Inet4Address.java Wed Apr 17 02:53:02 2013 -0700
@@ -100,27 +100,28 @@
Inet4Address() {
super();
- hostName = null;
- address = 0;
- family = IPv4;
+ holder().hostName = null;
+ holder().address = 0;
+ holder().family = IPv4;
}
Inet4Address(String hostName, byte addr[]) {
- this.hostName = hostName;
- this.family = IPv4;
+ holder().hostName = hostName;
+ holder().family = IPv4;
if (addr != null) {
if (addr.length == INADDRSZ) {
- address = addr[3] & 0xFF;
+ int address = addr[3] & 0xFF;
address |= ((addr[2] << 8) & 0xFF00);
address |= ((addr[1] << 16) & 0xFF0000);
address |= ((addr[0] << 24) & 0xFF000000);
+ holder().address = address;
}
}
}
Inet4Address(String hostName, int address) {
- this.hostName = hostName;
- this.family = IPv4;
- this.address = address;
+ holder().hostName = hostName;
+ holder().family = IPv4;
+ holder().address = address;
}
/**
@@ -134,8 +135,8 @@
private Object writeReplace() throws ObjectStreamException {
// will replace the to be serialized 'this' object
InetAddress inet = new InetAddress();
- inet.hostName = this.hostName;
- inet.address = this.address;
+ inet.holder().hostName = holder().getHostName();
+ inet.holder().address = holder().getAddress();
/**
* Prior to 1.4 an InetAddress was created with a family
@@ -143,7 +144,7 @@
* For compatibility reasons we must therefore write the
* the InetAddress with this family.
*/
- inet.family = 2;
+ inet.holder().family = 2;
return inet;
}
@@ -157,7 +158,7 @@
* @since JDK1.1
*/
public boolean isMulticastAddress() {
- return ((address & 0xf0000000) == 0xe0000000);
+ return ((holder().getAddress() & 0xf0000000) == 0xe0000000);
}
/**
@@ -167,7 +168,7 @@
* @since 1.4
*/
public boolean isAnyLocalAddress() {
- return address == 0;
+ return holder().getAddress() == 0;
}
/**
@@ -195,6 +196,7 @@
// defined in "Documenting Special Use IPv4 Address Blocks
// that have been Registered with IANA" by Bill Manning
// draft-manning-dsua-06.txt
+ int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 169)
&& (((address >>> 16) & 0xFF) == 254);
}
@@ -211,6 +213,7 @@
// 10/8 prefix
// 172.16/12 prefix
// 192.168/16 prefix
+ int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 10)
|| ((((address >>> 24) & 0xFF) == 172)
&& (((address >>> 16) & 0xF0) == 16))
@@ -257,6 +260,7 @@
*/
public boolean isMCLinkLocal() {
// 224.0.0/24 prefix and ttl == 1
+ int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 224)
&& (((address >>> 16) & 0xFF) == 0)
&& (((address >>> 8) & 0xFF) == 0);
@@ -272,6 +276,7 @@
*/
public boolean isMCSiteLocal() {
// 239.255/16 prefix or ttl < 32
+ int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 239)
&& (((address >>> 16) & 0xFF) == 255);
}
@@ -287,6 +292,7 @@
*/
public boolean isMCOrgLocal() {
// 239.192 - 239.195
+ int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 239)
&& (((address >>> 16) & 0xFF) >= 192)
&& (((address >>> 16) & 0xFF) <= 195);
@@ -300,6 +306,7 @@
* @return the raw IP address of this object.
*/
public byte[] getAddress() {
+ int address = holder().getAddress();
byte[] addr = new byte[INADDRSZ];
addr[0] = (byte) ((address >>> 24) & 0xFF);
@@ -325,7 +332,7 @@
* @return a hash code value for this IP address.
*/
public int hashCode() {
- return address;
+ return holder().getAddress();
}
/**
@@ -346,7 +353,7 @@
*/
public boolean equals(Object obj) {
return (obj != null) && (obj instanceof Inet4Address) &&
- (((InetAddress)obj).address == address);
+ (((InetAddress)obj).holder().getAddress() == holder().getAddress());
}
// Utilities
--- a/jdk/src/share/classes/java/net/Inet4AddressImpl.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/net/Inet4AddressImpl.java Wed Apr 17 02:53:02 2013 -0700
@@ -40,7 +40,7 @@
public synchronized InetAddress anyLocalAddress() {
if (anyLocalAddress == null) {
anyLocalAddress = new Inet4Address(); // {0x00,0x00,0x00,0x00}
- anyLocalAddress.hostName = "0.0.0.0";
+ anyLocalAddress.holder().hostName = "0.0.0.0";
}
return anyLocalAddress;
}
--- a/jdk/src/share/classes/java/net/Inet6Address.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/net/Inet6Address.java Wed Apr 17 02:53:02 2013 -0700
@@ -210,18 +210,18 @@
Inet6Address() {
super();
- hostName = null;
+ holder().hostName = null;
ipaddress = new byte[INADDRSZ];
- family = IPv6;
+ holder().family = IPv6;
}
/* checking of value for scope_id should be done by caller
* scope_id must be >= 0, or -1 to indicate not being set
*/
Inet6Address(String hostName, byte addr[], int scope_id) {
- this.hostName = hostName;
+ holder().hostName = hostName;
if (addr.length == INADDRSZ) { // normal IPv6 address
- family = IPv6;
+ holder().family = IPv6;
ipaddress = addr.clone();
}
if (scope_id >= 0) {
@@ -335,9 +335,9 @@
private void initif(String hostName, byte addr[],NetworkInterface nif)
throws UnknownHostException
{
- this.hostName = hostName;
+ holder().hostName = hostName;
if (addr.length == INADDRSZ) { // normal IPv6 address
- family = IPv6;
+ holder().family = IPv6;
ipaddress = addr.clone();
}
if (nif != null) {
@@ -420,6 +420,11 @@
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
+
+ if (getClass().getClassLoader() != null) {
+ throw new SecurityException ("invalid address type");
+ }
+
s.defaultReadObject();
if (ifname != null && !ifname.equals("")) {
@@ -447,7 +452,7 @@
ipaddress.length);
}
- if (family != IPv6) {
+ if (holder().getFamily() != IPv6) {
throw new InvalidObjectException("invalid address family type");
}
}
--- a/jdk/src/share/classes/java/net/Inet6AddressImpl.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/net/Inet6AddressImpl.java Wed Apr 17 02:53:02 2013 -0700
@@ -81,7 +81,7 @@
if (anyLocalAddress == null) {
if (InetAddress.preferIPv6Address) {
anyLocalAddress = new Inet6Address();
- anyLocalAddress.hostName = "::";
+ anyLocalAddress.holder().hostName = "::";
} else {
anyLocalAddress = (new Inet4AddressImpl()).anyLocalAddress();
}
--- a/jdk/src/share/classes/java/net/InetAddress.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/net/InetAddress.java Wed Apr 17 02:53:02 2013 -0700
@@ -35,8 +35,12 @@
import java.util.ServiceLoader;
import java.security.AccessController;
import java.io.ObjectStreamException;
+import java.io.ObjectStreamField;
import java.io.IOException;
import java.io.ObjectInputStream;
+import java.io.ObjectInputStream.GetField;
+import java.io.ObjectOutputStream;
+import java.io.ObjectOutputStream.PutField;
import sun.security.action.*;
import sun.net.InetAddressCachePolicy;
import sun.net.util.IPAddressUtil;
@@ -199,25 +203,48 @@
/* Specify address family preference */
static transient boolean preferIPv6Address = false;
- /**
- * @serial
- */
- String hostName;
+ static class InetAddressHolder {
+
+ InetAddressHolder() {}
+
+ InetAddressHolder(String hostName, int address, int family) {
+ this.hostName = hostName;
+ this.address = address;
+ this.family = family;
+ }
+
+ String hostName;
+
+ String getHostName() {
+ return hostName;
+ }
+
+ /**
+ * Holds a 32-bit IPv4 address.
+ */
+ int address;
- /**
- * Holds a 32-bit IPv4 address.
- *
- * @serial
- */
- int address;
+ int getAddress() {
+ return address;
+ }
+
+ /**
+ * Specifies the address family type, for instance, '1' for IPv4
+ * addresses, and '2' for IPv6 addresses.
+ */
+ int family;
- /**
- * Specifies the address family type, for instance, '1' for IPv4
- * addresses, and '2' for IPv6 addresses.
- *
- * @serial
- */
- int family;
+ int getFamily() {
+ return family;
+ }
+ }
+
+ /* Used to store the serializable fields of InetAddress */
+ private final transient InetAddressHolder holder;
+
+ InetAddressHolder holder() {
+ return holder;
+ }
/* Used to store the name service provider */
private static List<NameService> nameServices = null;
@@ -251,6 +278,7 @@
* put in the address cache, since it is not created by name.
*/
InetAddress() {
+ holder = new InetAddressHolder();
}
/**
@@ -263,7 +291,7 @@
*/
private Object readResolve() throws ObjectStreamException {
// will replace the deserialized 'this' object
- return new Inet4Address(this.hostName, this.address);
+ return new Inet4Address(holder().getHostName(), holder().getAddress());
}
/**
@@ -500,10 +528,10 @@
* @see SecurityManager#checkConnect
*/
String getHostName(boolean check) {
- if (hostName == null) {
- hostName = InetAddress.getHostFromNameService(this, check);
+ if (holder().getHostName() == null) {
+ holder().hostName = InetAddress.getHostFromNameService(this, check);
}
- return hostName;
+ return holder().getHostName();
}
/**
@@ -666,6 +694,7 @@
* @return a string representation of this IP address.
*/
public String toString() {
+ String hostName = holder().getHostName();
return ((hostName != null) ? hostName : "")
+ "/" + getHostAddress();
}
@@ -1522,14 +1551,58 @@
}
}
+ private static final long FIELDS_OFFSET;
+ private static final sun.misc.Unsafe UNSAFE;
+
+ static {
+ try {
+ sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+ FIELDS_OFFSET = unsafe.objectFieldOffset(
+ InetAddress.class.getDeclaredField("holder")
+ );
+ UNSAFE = unsafe;
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
+ }
+
private void readObject (ObjectInputStream s) throws
IOException, ClassNotFoundException {
- s.defaultReadObject ();
if (getClass().getClassLoader() != null) {
- hostName = null;
- address = 0;
throw new SecurityException ("invalid address type");
}
+ GetField gf = s.readFields();
+ String host = (String)gf.get("hostName", null);
+ int address= gf.get("address", 0);
+ int family= gf.get("family", 0);
+ InetAddressHolder h = new InetAddressHolder(host, address, family);
+ UNSAFE.putObject(this, FIELDS_OFFSET, h);
+ }
+
+ /* needed because the serializable fields no longer exist */
+
+ /**
+ * @serialField hostName String
+ * @serialField address int
+ * @serialField family int
+ */
+ private static final ObjectStreamField[] serialPersistentFields = {
+ new ObjectStreamField("hostName", String.class),
+ new ObjectStreamField("address", int.class),
+ new ObjectStreamField("family", int.class),
+ };
+
+ private void writeObject (ObjectOutputStream s) throws
+ IOException {
+ if (getClass().getClassLoader() != null) {
+ throw new SecurityException ("invalid address type");
+ }
+ PutField pf = s.putFields();
+ pf.put("hostName", holder().getHostName());
+ pf.put("address", holder().getAddress());
+ pf.put("family", holder().getFamily());
+ s.writeFields();
+ s.flush();
}
}
--- a/jdk/src/share/classes/java/net/InetSocketAddress.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/net/InetSocketAddress.java Wed Apr 17 02:53:02 2013 -0700
@@ -87,8 +87,8 @@
if (hostname != null)
return hostname;
if (addr != null) {
- if (addr.hostName != null)
- return addr.hostName;
+ if (addr.holder().getHostName() != null)
+ return addr.holder().getHostName();
else
return addr.getHostAddress();
}
--- a/jdk/src/share/classes/java/rmi/server/LogStream.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/rmi/server/LogStream.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -120,6 +120,13 @@
*/
@Deprecated
public static synchronized void setDefaultStream(PrintStream newDefault) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ sm.checkPermission(
+ new java.util.logging.LoggingPermission("control", null));
+ }
+
defaultStream = newDefault;
}
--- a/jdk/src/share/classes/java/security/AccessController.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/security/AccessController.java Wed Apr 17 02:53:02 2013 -0700
@@ -26,6 +26,8 @@
package java.security;
import sun.security.util.Debug;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
/**
* <p> The AccessController class is used for access control operations
@@ -264,6 +266,7 @@
* @see java.security.DomainCombiner
*/
+ @CallerSensitive
public static native <T> T doPrivileged(PrivilegedAction<T> action);
/**
@@ -288,14 +291,15 @@
*
* @since 1.6
*/
+ @CallerSensitive
public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) {
-
AccessControlContext acc = getStackAccessControlContext();
if (acc == null) {
return AccessController.doPrivileged(action);
}
DomainCombiner dc = acc.getAssignedCombiner();
- return AccessController.doPrivileged(action, preserveCombiner(dc));
+ return AccessController.doPrivileged(action,
+ preserveCombiner(dc, Reflection.getCallerClass()));
}
@@ -326,6 +330,7 @@
* @see #doPrivileged(PrivilegedAction)
* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
*/
+ @CallerSensitive
public static native <T> T doPrivileged(PrivilegedAction<T> action,
AccessControlContext context);
@@ -353,6 +358,7 @@
* @see #doPrivilegedWithCombiner(PrivilegedExceptionAction)
* @see java.security.DomainCombiner
*/
+ @CallerSensitive
public static native <T> T
doPrivileged(PrivilegedExceptionAction<T> action)
throws PrivilegedActionException;
@@ -383,34 +389,29 @@
*
* @since 1.6
*/
- public static <T> T doPrivilegedWithCombiner
- (PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
-
+ @CallerSensitive
+ public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action)
+ throws PrivilegedActionException
+ {
AccessControlContext acc = getStackAccessControlContext();
if (acc == null) {
return AccessController.doPrivileged(action);
}
DomainCombiner dc = acc.getAssignedCombiner();
- return AccessController.doPrivileged(action, preserveCombiner(dc));
+ return AccessController.doPrivileged(action,
+ preserveCombiner(dc, Reflection.getCallerClass()));
}
/**
* preserve the combiner across the doPrivileged call
*/
- private static AccessControlContext preserveCombiner
- (DomainCombiner combiner) {
-
- /**
- * callerClass[0] = Reflection.getCallerClass
- * callerClass[1] = AccessController.preserveCombiner
- * callerClass[2] = AccessController.doPrivileged
- * callerClass[3] = caller
- */
- final Class<?> callerClass = sun.reflect.Reflection.getCallerClass(3);
+ private static AccessControlContext preserveCombiner(DomainCombiner combiner,
+ Class<?> caller)
+ {
ProtectionDomain callerPd = doPrivileged
(new PrivilegedAction<ProtectionDomain>() {
public ProtectionDomain run() {
- return callerClass.getProtectionDomain();
+ return caller.getProtectionDomain();
}
});
@@ -455,6 +456,7 @@
* @see #doPrivileged(PrivilegedAction)
* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
*/
+ @CallerSensitive
public static native <T> T
doPrivileged(PrivilegedExceptionAction<T> action,
AccessControlContext context)
--- a/jdk/src/share/classes/java/sql/DriverManager.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/sql/DriverManager.java Wed Apr 17 02:53:02 2013 -0700
@@ -30,6 +30,7 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.CopyOnWriteArrayList;
+import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
@@ -192,14 +193,11 @@
* has been exceeded and has at least tried to cancel the
* current database connection attempt
*/
+ @CallerSensitive
public static Connection getConnection(String url,
java.util.Properties info) throws SQLException {
- // Gets the classloader of the code that called this method, may
- // be null.
- ClassLoader callerCL = DriverManager.getCallerClassLoader();
-
- return (getConnection(url, info, callerCL));
+ return (getConnection(url, info, Reflection.getCallerClass()));
}
/**
@@ -226,14 +224,11 @@
* has been exceeded and has at least tried to cancel the
* current database connection attempt
*/
+ @CallerSensitive
public static Connection getConnection(String url,
String user, String password) throws SQLException {
java.util.Properties info = new java.util.Properties();
- // Gets the classloader of the code that called this method, may
- // be null.
- ClassLoader callerCL = DriverManager.getCallerClassLoader();
-
if (user != null) {
info.put("user", user);
}
@@ -241,7 +236,7 @@
info.put("password", password);
}
- return (getConnection(url, info, callerCL));
+ return (getConnection(url, info, Reflection.getCallerClass()));
}
/**
@@ -259,16 +254,12 @@
* has been exceeded and has at least tried to cancel the
* current database connection attempt
*/
+ @CallerSensitive
public static Connection getConnection(String url)
throws SQLException {
java.util.Properties info = new java.util.Properties();
-
- // Gets the classloader of the code that called this method, may
- // be null.
- ClassLoader callerCL = DriverManager.getCallerClassLoader();
-
- return (getConnection(url, info, callerCL));
+ return (getConnection(url, info, Reflection.getCallerClass()));
}
/**
@@ -282,21 +273,20 @@
* that can connect to the given URL
* @exception SQLException if a database access error occurs
*/
+ @CallerSensitive
public static Driver getDriver(String url)
throws SQLException {
println("DriverManager.getDriver(\"" + url + "\")");
- // Gets the classloader of the code that called this method, may
- // be null.
- ClassLoader callerCL = DriverManager.getCallerClassLoader();
+ Class<?> callerClass = Reflection.getCallerClass();
// Walk through the loaded registeredDrivers attempting to locate someone
// who understands the given URL.
for (DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
- if(isDriverAllowed(aDriver.driver, callerCL)) {
+ if(isDriverAllowed(aDriver.driver, callerClass)) {
try {
if(aDriver.driver.acceptsURL(url)) {
// Success!
@@ -350,20 +340,18 @@
* @param driver the JDBC Driver to drop
* @exception SQLException if a database access error occurs
*/
+ @CallerSensitive
public static synchronized void deregisterDriver(Driver driver)
throws SQLException {
if (driver == null) {
return;
}
- // Gets the classloader of the code that called this method,
- // may be null.
- ClassLoader callerCL = DriverManager.getCallerClassLoader();
println("DriverManager.deregisterDriver: " + driver);
DriverInfo aDriver = new DriverInfo(driver);
if(registeredDrivers.contains(aDriver)) {
- if (isDriverAllowed(driver, callerCL)) {
+ if (isDriverAllowed(driver, Reflection.getCallerClass())) {
registeredDrivers.remove(aDriver);
} else {
// If the caller does not have permission to load the driver then
@@ -384,18 +372,17 @@
*
* @return the list of JDBC Drivers loaded by the caller's class loader
*/
+ @CallerSensitive
public static java.util.Enumeration<Driver> getDrivers() {
java.util.Vector<Driver> result = new java.util.Vector<>();
- // Gets the classloader of the code that called this method, may
- // be null.
- ClassLoader callerCL = DriverManager.getCallerClassLoader();
+ Class<?> callerClass = Reflection.getCallerClass();
// Walk through the loaded registeredDrivers.
for(DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
- if(isDriverAllowed(aDriver.driver, callerCL)) {
+ if(isDriverAllowed(aDriver.driver, callerClass)) {
result.addElement(aDriver.driver);
} else {
println(" skipping: " + aDriver.getClass().getName());
@@ -493,17 +480,13 @@
//------------------------------------------------------------------------
- // Internal method used to get the caller's class loader.
- // Replaces the call to the native method
- private static ClassLoader getCallerClassLoader() {
- Class<?> cc = Reflection.getCallerClass(3);
- ClassLoader cl = (cc != null) ? cc.getClassLoader() : null;
- return cl;
+ // Indicates whether the class object that would be created if the code calling
+ // DriverManager is accessible.
+ private static boolean isDriverAllowed(Driver driver, Class<?> caller) {
+ ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
+ return isDriverAllowed(driver, callerCL);
}
-
- // Indicates whether the class object that would be created if the code calling
- // DriverManager is accessible.
private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
boolean result = false;
if(driver != null) {
@@ -556,7 +539,7 @@
*/
try{
while(driversIterator.hasNext()) {
- println(" Loading done by the java.util.ServiceLoader : "+driversIterator.next());
+ driversIterator.next();
}
} catch(Throwable t) {
// Do nothing
@@ -586,18 +569,19 @@
// Worker method called by the public getConnection() methods.
private static Connection getConnection(
- String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {
+ String url, java.util.Properties info, Class<?> caller) throws SQLException {
/*
* When callerCl is null, we should check the application's
* (which is invoking this class indirectly)
* classloader, so that the JDBC driver class outside rt.jar
* can be loaded from here.
*/
+ ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
synchronized(DriverManager.class) {
- // synchronize loading of the correct classloader.
- if(callerCL == null) {
- callerCL = Thread.currentThread().getContextClassLoader();
- }
+ // synchronize loading of the correct classloader.
+ if (callerCL == null) {
+ callerCL = Thread.currentThread().getContextClassLoader();
+ }
}
if(url == null) {
--- a/jdk/src/share/classes/java/util/Collections.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/util/Collections.java Wed Apr 17 02:53:02 2013 -0700
@@ -28,6 +28,9 @@
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
/**
* This class consists exclusively of static methods that operate on or return
@@ -264,8 +267,7 @@
}
private static <T>
- int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key)
- {
+ int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
int low = 0;
int high = list.size()-1;
@@ -441,21 +443,21 @@
/**
* Randomly permutes the specified list using a default source of
* randomness. All permutations occur with approximately equal
- * likelihood.<p>
+ * likelihood.
*
- * The hedge "approximately" is used in the foregoing description because
+ * <p>The hedge "approximately" is used in the foregoing description because
* default source of randomness is only approximately an unbiased source
* of independently chosen bits. If it were a perfect source of randomly
* chosen bits, then the algorithm would choose permutations with perfect
- * uniformity.<p>
+ * uniformity.
*
- * This implementation traverses the list backwards, from the last element
- * up to the second, repeatedly swapping a randomly selected element into
- * the "current position". Elements are randomly selected from the
+ * <p>This implementation traverses the list backwards, from the last
+ * element up to the second, repeatedly swapping a randomly selected element
+ * into the "current position". Elements are randomly selected from the
* portion of the list that runs from the first element to the current
- * position, inclusive.<p>
+ * position, inclusive.
*
- * This method runs in linear time. If the specified list does not
+ * <p>This method runs in linear time. If the specified list does not
* implement the {@link RandomAccess} interface and is large, this
* implementation dumps the specified list into an array before shuffling
* it, and dumps the shuffled array back into the list. This avoids the
@@ -469,9 +471,10 @@
public static void shuffle(List<?> list) {
Random rnd = r;
if (rnd == null)
- r = rnd = new Random();
+ r = rnd = new Random(); // harmless race.
shuffle(list, rnd);
}
+
private static Random r;
/**
@@ -1391,6 +1394,67 @@
public int hashCode() {return m.hashCode();}
public String toString() {return m.toString();}
+ // Override default methods in Map
+ @Override
+ @SuppressWarnings("unchecked")
+ public V getOrDefault(Object k, V defaultValue) {
+ // Safe cast as we don't change the value
+ return ((Map<K, V>)m).getOrDefault(k, defaultValue);
+ }
+
+ @Override
+ public void forEach(BiConsumer<? super K, ? super V> action) {
+ m.forEach(action);
+ }
+
+ @Override
+ public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V putIfAbsent(K key, V value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean remove(Object key, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean replace(K key, V oldValue, V newValue) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V replace(K key, V value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V computeIfPresent(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V compute(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V merge(K key, V value,
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
/**
* We need this class in addition to UnmodifiableSet as
* Map.Entries themselves permit modification of the backing Map
@@ -1590,9 +1654,9 @@
* </pre>
* Failure to follow this advice may result in non-deterministic behavior.
*
- * <p>The returned collection does <i>not</i> pass the <tt>hashCode</tt>
- * and <tt>equals</tt> operations through to the backing collection, but
- * relies on <tt>Object</tt>'s equals and hashCode methods. This is
+ * <p>The returned collection does <i>not</i> pass the {@code hashCode}
+ * and {@code equals} operations through to the backing collection, but
+ * relies on {@code Object}'s equals and hashCode methods. This is
* necessary to preserve the contracts of these operations in the case
* that the backing collection is a set or a list.<p>
*
@@ -2107,6 +2171,57 @@
public String toString() {
synchronized (mutex) {return m.toString();}
}
+
+ // Override default methods in Map
+ @Override
+ public V getOrDefault(Object k, V defaultValue) {
+ synchronized (mutex) {return m.getOrDefault(k, defaultValue);}
+ }
+ @Override
+ public void forEach(BiConsumer<? super K, ? super V> action) {
+ synchronized (mutex) {m.forEach(action);}
+ }
+ @Override
+ public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+ synchronized (mutex) {m.replaceAll(function);}
+ }
+ @Override
+ public V putIfAbsent(K key, V value) {
+ synchronized (mutex) {return m.putIfAbsent(key, value);}
+ }
+ @Override
+ public boolean remove(Object key, Object value) {
+ synchronized (mutex) {return m.remove(key, value);}
+ }
+ @Override
+ public boolean replace(K key, V oldValue, V newValue) {
+ synchronized (mutex) {return m.replace(key, oldValue, newValue);}
+ }
+ @Override
+ public V replace(K key, V value) {
+ synchronized (mutex) {return m.replace(key, value);}
+ }
+ @Override
+ public V computeIfAbsent(K key,
+ Function<? super K, ? extends V> mappingFunction) {
+ synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);}
+ }
+ @Override
+ public V computeIfPresent(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);}
+ }
+ @Override
+ public V compute(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ synchronized (mutex) {return m.compute(key, remappingFunction);}
+ }
+ @Override
+ public V merge(K key, V value,
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ synchronized (mutex) {return m.merge(key, value, remappingFunction);}
+ }
+
private void writeObject(ObjectOutputStream s) throws IOException {
synchronized (mutex) {s.defaultWriteObject();}
}
@@ -2326,6 +2441,8 @@
}
public Iterator<E> iterator() {
+ // JDK-6363904 - unwrapped iterator could be typecast to
+ // ListIterator with unsafe set()
final Iterator<E> it = c.iterator();
return new Iterator<E>() {
public boolean hasNext() { return it.hasNext(); }
@@ -2652,7 +2769,7 @@
public List<E> subList(int fromIndex, int toIndex) {
return new CheckedRandomAccessList<>(
- list.subList(fromIndex, toIndex), type);
+ list.subList(fromIndex, toIndex), type);
}
}
@@ -2717,14 +2834,24 @@
throw new ClassCastException(badValueMsg(value));
}
+ private BiFunction<? super K, ? super V, ? extends V> typeCheck(
+ BiFunction<? super K, ? super V, ? extends V> func) {
+ Objects.requireNonNull(func);
+ return (k, v) -> {
+ V newValue = func.apply(k, v);
+ typeCheck(k, newValue);
+ return newValue;
+ };
+ }
+
private String badKeyMsg(Object key) {
return "Attempt to insert " + key.getClass() +
- " key into map with key type " + keyType;
+ " key into map with key type " + keyType;
}
private String badValueMsg(Object value) {
return "Attempt to insert " + value.getClass() +
- " value into map with value type " + valueType;
+ " value into map with value type " + valueType;
}
CheckedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType) {
@@ -2768,7 +2895,7 @@
Object v = e.getValue();
typeCheck(k, v);
checked.add(
- new AbstractMap.SimpleImmutableEntry<>((K) k, (V) v));
+ new AbstractMap.SimpleImmutableEntry<>((K)k, (V)v));
}
for (Map.Entry<K,V> e : checked)
m.put(e.getKey(), e.getValue());
@@ -2782,6 +2909,74 @@
return entrySet;
}
+ // Override default methods in Map
+ @Override
+ public void forEach(BiConsumer<? super K, ? super V> action) {
+ m.forEach(action);
+ }
+
+ @Override
+ public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+ m.replaceAll(typeCheck(function));
+ }
+
+ @Override
+ public V putIfAbsent(K key, V value) {
+ typeCheck(key, value);
+ return m.putIfAbsent(key, value);
+ }
+
+ @Override
+ public boolean remove(Object key, Object value) {
+ return m.remove(key, value);
+ }
+
+ @Override
+ public boolean replace(K key, V oldValue, V newValue) {
+ typeCheck(key, newValue);
+ return m.replace(key, oldValue, newValue);
+ }
+
+ @Override
+ public V replace(K key, V value) {
+ typeCheck(key, value);
+ return m.replace(key, value);
+ }
+
+ @Override
+ public V computeIfAbsent(K key,
+ Function<? super K, ? extends V> mappingFunction) {
+ Objects.requireNonNull(mappingFunction);
+ return m.computeIfAbsent(key, k -> {
+ V value = mappingFunction.apply(k);
+ typeCheck(k, value);
+ return value;
+ });
+ }
+
+ @Override
+ public V computeIfPresent(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ return m.computeIfPresent(key, typeCheck(remappingFunction));
+ }
+
+ @Override
+ public V compute(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ return m.compute(key, typeCheck(remappingFunction));
+ }
+
+ @Override
+ public V merge(K key, V value,
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ Objects.requireNonNull(remappingFunction);
+ return m.merge(key, value, (v1, v2) -> {
+ V newValue = remappingFunction.apply(v1, v2);
+ typeCheck(null, newValue);
+ return newValue;
+ });
+ }
+
/**
* We need this class in addition to CheckedSet as Map.Entry permits
* modification of the backing Map via the setValue operation. This
@@ -3456,6 +3651,67 @@
public int hashCode() {return 0;}
+ // Override default methods in Map
+ @Override
+ @SuppressWarnings("unchecked")
+ public V getOrDefault(Object k, V defaultValue) {
+ return defaultValue;
+ }
+
+ @Override
+ public void forEach(BiConsumer<? super K, ? super V> action) {
+ Objects.requireNonNull(action);
+ }
+
+ @Override
+ public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+ Objects.requireNonNull(function);
+ }
+
+ @Override
+ public V putIfAbsent(K key, V value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean remove(Object key, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean replace(K key, V oldValue, V newValue) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V replace(K key, V value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V computeIfAbsent(K key,
+ Function<? super K, ? extends V> mappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V computeIfPresent(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V compute(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V merge(K key, V value,
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
// Preserves singleton property
private Object readResolve() {
return EMPTY_MAP;
@@ -3619,6 +3875,65 @@
return values;
}
+ // Override default methods in Map
+ @Override
+ public V getOrDefault(Object key, V defaultValue) {
+ return eq(key, k) ? v : defaultValue;
+ }
+
+ @Override
+ public void forEach(BiConsumer<? super K, ? super V> action) {
+ action.accept(k, v);
+ }
+
+ @Override
+ public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V putIfAbsent(K key, V value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean remove(Object key, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean replace(K key, V oldValue, V newValue) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V replace(K key, V value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V computeIfAbsent(K key,
+ Function<? super K, ? extends V> mappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V computeIfPresent(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V compute(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V merge(K key, V value,
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
}
// Miscellaneous
--- a/jdk/src/share/classes/java/util/CurrencyData.properties Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/util/CurrencyData.properties Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 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
@@ -28,7 +28,7 @@
# Version of the currency code information in this class.
# It is a serial number that accompanies with each amendment.
-dataVersion=154
+dataVersion=155
# List of all valid ISO 4217 currency codes.
# To ensure compatibility, do not remove codes.
@@ -585,7 +585,7 @@
minor0=\
ADP-BEF-BIF-BYB-BYR-CLF-CLP-DJF-ESP-GNF-\
GRD-ISK-ITL-JPY-KMF-KRW-LUF-MGF-PYG-PTE-RWF-\
- TPE-TRL-VND-VUV-XAF-XOF-XPF
+ TPE-TRL-UGX-VND-VUV-XAF-XOF-XPF
minor1=
minor3=\
BHD-IQD-JOD-KWD-LYD-OMR-TND
--- a/jdk/src/share/classes/java/util/HashMap.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/util/HashMap.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -24,7 +24,11 @@
*/
package java.util;
+
import java.io.*;
+import java.util.function.Consumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
/**
* Hash table based implementation of the <tt>Map</tt> interface. This
@@ -376,6 +380,13 @@
return null == entry ? null : entry.getValue();
}
+ @Override
+ public V getOrDefault(Object key, V defaultValue) {
+ Entry<K,V> entry = getEntry(key);
+
+ return (entry == null) ? defaultValue : entry.getValue();
+ }
+
/**
* Returns <tt>true</tt> if this map contains a mapping for the
* specified key.
@@ -603,6 +614,261 @@
return (e == null ? null : e.value);
}
+ // optimized implementations of default methods in Map
+
+ @Override
+ public V putIfAbsent(K key, V value) {
+ if (table == EMPTY_TABLE) {
+ inflateTable(threshold);
+ }
+ int hash = (key == null) ? 0 : hash(key);
+ int i = indexFor(hash, table.length);
+ @SuppressWarnings("unchecked")
+ Entry<K,V> e = (Entry<K,V>)table[i];
+ for(; e != null; e = e.next) {
+ if (e.hash == hash && Objects.equals(e.key, key)) {
+ if(e.value != null) {
+ return e.value;
+ }
+ e.value = value;
+ modCount++;
+ e.recordAccess(this);
+ return null;
+ }
+ }
+
+ modCount++;
+ addEntry(hash, key, value, i);
+ return null;
+ }
+
+ @Override
+ public boolean remove(Object key, Object value) {
+ if (isEmpty()) {
+ return false;
+ }
+ int hash = (key == null) ? 0 : hash(key);
+ int i = indexFor(hash, table.length);
+ @SuppressWarnings("unchecked")
+ Entry<K,V> prev = (Entry<K,V>)table[i];
+ Entry<K,V> e = prev;
+
+ while (e != null) {
+ Entry<K,V> next = e.next;
+ if (e.hash == hash && Objects.equals(e.key, key)) {
+ if (!Objects.equals(e.value, value)) {
+ return false;
+ }
+ modCount++;
+ size--;
+ if (prev == e)
+ table[i] = next;
+ else
+ prev.next = next;
+ e.recordRemoval(this);
+ return true;
+ }
+ prev = e;
+ e = next;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean replace(K key, V oldValue, V newValue) {
+ if (isEmpty()) {
+ return false;
+ }
+ int hash = (key == null) ? 0 : hash(key);
+ int i = indexFor(hash, table.length);
+ @SuppressWarnings("unchecked")
+ Entry<K,V> e = (Entry<K,V>)table[i];
+ for (; e != null; e = e.next) {
+ if (e.hash == hash && Objects.equals(e.key, key) && Objects.equals(e.value, oldValue)) {
+ e.value = newValue;
+ e.recordAccess(this);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public V replace(K key, V value) {
+ if (isEmpty()) {
+ return null;
+ }
+ int hash = (key == null) ? 0 : hash(key);
+ int i = indexFor(hash, table.length);
+ @SuppressWarnings("unchecked")
+ Entry<K,V> e = (Entry<K,V>)table[i];
+ for (; e != null; e = e.next) {
+ if (e.hash == hash && Objects.equals(e.key, key)) {
+ V oldValue = e.value;
+ e.value = value;
+ e.recordAccess(this);
+ return oldValue;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
+ if (table == EMPTY_TABLE) {
+ inflateTable(threshold);
+ }
+ int hash = (key == null) ? 0 : hash(key);
+ int i = indexFor(hash, table.length);
+ @SuppressWarnings("unchecked")
+ Entry<K,V> e = (Entry<K,V>)table[i];
+ for (; e != null; e = e.next) {
+ if (e.hash == hash && Objects.equals(e.key, key)) {
+ V oldValue = e.value;
+ return oldValue == null ? (e.value = mappingFunction.apply(key)) : oldValue;
+ }
+ }
+
+ V newValue = mappingFunction.apply(key);
+ if (newValue != null) {
+ modCount++;
+ addEntry(hash, key, newValue, i);
+ }
+
+ return newValue;
+ }
+
+ @Override
+ public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ if (isEmpty()) {
+ return null;
+ }
+ int hash = (key == null) ? 0 : hash(key);
+ int i = indexFor(hash, table.length);
+ @SuppressWarnings("unchecked")
+ Entry<K,V> prev = (Entry<K,V>)table[i];
+ Entry<K,V> e = prev;
+
+ while (e != null) {
+ Entry<K,V> next = e.next;
+ if (e.hash == hash && Objects.equals(e.key, key)) {
+ V oldValue = e.value;
+ if (oldValue == null)
+ break;
+ V newValue = remappingFunction.apply(key, oldValue);
+ modCount++;
+ if (newValue == null) {
+ size--;
+ if (prev == e)
+ table[i] = next;
+ else
+ prev.next = next;
+ e.recordRemoval(this);
+ } else {
+ e.value = newValue;
+ e.recordAccess(this);
+ }
+ return newValue;
+ }
+ prev = e;
+ e = next;
+ }
+
+ return null;
+ }
+
+ @Override
+ public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ if (table == EMPTY_TABLE) {
+ inflateTable(threshold);
+ }
+ int hash = (key == null) ? 0 : hash(key);
+ int i = indexFor(hash, table.length);
+ @SuppressWarnings("unchecked")
+ Entry<K,V> prev = (Entry<K,V>)table[i];
+ Entry<K,V> e = prev;
+
+ while (e != null) {
+ Entry<K,V> next = e.next;
+ if (e.hash == hash && Objects.equals(e.key, key)) {
+ V oldValue = e.value;
+ V newValue = remappingFunction.apply(key, oldValue);
+ if (newValue != oldValue) {
+ modCount++;
+ if (newValue == null) {
+ size--;
+ if (prev == e)
+ table[i] = next;
+ else
+ prev.next = next;
+ e.recordRemoval(this);
+ } else {
+ e.value = newValue;
+ e.recordAccess(this);
+ }
+ }
+ return newValue;
+ }
+ prev = e;
+ e = next;
+ }
+
+ V newValue = remappingFunction.apply(key, null);
+ if (newValue != null) {
+ modCount++;
+ addEntry(hash, key, newValue, i);
+ }
+
+ return newValue;
+ }
+
+ @Override
+ public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ if (table == EMPTY_TABLE) {
+ inflateTable(threshold);
+ }
+ int hash = (key == null) ? 0 : hash(key);
+ int i = indexFor(hash, table.length);
+ @SuppressWarnings("unchecked")
+ Entry<K,V> prev = (Entry<K,V>)table[i];
+ Entry<K,V> e = prev;
+
+ while (e != null) {
+ Entry<K,V> next = e.next;
+ if (e.hash == hash && Objects.equals(e.key, key)) {
+ V oldValue = e.value;
+ V newValue = remappingFunction.apply(oldValue, value);
+ modCount++;
+ if (newValue == null) {
+ size--;
+ if (prev == e)
+ table[i] = next;
+ else
+ prev.next = next;
+ e.recordRemoval(this);
+ } else {
+ e.value = newValue;
+ e.recordAccess(this);
+ }
+ return newValue;
+ }
+ prev = e;
+ e = next;
+ }
+
+ if (value != null) {
+ modCount++;
+ addEntry(hash, key, value, i);
+ }
+
+ return value;
+ }
+
+ // end of optimized implementations of default methods in Map
+
/**
* Removes and returns the entry associated with the specified key
* in the HashMap. Returns null if the HashMap contains no mapping
@@ -697,8 +963,8 @@
return containsNullValue();
Entry<?,?>[] tab = table;
- for (int i = 0; i < tab.length ; i++)
- for (Entry<?,?> e = tab[i] ; e != null ; e = e.next)
+ for (int i = 0; i < tab.length; i++)
+ for (Entry<?,?> e = tab[i]; e != null; e = e.next)
if (value.equals(e.value))
return true;
return false;
@@ -709,8 +975,8 @@
*/
private boolean containsNullValue() {
Entry<?,?>[] tab = table;
- for (int i = 0; i < tab.length ; i++)
- for (Entry<?,?> e = tab[i] ; e != null ; e = e.next)
+ for (int i = 0; i < tab.length; i++)
+ for (Entry<?,?> e = tab[i]; e != null; e = e.next)
if (e.value == null)
return true;
return false;
--- a/jdk/src/share/classes/java/util/Hashtable.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/util/Hashtable.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -24,7 +24,11 @@
*/
package java.util;
+
import java.io.*;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import java.util.function.BiFunction;
/**
* This class implements a hash table, which maps keys to values. Any
@@ -455,6 +459,26 @@
}
}
+ private void addEntry(int hash, K key, V value, int index) {
+ modCount++;
+
+ Entry<?,?> tab[] = table;
+ if (count >= threshold) {
+ // Rehash the table if the threshold is exceeded
+ rehash();
+
+ tab = table;
+ hash = hash(key);
+ index = (hash & 0x7FFFFFFF) % tab.length;
+ }
+
+ // Creates the new entry.
+ @SuppressWarnings("unchecked")
+ Entry<K,V> e = (Entry<K,V>) tab[index];
+ tab[index] = new Entry<>(hash, key, value, e);
+ count++;
+ }
+
/**
* Maps the specified <code>key</code> to the specified
* <code>value</code> in this hashtable. Neither the key nor the
@@ -492,21 +516,7 @@
}
}
- modCount++;
- if (count >= threshold) {
- // Rehash the table if the threshold is exceeded
- rehash();
-
- tab = table;
- hash = hash(key);
- index = (hash & 0x7FFFFFFF) % tab.length;
- }
-
- // Creates the new entry.
- @SuppressWarnings("unchecked")
- Entry<K,V> e = (Entry<K,V>)tab[index];
- tab[index] = new Entry<>(hash, key, value, e);
- count++;
+ addEntry(hash, key, value, index);
return null;
}
@@ -892,6 +902,239 @@
return h;
}
+ @Override
+ public synchronized V getOrDefault(Object key, V defaultValue) {
+ V result = get(key);
+ return (null == result) ? defaultValue : result;
+ }
+
+ @Override
+ public synchronized void forEach(BiConsumer<? super K, ? super V> action) {
+ Objects.requireNonNull(action); // explicit check required in case
+ // table is empty.
+ Entry<?,?>[] tab = table;
+ for (Entry<?,?> entry : tab) {
+ while (entry != null) {
+ action.accept((K)entry.key, (V)entry.value);
+ entry = entry.next;
+ }
+ }
+ }
+
+ @Override
+ public synchronized void replaceAll(
+ BiFunction<? super K, ? super V, ? extends V> function) {
+ Map.super.replaceAll(function);
+ }
+
+ @Override
+ public synchronized V putIfAbsent(K key, V value) {
+ Objects.requireNonNull(value);
+
+ // Makes sure the key is not already in the hashtable.
+ Entry<?,?> tab[] = table;
+ int hash = hash(key);
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+ @SuppressWarnings("unchecked")
+ Entry<K,V> entry = (Entry<K,V>)tab[index];
+ for (; entry != null; entry = entry.next) {
+ if ((entry.hash == hash) && entry.key.equals(key)) {
+ V old = entry.value;
+ if (old == null) {
+ entry.value = value;
+ }
+ return old;
+ }
+ }
+
+ addEntry(hash, key, value, index);
+ return null;
+ }
+
+ @Override
+ public synchronized boolean remove(Object key, Object value) {
+ Objects.requireNonNull(value);
+
+ Entry<?,?> tab[] = table;
+ int hash = hash(key);
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+ @SuppressWarnings("unchecked")
+ Entry<K,V> e = (Entry<K,V>)tab[index];
+ for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
+ if ((e.hash == hash) && e.key.equals(key) && e.value.equals(value)) {
+ modCount++;
+ if (prev != null) {
+ prev.next = e.next;
+ } else {
+ tab[index] = e.next;
+ }
+ count--;
+ e.value = null;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized boolean replace(K key, V oldValue, V newValue) {
+ Entry<?,?> tab[] = table;
+ int hash = hash(key);
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+ @SuppressWarnings("unchecked")
+ Entry<K,V> e = (Entry<K,V>)tab[index];
+ for (; e != null; e = e.next) {
+ if ((e.hash == hash) && e.key.equals(key)) {
+ if (e.value.equals(oldValue)) {
+ e.value = newValue;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized V replace(K key, V value) {
+ Entry<?,?> tab[] = table;
+ int hash = hash(key);
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+ @SuppressWarnings("unchecked")
+ Entry<K,V> e = (Entry<K,V>)tab[index];
+ for (; e != null; e = e.next) {
+ if ((e.hash == hash) && e.key.equals(key)) {
+ V oldValue = e.value;
+ e.value = value;
+ return oldValue;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public synchronized V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
+ Objects.requireNonNull(mappingFunction);
+
+ Entry<?,?> tab[] = table;
+ int hash = hash(key);
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+ @SuppressWarnings("unchecked")
+ Entry<K,V> e = (Entry<K,V>)tab[index];
+ for (; e != null; e = e.next) {
+ if (e.hash == hash && e.key.equals(key)) {
+ // Hashtable not accept null value
+ return e.value;
+ }
+ }
+
+ V newValue = mappingFunction.apply(key);
+ if (newValue != null) {
+ addEntry(hash, key, newValue, index);
+ }
+
+ return newValue;
+ }
+
+ @Override
+ public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ Objects.requireNonNull(remappingFunction);
+
+ Entry<?,?> tab[] = table;
+ int hash = hash(key);
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+ @SuppressWarnings("unchecked")
+ Entry<K,V> e = (Entry<K,V>)tab[index];
+ for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
+ if (e.hash == hash && e.key.equals(key)) {
+ V newValue = remappingFunction.apply(key, e.value);
+ if (newValue == null) {
+ modCount++;
+ if (prev != null) {
+ prev.next = e.next;
+ } else {
+ tab[index] = e.next;
+ }
+ count--;
+ } else {
+ e.value = newValue;
+ }
+ return newValue;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ Objects.requireNonNull(remappingFunction);
+
+ Entry<?,?> tab[] = table;
+ int hash = hash(key);
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+ @SuppressWarnings("unchecked")
+ Entry<K,V> e = (Entry<K,V>)tab[index];
+ for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
+ if (e.hash == hash && Objects.equals(e.key, key)) {
+ V newValue = remappingFunction.apply(key, e.value);
+ if (newValue == null) {
+ modCount++;
+ if (prev != null) {
+ prev.next = e.next;
+ } else {
+ tab[index] = e.next;
+ }
+ count--;
+ } else {
+ e.value = newValue;
+ }
+ return newValue;
+ }
+ }
+
+ V newValue = remappingFunction.apply(key, null);
+ if (newValue != null) {
+ addEntry(hash, key, newValue, index);
+ }
+
+ return newValue;
+ }
+
+ @Override
+ public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ Objects.requireNonNull(remappingFunction);
+
+ Entry<?,?> tab[] = table;
+ int hash = hash(key);
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+ @SuppressWarnings("unchecked")
+ Entry<K,V> e = (Entry<K,V>)tab[index];
+ for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
+ if (e.hash == hash && e.key.equals(key)) {
+ V newValue = remappingFunction.apply(e.value, value);
+ if (newValue == null) {
+ modCount++;
+ if (prev != null) {
+ prev.next = e.next;
+ } else {
+ tab[index] = e.next;
+ }
+ count--;
+ } else {
+ e.value = newValue;
+ }
+ return newValue;
+ }
+ }
+
+ if (value != null) {
+ addEntry(hash, key, value, index);
+ }
+
+ return value;
+ }
+
/**
* Save the state of the Hashtable to a stream (i.e., serialize it).
*
--- a/jdk/src/share/classes/java/util/Map.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/util/Map.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -25,6 +25,10 @@
package java.util;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
/**
* An object that maps keys to values. A map cannot contain duplicate keys;
* each key can map to at most one value.
@@ -475,4 +479,613 @@
*/
int hashCode();
+ // Defaultable methods
+
+ /**
+ * Returns the value to which the specified key is mapped,
+ * or {@code defaultValue} if this map contains no mapping
+ * for the key.
+ *
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
+ * @param key the key whose associated value is to be returned
+ * @return the value to which the specified key is mapped, or
+ * {@code defaultValue} if this map contains no mapping for the key
+ * @throws ClassCastException if the key is of an inappropriate type for
+ * this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws NullPointerException if the specified key is null and this map
+ * does not permit null keys
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ */
+ default V getOrDefault(Object key, V defaultValue) {
+ V v;
+ return (((v = get(key)) != null) || containsKey(key))
+ ? v
+ : defaultValue;
+ }
+
+ /**
+ * Performs the given action on each entry in this map, in the order entries
+ * are returned by an entry set iterator (which may be unspecified), until
+ * all entries have been processed or the action throws an {@code Exception}.
+ * Exceptions thrown by the action are relayed to the caller.
+ *
+ * <p>The default implementation should be overridden by implementations if
+ * they can provide a more performant implementation than an iterator-based
+ * one.
+ *
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
+ * @implSpec The default implementation is equivalent to, for this
+ * {@code map}:
+ * <pre> {@code
+ * for ((Map.Entry<K, V> entry : map.entrySet())
+ * action.accept(entry.getKey(), entry.getValue());
+ * }</pre>
+ *
+ * @param action The action to be performed for each entry
+ * @throws NullPointerException if the specified action is null
+ * @throws ConcurrentModificationException if an entry is found to be
+ * removed during iteration
+ * @since 1.8
+ */
+ default void forEach(BiConsumer<? super K, ? super V> action) {
+ Objects.requireNonNull(action);
+ for (Map.Entry<K, V> entry : entrySet()) {
+ K k;
+ V v;
+ try {
+ k = entry.getKey();
+ v = entry.getValue();
+ } catch(IllegalStateException ise) {
+ throw new ConcurrentModificationException(ise);
+ }
+ action.accept(k, v);
+ }
+ }
+
+ /**
+ * Replaces each entry's value with the result of invoking the given
+ * function on that entry, in the order entries are returned by an entry
+ * set iterator, until all entries have been processed or the function
+ * throws an exception.
+ *
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
+ * @implSpec
+ * <p>The default implementation is equivalent to, for this {@code map}:
+ * <pre> {@code
+ * for ((Map.Entry<K, V> entry : map.entrySet())
+ * entry.setValue(function.apply(entry.getKey(), entry.getValue()));
+ * }</pre>
+ *
+ * @param function the function to apply to each entry
+ * @throws UnsupportedOperationException if the {@code set} operation
+ * is not supported by this map's entry set iterator.
+ * @throws ClassCastException if the class of a replacement value
+ * prevents it from being stored in this map
+ * @throws NullPointerException if the specified function is null, or the
+ * specified replacement value is null, and this map does not permit null
+ * values
+ * @throws ClassCastException if a replacement value is of an inappropriate
+ * type for this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws NullPointerException if function or a replacement value is null,
+ * and this map does not permit null keys or values
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws IllegalArgumentException if some property of a replacement value
+ * prevents it from being stored in this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws ConcurrentModificationException if an entry is found to be
+ * removed during iteration
+ * @since 1.8
+ */
+ default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+ Objects.requireNonNull(function);
+ for (Map.Entry<K, V> entry : entrySet()) {
+ K k;
+ V v;
+ try {
+ k = entry.getKey();
+ v = entry.getValue();
+ } catch(IllegalStateException ise) {
+ throw new ConcurrentModificationException(ise);
+ }
+ entry.setValue(function.apply(k, v));
+ }
+ }
+
+ /**
+ * If the specified key is not already associated with a value (or is mapped
+ * to {@code null}) associates it with the given value and returns
+ * {@code null}, else returns the current value.
+ *
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
+ * @implSpec
+ * The default implementation is equivalent to, for this {@code
+ * map}:
+ *
+ * <pre> {@code
+ * if (map.get(key) == null)
+ * return map.put(key, value);
+ * else
+ * return map.get(key);
+ * }</pre>
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return the previous value associated with the specified key, or
+ * {@code 1} if there was no mapping for the key.
+ * (A {@code null} return can also indicate that the map
+ * previously associated {@code null} with the key,
+ * if the implementation supports null values.)
+ * @throws UnsupportedOperationException if the {@code put} operation
+ * is not supported by this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws ClassCastException if the key or value is of an inappropriate
+ * type for this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws NullPointerException if the specified key or value is null,
+ * and this map does not permit null keys or values
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws IllegalArgumentException if some property of the specified key
+ * or value prevents it from being stored in this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws ConcurrentModificationException if a modification of the map is
+ * detected during insertion of the value.
+ * @since 1.8
+ */
+ default V putIfAbsent(K key, V value) {
+ V v = get(key);
+ if (v == null) {
+ if (put(key, value) != null) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ return v;
+ }
+
+ /**
+ * Removes the entry for the specified key only if it is currently
+ * mapped to the specified value.
+ *
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
+ * @implSpec
+ * The default implementation is equivalent to, for this {@code map}:
+ *
+ * <pre> {@code
+ * if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
+ * map.remove(key);
+ * return true;
+ * } else
+ * return false;
+ * }</pre>
+ *
+ * @param key key with which the specified value is associated
+ * @param value value expected to be associated with the specified key
+ * @return {@code true} if the value was removed
+ * @throws UnsupportedOperationException if the {@code remove} operation
+ * is not supported by this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws ClassCastException if the key or value is of an inappropriate
+ * type for this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws NullPointerException if the specified key or value is null,
+ * and this map does not permit null keys or values
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @since 1.8
+ */
+ default boolean remove(Object key, Object value) {
+ Object curValue = get(key);
+ if (!Objects.equals(curValue, value) ||
+ (curValue == null && !containsKey(key))) {
+ return false;
+ }
+ remove(key);
+ return true;
+ }
+
+ /**
+ * Replaces the entry for the specified key only if currently
+ * mapped to the specified value.
+ *
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
+ * @implSpec
+ * The default implementation is equivalent to, for this {@code map}:
+ *
+ * <pre> {@code
+ * if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
+ * map.put(key, newValue);
+ * return true;
+ * } else
+ * return false;
+ * }</pre>
+ *
+ * @param key key with which the specified value is associated
+ * @param oldValue value expected to be associated with the specified key
+ * @param newValue value to be associated with the specified key
+ * @return {@code true} if the value was replaced
+ * @throws UnsupportedOperationException if the {@code put} operation
+ * is not supported by this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws ClassCastException if the class of a specified key or value
+ * prevents it from being stored in this map
+ * @throws NullPointerException if a specified key or value is null,
+ * and this map does not permit null keys or values
+ * @throws IllegalArgumentException if some property of a specified key
+ * or value prevents it from being stored in this map
+ * @since 1.8
+ */
+ default boolean replace(K key, V oldValue, V newValue) {
+ Object curValue = get(key);
+ if (!Objects.equals(curValue, oldValue) ||
+ (curValue == null && !containsKey(key))) {
+ return false;
+ }
+ put(key, newValue);
+ return true;
+ }
+
+ /**
+ * Replaces the entry for the specified key only if it is
+ * currently mapped to some value.
+ *
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties.
+ *
+ * @implSpec
+ * The default implementation is equivalent to, for this {@code map}:
+ *
+ * <pre> {@code
+ * if (map.containsKey(key)) {
+ * return map.put(key, value);
+ * } else
+ * return null;
+ * }</pre>
+ *
+ * @param key key with which the specified value is associated
+ * @param value value to be associated with the specified key
+ * @return the previous value associated with the specified key, or
+ * {@code null} if there was no mapping for the key.
+ * (A {@code null} return can also indicate that the map
+ * previously associated {@code null} with the key,
+ * if the implementation supports null values.)
+ * @throws UnsupportedOperationException if the {@code put} operation
+ * is not supported by this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws ClassCastException if the class of the specified key or value
+ * prevents it from being stored in this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws NullPointerException if the specified key or value is null,
+ * and this map does not permit null keys or values
+ * @throws IllegalArgumentException if some property of the specified key
+ * or value prevents it from being stored in this map
+ * @since 1.8
+ */
+ default V replace(K key, V value) {
+ return containsKey(key) ? put(key, value) : null;
+ }
+
+ /**
+ * If the specified key is not already associated with a value (or
+ * is mapped to {@code null}), attempts to compute its value using
+ * the given mapping function and enters it into this map unless
+ * {@code null}.
+ *
+ * <p>If the function returns {@code null} no mapping is recorded. If
+ * the function itself throws an (unchecked) exception, the
+ * exception is rethrown, and no mapping is recorded. The most
+ * common usage is to construct a new object serving as an initial
+ * mapped value or memoized result, as in:
+ *
+ * <pre> {@code
+ * map.computeIfAbsent(key, k -> new Value(f(k)));
+ * }</pre>
+ *
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties. In particular, all implementations of
+ * subinterface {@link java.util.concurrent.ConcurrentMap} must document
+ * whether the function is applied once atomically only if the value is not
+ * present. Any class that permits null values must document
+ * whether and how this method distinguishes absence from null mappings.
+ *
+ * @implSpec
+ * The default implementation is equivalent to the following
+ * steps for this {@code map}, then returning the current value or
+ * {@code null} if now absent:
+ *
+ * <pre> {@code
+ * if (map.get(key) == null) {
+ * V newValue = mappingFunction.apply(key);
+ * if (newValue != null)
+ * map.putIfAbsent(key, newValue);
+ * }
+ * }</pre>
+ *
+ * @param key key with which the specified value is to be associated
+ * @param mappingFunction the function to compute a value
+ * @return the current (existing or computed) value associated with
+ * the specified key, or null if the computed value is null
+ * @throws NullPointerException if the specified key is null and
+ * this map does not support null keys, or the
+ * mappingFunction is null
+ * @throws UnsupportedOperationException if the {@code put} operation
+ * is not supported by this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws ClassCastException if the class of the specified key or value
+ * prevents it from being stored in this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @since 1.8
+ */
+ default V computeIfAbsent(K key,
+ Function<? super K, ? extends V> mappingFunction) {
+ V v, newValue;
+ return ((v = get(key)) == null &&
+ (newValue = mappingFunction.apply(key)) != null &&
+ (v = putIfAbsent(key, newValue)) == null) ? newValue : v;
+ }
+
+ /**
+ * If the value for the specified key is present and non-null, attempts to
+ * compute a new mapping given the key and its current mapped value.
+ *
+ * <p>If the function returns {@code null}, the mapping is removed. If the
+ * function itself throws an (unchecked) exception, the exception is
+ * rethrown, and the current mapping is left unchanged.
+ *
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties. In particular, all implementations of
+ * subinterface {@link java.util.concurrent.ConcurrentMap} must document
+ * whether the function is applied once atomically only if the value is not
+ * present. Any class that permits null values must document
+ * whether and how this method distinguishes absence from null mappings.
+ *
+ * @implSpec
+ * The default implementation is equivalent to performing the
+ * following steps for this {@code map}, then returning the
+ * current value or {@code null} if now absent:
+ *
+ * <pre> {@code
+ * if (map.get(key) != null) {
+ * V oldValue = map.get(key);
+ * V newValue = remappingFunction.apply(key, oldValue);
+ * if (newValue != null)
+ * map.replace(key, oldValue, newValue);
+ * else
+ * map.remove(key, oldValue);
+ * }
+ * }</pre>
+ *
+ * In concurrent contexts, the default implementation may retry
+ * these steps when multiple threads attempt updates.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param remappingFunction the function to compute a value
+ * @return the new value associated with the specified key, or null if none
+ * @throws NullPointerException if the specified key is null and
+ * this map does not support null keys, or the
+ * remappingFunction is null
+ * @throws UnsupportedOperationException if the {@code put} operation
+ * is not supported by this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws ClassCastException if the class of the specified key or value
+ * prevents it from being stored in this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @since 1.8
+ */
+ default V computeIfPresent(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ V oldValue;
+ while ((oldValue = get(key)) != null) {
+ V newValue = remappingFunction.apply(key, oldValue);
+ if (newValue != null) {
+ if (replace(key, oldValue, newValue))
+ return newValue;
+ } else if (remove(key, oldValue))
+ return null;
+ }
+ return oldValue;
+ }
+
+ /**
+ * Attempts to compute a mapping for the specified key and its
+ * current mapped value (or {@code null} if there is no current
+ * mapping). For example, to either create or append a {@code
+ * String msg} to a value mapping:
+ *
+ * <pre> {@code
+ * map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg))}</pre>
+ * (Method {@link #merge merge()} is often simpler to use for such purposes.)
+ *
+ * <p>If the function returns {@code null}, the mapping is removed (or
+ * remains absent if initially absent). If the function itself throws an
+ * (unchecked) exception, the exception is rethrown, and the current mapping
+ * is left unchanged.
+ *
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties. In particular, all implementations of
+ * subinterface {@link java.util.concurrent.ConcurrentMap} must document
+ * whether the function is applied once atomically only if the value is not
+ * present. Any class that permits null values must document
+ * whether and how this method distinguishes absence from null mappings.
+ *
+ * @implSpec
+ * The default implementation is equivalent to performing the following
+ * steps for this {@code map}, then returning the current value or
+ * {@code null} if absent:
+ *
+ * <pre> {@code
+ * V oldValue = map.get(key);
+ * V newValue = remappingFunction.apply(key, oldValue);
+ * if (oldValue != null ) {
+ * if (newValue != null)
+ * map.replace(key, oldValue, newValue);
+ * else
+ * map.remove(key, oldValue);
+ * } else {
+ * if (newValue != null)
+ * map.putIfAbsent(key, newValue);
+ * else
+ * return null;
+ * }
+ * }</pre>
+ *
+ * In concurrent contexts, the default implementation may retry
+ * these steps when multiple threads attempt updates.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param remappingFunction the function to compute a value
+ * @return the new value associated with the specified key, or null if none
+ * @throws NullPointerException if the specified key is null and
+ * this map does not support null keys, or the
+ * remappingFunction is null
+ * @throws UnsupportedOperationException if the {@code put} operation
+ * is not supported by this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws ClassCastException if the class of the specified key or value
+ * prevents it from being stored in this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @since 1.8
+ */
+ default V compute(K key,
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ V oldValue = get(key);
+ for (;;) {
+ V newValue = remappingFunction.apply(key, oldValue);
+ if (oldValue != null) {
+ if (newValue != null) {
+ if (replace(key, oldValue, newValue))
+ return newValue;
+ } else if (remove(key, oldValue)) {
+ return null;
+ }
+ oldValue = get(key);
+ } else {
+ if (newValue != null) {
+ if ((oldValue = putIfAbsent(key, newValue)) == null)
+ return newValue;
+ } else {
+ return null;
+ }
+ }
+ }
+ }
+
+ /**
+ * If the specified key is not already associated with a value or is
+ * associated with null, associates it with the given value.
+ * Otherwise, replaces the value with the results of the given
+ * remapping function, or removes if the result is {@code null}. This
+ * method may be of use when combining multiple mapped values for a key.
+ * For example, to either create or append a {@code String msg} to a
+ * value mapping:
+ *
+ * <pre> {@code
+ * map.merge(key, msg, String::concat)
+ * }</pre>
+ *
+ * <p>If the function returns {@code null}, the mapping is removed (or
+ * remains absent if initially absent). If the function itself throws an
+ * (unchecked) exception, the exception is rethrown, and the current mapping
+ * is left unchanged.
+ *
+ * <p>The default implementation makes no guarantees about synchronization
+ * or atomicity properties of this method. Any implementation providing
+ * atomicity guarantees must override this method and document its
+ * concurrency properties. In particular, all implementations of
+ * subinterface {@link java.util.concurrent.ConcurrentMap} must document
+ * whether the function is applied once atomically only if the value is not
+ * present. Any class that permits null values must document
+ * whether and how this method distinguishes absence from null mappings.
+ *
+ * @implSpec
+ * The default implementation is equivalent to performing the
+ * following steps for this {@code map}, then returning the
+ * current value or {@code null} if absent:
+ *
+ * <pre> {@code
+ * V oldValue = map.get(key);
+ * V newValue = (oldValue == null) ? value :
+ * remappingFunction.apply(oldValue, value);
+ * if (newValue == null)
+ * map.remove(key, oldValue);
+ * else if (oldValue == null)
+ * map.putIfAbsent(key, newValue);
+ * else
+ * map.replace(key, oldValue, newValue);
+ * }</pre>
+ *
+ * In concurrent contexts, the default implementation may retry
+ * these steps when multiple threads attempt updates.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value the value to use if absent
+ * @param remappingFunction the function to recompute a value if present
+ * @return the new value associated with the specified key, or null if none
+ * @throws UnsupportedOperationException if the {@code put} operation
+ * is not supported by this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws ClassCastException if the class of the specified key or value
+ * prevents it from being stored in this map
+ * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * @throws NullPointerException if the specified key is null and
+ * this map does not support null keys, or the
+ * remappingFunction is null
+ * @since 1.8
+ */
+ default V merge(K key, V value,
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ V oldValue = get(key);
+ for (;;) {
+ if (oldValue != null) {
+ V newValue = remappingFunction.apply(oldValue, value);
+ if (newValue != null) {
+ if (replace(key, oldValue, newValue))
+ return newValue;
+ } else if (remove(key, oldValue)) {
+ return null;
+ }
+ oldValue = get(key);
+ } else {
+ if (value == null) {
+ return null;
+ }
+
+ if ((oldValue = putIfAbsent(key, value)) == null) {
+ return value;
+ }
+ }
+ }
+ }
}
--- a/jdk/src/share/classes/java/util/ResourceBundle.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/util/ResourceBundle.java Wed Apr 17 02:53:02 2013 -0700
@@ -57,6 +57,8 @@
import java.util.jar.JarEntry;
import java.util.spi.ResourceBundleControlProvider;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
import sun.util.locale.BaseLocale;
import sun.util.locale.LocaleObjectCache;
@@ -440,14 +442,10 @@
/*
* Automatic determination of the ClassLoader to be used to load
- * resources on behalf of the client. N.B. The client is getLoader's
- * caller's caller.
+ * resources on behalf of the client.
*/
- private static ClassLoader getLoader() {
- Class<?>[] stack = getClassContext();
- /* Magic number 2 identifies our caller's caller */
- Class<?> c = stack[2];
- ClassLoader cl = (c == null) ? null : c.getClassLoader();
+ private static ClassLoader getLoader(Class<?> caller) {
+ ClassLoader cl = caller == null ? null : caller.getClassLoader();
if (cl == null) {
// When the caller's loader is the boot class loader, cl is null
// here. In that case, ClassLoader.getSystemClassLoader() may
@@ -461,8 +459,6 @@
return cl;
}
- private static native Class<?>[] getClassContext();
-
/**
* A wrapper of ClassLoader.getSystemClassLoader().
*/
@@ -746,11 +742,11 @@
* if no resource bundle for the specified base name can be found
* @return a resource bundle for the given base name and the default locale
*/
+ @CallerSensitive
public static final ResourceBundle getBundle(String baseName)
{
return getBundleImpl(baseName, Locale.getDefault(),
- /* must determine loader here, else we break stack invariant */
- getLoader(),
+ getLoader(Reflection.getCallerClass()),
getDefaultControl(baseName));
}
@@ -788,11 +784,11 @@
* needed.
* @since 1.6
*/
+ @CallerSensitive
public static final ResourceBundle getBundle(String baseName,
Control control) {
return getBundleImpl(baseName, Locale.getDefault(),
- /* must determine loader here, else we break stack invariant */
- getLoader(),
+ getLoader(Reflection.getCallerClass()),
control);
}
@@ -817,12 +813,12 @@
* if no resource bundle for the specified base name can be found
* @return a resource bundle for the given base name and locale
*/
+ @CallerSensitive
public static final ResourceBundle getBundle(String baseName,
Locale locale)
{
return getBundleImpl(baseName, locale,
- /* must determine loader here, else we break stack invariant */
- getLoader(),
+ getLoader(Reflection.getCallerClass()),
getDefaultControl(baseName));
}
@@ -863,11 +859,11 @@
* needed.
* @since 1.6
*/
+ @CallerSensitive
public static final ResourceBundle getBundle(String baseName, Locale targetLocale,
Control control) {
return getBundleImpl(baseName, targetLocale,
- /* must determine loader here, else we break stack invariant */
- getLoader(),
+ getLoader(Reflection.getCallerClass()),
control);
}
@@ -1721,8 +1717,9 @@
* @since 1.6
* @see ResourceBundle.Control#getTimeToLive(String,Locale)
*/
+ @CallerSensitive
public static final void clearCache() {
- clearCache(getLoader());
+ clearCache(getLoader(Reflection.getCallerClass()));
}
/**
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentHashMap.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentHashMap.java Wed Apr 17 02:53:02 2013 -0700
@@ -34,6 +34,7 @@
*/
package java.util.concurrent;
+import java.io.ObjectInputStream;
import java.util.concurrent.locks.*;
import java.util.*;
import java.io.Serializable;
@@ -1483,7 +1484,23 @@
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
- s.defaultReadObject();
+ // Don't call defaultReadObject()
+ ObjectInputStream.GetField oisFields = s.readFields();
+ final Segment<K,V>[] oisSegments = (Segment<K,V>[])oisFields.get("segments", null);
+
+ final int ssize = oisSegments.length;
+ if (ssize < 1 || ssize > MAX_SEGMENTS
+ || (ssize & (ssize-1)) != 0 ) // ssize not power of two
+ throw new java.io.InvalidObjectException("Bad number of segments:"
+ + ssize);
+ int sshift = 0, ssizeTmp = ssize;
+ while (ssizeTmp > 1) {
+ ++sshift;
+ ssizeTmp >>>= 1;
+ }
+ UNSAFE.putIntVolatile(this, SEGSHIFT_OFFSET, 32 - sshift);
+ UNSAFE.putIntVolatile(this, SEGMASK_OFFSET, ssize - 1);
+ UNSAFE.putObjectVolatile(this, SEGMENTS_OFFSET, oisSegments);
// set hashMask
UNSAFE.putIntVolatile(this, HASHSEED_OFFSET,
@@ -1517,6 +1534,9 @@
private static final long TBASE;
private static final int TSHIFT;
private static final long HASHSEED_OFFSET;
+ private static final long SEGSHIFT_OFFSET;
+ private static final long SEGMASK_OFFSET;
+ private static final long SEGMENTS_OFFSET;
static {
int ss, ts;
@@ -1530,6 +1550,12 @@
ss = UNSAFE.arrayIndexScale(sc);
HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
ConcurrentHashMap.class.getDeclaredField("hashSeed"));
+ SEGSHIFT_OFFSET = UNSAFE.objectFieldOffset(
+ ConcurrentHashMap.class.getDeclaredField("segmentShift"));
+ SEGMASK_OFFSET = UNSAFE.objectFieldOffset(
+ ConcurrentHashMap.class.getDeclaredField("segmentMask"));
+ SEGMENTS_OFFSET = UNSAFE.objectFieldOffset(
+ ConcurrentHashMap.class.getDeclaredField("segments"));
} catch (Exception e) {
throw new Error(e);
}
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentMap.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentMap.java Wed Apr 17 02:53:02 2013 -0700
@@ -38,7 +38,7 @@
/**
* A {@link java.util.Map} providing additional atomic
- * <tt>putIfAbsent</tt>, <tt>remove</tt>, and <tt>replace</tt> methods.
+ * {@code putIfAbsent}, {@code remove}, and {@code replace} methods.
*
* <p>Memory consistency effects: As with other concurrent
* collections, actions in a thread prior to placing an object into a
@@ -57,6 +57,21 @@
* @param <V> the type of mapped values
*/
public interface ConcurrentMap<K, V> extends Map<K, V> {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @implNote This implementation assumes that the ConcurrentMap cannot
+ * contain null values and get() returning null unambiguously means the key
+ * is absent. Implementations which support null values must override this
+ * default implementation.
+ */
+ @Override
+ default V getOrDefault(Object key, V defaultValue) {
+ V v;
+ return ((v = get(key)) != null) ? v : defaultValue;
+ }
+
/**
* If the specified key is not already associated
* with a value, associate it with the given value.
@@ -91,7 +106,7 @@
* Removes the entry for a key only if currently mapped to a given value.
* This is equivalent to
* <pre> {@code
- * if (map.containsKey(key) && map.get(key).equals(value)) {
+ * if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
* map.remove(key);
* return true;
* } else
@@ -101,8 +116,8 @@
*
* @param key key with which the specified value is associated
* @param value value expected to be associated with the specified key
- * @return <tt>true</tt> if the value was removed
- * @throws UnsupportedOperationException if the <tt>remove</tt> operation
+ * @return {@code true} if the value was removed
+ * @throws UnsupportedOperationException if the {@code remove} operation
* is not supported by this map
* @throws ClassCastException if the key or value is of an inappropriate
* type for this map
@@ -117,7 +132,7 @@
* Replaces the entry for a key only if currently mapped to a given value.
* This is equivalent to
* <pre> {@code
- * if (map.containsKey(key) && map.get(key).equals(oldValue)) {
+ * if (map.containsKey(key) && Objects.equals(map.get(key), oldValue)) {
* map.put(key, newValue);
* return true;
* } else
@@ -128,8 +143,8 @@
* @param key key with which the specified value is associated
* @param oldValue value expected to be associated with the specified key
* @param newValue value to be associated with the specified key
- * @return <tt>true</tt> if the value was replaced
- * @throws UnsupportedOperationException if the <tt>put</tt> operation
+ * @return {@code true} if the value was replaced
+ * @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
* @throws ClassCastException if the class of a specified key or value
* prevents it from being stored in this map
@@ -154,11 +169,11 @@
* @param key key with which the specified value is associated
* @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or
- * <tt>null</tt> if there was no mapping for the key.
- * (A <tt>null</tt> return can also indicate that the map
- * previously associated <tt>null</tt> with the key,
+ * {@code null} if there was no mapping for the key.
+ * (A {@code null} return can also indicate that the map
+ * previously associated {@code null} with the key,
* if the implementation supports null values.)
- * @throws UnsupportedOperationException if the <tt>put</tt> operation
+ * @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
* @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Wed Apr 17 02:53:02 2013 -0700
@@ -37,6 +37,9 @@
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
+
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
@@ -77,8 +80,9 @@
* or the field is inaccessible to the caller according to Java language
* access control
*/
+ @CallerSensitive
public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
- return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
+ return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName, Reflection.getCallerClass());
}
/**
@@ -365,9 +369,11 @@
private final Class<T> tclass;
private final Class<?> cclass;
- AtomicIntegerFieldUpdaterImpl(final Class<T> tclass, final String fieldName) {
+ AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
+ final String fieldName,
+ final Class<?> caller)
+ {
final Field field;
- final Class<?> caller;
final int modifiers;
try {
field = AccessController.doPrivileged(
@@ -376,7 +382,6 @@
return tclass.getDeclaredField(fieldName);
}
});
- caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers);
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Wed Apr 17 02:53:02 2013 -0700
@@ -37,6 +37,9 @@
import java.util.function.LongUnaryOperator;
import java.util.function.LongBinaryOperator;
import sun.misc.Unsafe;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
+
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
@@ -77,11 +80,13 @@
* or the field is inaccessible to the caller according to Java language
* access control
*/
+ @CallerSensitive
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
+ Class<?> caller = Reflection.getCallerClass();
if (AtomicLong.VM_SUPPORTS_LONG_CAS)
- return new CASUpdater<U>(tclass, fieldName);
+ return new CASUpdater<U>(tclass, fieldName, caller);
else
- return new LockedUpdater<U>(tclass, fieldName);
+ return new LockedUpdater<U>(tclass, fieldName, caller);
}
/**
@@ -365,9 +370,8 @@
private final Class<T> tclass;
private final Class<?> cclass;
- CASUpdater(final Class<T> tclass, final String fieldName) {
+ CASUpdater(final Class<T> tclass, final String fieldName, final Class<?> caller) {
final Field field;
- final Class<?> caller;
final int modifiers;
try {
field = AccessController.doPrivileged(
@@ -376,7 +380,6 @@
return tclass.getDeclaredField(fieldName);
}
});
- caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers);
@@ -490,9 +493,8 @@
private final Class<T> tclass;
private final Class<?> cclass;
- LockedUpdater(final Class<T> tclass, final String fieldName) {
+ LockedUpdater(final Class<T> tclass, final String fieldName, final Class<?> caller) {
Field field = null;
- Class<?> caller = null;
int modifiers = 0;
try {
field = AccessController.doPrivileged(
@@ -501,7 +503,6 @@
return tclass.getDeclaredField(fieldName);
}
});
- caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers);
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Wed Apr 17 02:53:02 2013 -0700
@@ -37,6 +37,9 @@
import java.util.function.UnaryOperator;
import java.util.function.BinaryOperator;
import sun.misc.Unsafe;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
+
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
@@ -96,10 +99,12 @@
* or the field is inaccessible to the caller according to Java language
* access control
*/
+ @CallerSensitive
public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
vclass,
- fieldName);
+ fieldName,
+ Reflection.getCallerClass());
}
/**
@@ -297,10 +302,11 @@
AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
Class<V> vclass,
- final String fieldName) {
+ final String fieldName,
+ final Class<?> caller)
+ {
final Field field;
final Class<?> fieldClass;
- final Class<?> caller;
final int modifiers;
try {
field = AccessController.doPrivileged(
@@ -309,7 +315,6 @@
return tclass.getDeclaredField(fieldName);
}
});
- caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers);
--- a/jdk/src/share/classes/java/util/logging/Logger.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/java/util/logging/Logger.java Wed Apr 17 02:53:02 2013 -0700
@@ -36,6 +36,8 @@
import java.util.ResourceBundle;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Supplier;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
/**
* A Logger object is used to log messages for a specific
@@ -333,13 +335,10 @@
}
}
- private static Logger demandLogger(String name, String resourceBundleName) {
+ private static Logger demandLogger(String name, String resourceBundleName, Class<?> caller) {
LogManager manager = LogManager.getLogManager();
SecurityManager sm = System.getSecurityManager();
if (sm != null && !SystemLoggerHelper.disableCallerCheck) {
- // 0: Reflection 1: Logger.demandLogger 2: Logger.getLogger 3: caller
- final int SKIP_FRAMES = 3;
- Class<?> caller = sun.reflect.Reflection.getCallerClass(SKIP_FRAMES);
if (caller.getClassLoader() == null) {
return manager.demandSystemLogger(name, resourceBundleName);
}
@@ -377,6 +376,7 @@
// Synchronization is not required here. All synchronization for
// adding a new Logger object is handled by LogManager.addLogger().
+ @CallerSensitive
public static Logger getLogger(String name) {
// This method is intentionally not a wrapper around a call
// to getLogger(name, resourceBundleName). If it were then
@@ -388,7 +388,7 @@
// would throw an IllegalArgumentException in the second call
// because the wrapper would result in an attempt to replace
// the existing "resourceBundleForFoo" with null.
- return demandLogger(name, null);
+ return demandLogger(name, null, Reflection.getCallerClass());
}
/**
@@ -434,8 +434,9 @@
// Synchronization is not required here. All synchronization for
// adding a new Logger object is handled by LogManager.addLogger().
+ @CallerSensitive
public static Logger getLogger(String name, String resourceBundleName) {
- Logger result = demandLogger(name, resourceBundleName);
+ Logger result = demandLogger(name, resourceBundleName, Reflection.getCallerClass());
// MissingResourceException or IllegalArgumentException can be
// thrown by setupResourceInfo().
--- a/jdk/src/share/classes/javax/script/ScriptEngineManager.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/javax/script/ScriptEngineManager.java Wed Apr 17 02:53:02 2013 -0700
@@ -28,6 +28,7 @@
import java.security.*;
import java.util.ServiceLoader;
import java.util.ServiceConfigurationError;
+import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;
@@ -60,9 +61,10 @@
*
* @see java.lang.Thread#getContextClassLoader
*/
+ @CallerSensitive
public ScriptEngineManager() {
ClassLoader ctxtLoader = Thread.currentThread().getContextClassLoader();
- if (canCallerAccessLoader(ctxtLoader)) {
+ if (canCallerAccessLoader(ctxtLoader, Reflection.getCallerClass())) {
if (DEBUG) System.out.println("using " + ctxtLoader);
init(ctxtLoader);
} else {
@@ -419,10 +421,10 @@
/** Global bindings associated with script engines created by this manager. */
private Bindings globalScope;
- private boolean canCallerAccessLoader(ClassLoader loader) {
+ private boolean canCallerAccessLoader(ClassLoader loader, Class<?> caller) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- ClassLoader callerLoader = getCallerClassLoader();
+ ClassLoader callerLoader = getClassLoader(caller);
if (!sun.misc.VM.isSystemDomainLoader(callerLoader)) {
if (loader != callerLoader || !isAncestor(loader, callerLoader)) {
try {
@@ -438,10 +440,9 @@
return true;
}
- // Note that this code is same as ClassLoader.getCallerClassLoader().
+ // Note that this code is same as ClassLoader.getClassLoader().
// But, that method is package private and hence we can't call here.
- private ClassLoader getCallerClassLoader() {
- Class<?> caller = Reflection.getCallerClass(3);
+ private ClassLoader getClassLoader(Class<?> caller) {
if (caller == null) {
return null;
}
--- a/jdk/src/share/classes/sun/awt/EmbeddedFrame.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/awt/EmbeddedFrame.java Wed Apr 17 02:53:02 2013 -0700
@@ -539,7 +539,7 @@
public void toBack() {}
public void updateFocusableWindowState() {}
public void updateAlwaysOnTop() {}
- public void setAlwaysOnTop(boolean alwaysOnTop) {}
+ public void updateAlwaysOnTopState() {}
public Component getGlobalHeavyweightFocusOwner() { return null; }
public void setBoundsPrivate(int x, int y, int width, int height) {
setBounds(x, y, width, height, SET_BOUNDS);
--- a/jdk/src/share/classes/sun/awt/datatransfer/TransferableProxy.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/awt/datatransfer/TransferableProxy.java Wed Apr 17 02:53:02 2013 -0700
@@ -102,11 +102,11 @@
protected final boolean isLocal;
}
-class ClassLoaderObjectOutputStream extends ObjectOutputStream {
+final class ClassLoaderObjectOutputStream extends ObjectOutputStream {
private final Map<Set<String>, ClassLoader> map =
new HashMap<Set<String>, ClassLoader>();
- public ClassLoaderObjectOutputStream(OutputStream os) throws IOException {
+ ClassLoaderObjectOutputStream(OutputStream os) throws IOException {
super(os);
}
@@ -140,16 +140,16 @@
map.put(s, classLoader);
}
- public Map<Set<String>, ClassLoader> getClassLoaderMap() {
+ Map<Set<String>, ClassLoader> getClassLoaderMap() {
return new HashMap(map);
}
}
-class ClassLoaderObjectInputStream extends ObjectInputStream {
+final class ClassLoaderObjectInputStream extends ObjectInputStream {
private final Map<Set<String>, ClassLoader> map;
- public ClassLoaderObjectInputStream(InputStream is,
- Map<Set<String>, ClassLoader> map)
+ ClassLoaderObjectInputStream(InputStream is,
+ Map<Set<String>, ClassLoader> map)
throws IOException {
super(is);
if (map == null) {
@@ -166,8 +166,11 @@
s.add(className);
ClassLoader classLoader = map.get(s);
-
- return Class.forName(className, false, classLoader);
+ if (classLoader != null) {
+ return Class.forName(className, false, classLoader);
+ } else {
+ return super.resolveClass(classDesc);
+ }
}
protected Class<?> resolveProxyClass(String[] interfaces)
@@ -179,6 +182,9 @@
}
ClassLoader classLoader = map.get(s);
+ if (classLoader == null) {
+ return super.resolveProxyClass(interfaces);
+ }
// The code below is mostly copied from the superclass.
ClassLoader nonPublicLoader = null;
--- a/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java Wed Apr 17 02:53:02 2013 -0700
@@ -868,6 +868,15 @@
* or if data buffer has not enough capacity.
*/
protected final void verify() {
+ /* Need to re-verify the dimensions since a sample model may be
+ * specified to the constructor
+ */
+ if (width <= 0 || height <= 0 ||
+ height > (Integer.MAX_VALUE / width))
+ {
+ throw new RasterFormatException("Invalid raster dimension");
+ }
+
for (int i = 0; i < dataOffsets.length; i++) {
if (dataOffsets[i] < 0) {
throw new RasterFormatException("Data offsets for band " + i
@@ -905,13 +914,14 @@
lastPixelOffset += lastScanOffset;
for (int i = 0; i < numDataElements; i++) {
- size = lastPixelOffset + dataOffsets[i];
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
throw new RasterFormatException("Incorrect band offset: "
+ dataOffsets[i]);
}
+ size = lastPixelOffset + dataOffsets[i];
+
if (size > maxSize) {
maxSize = size;
}
--- a/jdk/src/share/classes/sun/awt/image/BytePackedRaster.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/awt/image/BytePackedRaster.java Wed Apr 17 02:53:02 2013 -0700
@@ -1368,11 +1368,35 @@
throw new RasterFormatException("Data offsets must be >= 0");
}
+ /* Need to re-verify the dimensions since a sample model may be
+ * specified to the constructor
+ */
+ if (width <= 0 || height <= 0 ||
+ height > (Integer.MAX_VALUE / width))
+ {
+ throw new RasterFormatException("Invalid raster dimension");
+ }
+
+
+ /*
+ * pixelBitstride was verified in constructor, so just make
+ * sure that it is safe to multiply it by width.
+ */
+ if ((width - 1) > Integer.MAX_VALUE / pixelBitStride) {
+ throw new RasterFormatException("Invalid raster dimension");
+ }
+
+ if (scanlineStride < 0 ||
+ scanlineStride > (Integer.MAX_VALUE / height))
+ {
+ throw new RasterFormatException("Invalid scanline stride");
+ }
+
int lastbit = (dataBitOffset
+ (height-1) * scanlineStride * 8
+ (width-1) * pixelBitStride
+ pixelBitStride - 1);
- if (lastbit / 8 >= data.length) {
+ if (lastbit < 0 || lastbit / 8 >= data.length) {
throw new RasterFormatException("raster dimensions overflow " +
"array bounds");
}
--- a/jdk/src/share/classes/sun/awt/image/ImageRepresentation.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/awt/image/ImageRepresentation.java Wed Apr 17 02:53:02 2013 -0700
@@ -333,10 +333,10 @@
hints = h;
}
- private native void setICMpixels(int x, int y, int w, int h, int[] lut,
+ private native boolean setICMpixels(int x, int y, int w, int h, int[] lut,
byte[] pix, int off, int scansize,
IntegerComponentRaster ict);
- private native int setDiffICM(int x, int y, int w, int h, int[] lut,
+ private native boolean setDiffICM(int x, int y, int w, int h, int[] lut,
int transPix, int numLut, IndexColorModel icm,
byte[] pix, int off, int scansize,
ByteComponentRaster bct, int chanOff);
@@ -426,10 +426,10 @@
IndexColorModel icm = (IndexColorModel) model;
ByteComponentRaster bct = (ByteComponentRaster) biRaster;
int numlut = numSrcLUT;
- if (setDiffICM(x, y, w, h, srcLUT, srcLUTtransIndex,
+ if (!setDiffICM(x, y, w, h, srcLUT, srcLUTtransIndex,
numSrcLUT, icm,
pix, off, scansize, bct,
- bct.getDataOffset(0)) == 0) {
+ bct.getDataOffset(0))) {
convertToRGB();
}
else {
@@ -470,9 +470,14 @@
if (s_useNative) {
// Note that setICMpixels modifies the raster directly
// so we must mark it as changed afterwards
- setICMpixels(x, y, w, h, srcLUT, pix, off, scansize,
- iraster);
- iraster.markDirty();
+ if (setICMpixels(x, y, w, h, srcLUT, pix, off, scansize,
+ iraster))
+ {
+ iraster.markDirty();
+ } else {
+ abort();
+ return;
+ }
}
else {
int[] storage = new int[w*h];
--- a/jdk/src/share/classes/sun/awt/image/IntegerComponentRaster.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/awt/image/IntegerComponentRaster.java Wed Apr 17 02:53:02 2013 -0700
@@ -208,7 +208,7 @@
" SinglePixelPackedSampleModel");
}
- verify(false);
+ verify();
}
@@ -629,16 +629,26 @@
}
/**
- * Verify that the layout parameters are consistent with
- * the data. If strictCheck
- * is false, this method will check for ArrayIndexOutOfBounds conditions. If
- * strictCheck is true, this method will check for additional error
- * conditions such as line wraparound (width of a line greater than
- * the scanline stride).
- * @return String Error string, if the layout is incompatible with
- * the data. Otherwise returns null.
+ * Verify that the layout parameters are consistent with the data.
+ *
+ * The method verifies whether scanline stride and pixel stride do not
+ * cause an integer overflow during calculation of a position of the pixel
+ * in data buffer. It also verifies whether the data buffer has enough data
+ * to correspond the raster layout attributes.
+ *
+ * @throws RasterFormatException if an integer overflow is detected,
+ * or if data buffer has not enough capacity.
*/
- private void verify (boolean strictCheck) {
+ protected final void verify() {
+ /* Need to re-verify the dimensions since a sample model may be
+ * specified to the constructor
+ */
+ if (width <= 0 || height <= 0 ||
+ height > (Integer.MAX_VALUE / width))
+ {
+ throw new RasterFormatException("Invalid raster dimension");
+ }
+
if (dataOffsets[0] < 0) {
throw new RasterFormatException("Data offset ("+dataOffsets[0]+
") must be >= 0");
@@ -647,17 +657,46 @@
int maxSize = 0;
int size;
- for (int i=0; i < numDataElements; i++) {
- size = (height-1)*scanlineStride + (width-1)*pixelStride +
- dataOffsets[i];
+ // we can be sure that width and height are greater than 0
+ if (scanlineStride < 0 ||
+ scanlineStride > (Integer.MAX_VALUE / height))
+ {
+ // integer overflow
+ throw new RasterFormatException("Incorrect scanline stride: "
+ + scanlineStride);
+ }
+ int lastScanOffset = (height - 1) * scanlineStride;
+
+ if (pixelStride < 0 ||
+ pixelStride > (Integer.MAX_VALUE / width))
+ {
+ // integer overflow
+ throw new RasterFormatException("Incorrect pixel stride: "
+ + pixelStride);
+ }
+ int lastPixelOffset = (width - 1) * pixelStride;
+
+ if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) {
+ // integer overflow
+ throw new RasterFormatException("Incorrect raster attributes");
+ }
+ lastPixelOffset += lastScanOffset;
+
+ for (int i = 0; i < numDataElements; i++) {
+ if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
+ throw new RasterFormatException("Incorrect band offset: "
+ + dataOffsets[i]);
+ }
+
+ size = lastPixelOffset + dataOffsets[i];
+
if (size > maxSize) {
maxSize = size;
}
}
if (data.length < maxSize) {
- throw new RasterFormatException("Data array too small (should be "+
- maxSize
- +" but is "+data.length+" )");
+ throw new RasterFormatException("Data array too small (should be "
+ + maxSize + " )");
}
}
--- a/jdk/src/share/classes/sun/awt/image/IntegerInterleavedRaster.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/awt/image/IntegerInterleavedRaster.java Wed Apr 17 02:53:02 2013 -0700
@@ -151,7 +151,7 @@
throw new RasterFormatException("IntegerInterleavedRasters must have"+
" SinglePixelPackedSampleModel");
}
- verify(false);
+ verify();
}
@@ -540,31 +540,6 @@
return createCompatibleWritableRaster(width,height);
}
- /**
- * Verify that the layout parameters are consistent with
- * the data. If strictCheck
- * is false, this method will check for ArrayIndexOutOfBounds conditions. If
- * strictCheck is true, this method will check for additional error
- * conditions such as line wraparound (width of a line greater than
- * the scanline stride).
- * @return String Error string, if the layout is incompatible with
- * the data. Otherwise returns null.
- */
- private void verify (boolean strictCheck) {
- int maxSize = 0;
- int size;
-
- size = (height-1)*scanlineStride + (width-1) + dataOffsets[0];
- if (size > maxSize) {
- maxSize = size;
- }
- if (data.length < maxSize) {
- throw new RasterFormatException("Data array too small (should be "+
- maxSize
- +" but is "+data.length+" )");
- }
- }
-
public String toString() {
return new String ("IntegerInterleavedRaster: width = "+width
+" height = " + height
--- a/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java Wed Apr 17 02:53:02 2013 -0700
@@ -802,6 +802,15 @@
* or if data buffer has not enough capacity.
*/
protected final void verify() {
+ /* Need to re-verify the dimensions since a sample model may be
+ * specified to the constructor
+ */
+ if (width <= 0 || height <= 0 ||
+ height > (Integer.MAX_VALUE / width))
+ {
+ throw new RasterFormatException("Invalid raster dimension");
+ }
+
for (int i = 0; i < dataOffsets.length; i++) {
if (dataOffsets[i] < 0) {
throw new RasterFormatException("Data offsets for band " + i
@@ -839,12 +848,13 @@
lastPixelOffset += lastScanOffset;
for (int i = 0; i < numDataElements; i++) {
- size = lastPixelOffset + dataOffsets[i];
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
throw new RasterFormatException("Incorrect band offset: "
+ dataOffsets[i]);
}
+ size = lastPixelOffset + dataOffsets[i];
+
if (size > maxSize) {
maxSize = size;
}
--- a/jdk/src/share/classes/sun/font/CMap.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/font/CMap.java Wed Apr 17 02:53:02 2013 -0700
@@ -841,7 +841,6 @@
CMapFormat6(ByteBuffer bbuffer, int offset, char[] xlat) {
- System.err.println("WARNING: CMapFormat8 is untested.");
bbuffer.position(offset+6);
CharBuffer buffer = bbuffer.asCharBuffer();
firstCode = buffer.get();
@@ -884,7 +883,6 @@
CMapFormat8(ByteBuffer bbuffer, int offset, char[] xlat) {
- System.err.println("WARNING: CMapFormat8 is untested.");
bbuffer.position(12);
bbuffer.get(is32);
nGroups = bbuffer.getInt();
@@ -915,7 +913,6 @@
CMapFormat10(ByteBuffer bbuffer, int offset, char[] xlat) {
- System.err.println("WARNING: CMapFormat10 is untested.");
firstCode = bbuffer.getInt() & INTMASK;
entryCount = bbuffer.getInt() & INTMASK;
bbuffer.position(offset+20);
--- a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java Wed Apr 17 02:53:02 2013 -0700
@@ -85,45 +85,72 @@
private boolean imageAtOnce = false;
Object dataArray;
- private LCMSImageLayout(int np, int pixelType, int pixelSize) {
+ private int dataArrayLength; /* in bytes */
+
+ private LCMSImageLayout(int np, int pixelType, int pixelSize)
+ throws ImageLayoutException
+ {
this.pixelType = pixelType;
width = np;
height = 1;
- nextRowOffset = np * pixelSize;
+ nextRowOffset = safeMult(pixelSize, np);
offset = 0;
}
private LCMSImageLayout(int width, int height, int pixelType,
- int pixelSize) {
+ int pixelSize)
+ throws ImageLayoutException
+ {
this.pixelType = pixelType;
this.width = width;
this.height = height;
- nextRowOffset = width * pixelSize;
+ nextRowOffset = safeMult(pixelSize, width);
offset = 0;
}
- public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize) {
+
+ public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize)
+ throws ImageLayoutException
+ {
this(np, pixelType, pixelSize);
dataType = DT_BYTE;
dataArray = data;
+ dataArrayLength = data.length;
+
+ verify();
}
- public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize) {
+ public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize)
+ throws ImageLayoutException
+ {
this(np, pixelType, pixelSize);
dataType = DT_SHORT;
dataArray = data;
+ dataArrayLength = 2 * data.length;
+
+ verify();
}
- public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize) {
+ public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize)
+ throws ImageLayoutException
+ {
this(np, pixelType, pixelSize);
dataType = DT_INT;
dataArray = data;
+ dataArrayLength = 4 * data.length;
+
+ verify();
}
- public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize) {
+ public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize)
+ throws ImageLayoutException
+ {
this(np, pixelType, pixelSize);
dataType = DT_DOUBLE;
dataArray = data;
+ dataArrayLength = 8 * data.length;
+
+ verify();
}
private LCMSImageLayout() {
@@ -132,7 +159,7 @@
/* This method creates a layout object for given image.
* Returns null if the image is not supported by current implementation.
*/
- public static LCMSImageLayout createImageLayout(BufferedImage image) {
+ public static LCMSImageLayout createImageLayout(BufferedImage image) throws ImageLayoutException {
LCMSImageLayout l = new LCMSImageLayout();
switch (image.getType()) {
@@ -193,9 +220,10 @@
do {
IntegerComponentRaster intRaster = (IntegerComponentRaster)
image.getRaster();
- l.nextRowOffset = intRaster.getScanlineStride() * 4;
- l.offset = intRaster.getDataOffset(0) * 4;
+ l.nextRowOffset = safeMult(4, intRaster.getScanlineStride());
+ l.offset = safeMult(4, intRaster.getDataOffset(0));
l.dataArray = intRaster.getDataStorage();
+ l.dataArrayLength = 4 * intRaster.getDataStorage().length;
l.dataType = DT_INT;
if (l.nextRowOffset == l.width * 4 * intRaster.getPixelStride()) {
@@ -213,6 +241,7 @@
int firstBand = image.getSampleModel().getNumBands() - 1;
l.offset = byteRaster.getDataOffset(firstBand);
l.dataArray = byteRaster.getDataStorage();
+ l.dataArrayLength = byteRaster.getDataStorage().length;
l.dataType = DT_BYTE;
if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
l.imageAtOnce = true;
@@ -225,6 +254,7 @@
ByteComponentRaster byteRaster = (ByteComponentRaster)
image.getRaster();
l.nextRowOffset = byteRaster.getScanlineStride();
+ l.dataArrayLength = byteRaster.getDataStorage().length;
l.offset = byteRaster.getDataOffset(0);
l.dataArray = byteRaster.getDataStorage();
l.dataType = DT_BYTE;
@@ -239,9 +269,10 @@
do {
ShortComponentRaster shortRaster = (ShortComponentRaster)
image.getRaster();
- l.nextRowOffset = shortRaster.getScanlineStride() * 2;
- l.offset = shortRaster.getDataOffset(0) * 2;
+ l.nextRowOffset = safeMult(2, shortRaster.getScanlineStride());
+ l.offset = safeMult(2, shortRaster.getDataOffset(0));
l.dataArray = shortRaster.getDataStorage();
+ l.dataArrayLength = 2 * shortRaster.getDataStorage().length;
l.dataType = DT_SHORT;
if (l.nextRowOffset == l.width * 2 * shortRaster.getPixelStride()) {
@@ -252,6 +283,7 @@
default:
return null;
}
+ l.verify();
return l;
}
@@ -293,6 +325,46 @@
}
}
+ private void verify() throws ImageLayoutException {
+
+ if (offset < 0 || offset >= dataArrayLength) {
+ throw new ImageLayoutException("Invalid image layout");
+ }
+
+ int lastPixelOffset = safeMult(nextRowOffset, (height - 1));
+
+ lastPixelOffset = safeAdd(lastPixelOffset, (width - 1));
+
+ int off = safeAdd(offset, lastPixelOffset);
+
+ if (off < 0 || off >= dataArrayLength) {
+ throw new ImageLayoutException("Invalid image layout");
+ }
+ }
+
+ static int safeAdd(int a, int b) throws ImageLayoutException {
+ long res = a;
+ res += b;
+ if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) {
+ throw new ImageLayoutException("Invalid image layout");
+ }
+ return (int)res;
+ }
+
+ static int safeMult(int a, int b) throws ImageLayoutException {
+ long res = a;
+ res *= b;
+ if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) {
+ throw new ImageLayoutException("Invalid image layout");
+ }
+ return (int)res;
+ }
+
+ public static class ImageLayoutException extends Exception {
+ public ImageLayoutException(String message) {
+ super(message);
+ }
+ }
public static LCMSImageLayout createImageLayout(Raster r) {
LCMSImageLayout l = new LCMSImageLayout();
if (r instanceof ByteComponentRaster) {
--- a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java Wed Apr 17 02:53:02 2013 -0700
@@ -51,6 +51,7 @@
import java.awt.image.ComponentSampleModel;
import sun.java2d.cmm.*;
import sun.java2d.cmm.lcms.*;
+import static sun.java2d.cmm.lcms.LCMSImageLayout.ImageLayoutException;
public class LCMSTransform implements ColorTransform {
@@ -162,15 +163,19 @@
public void colorConvert(BufferedImage src, BufferedImage dst) {
LCMSImageLayout srcIL, dstIL;
+ try {
- dstIL = LCMSImageLayout.createImageLayout(dst);
+ dstIL = LCMSImageLayout.createImageLayout(dst);
- if (dstIL != null) {
- srcIL = LCMSImageLayout.createImageLayout(src);
- if (srcIL != null) {
- doTransform(srcIL, dstIL);
- return;
+ if (dstIL != null) {
+ srcIL = LCMSImageLayout.createImageLayout(src);
+ if (srcIL != null) {
+ doTransform(srcIL, dstIL);
+ return;
+ }
}
+ } catch (ImageLayoutException e) {
+ throw new CMMException("Unable to convert images");
}
Raster srcRas = src.getRaster();
@@ -228,14 +233,18 @@
}
int idx;
// TODO check for src npixels = dst npixels
- srcIL = new LCMSImageLayout(
- srcLine, srcLine.length/getNumInComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
- LCMSImageLayout.BYTES_SH(1), getNumInComponents());
- dstIL = new LCMSImageLayout(
- dstLine, dstLine.length/getNumOutComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
- LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
+ try {
+ srcIL = new LCMSImageLayout(
+ srcLine, srcLine.length/getNumInComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
+ LCMSImageLayout.BYTES_SH(1), getNumInComponents());
+ dstIL = new LCMSImageLayout(
+ dstLine, dstLine.length/getNumOutComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
+ LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
+ } catch (ImageLayoutException e) {
+ throw new CMMException("Unable to convert images");
+ }
// process each scanline
for (int y = 0; y < h; y++) {
// convert src scanline
@@ -284,16 +293,19 @@
alpha = new float[w];
}
int idx;
- srcIL = new LCMSImageLayout(
- srcLine, srcLine.length/getNumInComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
- LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
+ try {
+ srcIL = new LCMSImageLayout(
+ srcLine, srcLine.length/getNumInComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
+ LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
- dstIL = new LCMSImageLayout(
- dstLine, dstLine.length/getNumOutComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
- LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
-
+ dstIL = new LCMSImageLayout(
+ dstLine, dstLine.length/getNumOutComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
+ LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
+ } catch (ImageLayoutException e) {
+ throw new CMMException("Unable to convert images");
+ }
// process each scanline
for (int y = 0; y < h; y++) {
// convert src scanline
@@ -402,16 +414,19 @@
short[] srcLine = new short[w * srcNumBands];
short[] dstLine = new short[w * dstNumBands];
int idx;
- srcIL = new LCMSImageLayout(
- srcLine, srcLine.length/getNumInComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
- LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
+ try {
+ srcIL = new LCMSImageLayout(
+ srcLine, srcLine.length/getNumInComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
+ LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
- dstIL = new LCMSImageLayout(
- dstLine, dstLine.length/getNumOutComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
- LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
-
+ dstIL = new LCMSImageLayout(
+ dstLine, dstLine.length/getNumOutComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
+ LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
+ } catch (ImageLayoutException e) {
+ throw new CMMException("Unable to convert rasters");
+ }
// process each scanline
for (int y = 0; y < h; y++, ys++, yd++) {
// get src scanline
@@ -502,15 +517,18 @@
byte[] dstLine = new byte[w * dstNumBands];
int idx;
// TODO check for src npixels = dst npixels
- srcIL = new LCMSImageLayout(
- srcLine, srcLine.length/getNumInComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
- LCMSImageLayout.BYTES_SH(1), getNumInComponents());
- dstIL = new LCMSImageLayout(
- dstLine, dstLine.length/getNumOutComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
- LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
-
+ try {
+ srcIL = new LCMSImageLayout(
+ srcLine, srcLine.length/getNumInComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
+ LCMSImageLayout.BYTES_SH(1), getNumInComponents());
+ dstIL = new LCMSImageLayout(
+ dstLine, dstLine.length/getNumOutComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
+ LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
+ } catch (ImageLayoutException e) {
+ throw new CMMException("Unable to convert rasters");
+ }
// process each scanline
for (int y = 0; y < h; y++, ys++, yd++) {
// get src scanline
@@ -542,16 +560,20 @@
short[] srcLine = new short[w * srcNumBands];
short[] dstLine = new short[w * dstNumBands];
int idx;
- srcIL = new LCMSImageLayout(
- srcLine, srcLine.length/getNumInComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
- LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
+
+ try {
+ srcIL = new LCMSImageLayout(
+ srcLine, srcLine.length/getNumInComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
+ LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
- dstIL = new LCMSImageLayout(
- dstLine, dstLine.length/getNumOutComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
- LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
-
+ dstIL = new LCMSImageLayout(
+ dstLine, dstLine.length/getNumOutComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
+ LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
+ } catch (ImageLayoutException e) {
+ throw new CMMException("Unable to convert rasters");
+ }
// process each scanline
for (int y = 0; y < h; y++, ys++, yd++) {
// get src scanline
@@ -592,19 +614,23 @@
dst = new short [(src.length/getNumInComponents())*getNumOutComponents()];
}
- LCMSImageLayout srcIL = new LCMSImageLayout(
- src, src.length/getNumInComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
- LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
+ try {
+ LCMSImageLayout srcIL = new LCMSImageLayout(
+ src, src.length/getNumInComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
+ LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
- LCMSImageLayout dstIL = new LCMSImageLayout(
- dst, dst.length/getNumOutComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
- LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
+ LCMSImageLayout dstIL = new LCMSImageLayout(
+ dst, dst.length/getNumOutComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
+ LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
- doTransform(srcIL, dstIL);
+ doTransform(srcIL, dstIL);
- return dst;
+ return dst;
+ } catch (ImageLayoutException e) {
+ throw new CMMException("Unable to convert data");
+ }
}
public byte[] colorConvert(byte[] src, byte[] dst) {
@@ -612,18 +638,22 @@
dst = new byte [(src.length/getNumInComponents())*getNumOutComponents()];
}
- LCMSImageLayout srcIL = new LCMSImageLayout(
- src, src.length/getNumInComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
- LCMSImageLayout.BYTES_SH(1), getNumInComponents());
+ try {
+ LCMSImageLayout srcIL = new LCMSImageLayout(
+ src, src.length/getNumInComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
+ LCMSImageLayout.BYTES_SH(1), getNumInComponents());
- LCMSImageLayout dstIL = new LCMSImageLayout(
- dst, dst.length/getNumOutComponents(),
- LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
- LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
+ LCMSImageLayout dstIL = new LCMSImageLayout(
+ dst, dst.length/getNumOutComponents(),
+ LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
+ LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
- doTransform(srcIL, dstIL);
+ doTransform(srcIL, dstIL);
- return dst;
+ return dst;
+ } catch (ImageLayoutException e) {
+ throw new CMMException("Unable to convert data");
+ }
}
}
--- a/jdk/src/share/classes/sun/misc/Unsafe.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/misc/Unsafe.java Wed Apr 17 02:53:02 2013 -0700
@@ -28,6 +28,9 @@
import java.security.*;
import java.lang.reflect.*;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
+
/**
* A collection of methods for performing low-level, unsafe operations.
@@ -80,9 +83,10 @@
* <code>checkPropertiesAccess</code> method doesn't allow
* access to the system properties.
*/
+ @CallerSensitive
public static Unsafe getUnsafe() {
- Class<?> cc = sun.reflect.Reflection.getCallerClass(2);
- if (!VM.isSystemDomainLoader(cc.getClassLoader()))
+ Class<?> caller = Reflection.getCallerClass();
+ if (!VM.isSystemDomainLoader(caller.getClassLoader()))
throw new SecurityException("Unsafe");
return theUnsafe;
}
@@ -817,8 +821,6 @@
ClassLoader loader,
ProtectionDomain protectionDomain);
- public native Class<?> defineClass(String name, byte[] b, int off, int len);
-
/**
* Define a class but do not make it known to the class loader or system dictionary.
* <p>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/reflect/CallerSensitive.java Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,41 @@
+/*
+ * 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. 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.reflect;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+
+/**
+ * A method annotated @CallerSensitive is sensitive to its calling class,
+ * via {@link sun.reflect.Reflection#getCallerClass Reflection.getCallerClass},
+ * or via some equivalent.
+ *
+ * @author John R. Rose
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({CONSTRUCTOR, METHOD})
+public @interface CallerSensitive {
+}
--- a/jdk/src/share/classes/sun/reflect/Reflection.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/reflect/Reflection.java Wed Apr 17 02:53:02 2013 -0700
@@ -51,16 +51,11 @@
methodFilterMap = new HashMap<>();
}
- /** Returns the class of the method <code>realFramesToSkip</code>
- frames up the stack (zero-based), ignoring frames associated
- with java.lang.reflect.Method.invoke() and its implementation.
- The first frame is that associated with this method, so
- <code>getCallerClass(0)</code> returns the Class object for
- sun.reflect.Reflection. Frames associated with
- java.lang.reflect.Method.invoke() and its implementation are
- completely ignored and do not count toward the number of "real"
- frames skipped. */
- public static native Class<?> getCallerClass(int realFramesToSkip);
+ /** Returns the class of the caller of the method calling this method,
+ ignoring frames associated with java.lang.reflect.Method.invoke()
+ and its implementation. */
+ @CallerSensitive
+ public static native Class<?> getCallerClass();
/** Retrieves the access flags written to the class file. For
inner classes these flags may differ from those returned by
@@ -321,4 +316,27 @@
}
return newMembers;
}
+
+ /**
+ * Tests if the given method is caller-sensitive and the declaring class
+ * is defined by either the bootstrap class loader or extension class loader.
+ */
+ public static boolean isCallerSensitive(Method m) {
+ final ClassLoader loader = m.getDeclaringClass().getClassLoader();
+ if (sun.misc.VM.isSystemDomainLoader(loader) || isExtClassLoader(loader)) {
+ return m.isAnnotationPresent(CallerSensitive.class);
+ }
+ return false;
+ }
+
+ private static boolean isExtClassLoader(ClassLoader loader) {
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ while (cl != null) {
+ if (cl.getParent() == null && cl == loader) {
+ return true;
+ }
+ cl = cl.getParent();
+ }
+ return false;
+ }
}
--- a/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java Wed Apr 17 02:53:02 2013 -0700
@@ -46,8 +46,28 @@
class Trampoline {
+ static {
+ if (Trampoline.class.getClassLoader() == null) {
+ throw new Error(
+ "Trampoline must not be defined by the bootstrap classloader");
+ }
+ }
+
+ private static void ensureInvocableMethod(Method m)
+ throws InvocationTargetException
+ {
+ Class<?> clazz = m.getDeclaringClass();
+ if (clazz.equals(AccessController.class) ||
+ clazz.equals(Method.class) ||
+ clazz.getName().startsWith("java.lang.invoke."))
+ throw new InvocationTargetException(
+ new UnsupportedOperationException("invocation not supported"));
+ }
+
private static Object invoke(Method m, Object obj, Object[] params)
- throws InvocationTargetException, IllegalAccessException {
+ throws InvocationTargetException, IllegalAccessException
+ {
+ ensureInvocableMethod(m);
return m.invoke(obj, params);
}
}
@@ -251,16 +271,6 @@
*/
public static Object invoke(Method m, Object obj, Object[] params)
throws InvocationTargetException, IllegalAccessException {
- if (m.getDeclaringClass().equals(AccessController.class) ||
- (m.getDeclaringClass().equals(java.lang.invoke.MethodHandles.class)
- && m.getName().equals("lookup")) ||
- (m.getDeclaringClass().equals(java.lang.invoke.MethodHandles.Lookup.class)
- && (m.getName().startsWith("find") ||
- m.getName().startsWith("bind") ||
- m.getName().startsWith("unreflect"))) ||
- m.getDeclaringClass().equals(Method.class))
- throw new InvocationTargetException(
- new UnsupportedOperationException("invocation not supported"));
try {
return bounce.invoke(null, new Object[] {m, obj, params});
} catch (InvocationTargetException ie) {
@@ -293,10 +303,10 @@
Method.class, Object.class, Object[].class
};
Method b = t.getDeclaredMethod("invoke", types);
- ((AccessibleObject)b).setAccessible(true);
- return b;
- }
- });
+ b.setAccessible(true);
+ return b;
+ }
+ });
} catch (Exception e) {
throw new InternalError("bouncer cannot be found", e);
}
--- a/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java Wed Apr 17 02:53:02 2013 -0700
@@ -55,13 +55,19 @@
public class MarshalInputStream extends ObjectInputStream {
/**
- * value of "java.rmi.server.useCodebaseOnly" property,
+ * Value of "java.rmi.server.useCodebaseOnly" property,
* as cached at class initialization time.
+ *
+ * The default value is true. That is, the value is true
+ * if the property is absent or is not equal to "false".
+ * The value is only false when the property is present
+ * and is equal to "false".
*/
private static final boolean useCodebaseOnlyProperty =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetBooleanAction(
- "java.rmi.server.useCodebaseOnly")).booleanValue();
+ ! java.security.AccessController.doPrivileged(
+ new sun.security.action.GetPropertyAction(
+ "java.rmi.server.useCodebaseOnly", "true"))
+ .equalsIgnoreCase("false");
/** table to hold sun classes to which access is explicitly permitted */
protected static Map<String, Class<?>> permittedSunClasses
--- a/jdk/src/share/classes/sun/security/krb5/KrbApReq.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApReq.java Wed Apr 17 02:53:02 2013 -0700
@@ -204,7 +204,7 @@
int usage)
throws KrbException, IOException {
- ctime = new KerberosTime(KerberosTime.NOW);
+ ctime = KerberosTime.now();
init(options,
tgs_creds.ticket,
tgs_creds.key,
@@ -287,14 +287,14 @@
authenticator = new Authenticator(temp2);
ctime = authenticator.ctime;
cusec = authenticator.cusec;
- authenticator.ctime.setMicroSeconds(authenticator.cusec);
+ authenticator.ctime =
+ authenticator.ctime.withMicroSeconds(authenticator.cusec);
if (!authenticator.cname.equals(enc_ticketPart.cname)) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_BADMATCH);
}
- KerberosTime currTime = new KerberosTime(KerberosTime.NOW);
- if (!authenticator.ctime.inClockSkew(currTime))
+ if (!authenticator.ctime.inClockSkew())
throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
// start to check if it is a replay attack.
@@ -304,7 +304,7 @@
if (table.get(time, authenticator.cname.toString()) != null) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
} else {
- table.put(client, time, currTime.getTime());
+ table.put(client, time, System.currentTimeMillis());
}
if (initiator != null) {
@@ -329,7 +329,7 @@
// else
// save authenticator to check for later
- KerberosTime now = new KerberosTime(KerberosTime.NOW);
+ KerberosTime now = KerberosTime.now();
if ((enc_ticketPart.starttime != null &&
enc_ticketPart.starttime.greaterThanWRTClockSkew(now)) ||
--- a/jdk/src/share/classes/sun/security/krb5/KrbAppMessage.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbAppMessage.java Wed Apr 17 02:53:02 2013 -0700
@@ -71,12 +71,18 @@
}
if (packetTimestamp != null) {
- packetTimestamp.setMicroSeconds(packetUsec);
- if (!packetTimestamp.inClockSkew())
+ if (packetUsec != null) {
+ packetTimestamp =
+ packetTimestamp.withMicroSeconds(packetUsec.intValue());
+ }
+ if (!packetTimestamp.inClockSkew()) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
- } else
- if (timestampRequired)
+ }
+ } else {
+ if (timestampRequired) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
+ }
+ }
// XXX check replay cache
// if (rcache.repeated(packetTimestamp, packetUsec, packetSAddress))
--- a/jdk/src/share/classes/sun/security/krb5/KrbCred.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbCred.java Wed Apr 17 02:53:02 2013 -0700
@@ -103,7 +103,7 @@
delegatedCreds.renewTill, tgService,
delegatedCreds.cAddr);
- timeStamp = new KerberosTime(KerberosTime.NOW);
+ timeStamp = KerberosTime.now();
KrbCredInfo[] credInfos = {credInfo};
EncKrbCredPart encPart =
new EncKrbCredPart(credInfos,
--- a/jdk/src/share/classes/sun/security/krb5/KrbTgsReq.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbTgsReq.java Wed Apr 17 02:53:02 2013 -0700
@@ -147,8 +147,7 @@
princName = cname;
servName = sname;
- ctime = new KerberosTime(KerberosTime.NOW);
-
+ ctime = KerberosTime.now();
// check if they are valid arguments. The optional fields
// should be consistent with settings in KDCOptions.
--- a/jdk/src/share/classes/sun/security/krb5/internal/KerberosTime.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KerberosTime.java Wed Apr 17 02:53:02 2013 -0700
@@ -30,18 +30,20 @@
package sun.security.krb5.internal;
-import java.util.TimeZone;
-import sun.security.util.*;
+import sun.security.krb5.Asn1Exception;
import sun.security.krb5.Config;
import sun.security.krb5.KrbException;
-import sun.security.krb5.Asn1Exception;
+import sun.security.util.DerInputStream;
+import sun.security.util.DerOutputStream;
+import sun.security.util.DerValue;
+
+import java.io.IOException;
+import java.util.Calendar;
import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Calendar;
-import java.io.IOException;
+import java.util.TimeZone;
/**
- * Implements the ASN.1 KerberosTime type.
+ * Implements the ASN.1 KerberosTime type. This is an immutable class.
*
* <xmp>
* KerberosTime ::= GeneralizedTime -- with no fractional seconds
@@ -62,55 +64,38 @@
* same class can be used as a precise timestamp in Authenticator etc.
*/
-public class KerberosTime implements Cloneable {
+public class KerberosTime {
- private long kerberosTime; // milliseconds since epoch, a Date.getTime() value
- private int microSeconds; // the last three digits of the microsecond value
+ private final long kerberosTime; // milliseconds since epoch, Date.getTime()
+ private final int microSeconds; // last 3 digits of the real microsecond
// The time when this class is loaded. Used in setNow()
private static long initMilli = System.currentTimeMillis();
private static long initMicro = System.nanoTime() / 1000;
- private static long syncTime;
private static boolean DEBUG = Krb5.DEBUG;
- public static final boolean NOW = true;
- public static final boolean UNADJUSTED_NOW = false;
-
- public KerberosTime(long time) {
- kerberosTime = time;
- }
-
+ // Do not make this public. It's a little confusing that micro
+ // is only the last 3 digits of microsecond.
private KerberosTime(long time, int micro) {
kerberosTime = time;
microSeconds = micro;
}
- public Object clone() {
- return new KerberosTime(kerberosTime, microSeconds);
+ /**
+ * Creates a KerberosTime object from milliseconds since epoch.
+ */
+ public KerberosTime(long time) {
+ this(time, 0);
}
// This constructor is used in the native code
// src/windows/native/sun/security/krb5/NativeCreds.c
public KerberosTime(String time) throws Asn1Exception {
- kerberosTime = toKerberosTime(time);
- }
-
- /**
- * Constructs a KerberosTime object.
- * @param encoding a DER-encoded data.
- * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
- * @exception IOException if an I/O error occurs while reading encoded data.
- */
- public KerberosTime(DerValue encoding) throws Asn1Exception, IOException {
- GregorianCalendar calendar = new GregorianCalendar();
- Date temp = encoding.getGeneralizedTime();
- kerberosTime = temp.getTime();
+ this(toKerberosTime(time), 0);
}
private static long toKerberosTime(String time) throws Asn1Exception {
- // this method only used by KerberosTime class.
-
// ASN.1 GeneralizedTime format:
// "19700101000000Z"
@@ -133,30 +118,34 @@
Integer.parseInt(time.substring(8, 10)),
Integer.parseInt(time.substring(10, 12)),
Integer.parseInt(time.substring(12, 14)));
+ return calendar.getTimeInMillis();
+ }
- //The Date constructor assumes the setting are local relative
- //and converts the time to UTC before storing it. Since we
- //want the internal representation to correspond to local
- //and not UTC time we subtract the UTC time offset.
- return (calendar.getTime().getTime());
-
+ /**
+ * Creates a KerberosTime object from a Date object.
+ */
+ public KerberosTime(Date time) {
+ this(time.getTime(), 0);
}
- // should be moved to sun.security.krb5.util class
- public static String zeroPad(String s, int length) {
- StringBuffer temp = new StringBuffer(s);
- while (temp.length() < length)
- temp.insert(0, '0');
- return temp.toString();
- }
-
- public KerberosTime(Date time) {
- kerberosTime = time.getTime(); // (time.getTimezoneOffset() * 60000L);
- }
-
- public KerberosTime(boolean initToNow) {
- if (initToNow) {
- setNow();
+ /**
+ * Creates a KerberosTime object for now. It uses System.nanoTime()
+ * to get a more precise time than "new Date()".
+ */
+ public static KerberosTime now() {
+ long newMilli = System.currentTimeMillis();
+ long newMicro = System.nanoTime() / 1000;
+ long microElapsed = newMicro - initMicro;
+ long calcMilli = initMilli + microElapsed/1000;
+ if (calcMilli - newMilli > 100 || newMilli - calcMilli > 100) {
+ if (DEBUG) {
+ System.out.println("System time adjusted");
+ }
+ initMilli = newMilli;
+ initMicro = newMicro;
+ return new KerberosTime(newMilli, 0);
+ } else {
+ return new KerberosTime(calcMilli, (int)(microElapsed % 1000));
}
}
@@ -169,13 +158,13 @@
calendar.clear();
calendar.setTimeInMillis(kerberosTime);
- return zeroPad(Integer.toString(calendar.get(Calendar.YEAR)), 4) +
- zeroPad(Integer.toString(calendar.get(Calendar.MONTH) + 1), 2) +
- zeroPad(Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)), 2) +
- zeroPad(Integer.toString(calendar.get(Calendar.HOUR_OF_DAY)), 2) +
- zeroPad(Integer.toString(calendar.get(Calendar.MINUTE)), 2) +
- zeroPad(Integer.toString(calendar.get(Calendar.SECOND)), 2) + 'Z';
-
+ return String.format("%04d%02d%02d%02d%02d%02dZ",
+ calendar.get(Calendar.YEAR),
+ calendar.get(Calendar.MONTH) + 1,
+ calendar.get(Calendar.DAY_OF_MONTH),
+ calendar.get(Calendar.HOUR_OF_DAY),
+ calendar.get(Calendar.MINUTE),
+ calendar.get(Calendar.SECOND));
}
/**
@@ -194,40 +183,8 @@
return kerberosTime;
}
-
- public void setTime(Date time) {
- kerberosTime = time.getTime(); // (time.getTimezoneOffset() * 60000L);
- microSeconds = 0;
- }
-
- public void setTime(long time) {
- kerberosTime = time;
- microSeconds = 0;
- }
-
public Date toDate() {
- Date temp = new Date(kerberosTime);
- temp.setTime(temp.getTime());
- return temp;
- }
-
- public void setNow() {
- long newMilli = System.currentTimeMillis();
- long newMicro = System.nanoTime() / 1000;
- long microElapsed = newMicro - initMicro;
- long calcMilli = initMilli + microElapsed/1000;
- if (calcMilli - newMilli > 100 || newMilli - calcMilli > 100) {
- if (DEBUG) {
- System.out.println("System time adjusted");
- }
- initMilli = newMilli;
- initMicro = newMicro;
- setTime(newMilli);
- microSeconds = 0;
- } else {
- setTime(calcMilli);
- microSeconds = (int)(microElapsed % 1000);
- }
+ return new Date(kerberosTime);
}
public int getMicroSeconds() {
@@ -235,45 +192,25 @@
return temp_long.intValue() + microSeconds;
}
- public void setMicroSeconds(int usec) {
- microSeconds = usec % 1000;
- Integer temp_int = new Integer(usec);
- long temp_long = temp_int.longValue() / 1000L;
- kerberosTime = kerberosTime - (kerberosTime % 1000L) + temp_long;
+ /**
+ * Returns a new KerberosTime object with the original seconds
+ * and the given microseconds.
+ */
+ public KerberosTime withMicroSeconds(int usec) {
+ return new KerberosTime(
+ kerberosTime - kerberosTime%1000L + usec/1000L,
+ usec%1000);
}
- public void setMicroSeconds(Integer usec) {
- if (usec != null) {
- microSeconds = usec.intValue() % 1000;
- long temp_long = usec.longValue() / 1000L;
- kerberosTime = kerberosTime - (kerberosTime % 1000L) + temp_long;
- }
- }
-
- public boolean inClockSkew(int clockSkew) {
- KerberosTime now = new KerberosTime(KerberosTime.NOW);
-
- if (java.lang.Math.abs(kerberosTime - now.kerberosTime) >
- clockSkew * 1000L)
- return false;
- return true;
+ private boolean inClockSkew(int clockSkew) {
+ return java.lang.Math.abs(kerberosTime - System.currentTimeMillis())
+ <= clockSkew * 1000L;
}
public boolean inClockSkew() {
return inClockSkew(getDefaultSkew());
}
- public boolean inClockSkew(int clockSkew, KerberosTime now) {
- if (java.lang.Math.abs(kerberosTime - now.kerberosTime) >
- clockSkew * 1000L)
- return false;
- return true;
- }
-
- public boolean inClockSkew(KerberosTime time) {
- return inClockSkew(getDefaultSkew(), time);
- }
-
public boolean greaterThanWRTClockSkew(KerberosTime time, int clockSkew) {
if ((kerberosTime - time.kerberosTime) > clockSkew * 1000L)
return true;
@@ -317,24 +254,22 @@
return temp_long.intValue();
}
- public void setSeconds(int sec) {
- Integer temp_int = new Integer(sec);
- kerberosTime = temp_int.longValue() * 1000L;
- }
-
/**
* Parse (unmarshal) a kerberostime from a DER input stream. This form
* parsing might be used when expanding a value which is part of
* a constructed sequence and uses explicitly tagged type.
*
* @exception Asn1Exception on error.
- * @param data the Der input stream value, which contains one or more marshaled value.
+ * @param data the Der input stream value, which contains
+ * one or more marshaled value.
* @param explicitTag tag number.
* @param optional indicates if this data field is optional
* @return an instance of KerberosTime.
*
*/
- public static KerberosTime parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException {
+ public static KerberosTime parse(
+ DerInputStream data, byte explicitTag, boolean optional)
+ throws Asn1Exception, IOException {
if ((optional) && (((byte)data.peekByte() & (byte)0x1F)!= explicitTag))
return null;
DerValue der = data.getDerValue();
@@ -343,7 +278,8 @@
}
else {
DerValue subDer = der.getData().getDerValue();
- return new KerberosTime(subDer);
+ Date temp = subDer.getGeneralizedTime();
+ return new KerberosTime(temp.getTime(), 0);
}
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java Wed Apr 17 02:53:02 2013 -0700
@@ -187,14 +187,10 @@
kcred.pname = (PrincipalName)pname.clone();
if (flags != null)
kcred.flags = (TicketFlags)flags.clone();
- if (authtime != null)
- kcred.authtime = (KerberosTime)authtime.clone();
- if (starttime != null)
- kcred.starttime = (KerberosTime)starttime.clone();
- if (endtime != null)
- kcred.endtime = (KerberosTime)endtime.clone();
- if (renewTill != null)
- kcred.renewTill = (KerberosTime)renewTill.clone();
+ kcred.authtime = authtime;
+ kcred.starttime = starttime;
+ kcred.endtime = endtime;
+ kcred.renewTill = renewTill;
if (sname != null)
kcred.sname = (PrincipalName)sname.clone();
if (caddr != null)
--- a/jdk/src/share/classes/sun/security/krb5/internal/LastReqEntry.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/LastReqEntry.java Wed Apr 17 02:53:02 2013 -0700
@@ -90,7 +90,7 @@
public Object clone() {
LastReqEntry newEntry = new LastReqEntry();
newEntry.lrType = lrType;
- newEntry.lrValue = (KerberosTime)lrValue.clone();
+ newEntry.lrValue = lrValue;
return newEntry;
}
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/PAEncTSEnc.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/PAEncTSEnc.java Wed Apr 17 02:53:02 2013 -0700
@@ -65,7 +65,7 @@
}
public PAEncTSEnc() {
- KerberosTime now = new KerberosTime(KerberosTime.NOW);
+ KerberosTime now = KerberosTime.now();
pATimeStamp = now;
pAUSec = new Integer(now.getMicroSeconds());
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java Wed Apr 17 02:53:02 2013 -0700
@@ -68,14 +68,11 @@
sname = (PrincipalName) new_sname.clone();
key = (EncryptionKey) new_key.clone();
- authtime = (KerberosTime) new_authtime.clone();
- if (new_starttime != null) {
- starttime = (KerberosTime) new_starttime.clone();
- }
- endtime = (KerberosTime) new_endtime.clone();
- if (new_renewTill != null) {
- renewTill = (KerberosTime) new_renewTill.clone();
- }
+ authtime = new_authtime;
+ starttime = new_starttime;
+ endtime = new_endtime;
+ renewTill = new_renewTill;
+
if (new_caddr != null) {
caddr = (HostAddresses) new_caddr.clone();
}
@@ -104,14 +101,11 @@
ticket = (Ticket) kdcRep.ticket.clone();
key = (EncryptionKey) kdcRep.encKDCRepPart.key.clone();
flags = (TicketFlags) kdcRep.encKDCRepPart.flags.clone();
- authtime = (KerberosTime) kdcRep.encKDCRepPart.authtime.clone();
- if (kdcRep.encKDCRepPart.starttime != null) {
- starttime = (KerberosTime) kdcRep.encKDCRepPart.starttime.clone();
- }
- endtime = (KerberosTime) kdcRep.encKDCRepPart.endtime.clone();
- if (kdcRep.encKDCRepPart.renewTill != null) {
- renewTill = (KerberosTime) kdcRep.encKDCRepPart.renewTill.clone();
- }
+ authtime = kdcRep.encKDCRepPart.authtime;
+ starttime = kdcRep.encKDCRepPart.starttime;
+ endtime = kdcRep.encKDCRepPart.endtime;
+ renewTill = kdcRep.encKDCRepPart.renewTill;
+
sname = (PrincipalName) kdcRep.encKDCRepPart.sname.clone();
caddr = (HostAddresses) kdcRep.encKDCRepPart.caddr.clone();
secondTicket = (Ticket) new_secondTicket.clone();
@@ -128,18 +122,10 @@
sname = (PrincipalName) kdcRep.encKDCRepPart.sname.clone();
cname = (PrincipalName) kdcRep.cname.clone();
key = (EncryptionKey) kdcRep.encKDCRepPart.key.clone();
- authtime = (KerberosTime) kdcRep.encKDCRepPart.authtime.clone();
- if (kdcRep.encKDCRepPart.starttime != null) {
- starttime = (KerberosTime) kdcRep.encKDCRepPart.starttime.clone();
- } else {
- starttime = null;
- }
- endtime = (KerberosTime) kdcRep.encKDCRepPart.endtime.clone();
- if (kdcRep.encKDCRepPart.renewTill != null) {
- renewTill = (KerberosTime) kdcRep.encKDCRepPart.renewTill.clone();
- } else {
- renewTill = null;
- }
+ authtime = kdcRep.encKDCRepPart.authtime;
+ starttime = kdcRep.encKDCRepPart.starttime;
+ endtime = kdcRep.encKDCRepPart.endtime;
+ renewTill = kdcRep.encKDCRepPart.renewTill;
// if (kdcRep.msgType == Krb5.KRB_AS_REP) {
// isEncInSKey = false;
// secondTicket = null;
--- a/jdk/src/share/classes/sun/security/provider/SHA2.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/security/provider/SHA2.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -101,7 +101,7 @@
i2bBig4((int)bitsProcessed, buffer, 60);
implCompress(buffer, 0);
- i2bBig(state, 0, out, ofs, 32);
+ i2bBig(state, 0, out, ofs, engineGetDigestLength());
}
/**
--- a/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java Wed Apr 17 02:53:02 2013 -0700
@@ -843,5 +843,52 @@
"zCOfhbsRWdMLYepauaNZOIMZXmFwcrIl0TGMkTAtATz+XmZc\n" +
"-----END CERTIFICATE-----");
+ //
+ // Revoked code signing certificate w/ a stolen key issued by GoDaddy
+ // used to sign malware
+ //
+
+ // Subject: CN=CLEARESULT CONSULTING INC., OU=Corporate IT,
+ // O=CLEARESULT CONSULTING INC., L=Austin, ST=TX, C=US
+ // Issuer: SERIALNUMBER=07969287,
+ // CN=Go Daddy Secure Certification Authority,
+ // OU=http://certificates.godaddy.com/repository,
+ // O="GoDaddy.com, Inc.",
+ // L=Scottsdale,
+ // ST=Arizona,
+ // C=US
+ // Serial: 2b:73:43:2a:a8:4f:44
+ add("clearesult-consulting-inc-2AA84F44",
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIFYjCCBEqgAwIBAgIHK3NDKqhPRDANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE\n" +
+ "BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY\n" +
+ "BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm\n" +
+ "aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5\n" +
+ "IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky\n" +
+ "ODcwHhcNMTIwMjE1MjEwOTA2WhcNMTQwMjE1MjEwOTA2WjCBjDELMAkGA1UEBgwC\n" +
+ "VVMxCzAJBgNVBAgMAlRYMQ8wDQYDVQQHDAZBdXN0aW4xIzAhBgNVBAoMGkNMRUFS\n" +
+ "RVNVTFQgQ09OU1VMVElORyBJTkMuMRUwEwYDVQQLDAxDb3Jwb3JhdGUgSVQxIzAh\n" +
+ "BgNVBAMMGkNMRUFSRVNVTFQgQ09OU1VMVElORyBJTkMuMIIBIjANBgkqhkiG9w0B\n" +
+ "AQEFAAOCAQ8AMIIBCgKCAQEAtIOjCKeAicull+7ZIzt0/4ya3IeXUFlfypqKMLkU\n" +
+ "IbKjn0P5uMj6VE3rlbZr44RCegxvdnR6umBh1c0ZXoN3o+yc0JKcKcLiApmJJ277\n" +
+ "p7IbLwYDhBXRQNoIJm187IOMRPIxsKN4hL91txn9jGBmW+9zKlJlNhR5R7vjwU2E\n" +
+ "jrH/6oqsc9EM2yYpfjlNv6+3jSwAYZCkSWr+27PQOV+YHKmIxtJjX0upFz5FdIrV\n" +
+ "9CCX+L2Kji1THOkSgG4QTbYxmEcHqGViWz8hXLeNXjcbEsPuIiAu3hknxRHfUTE/\n" +
+ "U0Lh0Ug1e3LrJu+WnxM2SmUY4krsZ22c0yWUW9hzWITIjQIDAQABo4IBhzCCAYMw\n" +
+ "DwYDVR0TAQH/BAUwAwEBADATBgNVHSUEDDAKBggrBgEFBQcDAzAOBgNVHQ8BAf8E\n" +
+ "BAMCB4AwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5LmNvbS9n\n" +
+ "ZHM1LTE2LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcCMDkwNwYIKwYBBQUH\n" +
+ "AgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS8w\n" +
+ "gYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRk\n" +
+ "eS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHku\n" +
+ "Y29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydDAfBgNVHSMEGDAWgBT9\n" +
+ "rGEyk2xF1uLuhV+auud2mWjM5zAdBgNVHQ4EFgQUDtdeKqeN2QkcbEp1HovFieNB\n" +
+ "XiowDQYJKoZIhvcNAQEFBQADggEBAD74Agw5tvi2aBl4/f/s7/VE/BClzDsKMb9K\n" +
+ "v9qpeC45ZA/jelxV11HKbQnVF194gDb7D2H9OsAsRUy8HVKbXEcc/8dKvwOqb+BC\n" +
+ "2i/EmfjLgmCfezNFtLq8xcPxF3zIRc44vPrK0z4YZsaHdH+yTEJ51p5EMdTqaLaP\n" +
+ "4n5m8LX3RfqlQB9dYFe6dUoYZjKm9d/pIRww3VqfOzjl42Edi1w6dWmBVMx1NZuR\n" +
+ "DBabJH1vJ9Gd+KwxMCmBZ6pQPl28JDimhJhI2LNqU349uADQVV0HJosddN/ARyyI\n" +
+ "LSIQO7BnNVKVG9Iujf33bvPNeg0qNz5qw+rKKq97Pqeum+L5oKU=\n" +
+ "-----END CERTIFICATE-----");
}
}
--- a/jdk/src/share/javavm/export/jvm.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/javavm/export/jvm.h Wed Apr 17 02:53:02 2013 -0700
@@ -350,16 +350,21 @@
/*
* java.lang.Class and java.lang.ClassLoader
*/
+
+#define JVM_DEPTH -1
+
/*
- * Returns the class in which the code invoking the native method
- * belongs.
+ * Returns the immediate caller class of the native method invoking
+ * JVM_GetCallerClass. The Method.invoke and other frames due to
+ * reflection machinery are skipped.
*
- * Note that in JDK 1.1, native methods did not create a frame.
- * In 1.2, they do. Therefore native methods like Class.forName
- * can no longer look at the current frame for the caller class.
+ * The depth parameter must be -1 (JVM_DEPTH). The caller is expected
+ * to be marked with sun.reflect.CallerSensitive. The JVM will throw
+ * an error if it is not marked propertly.
*/
JNIEXPORT jclass JNICALL
-JVM_GetCallerClass(JNIEnv *env, int n);
+JVM_GetCallerClass(JNIEnv *env, int depth);
+
/*
* Find primitive classes
--- a/jdk/src/share/lib/security/java.security-linux Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/lib/security/java.security-linux Wed Apr 17 02:53:02 2013 -0700
@@ -177,23 +177,36 @@
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
package.access=sun.,\
- com.sun.xml.internal.bind.,\
- com.sun.xml.internal.org.jvnet.staxex.,\
- com.sun.xml.internal.ws.,\
+ com.sun.xml.internal.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.proxy.,\
- com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.bcel.internal.,\
+ com.sun.org.apache.regexp.internal.,\
+ com.sun.org.apache.xerces.internal.,\
+ com.sun.org.apache.xpath.internal.,\
+ com.sun.org.apache.xalan.internal.extensions.,\
+ com.sun.org.apache.xalan.internal.lib.,\
+ com.sun.org.apache.xalan.internal.res.,\
+ com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\
- com.sun.org.glassfish.external.,\
- com.sun.org.glassfish.gmbal.,\
+ com.sun.org.apache.xalan.internal.xslt.,\
+ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
+ com.sun.org.apache.xalan.internal.xsltc.compiler.,\
+ com.sun.org.apache.xalan.internal.xsltc.trax.,\
+ com.sun.org.apache.xalan.internal.xsltc.util.,\
+ com.sun.org.apache.xml.internal.res.,\
+ com.sun.org.apache.xml.internal.serializer.utils.,\
+ com.sun.org.apache.xml.internal.utils.,\
+ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\
jdk.internal.,\
jdk.nashorn.internal.,\
jdk.nashorn.tools.
+
#
# List of comma-separated packages that start with or equal this string
# will cause a security exception to be thrown when
@@ -205,23 +218,36 @@
# checkPackageDefinition.
#
package.definition=sun.,\
- com.sun.xml.internal.bind.,\
- com.sun.xml.internal.org.jvnet.staxex.,\
- com.sun.xml.internal.ws.,\
+ com.sun.xml.internal.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.proxy.,\
- com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.bcel.internal.,\
+ com.sun.org.apache.regexp.internal.,\
+ com.sun.org.apache.xerces.internal.,\
+ com.sun.org.apache.xpath.internal.,\
+ com.sun.org.apache.xalan.internal.extensions.,\
+ com.sun.org.apache.xalan.internal.lib.,\
+ com.sun.org.apache.xalan.internal.res.,\
+ com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\
- com.sun.org.glassfish.external.,\
- com.sun.org.glassfish.gmbal.,\
+ com.sun.org.apache.xalan.internal.xslt.,\
+ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
+ com.sun.org.apache.xalan.internal.xsltc.compiler.,\
+ com.sun.org.apache.xalan.internal.xsltc.trax.,\
+ com.sun.org.apache.xalan.internal.xsltc.util.,\
+ com.sun.org.apache.xml.internal.res.,\
+ com.sun.org.apache.xml.internal.serializer.utils.,\
+ com.sun.org.apache.xml.internal.utils.,\
+ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\
jdk.internal.,\
jdk.nashorn.internal.,\
jdk.nashorn.tools.
+
#
# Determines whether this properties file can be appended to
# or overridden on the command line via -Djava.security.properties
--- a/jdk/src/share/lib/security/java.security-macosx Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/lib/security/java.security-macosx Wed Apr 17 02:53:02 2013 -0700
@@ -178,17 +178,29 @@
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
package.access=sun.,\
- com.sun.xml.internal.bind.,\
- com.sun.xml.internal.org.jvnet.staxex.,\
- com.sun.xml.internal.ws.,\
+ com.sun.xml.internal.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.proxy.,\
- com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.bcel.internal.,\
+ com.sun.org.apache.regexp.internal.,\
+ com.sun.org.apache.xerces.internal.,\
+ com.sun.org.apache.xpath.internal.,\
+ com.sun.org.apache.xalan.internal.extensions.,\
+ com.sun.org.apache.xalan.internal.lib.,\
+ com.sun.org.apache.xalan.internal.res.,\
+ com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\
- com.sun.org.glassfish.external.,\
- com.sun.org.glassfish.gmbal.,\
+ com.sun.org.apache.xalan.internal.xslt.,\
+ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
+ com.sun.org.apache.xalan.internal.xsltc.compiler.,\
+ com.sun.org.apache.xalan.internal.xsltc.trax.,\
+ com.sun.org.apache.xalan.internal.xsltc.util.,\
+ com.sun.org.apache.xml.internal.res.,\
+ com.sun.org.apache.xml.internal.serializer.utils.,\
+ com.sun.org.apache.xml.internal.utils.,\
+ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\
jdk.internal.,\
@@ -207,17 +219,29 @@
# checkPackageDefinition.
#
package.definition=sun.,\
- com.sun.xml.internal.bind.,\
- com.sun.xml.internal.org.jvnet.staxex.,\
- com.sun.xml.internal.ws.,\
+ com.sun.xml.internal.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.proxy.,\
- com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.bcel.internal.,\
+ com.sun.org.apache.regexp.internal.,\
+ com.sun.org.apache.xerces.internal.,\
+ com.sun.org.apache.xpath.internal.,\
+ com.sun.org.apache.xalan.internal.extensions.,\
+ com.sun.org.apache.xalan.internal.lib.,\
+ com.sun.org.apache.xalan.internal.res.,\
+ com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\
- com.sun.org.glassfish.external.,\
- com.sun.org.glassfish.gmbal.,\
+ com.sun.org.apache.xalan.internal.xslt.,\
+ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
+ com.sun.org.apache.xalan.internal.xsltc.compiler.,\
+ com.sun.org.apache.xalan.internal.xsltc.trax.,\
+ com.sun.org.apache.xalan.internal.xsltc.util.,\
+ com.sun.org.apache.xml.internal.res.,\
+ com.sun.org.apache.xml.internal.serializer.utils.,\
+ com.sun.org.apache.xml.internal.utils.,\
+ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\
jdk.internal.,\
--- a/jdk/src/share/lib/security/java.security-solaris Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/lib/security/java.security-solaris Wed Apr 17 02:53:02 2013 -0700
@@ -179,17 +179,29 @@
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
package.access=sun.,\
- com.sun.xml.internal.bind.,\
- com.sun.xml.internal.org.jvnet.staxex.,\
- com.sun.xml.internal.ws.,\
+ com.sun.xml.internal.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.proxy.,\
- com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.bcel.internal.,\
+ com.sun.org.apache.regexp.internal.,\
+ com.sun.org.apache.xerces.internal.,\
+ com.sun.org.apache.xpath.internal.,\
+ com.sun.org.apache.xalan.internal.extensions.,\
+ com.sun.org.apache.xalan.internal.lib.,\
+ com.sun.org.apache.xalan.internal.res.,\
+ com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\
- com.sun.org.glassfish.external.,\
- com.sun.org.glassfish.gmbal.,\
+ com.sun.org.apache.xalan.internal.xslt.,\
+ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
+ com.sun.org.apache.xalan.internal.xsltc.compiler.,\
+ com.sun.org.apache.xalan.internal.xsltc.trax.,\
+ com.sun.org.apache.xalan.internal.xsltc.util.,\
+ com.sun.org.apache.xml.internal.res.,\
+ com.sun.org.apache.xml.internal.serializer.utils.,\
+ com.sun.org.apache.xml.internal.utils.,\
+ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\
jdk.internal.,\
@@ -207,17 +219,29 @@
# checkPackageDefinition.
#
package.definition=sun.,\
- com.sun.xml.internal.bind.,\
- com.sun.xml.internal.org.jvnet.staxex.,\
- com.sun.xml.internal.ws.,\
+ com.sun.xml.internal.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.proxy.,\
- com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.bcel.internal.,\
+ com.sun.org.apache.regexp.internal.,\
+ com.sun.org.apache.xerces.internal.,\
+ com.sun.org.apache.xpath.internal.,\
+ com.sun.org.apache.xalan.internal.extensions.,\
+ com.sun.org.apache.xalan.internal.lib.,\
+ com.sun.org.apache.xalan.internal.res.,\
+ com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\
- com.sun.org.glassfish.external.,\
- com.sun.org.glassfish.gmbal.,\
+ com.sun.org.apache.xalan.internal.xslt.,\
+ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
+ com.sun.org.apache.xalan.internal.xsltc.compiler.,\
+ com.sun.org.apache.xalan.internal.xsltc.trax.,\
+ com.sun.org.apache.xalan.internal.xsltc.util.,\
+ com.sun.org.apache.xml.internal.res.,\
+ com.sun.org.apache.xml.internal.serializer.utils.,\
+ com.sun.org.apache.xml.internal.utils.,\
+ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\
jdk.internal.,\
--- a/jdk/src/share/lib/security/java.security-windows Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/lib/security/java.security-windows Wed Apr 17 02:53:02 2013 -0700
@@ -178,22 +178,35 @@
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
package.access=sun.,\
- com.sun.xml.internal.bind.,\
- com.sun.xml.internal.org.jvnet.staxex.,\
- com.sun.xml.internal.ws.,\
+ com.sun.xml.internal.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.proxy.,\
- com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.bcel.internal.,\
+ com.sun.org.apache.regexp.internal.,\
+ com.sun.org.apache.xerces.internal.,\
+ com.sun.org.apache.xpath.internal.,\
+ com.sun.org.apache.xalan.internal.extensions.,\
+ com.sun.org.apache.xalan.internal.lib.,\
+ com.sun.org.apache.xalan.internal.res.,\
+ com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\
- com.sun.org.glassfish.external.,\
- com.sun.org.glassfish.gmbal.,\
+ com.sun.org.apache.xalan.internal.xslt.,\
+ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
+ com.sun.org.apache.xalan.internal.xsltc.compiler.,\
+ com.sun.org.apache.xalan.internal.xsltc.trax.,\
+ com.sun.org.apache.xalan.internal.xsltc.util.,\
+ com.sun.org.apache.xml.internal.res.,\
+ com.sun.org.apache.xml.internal.serializer.utils.,\
+ com.sun.org.apache.xml.internal.utils.,\
+ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\
jdk.internal.,\
jdk.nashorn.internal.,\
- jdk.nashorn.tools.
+ jdk.nashorn.tools.,\
+ com.sun.java.accessibility.
#
# List of comma-separated packages that start with or equal this string
@@ -206,22 +219,35 @@
# checkPackageDefinition.
#
package.definition=sun.,\
- com.sun.xml.internal.bind.,\
- com.sun.xml.internal.org.jvnet.staxex.,\
- com.sun.xml.internal.ws.,\
+ com.sun.xml.internal.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.proxy.,\
- com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.bcel.internal.,\
+ com.sun.org.apache.regexp.internal.,\
+ com.sun.org.apache.xerces.internal.,\
+ com.sun.org.apache.xpath.internal.,\
+ com.sun.org.apache.xalan.internal.extensions.,\
+ com.sun.org.apache.xalan.internal.lib.,\
+ com.sun.org.apache.xalan.internal.res.,\
+ com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\
- com.sun.org.glassfish.external.,\
- com.sun.org.glassfish.gmbal.,\
+ com.sun.org.apache.xalan.internal.xslt.,\
+ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
+ com.sun.org.apache.xalan.internal.xsltc.compiler.,\
+ com.sun.org.apache.xalan.internal.xsltc.trax.,\
+ com.sun.org.apache.xalan.internal.xsltc.util.,\
+ com.sun.org.apache.xml.internal.res.,\
+ com.sun.org.apache.xml.internal.serializer.utils.,\
+ com.sun.org.apache.xml.internal.utils.,\
+ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\
jdk.internal.,\
jdk.nashorn.internal.,\
- jdk.nashorn.tools.
+ jdk.nashorn.tools.,\
+ com.sun.java.accessibility.
#
# Determines whether this properties file can be appended to
--- a/jdk/src/share/native/java/lang/ClassLoader.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/java/lang/ClassLoader.c Wed Apr 17 02:53:02 2013 -0700
@@ -492,24 +492,6 @@
(*env)->ReleaseStringUTFChars(env, name, cname);
return res;
}
-
-JNIEXPORT jobject JNICALL
-Java_java_lang_ClassLoader_getCaller(JNIEnv *env, jclass cls, jint index)
-{
- jobjectArray jcallerStack;
- int len;
-
- jcallerStack = JVM_GetClassContext(env);
- if ((*env)->ExceptionCheck(env)) {
- return NULL;
- }
- len = (*env)->GetArrayLength(env, jcallerStack);
- if (index < len) {
- return (*env)->GetObjectArrayElement(env, jcallerStack, index);
- }
- return NULL;
-}
-
/*
* Class: java_lang_ClassLoader_NativeLibrary
* Method: findBuiltinLib
--- a/jdk/src/share/native/java/lang/ResourceBundle.c Tue Apr 16 05:32:39 2013 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 1997, 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.
- */
-
-#include "jni.h"
-#include "jvm.h"
-
-#include "java_util_ResourceBundle.h"
-
-JNIEXPORT jobjectArray JNICALL
-Java_java_util_ResourceBundle_getClassContext(JNIEnv *env, jobject this)
-{
- return JVM_GetClassContext(env);
-}
--- a/jdk/src/share/native/java/lang/SecurityManager.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/java/lang/SecurityManager.c Wed Apr 17 02:53:02 2013 -0700
@@ -29,7 +29,6 @@
#include "java_lang_SecurityManager.h"
#include "java_lang_ClassLoader.h"
-#include "java_util_ResourceBundle.h"
/*
* Make sure a security manager instance is initialized.
--- a/jdk/src/share/native/java/net/InetAddress.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/java/net/InetAddress.c Wed Apr 17 02:53:02 2013 -0700
@@ -33,8 +33,11 @@
*/
jclass ia_class;
-jfieldID ia_addressID;
-jfieldID ia_familyID;
+jclass iac_class;
+jfieldID ia_holderID;
+jfieldID iac_addressID;
+jfieldID iac_familyID;
+jfieldID iac_hostNameID;
jfieldID ia_preferIPv6AddressID;
/*
@@ -48,10 +51,18 @@
CHECK_NULL(c);
ia_class = (*env)->NewGlobalRef(env, c);
CHECK_NULL(ia_class);
- ia_addressID = (*env)->GetFieldID(env, ia_class, "address", "I");
- CHECK_NULL(ia_addressID);
- ia_familyID = (*env)->GetFieldID(env, ia_class, "family", "I");
- CHECK_NULL(ia_familyID);
+ c = (*env)->FindClass(env,"java/net/InetAddress$InetAddressHolder");
+ CHECK_NULL(c);
+ iac_class = (*env)->NewGlobalRef(env, c);
+ ia_holderID = (*env)->GetFieldID(env, ia_class, "holder", "Ljava/net/InetAddress$InetAddressHolder;");
+ CHECK_NULL(ia_holderID);
ia_preferIPv6AddressID = (*env)->GetStaticFieldID(env, ia_class, "preferIPv6Address", "Z");
CHECK_NULL(ia_preferIPv6AddressID);
+
+ iac_addressID = (*env)->GetFieldID(env, iac_class, "address", "I");
+ CHECK_NULL(iac_addressID);
+ iac_familyID = (*env)->GetFieldID(env, iac_class, "family", "I");
+ CHECK_NULL(iac_familyID);
+ iac_hostNameID = (*env)->GetFieldID(env, iac_class, "hostName", "Ljava/lang/String;");
+ CHECK_NULL(iac_hostNameID);
}
--- a/jdk/src/share/native/java/net/net_util.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/java/net/net_util.c Wed Apr 17 02:53:02 2013 -0700
@@ -84,6 +84,58 @@
}
}
+/* The address, and family fields used to be in InetAddress
+ * but are now in an implementation object. So, there is an extra
+ * level of indirection to access them now.
+ */
+
+extern jclass iac_class;
+extern jfieldID ia_holderID;
+extern jfieldID iac_addressID;
+extern jfieldID iac_familyID;
+
+void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address) {
+ jobject holder;
+ init(env);
+ holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
+ (*env)->SetIntField(env, holder, iac_addressID, address);
+}
+
+void setInetAddress_family(JNIEnv *env, jobject iaObj, int family) {
+ jobject holder;
+ init(env);
+ holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
+ (*env)->SetIntField(env, holder, iac_familyID, family);
+}
+
+void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject host) {
+ jobject holder;
+ init(env);
+ holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
+ (*env)->SetObjectField(env, holder, iac_hostNameID, host);
+}
+
+int getInetAddress_addr(JNIEnv *env, jobject iaObj) {
+ jobject holder;
+ init(env);
+ holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
+ return (*env)->GetIntField(env, holder, iac_addressID);
+}
+
+int getInetAddress_family(JNIEnv *env, jobject iaObj) {
+ jobject holder;
+ init(env);
+ holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
+ return (*env)->GetIntField(env, holder, iac_familyID);
+}
+
+jobject getInetAddress_hostName(JNIEnv *env, jobject iaObj) {
+ jobject holder;
+ init(env);
+ holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
+ return (*env)->GetObjectField(env, holder, iac_hostNameID);
+}
+
JNIEXPORT jobject JNICALL
NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
jobject iaObj;
@@ -110,8 +162,8 @@
iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
CHECK_NULL_RETURN(iaObj, NULL);
address = NET_IPv4MappedToIPv4(caddr);
- (*env)->SetIntField(env, iaObj, ia_addressID, address);
- (*env)->SetIntField(env, iaObj, ia_familyID, IPv4);
+ setInetAddress_addr(env, iaObj, address);
+ setInetAddress_family(env, iaObj, IPv4);
} else {
static jclass inet6Cls = 0;
jint scope;
@@ -131,7 +183,7 @@
(*env)->SetObjectField(env, iaObj, ia6_ipaddressID, ipaddress);
- (*env)->SetIntField(env, iaObj, ia_familyID, IPv6);
+ setInetAddress_family(env, iaObj, IPv6);
scope = getScopeID(him);
(*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
if (scope > 0)
@@ -153,9 +205,8 @@
}
iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
CHECK_NULL_RETURN(iaObj, NULL);
- (*env)->SetIntField(env, iaObj, ia_familyID, IPv4);
- (*env)->SetIntField(env, iaObj, ia_addressID,
- ntohl(him4->sin_addr.s_addr));
+ setInetAddress_family(env, iaObj, IPv4);
+ setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));
*port = ntohs(him4->sin_port);
}
return iaObj;
@@ -167,8 +218,7 @@
jint family = AF_INET;
#ifdef AF_INET6
- family = (*env)->GetIntField(env, iaObj, ia_familyID) == IPv4?
- AF_INET : AF_INET6;
+ family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
if (him->sa_family == AF_INET6) {
#ifdef WIN32
struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
@@ -183,7 +233,7 @@
return JNI_FALSE;
}
addrNew = NET_IPv4MappedToIPv4(caddrNew);
- addrCur = (*env)->GetIntField(env, iaObj, ia_addressID);
+ addrCur = getInetAddress_addr(env, iaObj);
if (addrNew == addrCur) {
return JNI_TRUE;
} else {
@@ -215,7 +265,7 @@
return JNI_FALSE;
}
addrNew = ntohl(him4->sin_addr.s_addr);
- addrCur = (*env)->GetIntField(env, iaObj, ia_addressID);
+ addrCur = getInetAddress_addr(env, iaObj);
if (addrNew == addrCur) {
return JNI_TRUE;
} else {
--- a/jdk/src/share/native/java/net/net_util.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/java/net/net_util.h Wed Apr 17 02:53:02 2013 -0700
@@ -53,10 +53,18 @@
* i.e. psi_timeoutID is PlainSocketImpl's timeout field's ID.
*/
extern jclass ia_class;
-extern jfieldID ia_addressID;
-extern jfieldID ia_familyID;
+extern jfieldID iac_addressID;
+extern jfieldID iac_familyID;
+extern jfieldID iac_hostNameID;
extern jfieldID ia_preferIPv6AddressID;
+extern void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address);
+extern void setInetAddress_family(JNIEnv *env, jobject iaObj, int family);
+extern void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject h);
+extern int getInetAddress_addr(JNIEnv *env, jobject iaObj);
+extern int getInetAddress_family(JNIEnv *env, jobject iaObj);
+extern jobject getInetAddress_hostName(JNIEnv *env, jobject iaObj);
+
extern jclass ia4_class;
extern jmethodID ia4_ctrID;
--- a/jdk/src/share/native/sun/awt/image/awt_ImageRep.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/awt/image/awt_ImageRep.c Wed Apr 17 02:53:02 2013 -0700
@@ -45,6 +45,53 @@
# define TRUE 1
#endif
+#define CHECK_STRIDE(yy, hh, ss) \
+ if ((ss) != 0) { \
+ int limit = 0x7fffffff / ((ss) > 0 ? (ss) : -(ss)); \
+ if (limit < (yy) || limit < ((yy) + (hh) - 1)) { \
+ /* integer oveflow */ \
+ return JNI_FALSE; \
+ } \
+ } \
+
+#define CHECK_SRC() \
+ do { \
+ int pixeloffset; \
+ if (off < 0 || off >= srcDataLength) { \
+ return JNI_FALSE; \
+ } \
+ CHECK_STRIDE(0, h, scansize); \
+ \
+ /* check scansize */ \
+ pixeloffset = scansize * (h - 1); \
+ if ((w - 1) > (0x7fffffff - pixeloffset)) { \
+ return JNI_FALSE; \
+ } \
+ pixeloffset += (w - 1); \
+ \
+ if (off > (0x7fffffff - pixeloffset)) { \
+ return JNI_FALSE; \
+ } \
+ } while (0) \
+
+#define CHECK_DST(xx, yy) \
+ do { \
+ int soffset = (yy) * sStride; \
+ int poffset = (xx) * pixelStride; \
+ if (poffset > (0x7fffffff - soffset)) { \
+ return JNI_FALSE; \
+ } \
+ poffset += soffset; \
+ if (dstDataOff > (0x7fffffff - poffset)) { \
+ return JNI_FALSE; \
+ } \
+ poffset += dstDataOff; \
+ \
+ if (poffset < 0 || poffset >= dstDataLength) { \
+ return JNI_FALSE; \
+ } \
+ } while (0) \
+
static jfieldID s_JnumSrcLUTID;
static jfieldID s_JsrcLUTtransIndexID;
@@ -58,7 +105,7 @@
/*
* This routine is used to draw ICM pixels into a default color model
*/
-JNIEXPORT void JNICALL
+JNIEXPORT jboolean JNICALL
Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
jint x, jint y, jint w,
jint h, jintArray jlut,
@@ -67,7 +114,10 @@
jobject jict)
{
unsigned char *srcData = NULL;
+ jint srcDataLength;
int *dstData;
+ jint dstDataLength;
+ jint dstDataOff;
int *dstP, *dstyP;
unsigned char *srcyP, *srcP;
int *srcLUT = NULL;
@@ -80,12 +130,20 @@
if (JNU_IsNull(env, jlut)) {
JNU_ThrowNullPointerException(env, "NullPointerException");
- return;
+ return JNI_FALSE;
}
if (JNU_IsNull(env, jpix)) {
JNU_ThrowNullPointerException(env, "NullPointerException");
- return;
+ return JNI_FALSE;
+ }
+
+ if (x < 0 || w < 1 || (0x7fffffff - x) < w) {
+ return JNI_FALSE;
+ }
+
+ if (y < 0 || h < 1 || (0x7fffffff - y) < h) {
+ return JNI_FALSE;
}
sStride = (*env)->GetIntField(env, jict, g_ICRscanstrID);
@@ -93,10 +151,47 @@
joffs = (*env)->GetObjectField(env, jict, g_ICRdataOffsetsID);
jdata = (*env)->GetObjectField(env, jict, g_ICRdataID);
+ if (JNU_IsNull(env, jdata)) {
+ /* no destination buffer */
+ return JNI_FALSE;
+ }
+
+ if (JNU_IsNull(env, joffs) || (*env)->GetArrayLength(env, joffs) < 1) {
+ /* invalid data offstes in raster */
+ return JNI_FALSE;
+ }
+
+ srcDataLength = (*env)->GetArrayLength(env, jpix);
+ dstDataLength = (*env)->GetArrayLength(env, jdata);
+
+ cOffs = (int *) (*env)->GetPrimitiveArrayCritical(env, joffs, NULL);
+ if (cOffs == NULL) {
+ JNU_ThrowNullPointerException(env, "Null channel offset array");
+ return JNI_FALSE;
+ }
+
+ dstDataOff = cOffs[0];
+
+ /* the offset array is not needed anymore and can be released */
+ (*env)->ReleasePrimitiveArrayCritical(env, joffs, cOffs, JNI_ABORT);
+ joffs = NULL;
+ cOffs = NULL;
+
+ /* do basic validation: make sure that offsets for
+ * first pixel and for last pixel are safe to calculate and use */
+ CHECK_STRIDE(y, h, sStride);
+ CHECK_STRIDE(x, w, pixelStride);
+
+ CHECK_DST(x, y);
+ CHECK_DST(x + w -1, y + h - 1);
+
+ /* check source array */
+ CHECK_SRC();
+
srcLUT = (int *) (*env)->GetPrimitiveArrayCritical(env, jlut, NULL);
if (srcLUT == NULL) {
JNU_ThrowNullPointerException(env, "Null IndexColorModel LUT");
- return;
+ return JNI_FALSE;
}
srcData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jpix,
@@ -104,27 +199,18 @@
if (srcData == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
JNU_ThrowNullPointerException(env, "Null data array");
- return;
- }
-
- cOffs = (int *) (*env)->GetPrimitiveArrayCritical(env, joffs, NULL);
- if (cOffs == NULL) {
- (*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
- (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
- JNU_ThrowNullPointerException(env, "Null channel offset array");
- return;
+ return JNI_FALSE;
}
dstData = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL);
if (dstData == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
- (*env)->ReleasePrimitiveArrayCritical(env, joffs, cOffs, JNI_ABORT);
JNU_ThrowNullPointerException(env, "Null tile data array");
- return;
+ return JNI_FALSE;
}
- dstyP = dstData + cOffs[0] + y*sStride + x*pixelStride;
+ dstyP = dstData + dstDataOff + y*sStride + x*pixelStride;
srcyP = srcData + off;
for (yIdx = 0; yIdx < h; yIdx++, srcyP += scansize, dstyP+=sStride) {
srcP = srcyP;
@@ -137,12 +223,12 @@
/* Release the locked arrays */
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
- (*env)->ReleasePrimitiveArrayCritical(env, joffs, cOffs, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT);
+ return JNI_TRUE;
}
-JNIEXPORT jint JNICALL
+JNIEXPORT jboolean JNICALL
Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
jint x, jint y, jint w,
jint h, jintArray jlut,
@@ -150,7 +236,7 @@
jobject jicm,
jbyteArray jpix, jint off,
jint scansize,
- jobject jbct, jint chanOff)
+ jobject jbct, jint dstDataOff)
{
unsigned int *srcLUT = NULL;
unsigned int *newLUT = NULL;
@@ -159,6 +245,8 @@
int mapSize;
jobject jdata = NULL;
jobject jnewlut = NULL;
+ jint srcDataLength;
+ jint dstDataLength;
unsigned char *srcData;
unsigned char *dstData;
unsigned char *dataP;
@@ -174,14 +262,23 @@
if (JNU_IsNull(env, jlut)) {
JNU_ThrowNullPointerException(env, "NullPointerException");
- return 0;
+ return JNI_FALSE;
}
if (JNU_IsNull(env, jpix)) {
JNU_ThrowNullPointerException(env, "NullPointerException");
- return 0;
+ return JNI_FALSE;
+ }
+
+ if (x < 0 || w < 1 || (0x7fffffff - x) < w) {
+ return JNI_FALSE;
}
+ if (y < 0 || h < 1 || (0x7fffffff - y) < h) {
+ return JNI_FALSE;
+ }
+
+
sStride = (*env)->GetIntField(env, jbct, g_BCRscanstrID);
pixelStride =(*env)->GetIntField(env, jbct, g_BCRpixstrID);
jdata = (*env)->GetObjectField(env, jbct, g_BCRdataID);
@@ -193,13 +290,31 @@
of byte data type, so we have to convert the image data
to default representation.
*/
- return 0;
+ return JNI_FALSE;
+ }
+
+ if (JNU_IsNull(env, jdata)) {
+ /* no destination buffer */
+ return JNI_FALSE;
}
+
+ srcDataLength = (*env)->GetArrayLength(env, jpix);
+ dstDataLength = (*env)->GetArrayLength(env, jdata);
+
+ CHECK_STRIDE(y, h, sStride);
+ CHECK_STRIDE(x, w, pixelStride);
+
+ CHECK_DST(x, y);
+ CHECK_DST(x + w -1, y + h - 1);
+
+ /* check source array */
+ CHECK_SRC();
+
srcLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jlut,
NULL);
if (srcLUT == NULL) {
/* out of memory error already thrown */
- return 0;
+ return JNI_FALSE;
}
newLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jnewlut,
@@ -208,7 +323,7 @@
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT,
JNI_ABORT);
/* out of memory error already thrown */
- return 0;
+ return JNI_FALSE;
}
newNumLut = numLut;
@@ -219,7 +334,7 @@
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT,
JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, jnewlut, newLUT, JNI_ABORT);
- return 0;
+ return JNI_FALSE;
}
/* Don't need these any more */
@@ -239,7 +354,7 @@
NULL);
if (srcData == NULL) {
/* out of memory error already thrown */
- return 0;
+ return JNI_FALSE;
}
dstData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jdata,
@@ -247,10 +362,10 @@
if (dstData == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
/* out of memory error already thrown */
- return 0;
+ return JNI_FALSE;
}
- ydataP = dstData + chanOff + y*sStride + x*pixelStride;
+ ydataP = dstData + dstDataOff + y*sStride + x*pixelStride;
ypixP = srcData + off;
for (i=0; i < h; i++) {
@@ -268,7 +383,7 @@
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT);
- return 1;
+ return JNI_TRUE;
}
static int compareLUTs(unsigned int *lut1, int numLut1, int transIdx,
--- a/jdk/src/share/native/sun/awt/image/awt_parseImage.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.c Wed Apr 17 02:53:02 2013 -0700
@@ -34,6 +34,7 @@
#include "java_awt_color_ColorSpace.h"
#include "awt_Mlib.h"
#include "safe_alloc.h"
+#include "safe_math.h"
static int setHints(JNIEnv *env, BufImageS_t *imageP);
--- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Wed Apr 17 02:53:02 2013 -0700
@@ -57,8 +57,8 @@
#define MAX(a,b) ((a) > (b) ? (a) : (b))
/* Cached Java method ids */
-static jmethodID ImageInputStream_readID;
-static jmethodID ImageInputStream_skipBytesID;
+static jmethodID JPEGImageReader_readInputDataID;
+static jmethodID JPEGImageReader_skipInputBytesID;
static jmethodID JPEGImageReader_warningOccurredID;
static jmethodID JPEGImageReader_warningWithMessageID;
static jmethodID JPEGImageReader_setImageDataID;
@@ -66,7 +66,7 @@
static jmethodID JPEGImageReader_pushBackID;
static jmethodID JPEGImageReader_passStartedID;
static jmethodID JPEGImageReader_passCompleteID;
-static jmethodID ImageOutputStream_writeID;
+static jmethodID JPEGImageWriter_writeOutputDataID;
static jmethodID JPEGImageWriter_warningOccurredID;
static jmethodID JPEGImageWriter_warningWithMessageID;
static jmethodID JPEGImageWriter_writeMetadataID;
@@ -923,7 +923,7 @@
RELEASE_ARRAYS(env, data, src->next_input_byte);
ret = (*env)->CallIntMethod(env,
sb->stream,
- ImageInputStream_readID,
+ JPEGImageReader_readInputDataID,
sb->hstreamBuffer, 0,
sb->bufferLength);
if ((*env)->ExceptionOccurred(env)
@@ -1013,7 +1013,7 @@
}
ret = (*env)->CallIntMethod(env, sb->stream,
- ImageInputStream_readID,
+ JPEGImageReader_readInputDataID,
sb->hstreamBuffer,
offset, buflen);
if ((*env)->ExceptionOccurred(env)
@@ -1107,7 +1107,7 @@
RELEASE_ARRAYS(env, data, src->next_input_byte);
ret = (*env)->CallLongMethod(env,
sb->stream,
- ImageInputStream_skipBytesID,
+ JPEGImageReader_skipInputBytesID,
(jlong) num_bytes);
if ((*env)->ExceptionOccurred(env)
|| !GET_ARRAYS(env, data, &(src->next_input_byte))) {
@@ -1382,13 +1382,13 @@
jclass qTableClass,
jclass huffClass) {
- ImageInputStream_readID = (*env)->GetMethodID(env,
- ImageInputStreamClass,
- "read",
+ JPEGImageReader_readInputDataID = (*env)->GetMethodID(env,
+ cls,
+ "readInputData",
"([BII)I");
- ImageInputStream_skipBytesID = (*env)->GetMethodID(env,
- ImageInputStreamClass,
- "skipBytes",
+ JPEGImageReader_skipInputBytesID = (*env)->GetMethodID(env,
+ cls,
+ "skipInputBytes",
"(J)J");
JPEGImageReader_warningOccurredID = (*env)->GetMethodID(env,
cls,
@@ -1531,8 +1531,7 @@
Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_setSource
(JNIEnv *env,
jobject this,
- jlong ptr,
- jobject source) {
+ jlong ptr) {
imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_common_ptr cinfo;
@@ -1546,7 +1545,7 @@
cinfo = data->jpegObj;
- imageio_set_stream(env, cinfo, data, source);
+ imageio_set_stream(env, cinfo, data, this);
imageio_init_source((j_decompress_ptr) cinfo);
}
@@ -2291,7 +2290,7 @@
(*env)->CallVoidMethod(env,
sb->stream,
- ImageOutputStream_writeID,
+ JPEGImageWriter_writeOutputDataID,
sb->hstreamBuffer,
0,
sb->bufferLength);
@@ -2328,7 +2327,7 @@
(*env)->CallVoidMethod(env,
sb->stream,
- ImageOutputStream_writeID,
+ JPEGImageWriter_writeOutputDataID,
sb->hstreamBuffer,
0,
datacount);
@@ -2366,13 +2365,12 @@
Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initWriterIDs
(JNIEnv *env,
jclass cls,
- jclass IOSClass,
jclass qTableClass,
jclass huffClass) {
- ImageOutputStream_writeID = (*env)->GetMethodID(env,
- IOSClass,
- "write",
+ JPEGImageWriter_writeOutputDataID = (*env)->GetMethodID(env,
+ cls,
+ "writeOutputData",
"([BII)V");
JPEGImageWriter_warningOccurredID = (*env)->GetMethodID(env,
@@ -2496,8 +2494,7 @@
Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest
(JNIEnv *env,
jobject this,
- jlong ptr,
- jobject destination) {
+ jlong ptr) {
imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_compress_ptr cinfo;
@@ -2511,7 +2508,7 @@
cinfo = (j_compress_ptr) data->jpegObj;
- imageio_set_stream(env, data->jpegObj, data, destination);
+ imageio_set_stream(env, data->jpegObj, data, this);
// Don't call the init method, as that depends on pinned arrays
--- a/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c Wed Apr 17 02:53:02 2013 -0700
@@ -42,6 +42,7 @@
#include "awt_Mlib.h"
#include "gdefs.h"
#include "safe_alloc.h"
+#include "safe_math.h"
/***************************************************************************
* Definitions *
@@ -1993,13 +1994,23 @@
unsigned char *dP = dataP;
#define NUM_LINES 10
int numLines = NUM_LINES;
- int nbytes = rasterP->width*4*NUM_LINES;
+ /* it is safe to calculate the scan length, because width has been verified
+ * on creation of the mlib image
+ */
+ int scanLength = rasterP->width * 4;
+
+ int nbytes = 0;
+ if (!SAFE_TO_MULT(numLines, scanLength)) {
+ return -1;
+ }
+
+ nbytes = numLines * scanLength;
for (y=0; y < rasterP->height; y+=numLines) {
/* getData, one scanline at a time */
if (y+numLines > rasterP->height) {
numLines = rasterP->height - y;
- nbytes = rasterP->width*4*numLines;
+ nbytes = numLines * scanLength;
}
jpixels = (*env)->CallObjectMethod(env, imageP->jimage,
g_BImgGetRGBMID, 0, y,
@@ -2129,8 +2140,14 @@
if (cvtToDefault) {
int status = 0;
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);
+ if (*mlibImagePP == NULL) {
+ return -1;
+ }
cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
- /* Make sure the image is cleared */
+ /* Make sure the image is cleared.
+ * NB: the image dimension is already verified, so we can
+ * safely calculate the length of the buffer.
+ */
memset(cDataP, 0, width*height*4);
if (!isSrc) {
@@ -2380,6 +2397,9 @@
case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
width, height);
+ if (*mlibImagePP == NULL) {
+ return -1;
+ }
if (!isSrc) return 0;
cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
return expandPackedBCR(env, rasterP, -1, cDataP);
@@ -2388,6 +2408,9 @@
if (rasterP->sppsm.maxBitSize <= 8) {
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
width, height);
+ if (*mlibImagePP == NULL) {
+ return -1;
+ }
if (!isSrc) return 0;
cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
return expandPackedSCR(env, rasterP, -1, cDataP);
@@ -2397,6 +2420,9 @@
if (rasterP->sppsm.maxBitSize <= 8) {
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
width, height);
+ if (*mlibImagePP == NULL) {
+ return -1;
+ }
if (!isSrc) return 0;
cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
return expandPackedICR(env, rasterP, -1, cDataP);
--- a/jdk/src/share/native/sun/awt/medialib/mlib_ImageCreate.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/awt/medialib/mlib_ImageCreate.c Wed Apr 17 02:53:02 2013 -0700
@@ -120,6 +120,7 @@
#include "mlib_image.h"
#include "mlib_ImageRowTable.h"
#include "mlib_ImageCreate.h"
+#include "safe_math.h"
/***************************************************************/
mlib_image* mlib_ImageSet(mlib_image *image,
@@ -247,28 +248,50 @@
return NULL;
};
+ if (!SAFE_TO_MULT(width, channels)) {
+ return NULL;
+ }
+
+ wb = width * channels;
+
switch (type) {
case MLIB_DOUBLE:
- wb = width * channels * 8;
+ if (!SAFE_TO_MULT(wb, 8)) {
+ return NULL;
+ }
+ wb *= 8;
break;
case MLIB_FLOAT:
case MLIB_INT:
- wb = width * channels * 4;
+ if (!SAFE_TO_MULT(wb, 4)) {
+ return NULL;
+ }
+ wb *= 4;
break;
case MLIB_USHORT:
case MLIB_SHORT:
- wb = width * channels * 2;
+ if (!SAFE_TO_MULT(wb, 4)) {
+ return NULL;
+ }
+ wb *= 2;
break;
case MLIB_BYTE:
- wb = width * channels;
+ // wb is ready
break;
case MLIB_BIT:
- wb = (width * channels + 7) / 8;
+ if (!SAFE_TO_ADD(7, wb)) {
+ return NULL;
+ }
+ wb = (wb + 7) / 8;
break;
default:
return NULL;
}
+ if (!SAFE_TO_MULT(wb, height)) {
+ return NULL;
+ }
+
data = mlib_malloc(wb * height);
if (data == NULL) {
return NULL;
--- a/jdk/src/share/native/sun/awt/medialib/safe_alloc.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/awt/medialib/safe_alloc.h Wed Apr 17 02:53:02 2013 -0700
@@ -41,10 +41,4 @@
(((w) > 0) && ((h) > 0) && ((sz) > 0) && \
(((0xffffffffu / ((juint)(w))) / ((juint)(h))) > ((juint)(sz))))
-#define SAFE_TO_MULT(a, b) \
- (((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b)))
-
-#define SAFE_TO_ADD(a, b) \
- (((a) >= 0) && ((b) >= 0) && ((0x7fffffff - (a)) > (b)))
-
#endif // __SAFE_ALLOC_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/awt/medialib/safe_math.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,35 @@
+/*
+ * 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. 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.
+ */
+
+#ifndef __SAFE_MATH_H__
+#define __SAFE_MATH_H__
+
+#define SAFE_TO_MULT(a, b) \
+ (((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b)))
+
+#define SAFE_TO_ADD(a, b) \
+ (((a) >= 0) && ((b) >= 0) && ((0x7fffffff - (a)) > (b)))
+
+#endif // __SAFE_MATH_H__
--- a/jdk/src/share/native/sun/font/FontInstanceAdapter.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/FontInstanceAdapter.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -66,8 +66,21 @@
yScalePixelsToUnits = upem / yppem;
};
+
const void *FontInstanceAdapter::getFontTable(LETag tableTag) const
{
+ size_t ignored = 0;
+ return getFontTable(tableTag, ignored);
+}
+
+static const LETag cacheMap[LAYOUTCACHE_ENTRIES] = {
+ GPOS_TAG, GDEF_TAG, GSUB_TAG, MORT_TAG, MORX_TAG, KERN_TAG
+};
+
+const void *FontInstanceAdapter::getFontTable(LETag tableTag, size_t &length) const
+{
+ length = 0;
+
if (!layoutTables) { // t1 font
return 0;
}
@@ -75,14 +88,19 @@
// cache in font's pscaler object
// font disposer will handle for us
- switch(tableTag) {
- case GSUB_TAG: if (layoutTables->gsub_len != -1) return (void*)layoutTables->gsub; break;
- case GPOS_TAG: if (layoutTables->gpos_len != -1) return (void*)layoutTables->gpos; break;
- case GDEF_TAG: if (layoutTables->gdef_len != -1) return (void*)layoutTables->gdef; break;
- case MORT_TAG: if (layoutTables->mort_len != -1) return (void*)layoutTables->mort; break;
- case KERN_TAG: if (layoutTables->kern_len != -1) return (void*)layoutTables->kern; break;
- default:
- //fprintf(stderr, "unexpected table request from font instance adapter: %x\n", tableTag);
+ int cacheIdx;
+ for (cacheIdx=0;cacheIdx<LAYOUTCACHE_ENTRIES;cacheIdx++) {
+ if (tableTag==cacheMap[cacheIdx]) break;
+ }
+
+ if (cacheIdx<LAYOUTCACHE_ENTRIES) { // if found
+ if (layoutTables->entries[cacheIdx].len != -1) {
+ length = layoutTables->entries[cacheIdx].len;
+ return layoutTables->entries[cacheIdx].ptr;
+ }
+ } else {
+ //fprintf(stderr, "unexpected table request from font instance adapter: %x\n", tableTag);
+ // (don't load any other tables)
return 0;
}
@@ -96,16 +114,13 @@
env->GetByteArrayRegion(tableBytes, 0, len, result);
}
- switch(tableTag) {
- case GSUB_TAG: layoutTables->gsub = (void*)result; layoutTables->gsub_len = len; break;
- case GPOS_TAG: layoutTables->gpos = (void*)result; layoutTables->gpos_len = len; break;
- case GDEF_TAG: layoutTables->gdef = (void*)result; layoutTables->gdef_len = len; break;
- case MORT_TAG: layoutTables->mort = (void*)result; layoutTables->mort_len = len; break;
- case KERN_TAG: layoutTables->kern = (void*)result; layoutTables->kern_len = len; break;
- default: break;
+ if (cacheIdx<LAYOUTCACHE_ENTRIES) { // if cacheable table
+ layoutTables->entries[cacheIdx].len = len;
+ layoutTables->entries[cacheIdx].ptr = (const void*)result;
}
- return (void*)result;
+ length = len;
+ return (const void*)result;
};
LEGlyphID FontInstanceAdapter::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const
--- a/jdk/src/share/native/sun/font/FontInstanceAdapter.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/FontInstanceAdapter.h Wed Apr 17 02:53:02 2013 -0700
@@ -86,6 +86,7 @@
// tables are cached with the native font scaler data
// only supports gsub, gpos, gdef, mort tables at present
virtual const void *getFontTable(LETag tableTag) const;
+ virtual const void *getFontTable(LETag tableTag, size_t &len) const;
virtual void *getKernPairs() const {
return layoutTables->kernPairs;
--- a/jdk/src/share/native/sun/font/fontscalerdefs.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/fontscalerdefs.h Wed Apr 17 02:53:02 2013 -0700
@@ -120,20 +120,19 @@
#define GPOS_TAG 0x47504F53 /* 'GPOS' */
#define GDEF_TAG 0x47444546 /* 'GDEF' */
#define MORT_TAG 0x6D6F7274 /* 'mort' */
+#define MORX_TAG 0x6D6F7278 /* 'morx' */
#define KERN_TAG 0x6B65726E /* 'kern' */
+typedef struct TTLayoutTableCacheEntry {
+ const void* ptr;
+ int len;
+} TTLayoutTableCacheEntry;
+
+#define LAYOUTCACHE_ENTRIES 6
+
typedef struct TTLayoutTableCache {
- void* gsub;
- void* gpos;
- void* gdef;
- void* mort;
- void* kern;
- void* kernPairs;
- int gsub_len;
- int gpos_len;
- int gdef_len;
- int mort_len;
- int kern_len;
+ TTLayoutTableCacheEntry entries[LAYOUTCACHE_ENTRIES];
+ void* kernPairs;
} TTLayoutTableCache;
#include "sunfontids.h"
--- a/jdk/src/share/native/sun/font/layout/AlternateSubstSubtables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/AlternateSubstSubtables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -39,19 +39,20 @@
U_NAMESPACE_BEGIN
-le_uint32 AlternateSubstitutionSubtable::process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter) const
+le_uint32 AlternateSubstitutionSubtable::process(const LEReferenceTo<AlternateSubstitutionSubtable> &base,
+ GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
// NOTE: For now, we'll just pick the first alternative...
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
- le_int32 coverageIndex = getGlyphCoverage(glyph);
+ le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
- if (coverageIndex >= 0) {
+ if (coverageIndex >= 0 && LE_SUCCESS(success)) {
le_uint16 altSetCount = SWAPW(alternateSetCount);
if (coverageIndex < altSetCount) {
Offset alternateSetTableOffset = SWAPW(alternateSetTableOffsetArray[coverageIndex]);
- const AlternateSetTable *alternateSetTable =
- (const AlternateSetTable *) ((char *) this + alternateSetTableOffset);
+ const LEReferenceTo<AlternateSetTable> alternateSetTable(base, success,
+ (const AlternateSetTable *) ((char *) this + alternateSetTableOffset));
TTGlyphID alternate = SWAPW(alternateSetTable->alternateArray[0]);
if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, alternate))) {
--- a/jdk/src/share/native/sun/font/layout/AlternateSubstSubtables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/AlternateSubstSubtables.h Wed Apr 17 02:53:02 2013 -0700
@@ -51,13 +51,17 @@
TTGlyphID alternateArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(AlternateSetTable, alternateArray)
+
struct AlternateSubstitutionSubtable : GlyphSubstitutionSubtable
{
le_uint16 alternateSetCount;
Offset alternateSetTableOffsetArray[ANY_NUMBER];
- le_uint32 process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter = NULL) const;
+ le_uint32 process(const LEReferenceTo<AlternateSubstitutionSubtable> &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter = NULL) const;
};
+LE_VAR_ARRAY(AlternateSubstitutionSubtable, alternateSetTableOffsetArray)
+
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/ArabicLayoutEngine.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ArabicLayoutEngine.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -26,7 +26,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -58,15 +58,18 @@
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ArabicOpenTypeLayoutEngine)
-ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
+ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode,
+ le_int32 languageCode, le_int32 typoFlags,
+ const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable,
+ LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
{
fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
fFeatureOrder = TRUE;
}
-ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
+ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode,
+ le_int32 languageCode,
le_int32 typoFlags, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
{
@@ -88,8 +91,9 @@
// Input: characters
// Output: characters, char indices, tags
// Returns: output character count
-le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
- LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
+le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count,
+ le_int32 max, le_bool rightToLeft, LEUnicode *&outChars,
+ LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
if (LE_FAILURE(success)) {
return 0;
@@ -137,32 +141,30 @@
return;
}
- if (fGPOSTable != NULL) {
+ if (!fGPOSTable.isEmpty()) {
OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphStorage, success);
- } else if (fGDEFTable != NULL) {
- GDEFMarkFilter filter(fGDEFTable);
-
+ } else if (!fGDEFTable.isEmpty()) {
+ GDEFMarkFilter filter(fGDEFTable, success);
adjustMarkGlyphs(glyphStorage, &filter, success);
} else {
- GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
- GDEFMarkFilter filter(gdefTable);
+ LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen);
+ GDEFMarkFilter filter(gdefTable, success);
adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
}
}
UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
- : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
+ : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags | LE_CHAR_FILTER_FEATURE_FLAG, success)
{
fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
-
- fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
+ /* OpenTypeLayoutEngine will allocate a substitution filter */
}
UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
{
- delete fSubstitutionFilter;
+ /* OpenTypeLayoutEngine will cleanup the substitution filter */
}
// "glyphs", "indices" -> glyphs, indices
@@ -233,7 +235,7 @@
return;
}
- GDEFMarkFilter filter(fGDEFTable);
+ GDEFMarkFilter filter(fGDEFTable, success);
adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
}
--- a/jdk/src/share/native/sun/font/layout/ArabicLayoutEngine.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ArabicLayoutEngine.h Wed Apr 17 02:53:02 2013 -0700
@@ -75,7 +75,7 @@
* @internal
*/
ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success);
+ le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success);
/**
* This constructor is used when the font requires a "canned" GSUB table which can't be known
--- a/jdk/src/share/native/sun/font/layout/ArabicShaping.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ArabicShaping.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -58,14 +58,16 @@
*/
ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c)
{
- const ClassDefinitionTable *joiningTypes = (const ClassDefinitionTable *) ArabicShaping::shapingTypeTable;
- le_int32 joiningType = joiningTypes->getGlyphClass(c);
+ LEErrorCode success = LE_NO_ERROR;
+ const LEReferenceTo<ClassDefinitionTable> joiningTypes((const ClassDefinitionTable *) ArabicShaping::shapingTypeTable,
+ ArabicShaping::shapingTypeTableLen);
+ le_int32 joiningType = joiningTypes->getGlyphClass(joiningTypes, c, success);
- if (joiningType >= 0 && joiningType < ArabicShaping::JT_COUNT) {
- return ArabicShaping::shapeTypes[joiningType];
- }
+ if (joiningType >= 0 && joiningType < ArabicShaping::JT_COUNT && LE_SUCCESS(success)) {
+ return ArabicShaping::shapeTypes[joiningType];
+ }
- return ArabicShaping::ST_NOSHAPE_NONE;
+ return ArabicShaping::ST_NOSHAPE_NONE;
}
#define isolFeatureTag LE_ISOL_FEATURE_TAG
--- a/jdk/src/share/native/sun/font/layout/ArabicShaping.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ArabicShaping.h Wed Apr 17 02:53:02 2013 -0700
@@ -93,6 +93,8 @@
static ShapeType getShapeType(LEUnicode c);
static const le_uint8 shapingTypeTable[];
+ static const size_t shapingTypeTableLen;
+
static const ShapeType shapeTypes[];
static void adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphStorage &glyphStorage);
--- a/jdk/src/share/native/sun/font/layout/AttachmentPosnSubtables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/AttachmentPosnSubtables.h Wed Apr 17 02:53:02 2013 -0700
@@ -52,14 +52,14 @@
Offset markArrayOffset;
Offset baseArrayOffset;
- inline le_int32 getBaseCoverage(LEGlyphID baseGlyphId) const;
+ inline le_int32 getBaseCoverage(const LETableReference &base, LEGlyphID baseGlyphId, LEErrorCode &success) const;
le_uint32 process(GlyphIterator *glyphIterator) const;
};
-inline le_int32 AttachmentPositioningSubtable::getBaseCoverage(LEGlyphID baseGlyphID) const
+inline le_int32 AttachmentPositioningSubtable::getBaseCoverage(const LETableReference &base, LEGlyphID baseGlyphID, LEErrorCode &success) const
{
- return getGlyphCoverage(baseCoverageTableOffset, baseGlyphID);
+ return getGlyphCoverage(base, baseCoverageTableOffset, baseGlyphID, success);
}
U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/CanonData.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/CanonData.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -3641,4 +3641,9 @@
0x00, 0xE6, 0xD2, 0x42, 0xD2, 0x44, 0x00, 0xE6
};
+
+const size_t CanonShaping::glyphSubstitutionTableLen = sizeof(glyphSubstitutionTable)/sizeof(glyphSubstitutionTable[0]);
+
+const size_t CanonShaping::glyphDefinitionTableLen = sizeof(glyphDefinitionTable)/sizeof(glyphDefinitionTable[0]);
+
U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/CanonShaping.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/CanonShaping.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -59,15 +59,15 @@
void CanonShaping::reorderMarks(const LEUnicode *inChars, le_int32 charCount, le_bool rightToLeft,
LEUnicode *outChars, LEGlyphStorage &glyphStorage)
{
- const GlyphDefinitionTableHeader *gdefTable = (const GlyphDefinitionTableHeader *) glyphDefinitionTable;
- const ClassDefinitionTable *classTable = gdefTable->getMarkAttachClassDefinitionTable();
+ LEErrorCode success = LE_NO_ERROR;
+ LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen);
+ LEReferenceTo<ClassDefinitionTable> classTable = gdefTable->getMarkAttachClassDefinitionTable(gdefTable, success);
le_int32 *combiningClasses = LE_NEW_ARRAY(le_int32, charCount);
le_int32 *indices = LE_NEW_ARRAY(le_int32, charCount);
- LEErrorCode status = LE_NO_ERROR;
le_int32 i;
for (i = 0; i < charCount; i += 1) {
- combiningClasses[i] = classTable->getGlyphClass((LEGlyphID) inChars[i]);
+ combiningClasses[i] = classTable->getGlyphClass(classTable, (LEGlyphID) inChars[i], success);
indices[i] = i;
}
@@ -96,7 +96,7 @@
le_int32 index = indices[i];
outChars[i] = inChars[index];
- glyphStorage.setCharIndex(out, index, status);
+ glyphStorage.setCharIndex(out, index, success);
}
LE_DELETE_ARRAY(indices);
--- a/jdk/src/share/native/sun/font/layout/CanonShaping.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/CanonShaping.h Wed Apr 17 02:53:02 2013 -0700
@@ -42,7 +42,9 @@
{
public:
static const le_uint8 glyphSubstitutionTable[];
+ static const size_t glyphSubstitutionTableLen;
static const le_uint8 glyphDefinitionTable[];
+ static const size_t glyphDefinitionTableLen;
static void reorderMarks(const LEUnicode *inChars, le_int32 charCount, le_bool rightToLeft,
LEUnicode *outChars, LEGlyphStorage &glyphStorage);
--- a/jdk/src/share/native/sun/font/layout/ClassDefinitionTables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ClassDefinitionTables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -37,24 +37,51 @@
U_NAMESPACE_BEGIN
-le_int32 ClassDefinitionTable::getGlyphClass(LEGlyphID glyphID) const
+le_int32 ClassDefinitionTable::getGlyphClass(const LETableReference& base, LEGlyphID glyphID, LEErrorCode &success) const
{
+ LEReferenceTo<ClassDefinitionTable> thisRef(base, success);
+ if (LE_FAILURE(success)) return 0;
+
+ switch(SWAPW(classFormat)) {
+ case 0:
+ return 0;
+
+ case 1:
+ {
+ const LEReferenceTo<ClassDefFormat1Table> f1Table(thisRef, success);
+ return f1Table->getGlyphClass(f1Table, glyphID, success);
+ }
+
+ case 2:
+ {
+ const LEReferenceTo<ClassDefFormat2Table> f2Table(thisRef, success);
+ return f2Table->getGlyphClass(f2Table, glyphID, success);
+ }
+
+ default:
+ return 0;
+ }
+}
+
+le_bool ClassDefinitionTable::hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const
+{
+ LEReferenceTo<ClassDefinitionTable> thisRef(base, success);
+ if (LE_FAILURE(success)) return 0;
+
switch(SWAPW(classFormat)) {
case 0:
return 0;
case 1:
{
- const ClassDefFormat1Table *f1Table = (const ClassDefFormat1Table *) this;
-
- return f1Table->getGlyphClass(glyphID);
+ const LEReferenceTo<ClassDefFormat1Table> f1Table(thisRef, success);
+ return f1Table->hasGlyphClass(f1Table, glyphClass, success);
}
case 2:
{
- const ClassDefFormat2Table *f2Table = (const ClassDefFormat2Table *) this;
-
- return f2Table->getGlyphClass(glyphID);
+ const LEReferenceTo<ClassDefFormat2Table> f2Table(thisRef, success);
+ return f2Table->hasGlyphClass(f2Table, glyphClass, success);
}
default:
@@ -62,51 +89,32 @@
}
}
-le_bool ClassDefinitionTable::hasGlyphClass(le_int32 glyphClass) const
+le_int32 ClassDefFormat1Table::getGlyphClass(const LETableReference& base, LEGlyphID glyphID, LEErrorCode &success) const
{
- switch(SWAPW(classFormat)) {
- case 0:
- return 0;
-
- case 1:
- {
- const ClassDefFormat1Table *f1Table = (const ClassDefFormat1Table *) this;
-
- return f1Table->hasGlyphClass(glyphClass);
- }
+ if(LE_FAILURE(success)) return 0;
- case 2:
- {
- const ClassDefFormat2Table *f2Table = (const ClassDefFormat2Table *) this;
-
- return f2Table->hasGlyphClass(glyphClass);
- }
-
- default:
- return 0;
- }
-}
-
-le_int32 ClassDefFormat1Table::getGlyphClass(LEGlyphID glyphID) const
-{
+ le_uint16 count = SWAPW(glyphCount);
+ LEReferenceToArrayOf<le_uint16> classValueArrayRef(base, success, &classValueArray[0], count);
TTGlyphID ttGlyphID = (TTGlyphID) LE_GET_GLYPH(glyphID);
TTGlyphID firstGlyph = SWAPW(startGlyph);
- TTGlyphID lastGlyph = firstGlyph + SWAPW(glyphCount);
+ TTGlyphID lastGlyph = firstGlyph + count;
- if (ttGlyphID >= firstGlyph && ttGlyphID < lastGlyph) {
- return SWAPW(classValueArray[ttGlyphID - firstGlyph]);
+ if (LE_SUCCESS(success) && ttGlyphID >= firstGlyph && ttGlyphID < lastGlyph) {
+ return SWAPW( classValueArrayRef(ttGlyphID - firstGlyph, success) );
}
return 0;
}
-le_bool ClassDefFormat1Table::hasGlyphClass(le_int32 glyphClass) const
+le_bool ClassDefFormat1Table::hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const
{
- le_uint16 count = SWAPW(glyphCount);
+ if(LE_FAILURE(success)) return 0;
+ le_uint16 count = SWAPW(glyphCount);
+ LEReferenceToArrayOf<le_uint16> classValueArrayRef(base, success, &classValueArray[0], count);
int i;
- for (i = 0; i < count; i += 1) {
- if (SWAPW(classValueArray[i]) == glyphClass) {
+ for (i = 0; LE_SUCCESS(success)&& (i < count); i += 1) {
+ if (SWAPW(classValueArrayRef(i,success)) == glyphClass) {
return TRUE;
}
}
@@ -114,27 +122,31 @@
return FALSE;
}
-le_int32 ClassDefFormat2Table::getGlyphClass(LEGlyphID glyphID) const
+le_int32 ClassDefFormat2Table::getGlyphClass(const LETableReference& base, LEGlyphID glyphID, LEErrorCode &success) const
{
+ if(LE_FAILURE(success)) return 0;
TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyphID);
le_uint16 rangeCount = SWAPW(classRangeCount);
+ LEReferenceToArrayOf<GlyphRangeRecord> classRangeRecordArrayRef(base, success, &classRangeRecordArray[0], rangeCount);
le_int32 rangeIndex =
- OpenTypeUtilities::getGlyphRangeIndex(ttGlyph, classRangeRecordArray, rangeCount);
+ OpenTypeUtilities::getGlyphRangeIndex(ttGlyph, classRangeRecordArrayRef, success);
- if (rangeIndex < 0) {
+ if (rangeIndex < 0 || LE_FAILURE(success)) {
return 0;
}
- return SWAPW(classRangeRecordArray[rangeIndex].rangeValue);
+ return SWAPW(classRangeRecordArrayRef(rangeIndex, success).rangeValue);
}
-le_bool ClassDefFormat2Table::hasGlyphClass(le_int32 glyphClass) const
+le_bool ClassDefFormat2Table::hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const
{
+ if(LE_FAILURE(success)) return 0;
le_uint16 rangeCount = SWAPW(classRangeCount);
+ LEReferenceToArrayOf<GlyphRangeRecord> classRangeRecordArrayRef(base, success, &classRangeRecordArray[0], rangeCount);
int i;
- for (i = 0; i < rangeCount; i += 1) {
- if (SWAPW(classRangeRecordArray[i].rangeValue) == glyphClass) {
+ for (i = 0; i < rangeCount && LE_SUCCESS(success); i += 1) {
+ if (SWAPW(classRangeRecordArrayRef(i,success).rangeValue) == glyphClass) {
return TRUE;
}
}
--- a/jdk/src/share/native/sun/font/layout/ClassDefinitionTables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ClassDefinitionTables.h Wed Apr 17 02:53:02 2013 -0700
@@ -46,8 +46,20 @@
{
le_uint16 classFormat;
- le_int32 getGlyphClass(LEGlyphID glyphID) const;
- le_bool hasGlyphClass(le_int32 glyphClass) const;
+ le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
+ le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
+
+ le_int32 getGlyphClass(LEGlyphID glyphID) const {
+ LETableReference base((const le_uint8*)this);
+ LEErrorCode ignored = LE_NO_ERROR;
+ return getGlyphClass(base,glyphID,ignored);
+ }
+
+ le_bool hasGlyphClass(le_int32 glyphClass) const {
+ LETableReference base((const le_uint8*)this);
+ LEErrorCode ignored = LE_NO_ERROR;
+ return hasGlyphClass(base,glyphClass,ignored);
+ }
};
struct ClassDefFormat1Table : ClassDefinitionTable
@@ -56,9 +68,11 @@
le_uint16 glyphCount;
le_uint16 classValueArray[ANY_NUMBER];
- le_int32 getGlyphClass(LEGlyphID glyphID) const;
- le_bool hasGlyphClass(le_int32 glyphClass) const;
+ le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
+ le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
};
+LE_VAR_ARRAY(ClassDefFormat1Table, classValueArray)
+
struct ClassRangeRecord
{
@@ -72,9 +86,10 @@
le_uint16 classRangeCount;
GlyphRangeRecord classRangeRecordArray[ANY_NUMBER];
- le_int32 getGlyphClass(LEGlyphID glyphID) const;
- le_bool hasGlyphClass(le_int32 glyphClass) const;
+ le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
+ le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
};
+LE_VAR_ARRAY(ClassDefFormat2Table, classRangeRecordArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/ContextualGlyphInsertion.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphInsertion.h Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -49,6 +49,11 @@
{
};
+struct ContextualGlyphInsertionHeader2 : MorphStateTableHeader2
+{
+ le_uint32 insertionTableOffset;
+};
+
enum ContextualGlyphInsertionFlags
{
cgiSetMark = 0x8000,
@@ -61,11 +66,17 @@
cgiMarkedInsertCountMask = 0x001F
};
-struct LigatureSubstitutionStateEntry : StateEntry
+struct ContextualGlyphInsertionStateEntry : StateEntry
{
ByteOffset currentInsertionListOffset;
ByteOffset markedInsertionListOffset;
};
+struct ContextualGlyphInsertionStateEntry2 : StateEntry2
+{
+ le_uint16 currentInsertionListIndex;
+ le_uint16 markedInsertionListIndex;
+};
+
U_NAMESPACE_END
#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphInsertionProc2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "StateTables.h"
+#include "MorphStateTables.h"
+#include "SubtableProcessor2.h"
+#include "StateTableProcessor2.h"
+#include "ContextualGlyphInsertionProc2.h"
+#include "LEGlyphStorage.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphInsertionProcessor2)
+
+ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2(
+ const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+ : StateTableProcessor2(morphSubtableHeader, success)
+{
+ contextualGlyphHeader = LEReferenceTo<ContextualGlyphInsertionHeader2>(morphSubtableHeader, success);
+ if(LE_FAILURE(success) || !contextualGlyphHeader.isValid()) return;
+ le_uint32 insertionTableOffset = SWAPL(contextualGlyphHeader->insertionTableOffset);
+ insertionTable = LEReferenceToArrayOf<le_uint16>(stHeader, success, insertionTableOffset, LE_UNBOUNDED_ARRAY);
+ entryTable = LEReferenceToArrayOf<ContextualGlyphInsertionStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
+}
+
+ContextualGlyphInsertionProcessor2::~ContextualGlyphInsertionProcessor2()
+{
+}
+
+void ContextualGlyphInsertionProcessor2::beginStateTable()
+{
+ markGlyph = 0;
+}
+
+void ContextualGlyphInsertionProcessor2::doInsertion(LEGlyphStorage &glyphStorage,
+ le_int16 atGlyph,
+ le_int16 &index,
+ le_int16 count,
+ le_bool /* isKashidaLike */,
+ le_bool isBefore,
+ LEErrorCode &success) {
+ LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(atGlyph, count + 1, success);
+
+ if(LE_FAILURE(success) || insertGlyphs==NULL) {
+ return;
+ }
+
+ // Note: Kashida vs Split Vowel seems to only affect selection and highlighting.
+ // We note the flag, but do not layout different.
+ // https://developer.apple.com/fonts/TTRefMan/RM06/Chap6mort.html
+
+ le_int16 targetIndex = 0;
+ if(isBefore) {
+ // insert at beginning
+ insertGlyphs[targetIndex++] = glyphStorage[atGlyph];
+ } else {
+ // insert at end
+ insertGlyphs[count] = glyphStorage[atGlyph];
+ }
+
+ while(count--) {
+ insertGlyphs[targetIndex++] = insertionTable.getObject(index++, success);
+ }
+ glyphStorage.applyInsertions();
+}
+
+le_uint16 ContextualGlyphInsertionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
+ EntryTableIndex2 index, LEErrorCode &success)
+{
+ const ContextualGlyphInsertionStateEntry2 *entry = entryTable.getAlias(index, success);
+
+ if(LE_FAILURE(success)) return 0; // TODO- which state?
+
+ le_uint16 newState = SWAPW(entry->newStateIndex);
+ le_uint16 flags = SWAPW(entry->flags);
+
+ le_int16 markIndex = SWAPW(entry->markedInsertionListIndex);
+ if (markIndex > 0) {
+ le_int16 count = (flags & cgiMarkedInsertCountMask) >> 5;
+ le_bool isKashidaLike = (flags & cgiMarkedIsKashidaLike);
+ le_bool isBefore = (flags & cgiMarkInsertBefore);
+ doInsertion(glyphStorage, markGlyph, markIndex, count, isKashidaLike, isBefore, success);
+ }
+
+ le_int16 currIndex = SWAPW(entry->currentInsertionListIndex);
+ if (currIndex > 0) {
+ le_int16 count = flags & cgiCurrentInsertCountMask;
+ le_bool isKashidaLike = (flags & cgiCurrentIsKashidaLike);
+ le_bool isBefore = (flags & cgiCurrentInsertBefore);
+ doInsertion(glyphStorage, currGlyph, currIndex, count, isKashidaLike, isBefore, success);
+ }
+
+ if (flags & cgiSetMark) {
+ markGlyph = currGlyph;
+ }
+
+ if (!(flags & cgiDontAdvance)) {
+ currGlyph += dir;
+ }
+
+ return newState;
+}
+
+void ContextualGlyphInsertionProcessor2::endStateTable()
+{
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphInsertionProc2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __CONTEXTUALGLYPHINSERTIONPROCESSOR2_H
+#define __CONTEXTUALGLYPHINSERTIONPROCESSOR2_H
+
+/**
+ * \file
+ * \internal
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "StateTableProcessor2.h"
+#include "ContextualGlyphInsertionProc2.h"
+#include "ContextualGlyphInsertion.h"
+
+U_NAMESPACE_BEGIN
+
+class LEGlyphStorage;
+
+class ContextualGlyphInsertionProcessor2 : public StateTableProcessor2
+{
+public:
+ virtual void beginStateTable();
+
+ virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage,
+ le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success);
+
+ virtual void endStateTable();
+
+ ContextualGlyphInsertionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+ virtual ~ContextualGlyphInsertionProcessor2();
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for the actual class.
+ *
+ * @stable ICU 2.8
+ */
+ virtual UClassID getDynamicClassID() const;
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for this class.
+ *
+ * @stable ICU 2.8
+ */
+ static UClassID getStaticClassID();
+
+private:
+ ContextualGlyphInsertionProcessor2();
+
+ /**
+ * Perform the actual insertion
+ * @param atGlyph index of glyph to insert at
+ * @param index index into the insertionTable (in/out)
+ * @param count number of insertions
+ * @param isKashidaLike Kashida like (vs Split Vowel like). No effect currently.
+ * @param isBefore if true, insert extra glyphs before the marked glyph
+ */
+ void doInsertion(LEGlyphStorage &glyphStorage,
+ le_int16 atGlyph,
+ le_int16 &index,
+ le_int16 count,
+ le_bool isKashidaLike,
+ le_bool isBefore,
+ LEErrorCode &success);
+
+
+protected:
+ le_int32 markGlyph;
+ LEReferenceToArrayOf<le_uint16> insertionTable;
+ LEReferenceToArrayOf<ContextualGlyphInsertionStateEntry2> entryTable;
+ LEReferenceTo<ContextualGlyphInsertionHeader2> contextualGlyphHeader;
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -43,13 +43,18 @@
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphSubstitutionProcessor)
-ContextualGlyphSubstitutionProcessor::ContextualGlyphSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader)
- : StateTableProcessor(morphSubtableHeader)
+ContextualGlyphSubstitutionProcessor::ContextualGlyphSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
+ : StateTableProcessor(morphSubtableHeader, success), entryTable(), contextualGlyphSubstitutionHeader(morphSubtableHeader, success)
{
- contextualGlyphSubstitutionHeader = (const ContextualGlyphSubstitutionHeader *) morphSubtableHeader;
- substitutionTableOffset = SWAPW(contextualGlyphSubstitutionHeader->substitutionTableOffset);
+ contextualGlyphSubstitutionHeader.orphan();
+ substitutionTableOffset = SWAPW(contextualGlyphSubstitutionHeader->substitutionTableOffset);
+
- entryTable = (const ContextualGlyphSubstitutionStateEntry *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
+ entryTable = LEReferenceToArrayOf<ContextualGlyphSubstitutionStateEntry>(stateTableHeader, success,
+ (const ContextualGlyphSubstitutionStateEntry*)(&stateTableHeader->stHeader),
+ entryTableOffset, LE_UNBOUNDED_ARRAY);
+ int16Table = LEReferenceToArrayOf<le_int16>(stateTableHeader, success, (const le_int16*)(&stateTableHeader->stHeader),
+ 0, LE_UNBOUNDED_ARRAY); // rest of the table as le_int16s
}
ContextualGlyphSubstitutionProcessor::~ContextualGlyphSubstitutionProcessor()
@@ -63,27 +68,26 @@
ByteOffset ContextualGlyphSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index)
{
- const ContextualGlyphSubstitutionStateEntry *entry = &entryTable[index];
- ByteOffset newState = SWAPW(entry->newStateOffset);
- le_int16 flags = SWAPW(entry->flags);
- WordOffset markOffset = SWAPW(entry->markOffset);
- WordOffset currOffset = SWAPW(entry->currOffset);
-
- if (markOffset != 0) {
- const le_int16 *table = (const le_int16 *) ((char *) &stateTableHeader->stHeader + markOffset * 2);
- LEGlyphID mGlyph = glyphStorage[markGlyph];
- TTGlyphID newGlyph = SWAPW(table[LE_GET_GLYPH(mGlyph)]);
+ LEErrorCode success = LE_NO_ERROR;
+ const ContextualGlyphSubstitutionStateEntry *entry = entryTable.getAlias(index, success);
+ ByteOffset newState = SWAPW(entry->newStateOffset);
+ le_int16 flags = SWAPW(entry->flags);
+ WordOffset markOffset = SWAPW(entry->markOffset);
+ WordOffset currOffset = SWAPW(entry->currOffset);
- glyphStorage[markGlyph] = LE_SET_GLYPH(mGlyph, newGlyph);
- }
+ if (markOffset != 0 && LE_SUCCESS(success)) {
+ LEGlyphID mGlyph = glyphStorage[markGlyph];
+ TTGlyphID newGlyph = SWAPW(int16Table.getObject(markOffset + LE_GET_GLYPH(mGlyph), success)); // whew.
+
+ glyphStorage[markGlyph] = LE_SET_GLYPH(mGlyph, newGlyph);
+ }
- if (currOffset != 0) {
- const le_int16 *table = (const le_int16 *) ((char *) &stateTableHeader->stHeader + currOffset * 2);
- LEGlyphID thisGlyph = glyphStorage[currGlyph];
- TTGlyphID newGlyph = SWAPW(table[LE_GET_GLYPH(thisGlyph)]);
+ if (currOffset != 0) {
+ LEGlyphID thisGlyph = glyphStorage[currGlyph];
+ TTGlyphID newGlyph = SWAPW(int16Table.getObject(currOffset + LE_GET_GLYPH(thisGlyph), success)); // whew.
- glyphStorage[currGlyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
- }
+ glyphStorage[currGlyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
+ }
if (flags & cgsSetMark) {
markGlyph = currGlyph;
--- a/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc.h Wed Apr 17 02:53:02 2013 -0700
@@ -56,7 +56,7 @@
virtual void endStateTable();
- ContextualGlyphSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader);
+ ContextualGlyphSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~ContextualGlyphSubstitutionProcessor();
/**
@@ -78,11 +78,11 @@
protected:
ByteOffset substitutionTableOffset;
- const ContextualGlyphSubstitutionStateEntry *entryTable;
-
+ LEReferenceToArrayOf<ContextualGlyphSubstitutionStateEntry> entryTable;
+ LEReferenceToArrayOf<le_int16> int16Table;
le_int32 markGlyph;
- const ContextualGlyphSubstitutionHeader *contextualGlyphSubstitutionHeader;
+ LEReferenceTo<ContextualGlyphSubstitutionHeader> contextualGlyphSubstitutionHeader;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "StateTables.h"
+#include "MorphStateTables.h"
+#include "SubtableProcessor2.h"
+#include "StateTableProcessor2.h"
+#include "ContextualGlyphSubstProc2.h"
+#include "LEGlyphStorage.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphSubstitutionProcessor2)
+
+ContextualGlyphSubstitutionProcessor2::ContextualGlyphSubstitutionProcessor2(
+ const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+ : StateTableProcessor2(morphSubtableHeader, success), contextualGlyphHeader(morphSubtableHeader, success)
+{
+ if(LE_FAILURE(success)) return;
+ le_uint32 perGlyphTableOffset = SWAPL(contextualGlyphHeader->perGlyphTableOffset);
+ perGlyphTable = LEReferenceToArrayOf<le_uint32> (stHeader, success, perGlyphTableOffset, LE_UNBOUNDED_ARRAY);
+ entryTable = LEReferenceToArrayOf<ContextualGlyphStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
+}
+
+ContextualGlyphSubstitutionProcessor2::~ContextualGlyphSubstitutionProcessor2()
+{
+}
+
+void ContextualGlyphSubstitutionProcessor2::beginStateTable()
+{
+ markGlyph = 0;
+}
+
+le_uint16 ContextualGlyphSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
+ EntryTableIndex2 index, LEErrorCode &success)
+{
+ if(LE_FAILURE(success)) return 0;
+ const ContextualGlyphStateEntry2 *entry = entryTable.getAlias(index, success);
+ if(LE_FAILURE(success)) return 0;
+ le_uint16 newState = SWAPW(entry->newStateIndex);
+ le_uint16 flags = SWAPW(entry->flags);
+ le_int16 markIndex = SWAPW(entry->markIndex);
+ le_int16 currIndex = SWAPW(entry->currIndex);
+
+ if (markIndex != -1) {
+ le_uint32 offset = SWAPL(perGlyphTable(markIndex, success));
+ LEGlyphID mGlyph = glyphStorage[markGlyph];
+ TTGlyphID newGlyph = lookup(offset, mGlyph, success);
+ glyphStorage[markGlyph] = LE_SET_GLYPH(mGlyph, newGlyph);
+ }
+
+ if (currIndex != -1) {
+ le_uint32 offset = SWAPL(perGlyphTable(currIndex, success));
+ LEGlyphID thisGlyph = glyphStorage[currGlyph];
+ TTGlyphID newGlyph = lookup(offset, thisGlyph, success);
+ glyphStorage[currGlyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
+ }
+
+ if (flags & cgsSetMark) {
+ markGlyph = currGlyph;
+ }
+
+ if (!(flags & cgsDontAdvance)) {
+ currGlyph += dir;
+ }
+
+ return newState;
+}
+
+TTGlyphID ContextualGlyphSubstitutionProcessor2::lookup(le_uint32 offset, LEGlyphID gid, LEErrorCode &success)
+{
+ TTGlyphID newGlyph = 0xFFFF;
+ if(LE_FAILURE(success)) return newGlyph;
+ LEReferenceTo<LookupTable> lookupTable(perGlyphTable, success, offset);
+ if(LE_FAILURE(success)) return newGlyph;
+ le_int16 format = SWAPW(lookupTable->format);
+
+ switch (format) {
+ case ltfSimpleArray: {
+#ifdef TEST_FORMAT
+ // Disabled pending for design review
+ LEReferenceTo<SimpleArrayLookupTable> lookupTable0(lookupTable, success);
+ LEReferenceToArrayOf<LookupValue> valueArray(lookupTable0, success, &lookupTable0->valueArray[0], LE_UNBOUNDED_ARRAY);
+ if(LE_FAILURE(success)) return newGlyph;
+ TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
+ newGlyph = SWAPW(lookupTable0->valueArray(glyphCode, success));
+#endif
+ break;
+ }
+ case ltfSegmentSingle: {
+#ifdef TEST_FORMAT
+ // Disabled pending for design review
+ LEReferenceTo<SegmentSingleLookupTable> lookupTable2 = (SegmentSingleLookupTable *) lookupTable;
+ const LookupSegment *segment = lookupTable2->lookupSegment(lookupTable2->segments, gid);
+ if (segment != NULL) {
+ newGlyph = SWAPW(segment->value);
+ }
+#endif
+ break;
+ }
+ case ltfSegmentArray: {
+ //printf("Context Lookup Table Format4: specific interpretation needed!\n");
+ break;
+ }
+ case ltfSingleTable:
+ {
+#ifdef TEST_FORMAT
+ // Disabled pending for design review
+ LEReferenceTo<SingleTableLookupTable> lookupTable6 = (SingleTableLookupTable *) lookupTable;
+ const LEReferenceTo<LookupSingle> segment = lookupTable6->lookupSingle(lookupTable6->entries, gid);
+ if (segment != NULL) {
+ newGlyph = SWAPW(segment->value);
+ }
+#endif
+ break;
+ }
+ case ltfTrimmedArray: {
+ LEReferenceTo<TrimmedArrayLookupTable> lookupTable8(lookupTable, success);
+ if (LE_FAILURE(success)) return newGlyph;
+ TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph);
+ TTGlyphID glyphCount = SWAPW(lookupTable8->glyphCount);
+ TTGlyphID lastGlyph = firstGlyph + glyphCount;
+ TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
+ if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) {
+ LEReferenceToArrayOf<LookupValue> valueArray(lookupTable8, success, &lookupTable8->valueArray[0], glyphCount);
+ newGlyph = SWAPW(valueArray(glyphCode - firstGlyph, success));
+ }
+ }
+ default:
+ break;
+ }
+ return newGlyph;
+}
+
+void ContextualGlyphSubstitutionProcessor2::endStateTable()
+{
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __CONTEXTUALGLYPHSUBSTITUTIONPROCESSOR2_H
+#define __CONTEXTUALGLYPHSUBSTITUTIONPROCESSOR2_H
+
+/**
+ * \file
+ * \internal
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "StateTableProcessor2.h"
+#include "ContextualGlyphSubstitution.h"
+
+U_NAMESPACE_BEGIN
+
+class LEGlyphStorage;
+
+class ContextualGlyphSubstitutionProcessor2 : public StateTableProcessor2
+{
+public:
+ virtual void beginStateTable();
+
+ virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success);
+
+ virtual void endStateTable();
+
+ ContextualGlyphSubstitutionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+ virtual ~ContextualGlyphSubstitutionProcessor2();
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for the actual class.
+ *
+ * @stable ICU 2.8
+ */
+ virtual UClassID getDynamicClassID() const;
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for this class.
+ *
+ * @stable ICU 2.8
+ */
+ static UClassID getStaticClassID();
+
+private:
+ ContextualGlyphSubstitutionProcessor2();
+ TTGlyphID lookup(le_uint32 offset, LEGlyphID gid, LEErrorCode &success);
+
+protected:
+ LEReferenceToArrayOf<le_uint32> perGlyphTable;
+ LEReferenceToArrayOf<ContextualGlyphStateEntry2> entryTable;
+
+ le_int16 perGlyphTableFormat;
+ le_int32 markGlyph;
+
+ LEReferenceTo<ContextualGlyphHeader2> contextualGlyphHeader;
+
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstitution.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstitution.h Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -49,6 +49,11 @@
ByteOffset substitutionTableOffset;
};
+struct ContextualGlyphHeader2 : MorphStateTableHeader2
+{
+ le_uint32 perGlyphTableOffset; // no more substitution tables
+};
+
enum ContextualGlyphSubstitutionFlags
{
cgsSetMark = 0x8000,
@@ -62,5 +67,11 @@
WordOffset currOffset;
};
+struct ContextualGlyphStateEntry2 : StateEntry2
+{
+ le_uint16 markIndex;
+ le_uint16 currIndex;
+};
+
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/ContextualSubstSubtables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ContextualSubstSubtables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -217,7 +217,7 @@
}
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
- le_int32 coverageIndex = getGlyphCoverage(glyph);
+ le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
if (coverageIndex >= 0) {
le_uint16 srSetCount = SWAPW(subRuleSetCount);
@@ -266,7 +266,7 @@
}
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
- le_int32 coverageIndex = getGlyphCoverage(glyph);
+ le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
if (coverageIndex >= 0) {
const ClassDefinitionTable *classDefinitionTable =
@@ -394,7 +394,7 @@
}
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
- le_int32 coverageIndex = getGlyphCoverage(glyph);
+ le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
if (coverageIndex >= 0) {
le_uint16 srSetCount = SWAPW(chainSubRuleSetCount);
@@ -465,7 +465,7 @@
}
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
- le_int32 coverageIndex = getGlyphCoverage(glyph);
+ le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
if (coverageIndex >= 0) {
const ClassDefinitionTable *backtrackClassDefinitionTable =
--- a/jdk/src/share/native/sun/font/layout/ContextualSubstSubtables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ContextualSubstSubtables.h Wed Apr 17 02:53:02 2013 -0700
@@ -43,6 +43,7 @@
#include "GlyphSubstitutionTables.h"
#include "GlyphIterator.h"
#include "LookupProcessor.h"
+#include "LETableReference.h"
U_NAMESPACE_BEGIN
@@ -88,6 +89,8 @@
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
};
+LE_VAR_ARRAY(ContextualSubstitutionFormat1Subtable, subRuleSetTableOffsetArray)
+
struct SubRuleSetTable
{
@@ -95,6 +98,7 @@
Offset subRuleTableOffsetArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(SubRuleSetTable, subRuleTableOffsetArray)
// NOTE: Multiple variable size arrays!!
struct SubRuleTable
@@ -104,6 +108,7 @@
TTGlyphID inputGlyphArray[ANY_NUMBER];
//SubstitutionLookupRecord substLookupRecordArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(SubRuleTable, inputGlyphArray)
struct ContextualSubstitutionFormat2Subtable : ContextualSubstitutionSubtable
{
@@ -113,12 +118,16 @@
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
};
+LE_VAR_ARRAY(ContextualSubstitutionFormat2Subtable, subClassSetTableOffsetArray)
+
struct SubClassSetTable
{
le_uint16 subClassRuleCount;
Offset subClassRuleTableOffsetArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(SubClassSetTable, subClassRuleTableOffsetArray)
+
// NOTE: Multiple variable size arrays!!
struct SubClassRuleTable
@@ -128,6 +137,8 @@
le_uint16 classArray[ANY_NUMBER];
//SubstitutionLookupRecord substLookupRecordArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(SubClassRuleTable, classArray)
+
// NOTE: This isn't a subclass of GlyphSubstitutionSubtable 'cause
// it has an array of coverage tables instead of a single coverage table...
@@ -143,6 +154,7 @@
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
};
+LE_VAR_ARRAY(ContextualSubstitutionFormat3Subtable, coverageTableOffsetArray)
struct ChainingContextualSubstitutionSubtable : ContextualSubstitutionBase
{
@@ -156,6 +168,8 @@
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
};
+LE_VAR_ARRAY(ChainingContextualSubstitutionFormat1Subtable, chainSubRuleSetTableOffsetArray)
+
struct ChainSubRuleSetTable
{
@@ -163,6 +177,7 @@
Offset chainSubRuleTableOffsetArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(ChainSubRuleSetTable, chainSubRuleTableOffsetArray)
// NOTE: Multiple variable size arrays!!
struct ChainSubRuleTable
@@ -176,6 +191,7 @@
//le_uint16 substCount;
//SubstitutionLookupRecord substLookupRecordArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(ChainSubRuleTable, backtrackGlyphArray)
struct ChainingContextualSubstitutionFormat2Subtable : ChainingContextualSubstitutionSubtable
{
@@ -187,12 +203,15 @@
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
};
+LE_VAR_ARRAY(ChainingContextualSubstitutionFormat2Subtable, chainSubClassSetTableOffsetArray)
struct ChainSubClassSetTable
{
le_uint16 chainSubClassRuleCount;
Offset chainSubClassRuleTableOffsetArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(ChainSubClassSetTable, chainSubClassRuleTableOffsetArray)
+
// NOTE: Multiple variable size arrays!!
struct ChainSubClassRuleTable
@@ -206,6 +225,7 @@
//le_uint16 substCount;
//SubstitutionLookupRecord substLookupRecordArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(ChainSubClassRuleTable, backtrackClassArray)
// NOTE: This isn't a subclass of GlyphSubstitutionSubtable 'cause
// it has arrays of coverage tables instead of a single coverage table...
@@ -225,6 +245,8 @@
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
};
+LE_VAR_ARRAY(ChainingContextualSubstitutionFormat3Subtable, backtrackCoverageTableOffsetArray)
+
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/CoverageTables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/CoverageTables.h Wed Apr 17 02:53:02 2013 -0700
@@ -56,6 +56,8 @@
le_int32 getGlyphCoverage(LEGlyphID glyphID) const;
};
+LE_VAR_ARRAY(CoverageFormat1Table, glyphArray)
+
struct CoverageFormat2Table : CoverageTable
{
@@ -64,6 +66,7 @@
le_int32 getGlyphCoverage(LEGlyphID glyphID) const;
};
+LE_VAR_ARRAY(CoverageFormat2Table, rangeRecordArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/CursiveAttachmentSubtables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/CursiveAttachmentSubtables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -39,10 +39,10 @@
U_NAMESPACE_BEGIN
-le_uint32 CursiveAttachmentSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
+le_uint32 CursiveAttachmentSubtable::process(const LEReferenceTo<CursiveAttachmentSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
LEGlyphID glyphID = glyphIterator->getCurrGlyphID();
- le_int32 coverageIndex = getGlyphCoverage(glyphID);
+ le_int32 coverageIndex = getGlyphCoverage(base, glyphID, success);
le_uint16 eeCount = SWAPW(entryExitCount);
if (coverageIndex < 0 || coverageIndex >= eeCount) {
@@ -51,7 +51,7 @@
}
LEPoint entryAnchor, exitAnchor;
- Offset entryOffset = SWAPW(entryExitRecords[coverageIndex].entryAnchor);
+ Offset entryOffset = SWAPW(entryExitRecords[coverageIndex].entryAnchor); // TODO
Offset exitOffset = SWAPW(entryExitRecords[coverageIndex].exitAnchor);
if (entryOffset != 0) {
--- a/jdk/src/share/native/sun/font/layout/CursiveAttachmentSubtables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/CursiveAttachmentSubtables.h Wed Apr 17 02:53:02 2013 -0700
@@ -57,8 +57,9 @@
le_uint16 entryExitCount;
EntryExitRecord entryExitRecords[ANY_NUMBER];
- le_uint32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
+ le_uint32 process(const LEReferenceTo<CursiveAttachmentSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
};
+LE_VAR_ARRAY(CursiveAttachmentSubtable, entryExitRecords)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/DeviceTables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/DeviceTables.h Wed Apr 17 02:53:02 2013 -0700
@@ -57,6 +57,7 @@
static const le_uint16 fieldSignBits[];
static const le_uint16 fieldBits[];
};
+LE_VAR_ARRAY(DeviceTable, deltaValues)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/ExtensionSubtables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ExtensionSubtables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -47,6 +47,8 @@
le_uint32 ExtensionSubtable::process(const LookupProcessor *lookupProcessor, le_uint16 lookupType,
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const
{
+ const LEReferenceTo<ExtensionSubtable> thisRef(lookupProcessor->getReference(), success); // create a reference to this
+
if (LE_FAILURE(success)) {
return 0;
}
@@ -55,9 +57,11 @@
if (elt != lookupType) {
le_uint32 extOffset = READ_LONG(extensionOffset);
- LookupSubtable *subtable = (LookupSubtable *) ((char *) this + extOffset);
+ LEReferenceTo<LookupSubtable> subtable(thisRef, success, extOffset);
- return lookupProcessor->applySubtable(subtable, elt, glyphIterator, fontInstance, success);
+ if(LE_SUCCESS(success)) {
+ return lookupProcessor->applySubtable(subtable, elt, glyphIterator, fontInstance, success);
+ }
}
return 0;
--- a/jdk/src/share/native/sun/font/layout/Features.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/Features.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -38,19 +38,20 @@
U_NAMESPACE_BEGIN
-const FeatureTable *FeatureListTable::getFeatureTable(le_uint16 featureIndex, LETag *featureTag) const
+LEReferenceTo<FeatureTable> FeatureListTable::getFeatureTable(const LETableReference &base, le_uint16 featureIndex, LETag *featureTag, LEErrorCode &success) const
{
- if (featureIndex >= SWAPW(featureCount)) {
- return 0;
- }
+ if (featureIndex >= SWAPW(featureCount) || LE_FAILURE(success)) {
+ return LEReferenceTo<FeatureTable>();
+ }
Offset featureTableOffset = featureRecordArray[featureIndex].featureTableOffset;
*featureTag = SWAPT(featureRecordArray[featureIndex].featureTag);
- return (const FeatureTable *) ((char *) this + SWAPW(featureTableOffset));
+ return LEReferenceTo<FeatureTable>(base, success, SWAPW(featureTableOffset));
}
+#if 0
/*
* Note: according to the OpenType Spec. v 1.4, the entries in the Feature
* List Table are sorted alphabetically by feature tag; however, there seem
@@ -82,5 +83,6 @@
return 0;
#endif
}
+#endif
U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/GDEFMarkFilter.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GDEFMarkFilter.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -36,9 +36,12 @@
U_NAMESPACE_BEGIN
-GDEFMarkFilter::GDEFMarkFilter(const GlyphDefinitionTableHeader *gdefTable)
+GDEFMarkFilter::GDEFMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success)
+ : classDefTable(gdefTable->getGlyphClassDefinitionTable(gdefTable, success))
{
- classDefTable = gdefTable->getGlyphClassDefinitionTable();
+ if(!classDefTable.isValid()) {
+ success = LE_INTERNAL_ERROR;
+ }
}
GDEFMarkFilter::~GDEFMarkFilter()
--- a/jdk/src/share/native/sun/font/layout/GDEFMarkFilter.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GDEFMarkFilter.h Wed Apr 17 02:53:02 2013 -0700
@@ -46,13 +46,13 @@
class GDEFMarkFilter : public UMemory, public LEGlyphFilter
{
private:
- const GlyphClassDefinitionTable *classDefTable;
+ const LEReferenceTo<GlyphClassDefinitionTable> classDefTable;
GDEFMarkFilter(const GDEFMarkFilter &other); // forbid copying of this class
GDEFMarkFilter &operator=(const GDEFMarkFilter &other); // forbid copying of this class
public:
- GDEFMarkFilter(const GlyphDefinitionTableHeader *gdefTable);
+ GDEFMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success);
virtual ~GDEFMarkFilter();
virtual le_bool accept(LEGlyphID glyph) const;
--- a/jdk/src/share/native/sun/font/layout/GXLayoutEngine.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GXLayoutEngine.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -41,9 +41,10 @@
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(GXLayoutEngine)
-GXLayoutEngine::GXLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const MorphTableHeader *morphTable, LEErrorCode &success)
+ GXLayoutEngine::GXLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const LEReferenceTo<MorphTableHeader> &morphTable, LEErrorCode &success)
: LayoutEngine(fontInstance, scriptCode, languageCode, 0, success), fMorphTable(morphTable)
{
+ fMorphTable.orphan();
// nothing else to do?
}
@@ -70,7 +71,7 @@
return 0;
}
- fMorphTable->process(glyphStorage);
+ fMorphTable->process(fMorphTable, glyphStorage, success);
return count;
}
--- a/jdk/src/share/native/sun/font/layout/GXLayoutEngine.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GXLayoutEngine.h Wed Apr 17 02:53:02 2013 -0700
@@ -74,7 +74,7 @@
*
* @internal
*/
- GXLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const MorphTableHeader *morphTable, LEErrorCode &success);
+ GXLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const LEReferenceTo<MorphTableHeader> &morphTable, LEErrorCode &success);
/**
* The destructor, virtual for correct polymorphic invocation.
@@ -104,7 +104,7 @@
*
* @internal
*/
- const MorphTableHeader *fMorphTable;
+ LEReferenceTo<MorphTableHeader> fMorphTable;
/**
* This method does GX layout using the font's 'mort' table. It converts the
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/GXLayoutEngine2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "LayoutEngine.h"
+#include "GXLayoutEngine2.h"
+#include "LEGlyphStorage.h"
+#include "MorphTables.h"
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(GXLayoutEngine2)
+
+GXLayoutEngine2::GXLayoutEngine2(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const LEReferenceTo<MorphTableHeader2> &morphTable, le_int32 typoFlags, LEErrorCode &success)
+ : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fMorphTable(morphTable)
+{
+ // nothing else to do?
+}
+
+GXLayoutEngine2::~GXLayoutEngine2()
+{
+ reset();
+}
+
+// apply 'morx' table
+le_int32 GXLayoutEngine2::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, LEGlyphStorage &glyphStorage, LEErrorCode &success)
+{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
+ if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
+ success = LE_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+
+ mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphStorage, success);
+
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
+ fMorphTable->process(fMorphTable, glyphStorage, fTypoFlags, success);
+ return count;
+}
+
+// apply positional tables
+void GXLayoutEngine2::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool /*reverse*/,
+ LEGlyphStorage &/*glyphStorage*/, LEErrorCode &success)
+{
+ if (LE_FAILURE(success)) {
+ return;
+ }
+
+ if (chars == NULL || offset < 0 || count < 0) {
+ success = LE_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+
+ // FIXME: no positional processing yet...
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/GXLayoutEngine2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __GXLAYOUTENGINE2_H
+#define __GXLAYOUTENGINE2_H
+
+#include "LETypes.h"
+#include "LayoutEngine.h"
+
+#include "MorphTables.h"
+
+U_NAMESPACE_BEGIN
+
+class LEFontInstance;
+class LEGlyphStorage;
+
+/**
+ * This class implements layout for QuickDraw GX or Apple Advanced Typograyph (AAT)
+ * fonts. A font is a GX or AAT font if it contains a 'mort' table. See Apple's
+ * TrueType Reference Manual (http://fonts.apple.com/TTRefMan/index.html) for details.
+ * Information about 'mort' tables is in the chapter titled "Font Files."
+ *
+ * @internal
+ */
+class GXLayoutEngine2 : public LayoutEngine
+{
+public:
+ /**
+ * This is the main constructor. It constructs an instance of GXLayoutEngine for
+ * a particular font, script and language. It takes the 'mort' table as a parameter since
+ * LayoutEngine::layoutEngineFactory has to read the 'mort' table to know that it has a
+ * GX font.
+ *
+ * Note: GX and AAT fonts don't contain any script and language specific tables, so
+ * the script and language are ignored.
+ *
+ * @param fontInstance - the font
+ * @param scriptCode - the script
+ * @param langaugeCode - the language
+ * @param morphTable - the 'mort' table
+ * @param success - set to an error code if the operation fails
+ *
+ * @see LayoutEngine::layoutEngineFactory
+ * @see ScriptAndLangaugeTags.h for script and language codes
+ *
+ * @internal
+ */
+ GXLayoutEngine2(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const LEReferenceTo<MorphTableHeader2> &morphTable, le_int32 typoFlags, LEErrorCode &success);
+
+ /**
+ * The destructor, virtual for correct polymorphic invocation.
+ *
+ * @internal
+ */
+ virtual ~GXLayoutEngine2();
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for the actual class.
+ *
+ * @stable ICU 2.8
+ */
+ virtual UClassID getDynamicClassID() const;
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for this class.
+ *
+ * @stable ICU 2.8
+ */
+ static UClassID getStaticClassID();
+
+protected:
+
+ /**
+ * The address of the 'mort' table
+ *
+ * @internal
+ */
+ const LEReferenceTo<MorphTableHeader2> fMorphTable;
+
+ /**
+ * This method does GX layout using the font's 'mort' table. It converts the
+ * input character codes to glyph indices using mapCharsToGlyphs, and then
+ * applies the 'mort' table.
+ *
+ * Input parameters:
+ * @param chars - the input character context
+ * @param offset - the index of the first character to process
+ * @param count - the number of characters to process
+ * @param max - the number of characters in the input context
+ * @param rightToLeft - <code>TRUE</code> if the text is in a right to left directional run
+ * @param glyphStorage - the glyph storage object. The glyph and char index arrays will be set.
+ *
+ * Output parameters:
+ * @param success - set to an error code if the operation fails
+ *
+ * @return the number of glyphs in the glyph index array
+ *
+ * @internal
+ */
+ virtual le_int32 computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
+ LEGlyphStorage &glyphStorage, LEErrorCode &success);
+
+ /**
+ * This method adjusts the glyph positions using the font's
+ * 'kern', 'trak', 'bsln', 'opbd' and 'just' tables.
+ *
+ * Input parameters:
+ * @param glyphStorage - the object holding the glyph storage. The positions will be updated as needed.
+ *
+ * Output parameters:
+ * @param success - set to an error code if the operation fails
+ *
+ * @internal
+ */
+ virtual void adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
+ LEGlyphStorage &glyphStorage, LEErrorCode &success);
+
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/GlyphDefinitionTables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphDefinitionTables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -36,24 +36,36 @@
U_NAMESPACE_BEGIN
-const GlyphClassDefinitionTable *GlyphDefinitionTableHeader::getGlyphClassDefinitionTable() const
+const LEReferenceTo<GlyphClassDefinitionTable>
+GlyphDefinitionTableHeader::getGlyphClassDefinitionTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
+ LEErrorCode &success) const
{
- return (const GlyphClassDefinitionTable *) ((char *) this + SWAPW(glyphClassDefOffset));
+ if(LE_FAILURE(success)) return LEReferenceTo<GlyphClassDefinitionTable>();
+ return LEReferenceTo<GlyphClassDefinitionTable>(base, success, SWAPW(glyphClassDefOffset));
}
-const AttachmentListTable *GlyphDefinitionTableHeader::getAttachmentListTable() const
+const LEReferenceTo<AttachmentListTable>
+GlyphDefinitionTableHeader::getAttachmentListTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
+ LEErrorCode &success) const
{
- return (const AttachmentListTable *) ((char *) this + SWAPW(attachListOffset));
+ if(LE_FAILURE(success)) return LEReferenceTo<AttachmentListTable>();
+ return LEReferenceTo<AttachmentListTable>(base, success, SWAPW(attachListOffset));
}
-const LigatureCaretListTable *GlyphDefinitionTableHeader::getLigatureCaretListTable() const
+const LEReferenceTo<LigatureCaretListTable>
+GlyphDefinitionTableHeader::getLigatureCaretListTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
+ LEErrorCode &success) const
{
- return (const LigatureCaretListTable *) ((char *) this + SWAPW(ligCaretListOffset));
+ if(LE_FAILURE(success)) return LEReferenceTo<LigatureCaretListTable>();
+ return LEReferenceTo<LigatureCaretListTable>(base, success, SWAPW(ligCaretListOffset));
}
-const MarkAttachClassDefinitionTable *GlyphDefinitionTableHeader::getMarkAttachClassDefinitionTable() const
+const LEReferenceTo<MarkAttachClassDefinitionTable>
+GlyphDefinitionTableHeader::getMarkAttachClassDefinitionTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
+ LEErrorCode &success) const
{
- return (const MarkAttachClassDefinitionTable *) ((char *) this + SWAPW(MarkAttachClassDefOffset));
+ if(LE_FAILURE(success)) return LEReferenceTo<MarkAttachClassDefinitionTable>();
+ return LEReferenceTo<MarkAttachClassDefinitionTable>(base, success, SWAPW(MarkAttachClassDefOffset));
}
U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/GlyphDefinitionTables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphDefinitionTables.h Wed Apr 17 02:53:02 2013 -0700
@@ -60,12 +60,14 @@
le_uint16 glyphCount;
Offset attachPointTableOffsetArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(AttachmentListTable, attachPointTableOffsetArray)
struct AttachPointTable
{
le_uint16 pointCount;
le_uint16 pointIndexArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(AttachPointTable, pointIndexArray)
struct LigatureCaretListTable
{
@@ -73,12 +75,14 @@
le_uint16 ligGlyphCount;
Offset ligGlyphTableOffsetArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(LigatureCaretListTable, ligGlyphTableOffsetArray)
struct LigatureGlyphTable
{
le_uint16 caretCount;
Offset caretValueTableOffsetArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(LigatureGlyphTable, caretValueTableOffsetArray)
struct CaretValueTable
{
@@ -111,10 +115,18 @@
Offset ligCaretListOffset;
Offset MarkAttachClassDefOffset;
- const GlyphClassDefinitionTable *getGlyphClassDefinitionTable() const;
- const AttachmentListTable *getAttachmentListTable()const ;
- const LigatureCaretListTable *getLigatureCaretListTable() const;
- const MarkAttachClassDefinitionTable *getMarkAttachClassDefinitionTable() const;
+ const LEReferenceTo<GlyphClassDefinitionTable>
+ getGlyphClassDefinitionTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
+ LEErrorCode &success) const;
+ const LEReferenceTo<AttachmentListTable>
+ getAttachmentListTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
+ LEErrorCode &success)const ;
+ const LEReferenceTo<LigatureCaretListTable>
+ getLigatureCaretListTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
+ LEErrorCode &success) const;
+ const LEReferenceTo<MarkAttachClassDefinitionTable>
+ getMarkAttachClassDefinitionTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
+ LEErrorCode &success) const;
};
U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/GlyphIterator.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphIterator.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -41,18 +41,21 @@
U_NAMESPACE_BEGIN
GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
- FeatureMask theFeatureMask, const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader)
+ FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader)
: direction(1), position(-1), nextLimit(-1), prevLimit(-1),
glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask), glyphGroup(0),
- glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL)
+ glyphClassDefinitionTable(), markAttachClassDefinitionTable()
{
+ LEErrorCode success = LE_NO_ERROR; // TODO
le_int32 glyphCount = glyphStorage.getGlyphCount();
- if (theGlyphDefinitionTableHeader != NULL) {
- glyphClassDefinitionTable = theGlyphDefinitionTableHeader->getGlyphClassDefinitionTable();
- markAttachClassDefinitionTable = theGlyphDefinitionTableHeader->getMarkAttachClassDefinitionTable();
+ if (theGlyphDefinitionTableHeader.isValid()) {
+ glyphClassDefinitionTable = theGlyphDefinitionTableHeader
+ -> getGlyphClassDefinitionTable(theGlyphDefinitionTableHeader, success);
+ markAttachClassDefinitionTable = theGlyphDefinitionTableHeader
+ ->getMarkAttachClassDefinitionTable(theGlyphDefinitionTableHeader, success);
}
nextLimit = glyphCount;
@@ -380,6 +383,7 @@
le_bool GlyphIterator::filterGlyph(le_uint32 index) const
{
+ LEErrorCode success = LE_NO_ERROR;
LEGlyphID glyphID = glyphStorage[index];
le_int32 glyphClass = gcdNoGlyphClass;
@@ -387,8 +391,8 @@
return TRUE;
}
- if (glyphClassDefinitionTable != NULL) {
- glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphID);
+ if (glyphClassDefinitionTable.isValid()) {
+ glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphClassDefinitionTable, glyphID, success);
}
switch (glyphClass)
@@ -410,8 +414,9 @@
le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
- if ((markAttachType != 0) && (markAttachClassDefinitionTable != NULL)) {
- return markAttachClassDefinitionTable->getGlyphClass(glyphID) != markAttachType;
+ if ((markAttachType != 0) && (markAttachClassDefinitionTable.isValid())) {
+ return markAttachClassDefinitionTable
+ -> getGlyphClass(markAttachClassDefinitionTable, glyphID, success) != markAttachType;
}
return FALSE;
@@ -461,6 +466,7 @@
while (newPosition != nextLimit && delta > 0) {
do {
newPosition += direction;
+ //fprintf(stderr,"%s:%d:%s: newPosition = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, newPosition, delta);
} while (newPosition != nextLimit && filterGlyph(newPosition));
delta -= 1;
@@ -468,6 +474,7 @@
position = newPosition;
+ //fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
return position != nextLimit;
}
@@ -483,6 +490,7 @@
while (newPosition != prevLimit && delta > 0) {
do {
newPosition -= direction;
+ //fprintf(stderr,"%s:%d:%s: newPosition = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, newPosition, delta);
} while (newPosition != prevLimit && filterGlyph(newPosition));
delta -= 1;
@@ -490,6 +498,7 @@
position = newPosition;
+ //fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
return position != prevLimit;
}
--- a/jdk/src/share/native/sun/font/layout/GlyphIterator.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphIterator.h Wed Apr 17 02:53:02 2013 -0700
@@ -49,7 +49,7 @@
class GlyphIterator : public UMemory {
public:
GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
- FeatureMask theFeatureMask, const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader);
+ FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader);
GlyphIterator(GlyphIterator &that);
@@ -117,8 +117,8 @@
FeatureMask featureMask;
le_int32 glyphGroup;
- const GlyphClassDefinitionTable *glyphClassDefinitionTable;
- const MarkAttachClassDefinitionTable *markAttachClassDefinitionTable;
+ LEReferenceTo<GlyphClassDefinitionTable> glyphClassDefinitionTable;
+ LEReferenceTo<MarkAttachClassDefinitionTable> markAttachClassDefinitionTable;
GlyphIterator &operator=(const GlyphIterator &other); // forbid copying of this class
};
--- a/jdk/src/share/native/sun/font/layout/GlyphLookupTables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphLookupTables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -37,21 +37,22 @@
U_NAMESPACE_BEGIN
-le_bool GlyphLookupTableHeader::coversScript(LETag scriptTag) const
+le_bool GlyphLookupTableHeader::coversScript(const LETableReference &base, LETag scriptTag, LEErrorCode &success) const
{
- const ScriptListTable *scriptListTable = (const ScriptListTable *) ((char *)this + SWAPW(scriptListOffset));
+ LEReferenceTo<ScriptListTable> scriptListTable(base, success, SWAPW(scriptListOffset));
- return scriptListOffset != 0 && scriptListTable->findScript(scriptTag) != NULL;
+ return (scriptListOffset != 0) && scriptListTable->findScript(scriptListTable, scriptTag, success) .isValid();
}
-le_bool GlyphLookupTableHeader::coversScriptAndLanguage(LETag scriptTag, LETag languageTag, le_bool exactMatch) const
+le_bool GlyphLookupTableHeader::coversScriptAndLanguage(const LETableReference &base, LETag scriptTag, LETag languageTag, LEErrorCode &success, le_bool exactMatch) const
{
- const ScriptListTable *scriptListTable = (const ScriptListTable *) ((char *)this + SWAPW(scriptListOffset));
- const LangSysTable *langSysTable = scriptListTable->findLanguage(scriptTag, languageTag, exactMatch);
+ LEReferenceTo<ScriptListTable> scriptListTable(base, success, SWAPW(scriptListOffset));
+ LEReferenceTo<LangSysTable> langSysTable = scriptListTable->findLanguage(scriptListTable,
+ scriptTag, languageTag, success, exactMatch);
// FIXME: could check featureListOffset, lookupListOffset, and lookup count...
// Note: don't have to SWAPW langSysTable->featureCount to check for non-zero.
- return langSysTable != NULL && langSysTable->featureCount != 0;
+ return LE_SUCCESS(success)&&langSysTable.isValid() && langSysTable->featureCount != 0;
}
U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/GlyphLookupTables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphLookupTables.h Wed Apr 17 02:53:02 2013 -0700
@@ -49,8 +49,8 @@
Offset featureListOffset;
Offset lookupListOffset;
- le_bool coversScript(LETag scriptTag) const;
- le_bool coversScriptAndLanguage(LETag scriptTag, LETag languageTag, le_bool exactMatch = FALSE) const;
+ le_bool coversScript(const LETableReference &base, LETag scriptTag, LEErrorCode &success) const;
+ le_bool coversScriptAndLanguage(const LETableReference &base, LETag scriptTag, LETag languageTag, LEErrorCode &success, le_bool exactMatch = FALSE) const;
};
U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/GlyphPositioningTables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphPositioningTables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -41,16 +41,16 @@
U_NAMESPACE_BEGIN
-void GlyphPositioningTableHeader::process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments, le_bool rightToLeft,
+void GlyphPositioningTableHeader::process(const LEReferenceTo<GlyphPositioningTableHeader> &base, LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments, le_bool rightToLeft,
LETag scriptTag, LETag languageTag,
- const GlyphDefinitionTableHeader *glyphDefinitionTableHeader, LEErrorCode &success,
+ const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader, LEErrorCode &success,
const LEFontInstance *fontInstance, const FeatureMap *featureMap, le_int32 featureMapCount, le_bool featureOrder) const
{
if (LE_FAILURE(success)) {
return;
}
- GlyphPositioningLookupProcessor processor(this, scriptTag, languageTag, featureMap, featureMapCount, featureOrder, success);
+ GlyphPositioningLookupProcessor processor(base, scriptTag, languageTag, featureMap, featureMapCount, featureOrder, success);
if (LE_FAILURE(success)) {
return;
}
--- a/jdk/src/share/native/sun/font/layout/GlyphPositioningTables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphPositioningTables.h Wed Apr 17 02:53:02 2013 -0700
@@ -40,6 +40,7 @@
#include "OpenTypeTables.h"
#include "Lookups.h"
#include "GlyphLookupTables.h"
+#include "LETableReference.h"
U_NAMESPACE_BEGIN
@@ -51,9 +52,9 @@
struct GlyphPositioningTableHeader : public GlyphLookupTableHeader
{
- void process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments,
+ void process(const LEReferenceTo<GlyphPositioningTableHeader> &base, LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments,
le_bool rightToLeft, LETag scriptTag, LETag languageTag,
- const GlyphDefinitionTableHeader *glyphDefinitionTableHeader, LEErrorCode &success,
+ const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader, LEErrorCode &success,
const LEFontInstance *fontInstance, const FeatureMap *featureMap, le_int32 featureMapCount, le_bool featureOrder) const;
};
--- a/jdk/src/share/native/sun/font/layout/GlyphPosnLookupProc.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphPosnLookupProc.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -57,7 +57,7 @@
typedef ChainingContextualSubstitutionSubtable ChainingContextualPositioningSubtable;
GlyphPositioningLookupProcessor::GlyphPositioningLookupProcessor(
- const GlyphPositioningTableHeader *glyphPositioningTableHeader,
+ const LEReferenceTo<GlyphPositioningTableHeader> &glyphPositioningTableHeader,
LETag scriptTag,
LETag languageTag,
const FeatureMap *featureMap,
@@ -65,7 +65,7 @@
le_bool featureOrder,
LEErrorCode& success)
: LookupProcessor(
- (char *) glyphPositioningTableHeader,
+ glyphPositioningTableHeader,
SWAPW(glyphPositioningTableHeader->scriptListOffset),
SWAPW(glyphPositioningTableHeader->featureListOffset),
SWAPW(glyphPositioningTableHeader->lookupListOffset),
@@ -84,7 +84,7 @@
{
}
-le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LookupSubtable *lookupSubtable, le_uint16 lookupType,
+le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LEReferenceTo<LookupSubtable> &lookupSubtable, le_uint16 lookupType,
GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance,
LEErrorCode& success) const
@@ -102,55 +102,55 @@
case gpstSingle:
{
- const SinglePositioningSubtable *subtable = (const SinglePositioningSubtable *) lookupSubtable;
+ LEReferenceTo<SinglePositioningSubtable> subtable(lookupSubtable, success);
- delta = subtable->process(glyphIterator, fontInstance);
+ delta = subtable->process(subtable, glyphIterator, fontInstance, success);
break;
}
case gpstPair:
{
- const PairPositioningSubtable *subtable = (const PairPositioningSubtable *) lookupSubtable;
+ LEReferenceTo<PairPositioningSubtable> subtable(lookupSubtable, success);
- delta = subtable->process(glyphIterator, fontInstance);
+ delta = subtable->process(subtable, glyphIterator, fontInstance, success);
break;
}
case gpstCursive:
{
- const CursiveAttachmentSubtable *subtable = (const CursiveAttachmentSubtable *) lookupSubtable;
+ LEReferenceTo<CursiveAttachmentSubtable> subtable(lookupSubtable, success);
- delta = subtable->process(glyphIterator, fontInstance);
+ delta = subtable->process(subtable, glyphIterator, fontInstance, success);
break;
}
case gpstMarkToBase:
{
- const MarkToBasePositioningSubtable *subtable = (const MarkToBasePositioningSubtable *) lookupSubtable;
+ LEReferenceTo<MarkToBasePositioningSubtable> subtable(lookupSubtable, success);
- delta = subtable->process(glyphIterator, fontInstance);
+ delta = subtable->process(subtable, glyphIterator, fontInstance, success);
break;
}
case gpstMarkToLigature:
{
- const MarkToLigaturePositioningSubtable *subtable = (const MarkToLigaturePositioningSubtable *) lookupSubtable;
+ LEReferenceTo<MarkToLigaturePositioningSubtable> subtable(lookupSubtable, success);
- delta = subtable->process(glyphIterator, fontInstance);
+ delta = subtable->process(subtable, glyphIterator, fontInstance, success);
break;
}
case gpstMarkToMark:
{
- const MarkToMarkPositioningSubtable *subtable = (const MarkToMarkPositioningSubtable *) lookupSubtable;
+ LEReferenceTo<MarkToMarkPositioningSubtable> subtable(lookupSubtable, success);
- delta = subtable->process(glyphIterator, fontInstance);
+ delta = subtable->process(subtable, glyphIterator, fontInstance, success);
break;
}
case gpstContext:
{
- const ContextualPositioningSubtable *subtable = (const ContextualPositioningSubtable *) lookupSubtable;
+ LEReferenceTo<ContextualPositioningSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, glyphIterator, fontInstance, success);
break;
@@ -158,7 +158,7 @@
case gpstChainedContext:
{
- const ChainingContextualPositioningSubtable *subtable = (const ChainingContextualPositioningSubtable *) lookupSubtable;
+ LEReferenceTo<ChainingContextualPositioningSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, glyphIterator, fontInstance, success);
break;
@@ -166,7 +166,7 @@
case gpstExtension:
{
- const ExtensionSubtable *subtable = (const ExtensionSubtable *) lookupSubtable;
+ LEReferenceTo<ExtensionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, lookupType, glyphIterator, fontInstance, success);
break;
--- a/jdk/src/share/native/sun/font/layout/GlyphPosnLookupProc.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphPosnLookupProc.h Wed Apr 17 02:53:02 2013 -0700
@@ -51,7 +51,7 @@
class GlyphPositioningLookupProcessor : public LookupProcessor
{
public:
- GlyphPositioningLookupProcessor(const GlyphPositioningTableHeader *glyphPositioningTableHeader,
+ GlyphPositioningLookupProcessor(const LEReferenceTo<GlyphPositioningTableHeader> &glyphPositioningTableHeader,
LETag scriptTag,
LETag languageTag,
const FeatureMap *featureMap,
@@ -61,7 +61,7 @@
virtual ~GlyphPositioningLookupProcessor();
- virtual le_uint32 applySubtable(const LookupSubtable *lookupSubtable, le_uint16 lookupType, GlyphIterator *glyphIterator,
+ virtual le_uint32 applySubtable(const LEReferenceTo<LookupSubtable> &lookupSubtable, le_uint16 lookupType, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, LEErrorCode& success) const;
protected:
--- a/jdk/src/share/native/sun/font/layout/GlyphSubstLookupProc.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphSubstLookupProc.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -51,7 +51,7 @@
U_NAMESPACE_BEGIN
GlyphSubstitutionLookupProcessor::GlyphSubstitutionLookupProcessor(
- const GlyphSubstitutionTableHeader *glyphSubstitutionTableHeader,
+ const LEReferenceTo<GlyphSubstitutionTableHeader> &glyphSubstitutionTableHeader,
LETag scriptTag,
LETag languageTag,
const LEGlyphFilter *filter,
@@ -60,7 +60,7 @@
le_bool featureOrder,
LEErrorCode& success)
: LookupProcessor(
- (char *) glyphSubstitutionTableHeader,
+ glyphSubstitutionTableHeader,
SWAPW(glyphSubstitutionTableHeader->scriptListOffset),
SWAPW(glyphSubstitutionTableHeader->featureListOffset),
SWAPW(glyphSubstitutionTableHeader->lookupListOffset),
@@ -73,7 +73,7 @@
{
}
-le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LookupSubtable *lookupSubtable, le_uint16 lookupType,
+le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LEReferenceTo<LookupSubtable> &lookupSubtable, le_uint16 lookupType,
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const
{
if (LE_FAILURE(success)) {
@@ -89,39 +89,39 @@
case gsstSingle:
{
- const SingleSubstitutionSubtable *subtable = (const SingleSubstitutionSubtable *) lookupSubtable;
+ const LEReferenceTo<SingleSubstitutionSubtable> subtable(lookupSubtable, success);
- delta = subtable->process(glyphIterator, fFilter);
+ delta = subtable->process(subtable, glyphIterator, success, fFilter);
break;
}
case gsstMultiple:
{
- const MultipleSubstitutionSubtable *subtable = (const MultipleSubstitutionSubtable *) lookupSubtable;
+ const LEReferenceTo<MultipleSubstitutionSubtable> subtable(lookupSubtable, success);
- delta = subtable->process(glyphIterator, success, fFilter);
+ delta = subtable->process(subtable, glyphIterator, success, fFilter);
break;
}
case gsstAlternate:
{
- const AlternateSubstitutionSubtable *subtable = (const AlternateSubstitutionSubtable *) lookupSubtable;
+ const LEReferenceTo<AlternateSubstitutionSubtable> subtable(lookupSubtable, success);
- delta = subtable->process(glyphIterator, fFilter);
+ delta = subtable->process(subtable, glyphIterator, success, fFilter);
break;
}
case gsstLigature:
{
- const LigatureSubstitutionSubtable *subtable = (const LigatureSubstitutionSubtable *) lookupSubtable;
+ const LEReferenceTo<LigatureSubstitutionSubtable> subtable(lookupSubtable, success);
- delta = subtable->process(glyphIterator, fFilter);
+ delta = subtable->process(subtable, glyphIterator, success, fFilter);
break;
}
case gsstContext:
{
- const ContextualSubstitutionSubtable *subtable = (const ContextualSubstitutionSubtable *) lookupSubtable;
+ const LEReferenceTo<ContextualSubstitutionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, glyphIterator, fontInstance, success);
break;
@@ -129,7 +129,7 @@
case gsstChainingContext:
{
- const ChainingContextualSubstitutionSubtable *subtable = (const ChainingContextualSubstitutionSubtable *) lookupSubtable;
+ const LEReferenceTo<ChainingContextualSubstitutionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, glyphIterator, fontInstance, success);
break;
@@ -137,7 +137,7 @@
case gsstExtension:
{
- const ExtensionSubtable *subtable = (const ExtensionSubtable *) lookupSubtable;
+ const LEReferenceTo<ExtensionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, lookupType, glyphIterator, fontInstance, success);
break;
--- a/jdk/src/share/native/sun/font/layout/GlyphSubstLookupProc.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphSubstLookupProc.h Wed Apr 17 02:53:02 2013 -0700
@@ -52,7 +52,7 @@
class GlyphSubstitutionLookupProcessor : public LookupProcessor
{
public:
- GlyphSubstitutionLookupProcessor(const GlyphSubstitutionTableHeader *glyphSubstitutionTableHeader,
+ GlyphSubstitutionLookupProcessor(const LEReferenceTo<GlyphSubstitutionTableHeader> &glyphSubstitutionTableHeader,
LETag scriptTag,
LETag languageTag,
const LEGlyphFilter *filter,
@@ -63,7 +63,7 @@
virtual ~GlyphSubstitutionLookupProcessor();
- virtual le_uint32 applySubtable(const LookupSubtable *lookupSubtable, le_uint16 lookupType, GlyphIterator *glyphIterator,
+ virtual le_uint32 applySubtable(const LEReferenceTo<LookupSubtable> &lookupSubtable, le_uint16 lookupType, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, LEErrorCode& success) const;
protected:
--- a/jdk/src/share/native/sun/font/layout/GlyphSubstitutionTables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphSubstitutionTables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -42,11 +42,12 @@
U_NAMESPACE_BEGIN
-le_int32 GlyphSubstitutionTableHeader::process(LEGlyphStorage &glyphStorage,
+le_int32 GlyphSubstitutionTableHeader::process(const LEReferenceTo<GlyphSubstitutionTableHeader> &base,
+ LEGlyphStorage &glyphStorage,
le_bool rightToLeft,
LETag scriptTag,
LETag languageTag,
- const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
+ const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader,
const LEGlyphFilter *filter,
const FeatureMap *featureMap,
le_int32 featureMapCount,
@@ -57,7 +58,7 @@
return 0;
}
- GlyphSubstitutionLookupProcessor processor(this, scriptTag, languageTag, filter, featureMap, featureMapCount, featureOrder, success);
+ GlyphSubstitutionLookupProcessor processor(base, scriptTag, languageTag, filter, featureMap, featureMapCount, featureOrder, success);
return processor.process(glyphStorage, NULL, rightToLeft, glyphDefinitionTableHeader, NULL, success);
}
--- a/jdk/src/share/native/sun/font/layout/GlyphSubstitutionTables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/GlyphSubstitutionTables.h Wed Apr 17 02:53:02 2013 -0700
@@ -50,11 +50,12 @@
struct GlyphSubstitutionTableHeader : public GlyphLookupTableHeader
{
- le_int32 process(LEGlyphStorage &glyphStorage,
+ le_int32 process(const LEReferenceTo<GlyphSubstitutionTableHeader> &base,
+ LEGlyphStorage &glyphStorage,
le_bool rightToLeft,
LETag scriptTag,
LETag languageTag,
- const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
+ const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader,
const LEGlyphFilter *filter,
const FeatureMap *featureMap,
le_int32 featureMapCount,
--- a/jdk/src/share/native/sun/font/layout/HanLayoutEngine.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/HanLayoutEngine.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -64,7 +64,7 @@
#define features (loclFeatureMask)
HanOpenTypeLayoutEngine::HanOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
+ le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
{
fFeatureMap = featureMap;
--- a/jdk/src/share/native/sun/font/layout/HanLayoutEngine.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/HanLayoutEngine.h Wed Apr 17 02:53:02 2013 -0700
@@ -73,7 +73,7 @@
* @internal
*/
HanOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTablem, LEErrorCode &success);
+ le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTablem, LEErrorCode &success);
/**
--- a/jdk/src/share/native/sun/font/layout/HangulLayoutEngine.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/HangulLayoutEngine.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -209,7 +209,7 @@
}
HangulOpenTypeLayoutEngine::HangulOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 /*languageCode*/,
- le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
+ le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, korLanguageCode, typoFlags, gsubTable, success)
{
fFeatureMap = featureMap;
--- a/jdk/src/share/native/sun/font/layout/HangulLayoutEngine.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/HangulLayoutEngine.h Wed Apr 17 02:53:02 2013 -0700
@@ -79,7 +79,7 @@
* @internal
*/
HangulOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success);
+ le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success);
/**
* This constructor is used when the font requires a "canned" GSUB table which can't be known
--- a/jdk/src/share/native/sun/font/layout/ICUFeatures.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ICUFeatures.h Wed Apr 17 02:53:02 2013 -0700
@@ -54,16 +54,21 @@
le_uint16 lookupCount;
le_uint16 lookupListIndexArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(FeatureTable, lookupListIndexArray)
struct FeatureListTable
{
le_uint16 featureCount;
FeatureRecord featureRecordArray[ANY_NUMBER];
- const FeatureTable *getFeatureTable(le_uint16 featureIndex, LETag *featureTag) const;
+ LEReferenceTo<FeatureTable> getFeatureTable(const LETableReference &base, le_uint16 featureIndex, LETag *featureTag, LEErrorCode &success) const;
- const FeatureTable *getFeatureTable(LETag featureTag) const;
+#if 0
+ const LEReferenceTo<FeatureTable> getFeatureTable(const LETableReference &base, LETag featureTag, LEErrorCode &success) const;
+#endif
};
+LE_VAR_ARRAY(FeatureListTable, featureRecordArray)
+
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/IndicClassTables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/IndicClassTables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2010 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -186,13 +186,15 @@
};
// FIXME: Should some of the bb's be pb's? (KA, NA, MA, YA, VA, etc. (approx 13))
+// U+C43 and U+C44 are _lm here not _dr. Similar to the situation with U+CC3 and
+// U+CC4 in Kannada below.
static const IndicClassTable::CharClass teluCharClasses[] =
{
_xx, _mp, _mp, _mp, _xx, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _iv, _xx, _iv, _iv, // 0C00 - 0C0F
_iv, _xx, _iv, _iv, _iv, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, // 0C10 - 0C1F
_bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _bb, _xx, _bb, _bb, _bb, _bb, _bb, _bb, // 0C20 - 0C2F
_bb, _bb, _bb, _bb, _xx, _bb, _bb, _bb, _bb, _bb, _xx, _xx, _xx, _xx, _da, _da, // 0C30 - 0C3F
- _da, _dr, _dr, _dr, _dr, _xx, _a1, _da, _s1, _xx, _da, _da, _da, _vr, _xx, _xx, // 0C40 - 0C4F
+ _da, _dr, _dr, _lm, _lm, _xx, _a1, _da, _s1, _xx, _da, _da, _da, _vr, _xx, _xx, // 0C40 - 0C4F
_xx, _xx, _xx, _xx, _xx, _da, _m2, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, // 0C50 - 0C5F
_iv, _iv, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx // 0C60 - 0C6F
};
--- a/jdk/src/share/native/sun/font/layout/IndicLayoutEngine.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/IndicLayoutEngine.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -50,7 +50,7 @@
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicOpenTypeLayoutEngine)
IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, le_bool version2, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
+ le_int32 typoFlags, le_bool version2, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success), fMPreFixups(NULL)
{
if ( version2 ) {
--- a/jdk/src/share/native/sun/font/layout/IndicLayoutEngine.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/IndicLayoutEngine.h Wed Apr 17 02:53:02 2013 -0700
@@ -81,7 +81,7 @@
* @internal
*/
IndicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, le_bool version2, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success);
+ le_int32 typoFlags, le_bool version2, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success);
/**
* This constructor is used when the font requires a "canned" GSUB table which can't be known
--- a/jdk/src/share/native/sun/font/layout/IndicRearrangement.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/IndicRearrangement.h Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -49,6 +49,10 @@
{
};
+struct IndicRearrangementSubtableHeader2 : MorphStateTableHeader2
+{
+};
+
enum IndicRearrangementFlags
{
irfMarkFirst = 0x8000,
@@ -85,6 +89,10 @@
{
};
+struct IndicRearrangementStateEntry2 : StateEntry2
+{
+};
+
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/IndicRearrangementProcessor.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/IndicRearrangementProcessor.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -43,11 +43,14 @@
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicRearrangementProcessor)
-IndicRearrangementProcessor::IndicRearrangementProcessor(const MorphSubtableHeader *morphSubtableHeader)
- : StateTableProcessor(morphSubtableHeader)
+ IndicRearrangementProcessor::IndicRearrangementProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
+ : StateTableProcessor(morphSubtableHeader, success),
+ indicRearrangementSubtableHeader(morphSubtableHeader, success),
+ entryTable(stateTableHeader, success, (const IndicRearrangementStateEntry*)(&stateTableHeader->stHeader),
+ entryTableOffset, LE_UNBOUNDED_ARRAY),
+ int16Table(stateTableHeader, success, (const le_int16*)entryTable.getAlias(), 0, LE_UNBOUNDED_ARRAY)
+
{
- indicRearrangementSubtableHeader = (const IndicRearrangementSubtableHeader *) morphSubtableHeader;
- entryTable = (const IndicRearrangementStateEntry *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
}
IndicRearrangementProcessor::~IndicRearrangementProcessor()
@@ -62,7 +65,8 @@
ByteOffset IndicRearrangementProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index)
{
- const IndicRearrangementStateEntry *entry = &entryTable[index];
+ LEErrorCode success = LE_NO_ERROR; // todo- make a param?
+ const IndicRearrangementStateEntry *entry = entryTable.getAlias(index,success);
ByteOffset newState = SWAPW(entry->newStateOffset);
IndicRearrangementFlags flags = (IndicRearrangementFlags) SWAPW(entry->flags);
--- a/jdk/src/share/native/sun/font/layout/IndicRearrangementProcessor.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/IndicRearrangementProcessor.h Wed Apr 17 02:53:02 2013 -0700
@@ -58,7 +58,7 @@
void doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb) const;
- IndicRearrangementProcessor(const MorphSubtableHeader *morphSubtableHeader);
+ IndicRearrangementProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~IndicRearrangementProcessor();
/**
@@ -79,8 +79,9 @@
le_int32 firstGlyph;
le_int32 lastGlyph;
- const IndicRearrangementStateEntry *entryTable;
- const IndicRearrangementSubtableHeader *indicRearrangementSubtableHeader;
+ LEReferenceTo<IndicRearrangementSubtableHeader> indicRearrangementSubtableHeader;
+ LEReferenceToArrayOf<IndicRearrangementStateEntry> entryTable;
+ LEReferenceToArrayOf<le_int16> int16Table;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/IndicRearrangementProcessor2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,425 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "StateTables.h"
+#include "MorphStateTables.h"
+#include "SubtableProcessor2.h"
+#include "StateTableProcessor2.h"
+#include "IndicRearrangementProcessor2.h"
+#include "LEGlyphStorage.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicRearrangementProcessor2)
+
+IndicRearrangementProcessor2::IndicRearrangementProcessor2(
+ const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+ : StateTableProcessor2(morphSubtableHeader, success), indicRearrangementSubtableHeader(morphSubtableHeader, success),
+ entryTable(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY)
+{
+}
+
+IndicRearrangementProcessor2::~IndicRearrangementProcessor2()
+{
+}
+
+void IndicRearrangementProcessor2::beginStateTable()
+{
+ firstGlyph = 0;
+ lastGlyph = 0;
+}
+
+le_uint16 IndicRearrangementProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
+ EntryTableIndex2 index, LEErrorCode &success)
+{
+ const IndicRearrangementStateEntry2 *entry = entryTable.getAlias(index, success);
+ if (LE_FAILURE(success)) return 0; // TODO - what to return in bad state?
+ le_uint16 newState = SWAPW(entry->newStateIndex); // index to the new state
+ IndicRearrangementFlags flags = (IndicRearrangementFlags) SWAPW(entry->flags);
+
+ if (flags & irfMarkFirst) {
+ firstGlyph = currGlyph;
+ }
+
+ if (flags & irfMarkLast) {
+ lastGlyph = currGlyph;
+ }
+
+ doRearrangementAction(glyphStorage, (IndicRearrangementVerb) (flags & irfVerbMask));
+
+ if (!(flags & irfDontAdvance)) {
+ currGlyph += dir;
+ }
+
+ return newState; // index to new state
+}
+
+void IndicRearrangementProcessor2::endStateTable()
+{
+}
+
+void IndicRearrangementProcessor2::doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb) const
+{
+ LEGlyphID a, b, c, d;
+ le_int32 ia, ib, ic, id, ix, x;
+ LEErrorCode success = LE_NO_ERROR;
+
+ switch(verb)
+ {
+ case irvNoAction:
+ break;
+
+ case irvxA:
+ a = glyphStorage[firstGlyph];
+ ia = glyphStorage.getCharIndex(firstGlyph, success);
+ x = firstGlyph + 1;
+
+ while (x <= lastGlyph) {
+ glyphStorage[x - 1] = glyphStorage[x];
+ ix = glyphStorage.getCharIndex(x, success);
+ glyphStorage.setCharIndex(x - 1, ix, success);
+ x += 1;
+ }
+
+ glyphStorage[lastGlyph] = a;
+ glyphStorage.setCharIndex(lastGlyph, ia, success);
+ break;
+
+ case irvDx:
+ d = glyphStorage[lastGlyph];
+ id = glyphStorage.getCharIndex(lastGlyph, success);
+ x = lastGlyph - 1;
+
+ while (x >= firstGlyph) {
+ glyphStorage[x + 1] = glyphStorage[x];
+ ix = glyphStorage.getCharIndex(x, success);
+ glyphStorage.setCharIndex(x + 1, ix, success);
+ x -= 1;
+ }
+
+ glyphStorage[firstGlyph] = d;
+ glyphStorage.setCharIndex(firstGlyph, id, success);
+ break;
+
+ case irvDxA:
+ a = glyphStorage[firstGlyph];
+ ia = glyphStorage.getCharIndex(firstGlyph, success);
+ id = glyphStorage.getCharIndex(lastGlyph, success);
+
+ glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
+ glyphStorage[lastGlyph] = a;
+
+ glyphStorage.setCharIndex(firstGlyph, id, success);
+ glyphStorage.setCharIndex(lastGlyph, ia, success);
+ break;
+
+ case irvxAB:
+ a = glyphStorage[firstGlyph];
+ b = glyphStorage[firstGlyph + 1];
+ ia = glyphStorage.getCharIndex(firstGlyph, success);
+ ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
+ x = firstGlyph + 2;
+
+ while (x <= lastGlyph) {
+ glyphStorage[x - 2] = glyphStorage[x];
+ ix = glyphStorage.getCharIndex(x, success);
+ glyphStorage.setCharIndex(x - 2, ix, success);
+ x += 1;
+ }
+
+ glyphStorage[lastGlyph - 1] = a;
+ glyphStorage[lastGlyph] = b;
+
+ glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
+ glyphStorage.setCharIndex(lastGlyph, ib, success);
+ break;
+
+ case irvxBA:
+ a = glyphStorage[firstGlyph];
+ b = glyphStorage[firstGlyph + 1];
+ ia = glyphStorage.getCharIndex(firstGlyph, success);
+ ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
+ x = firstGlyph + 2;
+
+ while (x <= lastGlyph) {
+ glyphStorage[x - 2] = glyphStorage[x];
+ ix = glyphStorage.getCharIndex(x, success);
+ glyphStorage.setCharIndex(x - 2, ix, success);
+ x += 1;
+ }
+
+ glyphStorage[lastGlyph - 1] = b;
+ glyphStorage[lastGlyph] = a;
+
+ glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
+ glyphStorage.setCharIndex(lastGlyph, ia, success);
+ break;
+
+ case irvCDx:
+ c = glyphStorage[lastGlyph - 1];
+ d = glyphStorage[lastGlyph];
+ ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
+ id = glyphStorage.getCharIndex(lastGlyph, success);
+ x = lastGlyph - 2;
+
+ while (x >= firstGlyph) {
+ glyphStorage[x + 2] = glyphStorage[x];
+ ix = glyphStorage.getCharIndex(x, success);
+ glyphStorage.setCharIndex(x + 2, ix, success);
+ x -= 1;
+ }
+
+ glyphStorage[firstGlyph] = c;
+ glyphStorage[firstGlyph + 1] = d;
+
+ glyphStorage.setCharIndex(firstGlyph, ic, success);
+ glyphStorage.setCharIndex(firstGlyph + 1, id, success);
+ break;
+
+ case irvDCx:
+ c = glyphStorage[lastGlyph - 1];
+ d = glyphStorage[lastGlyph];
+ ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
+ id = glyphStorage.getCharIndex(lastGlyph, success);
+ x = lastGlyph - 2;
+
+ while (x >= firstGlyph) {
+ glyphStorage[x + 2] = glyphStorage[x];
+ ix = glyphStorage.getCharIndex(x, success);
+ glyphStorage.setCharIndex(x + 2, ix, success);
+ x -= 1;
+ }
+
+ glyphStorage[firstGlyph] = d;
+ glyphStorage[firstGlyph + 1] = c;
+
+ glyphStorage.setCharIndex(firstGlyph, id, success);
+ glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
+ break;
+
+ case irvCDxA:
+ a = glyphStorage[firstGlyph];
+ c = glyphStorage[lastGlyph - 1];
+ d = glyphStorage[lastGlyph];
+ ia = glyphStorage.getCharIndex(firstGlyph, success);
+ ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
+ id = glyphStorage.getCharIndex(lastGlyph, success);
+ x = lastGlyph - 2;
+
+ while (x > firstGlyph) {
+ glyphStorage[x + 1] = glyphStorage[x];
+ ix = glyphStorage.getCharIndex(x, success);
+ glyphStorage.setCharIndex(x + 1, ix, success);
+ x -= 1;
+ }
+
+ glyphStorage[firstGlyph] = c;
+ glyphStorage[firstGlyph + 1] = d;
+ glyphStorage[lastGlyph] = a;
+
+ glyphStorage.setCharIndex(firstGlyph, ic, success);
+ glyphStorage.setCharIndex(firstGlyph + 1, id, success);
+ glyphStorage.setCharIndex(lastGlyph, ia, success);
+ break;
+
+ case irvDCxA:
+ a = glyphStorage[firstGlyph];
+ c = glyphStorage[lastGlyph - 1];
+ d = glyphStorage[lastGlyph];
+ ia = glyphStorage.getCharIndex(firstGlyph, success);
+ ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
+ id = glyphStorage.getCharIndex(lastGlyph, success);
+ x = lastGlyph - 2;
+
+ while (x > firstGlyph) {
+ glyphStorage[x + 1] = glyphStorage[x];
+ ix = glyphStorage.getCharIndex(x, success);
+ glyphStorage.setCharIndex(x + 1, ix, success);
+ x -= 1;
+ }
+
+ glyphStorage[firstGlyph] = d;
+ glyphStorage[firstGlyph + 1] = c;
+ glyphStorage[lastGlyph] = a;
+
+ glyphStorage.setCharIndex(firstGlyph, id, success);
+ glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
+ glyphStorage.setCharIndex(lastGlyph, ia, success);
+ break;
+
+ case irvDxAB:
+ a = glyphStorage[firstGlyph];
+ b = glyphStorage[firstGlyph + 1];
+ d = glyphStorage[lastGlyph];
+ ia = glyphStorage.getCharIndex(firstGlyph, success);
+ ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
+ id = glyphStorage.getCharIndex(lastGlyph, success);
+ x = firstGlyph + 2;
+
+ while (x < lastGlyph) {
+ glyphStorage[x - 2] = glyphStorage[x];
+ ix = glyphStorage.getCharIndex(x, success);
+ glyphStorage.setCharIndex(x - 2, ix, success);
+ x += 1;
+ }
+
+ glyphStorage[firstGlyph] = d;
+ glyphStorage[lastGlyph - 1] = a;
+ glyphStorage[lastGlyph] = b;
+
+ glyphStorage.setCharIndex(firstGlyph, id, success);
+ glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
+ glyphStorage.setCharIndex(lastGlyph, ib, success);
+ break;
+
+ case irvDxBA:
+ a = glyphStorage[firstGlyph];
+ b = glyphStorage[firstGlyph + 1];
+ d = glyphStorage[lastGlyph];
+ ia = glyphStorage.getCharIndex(firstGlyph, success);
+ ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
+ id = glyphStorage.getCharIndex(lastGlyph, success);
+ x = firstGlyph + 2;
+
+ while (x < lastGlyph) {
+ glyphStorage[x - 2] = glyphStorage[x];
+ ix = glyphStorage.getCharIndex(x, success);
+ glyphStorage.setCharIndex(x - 2, ix, success);
+ x += 1;
+ }
+
+ glyphStorage[firstGlyph] = d;
+ glyphStorage[lastGlyph - 1] = b;
+ glyphStorage[lastGlyph] = a;
+
+ glyphStorage.setCharIndex(firstGlyph, id, success);
+ glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
+ glyphStorage.setCharIndex(lastGlyph, ia, success);
+ break;
+
+ case irvCDxAB:
+ a = glyphStorage[firstGlyph];
+ b = glyphStorage[firstGlyph + 1];
+
+ glyphStorage[firstGlyph] = glyphStorage[lastGlyph - 1];
+ glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph];
+
+ glyphStorage[lastGlyph - 1] = a;
+ glyphStorage[lastGlyph] = b;
+
+ ia = glyphStorage.getCharIndex(firstGlyph, success);
+ ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
+ ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
+ id = glyphStorage.getCharIndex(lastGlyph, success);
+
+ glyphStorage.setCharIndex(firstGlyph, ic, success);
+ glyphStorage.setCharIndex(firstGlyph + 1, id, success);
+
+ glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
+ glyphStorage.setCharIndex(lastGlyph, ib, success);
+ break;
+
+ case irvCDxBA:
+ a = glyphStorage[firstGlyph];
+ b = glyphStorage[firstGlyph + 1];
+
+ glyphStorage[firstGlyph] = glyphStorage[lastGlyph - 1];
+ glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph];
+
+ glyphStorage[lastGlyph - 1] = b;
+ glyphStorage[lastGlyph] = a;
+
+ ia = glyphStorage.getCharIndex(firstGlyph, success);
+ ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
+ ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
+ id = glyphStorage.getCharIndex(lastGlyph, success);
+
+ glyphStorage.setCharIndex(firstGlyph, ic, success);
+ glyphStorage.setCharIndex(firstGlyph + 1, id, success);
+
+ glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
+ glyphStorage.setCharIndex(lastGlyph, ia, success);
+ break;
+
+ case irvDCxAB:
+ a = glyphStorage[firstGlyph];
+ b = glyphStorage[firstGlyph + 1];
+
+ glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
+ glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph - 1];
+
+ glyphStorage[lastGlyph - 1] = a;
+ glyphStorage[lastGlyph] = b;
+
+ ia = glyphStorage.getCharIndex(firstGlyph, success);
+ ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
+ ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
+ id = glyphStorage.getCharIndex(lastGlyph, success);
+
+ glyphStorage.setCharIndex(firstGlyph, id, success);
+ glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
+
+ glyphStorage.setCharIndex(lastGlyph - 1, ia, success);
+ glyphStorage.setCharIndex(lastGlyph, ib, success);
+ break;
+
+ case irvDCxBA:
+ a = glyphStorage[firstGlyph];
+ b = glyphStorage[firstGlyph + 1];
+
+ glyphStorage[firstGlyph] = glyphStorage[lastGlyph];
+ glyphStorage[firstGlyph + 1] = glyphStorage[lastGlyph - 1];
+
+ glyphStorage[lastGlyph - 1] = b;
+ glyphStorage[lastGlyph] = a;
+
+ ia = glyphStorage.getCharIndex(firstGlyph, success);
+ ib = glyphStorage.getCharIndex(firstGlyph + 1, success);
+ ic = glyphStorage.getCharIndex(lastGlyph - 1, success);
+ id = glyphStorage.getCharIndex(lastGlyph, success);
+
+ glyphStorage.setCharIndex(firstGlyph, id, success);
+ glyphStorage.setCharIndex(firstGlyph + 1, ic, success);
+
+ glyphStorage.setCharIndex(lastGlyph - 1, ib, success);
+ glyphStorage.setCharIndex(lastGlyph, ia, success);
+ break;
+
+ default:
+ break;
+ }
+
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/IndicRearrangementProcessor2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __INDICREARRANGEMENTPROCESSOR2_H
+#define __INDICREARRANGEMENTPROCESSOR2_H
+
+/**
+ * \file
+ * \internal
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor.h"
+#include "StateTableProcessor2.h"
+#include "IndicRearrangement.h"
+
+U_NAMESPACE_BEGIN
+
+class LEGlyphStorage;
+
+class IndicRearrangementProcessor2 : public StateTableProcessor2
+{
+public:
+ virtual void beginStateTable();
+
+ virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success);
+
+ virtual void endStateTable();
+
+ void doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb) const;
+
+ IndicRearrangementProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+ virtual ~IndicRearrangementProcessor2();
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for the actual class.
+ *
+ * @stable ICU 2.8
+ */
+ virtual UClassID getDynamicClassID() const;
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for this class.
+ *
+ * @stable ICU 2.8
+ */
+ static UClassID getStaticClassID();
+
+protected:
+ le_int32 firstGlyph;
+ le_int32 lastGlyph;
+
+ LEReferenceToArrayOf<IndicRearrangementStateEntry2> entryTable;
+ LEReferenceTo<IndicRearrangementSubtableHeader2> indicRearrangementSubtableHeader;
+
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/IndicReordering.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/IndicReordering.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -266,7 +266,7 @@
le_uint32 saveAuxData = fGlyphStorage.getAuxData(i+inv_count,success);
const SplitMatra *splitMatra = classTable->getSplitMatra(matraClass);
int j;
- for (j = 0 ; *(splitMatra)[j] != 0 ; j++) {
+ for (j = 0 ; j < SM_MAX_PIECES && *(splitMatra)[j] != 0 ; j++) {
LEUnicode piece = (*splitMatra)[j];
if ( j == 0 ) {
fOutChars[i+inv_count] = piece;
@@ -357,7 +357,7 @@
const SplitMatra *splitMatra = classTable->getSplitMatra(matraClass);
int i;
- for (i = 0; i < 3 && (*splitMatra)[i] != 0; i += 1) {
+ for (i = 0; i < SM_MAX_PIECES && (*splitMatra)[i] != 0; i += 1) {
LEUnicode piece = (*splitMatra)[i];
IndicClassTable::CharClass pieceClass = classTable->getCharClass(piece);
@@ -658,6 +658,11 @@
MPreFixups *mpreFixups = NULL;
const IndicClassTable *classTable = IndicClassTable::getScriptClassTable(scriptCode);
+ if(classTable==NULL) {
+ success = LE_MEMORY_ALLOCATION_ERROR;
+ return 0;
+ }
+
if (classTable->scriptFlags & SF_MPRE_FIXUP) {
mpreFixups = new MPreFixups(charCount);
if (mpreFixups == NULL) {
@@ -1224,7 +1229,6 @@
LEUnicode currentChar;
- LEUnicode virama;
LEUnicode workChars[2];
LEGlyphStorage workGlyphs;
@@ -1232,14 +1236,17 @@
//le_int32 offset = 0;
+#if 0
+// TODO: Should this section of code have actually been doing something?
// First find the relevant virama for the script we are dealing with
-
+ LEUnicode virama;
for ( currentChar = classTable->firstChar ; currentChar <= classTable->lastChar ; currentChar++ ) {
if ( classTable->isVirama(currentChar)) {
virama = currentChar;
break;
}
}
+#endif
for ( currentChar = classTable->firstChar ; currentChar <= classTable->lastChar ; currentChar++ ) {
if ( classTable->isConsonant(currentChar)) {
--- a/jdk/src/share/native/sun/font/layout/IndicReordering.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/IndicReordering.h Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2009 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -96,7 +96,9 @@
#define SF_POST_BASE_LIMIT_MASK 0x0000FFFFU
#define SF_NO_POST_BASE_LIMIT 0x00007FFFU
-typedef LEUnicode SplitMatra[3];
+#define SM_MAX_PIECES 3
+
+typedef LEUnicode SplitMatra[SM_MAX_PIECES];
class MPreFixups;
class LEGlyphStorage;
--- a/jdk/src/share/native/sun/font/layout/KernTable.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/KernTable.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -48,7 +48,7 @@
le_int16 value; // fword, kern value in funits
};
#define KERN_PAIRINFO_SIZE 6
-
+LE_CORRECT_SIZE(PairInfo, KERN_PAIRINFO_SIZE)
struct Subtable_0 {
le_uint16 nPairs;
le_uint16 searchRange;
@@ -56,6 +56,7 @@
le_uint16 rangeShift;
};
#define KERN_SUBTABLE_0_HEADER_SIZE 8
+LE_CORRECT_SIZE(Subtable_0, KERN_SUBTABLE_0_HEADER_SIZE)
// Kern table version 0 only
struct SubtableHeader {
@@ -64,6 +65,7 @@
le_uint16 coverage;
};
#define KERN_SUBTABLE_HEADER_SIZE 6
+LE_CORRECT_SIZE(SubtableHeader, KERN_SUBTABLE_HEADER_SIZE)
// Version 0 only, version 1 has different layout
struct KernTableHeader {
@@ -71,6 +73,7 @@
le_uint16 nTables;
};
#define KERN_TABLE_HEADER_SIZE 4
+LE_CORRECT_SIZE(KernTableHeader, KERN_TABLE_HEADER_SIZE)
#define COVERAGE_HORIZONTAL 0x1
#define COVERAGE_MINIMUM 0x2
@@ -92,21 +95,21 @@
* TODO: support multiple subtables
* TODO: respect header flags
*/
-KernTable::KernTable(const LEFontInstance* font_, const void* tableData)
- : pairs(0), font(font_)
+KernTable::KernTable(const LETableReference& base, LEErrorCode &success)
+ : pairs(), pairsSwapped(NULL), fTable(base)
{
- const KernTableHeader* header = (const KernTableHeader*)tableData;
- if (header == 0) {
+ if(LE_FAILURE(success) || (fTable.isEmpty())) {
#if DEBUG
fprintf(stderr, "no kern data\n");
#endif
return;
}
+ LEReferenceTo<KernTableHeader> header(fTable, success);
#if DEBUG
// dump first 32 bytes of header
for (int i = 0; i < 64; ++i) {
- fprintf(stderr, "%0.2x ", ((const char*)tableData)[i]&0xff);
+ fprintf(stderr, "%0.2x ", ((const char*)header.getAlias())[i]&0xff);
if (((i+1)&0xf) == 0) {
fprintf(stderr, "\n");
} else if (((i+1)&0x7) == 0) {
@@ -115,12 +118,17 @@
}
#endif
- if (header->version == 0 && SWAPW(header->nTables) > 0) {
- const SubtableHeader* subhead = (const SubtableHeader*)((char*)tableData + KERN_TABLE_HEADER_SIZE);
- if (subhead->version == 0) {
+ if(LE_FAILURE(success)) return;
+
+ if (!header.isEmpty() && header->version == 0 && SWAPW(header->nTables) > 0) {
+ LEReferenceTo<SubtableHeader> subhead(header, success, KERN_TABLE_HEADER_SIZE);
+
+ if (LE_SUCCESS(success) && !subhead.isEmpty() && subhead->version == 0) {
coverage = SWAPW(subhead->coverage);
if (coverage & COVERAGE_HORIZONTAL) { // only handle horizontal kerning
- const Subtable_0* table = (const Subtable_0*)((char*)subhead + KERN_SUBTABLE_HEADER_SIZE);
+ LEReferenceTo<Subtable_0> table(subhead, success, KERN_SUBTABLE_HEADER_SIZE);
+
+ if(table.isEmpty() || LE_FAILURE(success)) return;
nPairs = SWAPW(table->nPairs);
@@ -134,19 +142,31 @@
rangeShift = (nPairs * KERN_PAIRINFO_SIZE) - searchRange;
#endif
- pairs = (PairInfo*)font->getKernPairs();
- if (pairs == NULL) {
- char *pairData = (char*)table + KERN_SUBTABLE_0_HEADER_SIZE;
- char *pptr = pairData;
- pairs = (PairInfo*)(malloc(nPairs*sizeof(PairInfo)));
- PairInfo *p = (PairInfo*)pairs;
- for (int i = 0; i < nPairs; i++, pptr += KERN_PAIRINFO_SIZE, p++) {
- memcpy(p, pptr, KERN_PAIRINFO_SIZE);
+ if(LE_SUCCESS(success) && nPairs>0) {
+ // pairs is an instance member, and table is on the stack.
+ // set 'pairs' based on table.getAlias(). This will range check it.
+
+ pairs = LEReferenceToArrayOf<PairInfo>(fTable, // based on overall table
+ success,
+ (const PairInfo*)table.getAlias(), // subtable 0 + ..
+ KERN_SUBTABLE_0_HEADER_SIZE, // .. offset of header size
+ nPairs); // count
+ }
+ if (LE_SUCCESS(success) && pairs.isValid()) {
+ pairsSwapped = (PairInfo*)(malloc(nPairs*sizeof(PairInfo)));
+ PairInfo *p = (PairInfo*)pairsSwapped;
+ for (int i = 0; LE_SUCCESS(success) && i < nPairs; i++, p++) {
+ memcpy(p, pairs.getAlias(i,success), KERN_PAIRINFO_SIZE);
p->key = SWAPL(p->key);
}
- font->setKernPairs((void*)pairs);
+ fTable.getFont()->setKernPairs((void*)pairsSwapped); // store it
}
+#if 0
+ fprintf(stderr, "coverage: %0.4x nPairs: %d pairs %p\n", coverage, nPairs, pairs.getAlias());
+ fprintf(stderr, " searchRange: %d entrySelector: %d rangeShift: %d\n", searchRange, entrySelector, rangeShift);
+ fprintf(stderr, "[[ ignored font table entries: range %d selector %d shift %d ]]\n", SWAPW(table->searchRange), SWAPW(table->entrySelector), SWAPW(table->rangeShift));
+#endif
#if DEBUG
fprintf(stderr, "coverage: %0.4x nPairs: %d pairs 0x%x\n", coverage, nPairs, pairs);
fprintf(stderr,
@@ -194,14 +214,17 @@
* Process the glyph positions. The positions array has two floats for each
* glyph, plus a trailing pair to mark the end of the last glyph.
*/
-void KernTable::process(LEGlyphStorage& storage)
+void KernTable::process(LEGlyphStorage& storage, LEErrorCode &success)
{
- if (pairs) {
- LEErrorCode success = LE_NO_ERROR;
+ if(LE_FAILURE(success)) return;
+
+ if (pairsSwapped) {
+ success = LE_NO_ERROR;
le_uint32 key = storage[0]; // no need to mask off high bits
float adjust = 0;
- for (int i = 1, e = storage.getGlyphCount(); i < e; ++i) {
+
+ for (int i = 1, e = storage.getGlyphCount(); LE_SUCCESS(success)&& i < e; ++i) {
key = key << 16 | (storage[i] & 0xffff);
// argh, to do a binary search, we need to have the pair list in sorted order
@@ -209,7 +232,7 @@
// so either I have to swap the element each time I examine it, or I have to swap
// all the elements ahead of time and store them in the font
- const PairInfo* p = pairs;
+ const PairInfo* p = pairsSwapped;
const PairInfo* tp = (const PairInfo*)(p + (rangeShift/KERN_PAIRINFO_SIZE)); /* rangeshift is in original table bytes */
if (key > tp->key) {
p = tp;
@@ -225,7 +248,7 @@
tp = (const PairInfo*)(p + (probe/KERN_PAIRINFO_SIZE));
le_uint32 tkey = tp->key;
#if DEBUG
- fprintf(stdout, " %.3d (%0.8x)\n", (tp - pairs), tkey);
+ fprintf(stdout, " %.3d (%0.8x)\n", (tp - pairsSwapped), tkey);
#endif
if (tkey <= key) {
if (tkey == key) {
@@ -240,10 +263,10 @@
// device transform, or a faster way, such as moving the
// entire kern table up to Java.
LEPoint pt;
- pt.fX = font->xUnitsToPoints(value);
+ pt.fX = fTable.getFont()->xUnitsToPoints(value);
pt.fY = 0;
- font->getKerningAdjustment(pt);
+ fTable.getFont()->getKerningAdjustment(pt);
adjust += pt.fX;
break;
}
--- a/jdk/src/share/native/sun/font/layout/KernTable.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/KernTable.h Wed Apr 17 02:53:02 2013 -0700
@@ -26,7 +26,7 @@
/*
*
*
- * (C) Copyright IBM Corp. 2004-2005 - All Rights Reserved
+ * (C) Copyright IBM Corp. 2004-2013 - All Rights Reserved
*
*/
@@ -38,6 +38,7 @@
#endif
#include "LETypes.h"
+#include "LETableReference.h"
//#include "LEFontInstance.h"
//#include "LEGlyphStorage.h"
@@ -56,19 +57,20 @@
private:
le_uint16 coverage;
le_uint16 nPairs;
- const PairInfo* pairs;
- const LEFontInstance* font;
+ LEReferenceToArrayOf<PairInfo> pairs;
+ PairInfo *pairsSwapped;
+ const LETableReference &fTable;
le_uint16 searchRange;
le_uint16 entrySelector;
le_uint16 rangeShift;
public:
- KernTable(const LEFontInstance* font, const void* tableData);
+ KernTable(const LETableReference &table, LEErrorCode &success);
/*
* Process the glyph positions.
*/
- void process(LEGlyphStorage& storage);
+ void process(LEGlyphStorage& storage, LEErrorCode &success);
};
U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/KhmerLayoutEngine.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/KhmerLayoutEngine.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -43,7 +43,7 @@
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(KhmerOpenTypeLayoutEngine)
KhmerOpenTypeLayoutEngine::KhmerOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
+ le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
{
fFeatureMap = KhmerReordering::getFeatureMap(fFeatureMapCount);
--- a/jdk/src/share/native/sun/font/layout/KhmerLayoutEngine.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/KhmerLayoutEngine.h Wed Apr 17 02:53:02 2013 -0700
@@ -83,7 +83,7 @@
* @internal
*/
KhmerOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success);
+ le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success);
/**
* This constructor is used when the font requires a "canned" GSUB table which can't be known
--- a/jdk/src/share/native/sun/font/layout/LEFontInstance.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LEFontInstance.h Wed Apr 17 02:53:02 2013 -0700
@@ -190,6 +190,25 @@
*/
virtual const void *getFontTable(LETag tableTag) const = 0;
+ /**
+ * This method reads a table from the font. Note that in general,
+ * it only makes sense to call this method on an <code>LEFontInstance</code>
+ * which represents a physical font - i.e. one which has been returned by
+ * <code>getSubFont()</code>. This is because each subfont in a composite font
+ * will have different tables, and there's no way to know which subfont to access.
+ *
+ * Subclasses which represent composite fonts should always return <code>NULL</code>.
+ *
+ * This version sets a length, for range checking.
+ *
+ * @param tableTag - the four byte table tag. (e.g. 'cmap')
+ * @param length - ignored on entry, on exit will be the length of the table if known, or -1 if unknown.
+ * @return the address of the table in memory, or <code>NULL</code>
+ * if the table doesn't exist.
+ * @internal
+ */
+ virtual const void* getFontTable(LETag tableTag, size_t &length) const { length=-1; return getFontTable(tableTag); } /* -1 = unknown length */
+
virtual void *getKernPairs() const = 0;
virtual void setKernPairs(void *pairs) const = 0;
--- a/jdk/src/share/native/sun/font/layout/LEGlyphFilter.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LEGlyphFilter.h Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -36,6 +36,7 @@
U_NAMESPACE_BEGIN
+#ifndef U_HIDE_INTERNAL_API
/**
* This is a helper class that is used to
* recognize a set of glyph indices.
@@ -63,6 +64,7 @@
*/
virtual le_bool accept(LEGlyphID glyph) const = 0;
};
+#endif /* U_HIDE_INTERNAL_API */
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/LEInsertionList.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LEInsertionList.h Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
**********************************************************************
- * Copyright (C) 1998-2008, International Business Machines
+ * Copyright (C) 1998-2013, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
@@ -39,6 +39,7 @@
struct InsertionRecord;
+#ifndef U_HIDE_INTERNAL_API
/**
* This class encapsulates the callback used by <code>LEInsertionList</code>
* to apply an insertion from the insertion list.
@@ -194,6 +195,7 @@
*/
le_bool append;
};
+#endif /* U_HIDE_INTERNAL_API */
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/LEScripts.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LEScripts.h Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2010. All Rights Reserved.
+ * (C) Copyright IBM Corp. 1998-2013. All Rights Reserved.
*
* WARNING: THIS FILE IS MACHINE GENERATED. DO NOT HAND EDIT IT UNLESS
* YOU REALLY KNOW WHAT YOU'RE DOING.
@@ -241,8 +241,28 @@
palmScriptCode = 144,
sindScriptCode = 145,
waraScriptCode = 146,
+/**
+ * @stable ICU 4.8
+ */
- scriptCodeCount = 147
+ afakScriptCode = 147,
+ jurcScriptCode = 148,
+ mrooScriptCode = 149,
+ nshuScriptCode = 150,
+ shrdScriptCode = 151,
+ soraScriptCode = 152,
+ takrScriptCode = 153,
+ tangScriptCode = 154,
+ woleScriptCode = 155,
+/**
+ * @stable ICU 49
+ */
+
+ hluwScriptCode = 156, /* bump to match current ICU */
+ khojScriptCode = 157,
+ tirhScriptCode = 158,
+
+ scriptCodeCount = 159
};
U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/LETableReference.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,442 @@
+/*
+ * 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.
+ */
+
+/*
+ * -*- c++ -*-
+ *
+ * (C) Copyright IBM Corp. and others 2013 - All Rights Reserved
+ *
+ * Range checking
+ *
+ */
+
+#ifndef __LETABLEREFERENCE_H
+#define __LETABLEREFERENCE_H
+
+#include "LETypes.h"
+#include "LEFontInstance.h"
+
+
+#define kQuestionmarkTableTag 0x3F3F3F3FUL
+#define kTildeTableTag 0x7e7e7e7eUL
+#ifdef __cplusplus
+
+// internal - interface for range checking
+U_NAMESPACE_BEGIN
+
+#if LE_ASSERT_BAD_FONT
+class LETableReference; // fwd
+/**
+ * defined in OpenTypeUtilities.cpp
+ * @internal
+ */
+extern void _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len);
+
+#define LE_DEBUG_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0);
+#define LE_DEBUG_TR3(x,y,z) _debug_LETableReference(__FILE__, __LINE__, x, this, (const void*)y, (size_t)z);
+#if 0
+#define LE_TRACE_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0);
+#else
+#define LE_TRACE_TR(x)
+#endif
+
+#else
+#define LE_DEBUG_TR(x)
+#define LE_DEBUG_TR3(x,y,z)
+#define LE_TRACE_TR(x)
+#endif
+
+/**
+ * @internal
+ */
+class LETableReference {
+public:
+/**
+ * @internal
+ * Construct from a specific tag
+ */
+ LETableReference(const LEFontInstance* font, LETag tableTag, LEErrorCode &success) :
+ fFont(font), fTag(tableTag), fParent(NULL), fStart(NULL),fLength(LE_UINTPTR_MAX) {
+ loadTable(success);
+ LE_TRACE_TR("INFO: new table load")
+ }
+
+ LETableReference(const LETableReference &parent, LEErrorCode &success) : fFont(parent.fFont), fTag(parent.fTag), fParent(&parent), fStart(parent.fStart), fLength(parent.fLength) {
+ if(LE_FAILURE(success)) {
+ clear();
+ }
+ LE_TRACE_TR("INFO: new clone")
+ }
+
+ LETableReference(const le_uint8* data, size_t length = LE_UINTPTR_MAX) :
+ fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(data), fLength(length) {
+ LE_TRACE_TR("INFO: new raw")
+ }
+ LETableReference() :
+ fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(NULL), fLength(0) {
+ LE_TRACE_TR("INFO: new empty")
+ }
+
+ ~LETableReference() {
+ fTag=kTildeTableTag;
+ LE_TRACE_TR("INFO: new dtor")
+ }
+
+ /**
+ * @internal
+ * @param length if LE_UINTPTR_MAX means "whole table"
+ * subset
+ */
+ LETableReference(const LETableReference &parent, size_t offset, size_t length,
+ LEErrorCode &err) :
+ fFont(parent.fFont), fTag(parent.fTag), fParent(&parent),
+ fStart((parent.fStart)+offset), fLength(length) {
+ if(LE_SUCCESS(err)) {
+ if(isEmpty()) {
+ //err = LE_MISSING_FONT_TABLE_ERROR;
+ clear(); // it's just empty. Not an error.
+ } else if(offset >= fParent->fLength) {
+ LE_DEBUG_TR3("offset out of range: (%p) +%d", NULL, offset);
+ err = LE_INDEX_OUT_OF_BOUNDS_ERROR;
+ clear();
+ } else {
+ if(fLength == LE_UINTPTR_MAX &&
+ fParent->fLength != LE_UINTPTR_MAX) {
+ fLength = (fParent->fLength) - offset; // decrement length as base address is incremented
+ }
+ if(fLength != LE_UINTPTR_MAX) { // if we have bounds:
+ if(offset+fLength > fParent->fLength) {
+ LE_DEBUG_TR3("offset+fLength out of range: (%p) +%d", NULL, offset+fLength);
+ err = LE_INDEX_OUT_OF_BOUNDS_ERROR; // exceeded
+ clear();
+ }
+ }
+ }
+ } else {
+ clear();
+ }
+ LE_TRACE_TR("INFO: new subset")
+ }
+
+ const void* getAlias() const { return (const void*)fStart; }
+ const void* getAliasTODO() const { LE_DEBUG_TR("getAliasTODO()"); return (const void*)fStart; }
+ le_bool isEmpty() const { return fStart==NULL || fLength==0; }
+ le_bool isValid() const { return !isEmpty(); }
+ le_bool hasBounds() const { return fLength!=LE_UINTPTR_MAX; }
+ void clear() { fLength=0; fStart=NULL; }
+ size_t getLength() const { return fLength; }
+ const LEFontInstance* getFont() const { return fFont; }
+ LETag getTag() const { return fTag; }
+ const LETableReference* getParent() const { return fParent; }
+
+ void addOffset(size_t offset, LEErrorCode &success) {
+ if(hasBounds()) {
+ if(offset > fLength) {
+ LE_DEBUG_TR("addOffset off end");
+ success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
+ return;
+ } else {
+ fLength -= offset;
+ }
+ }
+ fStart += offset;
+ }
+
+ size_t ptrToOffset(const void *atPtr, LEErrorCode &success) const {
+ if(atPtr==NULL) return 0;
+ if(LE_FAILURE(success)) return LE_UINTPTR_MAX;
+ if((atPtr < fStart) ||
+ (hasBounds() && (atPtr > fStart+fLength))) {
+ LE_DEBUG_TR3("ptrToOffset args out of range: %p", atPtr, 0);
+ success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
+ return LE_UINTPTR_MAX;
+ }
+ return ((const le_uint8*)atPtr)-fStart;
+ }
+
+ /**
+ * Clamp down the length, for range checking.
+ */
+ size_t contractLength(size_t newLength) {
+ if(fLength!=LE_UINTPTR_MAX&&newLength>0&&newLength<=fLength) {
+ fLength = newLength;
+ }
+ return fLength;
+ }
+
+ /**
+ * Throw an error if offset+length off end
+ */
+public:
+ size_t verifyLength(size_t offset, size_t length, LEErrorCode &success) {
+ if(isValid()&&
+ LE_SUCCESS(success) &&
+ fLength!=LE_UINTPTR_MAX && length!=LE_UINTPTR_MAX && offset!=LE_UINTPTR_MAX &&
+ (offset+length)>fLength) {
+ LE_DEBUG_TR3("verifyLength failed (%p) %d",NULL, offset+length);
+ success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
+#if LE_ASSERT_BAD_FONT
+ fprintf(stderr, "offset=%lu, len=%lu, would be at %p, (%lu) off end. End at %p\n", offset,length, fStart+offset+length, (offset+length-fLength), (offset+length-fLength)+fStart);
+#endif
+ }
+ return fLength;
+ }
+
+ /**
+ * Change parent link to another
+ */
+ LETableReference &reparent(const LETableReference &base) {
+ fParent = &base;
+ return *this;
+ }
+
+ /**
+ * remove parent link. Factory functions should do this.
+ */
+ void orphan(void) {
+ fParent=NULL;
+ }
+
+protected:
+ const LEFontInstance* fFont;
+ LETag fTag;
+ const LETableReference *fParent;
+ const le_uint8 *fStart; // keep as 8 bit internally, for pointer math
+ size_t fLength;
+
+ void loadTable(LEErrorCode &success) {
+ if(LE_SUCCESS(success)) {
+ fStart = (const le_uint8*)(fFont->getFontTable(fTag, fLength)); // note - a null table is not an error.
+ }
+ }
+
+ void setRaw(const void *data, size_t length = LE_UINTPTR_MAX) {
+ fFont = NULL;
+ fTag = kQuestionmarkTableTag;
+ fParent = NULL;
+ fStart = (const le_uint8*)data;
+ fLength = length;
+ }
+};
+
+
+template<class T>
+class LETableVarSizer {
+ public:
+ inline static size_t getSize();
+};
+
+// base definition- could override for adjustments
+template<class T> inline
+size_t LETableVarSizer<T>::getSize() {
+ return sizeof(T);
+}
+
+/**
+ * \def LE_VAR_ARRAY
+ * @param x Type (T)
+ * @param y some member that is of length ANY_NUMBER
+ * Call this after defining a class, for example:
+ * LE_VAR_ARRAY(FeatureListTable,featureRecordArray)
+ * this is roughly equivalent to:
+ * template<> inline size_t LETableVarSizer<FeatureListTable>::getSize() { return sizeof(FeatureListTable) - (sizeof(le_uint16)*ANY_NUMBER); }
+ * it's a specialization that informs the LETableReference subclasses to NOT include the variable array in the size.
+ * dereferencing NULL is valid here because we never actually dereference it, just inside sizeof.
+ */
+#define LE_VAR_ARRAY(x,y) template<> inline size_t LETableVarSizer<x>::getSize() { return sizeof(x) - (sizeof(((const x*)0)->y)); }
+/**
+ * \def LE_CORRECT_SIZE
+ * @param x type (T)
+ * @param y fixed size for T
+ */
+#define LE_CORRECT_SIZE(x,y) template<> inline size_t LETableVarSizer<x>::getSize() { return y; }
+
+/**
+ * Open a new entry based on an existing table
+ */
+
+/**
+ * \def LE_UNBOUNDED_ARRAY
+ * define an array with no *known* bound. Will trim to available size.
+ * @internal
+ */
+#define LE_UNBOUNDED_ARRAY LE_UINT32_MAX
+
+template<class T>
+class LEReferenceToArrayOf : public LETableReference {
+public:
+ LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, size_t offset, le_uint32 count)
+ : LETableReference(parent, offset, LE_UINTPTR_MAX, success), fCount(count) {
+ LE_TRACE_TR("INFO: new RTAO by offset")
+ if(LE_SUCCESS(success)) {
+ if(count == LE_UNBOUNDED_ARRAY) { // not a known length
+ count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
+ }
+ LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*count, success);
+ }
+ if(LE_FAILURE(success)) {
+ fCount=0;
+ clear();
+ }
+ }
+
+ LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, le_uint32 count)
+ : LETableReference(parent, parent.ptrToOffset(array, success), LE_UINTPTR_MAX, success), fCount(count) {
+LE_TRACE_TR("INFO: new RTAO")
+ if(LE_SUCCESS(success)) {
+ if(count == LE_UNBOUNDED_ARRAY) { // not a known length
+ count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
+ }
+ LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*count, success);
+ }
+ if(LE_FAILURE(success)) clear();
+ }
+ LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, size_t offset, le_uint32 count)
+ : LETableReference(parent, parent.ptrToOffset(array, success)+offset, LE_UINTPTR_MAX, success), fCount(count) {
+LE_TRACE_TR("INFO: new RTAO")
+ if(LE_SUCCESS(success)) {
+ if(count == LE_UNBOUNDED_ARRAY) { // not a known length
+ count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
+ }
+ LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*count, success);
+ }
+ if(LE_FAILURE(success)) clear();
+ }
+
+ LEReferenceToArrayOf() :LETableReference(), fCount(0) {}
+
+ le_uint32 getCount() const { return fCount; }
+
+ using LETableReference::getAlias;
+
+ const T *getAlias(le_uint32 i, LEErrorCode &success) const {
+ return ((const T*)(((const char*)getAlias())+getOffsetFor(i, success)));
+ }
+
+ const T *getAliasTODO() const { LE_DEBUG_TR("getAliasTODO<>"); return (const T*)fStart; }
+
+ const T& getObject(le_uint32 i, LEErrorCode &success) const {
+ return *getAlias(i,success);
+ }
+
+ const T& operator()(le_uint32 i, LEErrorCode &success) const {
+ return *getAlias(i,success);
+ }
+
+ size_t getOffsetFor(le_uint32 i, LEErrorCode &success) const {
+ if(LE_SUCCESS(success)&&i<getCount()) {
+ return LETableVarSizer<T>::getSize()*i;
+ } else {
+ success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
+ }
+ return 0;
+ }
+
+ LEReferenceToArrayOf<T> &reparent(const LETableReference &base) {
+ fParent = &base;
+ return *this;
+ }
+
+ LEReferenceToArrayOf(const LETableReference& parent, LEErrorCode & success) : LETableReference(parent,0, LE_UINTPTR_MAX, success), fCount(0) {
+ LE_TRACE_TR("INFO: null RTAO")
+ }
+
+private:
+ le_uint32 fCount;
+};
+
+
+template<class T>
+class LEReferenceTo : public LETableReference {
+public:
+ /**
+ * open a sub reference.
+ * @param parent parent reference
+ * @param success error status
+ * @param atPtr location of reference - if NULL, will be at offset zero (i.e. downcast of parent). Otherwise must be a pointer within parent's bounds.
+ */
+ LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr)
+ : LETableReference(parent, parent.ptrToOffset(atPtr, success), LE_UINTPTR_MAX, success) {
+ verifyLength(0, LETableVarSizer<T>::getSize(), success);
+ if(LE_FAILURE(success)) clear();
+ }
+ /**
+ * ptr plus offset
+ */
+ LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr, size_t offset)
+ : LETableReference(parent, parent.ptrToOffset(atPtr, success)+offset, LE_UINTPTR_MAX, success) {
+ verifyLength(0, LETableVarSizer<T>::getSize(), success);
+ if(LE_FAILURE(success)) clear();
+ }
+ LEReferenceTo(const LETableReference &parent, LEErrorCode &success, size_t offset)
+ : LETableReference(parent, offset, LE_UINTPTR_MAX, success) {
+ verifyLength(0, LETableVarSizer<T>::getSize(), success);
+ if(LE_FAILURE(success)) clear();
+ }
+ LEReferenceTo(const LETableReference &parent, LEErrorCode &success)
+ : LETableReference(parent, 0, LE_UINTPTR_MAX, success) {
+ verifyLength(0, LETableVarSizer<T>::getSize(), success);
+ if(LE_FAILURE(success)) clear();
+ }
+ LEReferenceTo(const LEFontInstance *font, LETag tableTag, LEErrorCode &success)
+ : LETableReference(font, tableTag, success) {
+ verifyLength(0, LETableVarSizer<T>::getSize(), success);
+ if(LE_FAILURE(success)) clear();
+ }
+ LEReferenceTo(const le_uint8 *data, size_t length = LE_UINTPTR_MAX) : LETableReference(data, length) {}
+ LEReferenceTo(const T *data, size_t length = LE_UINTPTR_MAX) : LETableReference((const le_uint8*)data, length) {}
+ LEReferenceTo() : LETableReference(NULL) {}
+
+ LEReferenceTo<T>& operator=(const T* other) {
+ setRaw(other);
+ return *this;
+ }
+
+ LEReferenceTo<T> &reparent(const LETableReference &base) {
+ fParent = &base;
+ return *this;
+ }
+
+ /**
+ * roll forward by one <T> size.
+ * same as addOffset(LETableVarSizer<T>::getSize(),success)
+ */
+ void addObject(LEErrorCode &success) {
+ addOffset(LETableVarSizer<T>::getSize(), success);
+ }
+ void addObject(size_t count, LEErrorCode &success) {
+ addOffset(LETableVarSizer<T>::getSize()*count, success);
+ }
+
+ const T *operator->() const { return getAlias(); }
+ const T *getAlias() const { return (const T*)fStart; }
+ const T *getAliasTODO() const { LE_DEBUG_TR("getAliasTODO<>"); return (const T*)fStart; }
+};
+
+
+U_NAMESPACE_END
+
+#endif
+
+#endif
--- a/jdk/src/share/native/sun/font/layout/LETypes.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LETypes.h Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2010 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -50,14 +50,15 @@
#endif
#include "unicode/utypes.h"
+
+#ifdef __cplusplus
#include "unicode/uobject.h"
+#endif
+
#ifdef LE_USE_CMEMORY
#include "cmemory.h"
#endif
-#endif /* not standalone */
-
-
-U_NAMESPACE_BEGIN
+#endif
/*!
* \file
@@ -296,12 +297,14 @@
*/
typedef UChar32 LEUnicode32;
+#ifndef U_HIDE_DEPRECATED_API
/**
* Used to represent 16-bit Unicode code points.
*
* @deprecated since ICU 2.4. Use LEUnicode16 instead
*/
typedef UChar LEUnicode;
+#endif /* U_HIDE_DEPRECATED_API */
/**
* Used to hold a pair of (x, y) values which represent a point.
@@ -325,7 +328,7 @@
float fY;
};
-#ifndef XP_CPLUSPLUS
+#ifndef __cplusplus
/**
* Used to hold a pair of (x, y) values which represent a point.
*
@@ -335,6 +338,39 @@
#endif
+#ifndef U_HIDE_INTERNAL_API
+
+#ifndef LE_ASSERT_BAD_FONT
+#define LE_ASSERT_BAD_FONT 0
+#endif
+
+#if LE_ASSERT_BAD_FONT
+#include <stdio.h>
+#define LE_DEBUG_BAD_FONT(x) fprintf(stderr,"%s:%d: BAD FONT: %s\n", __FILE__, __LINE__, (x));
+#else
+#define LE_DEBUG_BAD_FONT(x)
+#endif
+
+/**
+ * Max value representable by a uintptr
+ */
+
+#ifndef UINT32_MAX
+#define LE_UINT32_MAX 0xFFFFFFFFU
+#else
+#define LE_UINT32_MAX UINT32_MAX
+#endif
+
+#ifndef UINTPTR_MAX
+#define LE_UINTPTR_MAX LE_UINT32_MAX
+#else
+#define LE_UINTPTR_MAX UINTPTR_MAX
+#endif
+
+/**
+ * Range check for overflow
+ */
+#define LE_RANGE_CHECK(type, count, ptrfn) (( (LE_UINTPTR_MAX / sizeof(type)) < count ) ? NULL : (ptrfn))
/**
* A convenience macro to get the length of an array.
*
@@ -356,7 +392,7 @@
*
* @internal
*/
-#define LE_NEW_ARRAY(type, count) (type *) uprv_malloc((count) * sizeof(type))
+#define LE_NEW_ARRAY(type, count) (type *) LE_RANGE_CHECK(type,count,uprv_malloc((count) * sizeof(type)))
/**
* Re-allocate an array of basic types. This is used to isolate the rest of
@@ -373,7 +409,52 @@
* @internal
*/
#define LE_DELETE_ARRAY(array) uprv_free((void *) (array))
-#endif
+#else
+/* !LE_USE_CMEMORY - Not using ICU memory - use C std lib versions */
+
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * A convenience macro to get the length of an array.
+ *
+ * @internal
+ */
+#define LE_ARRAY_SIZE(array) (sizeof array / sizeof array[0])
+
+/**
+ * A convenience macro for copying an array.
+ *
+ * @internal
+ */
+#define LE_ARRAY_COPY(dst, src, count) memcpy((void *) (dst), (void *) (src), (count) * sizeof (src)[0])
+
+/**
+ * Allocate an array of basic types. This is used to isolate the rest of
+ * the LayoutEngine code from cmemory.h.
+ *
+ * @internal
+ */
+#define LE_NEW_ARRAY(type, count) LE_RANGE_CHECK(type,count,(type *) malloc((count) * sizeof(type)))
+
+/**
+ * Re-allocate an array of basic types. This is used to isolate the rest of
+ * the LayoutEngine code from cmemory.h.
+ *
+ * @internal
+ */
+#define LE_GROW_ARRAY(array, newSize) realloc((void *) (array), (newSize) * sizeof (array)[0])
+
+ /**
+ * Free an array of basic types. This is used to isolate the rest of
+ * the LayoutEngine code from cmemory.h.
+ *
+ * @internal
+ */
+#define LE_DELETE_ARRAY(array) free((void *) (array))
+
+#endif /* LE_USE_CMEMORY */
+#endif /* U_HIDE_INTERNAL_API */
/**
* A macro to construct the four-letter tags used to
@@ -536,7 +617,7 @@
LE_RAND_FEATURE_TAG = 0x72616E64UL, /**< 'rand' */
LE_RLIG_FEATURE_TAG = 0x726C6967UL, /**< 'rlig' */
LE_RPHF_FEATURE_TAG = 0x72706866UL, /**< 'rphf' */
- LE_RKRF_FEATURE_TAG = 0x726B7266UL, /**< 'rkrf' */
+ LE_RKRF_FEATURE_TAG = 0x726B7266UL, /**< 'rkrf' */
LE_RTBD_FEATURE_TAG = 0x72746264UL, /**< 'rtbd' */
LE_RTLA_FEATURE_TAG = 0x72746C61UL, /**< 'rtla' */
LE_RUBY_FEATURE_TAG = 0x72756279UL, /**< 'ruby' */
@@ -588,6 +669,68 @@
};
/**
+ * @internal
+ */
+enum LEFeatureENUMs {
+ LE_Kerning_FEATURE_ENUM = 0, /**< Requests Kerning. Formerly LayoutEngine::kTypoFlagKern */
+ LE_Ligatures_FEATURE_ENUM = 1, /**< Requests Ligatures. Formerly LayoutEngine::kTypoFlagLiga */
+ LE_NoCanon_FEATURE_ENUM = 2, /**< Requests No Canonical Processing */
+ LE_CLIG_FEATURE_ENUM, /**< Feature specific enum */
+ LE_DLIG_FEATURE_ENUM, /**< Feature specific enum */
+ LE_HLIG_FEATURE_ENUM, /**< Feature specific enum */
+ LE_LIGA_FEATURE_ENUM, /**< Feature specific enum */
+ LE_RLIG_FEATURE_ENUM, /**< Feature specific enum */
+ LE_SMCP_FEATURE_ENUM, /**< Feature specific enum */
+ LE_FRAC_FEATURE_ENUM, /**< Feature specific enum */
+ LE_AFRC_FEATURE_ENUM, /**< Feature specific enum */
+ LE_ZERO_FEATURE_ENUM, /**< Feature specific enum */
+ LE_SWSH_FEATURE_ENUM, /**< Feature specific enum */
+ LE_CSWH_FEATURE_ENUM, /**< Feature specific enum */
+ LE_SALT_FEATURE_ENUM, /**< Feature specific enum */
+ LE_NALT_FEATURE_ENUM, /**< Feature specific enum */
+ LE_RUBY_FEATURE_ENUM, /**< Feature specific enum */
+ LE_SS01_FEATURE_ENUM, /**< Feature specific enum */
+ LE_SS02_FEATURE_ENUM, /**< Feature specific enum */
+ LE_SS03_FEATURE_ENUM, /**< Feature specific enum */
+ LE_SS04_FEATURE_ENUM, /**< Feature specific enum */
+ LE_SS05_FEATURE_ENUM, /**< Feature specific enum */
+ LE_SS06_FEATURE_ENUM, /**< Feature specific enum */
+ LE_SS07_FEATURE_ENUM, /**< Feature specific enum */
+
+ LE_CHAR_FILTER_FEATURE_ENUM = 31, /**< Apply CharSubstitutionFilter */
+ LE_FEATURE_ENUM_MAX = LE_CHAR_FILTER_FEATURE_ENUM
+};
+
+#define LE_Kerning_FEATURE_FLAG (1 << LE_Kerning_FEATURE_ENUM)
+#define LE_Ligatures_FEATURE_FLAG (1 << LE_Ligatures_FEATURE_ENUM)
+#define LE_NoCanon_FEATURE_FLAG (1 << LE_NoCanon_FEATURE_ENUM)
+#define LE_CLIG_FEATURE_FLAG (1 << LE_CLIG_FEATURE_ENUM)
+#define LE_DLIG_FEATURE_FLAG (1 << LE_DLIG_FEATURE_ENUM)
+#define LE_HLIG_FEATURE_FLAG (1 << LE_HLIG_FEATURE_ENUM)
+#define LE_LIGA_FEATURE_FLAG (1 << LE_LIGA_FEATURE_ENUM)
+#define LE_RLIG_FEATURE_FLAG (1 << LE_RLIG_FEATURE_ENUM)
+#define LE_SMCP_FEATURE_FLAG (1 << LE_SMCP_FEATURE_ENUM)
+#define LE_FRAC_FEATURE_FLAG (1 << LE_FRAC_FEATURE_ENUM)
+#define LE_AFRC_FEATURE_FLAG (1 << LE_AFRC_FEATURE_ENUM)
+#define LE_ZERO_FEATURE_FLAG (1 << LE_ZERO_FEATURE_ENUM)
+#define LE_SWSH_FEATURE_FLAG (1 << LE_SWSH_FEATURE_ENUM)
+#define LE_CSWH_FEATURE_FLAG (1 << LE_CSWH_FEATURE_ENUM)
+#define LE_SALT_FEATURE_FLAG (1 << LE_SALT_FEATURE_ENUM)
+#define LE_NALT_FEATURE_FLAG (1 << LE_NALT_FEATURE_ENUM)
+#define LE_RUBY_FEATURE_FLAG (1 << LE_RUBY_FEATURE_ENUM)
+#define LE_SS01_FEATURE_FLAG (1 << LE_SS01_FEATURE_ENUM)
+#define LE_SS02_FEATURE_FLAG (1 << LE_SS02_FEATURE_ENUM)
+#define LE_SS03_FEATURE_FLAG (1 << LE_SS03_FEATURE_ENUM)
+#define LE_SS04_FEATURE_FLAG (1 << LE_SS04_FEATURE_ENUM)
+#define LE_SS05_FEATURE_FLAG (1 << LE_SS05_FEATURE_ENUM)
+#define LE_SS06_FEATURE_FLAG (1 << LE_SS06_FEATURE_ENUM)
+#define LE_SS07_FEATURE_FLAG (1 << LE_SS07_FEATURE_ENUM)
+
+#define LE_CHAR_FILTER_FEATURE_FLAG (1 << LE_CHAR_FILTER_FEATURE_ENUM)
+
+#define LE_DEFAULT_FEATURE_FLAG (LE_Kerning_FEATURE_FLAG | LE_Ligatures_FEATURE_FLAG) /**< default features */
+
+/**
* Error codes returned by the LayoutEngine.
*
* @stable ICU 2.4
@@ -611,7 +754,7 @@
};
#endif
-#ifndef XP_CPLUSPLUS
+#ifndef __cplusplus
/**
* Error codes returned by the LayoutEngine.
*
@@ -638,7 +781,4 @@
#define LE_FAILURE(code) (U_FAILURE((UErrorCode)code))
#endif
-U_NAMESPACE_END
-#endif
-
-
+#endif /* __LETYPES_H */
--- a/jdk/src/share/native/sun/font/layout/LayoutEngine.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LayoutEngine.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -33,6 +33,7 @@
#include "LETypes.h"
#include "LEScripts.h"
#include "LELanguages.h"
+#include "LESwaps.h"
#include "LayoutEngine.h"
#include "ArabicLayoutEngine.h"
@@ -44,6 +45,8 @@
#include "ThaiLayoutEngine.h"
#include "TibetanLayoutEngine.h"
#include "GXLayoutEngine.h"
+#include "GXLayoutEngine2.h"
+
#include "ScriptAndLanguageTags.h"
#include "CharSubstitutionFilter.h"
@@ -63,6 +66,10 @@
/* Leave this copyright notice here! It needs to go somewhere in this library. */
static const char copyright[] = U_COPYRIGHT_STRING;
+/* TODO: remove these? */
+const le_int32 LayoutEngine::kTypoFlagKern = LE_Kerning_FEATURE_FLAG;
+const le_int32 LayoutEngine::kTypoFlagLiga = LE_Ligatures_FEATURE_FLAG;
+
const LEUnicode32 DefaultCharMapper::controlChars[] = {
0x0009, 0x000A, 0x000D,
/*0x200C, 0x200D,*/ 0x200E, 0x200F,
@@ -140,21 +147,21 @@
class CanonMarkFilter : public UMemory, public LEGlyphFilter
{
private:
- const GlyphClassDefinitionTable *classDefTable;
+ const LEReferenceTo<GlyphClassDefinitionTable> classDefTable;
CanonMarkFilter(const CanonMarkFilter &other); // forbid copying of this class
CanonMarkFilter &operator=(const CanonMarkFilter &other); // forbid copying of this class
public:
- CanonMarkFilter(const GlyphDefinitionTableHeader *gdefTable);
+ CanonMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success);
virtual ~CanonMarkFilter();
virtual le_bool accept(LEGlyphID glyph) const;
};
-CanonMarkFilter::CanonMarkFilter(const GlyphDefinitionTableHeader *gdefTable)
+CanonMarkFilter::CanonMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success)
+ : classDefTable(gdefTable->getMarkAttachClassDefinitionTable(gdefTable, success))
{
- classDefTable = gdefTable->getMarkAttachClassDefinitionTable();
}
CanonMarkFilter::~CanonMarkFilter()
@@ -164,9 +171,10 @@
le_bool CanonMarkFilter::accept(LEGlyphID glyph) const
{
- le_int32 glyphClass = classDefTable->getGlyphClass(glyph);
-
- return glyphClass != 0;
+ LEErrorCode success = LE_NO_ERROR;
+ le_int32 glyphClass = classDefTable->getGlyphClass(classDefTable, glyph, success);
+ if(LE_FAILURE(success)) return false;
+ return glyphClass != 0;
}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LayoutEngine)
@@ -251,24 +259,24 @@
return 0;
}
- if ((fTypoFlags & 0x4) == 0) { // no canonical processing
+ if ((fTypoFlags & LE_NoCanon_FEATURE_FLAG) == 0) { // no canonical processing
return count;
}
- const GlyphSubstitutionTableHeader *canonGSUBTable = (GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
+ LEReferenceTo<GlyphSubstitutionTableHeader> canonGSUBTable((GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable);
LETag scriptTag = OpenTypeLayoutEngine::getScriptTag(fScriptCode);
LETag langSysTag = OpenTypeLayoutEngine::getLangSysTag(fLanguageCode);
le_int32 i, dir = 1, out = 0, outCharCount = count;
- if (canonGSUBTable->coversScript(scriptTag)) {
+ if (canonGSUBTable->coversScript(canonGSUBTable,scriptTag, success) || LE_SUCCESS(success)) {
CharSubstitutionFilter *substitutionFilter = new CharSubstitutionFilter(fFontInstance);
if (substitutionFilter == NULL) {
success = LE_MEMORY_ALLOCATION_ERROR;
return 0;
}
- const LEUnicode *inChars = &chars[offset];
- LEUnicode *reordered = NULL;
+ const LEUnicode *inChars = &chars[offset];
+ LEUnicode *reordered = NULL;
LEGlyphStorage fakeGlyphStorage;
fakeGlyphStorage.allocateGlyphArray(count, rightToLeft, success);
@@ -278,20 +286,20 @@
return 0;
}
- // This is the cheapest way to get mark reordering only for Hebrew.
- // We could just do the mark reordering for all scripts, but most
- // of them probably don't need it...
- if (fScriptCode == hebrScriptCode) {
- reordered = LE_NEW_ARRAY(LEUnicode, count);
+ // This is the cheapest way to get mark reordering only for Hebrew.
+ // We could just do the mark reordering for all scripts, but most
+ // of them probably don't need it...
+ if (fScriptCode == hebrScriptCode) {
+ reordered = LE_NEW_ARRAY(LEUnicode, count);
- if (reordered == NULL) {
- delete substitutionFilter;
- success = LE_MEMORY_ALLOCATION_ERROR;
- return 0;
- }
+ if (reordered == NULL) {
+ delete substitutionFilter;
+ success = LE_MEMORY_ALLOCATION_ERROR;
+ return 0;
+ }
- CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, reordered, fakeGlyphStorage);
- inChars = reordered;
+ CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, reordered, fakeGlyphStorage);
+ inChars = reordered;
}
fakeGlyphStorage.allocateAuxData(success);
@@ -311,11 +319,11 @@
fakeGlyphStorage.setAuxData(out, canonFeatures, success);
}
- if (reordered != NULL) {
- LE_DELETE_ARRAY(reordered);
- }
+ if (reordered != NULL) {
+ LE_DELETE_ARRAY(reordered);
+ }
- outCharCount = canonGSUBTable->process(fakeGlyphStorage, rightToLeft, scriptTag, langSysTag, NULL, substitutionFilter, canonFeatureMap, canonFeatureMapCount, FALSE, success);
+ outCharCount = canonGSUBTable->process(canonGSUBTable, fakeGlyphStorage, rightToLeft, scriptTag, langSysTag, (const GlyphDefinitionTableHeader*)NULL, substitutionFilter, canonFeatureMap, canonFeatureMapCount, FALSE, success);
if (LE_FAILURE(success)) {
delete substitutionFilter;
@@ -416,16 +424,16 @@
return;
}
- GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
- CanonMarkFilter filter(gdefTable);
+ LEReferenceTo<GlyphDefinitionTableHeader> gdefTable((GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable,
+ CanonShaping::glyphDefinitionTableLen);
+ CanonMarkFilter filter(gdefTable, success);
adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
- if (fTypoFlags & 0x1) { /* kerning enabled */
- static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG;
-
- KernTable kt(fFontInstance, getFontTable(kernTableTag));
- kt.process(glyphStorage);
+ if (fTypoFlags & LE_Kerning_FEATURE_FLAG) { /* kerning enabled */
+ LETableReference kernTable(fFontInstance, LE_KERN_TABLE_TAG, success);
+ KernTable kt(kernTable, success);
+ kt.process(glyphStorage, success);
}
// default is no adjustments
@@ -510,9 +518,9 @@
glyphStorage.adjustPosition(glyphCount, xAdjust, 0, success);
}
-const void *LayoutEngine::getFontTable(LETag tableTag) const
+const void *LayoutEngine::getFontTable(LETag tableTag, size_t &length) const
{
- return fFontInstance->getFontTable(tableTag);
+ return fFontInstance->getFontTable(tableTag, length);
}
void LayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror,
@@ -559,37 +567,41 @@
void LayoutEngine::reset()
{
+ if(fGlyphStorage!=NULL) {
fGlyphStorage->reset();
+ fGlyphStorage = NULL;
+ }
}
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, LEErrorCode &success)
{
- // 3 -> kerning and ligatures
- return LayoutEngine::layoutEngineFactory(fontInstance, scriptCode, languageCode, 3, success);
+ //kerning and ligatures - by default
+ return LayoutEngine::layoutEngineFactory(fontInstance, scriptCode, languageCode, LE_DEFAULT_FEATURE_FLAG, success);
}
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
{
static const le_uint32 gsubTableTag = LE_GSUB_TABLE_TAG;
static const le_uint32 mortTableTag = LE_MORT_TABLE_TAG;
+ static const le_uint32 morxTableTag = LE_MORX_TABLE_TAG;
if (LE_FAILURE(success)) {
return NULL;
}
- const GlyphSubstitutionTableHeader *gsubTable = (const GlyphSubstitutionTableHeader *) fontInstance->getFontTable(gsubTableTag);
+ LEReferenceTo<GlyphSubstitutionTableHeader> gsubTable(fontInstance,gsubTableTag,success);
LayoutEngine *result = NULL;
LETag scriptTag = 0x00000000;
LETag languageTag = 0x00000000;
- LETag v2ScriptTag = OpenTypeLayoutEngine::getV2ScriptTag(scriptCode);
+ LETag v2ScriptTag = OpenTypeLayoutEngine::getV2ScriptTag(scriptCode);
// Right now, only invoke V2 processing for Devanagari. TODO: Allow more V2 scripts as they are
// properly tested.
- if ( v2ScriptTag == dev2ScriptTag && gsubTable != NULL && gsubTable->coversScript( v2ScriptTag )) {
- result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, TRUE, gsubTable, success);
- }
- else if (gsubTable != NULL && gsubTable->coversScript(scriptTag = OpenTypeLayoutEngine::getScriptTag(scriptCode))) {
+ if ( v2ScriptTag == dev2ScriptTag && gsubTable.isValid() && gsubTable->coversScript(gsubTable, v2ScriptTag, success )) {
+ result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, TRUE, gsubTable, success);
+ }
+ else if (gsubTable.isValid() && gsubTable->coversScript(gsubTable, scriptTag = OpenTypeLayoutEngine::getScriptTag(scriptCode), success)) {
switch (scriptCode) {
case bengScriptCode:
case devaScriptCode:
@@ -608,6 +620,11 @@
result = new ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
break;
+ case hebrScriptCode:
+ // Disable hebrew ligatures since they have only archaic uses, see ticket #8318
+ result = new OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags & ~kTypoFlagLiga, gsubTable, success);
+ break;
+
case hangScriptCode:
result = new HangulOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
break;
@@ -620,10 +637,10 @@
case janLanguageCode:
case zhtLanguageCode:
case zhsLanguageCode:
- if (gsubTable->coversScriptAndLanguage(scriptTag, languageTag, TRUE)) {
+ if (gsubTable->coversScriptAndLanguage(gsubTable, scriptTag, languageTag, success, TRUE)) {
result = new HanOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
break;
- }
+ }
// note: falling through to default case.
default:
@@ -646,26 +663,29 @@
break;
}
} else {
- const MorphTableHeader *morphTable = (MorphTableHeader *) fontInstance->getFontTable(mortTableTag);
-
- if (morphTable != NULL) {
- result = new GXLayoutEngine(fontInstance, scriptCode, languageCode, morphTable, success);
+ MorphTableHeader2 *morxTable = (MorphTableHeader2 *)fontInstance->getFontTable(morxTableTag);
+ if (morxTable != NULL && SWAPL(morxTable->version)==0x00020000) {
+ result = new GXLayoutEngine2(fontInstance, scriptCode, languageCode, morxTable, typoFlags, success);
} else {
- switch (scriptCode) {
- case bengScriptCode:
- case devaScriptCode:
- case gujrScriptCode:
- case kndaScriptCode:
- case mlymScriptCode:
- case oryaScriptCode:
- case guruScriptCode:
- case tamlScriptCode:
- case teluScriptCode:
- case sinhScriptCode:
- {
- result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
- break;
- }
+ LEReferenceTo<MorphTableHeader> mortTable(fontInstance, mortTableTag, success);
+ if (LE_SUCCESS(success) && mortTable.isValid() && SWAPL(mortTable->version)==0x00010000) { // mort
+ result = new GXLayoutEngine(fontInstance, scriptCode, languageCode, mortTable, success);
+ } else {
+ switch (scriptCode) {
+ case bengScriptCode:
+ case devaScriptCode:
+ case gujrScriptCode:
+ case kndaScriptCode:
+ case mlymScriptCode:
+ case oryaScriptCode:
+ case guruScriptCode:
+ case tamlScriptCode:
+ case teluScriptCode:
+ case sinhScriptCode:
+ {
+ result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
+ break;
+ }
case arabScriptCode:
//case hebrScriptCode:
@@ -683,9 +703,10 @@
result = new HangulOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break;
- default:
- result = new LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
- break;
+ default:
+ result = new LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
+ break;
+ }
}
}
}
--- a/jdk/src/share/native/sun/font/layout/LayoutEngine.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LayoutEngine.h Wed Apr 17 02:53:02 2013 -0700
@@ -26,7 +26,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -90,6 +90,14 @@
* @stable ICU 2.8
*/
class U_LAYOUT_API LayoutEngine : public UObject {
+public:
+#ifndef U_HIDE_INTERNAL_API
+ /** @internal Flag to request kerning. Use LE_Kerning_FEATURE_FLAG instead. */
+ static const le_int32 kTypoFlagKern;
+ /** @internal Flag to request ligatures. Use LE_Ligatures_FEATURE_FLAG instead. */
+ static const le_int32 kTypoFlagLiga;
+#endif /* U_HIDE_INTERNAL_API */
+
protected:
/**
* The object which holds the glyph storage
@@ -140,6 +148,7 @@
*/
le_bool fFilterZeroWidth;
+#ifndef U_HIDE_INTERNAL_API
/**
* This constructs an instance for a given font, script and language. Subclass constructors
* must call this constructor.
@@ -161,7 +170,10 @@
le_int32 languageCode,
le_int32 typoFlags,
LEErrorCode &success);
+#endif /* U_HIDE_INTERNAL_API */
+ // Do not enclose the protected default constructor with #ifndef U_HIDE_INTERNAL_API
+ // or else the compiler will create a public default constructor.
/**
* This overrides the default no argument constructor to make it
* difficult for clients to call it. Clients are expected to call
@@ -268,12 +280,18 @@
* some other way must override this method.
*
* @param tableTag - the four byte table tag.
+ * @param length - length to use
*
* @return the address of the table.
*
* @internal
*/
- virtual const void *getFontTable(LETag tableTag) const;
+ virtual const void *getFontTable(LETag tableTag, size_t &length) const;
+
+ /**
+ * @deprecated
+ */
+ virtual const void *getFontTable(LETag tableTag) const { size_t ignored; return getFontTable(tableTag, ignored); }
/**
* This method does character to glyph mapping. The default implementation
@@ -302,6 +320,7 @@
*/
virtual void mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror, LEGlyphStorage &glyphStorage, LEErrorCode &success);
+#ifndef U_HIDE_INTERNAL_API
/**
* This is a convenience method that forces the advance width of mark
* glyphs to be zero, which is required for proper selection and highlighting.
@@ -336,7 +355,7 @@
* @internal
*/
static void adjustMarkGlyphs(const LEUnicode chars[], le_int32 charCount, le_bool reverse, LEGlyphStorage &glyphStorage, LEGlyphFilter *markFilter, LEErrorCode &success);
-
+#endif /* U_HIDE_INTERNAL_API */
public:
/**
--- a/jdk/src/share/native/sun/font/layout/LigatureSubstProc.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LigatureSubstProc.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -47,15 +47,15 @@
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LigatureSubstitutionProcessor)
-LigatureSubstitutionProcessor::LigatureSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader)
- : StateTableProcessor(morphSubtableHeader)
+ LigatureSubstitutionProcessor::LigatureSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
+: StateTableProcessor(morphSubtableHeader, success), ligatureSubstitutionHeader(morphSubtableHeader, success)
{
- ligatureSubstitutionHeader = (const LigatureSubstitutionHeader *) morphSubtableHeader;
+ if(LE_FAILURE(success)) return;
ligatureActionTableOffset = SWAPW(ligatureSubstitutionHeader->ligatureActionTableOffset);
componentTableOffset = SWAPW(ligatureSubstitutionHeader->componentTableOffset);
ligatureTableOffset = SWAPW(ligatureSubstitutionHeader->ligatureTableOffset);
- entryTable = (const LigatureSubstitutionStateEntry *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
+ entryTable = LEReferenceToArrayOf<LigatureSubstitutionStateEntry>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
}
LigatureSubstitutionProcessor::~LigatureSubstitutionProcessor()
@@ -69,7 +69,9 @@
ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index)
{
- const LigatureSubstitutionStateEntry *entry = &entryTable[index];
+ LEErrorCode success = LE_NO_ERROR;
+ const LigatureSubstitutionStateEntry *entry = entryTable.getAlias(index, success);
+
ByteOffset newState = SWAPW(entry->newStateOffset);
le_int16 flags = SWAPW(entry->flags);
@@ -79,12 +81,16 @@
}
componentStack[m] = currGlyph;
+ } else if ( m == -1) {
+ // bad font- skip this glyph.
+ currGlyph++;
+ return newState;
}
ByteOffset actionOffset = flags & lsfActionOffsetMask;
if (actionOffset != 0) {
- const LigatureActionEntry *ap = (const LigatureActionEntry *) ((char *) &ligatureSubstitutionHeader->stHeader + actionOffset);
+ LEReferenceTo<LigatureActionEntry> ap(stHeader, success, actionOffset);
LigatureActionEntry action;
le_int32 offset, i = 0;
le_int32 stack[nComponents];
@@ -93,7 +99,8 @@
do {
le_uint32 componentGlyph = componentStack[m--];
- action = SWAPL(*ap++);
+ action = SWAPL(*ap.getAlias());
+ ap.addObject(success); // ap++
if (m < 0) {
m = nComponents - 1;
@@ -101,29 +108,48 @@
offset = action & lafComponentOffsetMask;
if (offset != 0) {
- const le_int16 *offsetTable = (const le_int16 *)((char *) &ligatureSubstitutionHeader->stHeader + 2 * SignExtend(offset, lafComponentOffsetMask));
+ LEReferenceToArrayOf<le_int16> offsetTable(stHeader, success, 2 * SignExtend(offset, lafComponentOffsetMask), LE_UNBOUNDED_ARRAY);
- i += SWAPW(offsetTable[LE_GET_GLYPH(glyphStorage[componentGlyph])]);
+ if(LE_FAILURE(success)) {
+ currGlyph++;
+ LE_DEBUG_BAD_FONT("off end of ligature substitution header");
+ return newState; // get out! bad font
+ }
+ if(componentGlyph > glyphStorage.getGlyphCount()) {
+ LE_DEBUG_BAD_FONT("preposterous componentGlyph");
+ currGlyph++;
+ return newState; // get out! bad font
+ }
+ i += SWAPW(offsetTable.getObject(LE_GET_GLYPH(glyphStorage[componentGlyph]), success));
if (action & (lafLast | lafStore)) {
- const TTGlyphID *ligatureOffset = (const TTGlyphID *) ((char *) &ligatureSubstitutionHeader->stHeader + i);
- TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset);
+ LEReferenceTo<TTGlyphID> ligatureOffset(stHeader, success, i);
+ TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset.getAlias());
- glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
- stack[++mm] = componentGlyph;
- i = 0;
+ glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
+ if(mm==nComponents) {
+ LE_DEBUG_BAD_FONT("exceeded nComponents");
+ mm--; // don't overrun the stack.
+ }
+ stack[++mm] = componentGlyph;
+ i = 0;
} else {
- glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF);
+ glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF);
}
}
- } while (!(action & lafLast));
+#if LE_ASSERT_BAD_FONT
+ if(m<0) {
+ LE_DEBUG_BAD_FONT("m<0")
+ }
+#endif
+ } while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items
while (mm >= 0) {
- if (++m >= nComponents) {
- m = 0;
- }
+ if (++m >= nComponents) {
+ m = 0;
+ }
- componentStack[m] = stack[mm--];
+ componentStack[m] = stack[mm--];
}
}
--- a/jdk/src/share/native/sun/font/layout/LigatureSubstProc.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LigatureSubstProc.h Wed Apr 17 02:53:02 2013 -0700
@@ -58,7 +58,7 @@
virtual void endStateTable();
- LigatureSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader);
+ LigatureSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~LigatureSubstitutionProcessor();
/**
@@ -83,12 +83,12 @@
ByteOffset componentTableOffset;
ByteOffset ligatureTableOffset;
- const LigatureSubstitutionStateEntry *entryTable;
+ LEReferenceToArrayOf<LigatureSubstitutionStateEntry> entryTable;
le_int32 componentStack[nComponents];
le_int16 m;
- const LigatureSubstitutionHeader *ligatureSubstitutionHeader;
+ LEReferenceTo<LigatureSubstitutionHeader> ligatureSubstitutionHeader;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp and Others. 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "StateTables.h"
+#include "MorphStateTables.h"
+#include "SubtableProcessor2.h"
+#include "StateTableProcessor2.h"
+#include "LigatureSubstProc2.h"
+#include "LEGlyphStorage.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+#define ExtendedComplement(m) ((le_int32) (~((le_uint32) (m))))
+#define SignBit(m) ((ExtendedComplement(m) >> 1) & (le_int32)(m))
+#define SignExtend(v,m) (((v) & SignBit(m))? ((v) | ExtendedComplement(m)): (v))
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LigatureSubstitutionProcessor2)
+
+LigatureSubstitutionProcessor2::LigatureSubstitutionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+ : StateTableProcessor2(morphSubtableHeader, success),
+ ligActionOffset(0),
+ ligatureSubstitutionHeader(morphSubtableHeader, success), componentOffset(0), ligatureOffset(0), entryTable()
+{
+ if (LE_FAILURE(success)) return;
+
+ ligActionOffset = SWAPL(ligatureSubstitutionHeader->ligActionOffset);
+ componentOffset = SWAPL(ligatureSubstitutionHeader->componentOffset);
+ ligatureOffset = SWAPL(ligatureSubstitutionHeader->ligatureOffset);
+
+ entryTable = LEReferenceToArrayOf<LigatureSubstitutionStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
+}
+
+LigatureSubstitutionProcessor2::~LigatureSubstitutionProcessor2()
+{
+}
+
+void LigatureSubstitutionProcessor2::beginStateTable()
+{
+ m = -1;
+}
+
+le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success)
+{
+ const LigatureSubstitutionStateEntry2 *entry = entryTable.getAlias(index, success);
+ if(LE_FAILURE(success)) return 0;
+
+ le_uint16 nextStateIndex = SWAPW(entry->nextStateIndex);
+ le_uint16 flags = SWAPW(entry->entryFlags);
+ le_uint16 ligActionIndex = SWAPW(entry->ligActionIndex);
+
+ if (flags & lsfSetComponent) {
+ if (++m >= nComponents) {
+ m = 0;
+ }
+ componentStack[m] = currGlyph;
+ } else if ( m == -1) {
+ // bad font- skip this glyph.
+ //LE_DEBUG_BAD_FONT("m==-1 (componentCount went negative)")
+ currGlyph+= dir;
+ return nextStateIndex;
+ }
+
+ ByteOffset actionOffset = flags & lsfPerformAction;
+
+ if (actionOffset != 0) {
+ LEReferenceTo<LigatureActionEntry> ap(stHeader, success, ligActionOffset); // byte offset
+ ap.addObject(ligActionIndex - 1, success); // index offset ( one before the actual start, because we will pre-increment)
+ LEReferenceToArrayOf<TTGlyphID> ligatureTable(stHeader, success, ligatureOffset, LE_UNBOUNDED_ARRAY);
+ LigatureActionEntry action;
+ le_int32 offset, i = 0;
+ le_int32 stack[nComponents];
+ le_int16 mm = -1;
+
+ LEReferenceToArrayOf<le_uint16> componentTable(stHeader, success, componentOffset, LE_UNBOUNDED_ARRAY);
+ if(LE_FAILURE(success)) {
+ currGlyph+= dir;
+ return nextStateIndex; // get out! bad font
+ }
+
+ do {
+ le_uint32 componentGlyph = componentStack[m--]; // pop off
+
+ ap.addObject(success);
+ action = SWAPL(*ap.getAlias());
+
+ if (m < 0) {
+ m = nComponents - 1;
+ }
+
+ offset = action & lafComponentOffsetMask;
+ if (offset != 0) {
+ if(componentGlyph > glyphStorage.getGlyphCount()) {
+ LE_DEBUG_BAD_FONT("preposterous componentGlyph");
+ currGlyph+= dir;
+ return nextStateIndex; // get out! bad font
+ }
+ i += SWAPW(componentTable(LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask)),success));
+
+ if (action & (lafLast | lafStore)) {
+ TTGlyphID ligatureGlyph = SWAPW(ligatureTable(i,success));
+ glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
+ if(mm==nComponents) {
+ LE_DEBUG_BAD_FONT("exceeded nComponents");
+ mm--; // don't overrun the stack.
+ }
+ stack[++mm] = componentGlyph;
+ i = 0;
+ } else {
+ glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF);
+ }
+ }
+#if LE_ASSERT_BAD_FONT
+ if(m<0) {
+ LE_DEBUG_BAD_FONT("m<0")
+ }
+#endif
+ } while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items
+
+ while (mm >= 0) {
+ if (++m >= nComponents) {
+ m = 0;
+ }
+
+ componentStack[m] = stack[mm--];
+ }
+ }
+
+ if (!(flags & lsfDontAdvance)) {
+ currGlyph += dir;
+ }
+
+ return nextStateIndex;
+}
+
+void LigatureSubstitutionProcessor2::endStateTable()
+{
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __LIGATURESUBSTITUTIONPROCESSOR2_H
+#define __LIGATURESUBSTITUTIONPROCESSOR2_H
+
+/**
+ * \file
+ * \internal
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "StateTableProcessor2.h"
+#include "LigatureSubstitution.h"
+
+U_NAMESPACE_BEGIN
+
+class LEGlyphStorage;
+
+#define nComponents 16
+
+class LigatureSubstitutionProcessor2 : public StateTableProcessor2
+{
+public:
+ virtual void beginStateTable();
+
+ virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
+ EntryTableIndex2 index, LEErrorCode &success);
+
+ virtual void endStateTable();
+
+ LigatureSubstitutionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+ virtual ~LigatureSubstitutionProcessor2();
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for the actual class.
+ *
+ * @stable ICU 2.8
+ */
+ virtual UClassID getDynamicClassID() const;
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for this class.
+ *
+ * @stable ICU 2.8
+ */
+ static UClassID getStaticClassID();
+
+private:
+ LigatureSubstitutionProcessor2();
+
+protected:
+ le_uint32 ligActionOffset;
+ le_uint32 componentOffset;
+ le_uint32 ligatureOffset;
+
+ LEReferenceToArrayOf<LigatureSubstitutionStateEntry2> entryTable;
+
+ le_int32 componentStack[nComponents];
+ le_int16 m;
+
+ const LEReferenceTo<LigatureSubstitutionHeader2> ligatureSubstitutionHeader;
+
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/LigatureSubstSubtables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LigatureSubstSubtables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -40,10 +40,10 @@
U_NAMESPACE_BEGIN
-le_uint32 LigatureSubstitutionSubtable::process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter) const
+le_uint32 LigatureSubstitutionSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
- le_int32 coverageIndex = getGlyphCoverage(glyph);
+ le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (coverageIndex >= 0) {
Offset ligSetTableOffset = SWAPW(ligSetTableOffsetArray[coverageIndex]);
--- a/jdk/src/share/native/sun/font/layout/LigatureSubstSubtables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LigatureSubstSubtables.h Wed Apr 17 02:53:02 2013 -0700
@@ -50,6 +50,7 @@
le_uint16 ligatureCount;
Offset ligatureTableOffsetArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(LigatureSetTable, ligatureTableOffsetArray)
struct LigatureTable
{
@@ -57,14 +58,16 @@
le_uint16 compCount;
TTGlyphID componentArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(LigatureTable, componentArray)
struct LigatureSubstitutionSubtable : GlyphSubstitutionSubtable
{
le_uint16 ligSetCount;
Offset ligSetTableOffsetArray[ANY_NUMBER];
- le_uint32 process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter = NULL) const;
+ le_uint32 process(const LETableReference &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter = NULL) const;
};
+LE_VAR_ARRAY(LigatureSubstitutionSubtable, ligSetTableOffsetArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/LigatureSubstitution.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LigatureSubstitution.h Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -52,17 +52,32 @@
ByteOffset ligatureTableOffset;
};
+struct LigatureSubstitutionHeader2 : MorphStateTableHeader2
+{
+ le_uint32 ligActionOffset;
+ le_uint32 componentOffset;
+ le_uint32 ligatureOffset;
+};
+
enum LigatureSubstitutionFlags
{
lsfSetComponent = 0x8000,
lsfDontAdvance = 0x4000,
- lsfActionOffsetMask = 0x3FFF
+ lsfActionOffsetMask = 0x3FFF, // N/A in morx
+ lsfPerformAction = 0x2000
};
struct LigatureSubstitutionStateEntry : StateEntry
{
};
+struct LigatureSubstitutionStateEntry2
+{
+ le_uint16 nextStateIndex;
+ le_uint16 entryFlags;
+ le_uint16 ligActionIndex;
+};
+
typedef le_uint32 LigatureActionEntry;
enum LigatureActionFlags
--- a/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2010 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -44,7 +44,7 @@
U_NAMESPACE_BEGIN
-le_uint32 LookupProcessor::applyLookupTable(const LookupTable *lookupTable, GlyphIterator *glyphIterator,
+le_uint32 LookupProcessor::applyLookupTable(const LEReferenceTo<LookupTable> &lookupTable, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, LEErrorCode& success) const
{
if (LE_FAILURE(success)) {
@@ -57,7 +57,7 @@
le_uint32 delta;
for (le_uint16 subtable = 0; subtable < subtableCount; subtable += 1) {
- const LookupSubtable *lookupSubtable = lookupTable->getLookupSubtable(subtable);
+ LEReferenceTo<LookupSubtable> lookupSubtable = lookupTable->getLookupSubtable(lookupTable, subtable, success);
delta = applySubtable(lookupSubtable, lookupType, glyphIterator, fontInstance, success);
@@ -72,7 +72,7 @@
}
le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments,
- le_bool rightToLeft, const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
+ le_bool rightToLeft, const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader,
const LEFontInstance *fontInstance, LEErrorCode& success) const
{
if (LE_FAILURE(success)) {
@@ -89,22 +89,21 @@
rightToLeft, 0, 0, glyphDefinitionTableHeader);
le_int32 newGlyphCount = glyphCount;
- for (le_uint16 order = 0; order < lookupOrderCount; order += 1) {
+ for (le_uint16 order = 0; order < lookupOrderCount && LE_SUCCESS(success); order += 1) {
le_uint16 lookup = lookupOrderArray[order];
FeatureMask selectMask = lookupSelectArray[lookup];
if (selectMask != 0) {
- const LookupTable *lookupTable = lookupListTable->getLookupTable(lookup);
-
- if (!lookupTable)
+ const LEReferenceTo<LookupTable> lookupTable = lookupListTable->getLookupTable(lookupListTable, lookup, success);
+ if (!lookupTable.isValid() ||LE_FAILURE(success) ) {
continue;
-
+ }
le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
glyphIterator.reset(lookupFlags, selectMask);
while (glyphIterator.findFeatureTag()) {
- applyLookupTable(lookupTable, &glyphIterator, fontInstance, success);
+ applyLookupTable(lookupTable, &glyphIterator, fontInstance, success); // TODO
if (LE_FAILURE(success)) {
return 0;
}
@@ -124,8 +123,8 @@
return 0;
}
- const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex);
- if (lookupTable == NULL) {
+ const LEReferenceTo<LookupTable> lookupTable = lookupListTable->getLookupTable(lookupListTable, lookupTableIndex, success);
+ if (!lookupTable.isValid()) {
success = LE_INTERNAL_ERROR;
return 0;
}
@@ -136,33 +135,35 @@
return delta;
}
-le_int32 LookupProcessor::selectLookups(const FeatureTable *featureTable, FeatureMask featureMask, le_int32 order)
+le_int32 LookupProcessor::selectLookups(const LEReferenceTo<FeatureTable> &featureTable, FeatureMask featureMask, le_int32 order, LEErrorCode &success)
{
- le_uint16 lookupCount = featureTable? SWAPW(featureTable->lookupCount) : 0;
+ le_uint16 lookupCount = featureTable.isValid()? SWAPW(featureTable->lookupCount) : 0;
le_int32 store = order;
- for (le_uint16 lookup = 0; lookup < lookupCount; lookup += 1) {
- le_uint16 lookupListIndex = SWAPW(featureTable->lookupListIndexArray[lookup]);
+ LEReferenceToArrayOf<le_uint16> lookupListIndexArray(featureTable, success, featureTable->lookupListIndexArray, lookupCount);
- if (lookupListIndex >= lookupSelectCount)
- continue;
+ for (le_uint16 lookup = 0; LE_SUCCESS(success) && lookup < lookupCount; lookup += 1) {
+ le_uint16 lookupListIndex = SWAPW(lookupListIndexArray.getObject(lookup,success));
+ if (lookupListIndex >= lookupSelectCount) {
+ continue;
+ }
- lookupSelectArray[lookupListIndex] |= featureMask;
- lookupOrderArray[store++] = lookupListIndex;
+ lookupSelectArray[lookupListIndex] |= featureMask;
+ lookupOrderArray[store++] = lookupListIndex;
}
return store - order;
}
-LookupProcessor::LookupProcessor(const char *baseAddress,
+LookupProcessor::LookupProcessor(const LETableReference &baseAddress,
Offset scriptListOffset, Offset featureListOffset, Offset lookupListOffset,
LETag scriptTag, LETag languageTag, const FeatureMap *featureMap, le_int32 featureMapCount, le_bool orderFeatures,
LEErrorCode& success)
- : lookupListTable(NULL), featureListTable(NULL), lookupSelectArray(NULL), lookupSelectCount(0),
- lookupOrderArray(NULL), lookupOrderCount(0)
+ : lookupListTable(), featureListTable(), lookupSelectArray(NULL), lookupSelectCount(0),
+ lookupOrderArray(NULL), lookupOrderCount(0), fReference(baseAddress)
{
- const ScriptListTable *scriptListTable = NULL;
- const LangSysTable *langSysTable = NULL;
+ LEReferenceTo<ScriptListTable> scriptListTable;
+ LEReferenceTo<LangSysTable> langSysTable;
le_uint16 featureCount = 0;
le_uint16 lookupListCount = 0;
le_uint16 requiredFeatureIndex;
@@ -172,29 +173,33 @@
}
if (scriptListOffset != 0) {
- scriptListTable = (const ScriptListTable *) (baseAddress + scriptListOffset);
- langSysTable = scriptListTable->findLanguage(scriptTag, languageTag);
+ scriptListTable = LEReferenceTo<ScriptListTable>(baseAddress, success, scriptListOffset);
+ langSysTable = scriptListTable->findLanguage(scriptListTable, scriptTag, languageTag, success);
- if (langSysTable != 0) {
- featureCount = SWAPW(langSysTable->featureCount);
- }
+ if (langSysTable.isValid() && LE_SUCCESS(success)) {
+ featureCount = SWAPW(langSysTable->featureCount);
+ }
}
if (featureListOffset != 0) {
- featureListTable = (const FeatureListTable *) (baseAddress + featureListOffset);
+ featureListTable = LEReferenceTo<FeatureListTable>(baseAddress, success, featureListOffset);
}
if (lookupListOffset != 0) {
- lookupListTable = (const LookupListTable *) (baseAddress + lookupListOffset);
+ lookupListTable = LEReferenceTo<LookupListTable>(baseAddress,success, lookupListOffset);
+ if(LE_SUCCESS(success) && lookupListTable.isValid()) {
lookupListCount = SWAPW(lookupListTable->lookupCount);
+ }
}
- if (langSysTable == NULL || featureListTable == NULL || lookupListTable == NULL ||
+ if (langSysTable.isEmpty() || featureListTable.isEmpty() || lookupListTable.isEmpty() ||
featureCount == 0 || lookupListCount == 0) {
return;
}
- requiredFeatureIndex = SWAPW(langSysTable->reqFeatureIndex);
+ if(langSysTable.isValid()) {
+ requiredFeatureIndex = SWAPW(langSysTable->reqFeatureIndex);
+ }
lookupSelectArray = LE_NEW_ARRAY(FeatureMask, lookupListCount);
if (lookupSelectArray == NULL) {
@@ -209,31 +214,39 @@
lookupSelectCount = lookupListCount;
le_int32 count, order = 0;
- le_int32 featureReferences = 0;
- const FeatureTable *featureTable = NULL;
+ le_uint32 featureReferences = 0;
+ LEReferenceTo<FeatureTable> featureTable;
LETag featureTag;
- const FeatureTable *requiredFeatureTable = NULL;
+ LEReferenceTo<FeatureTable> requiredFeatureTable;
LETag requiredFeatureTag = 0x00000000U;
// Count the total number of lookups referenced by all features. This will
// be the maximum number of entries in the lookupOrderArray. We can't use
// lookupListCount because some lookups might be referenced by more than
// one feature.
- for (le_int32 feature = 0; feature < featureCount; feature += 1) {
- le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]);
+ if(featureListTable.isValid() && LE_SUCCESS(success)) {
+ LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount);
- featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag);
+ for (le_uint32 feature = 0; LE_SUCCESS(success)&&(feature < featureCount); feature += 1) {
+ le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature, success));
- if (!featureTable)
- continue;
+ featureTable = featureListTable->getFeatureTable(featureListTable, featureIndex, &featureTag, success);
+ if (!featureTable.isValid() || LE_FAILURE(success)) {
+ continue;
+ }
+ featureReferences += SWAPW(featureTable->lookupCount);
+ }
+ }
- featureReferences += SWAPW(featureTable->lookupCount);
+ if (!featureTable.isValid() || LE_FAILURE(success)) {
+ success = LE_INTERNAL_ERROR;
+ return;
}
if (requiredFeatureIndex != 0xFFFF) {
- requiredFeatureTable = featureListTable->getFeatureTable(requiredFeatureIndex, &requiredFeatureTag);
- featureReferences += SWAPW(featureTable->lookupCount);
+ requiredFeatureTable = featureListTable->getFeatureTable(featureListTable, requiredFeatureIndex, &requiredFeatureTag, success);
+ featureReferences += SWAPW(featureTable->lookupCount);
}
lookupOrderArray = LE_NEW_ARRAY(le_uint16, featureReferences);
@@ -248,7 +261,7 @@
// If this is the required feature, add its lookups
if (requiredFeatureTag == fm.tag) {
- count += selectLookups(requiredFeatureTable, fm.mask, order);
+ count += selectLookups(requiredFeatureTable, fm.mask, order, success);
}
if (orderFeatures) {
@@ -258,7 +271,8 @@
}
for (le_uint16 feature = 0; feature < featureCount; feature += 1) {
- le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]);
+ LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount);
+ le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature,success));
// don't add the required feature to the list more than once...
// TODO: Do we need this check? (Spec. says required feature won't be in feature list...)
@@ -266,10 +280,10 @@
continue;
}
- featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag);
+ featureTable = featureListTable->getFeatureTable(featureListTable, featureIndex, &featureTag, success);
if (featureTag == fm.tag) {
- count += selectLookups(featureTable, fm.mask, order + count);
+ count += selectLookups(featureTable, fm.mask, order + count, success);
}
}
@@ -278,9 +292,10 @@
}
order += count;
- } else {
- for (le_uint16 feature = 0; feature < featureCount; feature += 1) {
- le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]);
+ } else if(langSysTable.isValid()) {
+ LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount);
+ for (le_uint16 feature = 0; LE_SUCCESS(success)&& (feature < featureCount); feature += 1) {
+ le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature,success));
// don't add the required feature to the list more than once...
// NOTE: This check is commented out because the spec. says that
@@ -292,10 +307,10 @@
}
#endif
- featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag);
+ featureTable = featureListTable->getFeatureTable(featureListTable, featureIndex, &featureTag, success);
if (featureTag == fm.tag) {
- order += selectLookups(featureTable, fm.mask, order);
+ order += selectLookups(featureTable, fm.mask, order, success);
}
}
}
--- a/jdk/src/share/native/sun/font/layout/LookupProcessor.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LookupProcessor.h Wed Apr 17 02:53:02 2013 -0700
@@ -41,6 +41,7 @@
#include "LETypes.h"
#include "LEFontInstance.h"
#include "OpenTypeTables.h"
+#include "LETableReference.h"
//#include "Lookups.h"
//#include "Features.h"
@@ -59,19 +60,21 @@
class LookupProcessor : public UMemory {
public:
le_int32 process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments,
- le_bool rightToLeft, const GlyphDefinitionTableHeader *glyphDefinitionTableHeader, const LEFontInstance *fontInstance, LEErrorCode& success) const;
+ le_bool rightToLeft, const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader, const LEFontInstance *fontInstance, LEErrorCode& success) const;
- le_uint32 applyLookupTable(const LookupTable *lookupTable, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
+ le_uint32 applyLookupTable(const LEReferenceTo<LookupTable> &lookupTable, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
le_uint32 applySingleLookup(le_uint16 lookupTableIndex, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
- virtual le_uint32 applySubtable(const LookupSubtable *lookupSubtable, le_uint16 subtableType,
+ virtual le_uint32 applySubtable(const LEReferenceTo<LookupSubtable> &lookupSubtable, le_uint16 subtableType,
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const = 0;
virtual ~LookupProcessor();
+ const LETableReference &getReference() const { return fReference; }
+
protected:
- LookupProcessor(const char *baseAddress,
+ LookupProcessor(const LETableReference &baseAddress,
Offset scriptListOffset,
Offset featureListOffset,
Offset lookupListOffset,
@@ -84,10 +87,10 @@
LookupProcessor();
- le_int32 selectLookups(const FeatureTable *featureTable, FeatureMask featureMask, le_int32 order);
+ le_int32 selectLookups(const LEReferenceTo<FeatureTable> &featureTable, FeatureMask featureMask, le_int32 order, LEErrorCode &success);
- const LookupListTable *lookupListTable;
- const FeatureListTable *featureListTable;
+ LEReferenceTo<LookupListTable> lookupListTable;
+ LEReferenceTo<FeatureListTable> featureListTable;
FeatureMask *lookupSelectArray;
le_uint32 lookupSelectCount;
@@ -95,6 +98,8 @@
le_uint16 *lookupOrderArray;
le_uint32 lookupOrderCount;
+ LETableReference fReference;
+
private:
LookupProcessor(const LookupProcessor &other); // forbid copying of this class
--- a/jdk/src/share/native/sun/font/layout/LookupTables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LookupTables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -49,22 +49,26 @@
of the derived classes, and implement it in the others by casting
the "this" pointer to the type that has the implementation.
*/
-const LookupSegment *BinarySearchLookupTable::lookupSegment(const LookupSegment *segments, LEGlyphID glyph) const
+const LookupSegment *BinarySearchLookupTable::lookupSegment(const LETableReference &base, const LookupSegment *segments, LEGlyphID glyph, LEErrorCode &success) const
{
+
le_int16 unity = SWAPW(unitSize);
le_int16 probe = SWAPW(searchRange);
le_int16 extra = SWAPW(rangeShift);
TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph);
- const LookupSegment *entry = segments;
- const LookupSegment *trial = (const LookupSegment *) ((char *) entry + extra);
+ LEReferenceTo<LookupSegment> entry(base, success, segments);
+ LEReferenceTo<LookupSegment> trial(entry, success, extra);
+
+ if(LE_FAILURE(success)) return NULL;
if (SWAPW(trial->lastGlyph) <= ttGlyph) {
entry = trial;
}
- while (probe > unity) {
+ while (probe > unity && LE_SUCCESS(success)) {
probe >>= 1;
- trial = (const LookupSegment *) ((char *) entry + probe);
+ trial = entry; // copy
+ trial.addOffset(probe, success);
if (SWAPW(trial->lastGlyph) <= ttGlyph) {
entry = trial;
@@ -72,28 +76,29 @@
}
if (SWAPW(entry->firstGlyph) <= ttGlyph) {
- return entry;
+ return entry.getAlias();
}
return NULL;
}
-const LookupSingle *BinarySearchLookupTable::lookupSingle(const LookupSingle *entries, LEGlyphID glyph) const
+const LookupSingle *BinarySearchLookupTable::lookupSingle(const LETableReference &base, const LookupSingle *entries, LEGlyphID glyph, LEErrorCode &success) const
{
le_int16 unity = SWAPW(unitSize);
le_int16 probe = SWAPW(searchRange);
le_int16 extra = SWAPW(rangeShift);
TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph);
- const LookupSingle *entry = entries;
- const LookupSingle *trial = (const LookupSingle *) ((char *) entry + extra);
+ LEReferenceTo<LookupSingle> entry(base, success, entries);
+ LEReferenceTo<LookupSingle> trial(entry, success, extra);
if (SWAPW(trial->glyph) <= ttGlyph) {
entry = trial;
}
- while (probe > unity) {
+ while (probe > unity && LE_SUCCESS(success)) {
probe >>= 1;
- trial = (const LookupSingle *) ((char *) entry + probe);
+ trial = entry;
+ trial.addOffset(probe, success);
if (SWAPW(trial->glyph) <= ttGlyph) {
entry = trial;
@@ -101,7 +106,7 @@
}
if (SWAPW(entry->glyph) == ttGlyph) {
- return entry;
+ return entry.getAlias();
}
return NULL;
--- a/jdk/src/share/native/sun/font/layout/LookupTables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/LookupTables.h Wed Apr 17 02:53:02 2013 -0700
@@ -39,6 +39,7 @@
#include "LETypes.h"
#include "LayoutTables.h"
+#include "LETableReference.h"
U_NAMESPACE_BEGIN
@@ -79,30 +80,34 @@
le_int16 entrySelector;
le_int16 rangeShift;
- const LookupSegment *lookupSegment(const LookupSegment *segments, LEGlyphID glyph) const;
+ const LookupSegment *lookupSegment(const LETableReference &base, const LookupSegment *segments, LEGlyphID glyph, LEErrorCode &success) const;
- const LookupSingle *lookupSingle(const LookupSingle *entries, LEGlyphID glyph) const;
+ const LookupSingle *lookupSingle(const LETableReference &base, const LookupSingle *entries, LEGlyphID glyph, LEErrorCode &success) const;
};
struct SimpleArrayLookupTable : LookupTable
{
LookupValue valueArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(SimpleArrayLookupTable, valueArray)
struct SegmentSingleLookupTable : BinarySearchLookupTable
{
LookupSegment segments[ANY_NUMBER];
};
+LE_VAR_ARRAY(SegmentSingleLookupTable, segments)
struct SegmentArrayLookupTable : BinarySearchLookupTable
{
LookupSegment segments[ANY_NUMBER];
};
+LE_VAR_ARRAY(SegmentArrayLookupTable, segments)
struct SingleTableLookupTable : BinarySearchLookupTable
{
LookupSingle entries[ANY_NUMBER];
};
+LE_VAR_ARRAY(SingleTableLookupTable, entries)
struct TrimmedArrayLookupTable : LookupTable
{
@@ -110,6 +115,7 @@
TTGlyphID glyphCount;
LookupValue valueArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(TrimmedArrayLookupTable, valueArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/Lookups.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/Lookups.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -37,33 +37,35 @@
U_NAMESPACE_BEGIN
-const LookupTable *LookupListTable::getLookupTable(le_uint16 lookupTableIndex) const
+const LEReferenceTo<LookupTable> LookupListTable::getLookupTable(const LEReferenceTo<LookupListTable> &base, le_uint16 lookupTableIndex, LEErrorCode &success) const
{
- if (lookupTableIndex >= SWAPW(lookupCount)) {
- return 0;
- }
+ LEReferenceToArrayOf<Offset> lookupTableOffsetArrayRef(base, success, (const Offset*)&lookupTableOffsetArray, SWAPW(lookupCount));
- Offset lookupTableOffset = lookupTableOffsetArray[lookupTableIndex];
-
- return (const LookupTable *) ((char *) this + SWAPW(lookupTableOffset));
+ if(LE_FAILURE(success) || lookupTableIndex>lookupTableOffsetArrayRef.getCount()) {
+ return LEReferenceTo<LookupTable>();
+ } else {
+ return LEReferenceTo<LookupTable>(base, success, SWAPW(lookupTableOffsetArrayRef.getObject(lookupTableIndex, success)));
+ }
}
-const LookupSubtable *LookupTable::getLookupSubtable(le_uint16 subtableIndex) const
+const LEReferenceTo<LookupSubtable> LookupTable::getLookupSubtable(const LEReferenceTo<LookupTable> &base, le_uint16 subtableIndex, LEErrorCode &success) const
{
- if (subtableIndex >= SWAPW(subTableCount)) {
- return 0;
- }
+ LEReferenceToArrayOf<Offset> subTableOffsetArrayRef(base, success, (const Offset*)&subTableOffsetArray, SWAPW(subTableCount));
- Offset subtableOffset = subTableOffsetArray[subtableIndex];
-
- return (const LookupSubtable *) ((char *) this + SWAPW(subtableOffset));
+ if(LE_FAILURE(success) || subtableIndex>subTableOffsetArrayRef.getCount()) {
+ return LEReferenceTo<LookupSubtable>();
+ } else {
+ return LEReferenceTo<LookupSubtable>(base, success, SWAPW(subTableOffsetArrayRef.getObject(subtableIndex, success)));
+ }
}
-le_int32 LookupSubtable::getGlyphCoverage(Offset tableOffset, LEGlyphID glyphID) const
+le_int32 LookupSubtable::getGlyphCoverage(const LEReferenceTo<LookupSubtable> &base, Offset tableOffset, LEGlyphID glyphID, LEErrorCode &success) const
{
- const CoverageTable *coverageTable = (const CoverageTable *) ((char *) this + SWAPW(tableOffset));
+ const LEReferenceTo<CoverageTable> coverageTable(base, success, SWAPW(tableOffset));
- return coverageTable->getGlyphCoverage(glyphID);
+ if(LE_FAILURE(success)) return 0;
+
+ return coverageTable->getGlyphCoverage(glyphID);
}
U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/Lookups.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/Lookups.h Wed Apr 17 02:53:02 2013 -0700
@@ -58,9 +58,14 @@
le_uint16 subtableFormat;
Offset coverageTableOffset;
- inline le_int32 getGlyphCoverage(LEGlyphID glyphID) const;
+ inline le_int32 getGlyphCoverage(const LEReferenceTo<LookupSubtable> &base, LEGlyphID glyphID, LEErrorCode &success) const;
+
+ le_int32 getGlyphCoverage(const LEReferenceTo<LookupSubtable> &base, Offset tableOffset, LEGlyphID glyphID, LEErrorCode &success) const;
- le_int32 getGlyphCoverage(Offset tableOffset, LEGlyphID glyphID) const;
+ // convenience
+ inline le_int32 getGlyphCoverage(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
+
+ inline le_int32 getGlyphCoverage(const LETableReference &base, Offset tableOffset, LEGlyphID glyphID, LEErrorCode &success) const;
};
struct LookupTable
@@ -70,20 +75,32 @@
le_uint16 subTableCount;
Offset subTableOffsetArray[ANY_NUMBER];
- const LookupSubtable *getLookupSubtable(le_uint16 subtableIndex) const;
+ const LEReferenceTo<LookupSubtable> getLookupSubtable(const LEReferenceTo<LookupTable> &base, le_uint16 subtableIndex, LEErrorCode &success) const;
};
+LE_VAR_ARRAY(LookupTable, subTableOffsetArray)
struct LookupListTable
{
le_uint16 lookupCount;
Offset lookupTableOffsetArray[ANY_NUMBER];
- const LookupTable *getLookupTable(le_uint16 lookupTableIndex) const;
+ const LEReferenceTo<LookupTable> getLookupTable(const LEReferenceTo<LookupListTable> &base, le_uint16 lookupTableIndex, LEErrorCode &success) const;
};
+LE_VAR_ARRAY(LookupListTable, lookupTableOffsetArray)
+
+inline le_int32 LookupSubtable::getGlyphCoverage(const LEReferenceTo<LookupSubtable> &base, LEGlyphID glyphID, LEErrorCode &success) const
+{
+ return getGlyphCoverage(base, coverageTableOffset, glyphID, success);
+}
-inline le_int32 LookupSubtable::getGlyphCoverage(LEGlyphID glyphID) const
-{
- return getGlyphCoverage(coverageTableOffset, glyphID);
+inline le_int32 LookupSubtable::getGlyphCoverage(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const {
+ LEReferenceTo<LookupSubtable> thisRef(base, success, this);
+ return getGlyphCoverage(thisRef, glyphID, success);
+}
+
+inline le_int32 LookupSubtable::getGlyphCoverage(const LETableReference &base, Offset tableOffset, LEGlyphID glyphID, LEErrorCode &success) const {
+ LEReferenceTo<LookupSubtable> thisRef(base, success, this);
+ return getGlyphCoverage(thisRef, tableOffset, glyphID, success);
}
U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/MPreFixups.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MPreFixups.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 2002-2008 - All Rights Reserved
+ * (C) Copyright IBM Corp. 2002-2013 - All Rights Reserved
*
*/
@@ -65,9 +65,9 @@
}
}
-void MPreFixups::apply(LEGlyphStorage &glyphStorage, LEErrorCode& leSuccess)
+void MPreFixups::apply(LEGlyphStorage &glyphStorage, LEErrorCode& success)
{
- if (LE_FAILURE(leSuccess)) {
+ if (LE_FAILURE(success)) {
return;
}
--- a/jdk/src/share/native/sun/font/layout/MarkArrays.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MarkArrays.h Wed Apr 17 02:53:02 2013 -0700
@@ -57,6 +57,7 @@
le_int32 getMarkClass(LEGlyphID glyphID, le_int32 coverageIndex, const LEFontInstance *fontInstance,
LEPoint &anchor) const;
};
+LE_VAR_ARRAY(MarkArray, markRecordArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -51,10 +51,10 @@
return 0xFFFF;
}
-le_int32 MarkToBasePositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
+le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
- le_int32 markCoverage = getGlyphCoverage((LEGlyphID) markGlyph);
+ le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
if (markCoverage < 0) {
// markGlyph isn't a covered mark glyph
@@ -75,7 +75,7 @@
// FIXME: We probably don't want to find a base glyph before a previous ligature...
GlyphIterator baseIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreLigatures*/));
LEGlyphID baseGlyph = findBaseGlyph(&baseIterator);
- le_int32 baseCoverage = getBaseCoverage((LEGlyphID) baseGlyph);
+ le_int32 baseCoverage = getBaseCoverage(base, (LEGlyphID) baseGlyph, success);
const BaseArray *baseArray = (const BaseArray *) ((char *) this + SWAPW(baseArrayOffset));
le_uint16 baseCount = SWAPW(baseArray->baseRecordCount);
--- a/jdk/src/share/native/sun/font/layout/MarkToBasePosnSubtables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MarkToBasePosnSubtables.h Wed Apr 17 02:53:02 2013 -0700
@@ -48,7 +48,7 @@
struct MarkToBasePositioningSubtable : AttachmentPositioningSubtable
{
- le_int32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
+ le_int32 process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
LEGlyphID findBaseGlyph(GlyphIterator *glyphIterator) const;
};
@@ -56,12 +56,14 @@
{
Offset baseAnchorTableOffsetArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(BaseRecord, baseAnchorTableOffsetArray)
struct BaseArray
{
le_int16 baseRecordCount;
BaseRecord baseRecordArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(BaseArray, baseRecordArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/MarkToLigaturePosnSubtables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MarkToLigaturePosnSubtables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -50,10 +50,10 @@
return 0xFFFF;
}
-le_int32 MarkToLigaturePositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
+le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
- le_int32 markCoverage = getGlyphCoverage((LEGlyphID) markGlyph);
+ le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
if (markCoverage < 0) {
// markGlyph isn't a covered mark glyph
@@ -74,7 +74,7 @@
// FIXME: we probably don't want to find a ligature before a previous base glyph...
GlyphIterator ligatureIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreBaseGlyphs*/));
LEGlyphID ligatureGlyph = findLigatureGlyph(&ligatureIterator);
- le_int32 ligatureCoverage = getBaseCoverage((LEGlyphID) ligatureGlyph);
+ le_int32 ligatureCoverage = getBaseCoverage(base, (LEGlyphID) ligatureGlyph, success);
const LigatureArray *ligatureArray = (const LigatureArray *) ((char *) this + SWAPW(baseArrayOffset));
le_uint16 ligatureCount = SWAPW(ligatureArray->ligatureCount);
--- a/jdk/src/share/native/sun/font/layout/MarkToLigaturePosnSubtables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MarkToLigaturePosnSubtables.h Wed Apr 17 02:53:02 2013 -0700
@@ -48,7 +48,7 @@
struct MarkToLigaturePositioningSubtable : AttachmentPositioningSubtable
{
- le_int32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
+ le_int32 process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
LEGlyphID findLigatureGlyph(GlyphIterator *glyphIterator) const;
};
@@ -56,18 +56,21 @@
{
Offset ligatureAnchorTableOffsetArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(ComponentRecord, ligatureAnchorTableOffsetArray)
struct LigatureAttachTable
{
le_uint16 componentCount;
ComponentRecord componentRecordArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(LigatureAttachTable, componentRecordArray)
struct LigatureArray
{
le_uint16 ligatureCount;
Offset ligatureAttachTableOffsetArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(LigatureArray, ligatureAttachTableOffsetArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/MarkToMarkPosnSubtables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MarkToMarkPosnSubtables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -51,10 +51,10 @@
return 0xFFFF;
}
-le_int32 MarkToMarkPositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
+le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
- le_int32 markCoverage = getGlyphCoverage((LEGlyphID) markGlyph);
+ le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
if (markCoverage < 0) {
// markGlyph isn't a covered mark glyph
@@ -74,7 +74,7 @@
GlyphIterator mark2Iterator(*glyphIterator);
LEGlyphID mark2Glyph = findMark2Glyph(&mark2Iterator);
- le_int32 mark2Coverage = getBaseCoverage((LEGlyphID) mark2Glyph);
+ le_int32 mark2Coverage = getBaseCoverage(base, (LEGlyphID) mark2Glyph, success);
const Mark2Array *mark2Array = (const Mark2Array *) ((char *) this + SWAPW(baseArrayOffset));
le_uint16 mark2Count = SWAPW(mark2Array->mark2RecordCount);
--- a/jdk/src/share/native/sun/font/layout/MarkToMarkPosnSubtables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MarkToMarkPosnSubtables.h Wed Apr 17 02:53:02 2013 -0700
@@ -48,7 +48,7 @@
struct MarkToMarkPositioningSubtable : AttachmentPositioningSubtable
{
- le_int32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
+ le_int32 process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
LEGlyphID findMark2Glyph(GlyphIterator *glyphIterator) const;
};
@@ -56,12 +56,14 @@
{
Offset mark2AnchorTableOffsetArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(Mark2Record, mark2AnchorTableOffsetArray)
struct Mark2Array
{
le_uint16 mark2RecordCount;
Mark2Record mark2RecordArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(Mark2Array, mark2RecordArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/MorphStateTables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MorphStateTables.h Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -49,5 +49,10 @@
StateTableHeader stHeader;
};
+struct MorphStateTableHeader2 : MorphSubtableHeader2
+{
+ StateTableHeader2 stHeader;
+};
+
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/MorphTables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MorphTables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -44,61 +44,61 @@
U_NAMESPACE_BEGIN
-void MorphTableHeader::process(LEGlyphStorage &glyphStorage) const
+void MorphTableHeader::process(const LETableReference &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const
{
- const ChainHeader *chainHeader = chains;
- le_uint32 chainCount = SWAPL(this->nChains);
+ le_uint32 chainCount = SWAPL(this->nChains);
+ LEReferenceTo<ChainHeader> chainHeader(base, success, chains); // moving header
+ LEReferenceToArrayOf<ChainHeader> chainHeaderArray(base, success, chains, chainCount);
le_uint32 chain;
- for (chain = 0; chain < chainCount; chain += 1) {
+ for (chain = 0; LE_SUCCESS(success) && (chain < chainCount); chain += 1) {
FeatureFlags defaultFlags = SWAPL(chainHeader->defaultFlags);
le_uint32 chainLength = SWAPL(chainHeader->chainLength);
le_int16 nFeatureEntries = SWAPW(chainHeader->nFeatureEntries);
le_int16 nSubtables = SWAPW(chainHeader->nSubtables);
- const MorphSubtableHeader *subtableHeader =
- (const MorphSubtableHeader *)&chainHeader->featureTable[nFeatureEntries];
+ LEReferenceTo<MorphSubtableHeader> subtableHeader =
+ LEReferenceTo<MorphSubtableHeader>(chainHeader,success, &(chainHeader->featureTable[nFeatureEntries]));
le_int16 subtable;
- for (subtable = 0; subtable < nSubtables; subtable += 1) {
+ for (subtable = 0; LE_SUCCESS(success) && (subtable < nSubtables); subtable += 1) {
le_int16 length = SWAPW(subtableHeader->length);
SubtableCoverage coverage = SWAPW(subtableHeader->coverage);
FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
// should check coverage more carefully...
- if ((coverage & scfVertical) == 0 && (subtableFeatures & defaultFlags) != 0) {
- subtableHeader->process(glyphStorage);
+ if ((coverage & scfVertical) == 0 && (subtableFeatures & defaultFlags) != 0 && LE_SUCCESS(success)) {
+ subtableHeader->process(subtableHeader, glyphStorage, success);
}
- subtableHeader = (const MorphSubtableHeader *) ((char *)subtableHeader + length);
+ subtableHeader.addOffset(length, success);
}
-
- chainHeader = (const ChainHeader *)((char *)chainHeader + chainLength);
+ chainHeader.addOffset(chainLength, success);
}
}
-void MorphSubtableHeader::process(LEGlyphStorage &glyphStorage) const
+void MorphSubtableHeader::process(const LEReferenceTo<MorphSubtableHeader> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const
{
SubtableProcessor *processor = NULL;
switch (SWAPW(coverage) & scfTypeMask)
{
case mstIndicRearrangement:
- processor = new IndicRearrangementProcessor(this);
+ processor = new IndicRearrangementProcessor(base, success);
break;
case mstContextualGlyphSubstitution:
- processor = new ContextualGlyphSubstitutionProcessor(this);
+ processor = new ContextualGlyphSubstitutionProcessor(base, success);
break;
case mstLigatureSubstitution:
- processor = new LigatureSubstitutionProcessor(this);
+ processor = new LigatureSubstitutionProcessor(base, success);
break;
case mstReservedUnused:
break;
case mstNonContextualGlyphSubstitution:
- processor = NonContextualGlyphSubstitutionProcessor::createInstance(this);
+ processor = NonContextualGlyphSubstitutionProcessor::createInstance(base, success);
break;
/*
@@ -112,8 +112,10 @@
}
if (processor != NULL) {
- processor->process(glyphStorage);
- delete processor;
+ if(LE_SUCCESS(success)) {
+ processor->process(glyphStorage, success);
+ }
+ delete processor;
}
}
--- a/jdk/src/share/native/sun/font/layout/MorphTables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MorphTables.h Wed Apr 17 02:53:02 2013 -0700
@@ -39,6 +39,7 @@
#include "LETypes.h"
#include "LayoutTables.h"
+#include "LETableReference.h"
U_NAMESPACE_BEGIN
@@ -65,6 +66,7 @@
le_int16 nSubtables;
FeatureTableEntry featureTable[ANY_NUMBER];
};
+LE_VAR_ARRAY(ChainHeader, featureTable)
struct MorphTableHeader
{
@@ -72,10 +74,12 @@
le_uint32 nChains;
ChainHeader chains[ANY_NUMBER];
- void process(LEGlyphStorage &glyphStorage) const;
+ void process(const LETableReference& base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const;
};
+LE_VAR_ARRAY(MorphTableHeader, chains)
typedef le_int16 SubtableCoverage;
+typedef le_uint32 SubtableCoverage2;
enum SubtableCoverageFlags
{
@@ -102,7 +106,305 @@
SubtableCoverage coverage;
FeatureFlags subtableFeatures;
- void process(LEGlyphStorage &glyphStorage) const;
+ void process(const LEReferenceTo<MorphSubtableHeader> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const;
+};
+
+enum SubtableCoverageFlags2
+{
+ scfVertical2 = 0x80000000,
+ scfReverse2 = 0x40000000,
+ scfIgnoreVt2 = 0x20000000,
+ scfReserved2 = 0x1FFFFF00,
+ scfTypeMask2 = 0x000000FF
+};
+
+struct MorphSubtableHeader2
+{
+ le_uint32 length;
+ SubtableCoverage2 coverage;
+ FeatureFlags subtableFeatures;
+
+ void process(const LEReferenceTo<MorphSubtableHeader2> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const;
+};
+
+struct ChainHeader2
+{
+ FeatureFlags defaultFlags;
+ le_uint32 chainLength;
+ le_uint32 nFeatureEntries;
+ le_uint32 nSubtables;
+ FeatureTableEntry featureTable[ANY_NUMBER];
+};
+LE_VAR_ARRAY(ChainHeader2, featureTable)
+
+struct MorphTableHeader2
+{
+ le_int32 version;
+ le_uint32 nChains;
+ ChainHeader2 chains[ANY_NUMBER];
+
+ void process(const LEReferenceTo<MorphTableHeader2> &base, LEGlyphStorage &glyphStorage, le_int32 typoFlags, LEErrorCode &success) const;
+};
+LE_VAR_ARRAY(MorphTableHeader2, chains)
+
+/*
+ * AAT Font Features
+ * source: https://developer.apple.com/fonts/registry/
+ * (plus addition from ATS/SFNTLayoutTypes.h)
+ */
+
+enum {
+
+ allTypographicFeaturesType = 0,
+
+ allTypeFeaturesOnSelector = 0,
+ allTypeFeaturesOffSelector = 1,
+
+ ligaturesType = 1,
+
+ requiredLigaturesOnSelector = 0,
+ requiredLigaturesOffSelector = 1,
+ commonLigaturesOnSelector = 2,
+ commonLigaturesOffSelector = 3,
+ rareLigaturesOnSelector = 4,
+ rareLigaturesOffSelector = 5,
+ logosOnSelector = 6,
+ logosOffSelector = 7,
+ rebusPicturesOnSelector = 8,
+ rebusPicturesOffSelector = 9,
+ diphthongLigaturesOnSelector = 10,
+ diphthongLigaturesOffSelector = 11,
+ squaredLigaturesOnSelector = 12,
+ squaredLigaturesOffSelector = 13,
+ abbrevSquaredLigaturesOnSelector = 14,
+ abbrevSquaredLigaturesOffSelector = 15,
+ symbolLigaturesOnSelector = 16,
+ symbolLigaturesOffSelector = 17,
+ contextualLigaturesOnSelector = 18,
+ contextualLigaturesOffSelector = 19,
+ historicalLigaturesOnSelector = 20,
+ historicalLigaturesOffSelector = 21,
+
+ cursiveConnectionType = 2,
+
+ unconnectedSelector = 0,
+ partiallyConnectedSelector = 1,
+ cursiveSelector = 2,
+
+ letterCaseType = 3,
+
+ upperAndLowerCaseSelector = 0,
+ allCapsSelector = 1,
+ allLowerCaseSelector = 2,
+ smallCapsSelector = 3,
+ initialCapsSelector = 4,
+ initialCapsAndSmallCapsSelector = 5,
+
+ verticalSubstitutionType = 4,
+
+ substituteVerticalFormsOnSelector = 0,
+ substituteVerticalFormsOffSelector = 1,
+
+ linguisticRearrangementType = 5,
+
+ linguisticRearrangementOnSelector = 0,
+ linguisticRearrangementOffSelector = 1,
+
+ numberSpacingType = 6,
+
+ monospacedNumbersSelector = 0,
+ proportionalNumbersSelector = 1,
+
+ /*
+ appleReserved1Type = 7,
+ */
+
+ smartSwashType = 8,
+
+ wordInitialSwashesOnSelector = 0,
+ wordInitialSwashesOffSelector = 1,
+ wordFinalSwashesOnSelector = 2,
+ wordFinalSwashesOffSelector = 3,
+ lineInitialSwashesOnSelector = 4,
+ lineInitialSwashesOffSelector = 5,
+ lineFinalSwashesOnSelector = 6,
+ lineFinalSwashesOffSelector = 7,
+ nonFinalSwashesOnSelector = 8,
+ nonFinalSwashesOffSelector = 9,
+
+ diacriticsType = 9,
+
+ showDiacriticsSelector = 0,
+ hideDiacriticsSelector = 1,
+ decomposeDiacriticsSelector = 2,
+
+ verticalPositionType = 10,
+
+ normalPositionSelector = 0,
+ superiorsSelector = 1,
+ inferiorsSelector = 2,
+ ordinalsSelector = 3,
+
+ fractionsType = 11,
+
+ noFractionsSelector = 0,
+ verticalFractionsSelector = 1,
+ diagonalFractionsSelector = 2,
+
+ /*
+ appleReserved2Type = 12,
+ */
+
+ overlappingCharactersType = 13,
+
+ preventOverlapOnSelector = 0,
+ preventOverlapOffSelector = 1,
+
+ typographicExtrasType = 14,
+
+ hyphensToEmDashOnSelector = 0,
+ hyphensToEmDashOffSelector = 1,
+ hyphenToEnDashOnSelector = 2,
+ hyphenToEnDashOffSelector = 3,
+ unslashedZeroOnSelector = 4,
+ slashedZeroOffSelector = 4,
+ unslashedZeroOffSelector = 5,
+ slashedZeroOnSelector = 5,
+ formInterrobangOnSelector = 6,
+ formInterrobangOffSelector = 7,
+ smartQuotesOnSelector = 8,
+ smartQuotesOffSelector = 9,
+ periodsToEllipsisOnSelector = 10,
+ periodsToEllipsisOffSelector = 11,
+
+ mathematicalExtrasType = 15,
+
+ hyphenToMinusOnSelector = 0,
+ hyphenToMinusOffSelector = 1,
+ asteriskToMultiplyOnSelector = 2,
+ asteriskToMultiplyOffSelector = 3,
+ slashToDivideOnSelector = 4,
+ slashToDivideOffSelector = 5,
+ inequalityLigaturesOnSelector = 6,
+ inequalityLigaturesOffSelector = 7,
+ exponentsOnSelector = 8,
+ exponentsOffSelector = 9,
+
+ ornamentSetsType = 16,
+
+ noOrnamentsSelector = 0,
+ dingbatsSelector = 1,
+ piCharactersSelector = 2,
+ fleuronsSelector = 3,
+ decorativeBordersSelector = 4,
+ internationalSymbolsSelector = 5,
+ mathSymbolsSelector = 6,
+
+ characterAlternativesType = 17,
+
+ noAlternatesSelector = 0,
+
+ designComplexityType = 18,
+
+ designLevel1Selector = 0,
+ designLevel2Selector = 1,
+ designLevel3Selector = 2,
+ designLevel4Selector = 3,
+ designLevel5Selector = 4,
+ designLevel6Selector = 5,
+ designLevel7Selector = 6,
+
+ styleOptionsType = 19,
+
+ noStyleOptionsSelector = 0,
+ displayTextSelector = 1,
+ engravedTextSelector = 2,
+ illuminatedCapsSelector = 3,
+ titlingCapsSelector = 4,
+ tallCapsSelector = 5,
+
+ characterShapeType = 20,
+
+ traditionalCharactersSelector = 0,
+ simplifiedCharactersSelector = 1,
+ jis1978CharactersSelector = 2,
+ jis1983CharactersSelector = 3,
+ jis1990CharactersSelector = 4,
+ traditionalAltOneSelector = 5,
+ traditionalAltTwoSelector = 6,
+ traditionalAltThreeSelector = 7,
+ traditionalAltFourSelector = 8,
+ traditionalAltFiveSelector = 9,
+ expertCharactersSelector = 10,
+
+ numberCaseType = 21,
+
+ lowerCaseNumbersSelector = 0,
+ upperCaseNumbersSelector = 1,
+
+ textSpacingType = 22,
+
+ proportionalTextSelector = 0,
+ monospacedTextSelector = 1,
+ halfWidthTextSelector = 2,
+ normallySpacedTextSelector = 3,
+
+ transliterationType = 23,
+
+ noTransliterationSelector = 0,
+ hanjaToHangulSelector = 1,
+ hiraganaToKatakanaSelector = 2,
+ katakanaToHiraganaSelector = 3,
+ kanaToRomanizationSelector = 4,
+ romanizationToHiraganaSelector = 5,
+ romanizationToKatakanaSelector = 6,
+ hanjaToHangulAltOneSelector = 7,
+ hanjaToHangulAltTwoSelector = 8,
+ hanjaToHangulAltThreeSelector = 9,
+
+ annotationType = 24,
+
+ noAnnotationSelector = 0,
+ boxAnnotationSelector = 1,
+ roundedBoxAnnotationSelector = 2,
+ circleAnnotationSelector = 3,
+ invertedCircleAnnotationSelector = 4,
+ parenthesisAnnotationSelector = 5,
+ periodAnnotationSelector = 6,
+ romanNumeralAnnotationSelector = 7,
+ diamondAnnotationSelector = 8,
+
+ kanaSpacingType = 25,
+
+ fullWidthKanaSelector = 0,
+ proportionalKanaSelector = 1,
+
+ ideographicSpacingType = 26,
+
+ fullWidthIdeographsSelector = 0,
+ proportionalIdeographsSelector = 1,
+
+ cjkRomanSpacingType = 103,
+
+ halfWidthCJKRomanSelector = 0,
+ proportionalCJKRomanSelector = 1,
+ defaultCJKRomanSelector = 2,
+ fullWidthCJKRomanSelector = 3,
+
+ rubyKanaType = 28,
+
+ rubyKanaOnSelector = 2,
+ rubyKanaOffSelector = 3,
+
+/* The following types are provided for compatibility; note that
+ their use is deprecated. */
+
+ adobeCharacterSpacingType = 100, /* prefer 22 */
+ adobeKanaSpacingType = 101, /* prefer 25 */
+ adobeKanjiSpacingType = 102, /* prefer 26 */
+ adobeSquareLigatures = 104, /* prefer 1 */
+
+ lastFeatureType = -1
};
U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/MorphTables2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,248 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ * (C) Copyright IBM Corp. and others 1998 - 2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "LayoutTables.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "IndicRearrangementProcessor2.h"
+#include "ContextualGlyphSubstProc2.h"
+#include "LigatureSubstProc2.h"
+#include "NonContextualGlyphSubstProc2.h"
+#include "ContextualGlyphInsertionProc2.h"
+#include "LEGlyphStorage.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+void MorphTableHeader2::process(const LEReferenceTo<MorphTableHeader2> &base, LEGlyphStorage &glyphStorage,
+ le_int32 typoFlags, LEErrorCode &success) const
+{
+ if(LE_FAILURE(success)) return;
+
+ le_uint32 chainCount = SWAPL(this->nChains);
+ LEReferenceTo<ChainHeader2> chainHeader(base, success, &chains[0]);
+ /* chainHeader and subtableHeader are implemented as a moving pointer rather than an array dereference
+ * to (slightly) reduce code churn. However, must be careful to preincrement them the 2nd time through.
+ * We don't want to increment them at the end of the loop, as that would attempt to dereference
+ * out of range memory.
+ */
+ le_uint32 chain;
+
+ for (chain = 0; LE_SUCCESS(success) && (chain < chainCount); chain++) {
+ if (chain>0) {
+ le_uint32 chainLength = SWAPL(chainHeader->chainLength);
+ chainHeader.addOffset(chainLength, success); // Don't increment the first time
+ }
+ FeatureFlags flag = SWAPL(chainHeader->defaultFlags);
+ le_uint32 nFeatureEntries = SWAPL(chainHeader->nFeatureEntries);
+ le_uint32 nSubtables = SWAPL(chainHeader->nSubtables);
+ LEReferenceTo<MorphSubtableHeader2> subtableHeader(chainHeader,
+ success, (const MorphSubtableHeader2 *)&chainHeader->featureTable[nFeatureEntries]);
+ le_uint32 subtable;
+ if(LE_FAILURE(success)) break; // malformed table
+
+ if (typoFlags != 0) {
+ le_uint32 featureEntry;
+ LEReferenceToArrayOf<FeatureTableEntry> featureTableRef(chainHeader, success, &chainHeader->featureTable[0], nFeatureEntries);
+ if(LE_FAILURE(success)) break;
+ // Feature subtables
+ for (featureEntry = 0; featureEntry < nFeatureEntries; featureEntry++) {
+ const FeatureTableEntry &featureTableEntry = featureTableRef(featureEntry, success);
+ le_int16 featureType = SWAPW(featureTableEntry.featureType);
+ le_int16 featureSetting = SWAPW(featureTableEntry.featureSetting);
+ le_uint32 enableFlags = SWAPL(featureTableEntry.enableFlags);
+ le_uint32 disableFlags = SWAPL(featureTableEntry.disableFlags);
+ switch (featureType) {
+ case ligaturesType:
+ if ((typoFlags & LE_Ligatures_FEATURE_ENUM ) && (featureSetting ^ 0x1)){
+ flag &= disableFlags;
+ flag |= enableFlags;
+ } else {
+ if (((typoFlags & LE_RLIG_FEATURE_FLAG) && featureSetting == requiredLigaturesOnSelector) ||
+ ((typoFlags & LE_CLIG_FEATURE_FLAG) && featureSetting == contextualLigaturesOnSelector) ||
+ ((typoFlags & LE_HLIG_FEATURE_FLAG) && featureSetting == historicalLigaturesOnSelector) ||
+ ((typoFlags & LE_LIGA_FEATURE_FLAG) && featureSetting == commonLigaturesOnSelector)) {
+ flag &= disableFlags;
+ flag |= enableFlags;
+ }
+ }
+ break;
+ case letterCaseType:
+ if ((typoFlags & LE_SMCP_FEATURE_FLAG) && featureSetting == smallCapsSelector) {
+ flag &= disableFlags;
+ flag |= enableFlags;
+ }
+ break;
+ case verticalSubstitutionType:
+ break;
+ case linguisticRearrangementType:
+ break;
+ case numberSpacingType:
+ break;
+ case smartSwashType:
+ if ((typoFlags & LE_SWSH_FEATURE_FLAG) && (featureSetting ^ 0x1)){
+ flag &= disableFlags;
+ flag |= enableFlags;
+ }
+ break;
+ case diacriticsType:
+ break;
+ case verticalPositionType:
+ break;
+ case fractionsType:
+ if (((typoFlags & LE_FRAC_FEATURE_FLAG) && featureSetting == diagonalFractionsSelector) ||
+ ((typoFlags & LE_AFRC_FEATURE_FLAG) && featureSetting == verticalFractionsSelector)) {
+ flag &= disableFlags;
+ flag |= enableFlags;
+ } else {
+ flag &= disableFlags;
+ }
+ break;
+ case typographicExtrasType:
+ if ((typoFlags & LE_ZERO_FEATURE_FLAG) && featureSetting == slashedZeroOnSelector) {
+ flag &= disableFlags;
+ flag |= enableFlags;
+ }
+ break;
+ case mathematicalExtrasType:
+ break;
+ case ornamentSetsType:
+ break;
+ case characterAlternativesType:
+ break;
+ case designComplexityType:
+ if (((typoFlags & LE_SS01_FEATURE_FLAG) && featureSetting == designLevel1Selector) ||
+ ((typoFlags & LE_SS02_FEATURE_FLAG) && featureSetting == designLevel2Selector) ||
+ ((typoFlags & LE_SS03_FEATURE_FLAG) && featureSetting == designLevel3Selector) ||
+ ((typoFlags & LE_SS04_FEATURE_FLAG) && featureSetting == designLevel4Selector) ||
+ ((typoFlags & LE_SS05_FEATURE_FLAG) && featureSetting == designLevel5Selector) ||
+ ((typoFlags & LE_SS06_FEATURE_FLAG) && featureSetting == designLevel6Selector) ||
+ ((typoFlags & LE_SS07_FEATURE_FLAG) && featureSetting == designLevel7Selector)) {
+
+ flag &= disableFlags;
+ flag |= enableFlags;
+ }
+ break;
+ case styleOptionsType:
+ break;
+ case characterShapeType:
+ break;
+ case numberCaseType:
+ break;
+ case textSpacingType:
+ break;
+ case transliterationType:
+ break;
+ case annotationType:
+ if ((typoFlags & LE_NALT_FEATURE_FLAG) && featureSetting == circleAnnotationSelector) {
+ flag &= disableFlags;
+ flag |= enableFlags;
+ }
+ break;
+ case kanaSpacingType:
+ break;
+ case ideographicSpacingType:
+ break;
+ case rubyKanaType:
+ if ((typoFlags & LE_RUBY_FEATURE_FLAG) && featureSetting == rubyKanaOnSelector) {
+ flag &= disableFlags;
+ flag |= enableFlags;
+ }
+ break;
+ case cjkRomanSpacingType:
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ for (subtable = 0; LE_SUCCESS(success) && subtable < nSubtables; subtable++) {
+ if(subtable>0) {
+ le_uint32 length = SWAPL(subtableHeader->length);
+ subtableHeader.addOffset(length, success); // Don't addOffset for the last entry.
+ }
+ le_uint32 coverage = SWAPL(subtableHeader->coverage);
+ FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
+ // should check coverage more carefully...
+ if (((coverage & scfIgnoreVt2) || !(coverage & scfVertical2)) && (subtableFeatures & flag) != 0) {
+ subtableHeader->process(subtableHeader, glyphStorage, success);
+ }
+ }
+ }
+}
+
+void MorphSubtableHeader2::process(const LEReferenceTo<MorphSubtableHeader2> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const
+{
+ SubtableProcessor2 *processor = NULL;
+
+ switch (SWAPL(coverage) & scfTypeMask2)
+ {
+ case mstIndicRearrangement:
+ processor = new IndicRearrangementProcessor2(base, success);
+ break;
+
+ case mstContextualGlyphSubstitution:
+ processor = new ContextualGlyphSubstitutionProcessor2(base, success);
+ break;
+
+ case mstLigatureSubstitution:
+ processor = new LigatureSubstitutionProcessor2(base, success);
+ break;
+
+ case mstReservedUnused:
+ break;
+
+ case mstNonContextualGlyphSubstitution:
+ processor = NonContextualGlyphSubstitutionProcessor2::createInstance(base, success);
+ break;
+
+
+ case mstContextualGlyphInsertion:
+ processor = new ContextualGlyphInsertionProcessor2(base, success);
+ break;
+
+ default:
+ return;
+ break; /*NOTREACHED*/
+ }
+
+ if (processor != NULL) {
+ processor->process(glyphStorage, success);
+ delete processor;
+ } else {
+ if(LE_SUCCESS(success)) {
+ success = LE_MEMORY_ALLOCATION_ERROR; // because ptr is null and we didn't break out.
+ }
+ }
+}
+
+U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/MultipleSubstSubtables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MultipleSubstSubtables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -39,7 +39,7 @@
U_NAMESPACE_BEGIN
-le_uint32 MultipleSubstitutionSubtable::process(GlyphIterator *glyphIterator, LEErrorCode& success, const LEGlyphFilter *filter) const
+le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, LEErrorCode& success, const LEGlyphFilter *filter) const
{
if (LE_FAILURE(success)) {
return 0;
@@ -58,7 +58,7 @@
return 0;
}
- le_int32 coverageIndex = getGlyphCoverage(glyph);
+ le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
le_uint16 seqCount = SWAPW(sequenceCount);
if (coverageIndex >= 0 && coverageIndex < seqCount) {
--- a/jdk/src/share/native/sun/font/layout/MultipleSubstSubtables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/MultipleSubstSubtables.h Wed Apr 17 02:53:02 2013 -0700
@@ -50,14 +50,16 @@
le_uint16 glyphCount;
TTGlyphID substituteArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(SequenceTable, substituteArray)
struct MultipleSubstitutionSubtable : GlyphSubstitutionSubtable
{
le_uint16 sequenceCount;
Offset sequenceTableOffsetArray[ANY_NUMBER];
- le_uint32 process(GlyphIterator *glyphIterator, LEErrorCode& success, const LEGlyphFilter *filter = NULL) const;
+ le_uint32 process(const LETableReference &base, GlyphIterator *glyphIterator, LEErrorCode& success, const LEGlyphFilter *filter = NULL) const;
};
+LE_VAR_ARRAY(MultipleSubstitutionSubtable, sequenceTableOffsetArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/NonContextualGlyphSubst.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/NonContextualGlyphSubst.h Wed Apr 17 02:53:02 2013 -0700
@@ -26,7 +26,7 @@
/*
*
*
- * (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -50,6 +50,11 @@
LookupTable table;
};
+struct NonContextualGlyphSubstitutionHeader2 : MorphSubtableHeader2
+{
+ LookupTable table;
+};
+
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/NonContextualGlyphSubstProc.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/NonContextualGlyphSubstProc.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -47,8 +47,8 @@
{
}
-NonContextualGlyphSubstitutionProcessor::NonContextualGlyphSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader)
- : SubtableProcessor(morphSubtableHeader)
+NonContextualGlyphSubstitutionProcessor::NonContextualGlyphSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
+ : SubtableProcessor(morphSubtableHeader, success)
{
}
@@ -56,26 +56,27 @@
{
}
-SubtableProcessor *NonContextualGlyphSubstitutionProcessor::createInstance(const MorphSubtableHeader *morphSubtableHeader)
+SubtableProcessor *NonContextualGlyphSubstitutionProcessor::createInstance(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
{
- const NonContextualGlyphSubstitutionHeader *header = (const NonContextualGlyphSubstitutionHeader *) morphSubtableHeader;
+ LEReferenceTo<NonContextualGlyphSubstitutionHeader> header(morphSubtableHeader, success);
- switch (SWAPW(header->table.format))
- {
+ if(LE_FAILURE(success)) return NULL;
+
+ switch (SWAPW(header->table.format)) {
case ltfSimpleArray:
- return new SimpleArrayProcessor(morphSubtableHeader);
+ return new SimpleArrayProcessor(morphSubtableHeader, success);
case ltfSegmentSingle:
- return new SegmentSingleProcessor(morphSubtableHeader);
+ return new SegmentSingleProcessor(morphSubtableHeader, success);
case ltfSegmentArray:
- return new SegmentArrayProcessor(morphSubtableHeader);
+ return new SegmentArrayProcessor(morphSubtableHeader, success);
case ltfSingleTable:
- return new SingleTableProcessor(morphSubtableHeader);
+ return new SingleTableProcessor(morphSubtableHeader, success);
case ltfTrimmedArray:
- return new TrimmedArrayProcessor(morphSubtableHeader);
+ return new TrimmedArrayProcessor(morphSubtableHeader, success);
default:
return NULL;
--- a/jdk/src/share/native/sun/font/layout/NonContextualGlyphSubstProc.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/NonContextualGlyphSubstProc.h Wed Apr 17 02:53:02 2013 -0700
@@ -49,13 +49,13 @@
class NonContextualGlyphSubstitutionProcessor : public SubtableProcessor
{
public:
- virtual void process(LEGlyphStorage &glyphStorage) = 0;
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success) = 0;
- static SubtableProcessor *createInstance(const MorphSubtableHeader *morphSubtableHeader);
+ static SubtableProcessor *createInstance(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
protected:
NonContextualGlyphSubstitutionProcessor();
- NonContextualGlyphSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader);
+ NonContextualGlyphSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &status);
virtual ~NonContextualGlyphSubstitutionProcessor();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/NonContextualGlyphSubstProc2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "NonContextualGlyphSubst.h"
+#include "NonContextualGlyphSubstProc2.h"
+#include "SimpleArrayProcessor2.h"
+#include "SegmentSingleProcessor2.h"
+#include "SegmentArrayProcessor2.h"
+#include "SingleTableProcessor2.h"
+#include "TrimmedArrayProcessor2.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+NonContextualGlyphSubstitutionProcessor2::NonContextualGlyphSubstitutionProcessor2()
+{
+}
+
+NonContextualGlyphSubstitutionProcessor2::NonContextualGlyphSubstitutionProcessor2(
+ const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+ : SubtableProcessor2(morphSubtableHeader, success)
+{
+}
+
+NonContextualGlyphSubstitutionProcessor2::~NonContextualGlyphSubstitutionProcessor2()
+{
+}
+
+SubtableProcessor2 *NonContextualGlyphSubstitutionProcessor2::createInstance(
+ const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+{
+ const LEReferenceTo<NonContextualGlyphSubstitutionHeader2> header(morphSubtableHeader, success);
+ if(LE_FAILURE(success)) return NULL;
+
+ switch (SWAPW(header->table.format))
+ {
+ case ltfSimpleArray:
+ return new SimpleArrayProcessor2(morphSubtableHeader, success);
+
+ case ltfSegmentSingle:
+ return new SegmentSingleProcessor2(morphSubtableHeader, success);
+
+ case ltfSegmentArray:
+ return new SegmentArrayProcessor2(morphSubtableHeader, success);
+
+ case ltfSingleTable:
+ return new SingleTableProcessor2(morphSubtableHeader, success);
+
+ case ltfTrimmedArray:
+ return new TrimmedArrayProcessor2(morphSubtableHeader, success);
+
+ default:
+ return NULL;
+ }
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/NonContextualGlyphSubstProc2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __NONCONTEXTUALGLYPHSUBSTITUTIONPROCESSOR2_H
+#define __NONCONTEXTUALGLYPHSUBSTITUTIONPROCESSOR2_H
+
+/**
+ * \file
+ * \internal
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "NonContextualGlyphSubst.h"
+
+U_NAMESPACE_BEGIN
+
+class LEGlyphStorage;
+
+class NonContextualGlyphSubstitutionProcessor2 : public SubtableProcessor2
+{
+public:
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success) = 0;
+
+ static SubtableProcessor2 *createInstance(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+
+protected:
+ NonContextualGlyphSubstitutionProcessor2();
+ NonContextualGlyphSubstitutionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+
+ virtual ~NonContextualGlyphSubstitutionProcessor2();
+
+private:
+ NonContextualGlyphSubstitutionProcessor2(const NonContextualGlyphSubstitutionProcessor2 &other); // forbid copying of this class
+ NonContextualGlyphSubstitutionProcessor2 &operator=(const NonContextualGlyphSubstitutionProcessor2 &other); // forbid copying of this class
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -26,7 +26,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2010 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -64,11 +64,27 @@
#define loclFeatureTag LE_LOCL_FEATURE_TAG
#define caltFeatureTag LE_CALT_FEATURE_TAG
-// 'dlig' not used at the moment
-#define dligFeatureTag 0x646C6967
+#define dligFeatureTag LE_DLIG_FEATURE_TAG
+#define rligFeatureTag LE_RLIG_FEATURE_TAG
+#define paltFeatureTag LE_PALT_FEATURE_TAG
-// 'palt'
-#define paltFeatureTag 0x70616C74
+#define hligFeatureTag LE_HLIG_FEATURE_TAG
+#define smcpFeatureTag LE_SMCP_FEATURE_TAG
+#define fracFeatureTag LE_FRAC_FEATURE_TAG
+#define afrcFeatureTag LE_AFRC_FEATURE_TAG
+#define zeroFeatureTag LE_ZERO_FEATURE_TAG
+#define swshFeatureTag LE_SWSH_FEATURE_TAG
+#define cswhFeatureTag LE_CSWH_FEATURE_TAG
+#define saltFeatureTag LE_SALT_FEATURE_TAG
+#define naltFeatureTag LE_NALT_FEATURE_TAG
+#define rubyFeatureTag LE_RUBY_FEATURE_TAG
+#define ss01FeatureTag LE_SS01_FEATURE_TAG
+#define ss02FeatureTag LE_SS02_FEATURE_TAG
+#define ss03FeatureTag LE_SS03_FEATURE_TAG
+#define ss04FeatureTag LE_SS04_FEATURE_TAG
+#define ss05FeatureTag LE_SS05_FEATURE_TAG
+#define ss06FeatureTag LE_SS06_FEATURE_TAG
+#define ss07FeatureTag LE_SS07_FEATURE_TAG
#define ccmpFeatureMask 0x80000000UL
#define ligaFeatureMask 0x40000000UL
@@ -80,60 +96,146 @@
#define loclFeatureMask 0x01000000UL
#define caltFeatureMask 0x00800000UL
+#define dligFeatureMask 0x00400000UL
+#define rligFeatureMask 0x00200000UL
+#define hligFeatureMask 0x00100000UL
+#define smcpFeatureMask 0x00080000UL
+#define fracFeatureMask 0x00040000UL
+#define afrcFeatureMask 0x00020000UL
+#define zeroFeatureMask 0x00010000UL
+#define swshFeatureMask 0x00008000UL
+#define cswhFeatureMask 0x00004000UL
+#define saltFeatureMask 0x00002000UL
+#define naltFeatureMask 0x00001000UL
+#define rubyFeatureMask 0x00000800UL
+#define ss01FeatureMask 0x00000400UL
+#define ss02FeatureMask 0x00000200UL
+#define ss03FeatureMask 0x00000100UL
+#define ss04FeatureMask 0x00000080UL
+#define ss05FeatureMask 0x00000040UL
+#define ss06FeatureMask 0x00000020UL
+#define ss07FeatureMask 0x00000010UL
+
#define minimalFeatures (ccmpFeatureMask | markFeatureMask | mkmkFeatureMask | loclFeatureMask | caltFeatureMask)
-#define ligaFeatures (ligaFeatureMask | cligFeatureMask | minimalFeatures)
-#define kernFeatures (kernFeatureMask | paltFeatureMask | minimalFeatures)
-#define kernAndLigaFeatures (ligaFeatures | kernFeatures)
static const FeatureMap featureMap[] =
{
{ccmpFeatureTag, ccmpFeatureMask},
{ligaFeatureTag, ligaFeatureMask},
{cligFeatureTag, cligFeatureMask},
- {kernFeatureTag, kernFeatureMask},
+ {kernFeatureTag, kernFeatureMask},
{paltFeatureTag, paltFeatureMask},
{markFeatureTag, markFeatureMask},
{mkmkFeatureTag, mkmkFeatureMask},
{loclFeatureTag, loclFeatureMask},
- {caltFeatureTag, caltFeatureMask}
+ {caltFeatureTag, caltFeatureMask},
+ {hligFeatureTag, hligFeatureMask},
+ {smcpFeatureTag, smcpFeatureMask},
+ {fracFeatureTag, fracFeatureMask},
+ {afrcFeatureTag, afrcFeatureMask},
+ {zeroFeatureTag, zeroFeatureMask},
+ {swshFeatureTag, swshFeatureMask},
+ {cswhFeatureTag, cswhFeatureMask},
+ {saltFeatureTag, saltFeatureMask},
+ {naltFeatureTag, naltFeatureMask},
+ {rubyFeatureTag, rubyFeatureMask},
+ {ss01FeatureTag, ss01FeatureMask},
+ {ss02FeatureTag, ss02FeatureMask},
+ {ss03FeatureTag, ss03FeatureMask},
+ {ss04FeatureTag, ss04FeatureMask},
+ {ss05FeatureTag, ss05FeatureMask},
+ {ss06FeatureTag, ss06FeatureMask},
+ {ss07FeatureTag, ss07FeatureMask}
};
static const le_int32 featureMapCount = LE_ARRAY_SIZE(featureMap);
OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
+ le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
: LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fFeatureMask(minimalFeatures),
fFeatureMap(featureMap), fFeatureMapCount(featureMapCount), fFeatureOrder(FALSE),
- fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL)
+ fGSUBTable(gsubTable),
+ fGDEFTable(fontInstance, LE_GDEF_TABLE_TAG, success),
+ fGPOSTable(fontInstance, LE_GPOS_TABLE_TAG, success), fSubstitutionFilter(NULL)
{
- static const le_uint32 gdefTableTag = LE_GDEF_TABLE_TAG;
- static const le_uint32 gposTableTag = LE_GPOS_TABLE_TAG;
- const GlyphPositioningTableHeader *gposTable = (const GlyphPositioningTableHeader *) getFontTable(gposTableTag);
-
- // todo: switch to more flags and bitfield rather than list of feature tags?
- switch (typoFlags & ~0x80000000L) {
- case 0: break; // default
- case 1: fFeatureMask = kernFeatures; break;
- case 2: fFeatureMask = ligaFeatures; break;
- case 3: fFeatureMask = kernAndLigaFeatures; break;
- default: break;
- }
-
- if (typoFlags & 0x80000000L) {
- fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
- }
+ applyTypoFlags();
setScriptAndLanguageTags();
- fGDEFTable = (const GlyphDefinitionTableHeader *) getFontTable(gdefTableTag);
-
// JK patch, 2008-05-30 - see Sinhala bug report and LKLUG font
// if (gposTable != NULL && gposTable->coversScriptAndLanguage(fScriptTag, fLangSysTag)) {
- if (gposTable != NULL && gposTable->coversScript(fScriptTag)) {
- fGPOSTable = gposTable;
+ if (!fGPOSTable.isEmpty()&& !fGPOSTable->coversScript(fGPOSTable, fScriptTag, success)) {
+ fGPOSTable.clear(); // already loaded
}
}
+void OpenTypeLayoutEngine::applyTypoFlags() {
+ const le_int32& typoFlags = fTypoFlags;
+ const LEFontInstance *fontInstance = fFontInstance;
+
+ switch (typoFlags & (LE_SS01_FEATURE_FLAG
+ | LE_SS02_FEATURE_FLAG
+ | LE_SS03_FEATURE_FLAG
+ | LE_SS04_FEATURE_FLAG
+ | LE_SS05_FEATURE_FLAG
+ | LE_SS06_FEATURE_FLAG
+ | LE_SS07_FEATURE_FLAG)) {
+ case LE_SS01_FEATURE_FLAG:
+ fFeatureMask |= ss01FeatureMask;
+ break;
+ case LE_SS02_FEATURE_FLAG:
+ fFeatureMask |= ss02FeatureMask;
+ break;
+ case LE_SS03_FEATURE_FLAG:
+ fFeatureMask |= ss03FeatureMask;
+ break;
+ case LE_SS04_FEATURE_FLAG:
+ fFeatureMask |= ss04FeatureMask;
+ break;
+ case LE_SS05_FEATURE_FLAG:
+ fFeatureMask |= ss05FeatureMask;
+ break;
+ case LE_SS06_FEATURE_FLAG:
+ fFeatureMask |= ss06FeatureMask;
+ break;
+ case LE_SS07_FEATURE_FLAG:
+ fFeatureMask |= ss07FeatureMask;
+ break;
+ }
+
+ if (typoFlags & LE_Kerning_FEATURE_FLAG) {
+ fFeatureMask |= (kernFeatureMask | paltFeatureMask);
+ // Convenience.
+ }
+ if (typoFlags & LE_Ligatures_FEATURE_FLAG) {
+ fFeatureMask |= (ligaFeatureMask | cligFeatureMask);
+ // Convenience TODO: should add: .. dligFeatureMask | rligFeatureMask ?
+ }
+ if (typoFlags & LE_CLIG_FEATURE_FLAG) fFeatureMask |= cligFeatureMask;
+ if (typoFlags & LE_DLIG_FEATURE_FLAG) fFeatureMask |= dligFeatureMask;
+ if (typoFlags & LE_HLIG_FEATURE_FLAG) fFeatureMask |= hligFeatureMask;
+ if (typoFlags & LE_LIGA_FEATURE_FLAG) fFeatureMask |= ligaFeatureMask;
+ if (typoFlags & LE_RLIG_FEATURE_FLAG) fFeatureMask |= rligFeatureMask;
+ if (typoFlags & LE_SMCP_FEATURE_FLAG) fFeatureMask |= smcpFeatureMask;
+ if (typoFlags & LE_FRAC_FEATURE_FLAG) fFeatureMask |= fracFeatureMask;
+ if (typoFlags & LE_AFRC_FEATURE_FLAG) fFeatureMask |= afrcFeatureMask;
+ if (typoFlags & LE_ZERO_FEATURE_FLAG) fFeatureMask |= zeroFeatureMask;
+ if (typoFlags & LE_SWSH_FEATURE_FLAG) fFeatureMask |= swshFeatureMask;
+ if (typoFlags & LE_CSWH_FEATURE_FLAG) fFeatureMask |= cswhFeatureMask;
+ if (typoFlags & LE_SALT_FEATURE_FLAG) fFeatureMask |= saltFeatureMask;
+ if (typoFlags & LE_RUBY_FEATURE_FLAG) fFeatureMask |= rubyFeatureMask;
+ if (typoFlags & LE_NALT_FEATURE_FLAG) {
+ // Mutually exclusive with ALL other features. http://www.microsoft.com/typography/otspec/features_ko.htm
+ fFeatureMask = naltFeatureMask;
+ }
+
+ if (typoFlags & LE_CHAR_FILTER_FEATURE_FLAG) {
+ // This isn't a font feature, but requests a Char Substitution Filter
+ fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
+ }
+
+}
+
void OpenTypeLayoutEngine::reset()
{
// NOTE: if we're called from
@@ -146,15 +248,17 @@
OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, LEErrorCode &success)
: LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fFeatureOrder(FALSE),
- fGSUBTable(NULL), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL)
+ fGSUBTable(), fGDEFTable(), fGPOSTable(), fSubstitutionFilter(NULL)
{
- setScriptAndLanguageTags();
+ applyTypoFlags();
+ setScriptAndLanguageTags();
}
OpenTypeLayoutEngine::~OpenTypeLayoutEngine()
{
- if (fTypoFlags & 0x80000000L) {
+ if (fTypoFlags & LE_CHAR_FILTER_FEATURE_FLAG) {
delete fSubstitutionFilter;
+ fSubstitutionFilter = NULL;
}
reset();
@@ -267,13 +371,13 @@
return 0;
}
- if (fGSUBTable != NULL) {
- if (fScriptTagV2 != nullScriptTag && fGSUBTable->coversScriptAndLanguage(fScriptTagV2,fLangSysTag)) {
- count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTagV2, fLangSysTag, fGDEFTable, fSubstitutionFilter,
+ if (fGSUBTable.isValid()) {
+ if (fScriptTagV2 != nullScriptTag && fGSUBTable->coversScriptAndLanguage(fGSUBTable, fScriptTagV2, fLangSysTag, success)) {
+ count = fGSUBTable->process(fGSUBTable, glyphStorage, rightToLeft, fScriptTagV2, fLangSysTag, fGDEFTable, fSubstitutionFilter,
fFeatureMap, fFeatureMapCount, fFeatureOrder, success);
} else {
- count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter,
+ count = fGSUBTable->process(fGSUBTable, glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter,
fFeatureMap, fFeatureMapCount, fFeatureOrder, success);
}
}
@@ -294,13 +398,13 @@
return 0;
}
- if (fGSUBTable != NULL) {
- if (fScriptTagV2 != nullScriptTag && fGSUBTable->coversScriptAndLanguage(fScriptTagV2,fLangSysTag)) {
- count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTagV2, fLangSysTag, fGDEFTable, fSubstitutionFilter,
+ if (fGSUBTable.isValid()) {
+ if (fScriptTagV2 != nullScriptTag && fGSUBTable->coversScriptAndLanguage(fGSUBTable,fScriptTagV2,fLangSysTag,success)) {
+ count = fGSUBTable->process(fGSUBTable, glyphStorage, rightToLeft, fScriptTagV2, fLangSysTag, fGDEFTable, fSubstitutionFilter,
fFeatureMap, fFeatureMapCount, fFeatureOrder, success);
} else {
- count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter,
+ count = fGSUBTable->process(fGSUBTable, glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter,
fFeatureMap, fFeatureMapCount, fFeatureOrder, success);
}
}
@@ -325,7 +429,7 @@
{
LEUnicode *outChars = NULL;
LEGlyphStorage fakeGlyphStorage;
- le_int32 outCharCount, outGlyphCount, fakeGlyphCount;
+ le_int32 outCharCount, outGlyphCount;
if (LE_FAILURE(success)) {
return 0;
@@ -343,11 +447,13 @@
}
if (outChars != NULL) {
- fakeGlyphCount = glyphProcessing(outChars, 0, outCharCount, outCharCount, rightToLeft, fakeGlyphStorage, success);
+ // le_int32 fakeGlyphCount =
+ glyphProcessing(outChars, 0, outCharCount, outCharCount, rightToLeft, fakeGlyphStorage, success);
LE_DELETE_ARRAY(outChars); // FIXME: a subclass may have allocated this, in which case this delete might not work...
//adjustGlyphs(outChars, 0, outCharCount, rightToLeft, fakeGlyphs, fakeGlyphCount);
} else {
- fakeGlyphCount = glyphProcessing(chars, offset, count, max, rightToLeft, fakeGlyphStorage, success);
+ // le_int32 fakeGlyphCount =
+ glyphProcessing(chars, offset, count, max, rightToLeft, fakeGlyphStorage, success);
//adjustGlyphs(chars, offset, count, rightToLeft, fakeGlyphs, fakeGlyphCount);
}
@@ -378,7 +484,7 @@
return;
}
- if (fGPOSTable != NULL) {
+ if (!fGPOSTable.isEmpty()) {
GlyphPositionAdjustments *adjustments = new GlyphPositionAdjustments(glyphCount);
le_int32 i;
@@ -401,19 +507,20 @@
}
#endif
- if (fGPOSTable != NULL) {
- if (fScriptTagV2 != nullScriptTag && fGPOSTable->coversScriptAndLanguage(fScriptTagV2,fLangSysTag)) {
- fGPOSTable->process(glyphStorage, adjustments, reverse, fScriptTagV2, fLangSysTag, fGDEFTable, success, fFontInstance,
- fFeatureMap, fFeatureMapCount, fFeatureOrder);
+ if (!fGPOSTable.isEmpty()) {
+ if (fScriptTagV2 != nullScriptTag &&
+ fGPOSTable->coversScriptAndLanguage(fGPOSTable, fScriptTagV2,fLangSysTag,success)) {
+ fGPOSTable->process(fGPOSTable, glyphStorage, adjustments, reverse, fScriptTagV2, fLangSysTag,
+ fGDEFTable, success, fFontInstance, fFeatureMap, fFeatureMapCount, fFeatureOrder);
} else {
- fGPOSTable->process(glyphStorage, adjustments, reverse, fScriptTag, fLangSysTag, fGDEFTable, success, fFontInstance,
- fFeatureMap, fFeatureMapCount, fFeatureOrder);
+ fGPOSTable->process(fGPOSTable, glyphStorage, adjustments, reverse, fScriptTag, fLangSysTag,
+ fGDEFTable, success, fFontInstance, fFeatureMap, fFeatureMapCount, fFeatureOrder);
}
- } else if ( fTypoFlags & 0x1 ) {
- static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG;
- KernTable kt(fFontInstance, getFontTable(kernTableTag));
- kt.process(glyphStorage);
+ } else if (fTypoFlags & LE_Kerning_FEATURE_FLAG) { /* kerning enabled */
+ LETableReference kernTable(fFontInstance, LE_KERN_TABLE_TAG, success);
+ KernTable kt(kernTable, success);
+ kt.process(glyphStorage, success);
}
float xAdjust = 0, yAdjust = 0;
--- a/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.h Wed Apr 17 02:53:02 2013 -0700
@@ -24,7 +24,7 @@
*/
/*
- * (C) Copyright IBM Corp. 1998-2010 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -35,6 +35,7 @@
#include "LEGlyphFilter.h"
#include "LEFontInstance.h"
#include "LayoutEngine.h"
+#include "LETableReference.h"
#include "GlyphSubstitutionTables.h"
#include "GlyphDefinitionTables.h"
@@ -88,7 +89,7 @@
* @internal
*/
OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success);
+ le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success);
/**
* This constructor is used when the font requires a "canned" GSUB table which can't be known
@@ -184,6 +185,11 @@
*/
static const LETag scriptTags[];
+ /**
+ * apply the typoflags. Only called by the c'tors.
+ */
+ void applyTypoFlags();
+
protected:
/**
* A set of "default" features. The default characterProcessing method
@@ -223,21 +229,21 @@
*
* @internal
*/
- const GlyphSubstitutionTableHeader *fGSUBTable;
+ LEReferenceTo<GlyphSubstitutionTableHeader> fGSUBTable;
/**
* The address of the GDEF table.
*
* @internal
*/
- const GlyphDefinitionTableHeader *fGDEFTable;
+ LEReferenceTo<GlyphDefinitionTableHeader> fGDEFTable;
/**
* The address of the GPOS table.
*
* @internal
*/
- const GlyphPositioningTableHeader *fGPOSTable;
+ LEReferenceTo<GlyphPositioningTableHeader> fGPOSTable;
/**
* An optional filter used to inhibit substitutions
--- a/jdk/src/share/native/sun/font/layout/OpenTypeTables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/OpenTypeTables.h Wed Apr 17 02:53:02 2013 -0700
@@ -38,6 +38,7 @@
*/
#include "LETypes.h"
+#include "LETableReference.h"
U_NAMESPACE_BEGIN
@@ -50,7 +51,7 @@
#define LE_GLYPH_GROUP_MASK 0x00000001UL
typedef le_uint32 FeatureMask;
-#define SWAPT(atag) ((LETag) ((atag[0] << 24) + (atag[1] << 16) + (atag[2] << 8) + atag[3]))
+#define SWAPT(atag) ((LETag) (((atag[0]) << 24) + ((atag[1]) << 16) + ((atag[2]) << 8) + (atag[3])))
struct TagAndOffsetRecord
{
--- a/jdk/src/share/native/sun/font/layout/OpenTypeUtilities.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/OpenTypeUtilities.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -76,58 +76,74 @@
return bit;
}
-Offset OpenTypeUtilities::getTagOffset(LETag tag, const TagAndOffsetRecord *records, le_int32 recordCount)
+
+Offset OpenTypeUtilities::getTagOffset(LETag tag, const LEReferenceToArrayOf<TagAndOffsetRecord> &records, LEErrorCode &success)
{
- le_uint8 bit = highBit(recordCount);
- le_int32 power = 1 << bit;
- le_int32 extra = recordCount - power;
- le_int32 probe = power;
- le_int32 index = 0;
+ if(LE_FAILURE(success)) return 0;
- if (SWAPT(records[extra].tag) <= tag) {
- index = extra;
+ le_uint32 recordCount = records.getCount();
+ le_uint8 bit = highBit(recordCount);
+ le_int32 power = 1 << bit;
+ le_int32 extra = recordCount - power;
+ le_int32 probe = power;
+ le_int32 index = 0;
+
+ {
+ const ATag &aTag = records.getAlias(extra,success)->tag;
+ if (SWAPT(aTag) <= tag) {
+ index = extra;
}
+ }
- while (probe > (1 << 0)) {
- probe >>= 1;
+ while (probe > (1 << 0) && LE_SUCCESS(success)) {
+ probe >>= 1;
- if (SWAPT(records[index + probe].tag) <= tag) {
- index += probe;
- }
+ {
+ const ATag &aTag = records.getAlias(index+probe,success)->tag;
+ if (SWAPT(aTag) <= tag) {
+ index += probe;
+ }
}
+ }
- if (SWAPT(records[index].tag) == tag) {
- return SWAPW(records[index].offset);
+ {
+ const ATag &aTag = records.getAlias(index,success)->tag;
+ if (SWAPT(aTag) == tag) {
+ return SWAPW(records.getAlias(index,success)->offset);
}
+ }
- return 0;
+ return 0;
}
-le_int32 OpenTypeUtilities::getGlyphRangeIndex(TTGlyphID glyphID, const GlyphRangeRecord *records, le_int32 recordCount)
+le_int32 OpenTypeUtilities::getGlyphRangeIndex(TTGlyphID glyphID, const LEReferenceToArrayOf<GlyphRangeRecord> &records, LEErrorCode &success)
{
+ if(LE_FAILURE(success)) return -1;
+
+ le_uint32 recordCount = records.getCount();
le_uint8 bit = highBit(recordCount);
le_int32 power = 1 << bit;
le_int32 extra = recordCount - power;
le_int32 probe = power;
le_int32 range = 0;
- if (recordCount == 0) {
- return -1;
- }
+ if (recordCount == 0) {
+ return -1;
+ }
- if (SWAPW(records[extra].firstGlyph) <= glyphID) {
+ if (SWAPW(records(extra,success).firstGlyph) <= glyphID) {
range = extra;
}
- while (probe > (1 << 0)) {
+ while (probe > (1 << 0) && LE_SUCCESS(success)) {
probe >>= 1;
- if (SWAPW(records[range + probe].firstGlyph) <= glyphID) {
+ if (SWAPW(records(range + probe,success).firstGlyph) <= glyphID) {
range += probe;
}
}
- if (SWAPW(records[range].firstGlyph) <= glyphID && SWAPW(records[range].lastGlyph) >= glyphID) {
+ if (SWAPW(records(range,success).firstGlyph) <= glyphID && SWAPW(records(range,success).lastGlyph) >= glyphID) {
return range;
}
@@ -199,6 +215,38 @@
}
}
+U_NAMESPACE_END
+#if LE_ASSERT_BAD_FONT
+#include <stdio.h>
+
+static const char *letagToStr(LETag tag, char *str) {
+ str[0]= 0xFF & (tag>>24);
+ str[1]= 0xFF & (tag>>16);
+ str[2]= 0xFF & (tag>>8);
+ str[3]= 0xFF & (tag>>0);
+ str[4]= 0;
+ return str;
+}
+
+U_CAPI void U_EXPORT2 _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len) {
+ char tagbuf[5];
-U_NAMESPACE_END
+ fprintf(stderr, "%s:%d: LETableReference@0x%p: ", f, l, what);
+ fprintf(stderr, msg, ptr, len);
+ fprintf(stderr, "\n");
+
+ for(int depth=0;depth<10&&(what!=NULL);depth++) {
+ for(int i=0;i<depth;i++) {
+ fprintf(stderr, " "); // indent
+ }
+ if(!what->isValid()) {
+ fprintf(stderr, "(invalid)");
+ }
+ fprintf(stderr, "@%p: tag (%s) font (0x%p), [0x%p+0x%lx]\n", what, letagToStr(what->getTag(), tagbuf), what->getFont(),
+ what->getAlias(), what->getLength());
+
+ what = what->getParent();
+ }
+}
+#endif
--- a/jdk/src/share/native/sun/font/layout/OpenTypeUtilities.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/OpenTypeUtilities.h Wed Apr 17 02:53:02 2013 -0700
@@ -45,8 +45,17 @@
class OpenTypeUtilities /* not : public UObject because all methods are static */ {
public:
static le_int8 highBit(le_int32 value);
- static Offset getTagOffset(LETag tag, const TagAndOffsetRecord *records, le_int32 recordCount);
- static le_int32 getGlyphRangeIndex(TTGlyphID glyphID, const GlyphRangeRecord *records, le_int32 recordCount);
+ static Offset getTagOffset(LETag tag, const LEReferenceToArrayOf<TagAndOffsetRecord> &records, LEErrorCode &success);
+ /**
+ * @deprecated TODO remove
+ */
+ static le_int32 getGlyphRangeIndex(TTGlyphID glyphID, const GlyphRangeRecord *records, le_int32 recordCount) {
+ LEErrorCode success = LE_NO_ERROR;
+ LETableReference recordRef0((const le_uint8*)records);
+ LEReferenceToArrayOf<GlyphRangeRecord> recordRef(recordRef0, success, (size_t)0, recordCount);
+ return getGlyphRangeIndex(glyphID, recordRef, success);
+ }
+ static le_int32 getGlyphRangeIndex(TTGlyphID glyphID, const LEReferenceToArrayOf<GlyphRangeRecord> &records, LEErrorCode &success);
static le_int32 search(le_uint16 value, const le_uint16 array[], le_int32 count);
static le_int32 search(le_uint32 value, const le_uint32 array[], le_int32 count);
static void sort(le_uint16 *array, le_int32 count);
--- a/jdk/src/share/native/sun/font/layout/PairPositioningSubtables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/PairPositioningSubtables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -41,7 +41,7 @@
U_NAMESPACE_BEGIN
-le_uint32 PairPositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
+le_uint32 PairPositioningSubtable::process(const LEReferenceTo<PairPositioningSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
switch(SWAPW(subtableFormat))
{
@@ -50,27 +50,32 @@
case 1:
{
- const PairPositioningFormat1Subtable *subtable = (const PairPositioningFormat1Subtable *) this;
+ const LEReferenceTo<PairPositioningFormat1Subtable> subtable(base, success, (const PairPositioningFormat1Subtable *) this);
- return subtable->process(glyphIterator, fontInstance);
+ if(LE_SUCCESS(success))
+ return subtable->process(subtable, glyphIterator, fontInstance, success);
+ else
+ return 0;
}
case 2:
{
- const PairPositioningFormat2Subtable *subtable = (const PairPositioningFormat2Subtable *) this;
+ const LEReferenceTo<PairPositioningFormat2Subtable> subtable(base, success, (const PairPositioningFormat2Subtable *) this);
- return subtable->process(glyphIterator, fontInstance);
+ if(LE_SUCCESS(success))
+ return subtable->process(subtable, glyphIterator, fontInstance, success);
+ else
+ return 0;
}
-
default:
- return 0;
+ return 0;
}
}
-le_uint32 PairPositioningFormat1Subtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
+le_uint32 PairPositioningFormat1Subtable::process(const LEReferenceTo<PairPositioningFormat1Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
- le_int32 coverageIndex = getGlyphCoverage(firstGlyph);
+ le_int32 coverageIndex = getGlyphCoverage(base, firstGlyph, success);
GlyphIterator tempIterator(*glyphIterator);
if (coverageIndex >= 0 && glyphIterator->next()) {
@@ -110,10 +115,10 @@
return 0;
}
-le_uint32 PairPositioningFormat2Subtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
+le_uint32 PairPositioningFormat2Subtable::process(const LEReferenceTo<PairPositioningFormat2Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
- le_int32 coverageIndex = getGlyphCoverage(firstGlyph);
+ le_int32 coverageIndex = getGlyphCoverage(base, firstGlyph, success);
GlyphIterator tempIterator(*glyphIterator);
if (coverageIndex >= 0 && glyphIterator->next()) {
--- a/jdk/src/share/native/sun/font/layout/PairPositioningSubtables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/PairPositioningSubtables.h Wed Apr 17 02:53:02 2013 -0700
@@ -59,13 +59,14 @@
le_uint16 pairValueCount;
PairValueRecord pairValueRecordArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(PairSetTable, pairValueRecordArray)
struct PairPositioningSubtable : GlyphPositioningSubtable
{
ValueFormat valueFormat1;
ValueFormat valueFormat2;
- le_uint32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
+ le_uint32 process(const LEReferenceTo<PairPositioningSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
};
struct PairPositioningFormat1Subtable : PairPositioningSubtable
@@ -73,12 +74,13 @@
le_uint16 pairSetCount;
Offset pairSetTableOffsetArray[ANY_NUMBER];
- le_uint32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
+ le_uint32 process(const LEReferenceTo<PairPositioningFormat1Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
private:
const PairValueRecord *findPairValueRecord(TTGlyphID glyphID, const PairValueRecord *records,
le_uint16 recordCount, le_uint16 recordSize) const;
};
+LE_VAR_ARRAY(PairPositioningFormat1Subtable, pairSetTableOffsetArray)
// NOTE: ValueRecord has a variable size
struct Class2Record
@@ -91,6 +93,7 @@
{
Class2Record class2RecordArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(Class1Record, class2RecordArray)
struct PairPositioningFormat2Subtable : PairPositioningSubtable
{
@@ -100,8 +103,9 @@
le_uint16 class2Count;
Class1Record class1RecordArray[ANY_NUMBER];
- le_uint32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
+ le_uint32 process(const LEReferenceTo<PairPositioningFormat2Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
};
+LE_VAR_ARRAY(PairPositioningFormat2Subtable, class1RecordArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/ScriptAndLanguage.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ScriptAndLanguage.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -38,29 +38,33 @@
U_NAMESPACE_BEGIN
-const LangSysTable *ScriptTable::findLanguage(LETag languageTag, le_bool exactMatch) const
+LEReferenceTo<LangSysTable> ScriptTable::findLanguage(const LETableReference& base, LETag languageTag, LEErrorCode &success, le_bool exactMatch) const
{
le_uint16 count = SWAPW(langSysCount);
Offset langSysTableOffset = exactMatch? 0 : SWAPW(defaultLangSysTableOffset);
if (count > 0) {
- Offset foundOffset =
- OpenTypeUtilities::getTagOffset(languageTag, langSysRecordArray, count);
+ LEReferenceToArrayOf<TagAndOffsetRecord> langSysRecords(base, success, langSysRecordArray, count);
+ Offset foundOffset =
+ OpenTypeUtilities::getTagOffset(languageTag, langSysRecords, success);
- if (foundOffset != 0) {
- langSysTableOffset = foundOffset;
- }
+ if (foundOffset != 0 && LE_SUCCESS(success)) {
+ langSysTableOffset = foundOffset;
+ }
}
if (langSysTableOffset != 0) {
- return (const LangSysTable *) ((char *)this + langSysTableOffset);
+ return LEReferenceTo<LangSysTable>(base, success, langSysTableOffset);
}
- return NULL;
+ return LEReferenceTo<LangSysTable>();
}
-const ScriptTable *ScriptListTable::findScript(LETag scriptTag) const
+LEReferenceTo<ScriptTable> ScriptListTable::findScript(const LETableReference &base, LETag scriptTag, LEErrorCode &success) const
{
+ if (LE_FAILURE(success) ) {
+ return LEReferenceTo<ScriptTable>(); // get out
+ }
/*
* There are some fonts that have a large, bogus value for scriptCount. To try
* and protect against this, we use the offset in the first scriptRecord,
@@ -74,38 +78,53 @@
* to be unsorted.
*/
le_uint16 count = SWAPW(scriptCount);
+
+ if (count == 0) {
+ return LEReferenceTo<ScriptTable>(); // no items, no search
+ }
+
+ // attempt to construct a ref with at least one element
+ LEReferenceToArrayOf<ScriptRecord> oneElementTable(base, success, &scriptRecordArray[0], 1);
+
+ if( LE_FAILURE(success) ) {
+ return LEReferenceTo<ScriptTable>(); // couldn't even read the first record - bad font.
+ }
+
le_uint16 limit = ((SWAPW(scriptRecordArray[0].offset) - sizeof(ScriptListTable)) / sizeof(scriptRecordArray)) + ANY_NUMBER;
Offset scriptTableOffset = 0;
+
if (count > limit) {
// the scriptCount value is bogus; do a linear search
// because limit may still be too large.
- for(le_int32 s = 0; s < limit; s += 1) {
- if (SWAPT(scriptRecordArray[s].tag) == scriptTag) {
- scriptTableOffset = SWAPW(scriptRecordArray[s].offset);
- break;
- }
+ LEReferenceToArrayOf<ScriptRecord> scriptRecordArrayRef(base, success, &scriptRecordArray[0], limit);
+ for(le_int32 s = 0; (s < limit)&&LE_SUCCESS(success); s += 1) {
+ if (SWAPT(scriptRecordArrayRef(s,success).tag) == scriptTag) {
+ scriptTableOffset = SWAPW(scriptRecordArrayRef(s,success).offset);
+ break;
+ }
}
} else {
- scriptTableOffset = OpenTypeUtilities::getTagOffset(scriptTag, scriptRecordArray, count);
+ LEReferenceToArrayOf<ScriptRecord> scriptRecordArrayRef(base, success, &scriptRecordArray[0], count);
+ scriptTableOffset = OpenTypeUtilities::getTagOffset(scriptTag, scriptRecordArrayRef, success); // TODO
}
if (scriptTableOffset != 0) {
- return (const ScriptTable *) ((char *)this + scriptTableOffset);
+ return LEReferenceTo<ScriptTable>(base, success, scriptTableOffset);
}
- return NULL;
+ return LEReferenceTo<ScriptTable>();
}
-const LangSysTable *ScriptListTable::findLanguage(LETag scriptTag, LETag languageTag, le_bool exactMatch) const
+LEReferenceTo<LangSysTable> ScriptListTable::findLanguage(const LETableReference &base, LETag scriptTag, LETag languageTag, LEErrorCode &success, le_bool exactMatch) const
{
- const ScriptTable *scriptTable = findScript(scriptTag);
+ const LEReferenceTo<ScriptTable> scriptTable = findScript(base, scriptTag, success);
- if (scriptTable == 0) {
- return NULL;
- }
+ if (scriptTable.isEmpty()) {
+ return LEReferenceTo<LangSysTable>();
+ }
- return scriptTable->findLanguage(languageTag, exactMatch);
+ return scriptTable->findLanguage(scriptTable, languageTag, success, exactMatch).reparent(base);
}
U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/ScriptAndLanguage.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ScriptAndLanguage.h Wed Apr 17 02:53:02 2013 -0700
@@ -51,6 +51,7 @@
le_uint16 featureCount;
le_uint16 featureIndexArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(LangSysTable, featureIndexArray)
struct ScriptTable
{
@@ -58,8 +59,9 @@
le_uint16 langSysCount;
LangSysRecord langSysRecordArray[ANY_NUMBER];
- const LangSysTable *findLanguage(LETag languageTag, le_bool exactMatch = FALSE) const;
+ LEReferenceTo<LangSysTable> findLanguage(const LETableReference &base, LETag languageTag, LEErrorCode &success, le_bool exactMatch = FALSE) const;
};
+LE_VAR_ARRAY(ScriptTable, langSysRecordArray)
typedef TagAndOffsetRecord ScriptRecord;
@@ -68,9 +70,10 @@
le_uint16 scriptCount;
ScriptRecord scriptRecordArray[ANY_NUMBER];
- const ScriptTable *findScript(LETag scriptTag) const;
- const LangSysTable *findLanguage(LETag scriptTag, LETag languageTag, le_bool exactMatch = FALSE) const;
+ LEReferenceTo<ScriptTable> findScript(const LETableReference &base, LETag scriptTag, LEErrorCode &success) const;
+ LEReferenceTo<LangSysTable> findLanguage(const LETableReference &base, LETag scriptTag, LETag languageTag, LEErrorCode &success, le_bool exactMatch = FALSE) const;
};
+LE_VAR_ARRAY(ScriptListTable, scriptRecordArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/ScriptAndLanguageTags.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ScriptAndLanguageTags.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2010. All Rights Reserved.
+ * (C) Copyright IBM Corp. 1998-2013. All Rights Reserved.
*
* WARNING: THIS FILE IS MACHINE GENERATED. DO NOT HAND EDIT IT UNLESS
* YOU REALLY KNOW WHAT YOU'RE DOING.
@@ -186,7 +186,18 @@
nbatScriptTag, /* 'nbat' (NBAT) */
palmScriptTag, /* 'palm' (PALM) */
sindScriptTag, /* 'sind' (SIND) */
- waraScriptTag /* 'wara' (WARA) */
+ waraScriptTag, /* 'wara' (WARA) */
+ afakScriptTag, /* 'afak' (AFAK) */
+ jurcScriptTag, /* 'jurc' (JURC) */
+ mrooScriptTag, /* 'mroo' (MROO) */
+ nshuScriptTag, /* 'nshu' (NSHU) */
+ shrdScriptTag, /* 'shrd' (SHARADA) */
+ soraScriptTag, /* 'sora' (SORA_SOMPENG) */
+ takrScriptTag, /* 'takr' (TAKRI) */
+ tangScriptTag, /* 'tang' (TANG) */
+ woleScriptTag, /* 'wole' (WOLE) */
+ khojScriptTag, /* 'khoj' (KHOJ) */
+ tirhScriptTag /* 'tirh' (TIRH) */
};
const LETag OpenTypeLayoutEngine::languageTags[] = {
--- a/jdk/src/share/native/sun/font/layout/ScriptAndLanguageTags.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ScriptAndLanguageTags.h Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2010. All Rights Reserved.
+ * (C) Copyright IBM Corp. 1998-2013. All Rights Reserved.
*
* WARNING: THIS FILE IS MACHINE GENERATED. DO NOT HAND EDIT IT UNLESS
* YOU REALLY KNOW WHAT YOU'RE DOING.
@@ -201,6 +201,17 @@
const LETag palmScriptTag = 0x70616C6D; /* 'palm' (PALM) */
const LETag sindScriptTag = 0x73696E64; /* 'sind' (SIND) */
const LETag waraScriptTag = 0x77617261; /* 'wara' (WARA) */
+const LETag afakScriptTag = 0x6166616B; /* 'afak' (AFAK) */
+const LETag jurcScriptTag = 0x6A757263; /* 'jurc' (JURC) */
+const LETag mrooScriptTag = 0x6D726F6F; /* 'mroo' (MROO) */
+const LETag nshuScriptTag = 0x6E736875; /* 'nshu' (NSHU) */
+const LETag shrdScriptTag = 0x73687264; /* 'shrd' (SHARADA) */
+const LETag soraScriptTag = 0x736F7261; /* 'sora' (SORA_SOMPENG) */
+const LETag takrScriptTag = 0x74616B72; /* 'takr' (TAKRI) */
+const LETag tangScriptTag = 0x74616E67; /* 'tang' (TANG) */
+const LETag woleScriptTag = 0x776F6C65; /* 'wole' (WOLE) */
+const LETag khojScriptTag = 0x6B686F6A; /* 'khoj' (KHOJ) */
+const LETag tirhScriptTag = 0x74697268; /* 'tirh' (TIRH) */
const LETag nullScriptTag = 0x00000000; /* '' (NULL) */
--- a/jdk/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -46,19 +46,18 @@
{
}
-SegmentArrayProcessor::SegmentArrayProcessor(const MorphSubtableHeader *morphSubtableHeader)
- : NonContextualGlyphSubstitutionProcessor(morphSubtableHeader)
+SegmentArrayProcessor::SegmentArrayProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
+ : NonContextualGlyphSubstitutionProcessor(morphSubtableHeader, success)
{
- const NonContextualGlyphSubstitutionHeader *header = (const NonContextualGlyphSubstitutionHeader *) morphSubtableHeader;
-
- segmentArrayLookupTable = (const SegmentArrayLookupTable *) &header->table;
+ LEReferenceTo<NonContextualGlyphSubstitutionHeader> header(morphSubtableHeader, success);
+ segmentArrayLookupTable = LEReferenceTo<SegmentArrayLookupTable>(morphSubtableHeader, success, (const SegmentArrayLookupTable*)&header->table);
}
SegmentArrayProcessor::~SegmentArrayProcessor()
{
}
-void SegmentArrayProcessor::process(LEGlyphStorage &glyphStorage)
+void SegmentArrayProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
const LookupSegment *segments = segmentArrayLookupTable->segments;
le_int32 glyphCount = glyphStorage.getGlyphCount();
@@ -66,17 +65,16 @@
for (glyph = 0; glyph < glyphCount; glyph += 1) {
LEGlyphID thisGlyph = glyphStorage[glyph];
- const LookupSegment *lookupSegment = segmentArrayLookupTable->lookupSegment(segments, thisGlyph);
+ const LookupSegment *lookupSegment = segmentArrayLookupTable->lookupSegment(segmentArrayLookupTable, segments, thisGlyph, success);
if (lookupSegment != NULL) {
TTGlyphID firstGlyph = SWAPW(lookupSegment->firstGlyph);
le_int16 offset = SWAPW(lookupSegment->value);
if (offset != 0) {
- TTGlyphID *glyphArray = (TTGlyphID *) ((char *) subtableHeader + offset);
- TTGlyphID newGlyph = SWAPW(glyphArray[LE_GET_GLYPH(thisGlyph) - firstGlyph]);
-
- glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
+ LEReferenceToArrayOf<TTGlyphID> glyphArray(subtableHeader, success, offset, LE_UNBOUNDED_ARRAY);
+ TTGlyphID newGlyph = SWAPW(glyphArray(LE_GET_GLYPH(thisGlyph) - firstGlyph, success));
+ glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
}
}
}
--- a/jdk/src/share/native/sun/font/layout/SegmentArrayProcessor.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SegmentArrayProcessor.h Wed Apr 17 02:53:02 2013 -0700
@@ -50,9 +50,9 @@
class SegmentArrayProcessor : public NonContextualGlyphSubstitutionProcessor
{
public:
- virtual void process(LEGlyphStorage &glyphStorage);
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success);
- SegmentArrayProcessor(const MorphSubtableHeader *morphSubtableHeader);
+ SegmentArrayProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~SegmentArrayProcessor();
@@ -74,7 +74,7 @@
SegmentArrayProcessor();
protected:
- const SegmentArrayLookupTable *segmentArrayLookupTable;
+ LEReferenceTo<SegmentArrayLookupTable> segmentArrayLookupTable;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/SegmentArrayProcessor2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "NonContextualGlyphSubst.h"
+#include "NonContextualGlyphSubstProc2.h"
+#include "SegmentArrayProcessor2.h"
+#include "LEGlyphStorage.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SegmentArrayProcessor2)
+
+SegmentArrayProcessor2::SegmentArrayProcessor2()
+{
+}
+
+SegmentArrayProcessor2::SegmentArrayProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+ : NonContextualGlyphSubstitutionProcessor2(morphSubtableHeader, success)
+{
+ const LEReferenceTo<NonContextualGlyphSubstitutionHeader2> header(morphSubtableHeader, success);
+ segmentArrayLookupTable = LEReferenceTo<SegmentArrayLookupTable>(morphSubtableHeader, success, &header->table); // don't parent to 'header' as it is on the stack
+}
+
+SegmentArrayProcessor2::~SegmentArrayProcessor2()
+{
+}
+
+void SegmentArrayProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
+{
+ const LookupSegment *segments = segmentArrayLookupTable->segments;
+ le_int32 glyphCount = glyphStorage.getGlyphCount();
+ le_int32 glyph;
+
+ for (glyph = 0; glyph < glyphCount; glyph += 1) {
+ LEGlyphID thisGlyph = glyphStorage[glyph];
+ const LookupSegment *lookupSegment = segmentArrayLookupTable->lookupSegment(segmentArrayLookupTable, segments, thisGlyph, success);
+
+ if (lookupSegment != NULL) {
+ TTGlyphID firstGlyph = SWAPW(lookupSegment->firstGlyph);
+ le_int16 offset = SWAPW(lookupSegment->value);
+
+ if (offset != 0) {
+ TTGlyphID *glyphArray = (TTGlyphID *) ((char *) subtableHeader.getAliasTODO() + offset);
+ TTGlyphID newGlyph = SWAPW(glyphArray[LE_GET_GLYPH(thisGlyph) - firstGlyph]);
+
+ glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
+ }
+ }
+ }
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/SegmentArrayProcessor2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __SEGMENTARRAYPROCESSOR_H
+#define __SEGMENTARRAYPROCESSOR_H
+
+/**
+ * \file
+ * \internal
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "NonContextualGlyphSubst.h"
+#include "NonContextualGlyphSubstProc2.h"
+
+U_NAMESPACE_BEGIN
+
+class LEGlyphStorage;
+
+class SegmentArrayProcessor2 : public NonContextualGlyphSubstitutionProcessor2
+{
+public:
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success);
+
+ SegmentArrayProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+
+ virtual ~SegmentArrayProcessor2();
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for the actual class.
+ *
+ * @stable ICU 2.8
+ */
+ virtual UClassID getDynamicClassID() const;
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for this class.
+ *
+ * @stable ICU 2.8
+ */
+ static UClassID getStaticClassID();
+
+private:
+ SegmentArrayProcessor2();
+
+protected:
+ LEReferenceTo<SegmentArrayLookupTable> segmentArrayLookupTable;
+
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/SegmentSingleProcessor.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SegmentSingleProcessor.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -46,29 +46,28 @@
{
}
-SegmentSingleProcessor::SegmentSingleProcessor(const MorphSubtableHeader *morphSubtableHeader)
- : NonContextualGlyphSubstitutionProcessor(morphSubtableHeader)
+SegmentSingleProcessor::SegmentSingleProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
+ : NonContextualGlyphSubstitutionProcessor(morphSubtableHeader, success)
{
- const NonContextualGlyphSubstitutionHeader *header = (const NonContextualGlyphSubstitutionHeader *) morphSubtableHeader;
-
- segmentSingleLookupTable = (const SegmentSingleLookupTable *) &header->table;
+ LEReferenceTo<NonContextualGlyphSubstitutionHeader> header(morphSubtableHeader, success);
+ segmentSingleLookupTable = LEReferenceTo<SegmentSingleLookupTable>(morphSubtableHeader, success, (const SegmentSingleLookupTable*)&header->table);
}
SegmentSingleProcessor::~SegmentSingleProcessor()
{
}
-void SegmentSingleProcessor::process(LEGlyphStorage &glyphStorage)
+void SegmentSingleProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
const LookupSegment *segments = segmentSingleLookupTable->segments;
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 glyph;
- for (glyph = 0; glyph < glyphCount; glyph += 1) {
+ for (glyph = 0; glyph < glyphCount && LE_SUCCESS(success); glyph += 1) {
LEGlyphID thisGlyph = glyphStorage[glyph];
- const LookupSegment *lookupSegment = segmentSingleLookupTable->lookupSegment(segments, thisGlyph);
+ const LookupSegment *lookupSegment = segmentSingleLookupTable->lookupSegment(segmentSingleLookupTable, segments, thisGlyph, success);
- if (lookupSegment != NULL) {
+ if (lookupSegment != NULL && LE_SUCCESS(success)) {
TTGlyphID newGlyph = (TTGlyphID) LE_GET_GLYPH(thisGlyph) + SWAPW(lookupSegment->value);
glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
--- a/jdk/src/share/native/sun/font/layout/SegmentSingleProcessor.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SegmentSingleProcessor.h Wed Apr 17 02:53:02 2013 -0700
@@ -50,9 +50,9 @@
class SegmentSingleProcessor : public NonContextualGlyphSubstitutionProcessor
{
public:
- virtual void process(LEGlyphStorage &glyphStorage);
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success);
- SegmentSingleProcessor(const MorphSubtableHeader *morphSubtableHeader);
+ SegmentSingleProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~SegmentSingleProcessor();
@@ -74,7 +74,7 @@
SegmentSingleProcessor();
protected:
- const SegmentSingleLookupTable *segmentSingleLookupTable;
+ LEReferenceTo<SegmentSingleLookupTable> segmentSingleLookupTable;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/SegmentSingleProcessor2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "NonContextualGlyphSubst.h"
+#include "NonContextualGlyphSubstProc2.h"
+#include "SegmentSingleProcessor2.h"
+#include "LEGlyphStorage.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SegmentSingleProcessor2)
+
+SegmentSingleProcessor2::SegmentSingleProcessor2()
+{
+}
+
+SegmentSingleProcessor2::SegmentSingleProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+ : NonContextualGlyphSubstitutionProcessor2(morphSubtableHeader, success)
+{
+ const LEReferenceTo<NonContextualGlyphSubstitutionHeader2> header(morphSubtableHeader, success);
+
+ segmentSingleLookupTable = LEReferenceTo<SegmentSingleLookupTable>(morphSubtableHeader, success, &header->table);
+}
+
+SegmentSingleProcessor2::~SegmentSingleProcessor2()
+{
+}
+
+void SegmentSingleProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
+{
+ const LookupSegment *segments = segmentSingleLookupTable->segments;
+ le_int32 glyphCount = glyphStorage.getGlyphCount();
+ le_int32 glyph;
+
+ for (glyph = 0; glyph < glyphCount; glyph += 1) {
+ LEGlyphID thisGlyph = glyphStorage[glyph];
+ const LookupSegment *lookupSegment = segmentSingleLookupTable->lookupSegment(segmentSingleLookupTable, segments, thisGlyph, success);
+
+ if (lookupSegment != NULL && LE_SUCCESS(success)) {
+ TTGlyphID newGlyph = (TTGlyphID) LE_GET_GLYPH(thisGlyph) + SWAPW(lookupSegment->value);
+
+ glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
+ }
+ }
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/SegmentSingleProcessor2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __SEGMENTSINGLEPROCESSOR_H
+#define __SEGMENTSINGLEPROCESSOR_H
+
+/**
+ * \file
+ * \internal
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "NonContextualGlyphSubst.h"
+#include "NonContextualGlyphSubstProc2.h"
+
+U_NAMESPACE_BEGIN
+
+class LEGlyphStorage;
+
+class SegmentSingleProcessor2 : public NonContextualGlyphSubstitutionProcessor2
+{
+public:
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success);
+
+ SegmentSingleProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+
+ virtual ~SegmentSingleProcessor2();
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for the actual class.
+ *
+ * @stable ICU 2.8
+ */
+ virtual UClassID getDynamicClassID() const;
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for this class.
+ *
+ * @stable ICU 2.8
+ */
+ static UClassID getStaticClassID();
+
+private:
+ SegmentSingleProcessor2();
+
+protected:
+ LEReferenceTo<SegmentSingleLookupTable> segmentSingleLookupTable;
+
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/ShapingTypeData.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ShapingTypeData.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -122,4 +122,6 @@
0x00, 0x05, 0xFE, 0xFF, 0xFE, 0xFF, 0x00, 0x05, 0xFF, 0xF9, 0xFF, 0xFB, 0x00, 0x05
};
+const size_t ArabicShaping::shapingTypeTableLen = sizeof(shapingTypeTable)/sizeof(shapingTypeTable[0]);
+
U_NAMESPACE_END
--- a/jdk/src/share/native/sun/font/layout/SimpleArrayProcessor.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SimpleArrayProcessor.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -46,29 +46,29 @@
{
}
-SimpleArrayProcessor::SimpleArrayProcessor(const MorphSubtableHeader *morphSubtableHeader)
- : NonContextualGlyphSubstitutionProcessor(morphSubtableHeader)
+SimpleArrayProcessor::SimpleArrayProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
+ : NonContextualGlyphSubstitutionProcessor(morphSubtableHeader, success)
{
- const NonContextualGlyphSubstitutionHeader *header = (const NonContextualGlyphSubstitutionHeader *) morphSubtableHeader;
-
- simpleArrayLookupTable = (const SimpleArrayLookupTable *) &header->table;
+ LEReferenceTo<NonContextualGlyphSubstitutionHeader> header(morphSubtableHeader, success);
+ simpleArrayLookupTable = LEReferenceTo<SimpleArrayLookupTable>(morphSubtableHeader, success, (const SimpleArrayLookupTable*)&header->table);
}
SimpleArrayProcessor::~SimpleArrayProcessor()
{
}
-void SimpleArrayProcessor::process(LEGlyphStorage &glyphStorage)
+void SimpleArrayProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 glyph;
- for (glyph = 0; glyph < glyphCount; glyph += 1) {
+ LEReferenceToArrayOf<LookupValue> valueArray(simpleArrayLookupTable, success, (const LookupValue*)&simpleArrayLookupTable->valueArray, LE_UNBOUNDED_ARRAY);
+
+ for (glyph = 0; LE_SUCCESS(success) && (glyph < glyphCount); glyph += 1) {
LEGlyphID thisGlyph = glyphStorage[glyph];
if (LE_GET_GLYPH(thisGlyph) < 0xFFFF) {
- TTGlyphID newGlyph = SWAPW(simpleArrayLookupTable->valueArray[LE_GET_GLYPH(thisGlyph)]);
-
- glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
+ TTGlyphID newGlyph = SWAPW(valueArray.getObject(LE_GET_GLYPH(thisGlyph),success));
+ glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
}
}
}
--- a/jdk/src/share/native/sun/font/layout/SimpleArrayProcessor.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SimpleArrayProcessor.h Wed Apr 17 02:53:02 2013 -0700
@@ -50,9 +50,9 @@
class SimpleArrayProcessor : public NonContextualGlyphSubstitutionProcessor
{
public:
- virtual void process(LEGlyphStorage &glyphStorage);
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success);
- SimpleArrayProcessor(const MorphSubtableHeader *morphSubtableHeader);
+ SimpleArrayProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~SimpleArrayProcessor();
@@ -74,7 +74,7 @@
SimpleArrayProcessor();
protected:
- const SimpleArrayLookupTable *simpleArrayLookupTable;
+ LEReferenceTo<SimpleArrayLookupTable> simpleArrayLookupTable;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/SimpleArrayProcessor2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "NonContextualGlyphSubst.h"
+#include "NonContextualGlyphSubstProc2.h"
+#include "SimpleArrayProcessor2.h"
+#include "LEGlyphStorage.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleArrayProcessor2)
+
+SimpleArrayProcessor2::SimpleArrayProcessor2()
+{
+}
+
+SimpleArrayProcessor2::SimpleArrayProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+ : NonContextualGlyphSubstitutionProcessor2(morphSubtableHeader, success)
+{
+ const LEReferenceTo<NonContextualGlyphSubstitutionHeader2> header(morphSubtableHeader, success);
+
+ simpleArrayLookupTable = LEReferenceTo<SimpleArrayLookupTable>(morphSubtableHeader, success, &header->table);
+ valueArray = LEReferenceToArrayOf<LookupValue>(morphSubtableHeader, success, &simpleArrayLookupTable->valueArray[0], LE_UNBOUNDED_ARRAY);
+}
+
+SimpleArrayProcessor2::~SimpleArrayProcessor2()
+{
+}
+
+void SimpleArrayProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
+{
+ if (LE_FAILURE(success)) return;
+ le_int32 glyphCount = glyphStorage.getGlyphCount();
+ le_int32 glyph;
+
+ for (glyph = 0; glyph < glyphCount; glyph += 1) {
+ LEGlyphID thisGlyph = glyphStorage[glyph];
+ if (LE_GET_GLYPH(thisGlyph) < 0xFFFF) {
+ TTGlyphID newGlyph = SWAPW(valueArray(LE_GET_GLYPH(thisGlyph),success));
+
+ glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
+ }
+ }
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/SimpleArrayProcessor2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __SIMPLEARRAYPROCESSOR2_H
+#define __SIMPLEARRAYPROCESSOR2_H
+
+/**
+ * \file
+ * \internal
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "NonContextualGlyphSubst.h"
+#include "NonContextualGlyphSubstProc2.h"
+
+U_NAMESPACE_BEGIN
+
+class LEGlyphStorage;
+
+class SimpleArrayProcessor2 : public NonContextualGlyphSubstitutionProcessor2
+{
+public:
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success);
+
+ SimpleArrayProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+
+ virtual ~SimpleArrayProcessor2();
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for the actual class.
+ *
+ * @stable ICU 2.8
+ */
+ virtual UClassID getDynamicClassID() const;
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for this class.
+ *
+ * @stable ICU 2.8
+ */
+ static UClassID getStaticClassID();
+
+private:
+ SimpleArrayProcessor2();
+
+protected:
+ LEReferenceTo<SimpleArrayLookupTable> simpleArrayLookupTable;
+ LEReferenceToArrayOf<LookupValue> valueArray;
+
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/SinglePositioningSubtables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SinglePositioningSubtables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -40,7 +40,7 @@
U_NAMESPACE_BEGIN
-le_uint32 SinglePositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
+le_uint32 SinglePositioningSubtable::process(const LEReferenceTo<SinglePositioningSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
switch(SWAPW(subtableFormat))
{
@@ -49,16 +49,16 @@
case 1:
{
- const SinglePositioningFormat1Subtable *subtable = (const SinglePositioningFormat1Subtable *) this;
+ const LEReferenceTo<SinglePositioningFormat1Subtable> subtable(base, success, (const SinglePositioningFormat1Subtable *) this);
- return subtable->process(glyphIterator, fontInstance);
+ return subtable->process(subtable, glyphIterator, fontInstance, success);
}
case 2:
{
- const SinglePositioningFormat2Subtable *subtable = (const SinglePositioningFormat2Subtable *) this;
+ const LEReferenceTo<SinglePositioningFormat2Subtable> subtable(base, success, (const SinglePositioningFormat2Subtable *) this);
- return subtable->process(glyphIterator, fontInstance);
+ return subtable->process(subtable, glyphIterator, fontInstance, success);
}
default:
@@ -66,10 +66,10 @@
}
}
-le_uint32 SinglePositioningFormat1Subtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
+le_uint32 SinglePositioningFormat1Subtable::process(const LEReferenceTo<SinglePositioningFormat1Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
- le_int32 coverageIndex = getGlyphCoverage(glyph);
+ le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (coverageIndex >= 0) {
valueRecord.adjustPosition(SWAPW(valueFormat), (const char *) this, *glyphIterator, fontInstance);
@@ -80,10 +80,10 @@
return 0;
}
-le_uint32 SinglePositioningFormat2Subtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
+le_uint32 SinglePositioningFormat2Subtable::process(const LEReferenceTo<SinglePositioningFormat2Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
- le_int16 coverageIndex = (le_int16) getGlyphCoverage(glyph);
+ le_int16 coverageIndex = (le_int16) getGlyphCoverage(base, glyph, success);
if (coverageIndex >= 0) {
valueRecordArray[0].adjustPosition(coverageIndex, SWAPW(valueFormat), (const char *) this, *glyphIterator, fontInstance);
--- a/jdk/src/share/native/sun/font/layout/SinglePositioningSubtables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SinglePositioningSubtables.h Wed Apr 17 02:53:02 2013 -0700
@@ -48,7 +48,7 @@
struct SinglePositioningSubtable : GlyphPositioningSubtable
{
- le_uint32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
+ le_uint32 process(const LEReferenceTo<SinglePositioningSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
};
struct SinglePositioningFormat1Subtable : SinglePositioningSubtable
@@ -56,7 +56,7 @@
ValueFormat valueFormat;
ValueRecord valueRecord;
- le_uint32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
+ le_uint32 process(const LEReferenceTo<SinglePositioningFormat1Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
};
struct SinglePositioningFormat2Subtable : SinglePositioningSubtable
@@ -65,8 +65,9 @@
le_uint16 valueCount;
ValueRecord valueRecordArray[ANY_NUMBER];
- le_uint32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
+ le_uint32 process(const LEReferenceTo<SinglePositioningFormat2Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
};
+LE_VAR_ARRAY(SinglePositioningFormat2Subtable, valueRecordArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/SingleSubstitutionSubtables.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SingleSubstitutionSubtables.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -39,7 +39,7 @@
U_NAMESPACE_BEGIN
-le_uint32 SingleSubstitutionSubtable::process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter) const
+le_uint32 SingleSubstitutionSubtable::process(const LEReferenceTo<SingleSubstitutionSubtable> &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
switch(SWAPW(subtableFormat))
{
@@ -48,16 +48,16 @@
case 1:
{
- const SingleSubstitutionFormat1Subtable *subtable = (const SingleSubstitutionFormat1Subtable *) this;
+ const LEReferenceTo<SingleSubstitutionFormat1Subtable> subtable(base, success, (const SingleSubstitutionFormat1Subtable *) this);
- return subtable->process(glyphIterator, filter);
+ return subtable->process(subtable, glyphIterator, success, filter);
}
case 2:
{
- const SingleSubstitutionFormat2Subtable *subtable = (const SingleSubstitutionFormat2Subtable *) this;
+ const LEReferenceTo<SingleSubstitutionFormat2Subtable> subtable(base, success, (const SingleSubstitutionFormat2Subtable *) this);
- return subtable->process(glyphIterator, filter);
+ return subtable->process(subtable, glyphIterator, success, filter);
}
default:
@@ -65,10 +65,10 @@
}
}
-le_uint32 SingleSubstitutionFormat1Subtable::process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter) const
+le_uint32 SingleSubstitutionFormat1Subtable::process(const LEReferenceTo<SingleSubstitutionFormat1Subtable> &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
- le_int32 coverageIndex = getGlyphCoverage(glyph);
+ le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (coverageIndex >= 0) {
TTGlyphID substitute = ((TTGlyphID) LE_GET_GLYPH(glyph)) + SWAPW(deltaGlyphID);
@@ -83,10 +83,10 @@
return 0;
}
-le_uint32 SingleSubstitutionFormat2Subtable::process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter) const
+le_uint32 SingleSubstitutionFormat2Subtable::process(const LEReferenceTo<SingleSubstitutionFormat2Subtable> &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
- le_int32 coverageIndex = getGlyphCoverage(glyph);
+ le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (coverageIndex >= 0) {
TTGlyphID substitute = SWAPW(substituteArray[coverageIndex]);
--- a/jdk/src/share/native/sun/font/layout/SingleSubstitutionSubtables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SingleSubstitutionSubtables.h Wed Apr 17 02:53:02 2013 -0700
@@ -47,14 +47,14 @@
struct SingleSubstitutionSubtable : GlyphSubstitutionSubtable
{
- le_uint32 process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter = NULL) const;
+ le_uint32 process(const LEReferenceTo<SingleSubstitutionSubtable> &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter = NULL) const;
};
struct SingleSubstitutionFormat1Subtable : SingleSubstitutionSubtable
{
le_int16 deltaGlyphID;
- le_uint32 process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter = NULL) const;
+ le_uint32 process(const LEReferenceTo<SingleSubstitutionFormat1Subtable> &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter = NULL) const;
};
struct SingleSubstitutionFormat2Subtable : SingleSubstitutionSubtable
@@ -62,8 +62,9 @@
le_uint16 glyphCount;
TTGlyphID substituteArray[ANY_NUMBER];
- le_uint32 process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter = NULL) const;
+ le_uint32 process(const LEReferenceTo<SingleSubstitutionFormat2Subtable> &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter = NULL) const;
};
+LE_VAR_ARRAY(SingleSubstitutionFormat2Subtable, substituteArray)
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/SingleTableProcessor.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SingleTableProcessor.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -46,26 +46,25 @@
{
}
-SingleTableProcessor::SingleTableProcessor(const MorphSubtableHeader *moprhSubtableHeader)
- : NonContextualGlyphSubstitutionProcessor(moprhSubtableHeader)
+SingleTableProcessor::SingleTableProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
+ : NonContextualGlyphSubstitutionProcessor(morphSubtableHeader, success)
{
- const NonContextualGlyphSubstitutionHeader *header = (const NonContextualGlyphSubstitutionHeader *) moprhSubtableHeader;
-
- singleTableLookupTable = (const SingleTableLookupTable *) &header->table;
+ LEReferenceTo<NonContextualGlyphSubstitutionHeader> header(morphSubtableHeader, success);
+ singleTableLookupTable = LEReferenceTo<SingleTableLookupTable>(morphSubtableHeader, success, (const SingleTableLookupTable*)&header->table);
}
SingleTableProcessor::~SingleTableProcessor()
{
}
-void SingleTableProcessor::process(LEGlyphStorage &glyphStorage)
+void SingleTableProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
const LookupSingle *entries = singleTableLookupTable->entries;
le_int32 glyph;
le_int32 glyphCount = glyphStorage.getGlyphCount();
for (glyph = 0; glyph < glyphCount; glyph += 1) {
- const LookupSingle *lookupSingle = singleTableLookupTable->lookupSingle(entries, glyphStorage[glyph]);
+ const LookupSingle *lookupSingle = singleTableLookupTable->lookupSingle(singleTableLookupTable, entries, glyphStorage[glyph], success);
if (lookupSingle != NULL) {
glyphStorage[glyph] = SWAPW(lookupSingle->value);
--- a/jdk/src/share/native/sun/font/layout/SingleTableProcessor.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SingleTableProcessor.h Wed Apr 17 02:53:02 2013 -0700
@@ -50,9 +50,9 @@
class SingleTableProcessor : public NonContextualGlyphSubstitutionProcessor
{
public:
- virtual void process(LEGlyphStorage &glyphStorage);
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success);
- SingleTableProcessor(const MorphSubtableHeader *morphSubtableHeader);
+ SingleTableProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~SingleTableProcessor();
@@ -74,7 +74,7 @@
SingleTableProcessor();
protected:
- const SingleTableLookupTable *singleTableLookupTable;
+ LEReferenceTo<SingleTableLookupTable> singleTableLookupTable;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/SingleTableProcessor2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "NonContextualGlyphSubst.h"
+#include "NonContextualGlyphSubstProc2.h"
+#include "SingleTableProcessor2.h"
+#include "LEGlyphStorage.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SingleTableProcessor2)
+
+SingleTableProcessor2::SingleTableProcessor2()
+{
+}
+
+SingleTableProcessor2::SingleTableProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+ : NonContextualGlyphSubstitutionProcessor2(morphSubtableHeader, success)
+{
+ const LEReferenceTo<NonContextualGlyphSubstitutionHeader2> header(morphSubtableHeader, success);
+
+ singleTableLookupTable = LEReferenceTo<SingleTableLookupTable>(morphSubtableHeader, success, &header->table);
+}
+
+SingleTableProcessor2::~SingleTableProcessor2()
+{
+}
+
+void SingleTableProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
+{
+ if(LE_FAILURE(success)) return;
+ const LookupSingle *entries = singleTableLookupTable->entries;
+ le_int32 glyph;
+ le_int32 glyphCount = glyphStorage.getGlyphCount();
+
+ for (glyph = 0; glyph < glyphCount; glyph += 1) {
+ const LookupSingle *lookupSingle = singleTableLookupTable->lookupSingle(singleTableLookupTable, entries, glyphStorage[glyph], success);
+
+ if (lookupSingle != NULL) {
+ glyphStorage[glyph] = SWAPW(lookupSingle->value);
+ }
+ }
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/SingleTableProcessor2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __SINGLETABLEPROCESSOR2_H
+#define __SINGLETABLEPROCESSOR2_H
+
+/**
+ * \file
+ * \internal
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "NonContextualGlyphSubst.h"
+#include "NonContextualGlyphSubstProc2.h"
+
+U_NAMESPACE_BEGIN
+
+class LEGlyphStorage;
+
+class SingleTableProcessor2 : public NonContextualGlyphSubstitutionProcessor2
+{
+public:
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success);
+
+ SingleTableProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+
+ virtual ~SingleTableProcessor2();
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for the actual class.
+ *
+ * @stable ICU 2.8
+ */
+ virtual UClassID getDynamicClassID() const;
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for this class.
+ *
+ * @stable ICU 2.8
+ */
+ static UClassID getStaticClassID();
+
+private:
+ SingleTableProcessor2();
+
+protected:
+ LEReferenceTo<SingleTableLookupTable> singleTableLookupTable;
+
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -44,17 +44,18 @@
{
}
-StateTableProcessor::StateTableProcessor(const MorphSubtableHeader *morphSubtableHeader)
- : SubtableProcessor(morphSubtableHeader)
+StateTableProcessor::StateTableProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
+ : SubtableProcessor(morphSubtableHeader, success), stateTableHeader(morphSubtableHeader, success),
+ stHeader(stateTableHeader, success, (const StateTableHeader*)&stateTableHeader->stHeader)
{
- stateTableHeader = (const MorphStateTableHeader *) morphSubtableHeader;
-
+ if(LE_FAILURE(success)) return;
stateSize = SWAPW(stateTableHeader->stHeader.stateSize);
classTableOffset = SWAPW(stateTableHeader->stHeader.classTableOffset);
stateArrayOffset = SWAPW(stateTableHeader->stHeader.stateArrayOffset);
entryTableOffset = SWAPW(stateTableHeader->stHeader.entryTableOffset);
- classTable = (const ClassTable *) ((char *) &stateTableHeader->stHeader + classTableOffset);
+ classTable = LEReferenceTo<ClassTable>(stateTableHeader, success, ((char *) &stateTableHeader->stHeader + classTableOffset));
+ if(LE_FAILURE(success)) return;
firstGlyph = SWAPW(classTable->firstGlyph);
lastGlyph = firstGlyph + SWAPW(classTable->nGlyphs);
}
@@ -63,8 +64,11 @@
{
}
-void StateTableProcessor::process(LEGlyphStorage &glyphStorage)
+void StateTableProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
+ if (LE_FAILURE(success)) return;
+ LE_STATE_PATIENCE_INIT();
+
// Start at state 0
// XXX: How do we know when to start at state 1?
ByteOffset currentState = stateArrayOffset;
@@ -76,6 +80,7 @@
beginStateTable();
while (currGlyph <= glyphCount) {
+ if(LE_STATE_PATIENCE_DECR()) break; // patience exceeded.
ClassCode classCode = classCodeOOB;
if (currGlyph == glyphCount) {
// XXX: How do we handle EOT vs. EOL?
@@ -90,10 +95,11 @@
}
}
- const EntryTableIndex *stateArray = (const EntryTableIndex *) ((char *) &stateTableHeader->stHeader + currentState);
- EntryTableIndex entryTableIndex = stateArray[(le_uint8)classCode];
-
+ LEReferenceToArrayOf<EntryTableIndex> stateArray(stHeader, success, currentState, LE_UNBOUNDED_ARRAY);
+ EntryTableIndex entryTableIndex = stateArray.getObject((le_uint8)classCode, success);
+ LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
+ LE_STATE_PATIENCE_INCR(currGlyph);
}
endStateTable();
--- a/jdk/src/share/native/sun/font/layout/StateTableProcessor.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/StateTableProcessor.h Wed Apr 17 02:53:02 2013 -0700
@@ -49,7 +49,7 @@
class StateTableProcessor : public SubtableProcessor
{
public:
- void process(LEGlyphStorage &glyphStorage);
+ void process(LEGlyphStorage &glyphStorage, LEErrorCode &success);
virtual void beginStateTable() = 0;
@@ -58,7 +58,7 @@
virtual void endStateTable() = 0;
protected:
- StateTableProcessor(const MorphSubtableHeader *morphSubtableHeader);
+ StateTableProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~StateTableProcessor();
StateTableProcessor();
@@ -68,11 +68,12 @@
ByteOffset stateArrayOffset;
ByteOffset entryTableOffset;
- const ClassTable *classTable;
+ LEReferenceTo<ClassTable> classTable;
TTGlyphID firstGlyph;
TTGlyphID lastGlyph;
- const MorphStateTableHeader *stateTableHeader;
+ LEReferenceTo<MorphStateTableHeader> stateTableHeader;
+ LEReferenceTo<StateTableHeader> stHeader; // for convenience
private:
StateTableProcessor(const StateTableProcessor &other); // forbid copying of this class
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/StateTableProcessor2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,236 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "StateTables.h"
+#include "MorphStateTables.h"
+#include "SubtableProcessor2.h"
+#include "StateTableProcessor2.h"
+#include "LEGlyphStorage.h"
+#include "LESwaps.h"
+#include "LookupTables.h"
+
+U_NAMESPACE_BEGIN
+
+StateTableProcessor2::StateTableProcessor2()
+{
+}
+
+StateTableProcessor2::StateTableProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+ : SubtableProcessor2(morphSubtableHeader, success), stateTableHeader(morphSubtableHeader, success),
+ stHeader(stateTableHeader, success, (const StateTableHeader2*)&stateTableHeader->stHeader),
+ nClasses(0), classTableOffset(0), stateArrayOffset(0), entryTableOffset(0), classTable(), format(0),
+ stateArray()
+{
+ if (LE_FAILURE(success)) {
+ return;
+ }
+ nClasses = SWAPL(stHeader->nClasses);
+ classTableOffset = SWAPL(stHeader->classTableOffset);
+ stateArrayOffset = SWAPL(stHeader->stateArrayOffset);
+ entryTableOffset = SWAPL(stHeader->entryTableOffset);
+
+ classTable = LEReferenceTo<LookupTable>(stHeader, success, classTableOffset);
+ format = SWAPW(classTable->format);
+
+ stateArray = LEReferenceToArrayOf<EntryTableIndex2>(stHeader, success, stateArrayOffset, LE_UNBOUNDED_ARRAY);
+}
+
+StateTableProcessor2::~StateTableProcessor2()
+{
+}
+
+void StateTableProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
+{
+ if (LE_FAILURE(success)) return;
+ // Start at state 0
+ // XXX: How do we know when to start at state 1?
+ le_uint16 currentState = 0;
+ le_int32 glyphCount = glyphStorage.getGlyphCount();
+
+ LE_STATE_PATIENCE_INIT();
+
+ le_int32 currGlyph = 0;
+ if ((coverage & scfReverse2) != 0) { // process glyphs in descending order
+ currGlyph = glyphCount - 1;
+ dir = -1;
+ } else {
+ dir = 1;
+ }
+
+ beginStateTable();
+ switch (format) {
+ case ltfSimpleArray: {
+#ifdef TEST_FORMAT
+ LEReferenceTo<SimpleArrayLookupTable> lookupTable0(classTable, success);
+ if(LE_FAILURE(success)) break;
+ while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
+ if (LE_FAILURE(success)) break;
+ if (LE_STATE_PATIENCE_DECR()) {
+ LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
+ break; // patience exceeded.
+ }
+ LookupValue classCode = classCodeOOB;
+ if (currGlyph == glyphCount || currGlyph == -1) {
+ // XXX: How do we handle EOT vs. EOL?
+ classCode = classCodeEOT;
+ } else {
+ LEGlyphID gid = glyphStorage[currGlyph];
+ TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
+
+ if (glyphCode == 0xFFFF) {
+ classCode = classCodeDEL;
+ } else {
+ classCode = SWAPW(lookupTable0->valueArray[gid]);
+ }
+ }
+ EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success));
+ LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
+ currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); // return a zero-based index instead of a byte offset
+ LE_STATE_PATIENCE_INCR(currGlyph);
+ }
+#endif
+ break;
+ }
+ case ltfSegmentSingle: {
+ LEReferenceTo<SegmentSingleLookupTable> lookupTable2(classTable, success);
+ if(LE_FAILURE(success)) break;
+ while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
+ if (LE_FAILURE(success)) break;
+ if (LE_STATE_PATIENCE_DECR()) {
+ LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
+ break; // patience exceeded.
+ }
+ LookupValue classCode = classCodeOOB;
+ if (currGlyph == glyphCount || currGlyph == -1) {
+ // XXX: How do we handle EOT vs. EOL?
+ classCode = classCodeEOT;
+ } else {
+ LEGlyphID gid = glyphStorage[currGlyph];
+ TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
+
+ if (glyphCode == 0xFFFF) {
+ classCode = classCodeDEL;
+ } else {
+ const LookupSegment *segment =
+ lookupTable2->lookupSegment(lookupTable2, lookupTable2->segments, gid, success);
+ if (segment != NULL && LE_SUCCESS(success)) {
+ classCode = SWAPW(segment->value);
+ }
+ }
+ }
+ EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses,success));
+ LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
+ currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success);
+ LE_STATE_PATIENCE_INCR(currGlyph);
+ }
+ break;
+ }
+ case ltfSegmentArray: {
+ //printf("Lookup Table Format4: specific interpretation needed!\n");
+ break;
+ }
+ case ltfSingleTable: {
+ LEReferenceTo<SingleTableLookupTable> lookupTable6(classTable, success);
+ while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
+ if (LE_FAILURE(success)) break;
+ if (LE_STATE_PATIENCE_DECR()) {
+ LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
+ break; // patience exceeded.
+ }
+ LookupValue classCode = classCodeOOB;
+ if (currGlyph == glyphCount || currGlyph == -1) {
+ // XXX: How do we handle EOT vs. EOL?
+ classCode = classCodeEOT;
+ } else if(currGlyph > glyphCount) {
+ // note if > glyphCount, we've run off the end (bad font)
+ currGlyph = glyphCount;
+ classCode = classCodeEOT;
+ } else {
+ LEGlyphID gid = glyphStorage[currGlyph];
+ TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
+
+ if (glyphCode == 0xFFFF) {
+ classCode = classCodeDEL;
+ } else {
+ const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6, lookupTable6->entries, gid, success);
+ if (segment != NULL) {
+ classCode = SWAPW(segment->value);
+ }
+ }
+ }
+ EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success));
+ LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
+ currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success);
+ LE_STATE_PATIENCE_INCR(currGlyph);
+ }
+ break;
+ }
+ case ltfTrimmedArray: {
+ LEReferenceTo<TrimmedArrayLookupTable> lookupTable8(classTable, success);
+ if (LE_FAILURE(success)) break;
+ TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph);
+ TTGlyphID lastGlyph = firstGlyph + SWAPW(lookupTable8->glyphCount);
+
+ while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
+ if(LE_STATE_PATIENCE_DECR()) {
+ LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
+ break; // patience exceeded.
+ }
+
+ LookupValue classCode = classCodeOOB;
+ if (currGlyph == glyphCount || currGlyph == -1) {
+ // XXX: How do we handle EOT vs. EOL?
+ classCode = classCodeEOT;
+ } else {
+ TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(glyphStorage[currGlyph]);
+ if (glyphCode == 0xFFFF) {
+ classCode = classCodeDEL;
+ } else if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) {
+ classCode = SWAPW(lookupTable8->valueArray[glyphCode - firstGlyph]);
+ }
+ }
+ EntryTableIndex2 entryTableIndex = SWAPW(stateArray(classCode + currentState * nClasses, success));
+ LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
+ currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex, success);
+ LE_STATE_PATIENCE_INCR(currGlyph);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ endStateTable();
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/StateTableProcessor2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __STATETABLEPROCESSOR2_H
+#define __STATETABLEPROCESSOR2_H
+
+/**
+ * \file
+ * \internal
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "MorphStateTables.h"
+#include "SubtableProcessor2.h"
+#include "LookupTables.h"
+
+U_NAMESPACE_BEGIN
+
+class LEGlyphStorage;
+
+class StateTableProcessor2 : public SubtableProcessor2
+{
+public:
+ void process(LEGlyphStorage &glyphStorage, LEErrorCode &success);
+
+ virtual void beginStateTable() = 0;
+
+ virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success) = 0;
+
+ virtual void endStateTable() = 0;
+
+protected:
+ StateTableProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+ virtual ~StateTableProcessor2();
+
+ StateTableProcessor2();
+
+ le_int32 dir;
+ le_uint16 format;
+ le_uint32 nClasses;
+ le_uint32 classTableOffset;
+ le_uint32 stateArrayOffset;
+ le_uint32 entryTableOffset;
+
+ LEReferenceTo<LookupTable> classTable;
+ LEReferenceToArrayOf<EntryTableIndex2> stateArray;
+ LEReferenceTo<MorphStateTableHeader2> stateTableHeader;
+ LEReferenceTo<StateTableHeader2> stHeader; // for convenience
+
+private:
+ StateTableProcessor2(const StateTableProcessor2 &other); // forbid copying of this class
+ StateTableProcessor2 &operator=(const StateTableProcessor2 &other); // forbid copying of this class
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/StateTables.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/StateTables.h Wed Apr 17 02:53:02 2013 -0700
@@ -25,7 +25,7 @@
/*
*
- * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
*
*/
@@ -42,6 +42,41 @@
U_NAMESPACE_BEGIN
+
+
+
+/*
+ * State table loop detection.
+ * Detects if too many ( LE_STATE_PATIENCE_COUNT ) state changes occur without moving the glyph index 'g'.
+ *
+ * Usage (pseudocode):
+ *
+ * {
+ * LE_STATE_PATIENCE_INIT();
+ *
+ * int g=0; // the glyph index - expect it to be moving
+ *
+ * for(;;) {
+ * if(LE_STATE_PATIENCE_DECR()) { // decrements the patience counter
+ * // ran out of patience, get out.
+ * break;
+ * }
+ *
+ * LE_STATE_PATIENCE_CURR(int, g); // store the 'current'
+ * state = newState(state,g);
+ * g+= <something, could be zero>;
+ * LE_STATE_PATIENCE_INCR(g); // if g has moved, increment the patience counter. Otherwise leave it.
+ * }
+ *
+ */
+
+#define LE_STATE_PATIENCE_COUNT 4096 /**< give up if a state table doesn't move the glyph after this many iterations */
+#define LE_STATE_PATIENCE_INIT() le_uint32 le_patience_count = LE_STATE_PATIENCE_COUNT
+#define LE_STATE_PATIENCE_DECR() --le_patience_count==0
+#define LE_STATE_PATIENCE_CURR(type,x) type le_patience_curr=(x)
+#define LE_STATE_PATIENCE_INCR(x) if((x)!=le_patience_curr) ++le_patience_count;
+
+
struct StateTableHeader
{
le_int16 stateSize;
@@ -50,6 +85,14 @@
ByteOffset entryTableOffset;
};
+struct StateTableHeader2
+{
+ le_uint32 nClasses;
+ le_uint32 classTableOffset;
+ le_uint32 stateArrayOffset;
+ le_uint32 entryTableOffset;
+};
+
enum ClassCodes
{
classCodeEOT = 0,
@@ -68,6 +111,7 @@
le_uint16 nGlyphs;
ClassCode classArray[ANY_NUMBER];
};
+LE_VAR_ARRAY(ClassTable, classArray)
enum StateNumber
{
@@ -85,6 +129,14 @@
le_int16 flags;
};
+typedef le_uint16 EntryTableIndex2;
+
+struct StateEntry2 // same struct different interpretation
+{
+ le_uint16 newStateIndex;
+ le_uint16 flags;
+};
+
U_NAMESPACE_END
#endif
--- a/jdk/src/share/native/sun/font/layout/SubtableProcessor.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SubtableProcessor.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -40,10 +40,10 @@
{
}
-SubtableProcessor::SubtableProcessor(const MorphSubtableHeader *morphSubtableHeader)
+SubtableProcessor::SubtableProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
+ : length(0), coverage(0), subtableFeatures(0L), subtableHeader(morphSubtableHeader)
{
- subtableHeader = morphSubtableHeader;
-
+ if(LE_FAILURE(success)) return;
length = SWAPW(subtableHeader->length);
coverage = SWAPW(subtableHeader->coverage);
subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
--- a/jdk/src/share/native/sun/font/layout/SubtableProcessor.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SubtableProcessor.h Wed Apr 17 02:53:02 2013 -0700
@@ -46,11 +46,11 @@
class SubtableProcessor : public UMemory {
public:
- virtual void process(LEGlyphStorage &glyphStorage) = 0;
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success) = 0;
virtual ~SubtableProcessor();
protected:
- SubtableProcessor(const MorphSubtableHeader *morphSubtableHeader);
+ SubtableProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
SubtableProcessor();
@@ -58,7 +58,7 @@
SubtableCoverage coverage;
FeatureFlags subtableFeatures;
- const MorphSubtableHeader *subtableHeader;
+ const LEReferenceTo<MorphSubtableHeader> subtableHeader;
private:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/SubtableProcessor2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+SubtableProcessor2::SubtableProcessor2()
+{
+}
+
+SubtableProcessor2::SubtableProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+ : subtableHeader(morphSubtableHeader, success), length(0), coverage(0), subtableFeatures(0L)
+{
+ if(LE_FAILURE(success)) return;
+
+ length = SWAPL(subtableHeader->length);
+ coverage = SWAPL(subtableHeader->coverage);
+ subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
+}
+
+SubtableProcessor2::~SubtableProcessor2()
+{
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/SubtableProcessor2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __SUBTABLEPROCESSOR2_H
+#define __SUBTABLEPROCESSOR2_H
+
+/**
+ * \file
+ * \internal
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+
+U_NAMESPACE_BEGIN
+
+class LEGlyphStorage;
+
+class SubtableProcessor2 : public UMemory {
+public:
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success) = 0;
+ virtual ~SubtableProcessor2();
+
+protected:
+ SubtableProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+
+ SubtableProcessor2();
+
+ le_uint32 length;
+ SubtableCoverage2 coverage;
+ FeatureFlags subtableFeatures;
+
+ const LEReferenceTo<MorphSubtableHeader2> subtableHeader;
+
+private:
+
+ SubtableProcessor2(const SubtableProcessor2 &other); // forbid copying of this class
+ SubtableProcessor2 &operator=(const SubtableProcessor2 &other); // forbid copying of this class
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/ThaiLayoutEngine.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ThaiLayoutEngine.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -134,11 +134,10 @@
return;
}
- if (fTypoFlags & 0x1) { /* kerning enabled */
- static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG;
-
- KernTable kt(fFontInstance, getFontTable(kernTableTag));
- kt.process(glyphStorage);
+ if (fTypoFlags & LE_Kerning_FEATURE_FLAG) { /* kerning enabled */
+ LETableReference kernTable(fFontInstance, LE_KERN_TABLE_TAG, success);
+ KernTable kt(kernTable, success);
+ kt.process(glyphStorage, success);
}
// default is no adjustments
--- a/jdk/src/share/native/sun/font/layout/TibetanLayoutEngine.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/TibetanLayoutEngine.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -49,7 +49,7 @@
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TibetanOpenTypeLayoutEngine)
TibetanOpenTypeLayoutEngine::TibetanOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
+ le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
{
fFeatureMap = TibetanReordering::getFeatureMap(fFeatureMapCount);
--- a/jdk/src/share/native/sun/font/layout/TibetanLayoutEngine.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/TibetanLayoutEngine.h Wed Apr 17 02:53:02 2013 -0700
@@ -83,7 +83,7 @@
* @internal
*/
TibetanOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
- le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success);
+ le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success);
/**
* This constructor is used when the font requires a "canned" GSUB table which can't be known
--- a/jdk/src/share/native/sun/font/layout/TrimmedArrayProcessor.cpp Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/TrimmedArrayProcessor.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -46,22 +46,28 @@
{
}
-TrimmedArrayProcessor::TrimmedArrayProcessor(const MorphSubtableHeader *morphSubtableHeader)
- : NonContextualGlyphSubstitutionProcessor(morphSubtableHeader)
+TrimmedArrayProcessor::TrimmedArrayProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
+ : NonContextualGlyphSubstitutionProcessor(morphSubtableHeader, success), firstGlyph(0), lastGlyph(0)
{
- const NonContextualGlyphSubstitutionHeader *header = (const NonContextualGlyphSubstitutionHeader *) morphSubtableHeader;
+ LEReferenceTo<NonContextualGlyphSubstitutionHeader> header(morphSubtableHeader, success);
+
+ if(LE_FAILURE(success)) return;
- trimmedArrayLookupTable = (const TrimmedArrayLookupTable *) &header->table;
- firstGlyph = SWAPW(trimmedArrayLookupTable->firstGlyph);
- lastGlyph = firstGlyph + SWAPW(trimmedArrayLookupTable->glyphCount);
+ trimmedArrayLookupTable = LEReferenceTo<TrimmedArrayLookupTable>(morphSubtableHeader, success, (const TrimmedArrayLookupTable*)&header->table);
+
+ if(LE_FAILURE(success)) return;
+
+ firstGlyph = SWAPW(trimmedArrayLookupTable->firstGlyph);
+ lastGlyph = firstGlyph + SWAPW(trimmedArrayLookupTable->glyphCount);
}
TrimmedArrayProcessor::~TrimmedArrayProcessor()
{
}
-void TrimmedArrayProcessor::process(LEGlyphStorage &glyphStorage)
+void TrimmedArrayProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
+ if(LE_FAILURE(success)) return;
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 glyph;
--- a/jdk/src/share/native/sun/font/layout/TrimmedArrayProcessor.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/TrimmedArrayProcessor.h Wed Apr 17 02:53:02 2013 -0700
@@ -50,9 +50,9 @@
class TrimmedArrayProcessor : public NonContextualGlyphSubstitutionProcessor
{
public:
- virtual void process(LEGlyphStorage &glyphStorage);
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success);
- TrimmedArrayProcessor(const MorphSubtableHeader *morphSubtableHeader);
+ TrimmedArrayProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~TrimmedArrayProcessor();
@@ -76,7 +76,7 @@
protected:
TTGlyphID firstGlyph;
TTGlyphID lastGlyph;
- const TrimmedArrayLookupTable *trimmedArrayLookupTable;
+ LEReferenceTo<TrimmedArrayLookupTable> trimmedArrayLookupTable;
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/TrimmedArrayProcessor2.cpp Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "NonContextualGlyphSubst.h"
+#include "NonContextualGlyphSubstProc2.h"
+#include "TrimmedArrayProcessor2.h"
+#include "LEGlyphStorage.h"
+#include "LESwaps.h"
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TrimmedArrayProcessor2)
+
+TrimmedArrayProcessor2::TrimmedArrayProcessor2()
+{
+}
+
+TrimmedArrayProcessor2::TrimmedArrayProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
+ : NonContextualGlyphSubstitutionProcessor2(morphSubtableHeader, success)
+{
+ const LEReferenceTo<NonContextualGlyphSubstitutionHeader2> header(morphSubtableHeader, success);
+
+ trimmedArrayLookupTable = LEReferenceTo<TrimmedArrayLookupTable>(morphSubtableHeader, success, &header->table);
+ firstGlyph = SWAPW(trimmedArrayLookupTable->firstGlyph);
+ lastGlyph = firstGlyph + SWAPW(trimmedArrayLookupTable->glyphCount);
+ valueArray = LEReferenceToArrayOf<LookupValue>(morphSubtableHeader, success, &trimmedArrayLookupTable->valueArray[0], LE_UNBOUNDED_ARRAY);
+}
+
+TrimmedArrayProcessor2::~TrimmedArrayProcessor2()
+{
+}
+
+void TrimmedArrayProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
+{
+ if(LE_FAILURE(success)) return;
+ le_int32 glyphCount = glyphStorage.getGlyphCount();
+ le_int32 glyph;
+
+ for (glyph = 0; glyph < glyphCount; glyph += 1) {
+ LEGlyphID thisGlyph = glyphStorage[glyph];
+ TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(thisGlyph);
+
+ if ((ttGlyph > firstGlyph) && (ttGlyph < lastGlyph)) {
+ TTGlyphID newGlyph = SWAPW(valueArray(ttGlyph - firstGlyph, success));
+
+ glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
+ }
+ }
+}
+
+U_NAMESPACE_END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/font/layout/TrimmedArrayProcessor2.h Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ *
+ */
+
+/*
+ *
+ * (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __TRIMMEDARRAYPROCESSOR2_H
+#define __TRIMMEDARRAYPROCESSOR2_H
+
+/**
+ * \file
+ * \internal
+ */
+
+#include "LETypes.h"
+#include "MorphTables.h"
+#include "SubtableProcessor2.h"
+#include "NonContextualGlyphSubst.h"
+#include "NonContextualGlyphSubstProc2.h"
+
+U_NAMESPACE_BEGIN
+
+class LEGlyphStorage;
+
+class TrimmedArrayProcessor2 : public NonContextualGlyphSubstitutionProcessor2
+{
+public:
+ virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success);
+
+ TrimmedArrayProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
+
+ virtual ~TrimmedArrayProcessor2();
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for the actual class.
+ *
+ * @stable ICU 2.8
+ */
+ virtual UClassID getDynamicClassID() const;
+
+ /**
+ * ICU "poor man's RTTI", returns a UClassID for this class.
+ *
+ * @stable ICU 2.8
+ */
+ static UClassID getStaticClassID();
+
+private:
+ TrimmedArrayProcessor2();
+
+protected:
+ TTGlyphID firstGlyph;
+ TTGlyphID lastGlyph;
+ LEReferenceTo<TrimmedArrayLookupTable> trimmedArrayLookupTable;
+ LEReferenceToArrayOf<LookupValue> valueArray;
+};
+
+U_NAMESPACE_END
+#endif
--- a/jdk/src/share/native/sun/font/layout/ValueRecords.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/ValueRecords.h Wed Apr 17 02:53:02 2013 -0700
@@ -64,6 +64,7 @@
static le_int16 getFieldCount(ValueFormat valueFormat);
static le_int16 getFieldIndex(ValueFormat valueFormat, ValueRecordField field);
};
+LE_VAR_ARRAY(ValueRecord, values)
enum ValueRecordFields
{
--- a/jdk/src/share/native/sun/font/sunFont.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/font/sunFont.c Wed Apr 17 02:53:02 2013 -0700
@@ -320,22 +320,20 @@
JNIEXPORT TTLayoutTableCache* newLayoutTableCache() {
TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache));
if (ltc) {
- ltc->gsub_len = -1;
- ltc->gpos_len = -1;
- ltc->gdef_len = -1;
- ltc->mort_len = -1;
- ltc->kern_len = -1;
+ int i;
+ for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {
+ ltc->entries[i].len = -1;
+ }
}
return ltc;
}
JNIEXPORT void freeLayoutTableCache(TTLayoutTableCache* ltc) {
if (ltc) {
- if (ltc->gsub) free(ltc->gsub);
- if (ltc->gpos) free(ltc->gpos);
- if (ltc->gdef) free(ltc->gdef);
- if (ltc->mort) free(ltc->mort);
- if (ltc->kern) free(ltc->kern);
+ int i;
+ for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {
+ if(ltc->entries[i].ptr) free (ltc->entries[i].ptr);
+ }
if (ltc->kernPairs) free(ltc->kernPairs);
free(ltc);
}
--- a/jdk/src/share/native/sun/reflect/Reflection.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/share/native/sun/reflect/Reflection.c Wed Apr 17 02:53:02 2013 -0700
@@ -27,9 +27,9 @@
#include "sun_reflect_Reflection.h"
JNIEXPORT jclass JNICALL Java_sun_reflect_Reflection_getCallerClass
-(JNIEnv *env, jclass unused, jint depth)
+(JNIEnv *env, jclass unused)
{
- return JVM_GetCallerClass(env, depth);
+ return JVM_GetCallerClass(env, JVM_DEPTH); // JVM_DEPTH is only the expected value
}
JNIEXPORT jint JNICALL Java_sun_reflect_Reflection_getClassAccessFlags
--- a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -993,8 +993,8 @@
XLayerProtocol.LAYER_NORMAL);
}
- public void setAlwaysOnTop(boolean alwaysOnTop) {
- this.alwaysOnTop = alwaysOnTop;
+ public void updateAlwaysOnTopState() {
+ this.alwaysOnTop = ((Window) this.target).isAlwaysOnTop();
updateAlwaysOnTop();
}
--- a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c Wed Apr 17 02:53:02 2013 -0700
@@ -135,9 +135,6 @@
ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
- ni_iaaddressID = (*env)->GetFieldID(env, ni_iacls, "address", "I");
- ni_iafamilyID = (*env)->GetFieldID(env, ni_iacls, "family", "I");
- ni_iahostID = (*env)->GetFieldID(env, ni_iacls, "hostName", "Ljava/lang/String;");
initialized = 1;
}
@@ -238,9 +235,8 @@
ret = NULL;
goto cleanupAndReturn;
}
- (*env)->SetIntField(env, iaObj, ni_iaaddressID,
- ntohl(((struct sockaddr_in*)(iterator->ai_addr))->sin_addr.s_addr));
- (*env)->SetObjectField(env, iaObj, ni_iahostID, name);
+ setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)(iterator->ai_addr))->sin_addr.s_addr));
+ setInetAddress_hostName(env, iaObj, name);
(*env)->SetObjectArrayElement(env, ret, retLen - i -1, iaObj);
i++;
iterator = iterator->ai_next;
@@ -372,9 +368,6 @@
static jclass ni_iacls;
static jclass ni_ia4cls;
static jmethodID ni_ia4ctrID;
-static jfieldID ni_iaaddressID;
-static jfieldID ni_iahostID;
-static jfieldID ni_iafamilyID;
static int initialized = 0;
/*
@@ -403,9 +396,6 @@
ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
- ni_iaaddressID = (*env)->GetFieldID(env, ni_iacls, "address", "I");
- ni_iafamilyID = (*env)->GetFieldID(env, ni_iacls, "family", "I");
- ni_iahostID = (*env)->GetFieldID(env, ni_iacls, "hostName", "Ljava/lang/String;");
initialized = 1;
}
@@ -499,9 +489,8 @@
ret = NULL;
goto cleanupAndReturn;
}
- (*env)->SetIntField(env, iaObj, ni_iaaddressID,
- ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
- (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
+ setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
+ setInetAddress_hostName(env, iaObj, host);
(*env)->SetObjectArrayElement(env, ret, i++, iaObj);
iterator = iterator->ai_next;
}
--- a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c Wed Apr 17 02:53:02 2013 -0700
@@ -120,9 +120,6 @@
static jclass ni_ia6cls;
static jmethodID ni_ia4ctrID;
static jmethodID ni_ia6ctrID;
-static jfieldID ni_iaaddressID;
-static jfieldID ni_iahostID;
-static jfieldID ni_iafamilyID;
static jfieldID ni_ia6ipaddressID;
static int initialized = 0;
@@ -159,9 +156,6 @@
ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
- ni_iaaddressID = (*env)->GetFieldID(env, ni_iacls, "address", "I");
- ni_iafamilyID = (*env)->GetFieldID(env, ni_iacls, "family", "I");
- ni_iahostID = (*env)->GetFieldID(env, ni_iacls, "hostName", "Ljava/lang/String;");
ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
initialized = 1;
}
@@ -315,9 +309,8 @@
ret = NULL;
goto cleanupAndReturn;
}
- (*env)->SetIntField(env, iaObj, ni_iaaddressID,
- ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
- (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
+ setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
+ setInetAddress_hostName(env, iaObj, host);
(*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
inetIndex++;
} else if (iterator->ai_family == AF_INET6) {
@@ -342,7 +335,7 @@
(*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
}
(*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
- (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
+ setInetAddress_hostName(env, iaObj, host);
(*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
inet6Index++;
}
--- a/jdk/src/solaris/native/java/net/NetworkInterface.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/solaris/native/java/net/NetworkInterface.c Wed Apr 17 02:53:02 2013 -0700
@@ -118,8 +118,6 @@
static jmethodID ni_ia4ctrID;
static jmethodID ni_ia6ctrID;
static jmethodID ni_ibctrID;
-static jfieldID ni_iaaddressID;
-static jfieldID ni_iafamilyID;
static jfieldID ni_ia6ipaddressID;
static jfieldID ni_ibaddressID;
static jfieldID ni_ib4broadcastID;
@@ -195,8 +193,6 @@
ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");
- ni_iaaddressID = (*env)->GetFieldID(env, ni_iacls, "address", "I");
- ni_iafamilyID = (*env)->GetFieldID(env, ni_iacls, "family", "I");
ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");
ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");
@@ -300,7 +296,7 @@
netif *ifs, *curr;
#ifdef AF_INET6
- int family = ( (*env)->GetIntField(env, iaObj, ni_iafamilyID) == IPv4 ) ? AF_INET : AF_INET6;
+ int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6;
#else
int family = AF_INET;
#endif
@@ -325,7 +321,7 @@
if (family == addrP->family) {
if (family == AF_INET) {
int address1 = htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr);
- int address2 = (*env)->GetIntField(env, iaObj, ni_iaaddressID);
+ int address2 = getInetAddress_addr(env, iaObj);
if (address1 == address2) {
match = JNI_TRUE;
@@ -651,7 +647,7 @@
if (addrP->family == AF_INET) {
iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
if (iaObj) {
- (*env)->SetIntField(env, iaObj, ni_iaaddressID, htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
+ setInetAddress_addr(env, iaObj, htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
}
ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
if (ibObj) {
@@ -660,8 +656,7 @@
jobject ia2Obj = NULL;
ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
if (ia2Obj) {
- (*env)->SetIntField(env, ia2Obj, ni_iaaddressID,
- htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
+ setInetAddress_addr(env, ia2Obj, htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
(*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
(*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
}
--- a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c Wed Apr 17 02:53:02 2013 -0700
@@ -552,14 +552,13 @@
iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&remote_addr, &port);
#ifdef AF_INET6
- family = (*env)->GetIntField(env, iaObj, ia_familyID) == IPv4?
- AF_INET : AF_INET6;
+ family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
#else
family = AF_INET;
#endif
if (family == AF_INET) { /* this API can't handle IPV6 addresses */
- int address = (*env)->GetIntField(env, iaObj, ia_addressID);
- (*env)->SetIntField(env, addressObj, ia_addressID, address);
+ int address = getInetAddress_addr(env, iaObj);
+ setInetAddress_addr(env, addressObj, address);
}
return port;
}
@@ -1028,23 +1027,18 @@
*/
static void mcast_set_if_by_if_v4(JNIEnv *env, jobject this, int fd, jobject value) {
static jfieldID ni_addrsID;
- static jfieldID ia_addressID;
struct in_addr in;
jobjectArray addrArray;
jsize len;
jobject addr;
int i;
- if (ni_addrsID == NULL || ia_addressID == NULL) {
+ if (ni_addrsID == NULL ) {
jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
CHECK_NULL(c);
ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
"[Ljava/net/InetAddress;");
CHECK_NULL(ni_addrsID);
- c = (*env)->FindClass(env,"java/net/InetAddress");
- CHECK_NULL(c);
- ia_addressID = (*env)->GetFieldID(env, c, "address", "I");
- CHECK_NULL(ia_addressID);
}
addrArray = (*env)->GetObjectField(env, value, ni_addrsID);
@@ -1065,8 +1059,8 @@
*/
for (i = 0; i < len; i++) {
addr = (*env)->GetObjectArrayElement(env, addrArray, i);
- if ((*env)->GetIntField(env, addr, ia_familyID) == IPv4) {
- in.s_addr = htonl((*env)->GetIntField(env, addr, ia_addressID));
+ if (getInetAddress_family(env, addr) == IPv4) {
+ in.s_addr = htonl(getInetAddress_addr(env, addr));
break;
}
}
@@ -1116,17 +1110,9 @@
* Throw exception if failed.
*/
static void mcast_set_if_by_addr_v4(JNIEnv *env, jobject this, int fd, jobject value) {
- static jfieldID ia_addressID;
struct in_addr in;
- if (ia_addressID == NULL) {
- jclass c = (*env)->FindClass(env,"java/net/InetAddress");
- CHECK_NULL(c);
- ia_addressID = (*env)->GetFieldID(env, c, "address", "I");
- CHECK_NULL(ia_addressID);
- }
-
- in.s_addr = htonl( (*env)->GetIntField(env, value, ia_addressID) );
+ in.s_addr = htonl( getInetAddress_addr(env, value) );
if (JVM_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF,
(const char*)&in, sizeof(in)) < 0) {
@@ -1456,7 +1442,6 @@
if (isIPV4) {
static jclass inet4_class;
static jmethodID inet4_ctrID;
- static jfieldID inet4_addrID;
static jclass ni_class;
static jmethodID ni_ctrID;
@@ -1486,15 +1471,13 @@
CHECK_NULL_RETURN(c, NULL);
inet4_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
CHECK_NULL_RETURN(inet4_ctrID, NULL);
- inet4_addrID = (*env)->GetFieldID(env, c, "address", "I");
- CHECK_NULL_RETURN(inet4_addrID, NULL);
inet4_class = (*env)->NewGlobalRef(env, c);
CHECK_NULL_RETURN(inet4_class, NULL);
}
addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0);
CHECK_NULL_RETURN(addr, NULL);
- (*env)->SetIntField(env, addr, inet4_addrID, ntohl(in.s_addr));
+ setInetAddress_addr(env, addr, ntohl(in.s_addr));
/*
* For IP_MULTICAST_IF return InetAddress
@@ -1942,7 +1925,7 @@
ipv6_join_leave = ipv6_available();
#ifdef __linux__
- if ((*env)->GetIntField(env, iaObj, ia_familyID) == IPv4) {
+ if (getInetAddress_family(env, iaObj) == IPv4) {
ipv6_join_leave = JNI_FALSE;
}
#endif
@@ -1989,7 +1972,7 @@
CHECK_NULL(ni_indexID);
}
- mname.imr_multiaddr.s_addr = htonl((*env)->GetIntField(env, iaObj, ia_addressID));
+ mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj));
mname.imr_address.s_addr = 0;
mname.imr_ifindex = (*env)->GetIntField(env, niObj, ni_indexID);
mname_len = sizeof(struct ip_mreqn);
@@ -2007,11 +1990,11 @@
}
addr = (*env)->GetObjectArrayElement(env, addrArray, 0);
- mname.imr_multiaddr.s_addr = htonl((*env)->GetIntField(env, iaObj, ia_addressID));
+ mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj));
#ifdef __linux__
- mname.imr_address.s_addr = htonl((*env)->GetIntField(env, addr, ia_addressID));
+ mname.imr_address.s_addr = htonl(getInetAddress_addr(env, addr));
#else
- mname.imr_interface.s_addr = htonl((*env)->GetIntField(env, addr, ia_addressID));
+ mname.imr_interface.s_addr = htonl(getInetAddress_addr(env, addr));
#endif
mname_len = sizeof(struct ip_mreq);
}
@@ -2046,7 +2029,7 @@
return;
}
- mname.imr_multiaddr.s_addr = htonl((*env)->GetIntField(env, iaObj, ia_addressID));
+ mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj));
mname.imr_address.s_addr = 0 ;
mname.imr_ifindex = index;
mname_len = sizeof(struct ip_mreqn);
@@ -2068,7 +2051,7 @@
#else
mname.imr_interface.s_addr = in.s_addr;
#endif
- mname.imr_multiaddr.s_addr = htonl((*env)->GetIntField(env, iaObj, ia_addressID));
+ mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj));
mname_len = sizeof(struct ip_mreq);
}
}
@@ -2133,10 +2116,10 @@
jbyte caddr[16];
jint family;
jint address;
- family = (*env)->GetIntField(env, iaObj, ia_familyID) == IPv4? AF_INET : AF_INET6;
+ family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
if (family == AF_INET) { /* will convert to IPv4-mapped address */
memset((char *) caddr, 0, 16);
- address = (*env)->GetIntField(env, iaObj, ia_addressID);
+ address = getInetAddress_addr(env, iaObj);
caddr[10] = 0xff;
caddr[11] = 0xff;
--- a/jdk/src/solaris/native/java/net/net_util_md.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/solaris/native/java/net/net_util_md.c Wed Apr 17 02:53:02 2013 -0700
@@ -777,7 +777,7 @@
NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,
int *len, jboolean v4MappedAddress) {
jint family;
- family = (*env)->GetIntField(env, iaObj, ia_familyID);
+ family = getInetAddress_family(env, iaObj);
#ifdef AF_INET6
/* needs work. 1. family 2. clean up him6 etc deallocate memory */
if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) {
@@ -789,7 +789,7 @@
if (family == IPv4) { /* will convert to IPv4-mapped address */
memset((char *) caddr, 0, 16);
- address = (*env)->GetIntField(env, iaObj, ia_addressID);
+ address = getInetAddress_addr(env, iaObj);
if (address == INADDR_ANY) {
/* we would always prefer IPv6 wildcard address
caddr[10] = 0xff;
@@ -898,7 +898,7 @@
return -1;
}
memset((char *) him4, 0, sizeof(struct sockaddr_in));
- address = (*env)->GetIntField(env, iaObj, ia_addressID);
+ address = getInetAddress_addr(env, iaObj);
him4->sin_port = htons((short) port);
him4->sin_addr.s_addr = (uint32_t) htonl(address);
him4->sin_family = AF_INET;
--- a/jdk/src/windows/classes/java/lang/ProcessImpl.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/classes/java/lang/ProcessImpl.java Wed Apr 17 02:53:02 2013 -0700
@@ -145,6 +145,88 @@
}
+ // We guarantee the only command file execution for implicit [cmd.exe] run.
+ // http://technet.microsoft.com/en-us/library/bb490954.aspx
+ private static final char CMD_BAT_ESCAPE[] = {' ', '\t', '<', '>', '&', '|', '^'};
+ private static final char WIN32_EXECUTABLE_ESCAPE[] = {' ', '\t', '<', '>'};
+
+ private static boolean isQuoted(boolean noQuotesInside, String arg,
+ String errorMessage) {
+ int lastPos = arg.length() - 1;
+ if (lastPos >=1 && arg.charAt(0) == '"' && arg.charAt(lastPos) == '"') {
+ // The argument has already been quoted.
+ if (noQuotesInside) {
+ if (arg.indexOf('"', 1) != lastPos) {
+ // There is ["] inside.
+ throw new IllegalArgumentException(errorMessage);
+ }
+ }
+ return true;
+ }
+ if (noQuotesInside) {
+ if (arg.indexOf('"') >= 0) {
+ // There is ["] inside.
+ throw new IllegalArgumentException(errorMessage);
+ }
+ }
+ return false;
+ }
+
+ private static boolean needsEscaping(boolean isCmdFile, String arg) {
+ // Switch off MS heuristic for internal ["].
+ // Please, use the explicit [cmd.exe] call
+ // if you need the internal ["].
+ // Example: "cmd.exe", "/C", "Extended_MS_Syntax"
+
+ // For [.exe] or [.com] file the unpaired/internal ["]
+ // in the argument is not a problem.
+ boolean argIsQuoted = isQuoted(isCmdFile, arg,
+ "Argument has embedded quote, use the explicit CMD.EXE call.");
+
+ if (!argIsQuoted) {
+ char testEscape[] = isCmdFile
+ ? CMD_BAT_ESCAPE
+ : WIN32_EXECUTABLE_ESCAPE;
+ for (int i = 0; i < testEscape.length; ++i) {
+ if (arg.indexOf(testEscape[i]) >= 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static String getExecutablePath(String path)
+ throws IOException
+ {
+ boolean pathIsQuoted = isQuoted(true, path,
+ "Executable name has embedded quote, split the arguments");
+
+ // Win32 CreateProcess requires path to be normalized
+ File fileToRun = new File(pathIsQuoted
+ ? path.substring(1, path.length() - 1)
+ : path);
+
+ // From the [CreateProcess] function documentation:
+ //
+ // "If the file name does not contain an extension, .exe is appended.
+ // Therefore, if the file name extension is .com, this parameter
+ // must include the .com extension. If the file name ends in
+ // a period (.) with no extension, or if the file name contains a path,
+ // .exe is not appended."
+ //
+ // "If the file name !does not contain a directory path!,
+ // the system searches for the executable file in the following
+ // sequence:..."
+ //
+ // In practice ANY non-existent path is extended by [.exe] extension
+ // in the [CreateProcess] funcion with the only exception:
+ // the path ends by (.)
+
+ return fileToRun.getPath();
+ }
+
+
private long handle = 0;
private OutputStream stdin_stream;
private InputStream stdout_stream;
@@ -157,30 +239,47 @@
final boolean redirectErrorStream)
throws IOException
{
- // Win32 CreateProcess requires cmd[0] to be normalized
- cmd[0] = new File(cmd[0]).getPath();
+ // The [executablePath] is not quoted for any case.
+ String executablePath = getExecutablePath(cmd[0]);
+
+ // We need to extend the argument verification procedure
+ // to guarantee the only command file execution for implicit [cmd.exe]
+ // run.
+ String upPath = executablePath.toUpperCase();
+ boolean isCmdFile = (upPath.endsWith(".CMD") || upPath.endsWith(".BAT"));
StringBuilder cmdbuf = new StringBuilder(80);
- for (int i = 0; i < cmd.length; i++) {
- if (i > 0) {
- cmdbuf.append(' ');
- }
+
+ // Quotation protects from interpretation of the [path] argument as
+ // start of longer path with spaces. Quotation has no influence to
+ // [.exe] extension heuristic.
+ cmdbuf.append('"');
+ cmdbuf.append(executablePath);
+ cmdbuf.append('"');
+
+ for (int i = 1; i < cmd.length; i++) {
+ cmdbuf.append(' ');
String s = cmd[i];
- if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) {
- if (s.charAt(0) != '"') {
- cmdbuf.append('"');
- cmdbuf.append(s);
- if (s.endsWith("\\")) {
- cmdbuf.append("\\");
- }
- cmdbuf.append('"');
- } else if (s.endsWith("\"")) {
- /* The argument has already been quoted. */
- cmdbuf.append(s);
- } else {
- /* Unmatched quote for the argument. */
- throw new IllegalArgumentException();
+ if (needsEscaping(isCmdFile, s)) {
+ cmdbuf.append('"');
+ cmdbuf.append(s);
+
+ // The code protects the [java.exe] and console command line
+ // parser, that interprets the [\"] combination as an escape
+ // sequence for the ["] char.
+ // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
+ //
+ // If the argument is an FS path, doubling of the tail [\]
+ // char is not a problem for non-console applications.
+ //
+ // The [\"] sequence is not an escape sequence for the [cmd.exe]
+ // command line parser. The case of the [""] tail escape
+ // sequence could not be realized due to the argument validation
+ // procedure.
+ if (!isCmdFile && s.endsWith("\\")) {
+ cmdbuf.append('\\');
}
+ cmdbuf.append('"');
} else {
cmdbuf.append(s);
}
--- a/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java Wed Apr 17 02:53:02 2013 -0700
@@ -102,7 +102,7 @@
if ((fd != null && fd1 != null) && !connected) {
return anyLocalBoundAddr;
}
- int family = connectedAddress == null ? -1 : connectedAddress.family;
+ int family = connectedAddress == null ? -1 : connectedAddress.holder().getFamily();
return socketLocalAddress(family);
} else
return super.getOption(optID);
--- a/jdk/src/windows/classes/sun/awt/windows/WFileDialogPeer.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WFileDialogPeer.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -237,7 +237,7 @@
// unused methods. Overridden to disable this functionality as
// it requires HWND which is not available for FileDialog
- public void setAlwaysOnTop(boolean value) {}
+ public void updateAlwaysOnTopState() {}
public void setDirectory(String dir) {}
public void setFile(String file) {}
public void setTitle(String title) {}
--- a/jdk/src/windows/classes/sun/awt/windows/WPrintDialogPeer.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WPrintDialogPeer.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -117,7 +117,7 @@
// unused methods. Overridden to disable this functionality as
// it requires HWND which is not available for FileDialog
void initialize() {}
- public void setAlwaysOnTop(boolean b) {}
+ public void updateAlwaysOnTopState() {}
public void setResizable(boolean resizable) {}
public void hide() {}
public void enable() {}
--- a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java Wed Apr 17 02:53:02 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -132,6 +132,10 @@
}
}
+ public void updateAlwaysOnTopState() {
+ setAlwaysOnTop(((Window)target).isAlwaysOnTop());
+ }
+
public void updateFocusableWindowState() {
setFocusableWindow(((Window)target).isFocusableWindow());
}
--- a/jdk/src/windows/native/java/net/Inet4AddressImpl.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/native/java/net/Inet4AddressImpl.c Wed Apr 17 02:53:02 2013 -0700
@@ -114,9 +114,6 @@
static jclass ni_iacls;
static jclass ni_ia4cls;
static jmethodID ni_ia4ctrID;
-static jfieldID ni_iaaddressID;
-static jfieldID ni_iahostID;
-static jfieldID ni_iafamilyID;
static int initialized = 0;
/*
@@ -149,9 +146,6 @@
ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
- ni_iaaddressID = (*env)->GetFieldID(env, ni_iacls, "address", "I");
- ni_iafamilyID = (*env)->GetFieldID(env, ni_iacls, "family", "I");
- ni_iahostID = (*env)->GetFieldID(env, ni_iacls, "hostName", "Ljava/lang/String;");
initialized = 1;
}
@@ -208,8 +202,7 @@
ret = NULL;
goto cleanupAndReturn;
}
- (*env)->SetIntField(env, iaObj, ni_iaaddressID,
- ntohl(address));
+ setInetAddress_addr(env, iaObj, ntohl(address));
(*env)->SetObjectArrayElement(env, ret, 0, iaObj);
JNU_ReleaseStringPlatformChars(env, host, hostname);
return ret;
@@ -242,9 +235,8 @@
ret = NULL;
goto cleanupAndReturn;
}
- (*env)->SetIntField(env, iaObj, ni_iaaddressID,
- ntohl((*addrp)->s_addr));
- (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
+ setInetAddress_addr(env, iaObj, ntohl((*addrp)->s_addr));
+ setInetAddress_hostName(env, iaObj, host);
(*env)->SetObjectArrayElement(env, ret, i, iaObj);
addrp++;
i++;
--- a/jdk/src/windows/native/java/net/Inet6AddressImpl.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/native/java/net/Inet6AddressImpl.c Wed Apr 17 02:53:02 2013 -0700
@@ -77,9 +77,6 @@
static jclass ni_ia6cls;
static jmethodID ni_ia4ctrID;
static jmethodID ni_ia6ctrID;
-static jfieldID ni_iaaddressID;
-static jfieldID ni_iahostID;
-static jfieldID ni_iafamilyID;
static jfieldID ni_ia6ipaddressID;
static int initialized = 0;
@@ -104,9 +101,6 @@
ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
- ni_iaaddressID = (*env)->GetFieldID(env, ni_iacls, "address", "I");
- ni_iafamilyID = (*env)->GetFieldID(env, ni_iacls, "family", "I");
- ni_iahostID = (*env)->GetFieldID(env, ni_iacls, "hostName", "Ljava/lang/String;");
ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
initialized = 1;
}
@@ -243,9 +237,8 @@
ret = NULL;
goto cleanupAndReturn;
}
- (*env)->SetIntField(env, iaObj, ni_iaaddressID,
- ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
- (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
+ setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
+ setInetAddress_hostName(env, iaObj, host);
(*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
inetIndex ++;
} else if (iterator->ai_family == AF_INET6) {
@@ -269,7 +262,7 @@
(*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
}
(*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
- (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
+ setInetAddress_hostName(env, iaObj, host);
(*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
inet6Index ++;
}
--- a/jdk/src/windows/native/java/net/NetworkInterface.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/native/java/net/NetworkInterface.c Wed Apr 17 02:53:02 2013 -0700
@@ -66,7 +66,6 @@
jfieldID ni_displayNameID; /* NetworkInterface.displayName */
jfieldID ni_childsID; /* NetworkInterface.childs */
jclass ni_iacls; /* InetAddress */
-jfieldID ni_iaAddr; /* InetAddress.address */
jclass ni_ia4cls; /* Inet4Address */
jmethodID ni_ia4Ctor; /* Inet4Address() */
@@ -480,7 +479,6 @@
ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
- ni_iaAddr = (*env)->GetFieldID(env, ni_iacls, "address", "I");
ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
@@ -568,7 +566,7 @@
}
/* default ctor will set family to AF_INET */
- (*env)->SetIntField(env, iaObj, ni_iaAddr, ntohl(addrs->addr.him4.sin_addr.s_addr));
+ setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr));
if (addrs->mask != -1) {
ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
if (ibObj == NULL) {
@@ -581,8 +579,7 @@
free_netaddr(netaddrP);
return NULL;
}
- (*env)->SetIntField(env, ia2Obj, ni_iaAddr,
- ntohl(addrs->brdcast.him4.sin_addr.s_addr));
+ setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr));
(*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj);
(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
@@ -736,7 +733,7 @@
(JNIEnv *env, jclass cls, jobject iaObj)
{
netif *ifList, *curr;
- jint addr = (*env)->GetIntField(env, iaObj, ni_iaAddr);
+ jint addr = getInetAddress_addr(env, iaObj);
jobject netifObj = NULL;
// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
--- a/jdk/src/windows/native/java/net/NetworkInterface.h Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/native/java/net/NetworkInterface.h Wed Apr 17 02:53:02 2013 -0700
@@ -71,7 +71,6 @@
extern jfieldID ni_childsID; /* NetworkInterface.childs */
extern jclass ni_iacls; /* InetAddress */
-extern jfieldID ni_iaAddr; /* InetAddress.address */
extern jclass ni_ia4cls; /* Inet4Address */
extern jmethodID ni_ia4Ctor; /* Inet4Address() */
--- a/jdk/src/windows/native/java/net/NetworkInterface_winXP.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/native/java/net/NetworkInterface_winXP.c Wed Apr 17 02:53:02 2013 -0700
@@ -33,6 +33,7 @@
#include "jni_util.h"
#include "NetworkInterface.h"
+#include "net_util.h"
/*
* Windows implementation of the java.net.NetworkInterface native methods.
@@ -477,7 +478,7 @@
}
/* default ctor will set family to AF_INET */
- (*env)->SetIntField(env, iaObj, ni_iaAddr, ntohl(addrs->addr.him4.sin_addr.s_addr));
+ setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr));
ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
if (ibObj == NULL) {
@@ -490,8 +491,7 @@
free_netaddr(netaddrP);
return NULL;
}
- (*env)->SetIntField(env, ia2Obj, ni_iaAddr,
- ntohl(addrs->brdcast.him4.sin_addr.s_addr));
+ setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr));
(*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj);
(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
--- a/jdk/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c Wed Apr 17 02:53:02 2013 -0700
@@ -432,7 +432,7 @@
int lcladdrlen;
int address;
- family = (*env)->GetIntField(env, addressObj, ia_familyID);
+ family = getInetAddress_family(env, addressObj);
if (family == IPv6 && !ipv6_supported) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
@@ -452,7 +452,7 @@
JNU_ThrowNullPointerException(env, "argument address");
return;
} else {
- address = (*env)->GetIntField(env, addressObj, ia_addressID);
+ address = getInetAddress_addr(env, addressObj);
}
if (NET_InetAddressToSockaddr(env, addressObj, port, (struct sockaddr *)&lcladdr, &lcladdrlen, JNI_FALSE) != 0) {
@@ -552,9 +552,9 @@
return;
}
- addr = (*env)->GetIntField(env, address, ia_addressID);
+ addr = getInetAddress_addr(env, address);
- family = (*env)->GetIntField(env, address, ia_familyID);
+ family = getInetAddress_family(env, address);
if (family == IPv6 && !ipv6_supported) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
@@ -670,7 +670,7 @@
return;
}
- family = (*env)->GetIntField(env, iaObj, ia_familyID);
+ family = getInetAddress_family(env, iaObj);
if (family == IPv4) {
fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
} else {
@@ -714,7 +714,7 @@
if (!w2k_or_later) { /* avoid this check on Win 2K or better. Does not work with IPv6.
* Check is not necessary on these OSes */
if (connected) {
- address = (*env)->GetIntField(env, iaObj, ia_addressID);
+ address = getInetAddress_addr(env, iaObj);
} else {
address = ntohl(rmtaddr.him4.sin_addr.s_addr);
}
@@ -823,7 +823,7 @@
if (IS_NULL(addressObj)) {
JNU_ThrowNullPointerException(env, "Null address in peek()");
} else {
- address = (*env)->GetIntField(env, addressObj, ia_addressID);
+ address = getInetAddress_addr(env, addressObj);
/* We only handle IPv4 for now. Will support IPv6 once its in the os */
family = AF_INET;
}
@@ -905,9 +905,8 @@
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", 0);
return 0;
}
- (*env)->SetIntField(env, addressObj, ia_addressID,
- ntohl(remote_addr.sin_addr.s_addr));
- (*env)->SetIntField(env, addressObj, ia_familyID, IPv4);
+ setInetAddress_addr(env, addressObj, ntohl(remote_addr.sin_addr.s_addr));
+ setInetAddress_family(env, addressObj, IPv4);
/* return port */
return ntohs(remote_addr.sin_port);
@@ -1574,21 +1573,16 @@
{
jobjectArray addrArray;
static jfieldID ni_addrsID=0;
- static jfieldID ia_familyID=0;
jsize len;
jobject addr;
int i;
- if (ni_addrsID == NULL || ia_familyID == NULL) {
+ if (ni_addrsID == NULL ) {
jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
CHECK_NULL_RETURN (c, -1);
ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
"[Ljava/net/InetAddress;");
CHECK_NULL_RETURN (ni_addrsID, -1);
- c = (*env)->FindClass(env,"java/net/InetAddress");
- CHECK_NULL_RETURN (c, -1);
- ia_familyID = (*env)->GetFieldID(env, c, "family", "I");
- CHECK_NULL_RETURN (ia_familyID, -1);
}
addrArray = (*env)->GetObjectField(env, nif, ni_addrsID);
@@ -1606,7 +1600,7 @@
for (i=0; i<len; i++) {
int fam;
addr = (*env)->GetObjectArrayElement(env, addrArray, i);
- fam = (*env)->GetIntField(env, addr, ia_familyID);
+ fam = getInetAddress_family(env, addr);
if (fam == family) {
*iaddr = addr;
return 0;
@@ -1618,20 +1612,13 @@
static int getInet4AddrFromIf (JNIEnv *env, jobject nif, struct in_addr *iaddr)
{
jobject addr;
- static jfieldID ia_addressID;
int ret = getInetAddrFromIf (env, IPv4, nif, &addr);
if (ret == -1) {
return -1;
}
- if (ia_addressID == 0) {
- jclass c = (*env)->FindClass(env,"java/net/InetAddress");
- CHECK_NULL_RETURN (c, -1);
- ia_addressID = (*env)->GetFieldID(env, c, "address", "I");
- CHECK_NULL_RETURN (ia_addressID, -1);
- }
- iaddr->s_addr = htonl((*env)->GetIntField(env, addr, ia_addressID));
+ iaddr->s_addr = htonl(getInetAddress_addr(env, addr));
return 0;
}
@@ -1706,17 +1693,9 @@
}
opt = java_net_SocketOptions_IP_MULTICAST_IF2;
} else {
- static jfieldID ia_addressID;
struct in_addr in;
- if (ia_addressID == NULL) {
- jclass c = (*env)->FindClass(env,"java/net/InetAddress");
- CHECK_NULL(c);
- ia_addressID = (*env)->GetFieldID(env, c, "address", "I");
- CHECK_NULL(ia_addressID);
- }
-
- in.s_addr = htonl((*env)->GetIntField(env, value, ia_addressID));
+ in.s_addr = htonl(getInetAddress_addr(env, value));
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
(const char*)&in, sizeof(in)) < 0) {
@@ -1945,7 +1924,6 @@
if (isIPV4) {
static jclass inet4_class;
static jmethodID inet4_ctrID;
- static jfieldID inet4_addrID;
static jclass ni_class;
static jmethodID ni_ctrID;
@@ -1975,15 +1953,13 @@
CHECK_NULL_RETURN(c, NULL);
inet4_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
CHECK_NULL_RETURN(inet4_ctrID, NULL);
- inet4_addrID = (*env)->GetFieldID(env, c, "address", "I");
- CHECK_NULL_RETURN(inet4_addrID, NULL);
inet4_class = (*env)->NewGlobalRef(env, c);
CHECK_NULL_RETURN(inet4_class, NULL);
}
addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0);
CHECK_NULL_RETURN(addr, NULL);
- (*env)->SetIntField(env, addr, inet4_addrID, ntohl(in.s_addr));
+ setInetAddress_addr(env, addr, ntohl(in.s_addr));
/*
* For IP_MULTICAST_IF return InetAddress
--- a/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c Wed Apr 17 02:53:02 2013 -0700
@@ -411,7 +411,7 @@
fdObj = (*env)->GetObjectField(env, this, psi_fdID);
fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
- family = (*env)->GetIntField(env, iaObj, ia_familyID);
+ family = getInetAddress_family(env, iaObj);
if (family == IPv6 && !ipv6_supported) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
@@ -724,9 +724,8 @@
return;
}
- (*env)->SetIntField(env, socketAddressObj, ia_addressID,
- ntohl(him.him4.sin_addr.s_addr));
- (*env)->SetIntField(env, socketAddressObj, ia_familyID, IPv4);
+ setInetAddress_addr(env, socketAddressObj, ntohl(him.him4.sin_addr.s_addr));
+ setInetAddress_family(env, socketAddressObj, IPv4);
(*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
} else {
jbyteArray addr;
@@ -754,7 +753,7 @@
}
addr = (*env)->GetObjectField (env, socketAddressObj, ia6_ipaddressID);
(*env)->SetByteArrayRegion (env, addr, 0, 16, (const char *)&him.him6.sin6_addr);
- (*env)->SetIntField(env, socketAddressObj, ia_familyID, IPv6);
+ setInetAddress_family(env, socketAddressObj, IPv6);
scope = him.him6.sin6_scope_id;
(*env)->SetIntField(env, socketAddressObj, ia6_scopeidID, scope);
if(scope>0) {
--- a/jdk/src/windows/native/java/net/net_util_md.c Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/src/windows/native/java/net/net_util_md.c Wed Apr 17 02:53:02 2013 -0700
@@ -804,7 +804,7 @@
NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,
int *len, jboolean v4MappedAddress) {
jint family, iafam;
- iafam = (*env)->GetIntField(env, iaObj, ia_familyID);
+ iafam = getInetAddress_family(env, iaObj);
family = (iafam == IPv4)? AF_INET : AF_INET6;
if (ipv6_available() && !(family == AF_INET && v4MappedAddress == JNI_FALSE)) {
struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
@@ -815,7 +815,7 @@
if (family == AF_INET) { /* will convert to IPv4-mapped address */
memset((char *) caddr, 0, 16);
- address = (*env)->GetIntField(env, iaObj, ia_addressID);
+ address = getInetAddress_addr(env, iaObj);
if (address == INADDR_ANY) {
/* we would always prefer IPv6 wildcard address
caddr[10] = 0xff;
@@ -854,7 +854,7 @@
return -1;
}
memset((char *) him4, 0, sizeof(struct sockaddr_in));
- address = (int)(*env)->GetIntField(env, iaObj, ia_addressID);
+ address = getInetAddress_addr(env, iaObj);
him4->sin_port = htons((short) port);
him4->sin_addr.s_addr = (u_long) htonl(address);
him4->sin_family = AF_INET;
--- a/jdk/test/Makefile Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/test/Makefile Wed Apr 17 02:53:02 2013 -0700
@@ -478,7 +478,7 @@
# Stable agentvm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_lang
JDK_DEFAULT_TARGETS += jdk_lang
-jdk_lang: $(call TestDirs, java/lang sun/invoke sun/misc vm)
+jdk_lang: $(call TestDirs, java/lang sun/invoke sun/misc sun/reflect vm)
$(call RunAgentvmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
@@ -513,8 +513,9 @@
javax/script \
java/sql javax/sql \
javax/smartcardio \
+ javax/xml/jaxp \
javax/xml/soap \
- javax/xml/ws com/sun/internal/ws \
+ javax/xml/ws com/sun/internal/ws com/sun/org/glassfish \
jdk/asm \
com/sun/org/apache/xerces \
com/sun/corba \
--- a/jdk/test/java/rmi/registry/classPathCodebase/ClassPathCodebase.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/test/java/rmi/registry/classPathCodebase/ClassPathCodebase.java Wed Apr 17 02:53:02 2013 -0700
@@ -31,7 +31,8 @@
*
* @library ../../testlibrary
* @build TestLibrary Dummy
- * @run main/othervm/policy=security.policy ClassPathCodebase
+ * @run main/othervm/policy=security.policy
+ * -Djava.rmi.server.useCodebaseOnly=false ClassPathCodebase
*/
import java.io.*;
--- a/jdk/test/java/rmi/registry/readTest/readTest.sh Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/test/java/rmi/registry/readTest/readTest.sh Wed Apr 17 02:53:02 2013 -0700
@@ -61,7 +61,8 @@
#start rmiregistry without any local classes on classpath
cd rmi_tmp
# NOTE: This RMI Registry port must match TestLibrary.READTEST_REGISTRY_PORT
-${TESTJAVA}${FS}bin${FS}rmiregistry ${TESTTOOLVMOPTS} 64005 > ..${FS}${RMIREG_OUT} 2>&1 &
+${TESTJAVA}${FS}bin${FS}rmiregistry -J-Djava.rmi.server.useCodebaseOnly=false \
+ ${TESTTOOLVMOPTS} 64005 > ..${FS}${RMIREG_OUT} 2>&1 &
RMIREG_PID=$!
# allow some time to start
sleep 3
--- a/jdk/test/java/rmi/server/RMIClassLoader/downloadArrayClass/DownloadArrayClass.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/test/java/rmi/server/RMIClassLoader/downloadArrayClass/DownloadArrayClass.java Wed Apr 17 02:53:02 2013 -0700
@@ -64,6 +64,10 @@
TestLibrary.bomb(e);
}
+ System.err.println("Setting codebase property to: " + remoteCodebase);
+ System.setProperty("java.rmi.server.codebase",
+ remoteCodebase.toString());
+
/*
* Load Foo from a non-RMI class loader so that it won't be already
* loaded by an RMI class loader in this VM (for whatever that's
--- a/jdk/test/java/rmi/server/RMIClassLoader/downloadArrayClass/security.policy Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/test/java/rmi/server/RMIClassLoader/downloadArrayClass/security.policy Wed Apr 17 02:53:02 2013 -0700
@@ -7,6 +7,8 @@
};
grant {
+ permission java.util.PropertyPermission
+ "java.rmi.server.codebase", "read,write";
// permissions needed to move classes into separate codebase directories
permission java.io.FilePermission
--- a/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/LoadProxyClasses.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/LoadProxyClasses.java Wed Apr 17 02:53:02 2013 -0700
@@ -32,7 +32,8 @@
* @library ../../../testlibrary
* @build TestLibrary FnnClass FnnUnmarshal NonpublicInterface
* NonpublicInterface1 PublicInterface PublicInterface1
- * @run main/othervm/policy=security.policy LoadProxyClasses
+ * @run main/othervm/policy=security.policy
+ * -Djava.rmi.server.useCodebaseOnly=false LoadProxyClasses
*/
import java.rmi.server.RMIClassLoader;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/server/RMIClassLoader/useCodebaseOnlyDefault/UseCodebaseOnlyDefault.java Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,100 @@
+/*
+ * 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 8001040
+ * @summary Tests proper parsing and defaulting of the
+ * "java.rmi.server.useCodebaseOnly" property.
+ *
+ * @run main/othervm UseCodebaseOnlyDefault true
+ * @run main/othervm -Djava.rmi.server.useCodebaseOnly=xyzzy UseCodebaseOnlyDefault true
+ * @run main/othervm -Djava.rmi.server.useCodebaseOnly UseCodebaseOnlyDefault true
+ * @run main/othervm -Djava.rmi.server.useCodebaseOnly=true UseCodebaseOnlyDefault true
+ * @run main/othervm -Djava.rmi.server.useCodebaseOnly=false UseCodebaseOnlyDefault false
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+import java.lang.reflect.Field;
+import sun.rmi.server.MarshalInputStream;
+
+/**
+ * usage: UseCodebaseOnlyDefault expected
+ *
+ * 'expected' is the expected value of useCodebaseOnly, which
+ * must be "true" or "false".
+ */
+public class UseCodebaseOnlyDefault {
+ static final String USAGE = "usage: UseCodebaseOnlyDefault boolean";
+ static final String PROPNAME = "java.rmi.server.useCodebaseOnly";
+
+ /**
+ * Gets the actual useCodebaseOnly value by creating an instance
+ * of MarshalInputStream and reflecting on the useCodebaseOnly field.
+ */
+ static boolean getActualValue() throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject("foo");
+ oos.close();
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ MarshalInputStream mis = new MarshalInputStream(bais);
+
+ Field f = MarshalInputStream.class.getDeclaredField("useCodebaseOnly");
+ f.setAccessible(true);
+ return f.getBoolean(mis);
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (args.length != 1) {
+ throw new IllegalArgumentException(USAGE);
+ }
+
+ boolean expected;
+ if (args[0].equals("true")) {
+ expected = true;
+ } else if (args[0].equals("false")) {
+ expected = false;
+ } else {
+ throw new IllegalArgumentException(USAGE);
+ }
+ System.out.println("expected = " + expected);
+
+ String prop = System.getProperty(PROPNAME);
+ System.out.print("Property " + PROPNAME);
+ if (prop == null) {
+ System.out.println(" is not set");
+ } else {
+ System.out.println(" = '" + prop + "'");
+ }
+
+ boolean actual = getActualValue();
+ System.out.println("actual = " + actual);
+
+ if (expected != actual)
+ throw new AssertionError("actual does not match expected value");
+ }
+}
--- a/jdk/test/java/rmi/testlibrary/RMID.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/test/java/rmi/testlibrary/RMID.java Wed Apr 17 02:53:02 2013 -0700
@@ -108,6 +108,9 @@
if (!TestParams.testClasses.equals("")) {
args += " -C-Dtest.classes=" + TestParams.testClasses;
}
+
+ args += " -C-Djava.rmi.server.useCodebaseOnly=false ";
+
args += " " + getCodeCoverageArgs();
return args;
}
--- a/jdk/test/java/util/Currency/tablea1.txt Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/test/java/util/Currency/tablea1.txt Wed Apr 17 02:53:02 2013 -0700
@@ -1,12 +1,12 @@
#
#
-# Amendments up until ISO 4217 AMENDMENT NUMBER 154
-# (As of 31 August 2012)
+# Amendments up until ISO 4217 AMENDMENT NUMBER 155
+# (As of 11 April 2013)
#
# Version
FILEVERSION=1
-DATAVERSION=154
+DATAVERSION=155
# ISO 4217 currency data
AF AFN 971 2
@@ -256,7 +256,7 @@
TM TMT 934 2
TC USD 840 2
TV AUD 36 2
-UG UGX 800 2
+UG UGX 800 0
UA UAH 980 2
AE AED 784 2
GB GBP 826 2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Map/Defaults.java Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,594 @@
+/*
+ * 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 8010122 8004518
+ * @summary Test Map default methods
+ * @author Mike Duigou
+ * @run testng Defaults
+ */
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.function.Supplier;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.fail;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+
+public class Defaults {
+
+ @Test(dataProvider = "Nulls Map<IntegerEnum,String>")
+ public void testGetOrDefaultNulls(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(null), "null key absent");
+ assertNull(map.get(null), "value not null");
+ assertSame(map.get(null), map.getOrDefault(null, EXTRA_VALUE), "values should match");
+ }
+
+ @Test(dataProvider = "Map<IntegerEnum,String>")
+ public void testGetOrDefault(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(KEYS[1]), "expected key missing");
+ assertSame(map.get(KEYS[1]), map.getOrDefault(KEYS[1], EXTRA_VALUE), "values should match");
+ assertFalse(map.containsKey(EXTRA_KEY), "expected absent key");
+ assertSame(map.getOrDefault(EXTRA_KEY, EXTRA_VALUE), EXTRA_VALUE, "value not returned as default");
+ assertNull(map.getOrDefault(EXTRA_KEY, null), "null not returned as default");
+ }
+
+ @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
+ public void testPutIfAbsentNulls(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(null), "null key absent");
+ assertNull(map.get(null), "value not null");
+ assertNull(map.putIfAbsent(null, EXTRA_VALUE), "previous not null");
+ assertTrue(map.containsKey(null), "null key absent");
+ assertSame(map.get(null), EXTRA_VALUE, "unexpected value");
+ assertSame(map.putIfAbsent(null, null), EXTRA_VALUE, "previous not expected value");
+ assertTrue(map.containsKey(null), "null key absent");
+ assertSame(map.get(null), EXTRA_VALUE, "unexpected value");
+ assertSame(map.remove(null), EXTRA_VALUE, "removed unexpected value");
+
+ assertFalse(map.containsKey(null), description + ": key present after remove");
+ assertNull(map.putIfAbsent(null, null), "previous not null");
+ assertTrue(map.containsKey(null), "null key absent");
+ assertNull(map.get(null), "value not null");
+ assertNull(map.putIfAbsent(null, EXTRA_VALUE), "previous not null");
+ assertSame(map.get(null), EXTRA_VALUE, "value not expected");
+ }
+
+ @Test(dataProvider = "R/W Map<IntegerEnum,String>")
+ public void testPutIfAbsent(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(KEYS[1]));
+ Object expected = map.get(KEYS[1]);
+ assertTrue(null == expected || expected == VALUES[1]);
+ assertSame(map.putIfAbsent(KEYS[1], EXTRA_VALUE), expected);
+ assertSame(map.get(KEYS[1]), expected);
+
+ assertFalse(map.containsKey(EXTRA_KEY));
+ assertSame(map.putIfAbsent(EXTRA_KEY, EXTRA_VALUE), null);
+ assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+ }
+
+ @Test(dataProvider = "Nulls Map<IntegerEnum,String>")
+ public void testForEach(String description, Map<IntegerEnum, String> map) {
+ IntegerEnum[] EACH_KEY = new IntegerEnum[map.size()];
+
+ map.forEach((k, v) -> {
+ int idx = (null == k) ? 0 : k.ordinal(); // substitute for index.
+ assertNull(EACH_KEY[idx]);
+ EACH_KEY[idx] = (idx == 0) ? KEYS[0] : k; // substitute for comparison.
+ assertSame(v, map.get(k));
+ });
+
+ assertEquals(KEYS, EACH_KEY);
+ }
+
+ @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
+ public static void testRemoveNulls(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(null), "null key absent");
+ assertNull(map.get(null), "value not null");
+ assertFalse(map.remove(null, EXTRA_VALUE), description);
+ assertTrue(map.containsKey(null));
+ assertNull(map.get(null));
+ assertTrue(map.remove(null, null));
+ assertFalse(map.containsKey(null));
+ assertNull(map.get(null));
+ assertFalse(map.remove(null, null));
+ }
+
+ @Test(dataProvider = "R/W Map<IntegerEnum,String>")
+ public static void testRemove(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(KEYS[1]));
+ Object expected = map.get(KEYS[1]);
+ assertTrue(null == expected || expected == VALUES[1]);
+ assertFalse(map.remove(KEYS[1], EXTRA_VALUE), description);
+ assertSame(map.get(KEYS[1]), expected);
+ assertTrue(map.remove(KEYS[1], expected));
+ assertNull(map.get(KEYS[1]));
+ assertFalse(map.remove(KEYS[1], expected));
+
+ assertFalse(map.containsKey(EXTRA_KEY));
+ assertFalse(map.remove(EXTRA_KEY, EXTRA_VALUE));
+ }
+
+ @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
+ public void testReplaceKVNulls(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(null), "null key absent");
+ assertNull(map.get(null), "value not null");
+ assertSame(map.replace(null, EXTRA_VALUE), null);
+ assertSame(map.get(null), EXTRA_VALUE);
+ }
+
+ @Test(dataProvider = "R/W Map<IntegerEnum,String>")
+ public void testReplaceKV(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(KEYS[1]));
+ Object expected = map.get(KEYS[1]);
+ assertTrue(null == expected || expected == VALUES[1]);
+ assertSame(map.replace(KEYS[1], EXTRA_VALUE), expected);
+ assertSame(map.get(KEYS[1]), EXTRA_VALUE);
+
+ assertFalse(map.containsKey(EXTRA_KEY));
+ assertNull(map.replace(EXTRA_KEY, EXTRA_VALUE));
+ assertFalse(map.containsKey(EXTRA_KEY));
+ assertNull(map.get(EXTRA_KEY));
+ assertNull(map.put(EXTRA_KEY, EXTRA_VALUE));
+ assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+ assertSame(map.replace(EXTRA_KEY, (String)expected), EXTRA_VALUE);
+ assertSame(map.get(EXTRA_KEY), expected);
+ }
+
+ @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
+ public void testReplaceKVVNulls(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(null), "null key absent");
+ assertNull(map.get(null), "value not null");
+ assertFalse(map.replace(null, EXTRA_VALUE, EXTRA_VALUE));
+ assertNull(map.get(null));
+ assertTrue(map.replace(null, null, EXTRA_VALUE));
+ assertSame(map.get(null), EXTRA_VALUE);
+ assertTrue(map.replace(null, EXTRA_VALUE, EXTRA_VALUE));
+ assertSame(map.get(null), EXTRA_VALUE);
+ }
+
+ @Test(dataProvider = "R/W Map<IntegerEnum,String>")
+ public void testReplaceKVV(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(KEYS[1]));
+ Object expected = map.get(KEYS[1]);
+ assertTrue(null == expected || expected == VALUES[1]);
+ assertFalse(map.replace(KEYS[1], EXTRA_VALUE, EXTRA_VALUE));
+ assertSame(map.get(KEYS[1]), expected);
+ assertTrue(map.replace(KEYS[1], (String)expected, EXTRA_VALUE));
+ assertSame(map.get(KEYS[1]), EXTRA_VALUE);
+ assertTrue(map.replace(KEYS[1], EXTRA_VALUE, EXTRA_VALUE));
+ assertSame(map.get(KEYS[1]), EXTRA_VALUE);
+
+ assertFalse(map.containsKey(EXTRA_KEY));
+ assertFalse(map.replace(EXTRA_KEY, EXTRA_VALUE, EXTRA_VALUE));
+ assertFalse(map.containsKey(EXTRA_KEY));
+ assertNull(map.get(EXTRA_KEY));
+ assertNull(map.put(EXTRA_KEY, EXTRA_VALUE));
+ assertTrue(map.containsKey(EXTRA_KEY));
+ assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+ assertTrue(map.replace(EXTRA_KEY, EXTRA_VALUE, EXTRA_VALUE));
+ assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+ }
+
+ @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
+ public void testComputeIfAbsentNulls(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(null), "null key absent");
+ assertNull(map.get(null), "value not null");
+ assertSame(map.computeIfAbsent(null, (k) -> EXTRA_VALUE), EXTRA_VALUE, description);
+ assertSame(map.get(null), EXTRA_VALUE, description);
+ }
+
+ @Test(dataProvider = "R/W Map<IntegerEnum,String>")
+ public void testComputeIfAbsent(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(KEYS[1]));
+ Object expected = map.get(KEYS[1]);
+ assertTrue(null == expected || expected == VALUES[1], description + String.valueOf(expected));
+ expected = (null == expected) ? EXTRA_VALUE : expected;
+ assertSame(map.computeIfAbsent(KEYS[1], (k) -> EXTRA_VALUE), expected, description);
+ assertSame(map.get(KEYS[1]), expected, description);
+
+ assertFalse(map.containsKey(EXTRA_KEY));
+ assertSame(map.computeIfAbsent(EXTRA_KEY, (k) -> EXTRA_VALUE), EXTRA_VALUE);
+ assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+ }
+
+ @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
+ public void testComputeIfPresentNulls(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(null));
+ assertNull(map.get(null));
+ assertSame(map.computeIfPresent(null, (k, v) -> {
+ fail();
+ return EXTRA_VALUE;
+ }), null, description);
+ assertTrue(map.containsKey(null));
+ assertSame(map.get(null), null, description);
+ }
+
+ @Test(dataProvider = "R/W Map<IntegerEnum,String>")
+ public void testComputeIfPresent(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(KEYS[1]));
+ Object value = map.get(KEYS[1]);
+ assertTrue(null == value || value == VALUES[1], description + String.valueOf(value));
+ Object expected = (null == value) ? null : EXTRA_VALUE;
+ assertSame(map.computeIfPresent(KEYS[1], (k, v) -> {
+ assertSame(v, value);
+ return EXTRA_VALUE;
+ }), expected, description);
+ assertSame(map.get(KEYS[1]), expected, description);
+
+ assertFalse(map.containsKey(EXTRA_KEY));
+ assertSame(map.computeIfPresent(EXTRA_KEY, (k, v) -> {
+ fail();
+ return EXTRA_VALUE;
+ }), null);
+ assertFalse(map.containsKey(EXTRA_KEY));
+ assertSame(map.get(EXTRA_KEY), null);
+ }
+
+ @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
+ public void testComputeNulls(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(null), "null key absent");
+ assertNull(map.get(null), "value not null");
+ assertSame(map.compute(null, (k, v) -> {
+ assertSame(k, null);
+ assertNull(v);
+ return EXTRA_VALUE;
+ }), EXTRA_VALUE, description);
+ assertTrue(map.containsKey(null));
+ assertSame(map.get(null), EXTRA_VALUE, description);
+ assertSame(map.remove(null), EXTRA_VALUE, "removed value not expected");
+ assertFalse(map.containsKey(null), "null key present");
+ assertSame(map.compute(null, (k, v) -> {
+ assertSame(k, null);
+ assertNull(v);
+ return null;
+ }), null, description);
+ }
+
+ @Test(dataProvider = "R/W Map<IntegerEnum,String>")
+ public void testCompute(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(KEYS[1]));
+ Object value = map.get(KEYS[1]);
+ assertTrue(null == value || value == VALUES[1], description + String.valueOf(value));
+ assertSame(map.compute(KEYS[1], (k, v) -> {
+ assertSame(k, KEYS[1]);
+ assertSame(v, value);
+ return EXTRA_VALUE;
+ }), EXTRA_VALUE, description);
+ assertSame(map.get(KEYS[1]), EXTRA_VALUE, description);
+ assertNull(map.compute(KEYS[1], (k, v) -> {
+ assertSame(v, EXTRA_VALUE);
+ return null;
+ }), description);
+ assertFalse(map.containsKey(KEYS[1]));
+
+ assertFalse(map.containsKey(EXTRA_KEY));
+ assertSame(map.compute(EXTRA_KEY, (k, v) -> {
+ assertNull(v);
+ return EXTRA_VALUE;
+ }), EXTRA_VALUE);
+ assertTrue(map.containsKey(EXTRA_KEY));
+ assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+ }
+
+
+ @Test(dataProvider = "R/W Nulls Map<IntegerEnum,String>")
+ public void testMergeNulls(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(null), "null key absent");
+ assertNull(map.get(null), "value not null");
+ assertSame(map.merge(null, EXTRA_VALUE, (v, vv) -> {
+ assertNull(v);
+ assertSame(vv, EXTRA_VALUE);
+ return vv;
+ }), EXTRA_VALUE, description);
+ assertTrue(map.containsKey(null));
+ assertSame(map.get(null), EXTRA_VALUE, description);
+ }
+
+ @Test(dataProvider = "R/W Map<IntegerEnum,String>")
+ public void testMerge(String description, Map<IntegerEnum, String> map) {
+ assertTrue(map.containsKey(KEYS[1]));
+ Object value = map.get(KEYS[1]);
+ assertTrue(null == value || value == VALUES[1], description + String.valueOf(value));
+ assertSame(map.merge(KEYS[1], EXTRA_VALUE, (v, vv) -> {
+ assertSame(v, value);
+ assertSame(vv, EXTRA_VALUE);
+ return vv;
+ }), EXTRA_VALUE, description);
+ assertSame(map.get(KEYS[1]), EXTRA_VALUE, description);
+ assertNull(map.merge(KEYS[1], EXTRA_VALUE, (v, vv) -> {
+ assertSame(v, EXTRA_VALUE);
+ assertSame(vv, EXTRA_VALUE);
+ return null;
+ }), description);
+ assertFalse(map.containsKey(KEYS[1]));
+
+ assertFalse(map.containsKey(EXTRA_KEY));
+ assertSame(map.merge(EXTRA_KEY, EXTRA_VALUE, (v, vv) -> {
+ assertNull(v);
+ assertSame(vv, EXTRA_VALUE);
+ return EXTRA_VALUE;
+ }), EXTRA_VALUE);
+ assertTrue(map.containsKey(EXTRA_KEY));
+ assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+ }
+
+ enum IntegerEnum {
+
+ e0, e1, e2, e3, e4, e5, e6, e7, e8, e9,
+ e10, e11, e12, e13, e14, e15, e16, e17, e18, e19,
+ e20, e21, e22, e23, e24, e25, e26, e27, e28, e29,
+ e30, e31, e32, e33, e34, e35, e36, e37, e38, e39,
+ e40, e41, e42, e43, e44, e45, e46, e47, e48, e49,
+ e50, e51, e52, e53, e54, e55, e56, e57, e58, e59,
+ e60, e61, e62, e63, e64, e65, e66, e67, e68, e69,
+ e70, e71, e72, e73, e74, e75, e76, e77, e78, e79,
+ e80, e81, e82, e83, e84, e85, e86, e87, e88, e89,
+ e90, e91, e92, e93, e94, e95, e96, e97, e98, e99,
+ EXTRA_KEY;
+ public static final int SIZE = values().length;
+ };
+ private static final int TEST_SIZE = IntegerEnum.SIZE - 1;
+ /**
+ * Realized keys ensure that there is always a hard ref to all test objects.
+ */
+ private static final IntegerEnum[] KEYS = new IntegerEnum[TEST_SIZE];
+ /**
+ * Realized values ensure that there is always a hard ref to all test
+ * objects.
+ */
+ private static final String[] VALUES = new String[TEST_SIZE];
+
+ static {
+ IntegerEnum[] keys = IntegerEnum.values();
+ for (int each = 0; each < TEST_SIZE; each++) {
+ KEYS[each] = keys[each];
+ VALUES[each] = String.valueOf(each);
+ }
+ }
+ private static final IntegerEnum EXTRA_KEY = IntegerEnum.EXTRA_KEY;
+ private static final String EXTRA_VALUE = String.valueOf(TEST_SIZE);
+
+ @DataProvider(name = "Map<IntegerEnum,String>", parallel = true)
+ public static Iterator<Object[]> allNullsMapProvider() {
+ return makeAllMaps().iterator();
+ }
+
+ @DataProvider(name = "Nulls Map<IntegerEnum,String>", parallel = true)
+ public static Iterator<Object[]> allMapProvider() {
+ return makeRWMaps(true).iterator();
+ }
+
+ @DataProvider(name = "R/W Map<IntegerEnum,String>", parallel = true)
+ public static Iterator<Object[]> rwMapProvider() {
+ return makeRWMapsNoNulls().iterator();
+ }
+
+ @DataProvider(name = "R/W Nulls Map<IntegerEnum,String>", parallel = true)
+ public static Iterator<Object[]> rwNullsMapProvider() {
+ return makeRWMaps(true).iterator();
+ }
+
+ private static Collection<Object[]> makeAllMapsNoNulls() {
+ Collection<Object[]> all = new ArrayList<>();
+
+ all.addAll(makeRWMaps(false));
+ all.addAll(makeRWNoNullsMaps());
+ all.addAll(makeROMaps(false));
+
+ return all;
+ }
+
+ private static Collection<Object[]> makeRWMapsNoNulls() {
+ Collection<Object[]> all = new ArrayList<>();
+
+ all.addAll(makeRWMaps(false));
+ all.addAll(makeRWNoNullsMaps());
+
+ return all;
+ }
+
+ private static Collection<Object[]> makeAllMaps() {
+ Collection<Object[]> all = new ArrayList<>();
+
+ all.addAll(makeROMaps(false));
+ all.addAll(makeRWMaps(false));
+ all.addAll(makeRWNoNullsMaps());
+ all.addAll(makeRWMaps(true));
+ all.addAll(makeROMaps(true));
+
+ return all;
+ }
+
+ private static Collection<Object[]> makeAllRWMaps() {
+ Collection<Object[]> all = new ArrayList<>();
+
+ all.addAll(makeRWMaps(false));
+ all.addAll(makeRWNoNullsMaps());
+ all.addAll(makeRWMaps(true));
+
+ return all;
+ }
+
+ private static Collection<Object[]> makeRWMaps(boolean nulls) {
+ return Arrays.asList(
+ new Object[]{"HashMap", makeMap(HashMap::new, nulls)},
+ new Object[]{"IdentityHashMap", makeMap(IdentityHashMap::new, nulls)},
+ new Object[]{"LinkedHashMap", makeMap(LinkedHashMap::new, nulls)},
+ new Object[]{"WeakHashMap", makeMap(WeakHashMap::new, nulls)},
+ new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(makeMap(HashMap::new, nulls), IntegerEnum.class, String.class)},
+ new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(makeMap(HashMap::new, nulls))},
+ new Object[]{"ExtendsAbstractMap", makeMap(ExtendsAbstractMap::new, nulls)});
+ }
+
+ private static Collection<Object[]> makeRWNoNullsMaps() {
+ return Arrays.asList(
+ // null hostile
+ new Object[]{"EnumMap", makeMap(() -> new EnumMap(IntegerEnum.class), false)},
+ new Object[]{"Hashtable", makeMap(Hashtable::new, false)},
+ new Object[]{"TreeMap", makeMap(TreeMap::new, false)},
+ new Object[]{"ConcurrentHashMap", makeMap(ConcurrentHashMap::new, false)},
+ new Object[]{"ConcurrentSkipListMap", makeMap(ConcurrentSkipListMap::new, false)},
+ new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(makeMap(ConcurrentHashMap::new, false), IntegerEnum.class, String.class)},
+ new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(makeMap(() -> new EnumMap(IntegerEnum.class), false))},
+ new Object[]{"ImplementsConcurrentMap", makeMap(ImplementsConcurrentMap::new, false)});
+ }
+
+ private static Collection<Object[]> makeROMaps(boolean nulls) {
+ return Arrays.asList(new Object[][]{
+ new Object[]{"Collections.unmodifiableMap(HashMap)", Collections.unmodifiableMap(makeMap(HashMap::new, nulls))}
+ });
+ }
+
+ private static Map<IntegerEnum, String> makeMap(Supplier<Map<IntegerEnum, String>> supplier, boolean nulls) {
+ Map<IntegerEnum, String> result = supplier.get();
+
+ for (int each = 0; each < TEST_SIZE; each++) {
+ if (nulls) {
+ result.put((each == 0) ? null : KEYS[each], null);
+ } else {
+ result.put(KEYS[each], VALUES[each]);
+ }
+ }
+
+ return result;
+ }
+
+ public interface Thrower<T extends Throwable> {
+
+ public void run() throws T;
+ }
+
+ public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable) {
+ assertThrows(thrower, throwable, null);
+ }
+
+ public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable, String message) {
+ Throwable result;
+ try {
+ thrower.run();
+ result = null;
+ } catch (Throwable caught) {
+ result = caught;
+ }
+
+ assertInstance(result, throwable,
+ (null != message)
+ ? message
+ : "Failed to throw " + throwable.getCanonicalName());
+ }
+
+ public static <T> void assertInstance(T actual, Class<? extends T> expected) {
+ assertInstance(expected.isInstance(actual), null);
+ }
+
+ public static <T> void assertInstance(T actual, Class<? extends T> expected, String message) {
+ assertTrue(expected.isInstance(actual), message);
+ }
+
+ /**
+ * A simple mutable map implementation that provides only default
+ * implementations of all methods. ie. none of the Map interface default
+ * methods have overridden implementations.
+ *
+ * @param <K> Type of keys
+ * @param <V> Type of values
+ */
+ public static class ExtendsAbstractMap<M extends Map<K,V>, K, V> extends AbstractMap<K, V> {
+
+ protected final M map;
+
+ public ExtendsAbstractMap() { this( (M) new HashMap<K,V>()); }
+
+ protected ExtendsAbstractMap(M map) { this.map = map; }
+
+ public Set<Map.Entry<K, V>> entrySet() {
+ return new AbstractSet<Map.Entry<K, V>>() {
+ public int size() {
+ return map.size();
+ }
+
+ public Iterator<Map.Entry<K,V>> iterator() {
+ final Iterator<Map.Entry<K,V>> source = map.entrySet().iterator();
+ return new Iterator<Map.Entry<K,V>>() {
+ public boolean hasNext() { return source.hasNext(); }
+ public Map.Entry<K,V> next() { return source.next(); }
+ public void remove() { source.remove(); }
+ };
+ }
+
+ public boolean add(Map.Entry<K,V> e) {
+ return map.entrySet().add(e);
+ }
+ };
+ }
+
+ public V put(K key, V value) {
+ return map.put(key, value);
+ }
+ }
+
+ /**
+ * A simple mutable concurrent map implementation that provides only default
+ * implementations of all methods. ie. none of the ConcurrentMap interface
+ * default methods have overridden implementations.
+ *
+ * @param <K> Type of keys
+ * @param <V> Type of values
+ */
+ public static class ImplementsConcurrentMap<K, V> extends ExtendsAbstractMap<ConcurrentMap<K,V>, K, V> implements ConcurrentMap<K,V> {
+ public ImplementsConcurrentMap() { super(new ConcurrentHashMap<K,V>()); }
+
+ // ConcurrentMap reabstracts these methods
+
+ public V replace(K k, V v) { return map.replace(k, v); };
+
+ public boolean replace(K k, V v, V vv) { return map.replace(k, v, vv); };
+
+ public boolean remove(Object k, Object v) { return map.remove(k, v); }
+
+ public V putIfAbsent(K k, V v) { return map.putIfAbsent(k, v); }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/reflect/CallerSensitive/CallerSensitiveFinder.java Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,216 @@
+/*
+ * 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.
+ */
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.jdeps.ClassFileReader;
+import static com.sun.tools.classfile.ConstantPool.*;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+
+/*
+ * @test
+ * @bug 8010117
+ * @summary Verify if CallerSensitive methods are annotated with
+ * sun.reflect.CallerSensitive annotation
+ * @build CallerSensitiveFinder MethodFinder
+ * @run main/othervm/timeout=900 -mx600m CallerSensitiveFinder
+ */
+public class CallerSensitiveFinder extends MethodFinder {
+ private static int numThreads = 3;
+ private static boolean verbose = false;
+ public static void main(String[] args) throws Exception {
+ List<Path> classes = new ArrayList<>();
+ String testclasses = System.getProperty("test.classes", ".");
+ int i = 0;
+ while (i < args.length) {
+ String arg = args[i++];
+ if (arg.equals("-v")) {
+ verbose = true;
+ } else {
+ Path p = Paths.get(testclasses, arg);
+ if (!p.toFile().exists()) {
+ throw new IllegalArgumentException(arg + " does not exist");
+ }
+ classes.add(p);
+ }
+ }
+ if (classes.isEmpty()) {
+ classes.addAll(PlatformClassPath.getJREClasses());
+ }
+ final String method = "sun/reflect/Reflection.getCallerClass";
+ CallerSensitiveFinder csfinder = new CallerSensitiveFinder(method);
+
+ List<String> errors = csfinder.run(classes);
+ if (!errors.isEmpty()) {
+ throw new RuntimeException(errors.size() +
+ " caller-sensitive methods are missing @CallerSensitive annotation");
+ }
+ }
+
+ private final List<String> csMethodsMissingAnnotation = new ArrayList<>();
+ public CallerSensitiveFinder(String... methods) {
+ super(methods);
+ }
+
+ public List<String> run(List<Path> classes) throws IOException, InterruptedException,
+ ExecutionException, ConstantPoolException
+ {
+ ExecutorService pool = Executors.newFixedThreadPool(numThreads);
+ for (Path path : classes) {
+ ClassFileReader reader = ClassFileReader.newInstance(path.toFile());
+ for (ClassFile cf : reader.getClassFiles()) {
+ String classFileName = cf.getName();
+ // for each ClassFile
+ // parse constant pool to find matching method refs
+ // parse each method (caller)
+ // - visit and find method references matching the given method name
+ pool.submit(getTask(cf));
+ }
+ }
+ waitForCompletion();
+ pool.shutdown();
+ return csMethodsMissingAnnotation;
+ }
+
+ private static final String CALLER_SENSITIVE_ANNOTATION = "Lsun/reflect/CallerSensitive;";
+ private static boolean isCallerSensitive(Method m, ConstantPool cp)
+ throws ConstantPoolException
+ {
+ RuntimeAnnotations_attribute attr =
+ (RuntimeAnnotations_attribute)m.attributes.get(Attribute.RuntimeVisibleAnnotations);
+ int index = 0;
+ if (attr != null) {
+ for (int i = 0; i < attr.annotations.length; i++) {
+ Annotation ann = attr.annotations[i];
+ String annType = cp.getUTF8Value(ann.type_index);
+ if (CALLER_SENSITIVE_ANNOTATION.equals(annType)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void referenceFound(ClassFile cf, Method m, Set<Integer> refs)
+ throws ConstantPoolException
+ {
+ String name = String.format("%s#%s %s", cf.getName(),
+ m.getName(cf.constant_pool),
+ m.descriptor.getValue(cf.constant_pool));
+ if (!CallerSensitiveFinder.isCallerSensitive(m, cf.constant_pool)) {
+ csMethodsMissingAnnotation.add(name);
+ System.err.println("Missing @CallerSensitive: " + name);
+ } else {
+ if (verbose) {
+ System.out.format("@CS %s%n", name);
+ }
+ }
+ }
+
+ private final List<FutureTask<String>> tasks = new ArrayList<FutureTask<String>>();
+ private FutureTask<String> getTask(final ClassFile cf) {
+ FutureTask<String> task = new FutureTask<String>(new Callable<String>() {
+ public String call() throws Exception {
+ return parse(cf);
+ }
+ });
+ tasks.add(task);
+ return task;
+ }
+
+ private void waitForCompletion() throws InterruptedException, ExecutionException {
+ for (FutureTask<String> t : tasks) {
+ String s = t.get();
+ }
+ System.out.println("Parsed " + tasks.size() + " classfiles");
+ }
+
+ static class PlatformClassPath {
+ static List<Path> getJREClasses() throws IOException {
+ List<Path> result = new ArrayList<Path>();
+ Path home = Paths.get(System.getProperty("java.home"));
+
+ if (home.endsWith("jre")) {
+ // jar files in <javahome>/jre/lib
+ // skip <javahome>/lib
+ result.addAll(addJarFiles(home.resolve("lib")));
+ } else if (home.resolve("lib").toFile().exists()) {
+ // either a JRE or a jdk build image
+ File classes = home.resolve("classes").toFile();
+ if (classes.exists() && classes.isDirectory()) {
+ // jdk build outputdir
+ result.add(classes.toPath());
+ }
+ // add other JAR files
+ result.addAll(addJarFiles(home.resolve("lib")));
+ } else {
+ throw new RuntimeException("\"" + home + "\" not a JDK home");
+ }
+ return result;
+ }
+
+ static List<Path> addJarFiles(final Path root) throws IOException {
+ final List<Path> result = new ArrayList<Path>();
+ final Path ext = root.resolve("ext");
+ Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
+ throws IOException {
+ if (dir.equals(root) || dir.equals(ext)) {
+ return FileVisitResult.CONTINUE;
+ } else {
+ // skip other cobundled JAR files
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException {
+ File f = file.toFile();
+ String fn = f.getName();
+ // parse alt-rt.jar as well
+ if (fn.endsWith(".jar") && !fn.equals("jfxrt.jar")) {
+ result.add(file);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ return result;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/reflect/CallerSensitive/MethodFinder.java Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ */
+
+import java.util.*;
+import com.sun.tools.classfile.*;
+import static com.sun.tools.classfile.ConstantPool.*;
+import com.sun.tools.classfile.Instruction.TypeKind;
+
+/**
+ * MethodFinder utility class to find references to the given methods.
+ */
+public abstract class MethodFinder {
+ final List<String> methods;
+ public MethodFinder(String... methods) {
+ this.methods = Arrays.asList(methods);
+ }
+
+ /**
+ * A callback method will be invoked when a method referencing
+ * any of the lookup methods.
+ *
+ * @param cf ClassFile
+ * @param m Method
+ * @param refs Set of constant pool indices that reference the methods
+ * matching the given lookup method names
+ */
+ public abstract void referenceFound(ClassFile cf, Method m, Set<Integer> refs)
+ throws ConstantPoolException;
+
+ public String parse(ClassFile cf) throws ConstantPoolException {
+ List<Integer> cprefs = new ArrayList<Integer>();
+ int index = 1;
+ for (ConstantPool.CPInfo cpInfo : cf.constant_pool.entries()) {
+ if (cpInfo.accept(cpVisitor, null)) {
+ cprefs.add(index);
+ }
+ index += cpInfo.size();
+ }
+
+ if (!cprefs.isEmpty()) {
+ for (Method m : cf.methods) {
+ Set<Integer> refs = new HashSet<Integer>();
+ Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code);
+ if (c_attr != null) {
+ for (Instruction instr : c_attr.getInstructions()) {
+ int idx = instr.accept(codeVisitor, cprefs);
+ if (idx > 0) {
+ refs.add(idx);
+ }
+ }
+ }
+ if (refs.size() > 0) {
+ referenceFound(cf, m, refs);
+ }
+ }
+ }
+ return cprefs.isEmpty() ? "" : cf.getName();
+ }
+
+ private ConstantPool.Visitor<Boolean,Void> cpVisitor =
+ new ConstantPool.Visitor<Boolean,Void>()
+ {
+ private boolean matches(CPRefInfo info) {
+ try {
+ CONSTANT_NameAndType_info nat = info.getNameAndTypeInfo();
+ return matches(info.getClassName(), nat.getName(), nat.getType());
+ } catch (ConstantPoolException ex) {
+ return false;
+ }
+ }
+
+ private boolean matches(String cn, String name, String type) {
+ return methods.contains(cn + "." + name);
+ }
+
+ public Boolean visitClass(CONSTANT_Class_info info, Void p) {
+ return false;
+ }
+
+ public Boolean visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
+ return matches(info);
+ }
+
+ public Boolean visitMethodref(CONSTANT_Methodref_info info, Void p) {
+ return matches(info);
+ }
+
+ public Boolean visitDouble(CONSTANT_Double_info info, Void p) {
+ return false;
+ }
+
+ public Boolean visitFieldref(CONSTANT_Fieldref_info info, Void p) {
+ return false;
+ }
+
+ public Boolean visitFloat(CONSTANT_Float_info info, Void p) {
+ return false;
+ }
+
+ public Boolean visitInteger(CONSTANT_Integer_info info, Void p) {
+ return false;
+ }
+
+ public Boolean visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) {
+ return false;
+ }
+
+ public Boolean visitLong(CONSTANT_Long_info info, Void p) {
+ return false;
+ }
+
+ public Boolean visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
+ return false;
+ }
+
+ public Boolean visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) {
+ return false;
+ }
+
+ public Boolean visitMethodType(CONSTANT_MethodType_info info, Void p) {
+ return false;
+ }
+
+ public Boolean visitString(CONSTANT_String_info info, Void p) {
+ return false;
+ }
+
+ public Boolean visitUtf8(CONSTANT_Utf8_info info, Void p) {
+ return false;
+ }
+ };
+
+ private Instruction.KindVisitor<Integer, List<Integer>> codeVisitor =
+ new Instruction.KindVisitor<Integer, List<Integer>>()
+ {
+ public Integer visitNoOperands(Instruction instr, List<Integer> p) {
+ return 0;
+ }
+
+ public Integer visitArrayType(Instruction instr, TypeKind kind, List<Integer> p) {
+ return 0;
+ }
+
+ public Integer visitBranch(Instruction instr, int offset, List<Integer> p) {
+ return 0;
+ }
+
+ public Integer visitConstantPoolRef(Instruction instr, int index, List<Integer> p) {
+ return p.contains(index) ? index : 0;
+ }
+
+ public Integer visitConstantPoolRefAndValue(Instruction instr, int index, int value, List<Integer> p) {
+ return p.contains(index) ? index : 0;
+ }
+
+ public Integer visitLocal(Instruction instr, int index, List<Integer> p) {
+ return 0;
+ }
+
+ public Integer visitLocalAndValue(Instruction instr, int index, int value, List<Integer> p) {
+ return 0;
+ }
+
+ public Integer visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, List<Integer> p) {
+ return 0;
+ }
+
+ public Integer visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, List<Integer> p) {
+ return 0;
+ }
+
+ public Integer visitValue(Instruction instr, int value, List<Integer> p) {
+ return 0;
+ }
+
+ public Integer visitUnknown(Instruction instr, List<Integer> p) {
+ return 0;
+ }
+ };
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/reflect/CallerSensitive/MissingCallerSensitive.java Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,65 @@
+/*
+ * 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 8010117
+ * @summary Test CallerSensitiveFinder to find missing annotation
+ * @compile -XDignore.symbol.file MissingCallerSensitive.java
+ * @build CallerSensitiveFinder MethodFinder
+ * @run main MissingCallerSensitive
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+public class MissingCallerSensitive {
+ public static void main(String[] args) throws Exception {
+ String testclasses = System.getProperty("test.classes", ".");
+ List<Path> classes = new ArrayList<>();
+ classes.add(Paths.get(testclasses, "MissingCallerSensitive.class"));
+
+ final String method = "sun/reflect/Reflection.getCallerClass";
+ CallerSensitiveFinder csfinder = new CallerSensitiveFinder(method);
+ List<String> errors = csfinder.run(classes);
+ if (errors.size() != 1) {
+ throw new RuntimeException("Unexpected number of methods found: " + errors.size());
+ }
+ String m = errors.get(0);
+ if (!m.startsWith("MissingCallerSensitive#missingCallerSensitiveAnnotation")) {
+ throw new RuntimeException("Unexpected method missing annotation: " + m);
+ }
+ }
+
+ @sun.reflect.CallerSensitive
+ public ClassLoader getCallerLoader() {
+ Class<?> c = sun.reflect.Reflection.getCallerClass();
+ return c.getClassLoader();
+ }
+
+ public ClassLoader missingCallerSensitiveAnnotation() {
+ Class<?> c = sun.reflect.Reflection.getCallerClass();
+ return c.getClassLoader();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/reflect/Reflection/GetCallerClass.java Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package boot;
+
+public class GetCallerClass {
+ @sun.reflect.CallerSensitive
+ public ClassLoader getCallerLoader() {
+ Class<?> c = sun.reflect.Reflection.getCallerClass();
+ return c.getClassLoader();
+ }
+
+ public ClassLoader missingCallerSensitiveAnnotation() {
+ Class<?> c = sun.reflect.Reflection.getCallerClass();
+ return c.getClassLoader();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/reflect/Reflection/GetCallerClassTest.java Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+import boot.GetCallerClass;
+import java.lang.reflect.*;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
+
+public class GetCallerClassTest {
+ private final GetCallerClass gcc; // boot.GetCallerClass is in bootclasspath
+ GetCallerClassTest() {
+ this.gcc = new GetCallerClass();
+ }
+
+ public static void main(String[] args) throws Exception {
+ GetCallerClassTest gcct = new GetCallerClassTest();
+ // ensure methods are annotated with @CallerSensitive
+ ensureAnnotationPresent(boot.GetCallerClass.class, "getCallerLoader", true);
+ ensureAnnotationPresent(GetCallerClassTest.class, "testNonSystemMethod", false);
+ // call Reflection.getCallerClass from bootclasspath with and without @CS
+ gcct.testCallerSensitiveMethods();
+ // call Reflection.getCallerClass from classpath with @CS
+ gcct.testNonSystemMethod();
+ }
+
+ private static void ensureAnnotationPresent(Class<?> c, String name, boolean cs)
+ throws NoSuchMethodException
+ {
+ Method m = c.getDeclaredMethod(name);
+ if (!m.isAnnotationPresent(CallerSensitive.class)) {
+ throw new RuntimeException("@CallerSensitive not present in method " + m);
+ }
+ if (Reflection.isCallerSensitive(m) != cs) {
+ throw new RuntimeException("Unexpected: isCallerSensitive returns " +
+ Reflection.isCallerSensitive(m));
+ }
+ }
+
+ private void testCallerSensitiveMethods() {
+ try {
+ ClassLoader cl = gcc.getCallerLoader();
+ if (cl != GetCallerClassTest.class.getClassLoader()) {
+ throw new RuntimeException("mismatched class loader");
+ }
+ gcc.missingCallerSensitiveAnnotation();
+ throw new RuntimeException("getCallerLoader not marked with @CallerSensitive");
+ } catch (InternalError e) {
+ StackTraceElement[] stackTrace = e.getStackTrace();
+ checkStackTrace(stackTrace, e);
+ if (!stackTrace[1].getClassName().equals(GetCallerClass.class.getName()) ||
+ !stackTrace[1].getMethodName().equals("missingCallerSensitiveAnnotation")) {
+ throw new RuntimeException("Unexpected error: " + e.getMessage(), e);
+ }
+ if (!stackTrace[2].getClassName().equals(GetCallerClassTest.class.getName()) ||
+ !stackTrace[2].getMethodName().equals("testCallerSensitiveMethods")) {
+ throw new RuntimeException("Unexpected error: " + e.getMessage(), e);
+ }
+ System.out.println("Expected error: " + e.getMessage());
+ }
+ }
+
+ @CallerSensitive
+ private void testNonSystemMethod() {
+ try {
+ Class<?> c = Reflection.getCallerClass();
+ throw new RuntimeException("@CallerSensitive testNonSystemMethods not supported");
+ } catch (InternalError e) {
+ StackTraceElement[] stackTrace = e.getStackTrace();
+ checkStackTrace(stackTrace, e);
+ if (!stackTrace[1].getClassName().equals(GetCallerClassTest.class.getName()) ||
+ !stackTrace[1].getMethodName().equals("testNonSystemMethod")) {
+ throw new RuntimeException("Unexpected error: " + e.getMessage(), e);
+ }
+ if (!stackTrace[2].getClassName().equals(GetCallerClassTest.class.getName()) ||
+ !stackTrace[2].getMethodName().equals("main")) {
+ throw new RuntimeException("Unexpected error: " + e.getMessage(), e);
+ }
+ System.out.println("Expected error: " + e.getMessage());
+ }
+ }
+
+ private void checkStackTrace(StackTraceElement[] stackTrace, Error e) {
+ if (stackTrace.length < 3) {
+ throw new RuntimeException("Unexpected error: " + e.getMessage(), e);
+ }
+
+ if (!stackTrace[0].getClassName().equals("sun.reflect.Reflection") ||
+ !stackTrace[0].getMethodName().equals("getCallerClass")) {
+ throw new RuntimeException("Unexpected error: " + e.getMessage(), e);
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/reflect/Reflection/GetCallerClassTest.sh Wed Apr 17 02:53:02 2013 -0700
@@ -0,0 +1,68 @@
+#
+# 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 8010117
+# @summary Test if the VM enforces sun.reflect.Reflection.getCallerClass
+# be called by methods annotated with sun.reflect.CallerSensitive
+#
+# @run shell GetCallerClassTest.sh
+
+if [ "${TESTSRC}" = "" ]
+then
+ echo "TESTSRC not set. Test cannot execute. Failed."
+ exit 1
+fi
+echo "TESTSRC=${TESTSRC}"
+if [ "${TESTJAVA}" = "" ]
+then
+ echo "TESTJAVA not set. Test cannot execute. Failed."
+ exit 1
+fi
+echo "TESTJAVA=${TESTJAVA}"
+if [ "${COMPILEJAVA}" = "" ]
+then
+ COMPILEJAVA="${TESTJAVA}"
+fi
+echo "COMPILEJAVA=${COMPILEJAVA}"
+if [ "${TESTCLASSES}" = "" ]
+then
+ echo "TESTCLASSES not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+BCP=${TESTCLASSES}/bcp
+rm -rf ${BCP}
+mkdir ${BCP}
+
+# Compile GetCallerClass in bootclasspath
+${COMPILEJAVA}/bin/javac ${TESTTOOLVMOPTS} \
+ -XDignore.symbol.file \
+ -d ${BCP} ${TESTSRC}/GetCallerClass.java || exit 1
+
+${COMPILEJAVA}/bin/javac ${TESTTOOLVMOPTS} \
+ -XDignore.symbol.file -Xbootclasspath/a:${BCP} \
+ -d ${TESTCLASSES} ${TESTSRC}/GetCallerClassTest.java || exit 2
+
+${TESTJAVA}/bin/java ${TESTVMOPTS} -Xbootclasspath/a:${BCP} \
+ -cp ${TESTCLASSES} GetCallerClassTest || exit 3
--- a/jdk/test/sun/security/krb5/MicroTime.java Tue Apr 16 05:32:39 2013 -0700
+++ b/jdk/test/sun/security/krb5/MicroTime.java Wed Apr 17 02:53:02 2013 -0700
@@ -22,7 +22,7 @@
*/
/*
* @test
- * @bug 6882687
+ * @bug 6882687 8011124
* @summary KerberosTime too imprecise
*/
@@ -32,11 +32,11 @@
public static void main(String[] args) throws Exception {
// We count how many different KerberosTime values
// can be acquired within one second.
- KerberosTime t1 = new KerberosTime(true);
+ KerberosTime t1 = KerberosTime.now();
KerberosTime last = t1;
int count = 0;
while (true) {
- KerberosTime t2 = new KerberosTime(true);
+ KerberosTime t2 = KerberosTime.now();
if (t2.getTime() - t1.getTime() > 1000) break;
if (!last.equals(t2)) {
last = t2;