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.UnsupportedCharsetException; 046import java.util.Properties; 047import java.util.function.Supplier; 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 static Supplier<Charset> defaultCharset = Charset::defaultCharset; 065 066 private static final Logger LOG = LoggerFactory.getLogger(IOConverter.class); 067 068 /** 069 * Utility classes should not have a public constructor. 070 */ 071 private IOConverter() { 072 } 073 074 @Converter 075 public static InputStream toInputStream(URL url) throws IOException { 076 return IOHelper.buffered(url.openStream()); 077 } 078 079 @Converter 080 public static InputStream toInputStream(File file) throws IOException { 081 return IOHelper.buffered(new FileInputStream(file)); 082 } 083 084 /** 085 * Converts the given {@link File} with the given charset to {@link InputStream} with the JVM default charset 086 * 087 * @param file the file to be converted 088 * @param charset the charset the file is read with 089 * @return the input stream with the JVM default charset 090 */ 091 public static InputStream toInputStream(File file, String charset) throws IOException { 092 if (charset != null) { 093 return new EncodingInputStream(file, charset); 094 } else { 095 return toInputStream(file); 096 } 097 } 098 099 /** 100 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 101 */ 102 @Deprecated 103 public static BufferedReader toReader(File file) throws IOException { 104 return toReader(file, (String) null); 105 } 106 107 @Converter 108 public static BufferedReader toReader(File file, Exchange exchange) throws IOException { 109 return toReader(file, IOHelper.getCharsetName(exchange)); 110 } 111 112 public static BufferedReader toReader(File file, String charset) throws IOException { 113 FileInputStream in = new FileInputStream(file); 114 return IOHelper.buffered(new EncodingFileReader(in, charset)); 115 } 116 117 @Converter 118 public static File toFile(String name) { 119 return new File(name); 120 } 121 122 @Converter 123 public static OutputStream toOutputStream(File file) throws FileNotFoundException { 124 return IOHelper.buffered(new FileOutputStream(file)); 125 } 126 127 /** 128 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 129 */ 130 @Deprecated 131 public static BufferedWriter toWriter(File file) throws IOException { 132 FileOutputStream os = new FileOutputStream(file, false); 133 return toWriter(os, IOHelper.getCharsetName(null, true)); 134 } 135 136 @Converter 137 public static BufferedWriter toWriter(File file, Exchange exchange) throws IOException { 138 FileOutputStream os = new FileOutputStream(file, false); 139 return toWriter(os, IOHelper.getCharsetName(exchange)); 140 } 141 142 public static BufferedWriter toWriter(File file, boolean append, String charset) throws IOException { 143 return toWriter(new FileOutputStream(file, append), charset); 144 } 145 146 public static BufferedWriter toWriter(FileOutputStream os, String charset) throws IOException { 147 return IOHelper.buffered(new EncodingFileWriter(os, charset)); 148 } 149 150 /** 151 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 152 */ 153 @Deprecated 154 public static Reader toReader(InputStream in) throws IOException { 155 return toReader(in, null); 156 } 157 158 @Converter 159 public static Reader toReader(InputStream in, Exchange exchange) throws IOException { 160 return IOHelper.buffered(new InputStreamReader(in, IOHelper.getCharsetName(exchange))); 161 } 162 163 @Converter 164 public static Reader toReader(byte[] data, Exchange exchange) throws IOException { 165 return toReader(new ByteArrayInputStream(data), exchange); 166 } 167 168 /** 169 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 170 */ 171 @Deprecated 172 public static Writer toWriter(OutputStream out) throws IOException { 173 return toWriter(out, null); 174 } 175 176 @Converter 177 public static Writer toWriter(OutputStream out, Exchange exchange) throws IOException { 178 return IOHelper.buffered(new OutputStreamWriter(out, IOHelper.getCharsetName(exchange))); 179 } 180 181 @Converter 182 public static StringReader toReader(String text) { 183 // no buffering required as the complete string input is already passed 184 // over as a whole 185 return new StringReader(text); 186 } 187 188 /** 189 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 190 */ 191 @Deprecated 192 public static InputStream toInputStream(String text) throws IOException { 193 return toInputStream(text, null); 194 } 195 196 @Converter 197 public static InputStream toInputStream(String text, Exchange exchange) throws IOException { 198 return toInputStream(text.getBytes(IOHelper.getCharsetName(exchange))); 199 } 200 201 @Converter 202 public static InputStream toInputStream(StringBuffer buffer, Exchange exchange) throws IOException { 203 return toInputStream(buffer.toString(), exchange); 204 } 205 206 @Converter 207 public static InputStream toInputStream(StringBuilder builder, Exchange exchange) throws IOException { 208 return toInputStream(builder.toString(), exchange); 209 } 210 211 /** 212 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 213 */ 214 @Deprecated 215 public static InputStream toInputStream(BufferedReader buffer) throws IOException { 216 return toInputStream(buffer, null); 217 } 218 219 @Converter 220 public static InputStream toInputStream(BufferedReader buffer, Exchange exchange) throws IOException { 221 return toInputStream(toString(buffer), exchange); 222 } 223 224 /** 225 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 226 */ 227 @Deprecated 228 public static String toString(byte[] data) throws IOException { 229 return toString(data, null); 230 } 231 232 @Converter 233 public static String toString(byte[] data, Exchange exchange) throws IOException { 234 return new String(data, IOHelper.getCharsetName(exchange)); 235 } 236 237 /** 238 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 239 */ 240 @Deprecated 241 public static String toString(File file) throws IOException { 242 return toString(file, null); 243 } 244 245 @Converter 246 public static String toString(File file, Exchange exchange) throws IOException { 247 return toString(toReader(file, exchange)); 248 } 249 250 @Converter 251 public static byte[] toByteArray(File file) throws IOException { 252 InputStream is = toInputStream(file); 253 try { 254 return toBytes(is); 255 } finally { 256 IOHelper.close(is, "file", LOG); 257 } 258 } 259 260 /** 261 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 262 */ 263 @Deprecated 264 public static byte[] toByteArray(Reader reader) throws IOException { 265 return toByteArray(reader, null); 266 } 267 268 @Converter 269 public static byte[] toByteArray(Reader reader, Exchange exchange) throws IOException { 270 return toByteArray(IOHelper.buffered(reader), exchange); 271 } 272 273 /** 274 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 275 */ 276 @Deprecated 277 public static String toString(URL url) throws IOException { 278 return toString(url, null); 279 } 280 281 @Converter 282 public static String toString(URL url, Exchange exchange) throws IOException { 283 InputStream is = toInputStream(url); 284 try { 285 return toString(is, exchange); 286 } finally { 287 IOHelper.close(is, "url", LOG); 288 } 289 } 290 291 @Converter 292 public static String toString(Reader reader) throws IOException { 293 return toString(IOHelper.buffered(reader)); 294 } 295 296 @Converter 297 public static String toString(BufferedReader reader) throws IOException { 298 StringBuilder sb = new StringBuilder(1024); 299 char[] buf = new char[1024]; 300 try { 301 int len; 302 // read until we reach then end which is the -1 marker 303 while ((len = reader.read(buf)) != -1) { 304 sb.append(buf, 0, len); 305 } 306 } finally { 307 IOHelper.close(reader, "reader", LOG); 308 } 309 310 return sb.toString(); 311 } 312 313 /** 314 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 315 */ 316 @Deprecated 317 public static byte[] toByteArray(BufferedReader reader) throws IOException { 318 return toByteArray(reader, null); 319 } 320 321 @Converter 322 public static byte[] toByteArray(BufferedReader reader, Exchange exchange) throws IOException { 323 String s = toString(reader); 324 return toByteArray(s, exchange); 325 } 326 327 /** 328 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 329 */ 330 @Deprecated 331 public static byte[] toByteArray(String value) throws IOException { 332 return toByteArray(value, null); 333 } 334 335 @Converter 336 public static byte[] toByteArray(String value, Exchange exchange) throws IOException { 337 return value.getBytes(IOHelper.getCharsetName(exchange)); 338 } 339 340 /** 341 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 342 */ 343 @Deprecated 344 public static String toString(InputStream in) throws IOException { 345 return toString(in, null); 346 } 347 348 @Converter 349 public static String toString(InputStream in, Exchange exchange) throws IOException { 350 return toString(toReader(in, exchange)); 351 } 352 353 @Converter 354 public static InputStream toInputStream(byte[] data) { 355 // no buffering required as the complete byte input is already passed 356 // over as a whole 357 return new ByteArrayInputStream(data); 358 } 359 360 @Converter 361 public static ObjectOutput toObjectOutput(OutputStream stream) throws IOException { 362 if (stream instanceof ObjectOutput) { 363 return (ObjectOutput) stream; 364 } else { 365 return new ObjectOutputStream(IOHelper.buffered(stream)); 366 } 367 } 368 369 @Converter 370 public static ObjectInput toObjectInput(final InputStream stream, final Exchange exchange) throws IOException { 371 if (stream instanceof ObjectInput) { 372 return (ObjectInput) stream; 373 } else { 374 return new ObjectInputStream(IOHelper.buffered(stream)) { 375 @Override 376 protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException { 377 // need to let Camel be able to resolve class using ClassResolver SPI, to let class loading 378 // work in OSGi and other containers 379 Class<?> answer = null; 380 String name = objectStreamClass.getName(); 381 if (exchange != null) { 382 LOG.trace("Loading class {} using Camel ClassResolver", name); 383 answer = exchange.getContext().getClassResolver().resolveClass(name); 384 } 385 if (answer == null) { 386 LOG.trace("Loading class {} using JDK default implementation", name); 387 answer = super.resolveClass(objectStreamClass); 388 } 389 return answer; 390 } 391 }; 392 } 393 } 394 395 @Converter 396 public static byte[] toBytes(InputStream stream) throws IOException { 397 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 398 IOHelper.copy(IOHelper.buffered(stream), bos); 399 400 // no need to close the ByteArrayOutputStream as it's close() 401 // implementation is noop 402 return bos.toByteArray(); 403 } 404 405 @Converter 406 public static byte[] toByteArray(ByteArrayOutputStream os) { 407 return os.toByteArray(); 408 } 409 410 @Converter 411 public static ByteBuffer covertToByteBuffer(InputStream is) throws IOException { 412 ByteArrayOutputStream os = new ByteArrayOutputStream(); 413 IOHelper.copyAndCloseInput(is, os); 414 return ByteBuffer.wrap(os.toByteArray()); 415 } 416 417 /** 418 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 419 */ 420 @Deprecated 421 public static String toString(ByteArrayOutputStream os) throws IOException { 422 return toString(os, null); 423 } 424 425 @Converter 426 public static String toString(ByteArrayOutputStream os, Exchange exchange) throws IOException { 427 return os.toString(IOHelper.getCharsetName(exchange)); 428 } 429 430 @Converter 431 public static InputStream toInputStream(ByteArrayOutputStream os) { 432 // no buffering required as the complete byte array input is already 433 // passed over as a whole 434 return new ByteArrayInputStream(os.toByteArray()); 435 } 436 437 @Converter 438 public static Properties toProperties(File file) throws IOException { 439 return toProperties(new FileInputStream(file)); 440 } 441 442 @Converter 443 public static Properties toProperties(InputStream is) throws IOException { 444 Properties prop = new Properties(); 445 try { 446 prop.load(is); 447 } finally { 448 IOHelper.close(is); 449 } 450 return prop; 451 } 452 453 @Converter 454 public static Properties toProperties(Reader reader) throws IOException { 455 Properties prop = new Properties(); 456 try { 457 prop.load(reader); 458 } finally { 459 IOHelper.close(reader); 460 } 461 return prop; 462 } 463 464 /** 465 * Gets the charset name if set as header or property {@link Exchange#CHARSET_NAME}. 466 * 467 * @param exchange the exchange 468 * @param useDefault should we fallback and use JVM default charset if no property existed? 469 * @return the charset, or <tt>null</tt> if no found 470 */ 471 @Deprecated 472 public static String getCharsetName(Exchange exchange, boolean useDefault) { 473 return IOHelper.getCharsetName(exchange, useDefault); 474 } 475 476 @Deprecated 477 public static String getCharsetName(Exchange exchange) { 478 return getCharsetName(exchange, true); 479 } 480 481 /** 482 * Encoding-aware input stream. 483 */ 484 public static class EncodingInputStream extends InputStream { 485 486 private final File file; 487 private final BufferedReader reader; 488 private final Charset defaultStreamCharset; 489 490 private ByteBuffer bufferBytes; 491 private CharBuffer bufferedChars = CharBuffer.allocate(4096); 492 493 public EncodingInputStream(File file, String charset) throws IOException { 494 this.file = file; 495 reader = toReader(file, charset); 496 defaultStreamCharset = defaultCharset.get(); 497 } 498 499 @Override 500 public int read() throws IOException { 501 if (bufferBytes == null || bufferBytes.remaining() <= 0) { 502 bufferedChars.clear(); 503 int len = reader.read(bufferedChars); 504 bufferedChars.flip(); 505 if (len == -1) { 506 return -1; 507 } 508 bufferBytes = defaultStreamCharset.encode(bufferedChars); 509 } 510 return bufferBytes.get(); 511 } 512 513 @Override 514 public void close() throws IOException { 515 reader.close(); 516 } 517 518 @Override 519 public void reset() throws IOException { 520 reader.reset(); 521 } 522 523 public InputStream toOriginalInputStream() throws FileNotFoundException { 524 return new FileInputStream(file); 525 } 526 } 527 528 /** 529 * Encoding-aware file reader. 530 */ 531 private static class EncodingFileReader extends InputStreamReader { 532 533 private final FileInputStream in; 534 535 /** 536 * @param in file to read 537 * @param charset character set to use 538 */ 539 EncodingFileReader(FileInputStream in, String charset) 540 throws FileNotFoundException, UnsupportedEncodingException { 541 super(in, charset); 542 this.in = in; 543 } 544 545 @Override 546 public void close() throws IOException { 547 try { 548 super.close(); 549 } finally { 550 in.close(); 551 } 552 } 553 } 554 555 /** 556 * Encoding-aware file writer. 557 */ 558 private static class EncodingFileWriter extends OutputStreamWriter { 559 560 private final FileOutputStream out; 561 562 /** 563 * @param out file to write 564 * @param charset character set to use 565 */ 566 EncodingFileWriter(FileOutputStream out, String charset) 567 throws FileNotFoundException, UnsupportedEncodingException { 568 super(out, charset); 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}