001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.converter; 018 019import java.io.BufferedReader; 020import java.io.BufferedWriter; 021import java.io.ByteArrayInputStream; 022import java.io.ByteArrayOutputStream; 023import java.io.File; 024import java.io.FileInputStream; 025import java.io.FileNotFoundException; 026import java.io.FileOutputStream; 027import java.io.IOException; 028import java.io.InputStream; 029import java.io.InputStreamReader; 030import java.io.ObjectInput; 031import java.io.ObjectInputStream; 032import java.io.ObjectOutput; 033import java.io.ObjectOutputStream; 034import java.io.ObjectStreamClass; 035import java.io.OutputStream; 036import java.io.OutputStreamWriter; 037import java.io.Reader; 038import java.io.StringReader; 039import java.io.UnsupportedEncodingException; 040import java.io.Writer; 041import java.net.URL; 042import java.nio.ByteBuffer; 043import java.nio.CharBuffer; 044import java.nio.charset.Charset; 045import java.nio.charset.CharsetEncoder; 046import java.nio.charset.UnsupportedCharsetException; 047import java.util.Properties; 048 049import org.apache.camel.Converter; 050import org.apache.camel.Exchange; 051import org.apache.camel.util.IOHelper; 052import org.slf4j.Logger; 053import org.slf4j.LoggerFactory; 054 055/** 056 * Some core java.io based <a 057 * href="http://camel.apache.org/type-converter.html">Type Converters</a> 058 * 059 * @version 060 */ 061@Converter 062public final class IOConverter { 063 064 private static final Logger LOG = LoggerFactory.getLogger(IOConverter.class); 065 066 /** 067 * Utility classes should not have a public constructor. 068 */ 069 private IOConverter() { 070 } 071 072 @Converter 073 public static InputStream toInputStream(URL url) throws IOException { 074 return IOHelper.buffered(url.openStream()); 075 } 076 077 @Converter 078 public static InputStream toInputStream(File file) throws IOException { 079 return IOHelper.buffered(new FileInputStream(file)); 080 } 081 082 /** 083 * Converts the given {@link File} with the given charset to {@link InputStream} with the JVM default charset 084 * 085 * @param file the file to be converted 086 * @param charset the charset the file is read with 087 * @return the input stream with the JVM default charset 088 */ 089 public static InputStream toInputStream(File file, String charset) throws IOException { 090 if (charset != null) { 091 return new EncodingInputStream(file, charset); 092 } else { 093 return toInputStream(file); 094 } 095 } 096 097 /** 098 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 099 */ 100 @Deprecated 101 public static BufferedReader toReader(File file) throws IOException { 102 return toReader(file, (String) null); 103 } 104 105 @Converter 106 public static BufferedReader toReader(File file, Exchange exchange) throws IOException { 107 return toReader(file, IOHelper.getCharsetName(exchange)); 108 } 109 110 public static BufferedReader toReader(File file, String charset) throws IOException { 111 FileInputStream in = new FileInputStream(file); 112 return IOHelper.buffered(new EncodingFileReader(in, charset)); 113 } 114 115 @Converter 116 public static File toFile(String name) { 117 return new File(name); 118 } 119 120 @Converter 121 public static OutputStream toOutputStream(File file) throws FileNotFoundException { 122 return IOHelper.buffered(new FileOutputStream(file)); 123 } 124 125 /** 126 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 127 */ 128 @Deprecated 129 public static BufferedWriter toWriter(File file) throws IOException { 130 FileOutputStream os = new FileOutputStream(file, false); 131 return toWriter(os, IOHelper.getCharsetName(null, true)); 132 } 133 134 @Converter 135 public static BufferedWriter toWriter(File file, Exchange exchange) throws IOException { 136 FileOutputStream os = new FileOutputStream(file, false); 137 return toWriter(os, IOHelper.getCharsetName(exchange)); 138 } 139 140 public static BufferedWriter toWriter(File file, boolean append, String charset) throws IOException { 141 return toWriter(new FileOutputStream(file, append), charset); 142 } 143 144 public static BufferedWriter toWriter(FileOutputStream os, String charset) throws IOException { 145 return IOHelper.buffered(new EncodingFileWriter(os, charset)); 146 } 147 148 public static BufferedWriter toWriter(FileOutputStream os, CharsetEncoder enc) throws IOException { 149 return IOHelper.buffered(new EncodingFileWriter(os, enc)); 150 } 151 152 /** 153 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 154 */ 155 @Deprecated 156 public static Reader toReader(InputStream in) throws IOException { 157 return toReader(in, null); 158 } 159 160 @Converter 161 public static Reader toReader(InputStream in, Exchange exchange) throws IOException { 162 return IOHelper.buffered(new InputStreamReader(in, IOHelper.getCharsetName(exchange))); 163 } 164 165 /** 166 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 167 */ 168 @Deprecated 169 public static Writer toWriter(OutputStream out) throws IOException { 170 return toWriter(out, null); 171 } 172 173 @Converter 174 public static Writer toWriter(OutputStream out, Exchange exchange) throws IOException { 175 return IOHelper.buffered(new OutputStreamWriter(out, IOHelper.getCharsetName(exchange))); 176 } 177 178 @Converter 179 public static StringReader toReader(String text) { 180 // no buffering required as the complete string input is already passed 181 // over as a whole 182 return new StringReader(text); 183 } 184 185 /** 186 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 187 */ 188 @Deprecated 189 public static InputStream toInputStream(String text) throws IOException { 190 return toInputStream(text, null); 191 } 192 193 @Converter 194 public static InputStream toInputStream(String text, Exchange exchange) throws IOException { 195 return toInputStream(text.getBytes(IOHelper.getCharsetName(exchange))); 196 } 197 198 @Converter 199 public static InputStream toInputStream(StringBuffer buffer, Exchange exchange) throws IOException { 200 return toInputStream(buffer.toString(), exchange); 201 } 202 203 @Converter 204 public static InputStream toInputStream(StringBuilder builder, Exchange exchange) throws IOException { 205 return toInputStream(builder.toString(), exchange); 206 } 207 208 /** 209 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 210 */ 211 @Deprecated 212 public static InputStream toInputStream(BufferedReader buffer) throws IOException { 213 return toInputStream(buffer, null); 214 } 215 216 @Converter 217 public static InputStream toInputStream(BufferedReader buffer, Exchange exchange) throws IOException { 218 return toInputStream(toString(buffer), exchange); 219 } 220 221 /** 222 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 223 */ 224 @Deprecated 225 public static String toString(byte[] data) throws IOException { 226 return toString(data, null); 227 } 228 229 @Converter 230 public static String toString(byte[] data, Exchange exchange) throws IOException { 231 return new String(data, IOHelper.getCharsetName(exchange)); 232 } 233 234 /** 235 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 236 */ 237 @Deprecated 238 public static String toString(File file) throws IOException { 239 return toString(file, null); 240 } 241 242 @Converter 243 public static String toString(File file, Exchange exchange) throws IOException { 244 return toString(toReader(file, exchange)); 245 } 246 247 @Converter 248 public static byte[] toByteArray(File file) throws IOException { 249 InputStream is = toInputStream(file); 250 try { 251 return toBytes(is); 252 } finally { 253 IOHelper.close(is, "file", LOG); 254 } 255 } 256 257 /** 258 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 259 */ 260 @Deprecated 261 public static byte[] toByteArray(Reader reader) throws IOException { 262 return toByteArray(reader, null); 263 } 264 265 @Converter 266 public static byte[] toByteArray(Reader reader, Exchange exchange) throws IOException { 267 return toByteArray(IOHelper.buffered(reader), exchange); 268 } 269 270 /** 271 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 272 */ 273 @Deprecated 274 public static String toString(URL url) throws IOException { 275 return toString(url, null); 276 } 277 278 @Converter 279 public static String toString(URL url, Exchange exchange) throws IOException { 280 InputStream is = toInputStream(url); 281 try { 282 return toString(is, exchange); 283 } finally { 284 IOHelper.close(is, "url", LOG); 285 } 286 } 287 288 @Converter 289 public static String toString(Reader reader) throws IOException { 290 return toString(IOHelper.buffered(reader)); 291 } 292 293 @Converter 294 public static String toString(BufferedReader reader) throws IOException { 295 StringBuilder sb = new StringBuilder(1024); 296 char[] buf = new char[1024]; 297 try { 298 int len; 299 // read until we reach then end which is the -1 marker 300 while ((len = reader.read(buf)) != -1) { 301 sb.append(buf, 0, len); 302 } 303 } finally { 304 IOHelper.close(reader, "reader", LOG); 305 } 306 307 return sb.toString(); 308 } 309 310 /** 311 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 312 */ 313 @Deprecated 314 public static byte[] toByteArray(BufferedReader reader) throws IOException { 315 return toByteArray(reader, null); 316 } 317 318 @Converter 319 public static byte[] toByteArray(BufferedReader reader, Exchange exchange) throws IOException { 320 String s = toString(reader); 321 return toByteArray(s, exchange); 322 } 323 324 /** 325 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 326 */ 327 @Deprecated 328 public static byte[] toByteArray(String value) throws IOException { 329 return toByteArray(value, null); 330 } 331 332 @Converter 333 public static byte[] toByteArray(String value, Exchange exchange) throws IOException { 334 return value.getBytes(IOHelper.getCharsetName(exchange)); 335 } 336 337 /** 338 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 339 */ 340 @Deprecated 341 public static String toString(InputStream in) throws IOException { 342 return toString(in, null); 343 } 344 345 @Converter 346 public static String toString(InputStream in, Exchange exchange) throws IOException { 347 return toString(toReader(in, exchange)); 348 } 349 350 @Converter 351 public static InputStream toInputStream(byte[] data) { 352 // no buffering required as the complete byte input is already passed 353 // over as a whole 354 return new ByteArrayInputStream(data); 355 } 356 357 @Converter 358 public static ObjectOutput toObjectOutput(OutputStream stream) throws IOException { 359 if (stream instanceof ObjectOutput) { 360 return (ObjectOutput) stream; 361 } else { 362 return new ObjectOutputStream(IOHelper.buffered(stream)); 363 } 364 } 365 366 @Converter 367 public static ObjectInput toObjectInput(final InputStream stream, final Exchange exchange) throws IOException { 368 if (stream instanceof ObjectInput) { 369 return (ObjectInput) stream; 370 } else { 371 return new ObjectInputStream(IOHelper.buffered(stream)) { 372 @Override 373 protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException { 374 // need to let Camel be able to resolve class using ClassResolver SPI, to let class loading 375 // work in OSGi and other containers 376 Class<?> answer = null; 377 String name = objectStreamClass.getName(); 378 if (exchange != null) { 379 LOG.trace("Loading class {} using Camel ClassResolver", name); 380 answer = exchange.getContext().getClassResolver().resolveClass(name); 381 } 382 if (answer == null) { 383 LOG.trace("Loading class {} using JDK default implementation", name); 384 answer = super.resolveClass(objectStreamClass); 385 } 386 return answer; 387 } 388 }; 389 } 390 } 391 392 @Converter 393 public static byte[] toBytes(InputStream stream) throws IOException { 394 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 395 IOHelper.copy(IOHelper.buffered(stream), bos); 396 397 // no need to close the ByteArrayOutputStream as it's close() 398 // implementation is noop 399 return bos.toByteArray(); 400 } 401 402 @Converter 403 public static byte[] toByteArray(ByteArrayOutputStream os) { 404 return os.toByteArray(); 405 } 406 407 /** 408 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 409 */ 410 @Deprecated 411 public static String toString(ByteArrayOutputStream os) throws IOException { 412 return toString(os, null); 413 } 414 415 @Converter 416 public static String toString(ByteArrayOutputStream os, Exchange exchange) throws IOException { 417 return os.toString(IOHelper.getCharsetName(exchange)); 418 } 419 420 @Converter 421 public static InputStream toInputStream(ByteArrayOutputStream os) { 422 // no buffering required as the complete byte array input is already 423 // passed over as a whole 424 return new ByteArrayInputStream(os.toByteArray()); 425 } 426 427 @Converter 428 public static Properties toProperties(File file) throws IOException { 429 return toProperties(new FileInputStream(file)); 430 } 431 432 @Converter 433 public static Properties toProperties(InputStream is) throws IOException { 434 Properties prop = new Properties(); 435 try { 436 prop.load(is); 437 } finally { 438 IOHelper.close(is); 439 } 440 return prop; 441 } 442 443 @Converter 444 public static Properties toProperties(Reader reader) throws IOException { 445 Properties prop = new Properties(); 446 try { 447 prop.load(reader); 448 } finally { 449 IOHelper.close(reader); 450 } 451 return prop; 452 } 453 454 /** 455 * Gets the charset name if set as header or property {@link Exchange#CHARSET_NAME}. 456 * 457 * @param exchange the exchange 458 * @param useDefault should we fallback and use JVM default charset if no property existed? 459 * @return the charset, or <tt>null</tt> if no found 460 */ 461 @Deprecated 462 public static String getCharsetName(Exchange exchange, boolean useDefault) { 463 return IOHelper.getCharsetName(exchange, useDefault); 464 } 465 466 @Deprecated 467 public static String getCharsetName(Exchange exchange) { 468 return getCharsetName(exchange, true); 469 } 470 471 /** 472 * Encoding-aware input stream. 473 */ 474 public static class EncodingInputStream extends InputStream { 475 476 private final File file; 477 private final BufferedReader reader; 478 private final Charset defaultStreamCharset; 479 480 private ByteBuffer bufferBytes; 481 private CharBuffer bufferedChars = CharBuffer.allocate(4096); 482 483 public EncodingInputStream(File file, String charset) throws IOException { 484 this.file = file; 485 reader = toReader(file, charset); 486 defaultStreamCharset = Charset.defaultCharset(); 487 } 488 489 @Override 490 public int read() throws IOException { 491 if (bufferBytes == null || bufferBytes.remaining() <= 0) { 492 bufferedChars.clear(); 493 int len = reader.read(bufferedChars); 494 bufferedChars.flip(); 495 if (len == -1) { 496 return -1; 497 } 498 bufferBytes = defaultStreamCharset.encode(bufferedChars); 499 } 500 return bufferBytes.get(); 501 } 502 503 @Override 504 public void close() throws IOException { 505 reader.close(); 506 } 507 508 @Override 509 public void reset() throws IOException { 510 reader.reset(); 511 } 512 513 public InputStream toOriginalInputStream() throws FileNotFoundException { 514 return new FileInputStream(file); 515 } 516 } 517 518 /** 519 * Encoding-aware file reader. 520 */ 521 private static class EncodingFileReader extends InputStreamReader { 522 523 private final FileInputStream in; 524 525 /** 526 * @param in file to read 527 * @param charset character set to use 528 */ 529 EncodingFileReader(FileInputStream in, String charset) 530 throws FileNotFoundException, UnsupportedEncodingException { 531 super(in, charset); 532 this.in = in; 533 } 534 535 @Override 536 public void close() throws IOException { 537 try { 538 super.close(); 539 } finally { 540 in.close(); 541 } 542 } 543 } 544 545 /** 546 * Encoding-aware file writer. 547 */ 548 private static class EncodingFileWriter extends OutputStreamWriter { 549 550 private final FileOutputStream out; 551 552 /** 553 * @param out file to write 554 * @param charset character set to use 555 */ 556 EncodingFileWriter(FileOutputStream out, String charset) 557 throws FileNotFoundException, UnsupportedEncodingException { 558 super(out, charset); 559 this.out = out; 560 } 561 562 /** 563 * @param out file to write 564 * @param enc character set to use 565 */ 566 EncodingFileWriter(FileOutputStream out, CharsetEncoder enc) 567 throws FileNotFoundException, UnsupportedEncodingException { 568 super(out, enc); 569 this.out = out; 570 } 571 572 @Override 573 public void close() throws IOException { 574 try { 575 super.close(); 576 } finally { 577 out.close(); 578 } 579 } 580 } 581 582 /** 583 * This method will take off the quotes and double quotes of the charset 584 */ 585 @Deprecated 586 public static String normalizeCharset(String charset) { 587 return IOHelper.normalizeCharset(charset); 588 } 589 590 @Deprecated 591 public static void validateCharset(String charset) throws UnsupportedCharsetException { 592 IOHelper.validateCharset(charset); 593 } 594 595}