001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.soap;
014
015import java.util.*;
016import java.util.concurrent.*;
017
018import org.apache.juneau.*;
019import org.apache.juneau.annotation.*;
020import org.apache.juneau.collections.*;
021import org.apache.juneau.serializer.*;
022import org.apache.juneau.xml.*;
023
024/**
025 * Serializes POJOs to HTTP responses as XML+SOAP.
026 *
027 * <h5 class='topic'>Media types</h5>
028 *
029 * Handles <c>Accept</c> types:  <bc>text/xml+soap</bc>
030 * <p>
031 * Produces <c>Content-Type</c> types:  <bc>text/xml+soap</bc>
032 *
033 * <h5 class='topic'>Description</h5>
034 *
035 * Essentially the same output as {@link XmlDocSerializer}, except wrapped in a standard SOAP envelope.
036 */
037@ConfigurableContext
038public final class SoapXmlSerializer extends XmlSerializer implements SoapXmlMetaProvider,SoapXmlCommon {
039
040   //-------------------------------------------------------------------------------------------------------------------
041   // Configurable properties
042   //-------------------------------------------------------------------------------------------------------------------
043
044   static final String PREFIX = "SoapXmlSerializer";
045
046   /**
047    * Configuration property:  The <c>SOAPAction</c> HTTP header value to set on responses.
048    *
049    * <h5 class='section'>Property:</h5>
050    * <ul class='spaced-list'>
051    *    <li><b>ID:</b>  {@link org.apache.juneau.soap.SoapXmlSerializer#SOAPXML_SOAPAction SOAPXML_SOAPAction}
052    *    <li><b>Name:</b>  <js>"SoapXmlSerializer.SOAPAction.s"</js>
053    *    <li><b>Data type:</b>  <c>String</c>
054    *    <li><b>System property:</b>  <c>SoapXmlSerializer.SOAPAction</c>
055    *    <li><b>Environment variable:</b>  <c>SOAPXMLSERIALIZER_SOAPACTION</c>
056    *    <li><b>Default:</b>  <js>"http://www.w3.org/2003/05/soap-envelope"</js>
057    *    <li><b>Annotations:</b>
058    *       <ul>
059    *          <li class='ja'>{@link org.apache.juneau.soap.annotation.SoapXmlConfig#soapAction()}
060    *       </ul>
061    *    <li><b>Methods:</b>
062    *       <ul>
063    *          <li class='jm'>{@link org.apache.juneau.soap.SoapXmlSerializerBuilder#soapAction(String)}
064    *       </ul>
065    * </ul>
066    */
067   public static final String SOAPXML_SOAPAction = PREFIX + ".SOAPAction.s";
068
069
070   //-------------------------------------------------------------------------------------------------------------------
071   // Instance
072   //-------------------------------------------------------------------------------------------------------------------
073
074   final String soapAction;
075   private final Map<ClassMeta<?>,SoapXmlClassMeta> soapXmlClassMetas = new ConcurrentHashMap<>();
076   private final Map<BeanPropertyMeta,SoapXmlBeanPropertyMeta> soapXmlBeanPropertyMetas = new ConcurrentHashMap<>();
077
078   /**
079    * Constructor.
080    *
081    * @param ps The property store containing all the settings for this object.
082    */
083   public SoapXmlSerializer(PropertyStore ps) {
084      super(ps, "text/xml", "text/xml+soap");
085      soapAction = getStringProperty(SOAPXML_SOAPAction, "http://www.w3.org/2003/05/soap-envelope");
086   }
087
088   @Override /* Context */
089   public SoapXmlSerializerBuilder builder() {
090      return new SoapXmlSerializerBuilder(getPropertyStore());
091   }
092
093   /**
094    * Instantiates a new clean-slate {@link SoapXmlSerializerBuilder} object.
095    *
096    * <p>
097    * This is equivalent to simply calling <code><jk>new</jk> SoapXmlSerializerBuilder()</code>.
098    *
099    * <p>
100    * Note that this method creates a builder initialized to all default settings, whereas {@link #builder()} copies
101    * the settings of the object called on.
102    *
103    * @return A new {@link SoapXmlSerializerBuilder} object.
104    */
105   public static SoapXmlSerializerBuilder create() {
106      return new SoapXmlSerializerBuilder();
107   }
108
109   @Override /* Serializer */
110   public SoapXmlSerializerSession createSession() {
111      return createSession(createDefaultSessionArgs());
112   }
113
114   @Override /* Serializer */
115   public SoapXmlSerializerSession createSession(SerializerSessionArgs args) {
116      return new SoapXmlSerializerSession(this, args);
117   }
118
119   //-----------------------------------------------------------------------------------------------------------------
120   // Extended metadata
121   //-----------------------------------------------------------------------------------------------------------------
122
123   @Override /* SoapXmlMetaProvider */
124   public SoapXmlClassMeta getSoapXmlClassMeta(ClassMeta<?> cm) {
125      SoapXmlClassMeta m = soapXmlClassMetas.get(cm);
126      if (m == null) {
127         m = new SoapXmlClassMeta(cm, this);
128         soapXmlClassMetas.put(cm, m);
129      }
130      return m;
131   }
132
133   @Override /* SoapXmlMetaProvider */
134   public SoapXmlBeanPropertyMeta getSoapXmlBeanPropertyMeta(BeanPropertyMeta bpm) {
135      if (bpm == null)
136         return SoapXmlBeanPropertyMeta.DEFAULT;
137      SoapXmlBeanPropertyMeta m = soapXmlBeanPropertyMetas.get(bpm);
138      if (m == null) {
139         m = new SoapXmlBeanPropertyMeta(bpm.getDelegateFor(), this);
140         soapXmlBeanPropertyMetas.put(bpm, m);
141      }
142      return m;
143   }
144
145   //-----------------------------------------------------------------------------------------------------------------
146   // Properties
147   //-----------------------------------------------------------------------------------------------------------------
148
149   /**
150    * The SOAPAction HTTP header value to set on responses.
151    *
152    * @see #SOAPXML_SOAPAction
153    * @return
154    *    The SOAPAction HTTP header value to set on responses.
155    */
156   public String getSoapAction() {
157      return soapAction;
158   }
159
160   //-----------------------------------------------------------------------------------------------------------------
161   // Other methods
162   //-----------------------------------------------------------------------------------------------------------------
163
164   @Override /* Context */
165   public OMap toMap() {
166      return super.toMap()
167         .a("SoapXmlSerializer", new DefaultFilteringOMap()
168            .a("soapAction", soapAction)
169         );
170   }
171}