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.serializer;
018
019import java.io.*;
020import java.lang.reflect.*;
021import java.util.*;
022import java.util.function.*;
023
024import org.apache.juneau.*;
025import org.apache.juneau.common.utils.*;
026import org.apache.juneau.httppart.*;
027import org.apache.juneau.internal.*;
028import org.apache.juneau.svl.*;
029
030/**
031 * Subclass of {@link SerializerSession} for stream-based serializers.
032 *
033 * <h5 class='topic'>Description</h5>
034 *
035 * This class is the parent class of all byte-based serializers.
036 * <br>It has 1 abstract method to implement...
037 * <ul>
038 *    <li>{@link #doSerialize(SerializerPipe, Object)}
039 * </ul>
040 *
041 * <h5 class='section'>Notes:</h5><ul>
042 *    <li class='warn'>This class is not thread safe and is typically discarded after one use.
043 * </ul>
044 *
045 * <h5 class='section'>See Also:</h5><ul>
046 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a>
047 * </ul>
048 */
049public class OutputStreamSerializerSession extends SerializerSession {
050
051   //-----------------------------------------------------------------------------------------------------------------
052   // Static
053   //-----------------------------------------------------------------------------------------------------------------
054
055   /**
056    * Creates a new builder for this object.
057    *
058    * @param ctx The context creating this session.
059    * @return A new builder.
060    */
061   public static Builder create(OutputStreamSerializer ctx) {
062      return new Builder(ctx);
063   }
064
065   //-----------------------------------------------------------------------------------------------------------------
066   // Builder
067   //-----------------------------------------------------------------------------------------------------------------
068
069   /**
070    * Builder class.
071    */
072   public static class Builder extends SerializerSession.Builder {
073
074      OutputStreamSerializer ctx;
075
076      /**
077       * Constructor
078       *
079       * @param ctx The context creating this session.
080       */
081      protected Builder(OutputStreamSerializer ctx) {
082         super(ctx);
083         this.ctx = ctx;
084      }
085
086      @Override
087      public OutputStreamSerializerSession build() {
088         return new OutputStreamSerializerSession(this);
089      }
090      @Override /* Overridden from Builder */
091      public <T> Builder apply(Class<T> type, Consumer<T> apply) {
092         super.apply(type, apply);
093         return this;
094      }
095
096      @Override /* Overridden from Builder */
097      public Builder debug(Boolean value) {
098         super.debug(value);
099         return this;
100      }
101
102      @Override /* Overridden from Builder */
103      public Builder properties(Map<String,Object> value) {
104         super.properties(value);
105         return this;
106      }
107
108      @Override /* Overridden from Builder */
109      public Builder property(String key, Object value) {
110         super.property(key, value);
111         return this;
112      }
113
114      @Override /* Overridden from Builder */
115      public Builder unmodifiable() {
116         super.unmodifiable();
117         return this;
118      }
119
120      @Override /* Overridden from Builder */
121      public Builder locale(Locale value) {
122         super.locale(value);
123         return this;
124      }
125
126      @Override /* Overridden from Builder */
127      public Builder localeDefault(Locale value) {
128         super.localeDefault(value);
129         return this;
130      }
131
132      @Override /* Overridden from Builder */
133      public Builder mediaType(MediaType value) {
134         super.mediaType(value);
135         return this;
136      }
137
138      @Override /* Overridden from Builder */
139      public Builder mediaTypeDefault(MediaType value) {
140         super.mediaTypeDefault(value);
141         return this;
142      }
143
144      @Override /* Overridden from Builder */
145      public Builder timeZone(TimeZone value) {
146         super.timeZone(value);
147         return this;
148      }
149
150      @Override /* Overridden from Builder */
151      public Builder timeZoneDefault(TimeZone value) {
152         super.timeZoneDefault(value);
153         return this;
154      }
155
156      @Override /* Overridden from Builder */
157      public Builder javaMethod(Method value) {
158         super.javaMethod(value);
159         return this;
160      }
161
162      @Override /* Overridden from Builder */
163      public Builder resolver(VarResolverSession value) {
164         super.resolver(value);
165         return this;
166      }
167
168      @Override /* Overridden from Builder */
169      public Builder schema(HttpPartSchema value) {
170         super.schema(value);
171         return this;
172      }
173
174      @Override /* Overridden from Builder */
175      public Builder schemaDefault(HttpPartSchema value) {
176         super.schemaDefault(value);
177         return this;
178      }
179
180      @Override /* Overridden from Builder */
181      public Builder uriContext(UriContext value) {
182         super.uriContext(value);
183         return this;
184      }
185   }
186
187   //-----------------------------------------------------------------------------------------------------------------
188   // Instance
189   //-----------------------------------------------------------------------------------------------------------------
190
191   private final OutputStreamSerializer ctx;
192
193   /**
194    * Constructor.
195    *
196    * @param builder The builder for this object.
197    */
198   protected OutputStreamSerializerSession(Builder builder) {
199      super(builder);
200      ctx = builder.ctx;
201   }
202
203   @Override /* SerializerSession */
204   public final boolean isWriterSerializer() {
205      return false;
206   }
207
208   @Override /* SerializerSession */
209   protected SerializerPipe createPipe(Object output) {
210      return new SerializerPipe(output);
211   }
212
213   /**
214    * Convenience method for serializing an object to a <code><jk>byte</jk></code>.
215    *
216    * @param o The object to serialize.
217    * @return The output serialized to a byte array.
218    * @throws SerializeException If a problem occurred trying to convert the output.
219    */
220   @Override /* SerializerSession */
221   public final byte[] serialize(Object o) throws SerializeException {
222      ByteArrayOutputStream baos = new ByteArrayOutputStream();
223      try {
224         serialize(o, baos);
225         baos.flush();
226      } catch (IOException e) {
227         throw new SerializeException(e); // Should never happen.
228      }
229      return baos.toByteArray();
230   }
231
232   @Override /* SerializerSession */
233   public final String serializeToString(Object o) throws SerializeException {
234      byte[] b = serialize(o);
235      switch(getBinaryFormat()) {
236         case SPACED_HEX:  return StringUtils.toSpacedHex(b);
237         case HEX:  return StringUtils.toHex(b);
238         case BASE64:  return StringUtils.base64Encode(b);
239         default: return null;
240      }
241   }
242
243   //-----------------------------------------------------------------------------------------------------------------
244   // Properties
245   //-----------------------------------------------------------------------------------------------------------------
246
247   /**
248    * Binary output format.
249    *
250    * @see OutputStreamSerializer.Builder#binaryFormat(BinaryFormat)
251    * @return
252    *    The format to use for the {@link #serializeToString(Object)} method on stream-based serializers when converting byte arrays to strings.
253    */
254   protected final BinaryFormat getBinaryFormat() {
255      return ctx.getBinaryFormat();
256   }
257}