You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AbstractAFPObject.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.afp.modca;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.io.OutputStream;
  22. import java.util.Collection;
  23. import java.util.Iterator;
  24. import org.apache.commons.logging.Log;
  25. import org.apache.commons.logging.LogFactory;
  26. import org.apache.fop.afp.Streamable;
  27. import org.apache.fop.afp.util.BinaryUtils;
  28. /**
  29. * This is the base class for all data stream objects. Page objects are
  30. * responsible for building and generating the binary datastream in an
  31. * AFP format.
  32. */
  33. public abstract class AbstractAFPObject implements Streamable {
  34. /** Static logging instance */
  35. protected static final Log log // CSOK: ConstantName
  36. = LogFactory.getLog("org.apache.xmlgraphics.afp.modca");
  37. /** the structured field class id */
  38. protected static final byte SF_CLASS = (byte)0xD3;
  39. /** the structure field header */
  40. protected static final byte[] SF_HEADER = new byte[] {
  41. 0x5A, // Structured field identifier
  42. 0x00, // Length byte 1
  43. 0x10, // Length byte 2
  44. SF_CLASS, // Structured field id byte 1
  45. (byte) 0x00, // Structured field id byte 2
  46. (byte) 0x00, // Structured field id byte 3
  47. 0x00, // Flags
  48. 0x00, // Reserved
  49. 0x00, // Reserved
  50. };
  51. /**
  52. * Copies the template structured field data array to the given byte array
  53. *
  54. * @param data the structured field data byte array
  55. * @param type the type code
  56. * @param category the category code
  57. */
  58. protected void copySF(byte[] data, byte type, byte category) {
  59. copySF(data, SF_CLASS, type, category);
  60. }
  61. /**
  62. * Copies the template structured field data array to the given byte array
  63. *
  64. * @param data the structured field data byte array
  65. * @param clazz the class code
  66. * @param type the type code
  67. * @param category the category code
  68. */
  69. protected static void copySF(byte[] data, byte clazz, byte type, byte category) {
  70. System.arraycopy(SF_HEADER, 0, data, 0, SF_HEADER.length);
  71. data[3] = clazz;
  72. data[4] = type;
  73. data[5] = category;
  74. }
  75. /**
  76. * Writes a collection of Streamable to the AFP Datastream.
  77. *
  78. * @param objects a list of AFPObjects
  79. * @param os The stream to write to
  80. * @throws java.io.IOException an I/O exception of some sort has occurred.
  81. */
  82. protected void writeObjects(Collection/*<Streamable>*/ objects, OutputStream os)
  83. throws IOException {
  84. if (objects != null && objects.size() > 0) {
  85. Iterator it = objects.iterator();
  86. while (it.hasNext()) {
  87. Object object = it.next();
  88. if (object instanceof Streamable) {
  89. ((Streamable)object).writeToStream(os);
  90. it.remove(); // once written, immediately remove the object
  91. }
  92. }
  93. }
  94. }
  95. /**
  96. * Reads data chunks from an InputStream
  97. * and then formats them with a structured header to a given OutputStream
  98. *
  99. * @param dataHeader the header data
  100. * @param lengthOffset offset of length field in data chunk
  101. * @param maxChunkLength the maximum chunk length
  102. * @param inputStream the InputStream to read from
  103. * @param outputStream the OutputStream to write to
  104. * @throws IOException thrown if an I/O exception of some sort has occurred.
  105. */
  106. protected static void copyChunks(byte[] dataHeader, int lengthOffset,
  107. int maxChunkLength, InputStream inputStream, OutputStream outputStream)
  108. throws IOException {
  109. int headerLen = dataHeader.length - lengthOffset;
  110. // length field is just before data so do not include in data length
  111. if (headerLen == 2) {
  112. headerLen = 0;
  113. }
  114. byte[] data = new byte[maxChunkLength];
  115. int numBytesRead = 0;
  116. while ((numBytesRead = inputStream.read(data, 0, maxChunkLength)) > 0) {
  117. byte[] len = BinaryUtils.convert(headerLen + numBytesRead, 2);
  118. dataHeader[lengthOffset] = len[0]; // Length byte 1
  119. dataHeader[lengthOffset + 1] = len[1]; // Length byte 2
  120. outputStream.write(dataHeader);
  121. outputStream.write(data, 0, numBytesRead);
  122. }
  123. }
  124. /**
  125. * Writes data chunks to a given outputstream
  126. *
  127. * @param data the data byte array
  128. * @param dataHeader the header data
  129. * @param lengthOffset offset of length field in data chunk
  130. * @param maxChunkLength the maximum chunk length
  131. * @param os the outputstream to write to
  132. * @throws IOException thrown if an I/O exception of some sort has occurred.
  133. */
  134. protected static void writeChunksToStream(byte[] data, byte[] dataHeader,
  135. int lengthOffset, int maxChunkLength, OutputStream os) throws IOException {
  136. int dataLength = data.length;
  137. int numFullChunks = dataLength / maxChunkLength;
  138. int lastChunkLength = dataLength % maxChunkLength;
  139. int headerLen = dataHeader.length - lengthOffset;
  140. // length field is just before data so do not include in data length
  141. if (headerLen == 2) {
  142. headerLen = 0;
  143. }
  144. byte[] len;
  145. int off = 0;
  146. if (numFullChunks > 0) {
  147. // write out full data chunks
  148. len = BinaryUtils.convert(headerLen + maxChunkLength, 2);
  149. dataHeader[lengthOffset] = len[0]; // Length byte 1
  150. dataHeader[lengthOffset + 1] = len[1]; // Length byte 2
  151. for (int i = 0; i < numFullChunks; i++, off += maxChunkLength) {
  152. os.write(dataHeader);
  153. os.write(data, off, maxChunkLength);
  154. }
  155. }
  156. if (lastChunkLength > 0) {
  157. // write last data chunk
  158. len = BinaryUtils.convert(headerLen + lastChunkLength, 2);
  159. dataHeader[lengthOffset] = len[0]; // Length byte 1
  160. dataHeader[lengthOffset + 1] = len[1]; // Length byte 2
  161. os.write(dataHeader);
  162. os.write(data, off, lastChunkLength);
  163. }
  164. }
  165. /**
  166. * Truncates the string as necessary
  167. *
  168. * @param str a character string
  169. * @param maxLength the maximum length allowed for the string
  170. * @return a possibly truncated string
  171. */
  172. protected String truncate(String str, int maxLength) {
  173. if (str.length() > maxLength) {
  174. str = str.substring(0, maxLength);
  175. log.warn("truncated character string '"
  176. + str + "', longer than " + maxLength + " chars");
  177. }
  178. return str;
  179. }
  180. /** structured field type codes */
  181. public interface Type {
  182. /** Attribute */
  183. byte ATTRIBUTE = (byte)0xA0;
  184. /** Copy Count */
  185. byte COPY_COUNT = (byte)0xA2;
  186. /** Descriptor */
  187. byte DESCRIPTOR = (byte)0xA6;
  188. /** Control */
  189. byte CONTROL = (byte)0xA7;
  190. /** Begin */
  191. byte BEGIN = (byte)0xA8;
  192. /** End */
  193. byte END = (byte)0xA9;
  194. /** Map */
  195. byte MAP = (byte)0xAB;
  196. /** Position */
  197. byte POSITION = (byte)0xAC;
  198. /** Process */
  199. byte PROCESS = (byte)0xAD;
  200. /** Include */
  201. byte INCLUDE = (byte)0xAF;
  202. /** Table */
  203. byte TABLE = (byte)0xB0;
  204. /** Migration */
  205. byte MIGRATION = (byte)0xB1;
  206. /** Variable */
  207. byte VARIABLE = (byte)0xB2;
  208. /** Link */
  209. byte LINK = (byte)0xB4;
  210. /** Data */
  211. byte DATA = (byte)0xEE;
  212. }
  213. /** structured field category codes */
  214. public interface Category {
  215. /** Page Segment */
  216. byte PAGE_SEGMENT = (byte)0x5F;
  217. /** Object Area */
  218. byte OBJECT_AREA = (byte)0x6B;
  219. /** Color Attribute Table */
  220. byte COLOR_ATTRIBUTE_TABLE = (byte)0x77;
  221. /** IM Image */
  222. byte IM_IMAGE = (byte)0x7B;
  223. /** Medium */
  224. byte MEDIUM = (byte)0x88;
  225. /** Coded Font */
  226. byte CODED_FONT = (byte)0x8A;
  227. /** Process Element */
  228. byte PROCESS_ELEMENT = (byte)0x90;
  229. /** Object Container */
  230. byte OBJECT_CONTAINER = (byte)0x92;
  231. /** Presentation Text */
  232. byte PRESENTATION_TEXT = (byte)0x9B;
  233. /** Index */
  234. byte INDEX = (byte)0xA7;
  235. /** Document */
  236. byte DOCUMENT = (byte)0xA8;
  237. /** Page Group */
  238. byte PAGE_GROUP = (byte)0xAD;
  239. /** Page */
  240. byte PAGE = (byte)0xAF;
  241. /** Graphics */
  242. byte GRAPHICS = (byte)0xBB;
  243. /** Data Resource */
  244. byte DATA_RESOURCE = (byte)0xC3;
  245. /** Document Environment Group (DEG) */
  246. byte DOCUMENT_ENVIRONMENT_GROUP = (byte)0xC4;
  247. /** Resource Group */
  248. byte RESOURCE_GROUP = (byte)0xC6;
  249. /** Object Environment Group (OEG) */
  250. byte OBJECT_ENVIRONMENT_GROUP = (byte)0xC7;
  251. /** Active Environment Group (AEG) */
  252. byte ACTIVE_ENVIRONMENT_GROUP = (byte)0xC9;
  253. /** Medium Map */
  254. byte MEDIUM_MAP = (byte)0xCC;
  255. /** Form Map */
  256. byte FORM_MAP = (byte)0xCD;
  257. /** Name Resource */
  258. byte NAME_RESOURCE = (byte)0xCE;
  259. /** Page Overlay */
  260. byte PAGE_OVERLAY = (byte)0xD8;
  261. /** Resource Environment Group (REG) */
  262. byte RESOURCE_ENVIROMENT_GROUP = (byte)0xD9;
  263. /** Overlay */
  264. byte OVERLAY = (byte)0xDF;
  265. /** Data Suppression */
  266. byte DATA_SUPRESSION = (byte)0xEA;
  267. /** Bar Code */
  268. byte BARCODE = (byte)0xEB;
  269. /** No Operation */
  270. byte NO_OPERATION = (byte)0xEE;
  271. /** Image */
  272. byte IMAGE = (byte)0xFB;
  273. }
  274. }