| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.tika.mime; |
| |
| import java.io.Serializable; |
| import java.util.ArrayList; |
| |
| /** |
| * Internet media type. |
| */ |
| public final class MimeType implements Comparable<MimeType>, Serializable { |
| |
| /** |
| * Serial version UID. |
| */ |
| private static final long serialVersionUID = 4357830439860729201L; |
| |
| /** |
| * Checks that the given string is a valid Internet media type name |
| * based on rules from RFC 2054 section 5.3. For validation purposes the |
| * rules can be simplified to the following: |
| * <pre> |
| * name := token "/" token |
| * token := 1*<any (US-ASCII) CHAR except SPACE, CTLs, or tspecials> |
| * tspecials := "(" / ")" / "<" / ">" / "@" / "," / ";" / ":" / |
| * "\" / <"> / "/" / "[" / "]" / "?" / "=" |
| * </pre> |
| * |
| * @param name name string |
| * @return <code>true</code> if the string is a valid media type name, |
| * <code>false</code> otherwise |
| */ |
| public static boolean isValid(String name) { |
| if (name == null) { |
| throw new IllegalArgumentException("Name is missing"); |
| } |
| |
| boolean slash = false; |
| for (int i = 0; i < name.length(); i++) { |
| char ch = name.charAt(i); |
| if (ch <= ' ' || ch >= 127 || ch == '(' || ch == ')' || |
| ch == '<' || ch == '>' || ch == '@' || ch == ',' || |
| ch == ';' || ch == ':' || ch == '\\' || ch == '"' || |
| ch == '[' || ch == ']' || ch == '?' || ch == '=') { |
| return false; |
| } else if (ch == '/') { |
| if (slash || i == 0 || i + 1 == name.length()) { |
| return false; |
| } |
| slash = true; |
| } |
| } |
| return slash; |
| } |
| |
| /** |
| * The normalized media type name. |
| */ |
| private final MediaType type; |
| |
| /** |
| * Description of this media type. |
| */ |
| private String description = ""; |
| |
| /** The magics associated to this Mime-Type */ |
| private final ArrayList<Magic> magics = new ArrayList<Magic>(); |
| |
| /** The root-XML associated to this Mime-Type */ |
| private final ArrayList<RootXML> rootXML = new ArrayList<RootXML>(); |
| |
| /** The minimum length of data to provides for magic analyzis */ |
| private int minLength = 0; |
| |
| /** Preferred extension with starting dot or empty string */ |
| private String extension = ""; |
| |
| /** |
| * Creates a media type with the give name and containing media type |
| * registry. The name is expected to be valid and normalized to lower |
| * case. This constructor should only be called by |
| * {@link MimeTypes#forName(String)} to keep the media type registry |
| * up to date. |
| * |
| * @param type normalized media type name |
| */ |
| MimeType(MediaType type) { |
| if (type == null) { |
| throw new IllegalArgumentException("Media type name is missing"); |
| } |
| this.type = type; |
| } |
| |
| /** |
| * Returns the normalized media type name. |
| * |
| * @return media type |
| */ |
| public MediaType getType() { |
| return type; |
| } |
| |
| /** |
| * Returns the name of this media type. |
| * |
| * @return media type name (lower case) |
| */ |
| public String getName() { |
| return type.toString(); |
| } |
| |
| /** |
| * Returns the description of this media type. |
| * |
| * @return media type description |
| */ |
| public String getDescription() { |
| return description; |
| } |
| |
| /** |
| * Set the description of this media type. |
| * |
| * @param description media type description |
| */ |
| public void setDescription(String description) { |
| if (description == null) { |
| throw new IllegalArgumentException("Description is missing"); |
| } |
| this.description = description; |
| } |
| |
| /** |
| * Add some rootXML info to this mime-type |
| * |
| * @param namespaceURI |
| * @param localName |
| */ |
| void addRootXML(String namespaceURI, String localName) { |
| rootXML.add(new RootXML(this, namespaceURI, localName)); |
| } |
| |
| boolean matchesXML(String namespaceURI, String localName) { |
| for (RootXML xml : rootXML) { |
| if (xml.matches(namespaceURI, localName)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| boolean hasRootXML() { |
| return (rootXML.size() > 0); |
| } |
| |
| RootXML[] getRootXMLs() { |
| return rootXML.toArray(new RootXML[rootXML.size()]); |
| } |
| |
| Magic[] getMagics() { |
| return magics.toArray(new Magic[magics.size()]); |
| } |
| |
| void addMagic(Magic magic) { |
| if (magic == null) { |
| return; |
| } |
| magics.add(magic); |
| } |
| |
| int getMinLength() { |
| return minLength; |
| } |
| |
| public boolean hasMagic() { |
| return (magics.size() > 0); |
| } |
| |
| public boolean matchesMagic(byte[] data) { |
| for (int i = 0; i < magics.size(); i++) { |
| Magic magic = magics.get(i); |
| if (magic.eval(data)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public boolean matches(byte[] data) { |
| return matchesMagic(data); |
| } |
| |
| /** |
| * Defines a RootXML description. RootXML is made of a localName and/or a |
| * namespaceURI. |
| */ |
| class RootXML implements Serializable { |
| |
| /** |
| * Serial version UID. |
| */ |
| private static final long serialVersionUID = 5140496601491000730L; |
| |
| private MimeType type = null; |
| |
| private String namespaceURI = null; |
| |
| private String localName = null; |
| |
| RootXML(MimeType type, String namespaceURI, String localName) { |
| if (isEmpty(namespaceURI) && isEmpty(localName)) { |
| throw new IllegalArgumentException( |
| "Both namespaceURI and localName cannot be empty"); |
| } |
| this.type = type; |
| this.namespaceURI = namespaceURI; |
| this.localName = localName; |
| } |
| |
| boolean matches(String namespaceURI, String localName) { |
| //Compare namespaces |
| if (!isEmpty(this.namespaceURI)) { |
| if (!this.namespaceURI.equals(namespaceURI)) { |
| return false; |
| } |
| } |
| else{ |
| // else if it was empty then check to see if the provided namespaceURI |
| // is empty. If it is not, then these two aren't equal and return false |
| if(!isEmpty(namespaceURI)){ |
| return false; |
| } |
| } |
| |
| //Compare root element's local name |
| if (!isEmpty(this.localName)) { |
| if (!this.localName.equals(localName)) { |
| return false; |
| } |
| } |
| else{ |
| // else if it was empty then check to see if the provided localName |
| // is empty. If it is not, then these two aren't equal and return false |
| if(!isEmpty(localName)){ |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Checks if a string is null or empty. |
| */ |
| private boolean isEmpty(String str) { |
| return (str == null) || (str.equals("")); |
| } |
| |
| MimeType getType() { |
| return type; |
| } |
| |
| String getNameSpaceURI() { |
| return namespaceURI; |
| } |
| |
| String getLocalName() { |
| return localName; |
| } |
| |
| public String toString() { |
| return type + ", " + namespaceURI + ", " + localName; |
| } |
| } |
| |
| //----------------------------------------------------------< Comparable > |
| |
| public int compareTo(MimeType mime) { |
| return type.compareTo(mime.type); |
| } |
| |
| //--------------------------------------------------------------< Object > |
| |
| /** |
| * Returns the name of this media type. |
| * |
| * @return media type name |
| */ |
| public String toString() { |
| return type.toString(); |
| } |
| |
| /** |
| * Get preferred extension |
| * |
| * @return extension (with starting dot) or empty string |
| */ |
| public String getExtension() { |
| return extension; |
| } |
| |
| void setExtension(String extension) { |
| this.extension = extension; |
| } |
| } |