001/** 002 * Java Web Archive Toolkit - Software to read and validate ARC, WARC 003 * and GZip files. (http://jwat.org/) 004 * Copyright 2011-2012 Netarkivet.dk (http://netarkivet.dk/) 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.jwat.common; 019 020/** 021 * Simple class to validate a scheme in the beginning of a byte array. 022 * 023 * @author nicl 024 */ 025public class Scheme { 026 027 /** Bit field used to identify valid first/follow characters. */ 028 protected static int[] bf = new int[256]; 029 030 /** 031 * Disable instantiation. 032 */ 033 protected Scheme() { 034 } 035 036 /* 037 * Initialize first/follow bit field. 038 */ 039 static { 040 String alphas = "abcdefghijklmnopqrstuvwxyz"; 041 for (int i=0; i<alphas.length(); ++i) { 042 bf[alphas.charAt(i)] = 3; 043 } 044 alphas = alphas.toUpperCase(); 045 for (int i=0; i<alphas.length(); ++i) { 046 bf[alphas.charAt(i)] = 3; 047 } 048 String digits = "1234567890"; 049 for (int i=0; i<digits.length(); ++i) { 050 bf[digits.charAt(i)] = 2; 051 } 052 String scheme = "+-."; 053 for (int i=0; i<scheme.length(); ++i) { 054 bf[scheme.charAt(i)] = 2; 055 } 056 } 057 058 /** 059 * Returns true if the start of the array is a valid scheme. 060 * @param bytes byte array in which to look for a valid scheme at the beginning 061 * @return true if the start of the array is a valid scheme 062 */ 063 public static boolean startsWithScheme(byte[] bytes) { 064 boolean result = false; 065 if (bytes != null) { 066 int idx = 0; 067 boolean bLoop = true; 068 int c; 069 while (bLoop) { 070 if (idx < bytes.length) { 071 c = bytes[idx]; 072 if (c == ':') { 073 bLoop = false; 074 if (idx > 0) { 075 result = true; 076 } 077 } else if (idx > 0) { 078 bLoop = ((bf[c & 255] & 2) != 0); 079 } else { 080 bLoop = ((bf[c & 255] & 1) != 0); 081 } 082 } else { 083 bLoop = false; 084 } 085 ++idx; 086 } 087 } 088 return result; 089 } 090 091 /** 092 * Returns a scheme if the given string has a valid scheme at the beginning 093 * of null if no scheme was found. 094 * @param uri a possible URI string 095 * @return a scheme if one is found or null 096 */ 097 public static String getScheme(String uri) { 098 if (uri != null) { 099 StringBuilder sb = new StringBuilder(); 100 int idx = 0; 101 boolean bLoop = true; 102 int c; 103 while (bLoop) { 104 if (idx < uri.length()) { 105 c = uri.charAt(idx); 106 if (c < 256) { 107 if (c == ':') { 108 //bLoop = false; 109 if (idx > 0) { 110 return sb.toString(); 111 } 112 } else if (idx > 0) { 113 sb.append((char)c); 114 bLoop = ((bf[c] & 2) != 0); 115 } else { 116 sb.append((char)c); 117 bLoop = ((bf[c] & 1) != 0); 118 } 119 } else { 120 bLoop = false; 121 } 122 } else { 123 bLoop = false; 124 } 125 ++idx; 126 } 127 } 128 return null; 129 } 130 131}