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.juneau.swaps;
018
019import static org.apache.juneau.common.utils.IOUtils.*;
020import static org.apache.juneau.common.utils.StringUtils.*;
021
022import java.io.*;
023
024import org.apache.juneau.*;
025import org.apache.juneau.swap.*;
026
027/**
028 * Transforms <code>InputStreams</code> to {@link String Strings}.
029 *
030 * <h5 class='section'>See Also:</h5><ul>
031 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SwapBasics">Swap Basics</a>
032
033 * </ul>
034 */
035public abstract class InputStreamSwap extends StringSwap<InputStream> {
036
037   /**
038    * Converts {@link InputStream InputStreams} to BASE-64 encoding.
039    */
040   public static class Base64 extends InputStreamSwap {
041      /**
042       * Converts the specified {@link InputStream} to a {@link String}.
043       */
044      @Override /* ObjectSwap */
045      public String swap(BeanSession session, InputStream is) throws Exception {
046         return base64Encode(toBytes(is));
047      }
048
049      /**
050       * Converts the specified {@link String} to an {@link InputStream}.
051       */
052      @Override /* ObjectSwap */
053      public InputStream unswap(BeanSession session, String s, ClassMeta<?> hint) throws Exception {
054         return toStream(base64Decode(s), hint);
055      }
056   }
057
058   /**
059    * Converts {@link InputStream InputStreams} to hex encoding.
060    */
061   public static class Hex extends InputStreamSwap {
062      /**
063       * Converts the specified {@link InputStream} to a {@link String}.
064       */
065      @Override /* ObjectSwap */
066      public String swap(BeanSession session, InputStream is) throws Exception {
067         return toHex(toBytes(is));
068      }
069
070      /**
071       * Converts the specified {@link String} to an {@link InputStream}.
072       */
073      @Override /* ObjectSwap */
074      public InputStream unswap(BeanSession session, String s, ClassMeta<?> hint) throws Exception {
075         return toStream(fromHex(s), hint);
076      }
077   }
078
079   /**
080    * Converts {@link InputStream InputStreams} to spaced-hex encoding.
081    */
082   public static class SpacedHex extends InputStreamSwap {
083      /**
084       * Converts the specified {@link InputStream} to a {@link String}.
085       */
086      @Override /* ObjectSwap */
087      public String swap(BeanSession session, InputStream is) throws Exception {
088         return toSpacedHex(toBytes(is));
089      }
090
091      /**
092       * Converts the specified {@link String} to an {@link InputStream}.
093       */
094      @Override /* ObjectSwap */
095      public InputStream unswap(BeanSession session, String s, ClassMeta<?> hint) throws Exception {
096         return toStream(fromSpacedHex(s), hint);
097      }
098   }
099
100   /**
101    * Convert the specified input stream to a byte array.
102    *
103    * @param is
104    *    The input stream to convert to bytes.
105    *    <br>Can be <jk>null</jk>.
106    *    <br>The stream is automatically closed.
107    * @return The byte array.
108    * @throws IOException Thrown by input stream.
109    */
110   protected byte[] toBytes(InputStream is) throws IOException {
111      return readBytes(is);
112   }
113
114
115   /**
116    * Convert the specified byte array into an input stream.
117    *
118    * @param b The byte array.
119    * @param hint Contains a hint about what subtype is being requested.
120    * @return The byte array.
121    */
122   protected InputStream toStream(byte[] b, ClassMeta<?> hint) {
123      Class<?> c = hint == null ? InputStream.class : hint.getInnerClass();
124      if (c == InputStream.class || c == ByteArrayInputStream.class)
125         return new ByteArrayInputStream(b);
126      return null;
127   }
128}