changeset 37308 | 4c4141aac146 |
parent 36734 | 18c3da127b06 |
child 37593 | 824750ada3d6 |
37307:eb17ca049605 | 37308:4c4141aac146 |
---|---|
892 |
892 |
893 // The bad character shift for "class-path:" |
893 // The bad character shift for "class-path:" |
894 private static final byte[] CLASSPATH_LASTOCC; |
894 private static final byte[] CLASSPATH_LASTOCC; |
895 |
895 |
896 private static final byte[] MULTIRELEASE_CHARS = |
896 private static final byte[] MULTIRELEASE_CHARS = |
897 {'M','U','L','T','I','-','R','E','L','E', 'A', 'S', 'E', ':', ' '}; |
897 {'M','U','L','T','I','-','R','E','L','E', 'A', 'S', 'E', ':', |
898 ' ', 'T', 'R', 'U', 'E'}; |
|
898 |
899 |
899 // The bad character shift for "multi-release: " |
900 // The bad character shift for "multi-release: " |
900 private static final byte[] MULTIRELEASE_LASTOCC; |
901 private static final byte[] MULTIRELEASE_LASTOCC; |
901 |
902 |
902 static { |
903 static { |
912 CLASSPATH_LASTOCC[(int)':' - 32] = 11; |
913 CLASSPATH_LASTOCC[(int)':' - 32] = 11; |
913 CLASSPATH_LASTOCC[(int)' ' - 32] = 12; |
914 CLASSPATH_LASTOCC[(int)' ' - 32] = 12; |
914 |
915 |
915 MULTIRELEASE_LASTOCC = new byte[64]; |
916 MULTIRELEASE_LASTOCC = new byte[64]; |
916 MULTIRELEASE_LASTOCC[(int)'M' - 32] = 1; |
917 MULTIRELEASE_LASTOCC[(int)'M' - 32] = 1; |
917 MULTIRELEASE_LASTOCC[(int)'U' - 32] = 2; |
|
918 MULTIRELEASE_LASTOCC[(int)'T' - 32] = 4; |
|
919 MULTIRELEASE_LASTOCC[(int)'I' - 32] = 5; |
918 MULTIRELEASE_LASTOCC[(int)'I' - 32] = 5; |
920 MULTIRELEASE_LASTOCC[(int)'-' - 32] = 6; |
919 MULTIRELEASE_LASTOCC[(int)'-' - 32] = 6; |
921 MULTIRELEASE_LASTOCC[(int)'R' - 32] = 7; |
|
922 MULTIRELEASE_LASTOCC[(int)'L' - 32] = 9; |
920 MULTIRELEASE_LASTOCC[(int)'L' - 32] = 9; |
923 MULTIRELEASE_LASTOCC[(int)'A' - 32] = 11; |
921 MULTIRELEASE_LASTOCC[(int)'A' - 32] = 11; |
924 MULTIRELEASE_LASTOCC[(int)'S' - 32] = 12; |
922 MULTIRELEASE_LASTOCC[(int)'S' - 32] = 12; |
925 MULTIRELEASE_LASTOCC[(int)'E' - 32] = 13; |
|
926 MULTIRELEASE_LASTOCC[(int)':' - 32] = 14; |
923 MULTIRELEASE_LASTOCC[(int)':' - 32] = 14; |
927 MULTIRELEASE_LASTOCC[(int)' ' - 32] = 15; |
924 MULTIRELEASE_LASTOCC[(int)' ' - 32] = 15; |
925 MULTIRELEASE_LASTOCC[(int)'T' - 32] = 16; |
|
926 MULTIRELEASE_LASTOCC[(int)'R' - 32] = 17; |
|
927 MULTIRELEASE_LASTOCC[(int)'U' - 32] = 18; |
|
928 MULTIRELEASE_LASTOCC[(int)'E' - 32] = 19; |
|
928 } |
929 } |
929 |
930 |
930 private JarEntry getManEntry() { |
931 private JarEntry getManEntry() { |
931 if (manEntry == null) { |
932 if (manEntry == null) { |
932 // First look up manifest entry using standard name |
933 // First look up manifest entry using standard name |
964 * Returns true if the pattern {@code src} is found in {@code b}. |
965 * Returns true if the pattern {@code src} is found in {@code b}. |
965 * The {@code lastOcc} array is the precomputed bad character shifts. |
966 * The {@code lastOcc} array is the precomputed bad character shifts. |
966 * Since there are no repeated substring in our search strings, |
967 * Since there are no repeated substring in our search strings, |
967 * the good suffix shifts can be replaced with a comparison. |
968 * the good suffix shifts can be replaced with a comparison. |
968 */ |
969 */ |
969 private boolean match(byte[] src, byte[] b, byte[] lastOcc) { |
970 private int match(byte[] src, byte[] b, byte[] lastOcc) { |
970 int len = src.length; |
971 int len = src.length; |
971 int last = b.length - len; |
972 int last = b.length - len; |
972 int i = 0; |
973 int i = 0; |
973 next: |
974 next: |
974 while (i <= last) { |
975 while (i <= last) { |
988 // no match, character not valid for name |
989 // no match, character not valid for name |
989 i += len; |
990 i += len; |
990 continue next; |
991 continue next; |
991 } |
992 } |
992 } |
993 } |
993 return true; |
994 return i; |
994 } |
995 } |
995 return false; |
996 return -1; |
996 } |
997 } |
997 |
998 |
998 /** |
999 /** |
999 * On first invocation, check if the JAR file has the Class-Path |
1000 * On first invocation, check if the JAR file has the Class-Path |
1000 * and the Multi-Release attribute. A no-op on subsequent calls. |
1001 * and the Multi-Release attribute. A no-op on subsequent calls. |
1009 } |
1010 } |
1010 JarEntry manEntry = getManEntry(); |
1011 JarEntry manEntry = getManEntry(); |
1011 if (manEntry != null) { |
1012 if (manEntry != null) { |
1012 byte[] b = getBytes(manEntry); |
1013 byte[] b = getBytes(manEntry); |
1013 hasClassPathAttribute = match(CLASSPATH_CHARS, b, |
1014 hasClassPathAttribute = match(CLASSPATH_CHARS, b, |
1014 CLASSPATH_LASTOCC); |
1015 CLASSPATH_LASTOCC) != -1; |
1015 // is this a multi-release jar file |
1016 // is this a multi-release jar file |
1016 if (MULTI_RELEASE_ENABLED && version != BASE_VERSION) { |
1017 if (MULTI_RELEASE_ENABLED && version != BASE_VERSION) { |
1017 isMultiRelease = match(MULTIRELEASE_CHARS, b, |
1018 int i = match(MULTIRELEASE_CHARS, b, MULTIRELEASE_LASTOCC); |
1018 MULTIRELEASE_LASTOCC); |
1019 if (i != -1) { |
1020 i += MULTIRELEASE_CHARS.length; |
|
1021 if (i < b.length) { |
|
1022 byte c = b[i++]; |
|
1023 // Check that the value is followed by a newline |
|
1024 // and does not have a continuation |
|
1025 if (c == '\n' && |
|
1026 (i == b.length || b[i] != ' ')) { |
|
1027 isMultiRelease = true; |
|
1028 } else if (c == '\r') { |
|
1029 if (i == b.length) { |
|
1030 isMultiRelease = true; |
|
1031 } else { |
|
1032 c = b[i++]; |
|
1033 if (c == '\n') { |
|
1034 if (i == b.length || b[i] != ' ') { |
|
1035 isMultiRelease = true; |
|
1036 } |
|
1037 } else if (c != ' ') { |
|
1038 isMultiRelease = true; |
|
1039 } |
|
1040 } |
|
1041 } |
|
1042 } |
|
1043 } |
|
1019 } |
1044 } |
1020 } |
1045 } |
1021 hasCheckedSpecialAttributes = true; |
1046 hasCheckedSpecialAttributes = true; |
1022 } |
1047 } |
1023 } |
1048 } |