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 (the
006 * "License"); you may not use this file except in compliance with the
007 * 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.http.header;
018
019import static org.apache.juneau.commons.utils.StringUtils.*;
020
021import java.util.function.*;
022
023import org.apache.juneau.http.*;
024
025/**
026 * Represents an HTTP <c>Thrown</c> header.
027 *
028 * <p>
029 * Serialized exception information.
030 *
031 * @since 9.2.1
032 */
033@SuppressWarnings({
034   "java:S9149" // Public Juneau DSL factory; hiding parent of()/create() is intentional.
035})
036public class Thrown extends HttpCsvHeader {
037
038   public static final String NAME = "Thrown";
039
040   public Thrown(String value) {
041      super(NAME, value);
042   }
043
044   public Thrown(String... values) {
045      super(NAME, values);
046   }
047
048   private Thrown(Supplier<?> supplier, int lazyMode) {
049      super(NAME, supplier, lazyMode);
050   }
051
052   public static Thrown of(String value) {
053      return new Thrown(value);
054   }
055
056   public static Thrown of(String... values) {
057      return new Thrown(values);
058   }
059
060   // Distinct 2-arg factory so two literal String args bind here (returning Thrown) instead of the inherited
061   // fixed-arity HttpCsvHeader.of(String name, String value), which Java overload resolution would otherwise prefer.
062   public static Thrown of(String value1, String value2) {
063      return new Thrown(value1, value2);
064   }
065
066   /**
067    * Creates a {@code Thrown} header value from one or more {@link Throwable} instances.
068    *
069    * <p>
070    * Each throwable is encoded as {@code <urlEncode(className)>;<urlEncode(message)>} and the entries
071    * are joined with {@code ", "}.
072    *
073    * @param values The throwables to encode. {@code null} entries are ignored.
074    * @return A new header. Never {@code null}.
075    */
076   public static Thrown of(Throwable... values) {
077      var sb = new StringBuilder();
078      if (values != null) {
079         var first = true;
080         for (var v : values) {
081            if (v == null)
082               continue;
083            if (!first)
084               sb.append(", ");
085            first = false;
086            sb.append(urlEncode(UnmodifiableBean.logicalType(v).getName())).append(';');
087            if (v.getMessage() != null)
088               sb.append(urlEncode(v.getMessage()));
089         }
090      }
091      return new Thrown(sb.toString());
092   }
093
094   public static Thrown ofLazyWire(Supplier<String> supplier) {
095      return new Thrown(supplier, LAZY_WIRE_STRING);
096   }
097
098   public static Thrown ofLazyTokens(Supplier<String[]> supplier) {
099      return new Thrown(supplier, LAZY_TOKENS);
100   }
101}