1 2 17 18 19 package org.apache.poi.poifs.property; 20 21 import java.io.*; 22 23 import java.util.*; 24 25 import org.apache.poi.hpsf.ClassID; 26 27 import org.apache.poi.poifs.common.POIFSConstants; 28 import org.apache.poi.poifs.dev.POIFSViewable; 29 import org.apache.poi.util.ByteField; 30 import org.apache.poi.util.IntegerField; 31 import org.apache.poi.util.LittleEndianConsts; 32 import org.apache.poi.util.ShortField; 33 34 40 41 public abstract class Property 42 implements Child, POIFSViewable 43 { 44 static final private byte _default_fill = ( byte ) 0x00; 45 static final private int _name_size_offset = 0x40; 46 static final private int _max_name_length = 47 (_name_size_offset / LittleEndianConsts.SHORT_SIZE) - 1; 48 static final protected int _NO_INDEX = -1; 49 50 static final private int _node_color_offset = 0x43; 52 static final private int _previous_property_offset = 0x44; 53 static final private int _next_property_offset = 0x48; 54 static final private int _child_property_offset = 0x4C; 55 static final private int _storage_clsid_offset = 0x50; 56 static final private int _user_flags_offset = 0x60; 57 static final private int _seconds_1_offset = 0x64; 58 static final private int _days_1_offset = 0x68; 59 static final private int _seconds_2_offset = 0x6C; 60 static final private int _days_2_offset = 0x70; 61 static final private int _start_block_offset = 0x74; 62 static final private int _size_offset = 0x78; 63 64 static final protected byte _NODE_BLACK = 1; 66 static final protected byte _NODE_RED = 0; 67 68 static final private int _big_block_minimum_bytes = 4096; 70 private String _name; 71 private ShortField _name_size; 72 private ByteField _property_type; 73 private ByteField _node_color; 74 private IntegerField _previous_property; 75 private IntegerField _next_property; 76 private IntegerField _child_property; 77 private ClassID _storage_clsid; 78 private IntegerField _user_flags; 79 private IntegerField _seconds_1; 80 private IntegerField _days_1; 81 private IntegerField _seconds_2; 82 private IntegerField _days_2; 83 private IntegerField _start_block; 84 private IntegerField _size; 85 private byte[] _raw_data; 86 private int _index; 87 private Child _next_child; 88 private Child _previous_child; 89 90 93 94 protected Property() 95 { 96 _raw_data = new byte[ POIFSConstants.PROPERTY_SIZE ]; 97 Arrays.fill(_raw_data, _default_fill); 98 _name_size = new ShortField(_name_size_offset); 99 _property_type = 100 new ByteField(PropertyConstants.PROPERTY_TYPE_OFFSET); 101 _node_color = new ByteField(_node_color_offset); 102 _previous_property = new IntegerField(_previous_property_offset, 103 _NO_INDEX, _raw_data); 104 _next_property = new IntegerField(_next_property_offset, 105 _NO_INDEX, _raw_data); 106 _child_property = new IntegerField(_child_property_offset, 107 _NO_INDEX, _raw_data); 108 _storage_clsid = new ClassID(_raw_data,_storage_clsid_offset); 109 _user_flags = new IntegerField(_user_flags_offset, 0, _raw_data); 110 _seconds_1 = new IntegerField(_seconds_1_offset, 0, 111 _raw_data); 112 _days_1 = new IntegerField(_days_1_offset, 0, _raw_data); 113 _seconds_2 = new IntegerField(_seconds_2_offset, 0, 114 _raw_data); 115 _days_2 = new IntegerField(_days_2_offset, 0, _raw_data); 116 _start_block = new IntegerField(_start_block_offset); 117 _size = new IntegerField(_size_offset, 0, _raw_data); 118 _index = _NO_INDEX; 119 setName(""); 120 setNextChild(null); 121 setPreviousChild(null); 122 } 123 124 131 132 protected Property(final int index, final byte [] array, final int offset) 133 { 134 _raw_data = new byte[ POIFSConstants.PROPERTY_SIZE ]; 135 System.arraycopy(array, offset, _raw_data, 0, 136 POIFSConstants.PROPERTY_SIZE); 137 _name_size = new ShortField(_name_size_offset, _raw_data); 138 _property_type = 139 new ByteField(PropertyConstants.PROPERTY_TYPE_OFFSET, _raw_data); 140 _node_color = new ByteField(_node_color_offset, _raw_data); 141 _previous_property = new IntegerField(_previous_property_offset, 142 _raw_data); 143 _next_property = new IntegerField(_next_property_offset, 144 _raw_data); 145 _child_property = new IntegerField(_child_property_offset, 146 _raw_data); 147 _storage_clsid = new ClassID(_raw_data,_storage_clsid_offset); 148 _user_flags = new IntegerField(_user_flags_offset, 0, _raw_data); 149 _seconds_1 = new IntegerField(_seconds_1_offset, _raw_data); 150 _days_1 = new IntegerField(_days_1_offset, _raw_data); 151 _seconds_2 = new IntegerField(_seconds_2_offset, _raw_data); 152 _days_2 = new IntegerField(_days_2_offset, _raw_data); 153 _start_block = new IntegerField(_start_block_offset, _raw_data); 154 _size = new IntegerField(_size_offset, _raw_data); 155 _index = index; 156 int name_length = (_name_size.get() / LittleEndianConsts.SHORT_SIZE) 157 - 1; 158 159 if (name_length < 1) 160 { 161 _name = ""; 162 } 163 else 164 { 165 char[] char_array = new char[ name_length ]; 166 int name_offset = 0; 167 168 for (int j = 0; j < name_length; j++) 169 { 170 char_array[ j ] = ( char ) new ShortField(name_offset, 171 _raw_data).get(); 172 name_offset += LittleEndianConsts.SHORT_SIZE; 173 } 174 _name = new String (char_array, 0, name_length); 175 } 176 _next_child = null; 177 _previous_child = null; 178 } 179 180 189 190 public void writeData(final OutputStream stream) 191 throws IOException 192 { 193 stream.write(_raw_data); 194 } 195 196 202 203 public void setStartBlock(final int startBlock) 204 { 205 _start_block.set(startBlock, _raw_data); 206 } 207 208 211 212 public int getStartBlock() 213 { 214 return _start_block.get(); 215 } 216 217 222 223 public int getSize() 224 { 225 return _size.get(); 226 } 227 228 234 235 public boolean shouldUseSmallBlocks() 236 { 237 return Property.isSmall(_size.get()); 238 } 239 240 248 249 public static boolean isSmall(final int length) 250 { 251 return length < _big_block_minimum_bytes; 252 } 253 254 259 260 public String getName() 261 { 262 return _name; 263 } 264 265 268 269 abstract public boolean isDirectory(); 270 271 276 public ClassID getStorageClsid() 277 { 278 return _storage_clsid; 279 } 280 281 286 protected final void setName(final String name) 287 { 288 char[] char_array = name.toCharArray(); 289 int limit = Math.min(char_array.length, _max_name_length); 290 291 _name = new String (char_array, 0, limit); 292 short offset = 0; 293 int j = 0; 294 295 for (; j < limit; j++) 296 { 297 new ShortField(offset, ( short ) char_array[ j ], _raw_data); 298 offset += LittleEndianConsts.SHORT_SIZE; 299 } 300 for (; j < _max_name_length + 1; j++) 301 { 302 new ShortField(offset, ( short ) 0, _raw_data); 303 offset += LittleEndianConsts.SHORT_SIZE; 304 } 305 306 _name_size 308 .set(( short ) ((limit + 1) 309 * LittleEndianConsts.SHORT_SIZE), _raw_data); 310 } 311 312 317 public void setStorageClsid( ClassID clsidStorage) 318 { 319 _storage_clsid = clsidStorage; 320 if( clsidStorage == null) { 321 Arrays.fill( _raw_data, _storage_clsid_offset, _storage_clsid_offset + ClassID.LENGTH, (byte) 0); 322 } else { 323 clsidStorage.write( _raw_data, _storage_clsid_offset); 324 } 325 } 326 331 332 protected void setPropertyType(final byte propertyType) 333 { 334 _property_type.set(propertyType, _raw_data); 335 } 336 337 342 343 protected void setNodeColor(final byte nodeColor) 344 { 345 _node_color.set(nodeColor, _raw_data); 346 } 347 348 353 354 protected void setChildProperty(final int child) 355 { 356 _child_property.set(child, _raw_data); 357 } 358 359 364 365 protected int getChildIndex() 366 { 367 return _child_property.get(); 368 } 369 370 375 376 protected void setSize(final int size) 377 { 378 _size.set(size, _raw_data); 379 } 380 381 387 388 protected void setIndex(final int index) 389 { 390 _index = index; 391 } 392 393 398 399 protected int getIndex() 400 { 401 return _index; 402 } 403 404 408 409 abstract protected void preWrite(); 410 411 416 417 int getNextChildIndex() 418 { 419 return _next_property.get(); 420 } 421 422 427 428 int getPreviousChildIndex() 429 { 430 return _previous_property.get(); 431 } 432 433 440 441 static boolean isValidIndex(int index) 442 { 443 return index != _NO_INDEX; 444 } 445 446 447 448 453 454 public Child getNextChild() 455 { 456 return _next_child; 457 } 458 459 464 465 public Child getPreviousChild() 466 { 467 return _previous_child; 468 } 469 470 476 477 public void setNextChild(final Child child) 478 { 479 _next_child = child; 480 _next_property.set((child == null) ? _NO_INDEX 481 : (( Property ) child) 482 .getIndex(), _raw_data); 483 } 484 485 491 492 public void setPreviousChild(final Child child) 493 { 494 _previous_child = child; 495 _previous_property.set((child == null) ? _NO_INDEX 496 : (( Property ) child) 497 .getIndex(), _raw_data); 498 } 499 500 501 502 503 509 510 public Object [] getViewableArray() 511 { 512 Object [] results = new Object [ 5 ]; 513 514 results[ 0 ] = "Name = \"" + getName() + "\""; 515 results[ 1 ] = "Property Type = " + _property_type.get(); 516 results[ 2 ] = "Node Color = " + _node_color.get(); 517 long time = _days_1.get(); 518 519 time <<= 32; 520 time += (( long ) _seconds_1.get()) & 0x0000FFFFL; 521 results[ 3 ] = "Time 1 = " + time; 522 time = _days_2.get(); 523 time <<= 32; 524 time += (( long ) _seconds_2.get()) & 0x0000FFFFL; 525 results[ 4 ] = "Time 2 = " + time; 526 return results; 527 } 528 529 536 537 public Iterator getViewableIterator() 538 { 539 return Collections.EMPTY_LIST.iterator(); 540 } 541 542 549 550 public boolean preferArray() 551 { 552 return true; 553 } 554 555 561 562 public String getShortDescription() 563 { 564 StringBuffer buffer = new StringBuffer (); 565 566 buffer.append("Property: \"").append(getName()).append("\""); 567 return buffer.toString(); 568 } 569 570 571 } 573 | Popular Tags |