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