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.marshall.swaps; 018 019import org.apache.juneau.marshall.*; 020import org.apache.juneau.marshall.csv.*; 021import org.apache.juneau.marshall.oapi.*; 022import org.apache.juneau.marshall.parser.*; 023import org.apache.juneau.marshall.serializer.*; 024import org.apache.juneau.marshall.swap.spi.*; 025 026/** 027 * Thin delegating swap for top-level {@code byte[]} values in textual serializers. 028 * 029 * <p> 030 * Used as a fall-back swap by {@link DefaultSwaps} for root-level / map-value / 031 * collection-element {@code byte[]} payloads that are not bean properties. Delegates to whichever 032 * {@link BinaryFormat} is configured on the 033 * {@link MarshallingContext}. 034 * 035 * <p>Disabled for: 036 * <ul> 037 * <li>Binary serializers / parsers with a native byte-array wire type — 038 * gated by {@link OutputStreamSerializerSession#hasNativeBytes()} / 039 * {@link InputStreamParserSession#hasNativeBytes()}. Sessions that return {@code true} 040 * (MsgPack / CBOR / BSON) emit / consume native byte sequences and skip this swap. Sessions 041 * that return {@code false} (Parquet, binary RDF) have no native byte-array primitive and 042 * still run this swap to produce / consume the configured text wire form. 043 * <li>CSV serializers / parsers ({@link CsvSerializerSession} / {@link CsvParserSession}) — CSV exposes its 044 * own per-cell {@code byteArrayFormat} setting via {@link CsvByteArrayCellFormat}. 045 * <li>{@code null}-session lookups (i.e. {@link ClassMeta}-level conversion plumbing) — keeps the 046 * String-to-{@code byte[]} fallback in {@code BasicConverter} / {@code MarshallingContext.findConversion} 047 * on the simple {@link String#getBytes(java.nio.charset.Charset)} path for non-binary inputs. 048 * </ul> 049 * 050 * <h5 class='section'>See Also:</h5><ul> 051 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Swaps">Swap</a> 052 * </ul> 053 */ 054public class BinarySwap extends StringSwap<byte[]> { 055 056 @Override /* Overridden from ObjectSwap */ 057 public int match(MarshallingSession session) { 058 // Null sessions arrive from ClassMeta-level conversion lookup paths. Returning 0 keeps the 059 // default String-to-byte[] conversion (UTF-8 getBytes) intact for callers that aren't actually 060 // trying to encode/decode a wire-format binary payload. 061 if (session == null) 062 return 0; 063 // Binary serializers / parsers with a native byte-array wire type handle byte[] natively — skip 064 // this swap so the underlying BSON / CBOR / MsgPack writer emits the raw byte sequence and the 065 // corresponding parser consumes it. Binary serializers without a native byte-array wire type 066 // (Parquet, binary RDF) report hasNativeBytes()==false and still run this swap to produce / 067 // consume the configured text wire form (HEX / BASE64 / etc.). 068 if (session instanceof OutputStreamSerializerSession session2 && session2.hasNativeBytes()) 069 return 0; 070 if (session instanceof InputStreamParserSession session2 && session2.hasNativeBytes()) 071 return 0; 072 // CSV defers byte[] cell formatting to its own CsvByteArrayCellFormat-driven cell serializer/parser. 073 if (session instanceof CsvSerializerSession || session instanceof CsvParserSession) 074 return 0; 075 // OpenAPI part serializers/parsers drive byte[] cell encoding from the {@code format} schema attribute 076 // (BYTE / BINARY / BINARY_SPACED). Skipping this swap leaves the raw byte[] in place so the 077 // OpenAPI session can apply the schema-directed encoding directly. 078 if (session instanceof OpenApiSerializerSession || session instanceof OpenApiParserSession) 079 return 0; 080 // NOT_SET means "no wire format configured" — leave byte[] in its native language form so the 081 // surrounding serializer falls back to its built-in array representation (e.g. JSON array). 082 if (session.getMarshallingContext().getBinaryFormat() == BinaryFormat.NOT_SET) 083 return 0; 084 return super.match(session); 085 } 086 087 @Override /* Overridden from ObjectSwap */ 088 public String swap(MarshallingSession session, byte[] o) { 089 return session.getMarshallingContext().getBinaryFormat().format(o); 090 } 091 092 @Override /* Overridden from ObjectSwap */ 093 public byte[] unswap(MarshallingSession session, String o, ClassMeta<?> hint) { 094 return session.getMarshallingContext().getBinaryFormat().parse(o); 095 } 096}