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