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