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