Complete support for OOXML content types with parameters, including parts of the patch from Sebastien Schneider from bug #55026

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1569976 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2014-02-19 23:34:53 +00:00
parent edf1ffd89b
commit 56d6f0342a
2 changed files with 54 additions and 38 deletions

View File

@ -72,6 +72,11 @@ public final class ContentType {
* Media type compiled pattern, with parameters. * Media type compiled pattern, with parameters.
*/ */
private final static Pattern patternTypeSubTypeParams; private final static Pattern patternTypeSubTypeParams;
/**
* Pattern to match on just the parameters part, to work
* around the Java Regexp group capture behaviour
*/
private final static Pattern patternParams;
static { static {
/* /*
@ -123,7 +128,8 @@ public final class ContentType {
patternTypeSubType = Pattern.compile("^(" + token + "+)/(" + patternTypeSubType = Pattern.compile("^(" + token + "+)/(" +
token + "+)$"); token + "+)$");
patternTypeSubTypeParams = Pattern.compile("^(" + token + "+)/(" + patternTypeSubTypeParams = Pattern.compile("^(" + token + "+)/(" +
token + "+)(;" + parameter + ")+$"); token + "+)(;" + parameter + ")*$");
patternParams = Pattern.compile(";" + parameter);
} }
/** /**
@ -154,37 +160,41 @@ public final class ContentType {
// Parameters // Parameters
this.parameters = new Hashtable<String, String>(1); this.parameters = new Hashtable<String, String>(1);
//System.out.println(mMediaType.groupCount() + " = " + contentType); // Java RegExps are unhelpful, and won't do multiple group captures
//for (int j=1; j<mMediaType.groupCount(); j++) { System.out.println(" " + j + " - " + mMediaType.group(j)); } // See http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#cg
for (int i = 4; i <= mMediaType.groupCount() if (mMediaType.groupCount() >= 5) {
&& (mMediaType.group(i) != null); i += 2) { Matcher mParams = patternParams.matcher(contentType.substring(mMediaType.end(2)));
this.parameters.put(mMediaType.group(i), mMediaType while (mParams.find()) {
.group(i + 1)); this.parameters.put(mParams.group(1), mParams.group(2));
}
} }
} }
} }
/**
* Returns the content type as a string, including parameters
*/
@Override @Override
public final String toString() { public final String toString() {
StringBuffer retVal = new StringBuffer(); return toString(true);
retVal.append(this.getType());
retVal.append("/");
retVal.append(this.getSubType());
return retVal.toString();
} }
public final String toStringWithParameters() { public final String toString(boolean withParameters) {
StringBuffer retVal = new StringBuffer(); StringBuffer retVal = new StringBuffer();
retVal.append(toString()); retVal.append(this.getType());
retVal.append("/");
for (String key : parameters.keySet()) { retVal.append(this.getSubType());
retVal.append(";");
retVal.append(key); if (withParameters) {
retVal.append("="); for (String key : parameters.keySet()) {
retVal.append(parameters.get(key)); retVal.append(";");
} retVal.append(key);
return retVal.toString(); retVal.append("=");
} retVal.append(parameters.get(key));
}
}
return retVal.toString();
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {

View File

@ -88,12 +88,15 @@ public final class TestContentType extends TestCase {
* Invalid parameters are verified as incorrect in * Invalid parameters are verified as incorrect in
* {@link #testContentTypeParameterFailure()} * {@link #testContentTypeParameterFailure()}
*/ */
public void testContentTypeParam() { public void testContentTypeParam() throws InvalidFormatException {
// TODO Review [01.2], then add tests for valid ones String[] contentTypesToTest = new String[] { "mail/toto;titi=tata",
// TODO See bug #55026 "text/xml;a=b;c=d", "text/xml;key1=param1;key2=param2",
// String[] contentTypesToTest = new String[] { "mail/toto;titi=tata", "application/pgp-key;version=\"2\"",
// "text/xml;a=b;c=d" // TODO Maybe more? "application/x-resqml+xml;version=2.0;type=obj_global2dCrs"
// }; };
for (String contentType : contentTypesToTest) {
new ContentType(contentType);
}
} }
/** /**
@ -103,6 +106,7 @@ public final class TestContentType extends TestCase {
public void testContentTypeParameterFailure() { public void testContentTypeParameterFailure() {
String[] contentTypesToTest = new String[] { String[] contentTypesToTest = new String[] {
"mail/toto;\"titi=tata\"", // quotes not allowed like that "mail/toto;\"titi=tata\"", // quotes not allowed like that
"mail/toto;titi = tata", // spaces not allowed
"text/\u0080" // characters above ASCII are not allowed "text/\u0080" // characters above ASCII are not allowed
}; };
for (int i = 0; i < contentTypesToTest.length; ++i) { for (int i = 0; i < contentTypesToTest.length; ++i) {
@ -146,7 +150,7 @@ public final class TestContentType extends TestCase {
* Check that we can open a file where there are valid * Check that we can open a file where there are valid
* parameters on a content type * parameters on a content type
*/ */
public void DISABLEDtestFileWithContentTypeParams() throws Exception { public void testFileWithContentTypeParams() throws Exception {
InputStream is = OpenXML4JTestDataSamples.openSampleStream("ContentTypeHasParameters.ooxml"); InputStream is = OpenXML4JTestDataSamples.openSampleStream("ContentTypeHasParameters.ooxml");
OPCPackage p = OPCPackage.open(is); OPCPackage p = OPCPackage.open(is);
@ -171,27 +175,29 @@ public final class TestContentType extends TestCase {
} }
// Global Crs types do have params // Global Crs types do have params
else if (part.getPartName().toString().equals("/global1dCrs.xml")) { else if (part.getPartName().toString().equals("/global1dCrs.xml")) {
//System.out.println(part.getContentTypeDetails().toStringWithParameters()); assertEquals(typeResqml, part.getContentType().substring(0, typeResqml.length()));
assertEquals(typeResqml, part.getContentType()); assertEquals(typeResqml, part.getContentTypeDetails().toString(false));
assertEquals(typeResqml, part.getContentTypeDetails().toString());
assertEquals(true, part.getContentTypeDetails().hasParameters()); assertEquals(true, part.getContentTypeDetails().hasParameters());
assertEquals(typeResqml+";version=2.0;type=obj_global1dCrs", part.getContentTypeDetails().toString());
assertEquals(2, part.getContentTypeDetails().getParameterKeys().length); assertEquals(2, part.getContentTypeDetails().getParameterKeys().length);
assertEquals("2.0", part.getContentTypeDetails().getParameter("version")); assertEquals("2.0", part.getContentTypeDetails().getParameter("version"));
assertEquals("obj_global1dCrs", part.getContentTypeDetails().getParameter("type")); assertEquals("obj_global1dCrs", part.getContentTypeDetails().getParameter("type"));
} }
else if (part.getPartName().toString().equals("/global2dCrs.xml")) { else if (part.getPartName().toString().equals("/global2dCrs.xml")) {
assertEquals(typeResqml, part.getContentType()); assertEquals(typeResqml, part.getContentType().substring(0, typeResqml.length()));
assertEquals(typeResqml, part.getContentTypeDetails().toString()); assertEquals(typeResqml, part.getContentTypeDetails().toString(false));
assertEquals(true, part.getContentTypeDetails().hasParameters()); assertEquals(true, part.getContentTypeDetails().hasParameters());
assertEquals(typeResqml+";version=2.0;type=obj_global2dCrs", part.getContentTypeDetails().toString());
assertEquals(2, part.getContentTypeDetails().getParameterKeys().length); assertEquals(2, part.getContentTypeDetails().getParameterKeys().length);
assertEquals("2.0", part.getContentTypeDetails().getParameter("version")); assertEquals("2.0", part.getContentTypeDetails().getParameter("version"));
assertEquals("obj_global2dCrs", part.getContentTypeDetails().getParameter("type")); assertEquals("obj_global2dCrs", part.getContentTypeDetails().getParameter("type"));
} }
// Other thingy // Other thingy
else if (part.getPartName().toString().equals("/myTestingGuid.xml")) { else if (part.getPartName().toString().equals("/myTestingGuid.xml")) {
assertEquals(typeResqml, part.getContentType()); assertEquals(typeResqml, part.getContentType().substring(0, typeResqml.length()));
assertEquals(typeResqml, part.getContentTypeDetails().toString()); assertEquals(typeResqml, part.getContentTypeDetails().toString(false));
assertEquals(true, part.getContentTypeDetails().hasParameters()); assertEquals(true, part.getContentTypeDetails().hasParameters());
assertEquals(typeResqml+";version=2.0;type=obj_tectonicBoundaryFeature", part.getContentTypeDetails().toString());
assertEquals(2, part.getContentTypeDetails().getParameterKeys().length); assertEquals(2, part.getContentTypeDetails().getParameterKeys().length);
assertEquals("2.0", part.getContentTypeDetails().getParameter("version")); assertEquals("2.0", part.getContentTypeDetails().getParameter("version"));
assertEquals("obj_tectonicBoundaryFeature", part.getContentTypeDetails().getParameter("type")); assertEquals("obj_tectonicBoundaryFeature", part.getContentTypeDetails().getParameter("type"));