| /* ==================================================================== |
| 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.poi.hemf.record; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.apache.poi.hemf.hemfplus.record.HemfPlusRecord; |
| import org.apache.poi.hemf.hemfplus.record.HemfPlusRecordType; |
| import org.apache.poi.util.Internal; |
| import org.apache.poi.util.LittleEndian; |
| import org.apache.poi.util.RecordFormatException; |
| |
| /** |
| * An HemfCommentEMFPlus may contain one or more EMFPlus records |
| */ |
| @Internal |
| public class HemfCommentEMFPlus extends AbstractHemfComment { |
| |
| long dataSize; |
| public HemfCommentEMFPlus(byte[] rawBytes) { |
| //these rawBytes contain only the EMFPlusRecord(s?) |
| //the EmfComment type, size, datasize and comment identifier have all been stripped. |
| //The EmfPlus type, flags, size, data size should start at rawBytes[0] |
| super(rawBytes); |
| |
| } |
| |
| public List<HemfPlusRecord> getRecords() { |
| return HemfPlusParser.parse(getRawBytes()); |
| } |
| |
| private static class HemfPlusParser { |
| |
| public static List<HemfPlusRecord> parse(byte[] bytes) { |
| List<HemfPlusRecord> records = new ArrayList<HemfPlusRecord>(); |
| int offset = 0; |
| while (offset < bytes.length) { |
| if (offset + 12 > bytes.length) { |
| //if header will go beyond bytes, stop now |
| //TODO: log or throw |
| break; |
| } |
| int type = LittleEndian.getUShort(bytes, offset); offset += LittleEndian.SHORT_SIZE; |
| int flags = LittleEndian.getUShort(bytes, offset); offset += LittleEndian.SHORT_SIZE; |
| long sizeLong = LittleEndian.getUInt(bytes, offset); offset += LittleEndian.INT_SIZE; |
| if (sizeLong >= Integer.MAX_VALUE) { |
| throw new RecordFormatException("size of emf record >= Integer.MAX_VALUE"); |
| } |
| int size = (int)sizeLong; |
| long dataSizeLong = LittleEndian.getUInt(bytes, offset); offset += LittleEndian.INT_SIZE; |
| if (dataSizeLong >= Integer.MAX_VALUE) { |
| throw new RuntimeException("data size of emfplus record cannot be >= Integer.MAX_VALUE"); |
| } |
| int dataSize = (int)dataSizeLong; |
| if (dataSize + offset > bytes.length) { |
| //TODO: log or throw? |
| break; |
| } |
| HemfPlusRecord record = buildRecord(type, flags, dataSize, offset, bytes); |
| records.add(record); |
| offset += dataSize; |
| } |
| return records; |
| } |
| |
| private static HemfPlusRecord buildRecord(int recordId, int flags, int size, int offset, byte[] bytes) { |
| HemfPlusRecord record = null; |
| HemfPlusRecordType type = HemfPlusRecordType.getById(recordId); |
| if (type == null) { |
| throw new RuntimeException("Undefined record of type:"+recordId); |
| } |
| try { |
| record = type.clazz.newInstance(); |
| } catch (InstantiationException e) { |
| throw new RuntimeException(e); |
| } catch (IllegalAccessException e) { |
| throw new RuntimeException(e); |
| } |
| byte[] dataBytes = new byte[size]; |
| System.arraycopy(bytes, offset, dataBytes, 0, size); |
| try { |
| record.init(dataBytes, recordId, flags); |
| } catch (IOException e) { |
| throw new RuntimeException(e); |
| } |
| return record; |
| |
| } |
| } |
| } |