|
|
@@ -0,0 +1,284 @@ |
|
|
|
/* |
|
|
|
* 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. |
|
|
|
*/ |
|
|
|
|
|
|
|
/* $Id$ */ |
|
|
|
|
|
|
|
package org.apache.fop.afp.parser; |
|
|
|
|
|
|
|
import java.io.DataInputStream; |
|
|
|
import java.io.EOFException; |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.PrintStream; |
|
|
|
import java.text.DecimalFormat; |
|
|
|
|
|
|
|
import org.apache.commons.io.HexDump; |
|
|
|
|
|
|
|
/** |
|
|
|
* Represents an unparsed (generic) AFP structured field. |
|
|
|
*/ |
|
|
|
public class UnparsedStructuredField { |
|
|
|
|
|
|
|
private short sfLength; |
|
|
|
private byte sfClassCode; |
|
|
|
private byte sfTypeCode; |
|
|
|
private byte sfCategoryCode; |
|
|
|
private boolean sfiExtensionPresent; |
|
|
|
private boolean sfiSegmentedData; |
|
|
|
private boolean sfiPaddingPresent; |
|
|
|
private short extLength; |
|
|
|
private byte[] extData; |
|
|
|
private byte[] data; |
|
|
|
|
|
|
|
/** |
|
|
|
* Default constructor. |
|
|
|
*/ |
|
|
|
public UnparsedStructuredField() { |
|
|
|
//nop |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Reads a structured field from a {@link DataInputStream}. The resulting object can be |
|
|
|
* further interpreted be follow-up code. |
|
|
|
* @param din the stream to read from |
|
|
|
* @return the generic structured field |
|
|
|
* @throws IOException if an I/O error occurs |
|
|
|
*/ |
|
|
|
public static UnparsedStructuredField readStructuredField(DataInputStream din) |
|
|
|
throws IOException { |
|
|
|
short len; |
|
|
|
try { |
|
|
|
len = din.readShort(); |
|
|
|
} catch (EOFException eof) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
UnparsedStructuredField sf = new UnparsedStructuredField(); |
|
|
|
sf.sfLength = len; |
|
|
|
sf.sfClassCode = din.readByte(); |
|
|
|
sf.sfTypeCode = din.readByte(); |
|
|
|
sf.sfCategoryCode = din.readByte(); |
|
|
|
|
|
|
|
byte f = din.readByte(); |
|
|
|
sf.sfiExtensionPresent = (f & 0x01) != 0; |
|
|
|
sf.sfiSegmentedData = (f & 0x04) != 0; |
|
|
|
sf.sfiPaddingPresent = (f & 0x10) != 0; |
|
|
|
din.skip(2); //Reserved |
|
|
|
|
|
|
|
int dataLength = sf.sfLength - 8; |
|
|
|
if (sf.sfiExtensionPresent) { |
|
|
|
sf.extLength = (short)(((short)din.readByte()) & 0xFF); |
|
|
|
sf.extData = new byte[sf.extLength - 1]; |
|
|
|
din.readFully(sf.extData); |
|
|
|
dataLength -= sf.extLength; |
|
|
|
} |
|
|
|
sf.data = new byte[dataLength]; |
|
|
|
din.readFully(sf.data); |
|
|
|
return sf; |
|
|
|
} |
|
|
|
|
|
|
|
/** {@inheritDoc} */ |
|
|
|
public String toString() { |
|
|
|
StringBuffer sb = new StringBuffer("Structured Field: "); |
|
|
|
sb.append(Integer.toHexString(getSfTypeID()).toUpperCase()); |
|
|
|
sb.append(", len="); |
|
|
|
sb.append(new DecimalFormat("00000").format(getSfLength())); |
|
|
|
sb.append(" ").append(getTypeCodeAsString()); |
|
|
|
sb.append(" ").append(getCategoryCodeAsString()); |
|
|
|
if (isSfiExtensionPresent()) { |
|
|
|
sb.append(", SFI extension present"); |
|
|
|
} |
|
|
|
if (isSfiSegmentedData()) { |
|
|
|
sb.append(", segmented data"); |
|
|
|
} |
|
|
|
if (isSfiPaddingPresent()) { |
|
|
|
sb.append(", with padding"); |
|
|
|
} |
|
|
|
return sb.toString(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Dump the structured field as hex data to the given {@link PrintStream}. |
|
|
|
* @param out the {@link PrintStream} to dump to |
|
|
|
* @throws IOException if an I/O error occurs |
|
|
|
*/ |
|
|
|
public void dump(PrintStream out) throws IOException { |
|
|
|
out.println(toString()); |
|
|
|
HexDump.dump(getData(), 0, out, 0); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Dump the structured field as hex data to <code>System.out</code>. |
|
|
|
* @throws IOException if an I/O error occurs |
|
|
|
*/ |
|
|
|
public void dump() throws IOException { |
|
|
|
dump(System.out); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns type code function name for this field. |
|
|
|
* @return the type code function name |
|
|
|
*/ |
|
|
|
public String getTypeCodeAsString() { |
|
|
|
switch ((int)getSfTypeCode() & 0xFF) { |
|
|
|
case 0xA0: return "Attribute"; |
|
|
|
case 0xA2: return "CopyCount"; |
|
|
|
case 0xA6: return "Descriptor"; |
|
|
|
case 0xA7: return "Control"; |
|
|
|
case 0xA8: return "Begin"; |
|
|
|
case 0xA9: return "End"; |
|
|
|
case 0xAB: return "Map"; |
|
|
|
case 0xAC: return "Position"; |
|
|
|
case 0xAD: return "Process"; |
|
|
|
case 0xAF: return "Include"; |
|
|
|
case 0xB0: return "Table"; |
|
|
|
case 0xB1: return "Migration"; |
|
|
|
case 0xB2: return "Variable"; |
|
|
|
case 0xB4: return "Link"; |
|
|
|
case 0xEE: return "Data"; |
|
|
|
default: return "Unknown:" + Integer.toHexString((int)getSfTypeCode()).toUpperCase(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns category code function name for this field. |
|
|
|
* @return the category code function name |
|
|
|
*/ |
|
|
|
public String getCategoryCodeAsString() { |
|
|
|
switch ((int)getSfCategoryCode() & 0xFF) { |
|
|
|
case 0x5F: return "Page Segment"; |
|
|
|
case 0x6B: return "Object Area"; |
|
|
|
case 0x77: return "Color Attribute Table"; |
|
|
|
case 0x7B: return "IM Image"; |
|
|
|
case 0x88: return "Medium"; |
|
|
|
case 0x8A: return "Coded Font"; |
|
|
|
case 0x90: return "Process Element"; |
|
|
|
case 0x92: return "Object Container"; |
|
|
|
case 0x9B: return "Presentation Text"; |
|
|
|
case 0xA7: return "Index"; |
|
|
|
case 0xA8: return "Document"; |
|
|
|
case 0xAD: return "Page Group"; |
|
|
|
case 0xAF: return "Page"; |
|
|
|
case 0xBB: return "Graphics"; |
|
|
|
case 0xC3: return "Data Resource"; |
|
|
|
case 0xC4: return "Document Environment Group (DEG)"; |
|
|
|
case 0xC6: return "Resource Group"; |
|
|
|
case 0xC7: return "Object Environment Group (OEG)"; |
|
|
|
case 0xC9: return "Active Environment Group (AEG)"; |
|
|
|
case 0xCC: return "Medium Map"; |
|
|
|
case 0xCD: return "Form Map"; |
|
|
|
case 0xCE: return "Name Resource"; |
|
|
|
case 0xD8: return "Page Overlay"; |
|
|
|
case 0xD9: return "Resource Environment Group (REG)"; |
|
|
|
case 0xDF: return "Overlay"; |
|
|
|
case 0xEA: return "Data Supression"; |
|
|
|
case 0xEB: return "Bar Code"; |
|
|
|
case 0xEE: return "No Operation"; |
|
|
|
case 0xFB: return "Image"; |
|
|
|
default: return "Unknown:" + Integer.toHexString((int)getSfTypeCode()).toUpperCase(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns the structured field's length. |
|
|
|
* @return the field length |
|
|
|
*/ |
|
|
|
public short getSfLength() { |
|
|
|
return sfLength; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns the structured field's identifier. |
|
|
|
* @return the field identifier |
|
|
|
*/ |
|
|
|
public int getSfTypeID() { |
|
|
|
return ((getSfClassCode() & 0xFF) << 16) |
|
|
|
| ((getSfTypeCode() & 0xFF) << 8) |
|
|
|
| (getSfCategoryCode() & 0xFF); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns the structured field's class code. |
|
|
|
* @return the field class code |
|
|
|
*/ |
|
|
|
public byte getSfClassCode() { |
|
|
|
return sfClassCode; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns the structured field's type code. |
|
|
|
* @return the type code |
|
|
|
*/ |
|
|
|
public byte getSfTypeCode() { |
|
|
|
return sfTypeCode; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns the structured field's category code. |
|
|
|
* @return the sfCategoryCode |
|
|
|
*/ |
|
|
|
public byte getSfCategoryCode() { |
|
|
|
return sfCategoryCode; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Indicates whether an field introducer extension is present. |
|
|
|
* @return true if an field introducer extension is present |
|
|
|
*/ |
|
|
|
public boolean isSfiExtensionPresent() { |
|
|
|
return sfiExtensionPresent; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Indicates whether segmented data is present. |
|
|
|
* @return true if the data is segmented |
|
|
|
*/ |
|
|
|
public boolean isSfiSegmentedData() { |
|
|
|
return sfiSegmentedData; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Indicates whether the data is padded. |
|
|
|
* @return true if the data is padded |
|
|
|
*/ |
|
|
|
public boolean isSfiPaddingPresent() { |
|
|
|
return sfiPaddingPresent; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns the length of the extension if present. |
|
|
|
* @return the length of the extension (or 0 if no extension is present) |
|
|
|
*/ |
|
|
|
public short getExtLength() { |
|
|
|
return extLength; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns the extension data if present. |
|
|
|
* @return the extension data (or null if no extension is present) |
|
|
|
*/ |
|
|
|
public byte[] getExtData() { |
|
|
|
return extData; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns the structured field's payload. |
|
|
|
* @return the field's data |
|
|
|
*/ |
|
|
|
public byte[] getData() { |
|
|
|
return data; |
|
|
|
} |
|
|
|
|
|
|
|
} |