Home | History | Annotate | Download | only in fs
      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 {
     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
     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      */
     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      */
     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      */
     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      */
    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