1 /* 2 * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.fs; 27 28 import java.nio.file.Path; 29 import java.nio.file.spi.FileTypeDetector; 30 import java.util.Locale; 31 import java.io.IOException; 32 33 /** 34 * Base implementation of FileTypeDetector 35 */ 36 37 public abstract class AbstractFileTypeDetector 38 extends FileTypeDetector 39 { AbstractFileTypeDetector()40 protected AbstractFileTypeDetector() { 41 super(); 42 } 43 44 /** 45 * Invokes the appropriate probe method to guess a file's content type, 46 * and checks that the content type's syntax is valid. 47 */ 48 @Override probeContentType(Path file)49 public final String probeContentType(Path file) throws IOException { 50 if (file == null) 51 throw new NullPointerException("'file' is null"); 52 String result = implProbeContentType(file); 53 return (result == null) ? null : parse(result); 54 } 55 56 /** 57 * Probes the given file to guess its content type. 58 */ implProbeContentType(Path file)59 protected abstract String implProbeContentType(Path file) 60 throws IOException; 61 62 /** 63 * Parses a candidate content type into its type and subtype, returning 64 * null if either token is invalid. 65 */ parse(String s)66 private static String parse(String s) { 67 int slash = s.indexOf('/'); 68 int semicolon = s.indexOf(';'); 69 if (slash < 0) 70 return null; // no subtype 71 String type = s.substring(0, slash).trim().toLowerCase(Locale.ENGLISH); 72 if (!isValidToken(type)) 73 return null; // invalid type 74 String subtype = (semicolon < 0) ? s.substring(slash + 1) : 75 s.substring(slash + 1, semicolon); 76 subtype = subtype.trim().toLowerCase(Locale.ENGLISH); 77 if (!isValidToken(subtype)) 78 return null; // invalid subtype 79 StringBuilder sb = new StringBuilder(type.length() + subtype.length() + 1); 80 sb.append(type); 81 sb.append('/'); 82 sb.append(subtype); 83 return sb.toString(); 84 } 85 86 /** 87 * Special characters 88 */ 89 private static final String TSPECIALS = "()<>@,;:/[]?=\\\""; 90 91 /** 92 * Returns true if the character is a valid token character. 93 */ isTokenChar(char c)94 private static boolean isTokenChar(char c) { 95 return (c > 040) && (c < 0177) && (TSPECIALS.indexOf(c) < 0); 96 } 97 98 /** 99 * Returns true if the given string is a legal type or subtype. 100 */ isValidToken(String s)101 private static boolean isValidToken(String s) { 102 int len = s.length(); 103 if (len == 0) 104 return false; 105 for (int i = 0; i < len; i++) { 106 if (!isTokenChar(s.charAt(i))) 107 return false; 108 } 109 return true; 110 } 111 } 112