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 static org.apache.juneau.commons.utils.AssertionUtils.*;
020import static org.apache.juneau.commons.utils.Utils.*;
021
022import java.lang.annotation.*;
023import java.util.*;
024
025import org.apache.juneau.*;
026import org.apache.juneau.commons.collections.*;
027import org.apache.juneau.commons.function.*;
028import org.apache.juneau.commons.reflect.*;
029
030/**
031 * Subclass of {@link Serializer} for byte-based serializers.
032 *
033 * <h5 class='section'>Notes:</h5><ul>
034 *    <li class='note'>This class is thread safe and reusable.
035 * </ul>
036 *
037 * <h5 class='section'>See Also:</h5><ul>
038 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a>
039
040 * </ul>
041 */
042public class OutputStreamSerializer extends Serializer {
043   /**
044    * Builder class.
045    */
046   public static class Builder extends Serializer.Builder {
047
048      private BinaryFormat binaryFormat;
049
050      /**
051       * Constructor, default settings.
052       */
053      protected Builder() {
054         binaryFormat = env("OutputStreamSerializer.binaryFormat", BinaryFormat.HEX);
055      }
056
057      /**
058       * Copy constructor.
059       *
060       * @param copyFrom The builder to copy from.
061       *    <br>Cannot be <jk>null</jk>.
062       */
063      protected Builder(Builder copyFrom) {
064         super(assertArgNotNull("copyFrom", copyFrom));
065         binaryFormat = copyFrom.binaryFormat;
066      }
067
068      /**
069       * Copy constructor.
070       *
071       * @param copyFrom The bean to copy from.
072       *    <br>Cannot be <jk>null</jk>.
073       */
074      protected Builder(OutputStreamSerializer copyFrom) {
075         super(assertArgNotNull("copyFrom", copyFrom));
076         binaryFormat = copyFrom.binaryFormat;
077      }
078
079      @Override /* Overridden from Builder */
080      public Builder accept(String value) {
081         super.accept(value);
082         return this;
083      }
084
085      @Override /* Overridden from Builder */
086      public Builder addBeanTypes() {
087         super.addBeanTypes();
088         return this;
089      }
090
091      @Override /* Overridden from Builder */
092      public Builder addBeanTypes(boolean value) {
093         super.addBeanTypes(value);
094         return this;
095      }
096
097      @Override /* Overridden from Builder */
098      public Builder addRootType() {
099         super.addRootType();
100         return this;
101      }
102
103      @Override /* Overridden from Builder */
104      public Builder addRootType(boolean value) {
105         super.addRootType(value);
106         return this;
107      }
108
109      @Override /* Overridden from Builder */
110      public Builder annotations(Annotation...values) {
111         super.annotations(values);
112         return this;
113      }
114
115      @Override /* Overridden from Builder */
116      public Builder apply(AnnotationWorkList work) {
117         super.apply(work);
118         return this;
119      }
120
121      @Override /* Overridden from Builder */
122      public Builder applyAnnotations(Class<?>...from) {
123         super.applyAnnotations(from);
124         return this;
125      }
126
127      @Override /* Overridden from Builder */
128      public Builder applyAnnotations(Object...from) {
129         super.applyAnnotations(from);
130         return this;
131      }
132
133      @Override /* Overridden from Builder */
134      public Builder beanClassVisibility(Visibility value) {
135         super.beanClassVisibility(value);
136         return this;
137      }
138
139      @Override /* Overridden from Builder */
140      public Builder beanConstructorVisibility(Visibility value) {
141         super.beanConstructorVisibility(value);
142         return this;
143      }
144
145      @Override /* Overridden from Builder */
146      public Builder beanContext(BeanContext value) {
147         super.beanContext(value);
148         return this;
149      }
150
151      @Override /* Overridden from Builder */
152      public Builder beanContext(BeanContext.Builder value) {
153         super.beanContext(value);
154         return this;
155      }
156
157      @Override /* Overridden from Builder */
158      public Builder beanDictionary(java.lang.Class<?>...values) {
159         super.beanDictionary(values);
160         return this;
161      }
162
163      @Override /* Overridden from Builder */
164      public Builder beanFieldVisibility(Visibility value) {
165         super.beanFieldVisibility(value);
166         return this;
167      }
168
169      @Override /* Overridden from Builder */
170      public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) {
171         super.beanInterceptor(on, value);
172         return this;
173      }
174
175      @Override /* Overridden from Builder */
176      public Builder beanMapPutReturnsOldValue() {
177         super.beanMapPutReturnsOldValue();
178         return this;
179      }
180
181      @Override /* Overridden from Builder */
182      public Builder beanMethodVisibility(Visibility value) {
183         super.beanMethodVisibility(value);
184         return this;
185      }
186
187      @Override /* Overridden from Builder */
188      public Builder beanProperties(Class<?> beanClass, String properties) {
189         super.beanProperties(beanClass, properties);
190         return this;
191      }
192
193      @Override /* Overridden from Builder */
194      public Builder beanProperties(Map<String,Object> values) {
195         super.beanProperties(values);
196         return this;
197      }
198
199      @Override /* Overridden from Builder */
200      public Builder beanProperties(String beanClassName, String properties) {
201         super.beanProperties(beanClassName, properties);
202         return this;
203      }
204
205      @Override /* Overridden from Builder */
206      public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) {
207         super.beanPropertiesExcludes(beanClass, properties);
208         return this;
209      }
210
211      @Override /* Overridden from Builder */
212      public Builder beanPropertiesExcludes(Map<String,Object> values) {
213         super.beanPropertiesExcludes(values);
214         return this;
215      }
216
217      @Override /* Overridden from Builder */
218      public Builder beanPropertiesExcludes(String beanClassName, String properties) {
219         super.beanPropertiesExcludes(beanClassName, properties);
220         return this;
221      }
222
223      @Override /* Overridden from Builder */
224      public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) {
225         super.beanPropertiesReadOnly(beanClass, properties);
226         return this;
227      }
228
229      @Override /* Overridden from Builder */
230      public Builder beanPropertiesReadOnly(Map<String,Object> values) {
231         super.beanPropertiesReadOnly(values);
232         return this;
233      }
234
235      @Override /* Overridden from Builder */
236      public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
237         super.beanPropertiesReadOnly(beanClassName, properties);
238         return this;
239      }
240
241      @Override /* Overridden from Builder */
242      public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) {
243         super.beanPropertiesWriteOnly(beanClass, properties);
244         return this;
245      }
246
247      @Override /* Overridden from Builder */
248      public Builder beanPropertiesWriteOnly(Map<String,Object> values) {
249         super.beanPropertiesWriteOnly(values);
250         return this;
251      }
252
253      @Override /* Overridden from Builder */
254      public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
255         super.beanPropertiesWriteOnly(beanClassName, properties);
256         return this;
257      }
258
259      @Override /* Overridden from Builder */
260      public Builder beansRequireDefaultConstructor() {
261         super.beansRequireDefaultConstructor();
262         return this;
263      }
264
265      @Override /* Overridden from Builder */
266      public Builder beansRequireSerializable() {
267         super.beansRequireSerializable();
268         return this;
269      }
270
271      @Override /* Overridden from Builder */
272      public Builder beansRequireSettersForGetters() {
273         super.beansRequireSettersForGetters();
274         return this;
275      }
276
277      /**
278       * Binary output format.
279       *
280       * <p>
281       * When using the {@link OutputStreamSerializer#serializeToString(Object)} method on stream-based serializers, this defines the format to use
282       * when converting the resulting byte array to a string.
283       *
284       * <h5 class='section'>Example:</h5>
285       * <p class='bjava'>
286       *    <jc>// Create a serializer that serializes to BASE64.</jc>
287       *    OutputStreamSerializer <jv>serializer</jv> = MsgPackSerializer
288       *       .<jsm>create</jsm>()
289       *       .binaryFormat(<jsf>BASE64</jsf>)
290       *       .build();
291       *
292       *    <jc>// The bean we want to serialize.</jc>
293       *    <jk>public class</jk> MyBean {...}
294       *
295       *    <jc>// MessagePack will generate BASE64-encoded string.</jc>
296       *    String <jv>msgPack</jv> = <jv>serializer</jv>.serializeToString(<jk>new</jk> MyBean());
297       * </p>
298       *
299       * @param value
300       *    The new value for this property.
301       *    <br>The default is {@link BinaryFormat#HEX}.
302       *    <br>Cannot be <jk>null</jk>.
303       * @return This object.
304       */
305      public Builder binaryFormat(BinaryFormat value) {
306         binaryFormat = assertArgNotNull("value", value);
307         return this;
308      }
309
310      @Override /* Overridden from Context.Builder */
311      public OutputStreamSerializer build() {
312         return build(OutputStreamSerializer.class);
313      }
314
315      @Override /* Overridden from Builder */
316      public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
317         super.cache(value);
318         return this;
319      }
320
321      @Override /* Overridden from Context.Builder */
322      public Builder copy() {
323         return new Builder(this);
324      }
325
326      @Override /* Overridden from Builder */
327      public Builder debug() {
328         super.debug();
329         return this;
330      }
331
332      @Override /* Overridden from Builder */
333      public Builder debug(boolean value) {
334         super.debug(value);
335         return this;
336      }
337
338      @Override /* Overridden from Builder */
339      public Builder detectRecursions() {
340         super.detectRecursions();
341         return this;
342      }
343
344      @Override /* Overridden from Builder */
345      public Builder detectRecursions(boolean value) {
346         super.detectRecursions(value);
347         return this;
348      }
349
350      @Override /* Overridden from Builder */
351      public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) {
352         super.dictionaryOn(on, values);
353         return this;
354      }
355
356      @Override /* Overridden from Builder */
357      public Builder disableBeansRequireSomeProperties() {
358         super.disableBeansRequireSomeProperties();
359         return this;
360      }
361
362      @Override /* Overridden from Builder */
363      public Builder disableIgnoreMissingSetters() {
364         super.disableIgnoreMissingSetters();
365         return this;
366      }
367
368      @Override /* Overridden from Builder */
369      public Builder disableIgnoreTransientFields() {
370         super.disableIgnoreTransientFields();
371         return this;
372      }
373
374      @Override /* Overridden from Builder */
375      public Builder disableIgnoreUnknownNullBeanProperties() {
376         super.disableIgnoreUnknownNullBeanProperties();
377         return this;
378      }
379
380      @Override /* Overridden from Builder */
381      public Builder disableInterfaceProxies() {
382         super.disableInterfaceProxies();
383         return this;
384      }
385
386      @Override /* Overridden from Builder */
387      public <T> Builder example(Class<T> pojoClass, String json) {
388         super.example(pojoClass, json);
389         return this;
390      }
391
392      @Override /* Overridden from Builder */
393      public <T> Builder example(Class<T> pojoClass, T o) {
394         super.example(pojoClass, o);
395         return this;
396      }
397
398      @Override /* Overridden from Builder */
399      public Builder findFluentSetters() {
400         super.findFluentSetters();
401         return this;
402      }
403
404      @Override /* Overridden from Builder */
405      public Builder findFluentSetters(Class<?> on) {
406         super.findFluentSetters(on);
407         return this;
408      }
409
410      @Override /* Overridden from Context.Builder */
411      public HashKey hashKey() {
412         return HashKey.of(super.hashKey(), binaryFormat);
413      }
414
415      @Override /* Overridden from Builder */
416      public Builder ignoreInvocationExceptionsOnGetters() {
417         super.ignoreInvocationExceptionsOnGetters();
418         return this;
419      }
420
421      @Override /* Overridden from Builder */
422      public Builder ignoreInvocationExceptionsOnSetters() {
423         super.ignoreInvocationExceptionsOnSetters();
424         return this;
425      }
426
427      @Override /* Overridden from Builder */
428      public Builder ignoreRecursions() {
429         super.ignoreRecursions();
430         return this;
431      }
432
433      @Override /* Overridden from Builder */
434      public Builder ignoreRecursions(boolean value) {
435         super.ignoreRecursions(value);
436         return this;
437      }
438
439      @Override /* Overridden from Builder */
440      public Builder ignoreUnknownBeanProperties() {
441         super.ignoreUnknownBeanProperties();
442         return this;
443      }
444
445      @Override /* Overridden from Builder */
446      public Builder ignoreUnknownEnumValues() {
447         super.ignoreUnknownEnumValues();
448         return this;
449      }
450
451      @Override /* Overridden from Builder */
452      public Builder impl(Context value) {
453         super.impl(value);
454         return this;
455      }
456
457      @Override /* Overridden from Builder */
458      public Builder implClass(Class<?> interfaceClass, Class<?> implClass) {
459         super.implClass(interfaceClass, implClass);
460         return this;
461      }
462
463      @Override /* Overridden from Builder */
464      public Builder implClasses(Map<Class<?>,Class<?>> values) {
465         super.implClasses(values);
466         return this;
467      }
468
469      @Override /* Overridden from Builder */
470      public Builder initialDepth(int value) {
471         super.initialDepth(value);
472         return this;
473      }
474
475      @Override /* Overridden from Builder */
476      public Builder interfaceClass(Class<?> on, Class<?> value) {
477         super.interfaceClass(on, value);
478         return this;
479      }
480
481      @Override /* Overridden from Builder */
482      public Builder interfaces(java.lang.Class<?>...value) {
483         super.interfaces(value);
484         return this;
485      }
486
487      @Override /* Overridden from Builder */
488      public Builder keepNullProperties() {
489         super.keepNullProperties();
490         return this;
491      }
492
493      @Override /* Overridden from Builder */
494      public Builder keepNullProperties(boolean value) {
495         super.keepNullProperties(value);
496         return this;
497      }
498
499      @Override /* Overridden from Builder */
500      public Builder listener(Class<? extends org.apache.juneau.serializer.SerializerListener> value) {
501         super.listener(value);
502         return this;
503      }
504
505      @Override /* Overridden from Builder */
506      public Builder locale(Locale value) {
507         super.locale(value);
508         return this;
509      }
510
511      @Override /* Overridden from Builder */
512      public Builder maxDepth(int value) {
513         super.maxDepth(value);
514         return this;
515      }
516
517      @Override /* Overridden from Builder */
518      public Builder mediaType(MediaType value) {
519         super.mediaType(value);
520         return this;
521      }
522
523      @Override /* Overridden from Builder */
524      public Builder notBeanClasses(java.lang.Class<?>...values) {
525         super.notBeanClasses(values);
526         return this;
527      }
528
529      @Override /* Overridden from Builder */
530      public Builder notBeanPackages(String...values) {
531         super.notBeanPackages(values);
532         return this;
533      }
534
535      @Override /* Overridden from Builder */
536      public Builder produces(String value) {
537         super.produces(value);
538         return this;
539      }
540
541      @Override /* Overridden from Builder */
542      public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) {
543         super.propertyNamer(on, value);
544         return this;
545      }
546
547      @Override /* Overridden from Builder */
548      public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) {
549         super.propertyNamer(value);
550         return this;
551      }
552
553      @Override /* Overridden from Builder */
554      public Builder sortCollections() {
555         super.sortCollections();
556         return this;
557      }
558
559      @Override /* Overridden from Builder */
560      public Builder sortCollections(boolean value) {
561         super.sortCollections(value);
562         return this;
563      }
564
565      @Override /* Overridden from Builder */
566      public Builder sortMaps() {
567         super.sortMaps();
568         return this;
569      }
570
571      @Override /* Overridden from Builder */
572      public Builder sortMaps(boolean value) {
573         super.sortMaps(value);
574         return this;
575      }
576
577      @Override /* Overridden from Builder */
578      public Builder sortProperties() {
579         super.sortProperties();
580         return this;
581      }
582
583      @Override /* Overridden from Builder */
584      public Builder sortProperties(java.lang.Class<?>...on) {
585         super.sortProperties(on);
586         return this;
587      }
588
589      @Override /* Overridden from Builder */
590      public Builder stopClass(Class<?> on, Class<?> value) {
591         super.stopClass(on, value);
592         return this;
593      }
594
595      @Override /* Overridden from Builder */
596      public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) {
597         super.swap(normalClass, swappedClass, swapFunction);
598         return this;
599      }
600
601      @Override /* Overridden from Builder */
602      public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) {
603         super.swap(normalClass, swappedClass, swapFunction, unswapFunction);
604         return this;
605      }
606
607      @Override /* Overridden from Builder */
608      public Builder swaps(Class<?>...values) {
609         super.swaps(values);
610         return this;
611      }
612
613      @Override /* Overridden from Builder */
614      public Builder swaps(Object...values) {
615         super.swaps(values);
616         return this;
617      }
618
619      @Override /* Overridden from Builder */
620      public Builder timeZone(TimeZone value) {
621         super.timeZone(value);
622         return this;
623      }
624
625      @Override /* Overridden from Builder */
626      public Builder trimEmptyCollections() {
627         super.trimEmptyCollections();
628         return this;
629      }
630
631      @Override /* Overridden from Builder */
632      public Builder trimEmptyCollections(boolean value) {
633         super.trimEmptyCollections(value);
634         return this;
635      }
636
637      @Override /* Overridden from Builder */
638      public Builder trimEmptyMaps() {
639         super.trimEmptyMaps();
640         return this;
641      }
642
643      @Override /* Overridden from Builder */
644      public Builder trimEmptyMaps(boolean value) {
645         super.trimEmptyMaps(value);
646         return this;
647      }
648
649      @Override /* Overridden from Builder */
650      public Builder trimStrings() {
651         super.trimStrings();
652         return this;
653      }
654
655      @Override /* Overridden from Builder */
656      public Builder trimStrings(boolean value) {
657         super.trimStrings(value);
658         return this;
659      }
660
661      @Override /* Overridden from Builder */
662      public Builder type(Class<? extends org.apache.juneau.Context> value) {
663         super.type(value);
664         return this;
665      }
666
667      @Override /* Overridden from Builder */
668      public Builder typeName(Class<?> on, String value) {
669         super.typeName(on, value);
670         return this;
671      }
672
673      @Override /* Overridden from Builder */
674      public Builder typePropertyName(Class<?> on, String value) {
675         super.typePropertyName(on, value);
676         return this;
677      }
678
679      @Override /* Overridden from Builder */
680      public Builder typePropertyName(String value) {
681         super.typePropertyName(value);
682         return this;
683      }
684
685      @Override /* Overridden from Builder */
686      public Builder uriContext(UriContext value) {
687         super.uriContext(value);
688         return this;
689      }
690
691      @Override /* Overridden from Builder */
692      public Builder uriRelativity(UriRelativity value) {
693         super.uriRelativity(value);
694         return this;
695      }
696
697      @Override /* Overridden from Builder */
698      public Builder uriResolution(UriResolution value) {
699         super.uriResolution(value);
700         return this;
701      }
702
703      @Override /* Overridden from Builder */
704      public Builder useEnumNames() {
705         super.useEnumNames();
706         return this;
707      }
708
709      @Override /* Overridden from Builder */
710      public Builder useJavaBeanIntrospector() {
711         super.useJavaBeanIntrospector();
712         return this;
713      }
714   }
715
716   /**
717    * Creates a new builder for this object.
718    *
719    * @return A new builder.
720    */
721   public static Builder create() {
722      return new Builder();
723   }
724
725   final BinaryFormat binaryFormat;
726
727   /**
728    * Constructor.
729    *
730    * @param builder
731    *    The builder for this object.
732    */
733   protected OutputStreamSerializer(Builder builder) {
734      super(builder);
735
736      binaryFormat = builder.binaryFormat;
737   }
738
739   @Override /* Overridden from Context */
740   public OutputStreamSerializerSession.Builder createSession() {
741      return OutputStreamSerializerSession.create(this);
742   }
743
744   @Override /* Overridden from Context */
745   public OutputStreamSerializerSession getSession() { return createSession().build(); }
746
747   @Override /* Overridden from Serializer */
748   public final boolean isWriterSerializer() { return false; }
749
750   /**
751    * Convenience method for serializing an object to a <code><jk>byte</jk></code>.
752    *
753    * @param o The object to serialize.
754    * @return The output serialized to a byte array.
755    * @throws SerializeException If a problem occurred trying to convert the output.
756    */
757   @Override
758   public final byte[] serialize(Object o) throws SerializeException {
759      return getSession().serialize(o);
760   }
761
762   /**
763    * Binary output format.
764    *
765    * @see Builder#binaryFormat(BinaryFormat)
766    * @return
767    *    The format to use for the {@link #serializeToString(Object)} method on stream-based serializers when converting byte arrays to strings.
768    */
769   protected final BinaryFormat getBinaryFormat() { return binaryFormat; }
770
771   @Override /* Overridden from Serializer */
772   protected FluentMap<String,Object> properties() {
773      return super.properties()
774         .a("binaryFormat", binaryFormat);
775   }
776}