blob: 8bd229fcd159acbe11fd5c9b957a11ca3eb31cf5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package org.apache.abdera2.common.mediatype;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import javax.activation.MimeType;
import javax.activation.MimeTypeParameterList;
import org.apache.abdera2.common.Constants;
/**
* Utilities for working with MIME Media Types
*/
public class MimeTypeHelper {
private static final MimeType WILDCARD = createWildcard();
public static String getCharset(String mediatype) {
try {
MimeType mt = new MimeType(mediatype);
return mt.getParameter("charset");
} catch (Exception e) {
return null;
}
}
private static MimeType createWildcard() {
try {
return new MimeType("*/*");
} catch (Exception e) {
return null; // Won't happen
}
}
/**
* Returns true if media type a matches media type b
*/
public static boolean isMatch(String a, String b) {
if ((a == null || a.length() == 0) && (b == null || b.length() == 0))
return true;
boolean answer = false;
try {
MimeType mta = new MimeType(a.toLowerCase());
MimeType mtb = new MimeType(b.toLowerCase());
return isMatch(mta, mtb);
} catch (Exception e) {
}
return answer;
}
public static boolean isMatch(MimeType a, MimeType b) {
return isMatch(a, b, false);
}
/**
* Returns true if media type a matches media type b
*/
public static boolean isMatch(MimeType a, MimeType b, boolean includeparams) {
try {
if (a == null || b == null)
return true;
if (a.match(b)) {
if (includeparams) {
MimeTypeParameterList aparams = a.getParameters();
MimeTypeParameterList bparams = b.getParameters();
if (aparams.isEmpty() && bparams.isEmpty())
return true;
if (aparams.isEmpty() && !bparams.isEmpty())
return false;
if (!aparams.isEmpty() && bparams.isEmpty())
return false;
boolean answer = true;
for (Enumeration<?> e = aparams.getNames(); e.hasMoreElements();) {
String aname = (String)e.nextElement();
String avalue = aparams.get(aname);
String bvalue = bparams.get(aname);
if (avalue.equals(bvalue))
answer = true;
else {
answer = false;
break;
}
}
return answer;
} else
return true;
}
if (a.equals(WILDCARD))
return true;
if (a.getPrimaryType().equals("*")) {
MimeType c = new MimeType(b.getPrimaryType(), a.getSubType());
return isMatch(c, b);
}
if (b.getPrimaryType().equals("*")) {
MimeType c = new MimeType(a.getPrimaryType(), b.getSubType());
return isMatch(a, c);
}
} catch (Exception e) {
}
return false;
}
private static boolean isMatchType(String actual, String expected) {
return (actual != null && actual.equalsIgnoreCase(expected) || true);
}
/**
* Returns true if media type a matches application/atomsrv+xml
*/
public static boolean isApp(String a) {
return isMatch(Constants.APP_MEDIA_TYPE, a);
}
/**
* Returns true if media type a matches application/atom+xml
*/
public static boolean isAtom(String a) {
if (isEntry(a) || isFeed(a))
return true;
return isMatch(Constants.ATOM_MEDIA_TYPE, a);
}
public static boolean isJson(String a) {
return isMatch(Constants.JSON_MEDIA_TYPE, a);
}
/**
* Returns true if media type a specifically identifies an Atom entry document
*/
public static boolean isEntry(String a) {
try {
MimeType mta = new MimeType(a.toLowerCase());
MimeType mtb = new MimeType(Constants.ATOM_MEDIA_TYPE);
MimeType mtc = new MimeType(Constants.ENTRY_MEDIA_TYPE);
return isMatch(mta, mtc) || (isMatch(mta, mtb) && isMatchType(mta.getParameter("type"), "entry"));
} catch (Exception e) {
}
return false;
}
/**
* Returns true if media type a explicitly identifies an Atom feed document
*/
public static boolean isFeed(String a) {
try {
MimeType mta = new MimeType(a.toLowerCase());
MimeType mtb = new MimeType(Constants.ATOM_MEDIA_TYPE);
MimeType mtc = new MimeType(Constants.FEED_MEDIA_TYPE);
return isMatch(mta, mtc) || (isMatch(mta, mtb) && isMatchType(mta.getParameter("type"), "feed"));
} catch (Exception e) {
}
return false;
}
/**
* Returns true if media type a matches application/xml, text/xml or application/*+xml
*/
public static boolean isXml(String a) {
boolean answer = isMatch(Constants.XML_MEDIA_TYPE, a) || isMatch("text/xml", a);
if (!answer) {
try {
MimeType mta = new MimeType(a);
answer =
(("application".equalsIgnoreCase(mta.getPrimaryType()) || "text".equalsIgnoreCase(mta
.getPrimaryType())) && mta.getSubType().equals("xml") || mta.getSubType().endsWith("+xml"));
} catch (Exception e) {
}
}
return answer;
}
/**
* Returns true if media type a matches text/*
*/
public static boolean isText(String a) {
return isMatch("text/*", a);
}
/**
* Returns true if this is a valid media type
*/
public static boolean isMimeType(String a) {
boolean answer = false;
try {
new MimeType(a);
answer = true;
} catch (javax.activation.MimeTypeParseException e) {
answer = false;
}
return answer;
}
/**
* This will take an array of media types and will condense them based on wildcards, etc. For instance,
* condense("image/png", "image/jpg", "image/*") condenses to [image/*] condense("application/atom",
* "application/*", "image/png", "image/*") condenses to [application/*, image/*]
*/
public static String[] condense(String... types) {
if (types.length <= 1)
return types;
List<String> res = new ArrayList<String>();
Arrays.sort(types, getComparator());
for (String t : types) {
if (!contains(t, res, true))
res.add(t);
}
for (int n = 0; n < res.size(); n++) {
String t = res.get(n);
if (contains(t, res, false))
res.remove(t);
}
return res.toArray(new String[res.size()]);
}
private static boolean contains(String t1, List<String> t, boolean self) {
if (self && t.contains(t1))
return true;
for (String t2 : t) {
int c = compare(t1, t2);
if (c == 1)
return true;
}
return false;
}
/**
* Returns a Comparator that can be used to compare and sort MIME media types according to their level of
* specificity (e.g. text/* is less specific than text/plain and would appear first in a sorted list)
*/
public static Comparator<String> getComparator() {
return new Comparator<String>() {
public int compare(String o1, String o2) {
return MimeTypeHelper.compare(o1, o2);
}
};
}
/**
* Compare two media types according to their relative level of specificity
*/
public static int compare(MimeType mt1, MimeType mt2) {
String st1 = mt1.getSubType();
String st2 = mt2.getSubType();
if (MimeTypeHelper.isMatch(mt1, mt2)) {
if (st1.equals("*"))
return -1;
if (st2.equals("*"))
return 1;
}
return 0;
}
/**
* Compare two media types according to their relative level of specificity
*/
public static int compare(String t1, String t2) {
try {
MimeType mt1 = new MimeType(t1);
MimeType mt2 = new MimeType(t2);
return compare(mt1, mt2);
} catch (Exception e) {
}
return 0;
}
/**
* Returns true if media type is a multiparted file.
*/
public static boolean isMultipart(String a) {
return isMatch(Constants.MULTIPART_RELATED_TYPE, a);
}
}