908 : new JarFileEntry(manEntry.getName(), manEntry);
909 }
910 return manEntry;
911 }
912
913 /**
914 * Returns {@code true} iff this JAR file has a manifest with the
915 * Class-Path attribute
916 */
917 boolean hasClassPathAttribute() throws IOException {
918 checkForSpecialAttributes();
919 return hasClassPathAttribute;
920 }
921
922 /**
923 * Returns true if the pattern {@code src} is found in {@code b}.
924 * The {@code lastOcc} array is the precomputed bad character shifts.
925 * Since there are no repeated substring in our search strings,
926 * the good suffix shifts can be replaced with a comparison.
927 */
928 private int match(byte[] src, byte[] b, byte[] lastOcc, byte[] optoSft) {
929 int len = src.length;
930 int last = b.length - len;
931 int i = 0;
932 next:
933 while (i <= last) {
934 for (int j = (len - 1); j >= 0; j--) {
935 byte c = b[i + j];
936 if (c >= ' ' && c <= 'z') {
937 if (c >= 'a') c -= 32; // Canonicalize
938
939 if (c != src[j]) {
940 // no match
941 int badShift = lastOcc[c - 32];
942 i += Math.max(j + 1 - badShift, optoSft[j]);
943 continue next;
944 }
945 } else {
946 // no match, character not valid for name
947 i += len;
948 continue next;
955
956 /**
957 * On first invocation, check if the JAR file has the Class-Path
958 * and the Multi-Release attribute. A no-op on subsequent calls.
959 */
960 private void checkForSpecialAttributes() throws IOException {
961 if (hasCheckedSpecialAttributes) {
962 return;
963 }
964 synchronized (this) {
965 if (hasCheckedSpecialAttributes) {
966 return;
967 }
968 JarEntry manEntry = getManEntry();
969 if (manEntry != null) {
970 byte[] b = getBytes(manEntry);
971 hasClassPathAttribute = match(CLASSPATH_CHARS, b,
972 CLASSPATH_LASTOCC, CLASSPATH_OPTOSFT) != -1;
973 // is this a multi-release jar file
974 if (MULTI_RELEASE_ENABLED) {
975 int i = match(MULTIRELEASE_CHARS, b, MULTIRELEASE_LASTOCC,
976 MULTIRELEASE_OPTOSFT);
977 if (i != -1) {
978 i += MULTIRELEASE_CHARS.length;
979 if (i < b.length) {
980 byte c = b[i++];
981 // Check that the value is followed by a newline
982 // and does not have a continuation
983 if (c == '\n' &&
984 (i == b.length || b[i] != ' ')) {
985 isMultiRelease = true;
986 } else if (c == '\r') {
987 if (i == b.length) {
988 isMultiRelease = true;
989 } else {
990 c = b[i++];
991 if (c == '\n') {
992 if (i == b.length || b[i] != ' ') {
993 isMultiRelease = true;
994 }
|
908 : new JarFileEntry(manEntry.getName(), manEntry);
909 }
910 return manEntry;
911 }
912
913 /**
914 * Returns {@code true} iff this JAR file has a manifest with the
915 * Class-Path attribute
916 */
917 boolean hasClassPathAttribute() throws IOException {
918 checkForSpecialAttributes();
919 return hasClassPathAttribute;
920 }
921
922 /**
923 * Returns true if the pattern {@code src} is found in {@code b}.
924 * The {@code lastOcc} array is the precomputed bad character shifts.
925 * Since there are no repeated substring in our search strings,
926 * the good suffix shifts can be replaced with a comparison.
927 */
928 private static int match(byte[] src, byte[] b, byte[] lastOcc, byte[] optoSft) {
929 int len = src.length;
930 int last = b.length - len;
931 int i = 0;
932 next:
933 while (i <= last) {
934 for (int j = (len - 1); j >= 0; j--) {
935 byte c = b[i + j];
936 if (c >= ' ' && c <= 'z') {
937 if (c >= 'a') c -= 32; // Canonicalize
938
939 if (c != src[j]) {
940 // no match
941 int badShift = lastOcc[c - 32];
942 i += Math.max(j + 1 - badShift, optoSft[j]);
943 continue next;
944 }
945 } else {
946 // no match, character not valid for name
947 i += len;
948 continue next;
955
956 /**
957 * On first invocation, check if the JAR file has the Class-Path
958 * and the Multi-Release attribute. A no-op on subsequent calls.
959 */
960 private void checkForSpecialAttributes() throws IOException {
961 if (hasCheckedSpecialAttributes) {
962 return;
963 }
964 synchronized (this) {
965 if (hasCheckedSpecialAttributes) {
966 return;
967 }
968 JarEntry manEntry = getManEntry();
969 if (manEntry != null) {
970 byte[] b = getBytes(manEntry);
971 hasClassPathAttribute = match(CLASSPATH_CHARS, b,
972 CLASSPATH_LASTOCC, CLASSPATH_OPTOSFT) != -1;
973 // is this a multi-release jar file
974 if (MULTI_RELEASE_ENABLED) {
975 // Keep this implementation up to date with
976 // JarFileSystem::isMultiReleaseJar
977 int i = match(MULTIRELEASE_CHARS, b, MULTIRELEASE_LASTOCC,
978 MULTIRELEASE_OPTOSFT);
979 if (i != -1) {
980 i += MULTIRELEASE_CHARS.length;
981 if (i < b.length) {
982 byte c = b[i++];
983 // Check that the value is followed by a newline
984 // and does not have a continuation
985 if (c == '\n' &&
986 (i == b.length || b[i] != ' ')) {
987 isMultiRelease = true;
988 } else if (c == '\r') {
989 if (i == b.length) {
990 isMultiRelease = true;
991 } else {
992 c = b[i++];
993 if (c == '\n') {
994 if (i == b.length || b[i] != ' ') {
995 isMultiRelease = true;
996 }
|