1 16 17 package org.apache.poi.hpsf; 18 19 import java.io.IOException ; 20 import java.io.OutputStream ; 21 import java.io.UnsupportedEncodingException ; 22 import java.util.Date ; 23 import java.util.LinkedList ; 24 import java.util.List ; 25 26 import org.apache.poi.util.LittleEndian; 27 import org.apache.poi.util.LittleEndianConsts; 28 29 50 public class VariantSupport extends Variant 51 { 52 53 private static boolean logUnsupportedTypes = false; 54 55 62 public static void setLogUnsupportedTypes(final boolean logUnsupportedTypes) 63 { 64 VariantSupport.logUnsupportedTypes = logUnsupportedTypes; 65 } 66 67 74 public static boolean isLogUnsupportedTypes() 75 { 76 return logUnsupportedTypes; 77 } 78 79 80 81 85 protected static List unsupportedMessage; 86 87 94 protected static void writeUnsupportedTypeMessage 95 (final UnsupportedVariantTypeException ex) 96 { 97 if (isLogUnsupportedTypes()) 98 { 99 if (unsupportedMessage == null) 100 unsupportedMessage = new LinkedList (); 101 Long vt = new Long (ex.getVariantType()); 102 if (!unsupportedMessage.contains(vt)) 103 { 104 System.err.println(ex.getMessage()); 105 unsupportedMessage.add(vt); 106 } 107 } 108 } 109 110 111 112 132 public static Object read(final byte[] src, final int offset, 133 final int length, final long type, 134 final int codepage) 135 throws ReadingNotSupportedException, UnsupportedEncodingException 136 { 137 Object value; 138 int o1 = offset; 139 int l1 = length - LittleEndian.INT_SIZE; 140 long lType = type; 141 142 144 if (codepage == Constants.CP_UNICODE && type == Variant.VT_LPSTR) 145 lType = Variant.VT_LPWSTR; 146 147 switch ((int) lType) 148 { 149 case Variant.VT_EMPTY: 150 { 151 value = null; 152 break; 153 } 154 case Variant.VT_I2: 155 { 156 160 value = new Integer (LittleEndian.getUShort(src, o1)); 161 break; 162 } 163 case Variant.VT_I4: 164 { 165 169 value = new Long (LittleEndian.getUInt(src, o1)); 170 break; 171 } 172 case Variant.VT_FILETIME: 173 { 174 178 final long low = LittleEndian.getUInt(src, o1); 179 o1 += LittleEndian.INT_SIZE; 180 final long high = LittleEndian.getUInt(src, o1); 181 value = Util.filetimeToDate((int) high, (int) low); 182 break; 183 } 184 case Variant.VT_LPSTR: 185 { 186 191 final int first = o1 + LittleEndian.INT_SIZE; 192 long last = first + LittleEndian.getUInt(src, o1) - 1; 193 o1 += LittleEndian.INT_SIZE; 194 while (src[(int) last] == 0 && first <= last) 195 last--; 196 final int l = (int) (last - first + 1); 197 value = codepage != -1 ? 198 new String (src, (int) first, l, 199 codepageToEncoding(codepage)) : 200 new String (src, (int) first, l); 201 break; 202 } 203 case Variant.VT_LPWSTR: 204 { 205 210 final int first = o1 + LittleEndian.INT_SIZE; 211 long last = first + LittleEndian.getUInt(src, o1) - 1; 212 long l = last - first; 213 o1 += LittleEndian.INT_SIZE; 214 StringBuffer b = new StringBuffer ((int) (last - first)); 215 for (int i = 0; i <= l; i++) 216 { 217 final int i1 = o1 + (i * 2); 218 final int i2 = i1 + 1; 219 final int high = src[i2] << 8; 220 final int low = src[i1] & 0x00ff; 221 final char c = (char) (high | low); 222 b.append(c); 223 } 224 225 while (b.length() > 0 && b.charAt(b.length() - 1) == 0x00) 226 b.setLength(b.length() - 1); 227 value = b.toString(); 228 break; 229 } 230 case Variant.VT_CF: 231 { 232 final byte[] v = new byte[l1]; 233 for (int i = 0; i < l1; i++) 234 v[i] = src[(int) (o1 + i)]; 235 value = v; 236 break; 237 } 238 case Variant.VT_BOOL: 239 { 240 245 long bool = LittleEndian.getUInt(src, o1); 247 if (bool != 0) 248 value = Boolean.TRUE; 249 else 250 value = Boolean.FALSE; 251 break; 252 } 253 default: 254 { 255 final byte[] v = new byte[l1]; 256 for (int i = 0; i < l1; i++) 257 v[i] = src[(int) (o1 + i)]; 258 throw new ReadingNotSupportedException(type, v); 259 } 260 } 261 return value; 262 } 263 264 265 266 280 public static String codepageToEncoding(final int codepage) 281 throws UnsupportedEncodingException 282 { 283 if (codepage <= 0) 284 throw new UnsupportedEncodingException 285 ("Codepage number may not be " + codepage); 286 switch (codepage) 287 { 288 case Constants.CP_MACROMAN: 289 return "MacRoman"; 290 case Constants.CP_SJIS: 291 return "SJIS"; 292 case Constants.CP_UTF16: 293 return "UTF-16"; 294 case Constants.CP_UTF8: 295 return "UTF-8"; 296 default: 297 return "cp" + codepage; 298 } 299 } 300 301 302 321 public static int write(final OutputStream out, final long type, 322 final Object value, final int codepage) 323 throws IOException , WritingNotSupportedException 324 { 325 int length = 0; 326 switch ((int) type) 327 { 328 case Variant.VT_BOOL: 329 { 330 int trueOrFalse; 331 if (((Boolean ) value).booleanValue()) 332 trueOrFalse = 1; 333 else 334 trueOrFalse = 0; 335 length = TypeWriter.writeUIntToStream(out, trueOrFalse); 336 break; 337 } 338 case Variant.VT_LPSTR: 339 { 340 final byte[] bytes = 341 (codepage == -1 ? 342 ((String ) value).getBytes() : 343 ((String ) value).getBytes(codepageToEncoding(codepage))); 344 length = TypeWriter.writeUIntToStream(out, bytes.length + 1); 345 final byte[] b = new byte[bytes.length + 1]; 346 System.arraycopy(bytes, 0, b, 0, bytes.length); 347 b[b.length - 1] = 0x00; 348 out.write(b); 349 length += b.length; 350 break; 351 } 352 case Variant.VT_LPWSTR: 353 { 354 final int nrOfChars = ((String ) value).length() + 1; 355 length += TypeWriter.writeUIntToStream(out, nrOfChars); 356 char[] s = Util.pad4((String ) value); 357 for (int i = 0; i < s.length; i++) 358 { 359 final int high = (int) ((s[i] & 0x0000ff00) >> 8); 360 final int low = (int) (s[i] & 0x000000ff); 361 final byte highb = (byte) high; 362 final byte lowb = (byte) low; 363 out.write(lowb); 364 out.write(highb); 365 length += 2; 366 } 367 out.write(0x00); 368 out.write(0x00); 369 length += 2; 370 break; 371 } 372 case Variant.VT_CF: 373 { 374 final byte[] b = (byte[]) value; 375 out.write(b); 376 length = b.length; 377 break; 378 } 379 case Variant.VT_EMPTY: 380 { 381 TypeWriter.writeUIntToStream(out, Variant.VT_EMPTY); 382 length = LittleEndianConsts.INT_SIZE; 383 break; 384 } 385 case Variant.VT_I2: 386 { 387 TypeWriter.writeToStream(out, ((Integer ) value).shortValue()); 388 length = LittleEndianConsts.SHORT_SIZE; 389 break; 390 } 391 case Variant.VT_I4: 392 { 393 length += TypeWriter.writeToStream(out, 394 ((Long ) value).intValue()); 395 break; 396 } 397 case Variant.VT_FILETIME: 398 { 399 long filetime = Util.dateToFileTime((Date ) value); 400 int high = (int) ((filetime >> 32) & 0x00000000FFFFFFFFL); 401 int low = (int) (filetime & 0x00000000FFFFFFFFL); 402 length += TypeWriter.writeUIntToStream 403 (out, 0x0000000FFFFFFFFL & low); 404 length += TypeWriter.writeUIntToStream 405 (out, 0x0000000FFFFFFFFL & high); 406 break; 407 } 408 default: 409 { 410 412 if (value instanceof byte[]) 413 { 414 final byte[] b = (byte[]) value; 415 out.write(b); 416 length = b.length; 417 writeUnsupportedTypeMessage 418 (new WritingNotSupportedException(type, value)); 419 } 420 else 421 throw new WritingNotSupportedException(type, value); 422 break; 423 } 424 } 425 426 return length; 427 } 428 429 } 430 | Popular Tags |