Package com.jaxws.json.codec

Source Code of com.jaxws.json.codec.JSONCodec

package com.jaxws.json.codec;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.zip.GZIPOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.handler.MessageContext;

import com.jaxws.json.codec.decode.FormDecoder;
import com.jaxws.json.codec.decode.JSONDecoder;
import com.jaxws.json.codec.doc.JSONHttpMetadataPublisher;
import com.jaxws.json.codec.encode.JSONEncoder;
import com.jaxws.json.feature.JSONWebService;
import com.jaxws.json.packet.handler.Encoder;
import com.jaxws.json.serializer.JSONObjectCustomizer;
import com.sun.istack.NotNull;
import com.sun.istack.Nullable;
import com.sun.xml.ws.api.SOAPVersion;
import com.sun.xml.ws.api.WSBinding;
import com.sun.xml.ws.api.message.Message;
import com.sun.xml.ws.api.message.Messages;
import com.sun.xml.ws.api.message.Packet;
import com.sun.xml.ws.api.model.SEIModel;
import com.sun.xml.ws.api.pipe.Codec;
import com.sun.xml.ws.api.pipe.ContentType;
import com.sun.xml.ws.api.server.BoundEndpoint;
import com.sun.xml.ws.api.server.EndpointAwareCodec;
import com.sun.xml.ws.api.server.EndpointComponent;
import com.sun.xml.ws.api.server.Module;
import com.sun.xml.ws.api.server.WSEndpoint;
import com.sun.xml.ws.client.sei.SEIStub;
import com.sun.xml.ws.model.JavaMethodImpl;
import com.sun.xml.ws.protocol.soap.MessageCreationException;
import com.sun.xml.ws.server.UnsupportedMediaException;
import com.sun.xml.ws.transport.Headers;
import com.sun.xml.ws.transport.http.HttpMetadataPublisher;
import com.sun.xml.ws.transport.http.WSHTTPConnection;
import com.sun.xml.ws.util.ServiceFinder;

/**
* @model abstract="false" interface="false"
* @author Sundaramurthi
* @version 1.0
* @mail sundaramurthis@gmail.com
*/
public class JSONCodec implements EndpointAwareCodec, EndpointComponent {
  private static final Logger LOG      = Logger.getLogger(JSONCodec.class.getName());
 
  /**
   * Static content type of json. used in request/response verification.
   */
  public static final ContentType   jsonContentType     = new JSONContentType();
 
  /**
   * Flag to enable/disable json request call status.
   */
  public static     String     STATUS_PROPERTY_NAME     = "statusFlag";
  public static final String    STATUS_PROPERTY_NAME_KEY  = "json.response.statusFlag";
 

  /**
   * TRACE back JSON object name
   */
  public static final String     TRACE           = "TRACE";

  /**
   * http header name for trace log
   */
  public static final String     XDEBUG_HEADER      = "X-Debug";
 
  /**
   * Http header for custom json parameter name
   */
  public static final String    XJSONPARAM_HEADER    = "X-JSONParam";
 
  /**
   *
   */
  public static final String     CONTENT_DISPOSITION_HEADER = "Content-Disposition";

  public static final String     JSON_MAP_KEY       = "JSON_MAP_KEY";
 
  public static final String    FORCED_RESPONSE_CONTENT_TYPE  = "FORCED_RESPONSE_CONTENT_TYPE";
 
  /**
   * Default json parameter name if XJSONPARAM_HEADER not present in http request
   */
  public static final String    XJSONPARAM_DEFAULT    = "JSON";
 
  /**
   * Attachment key
   */
  public static final String    MIME_ATTACHMENTS    = "ATTACHMENTS";
 
  /**
   * Java default ISO date format, timezone specified with out separator (E.g 2010-11-24T17:23:10+0100) last time zone part specified with out ':' separtor.
   * To add separator between hour and minute part of timezone  useTimezoneSeparator set to true.
   * If useTimezoneSeparator =true  data with ISO format written in json as 2010-11-24T17:23:10+01:00
   *
   * FYI: both with separator (+01:00) or with out separator (+0100) are valid according to ISO date format.
   *
   * <blockquote>
   * Property name <i>(jsonservice.properties)</i>: <b>json.date.iso.useTimezoneSeparator</b>
   * </blockquote>
   *
   * Default: false
   */
  public static final String      useTimezoneSeparator_KEY= "json.date.iso.useTimezoneSeparator";
  public static     boolean     useTimezoneSeparator   = false;
 
  /**
   * Date format used in JSON input and output. All java.util.Date, Calender and Timestamp use specified format.
   * For available format look at com.jaxws.json.DateFormat
   *
   * <blockquote>
   * Property name <i>(jsonservice.properties)</i>: <b>com.jaxws.json.DateFormat</b>
   * </blockquote>
   *
   * Default: DateFormat.PLAIN
   */
  public static final  String      dateFormat_KEY       = com.jaxws.json.codec.DateFormat.class.getName();
  public static DateFormat      dateFormat         = DateFormat.PLAIN;
 
  /**
   * Request Payload name (Operation Name) enabled in JSON request. E.g. Operation called "getVersion",  this request object warped with object named "getVersion".
   *
   * When set to json.request.enable.payloadname=true:
   *
   * Request:
   * <code> {"getVersion":{"requestContext":{"token":""}}}</code>
   *
   * When set to json.request.enable.payloadname=false
   *
   * Request:
   * <code> {"requestContext":{"token":""}}</code>
   * <b> When request payload set to false. End point should be appended with operation name.</b>
   *
   * E.g: Endpoint when payload enabled.
   * .../1_0/settings.json
   *
   * E.g: Endpoint when payload disabled.
   * .../1_0/settings.json?getVersion&...
   *
   * <blockquote>
   * Property name <i>(jsonservice.properties)</i>: <b>json.request.enable.payloadname</b>
   * </blockquote>
   *
   * Default: true
   */
  //private static boolean        requestPayloadInJSON = true; 
 
 
  /**
   * Response Payload name (Operation response Name) enabled in JSON response. E.g. Operation called "getVersion" which returns response object "versionInfo".
   * This response object warped with operation object.
   *
   * When set to json.response.enable.payloadname=true:
   *
   * Request:
   * <code> {"getVersion":{"requestContext":{"token":""}}}</code>
   *
   * Response: 
   * <code>{"getVersionXXX":{"versionInfo":{"version":"1.0","buildDate":"1290612232525","releaseDate":"1290612232525"}}}</code>
   *
   * "getVersionXXX" is a response element name defined in wsdl.
   *
   * When set to json.response.enable.payloadname=false
   *
   * Response:  <code>{"versionInfo":{"version":"1.0","buildDate":"1290612232525","releaseDate":"1290612232525"}}</code>
   * <blockquote>
   * Property name <i>(jsonservice.properties)</i>: <b>json.response.enable.payloadname</b>
   * </blockquote>
   *
   * Default: false
   *
   * This property normally true for better automated testing. In application suggested to be false.
   */
  public static final String      responsePayloadEnabled_KEY  = "json.response.enable.payloadname"
  public static boolean        responsePayloadEnabled    = false
   
    /**
     * Null values are ignored in JSON response when set to true.
     *
     * E.g: when set to false:   <code>{"versionInfo":{"version":"null","buildDate":"34234234"}}</code>
    
     * E.g: when set to true:   <code>{"versionInfo":{"buildDate":"34234234"}}</code>
     * since value of version is null it is ignored in json output.
     *
     * <blockquote>
   * Property name <i>(jsonservice.properties)</i>: <b>json.excludeNullProperties</b>
   * </blockquote>
   *
   * Default: true
   *
   * @see createDefaultOnNonNullable. In case of null value with createDefaultOnNonNullable is true new object created.
   * In case of primitive with no default value end with null, these null value response determined by excludeNullProperties
     */
  public static final String      excludeNullProperties_KEY  = "json.excludeNullProperties";
    public static boolean        excludeNullProperties    = true;
   
    /**
     * Null or non present values in JOSN request are non nullable in server, in this case create empty object.
     * E.e <code>{"getUser":{}}</code> version part of getUser call user object/id marked as nullable false in XSD.
     * But in JSON sending null or non present. This case up on enable this flag, In case of object new instance created and assigned,
     * IN case of primitive with xsd default, default value populated.
     *
     * Applicable only for beans. In case of primitive with default value is xsd always populated.
     */
    public static final String      createDefaultOnNonNullable_KEY  = "json.createDefaultOnNonNullable";
    public static boolean         createDefaultOnNonNullable  = true;
    /**
     * JSON response written as gzip encoded format. It's dependent on Accept-content: type header in http request.
     * When set to true response return as gzip if client send Accept-Encoding with gzip true.
     *
     * <blockquote>
   * Property name <i>(jsonservice.properties)</i>: <b>json.response.gzip</b>
   * </blockquote>
   *
   * Default: true
     */
    public static final String      gzip_KEY          = "json.response.gzip";
    public static boolean        gzip            = true
   
   
    /**
     * List of excluded properties, User can add one or more with regex format.
     *
     * E.e json.exclude.serialVersionUID=serialVersionUID
     * 
     * <blockquote>
   * Property name <i>(jsonservice.properties)</i>: <b>json.exclude.xxx</b>
   * </blockquote>
   *
   * Default: empty. All are included
     */
    public static final String      excludeProperties_KEY    = "json.exclude";
    public static final Collection<Pattern> excludeProperties     = new ArrayList<Pattern>();
   
    /**
     * List of included properties, User can add one with regex format. By specifying include property, properties which are not matching to include are ignored in json output.
     * 
     * <blockquote>
   * Property name <i>(jsonservice.properties)</i>: <b>json.include</b>
   * </blockquote>
   *
   * Default: empty.
     */
    public static final String        includeProperties_KEY    = "json.include";
    public static     Collection<Pattern>  includeProperties      = null;//new ArrayList<Pattern>();
   
    /**
     * In JAXB generated object list sequence generated with warped object. Seralizing it to json end with unnessary objects.
     * To avoid it user can set listWrapperSkip=true.
     *
     * Eg:
     *  In XSF
     *  <code>
     *   <xsd:element name="items">
              <xsd:complexType>
                <xsd:sequence>
                  <xsd:element name="item" type="xxxx" maxOccurs="unbounded" minOccurs="1"/>
                </xsd:sequence>
              </xsd:complexType>
            </xsd:element>
     </code>
     *
     * Above XSD lead to java object as
     *
     * Items{
     *     List<Item> getItems(){
     *       return <List>
     *     }
     * }
     * 
     *
     * Result JSON representation of items looks like when listWrapperSkip set to false.
     *
     * {"items":
     *     {"item":[...]}
     * }
     *
     * In most case java script developers don't prefer to have two object names.
     * Result JSON representation of items looks like when listWrapperSkip set to true.
     *
     * {"items":[..]}
     *
     *
     * <blockquote>
   * Property name <i>(jsonservice.properties)</i>: <b>json.list.wrapperSkip</b>
   * </blockquote>
   *
   * Default: false.
     */
    public static   final   String    listWrapperSkip_KEY      = "json.list.wrapperSkip";
    public static       boolean   listWrapperSkip       = false;
   
    /**
     * Match pattern which convert lists to MAP. TODO
     */
    public static   final   String    globalMapKeyPattern_KEY    = "json.list.map.key";
    public static       Pattern   globalMapKeyPattern     = null;
    public static   final   String     globalMapValuePattern_KEY  = "json.list.map.value";
    public static       Pattern   globalMapValuePattern     = null;
    /**
     * List of custom encoder used to handle non JSON response.
     * User can register customized encoder like HTML, plain text etc output.
     */
    public static final   String     ENCODER           = "ENCODER";
   
    /**
     * List of custom JSON object customizer. Which can be used to customize JSON output of specific object.
     * E.g an object/Class provided by third party library and its used in JSON encoding/decoding.
     * And prefer to serialize in custom format.
     */
    private     Map<Class<? extends Object>,JSONObjectCustomizer>   jsonObjectCustomizer;
   
   
    /**
     * WS end point configuration object.
     */
    private     WSEndpoint<?>     endpoint;
   
  /**
   * Binding ID used for codec.
   */
  private final   WSBinding       binding;
 
  /**
   * Document and model publisher.
   */
  private HttpMetadataPublisher     metadataPublisher;
 
  public final   SOAPVersion     soapVersion;
   
    static private SEIModel       staticSeiModel;

    static{
      LOG.info("Initalizing JSON codec static part.");
      Properties     properties       = new Properties();
      URL       serviceProperties   = JSONCodec.class.getResource("/jsonservice.properties");
      if(serviceProperties != null){
        LOG.info("Using JSON service properties from " + serviceProperties);
        try {
        properties.load(serviceProperties.openStream());
      } catch (Throwable thrown) {
        LOG.log(Level.CONFIG,"property load", thrown);
      }
      }
      for(Object key:properties.keySet()){
        if(key.toString().equals(excludeNullProperties_KEY)){
          excludeNullProperties  = Boolean.valueOf(properties.getProperty(key.toString()).trim());
        }else if(key.toString().equals(createDefaultOnNonNullable_KEY)){
          createDefaultOnNonNullable  = Boolean.valueOf(properties.getProperty(key.toString()).trim());
        }else if(key.toString().startsWith(includeProperties_KEY)){
          includeProperties.add(Pattern.compile(properties.getProperty(key.toString())));
        }else if(key.toString().equals(gzip_KEY)){
          gzip  = Boolean.valueOf(properties.getProperty(key.toString()).trim());
        }else if(key.toString().equals(responsePayloadEnabled_KEY)){
          responsePayloadEnabled  = Boolean.valueOf(properties.getProperty(key.toString()).trim());
        }/*else if(key.toString().equals("json.request.enable.payloadname")){
          requestPayloadInJSON  = Boolean.valueOf(properties.getProperty(key.toString()).trim());
        }*/else if(key.toString().startsWith(excludeProperties_KEY)){
          excludeProperties.add(Pattern.compile(properties.getProperty(key.toString())));
        }else if(key.toString().equals(globalMapKeyPattern_KEY)){
          globalMapKeyPattern = Pattern.compile(properties.getProperty(key.toString()).trim());
        }else if(key.toString().equals(globalMapValuePattern_KEY)){
          globalMapValuePattern = Pattern.compile(properties.getProperty(key.toString()).trim());
        }else if(key.toString().equals(listWrapperSkip_KEY)){
          listWrapperSkip = Boolean.valueOf(properties.getProperty(key.toString()).trim());
        }else if(key.toString().equals(dateFormat_KEY)){
          dateFormat  = Enum.valueOf(com.jaxws.json.codec.DateFormat.class, properties.getProperty(key.toString()).trim());
        }else if(key.toString().equals(useTimezoneSeparator_KEY)){
          useTimezoneSeparator  = Boolean.valueOf(properties.getProperty(key.toString()).trim());
        }else if(key.toString().equals(STATUS_PROPERTY_NAME_KEY)){
          STATUS_PROPERTY_NAME  = properties.getProperty(STATUS_PROPERTY_NAME_KEY, null);
          if(STATUS_PROPERTY_NAME != null && STATUS_PROPERTY_NAME.trim().isEmpty()){
            STATUS_PROPERTY_NAME  = null;
          }
        }
      }
    LOG.info("Initalizing JSON codec static part. Done");
    }
   
  /**
   * Create codec using SOAP WSBinding
   * @param binding
   */
  public JSONCodec(WSBinding binding) {
    this.binding = binding;
    this.soapVersion = binding.getSOAPVersion();
    initCustom(); // Always Create codec local copy of custom serializer.
  }
 
  /**
   * Copy codec.
   *
   * @param that
   */
  public JSONCodec(JSONCodec that) {
        this(that.binding);
        this.endpoint         = that.endpoint;
        this.metadataPublisher    = that.metadataPublisher;
    }
 
  /**
   * Initialize custom JSON serializer
   */
  private void initCustom() {
    jsonObjectCustomizer = new HashMap<Class<? extends Object>, JSONObjectCustomizer>();
    for (JSONObjectCustomizer serializer : ServiceFinder
        .find(JSONObjectCustomizer.class)) {
      jsonObjectCustomizer.put(serializer.getAcceptClass(), serializer);
    }
  }
 
  /**
   *
   * @return Map of custom serializers.
   */
  public Map<Class<? extends Object>, JSONObjectCustomizer> getCustomSerializer(){
    return jsonObjectCustomizer;
  }

  @SuppressWarnings({ "unchecked", "rawtypes" })
  public void setEndpoint(WSEndpoint endpoint) {
    this.endpoint = endpoint;
        endpoint.getComponentRegistry().add(this);
  }

 
  /* (non-Javadoc)
   * @see com.sun.xml.ws.api.pipe.Codec#copy()
   */
  public Codec copy() {
     return new JSONCodec(this);
  }
 
  /**
   * @param packet
   * @return
   */
  public SEIModel getSEIModel(@NotNull final Packet packet){
    SEIModel seiModel;
    if(this.endpoint != null){
      seiModel  = this.endpoint.getSEIModel();
    }else if(packet.proxy != null && packet.proxy instanceof SEIStub){
      seiModel  = ((SEIStub) packet.proxy).seiModel;
    }else{
      seiModel = staticSeiModel;
    }
    if(seiModel == null){
      throw new Error("Packet or end point dont have SEI Model");
    }
    //Used in test cases while coding/decoding required in 2 way
    staticSeiModel  = seiModel;
    return seiModel;
  }
 
  /**
   * Method converts the JSON input into JAX-WS message object.
   * @model
   */
  public void decode(InputStream in, String sContentType, Packet packet)
      throws IOException {
    if(sContentType == null) sContentType = FormDecoder.FORM_URLENCODED;
    // Add trace log if X-Debug or TRACE request.
    DebugTrace     traceLog    = (packet.supports(MessageContext.HTTP_REQUEST_HEADERS) &&
    ((Headers)packet.get(MessageContext.HTTP_REQUEST_HEADERS)).containsKey(XDEBUG_HEADER)) ? new DebugTrace() : null;
   
    if(traceLog != null){
      // Add trace log if X-Debug or TRACE request.
      packet.invocationProperties.put(TRACE, traceLog);
      traceLog.info("Request Content-type: " + sContentType);
    }
    //
    Message     message     = null;
    com.sun.xml.ws.encoding.ContentType   contentType    = new com.sun.xml.ws.encoding.ContentType(sContentType);
    if(contentType.getBaseType().equalsIgnoreCase(JSONContentType.JSON_MIME_TYPE)){
      JSONDecoder decoder = new JSONDecoder(this,in,packet);
      if(traceLog != null)traceLog.info("calling json to ws message converter: "+ new Date());
      try{
        message = decoder.getWSMessage();
      }catch(Exception exp){
        if(traceLog != null)traceLog.error(exp.getMessage());
        if(packet.supports(MessageContext.SERVLET_RESPONSE)){
          ((HttpServletResponse)packet.get(MessageContext.SERVLET_RESPONSE)).setStatus(400);
        }
        throwMessageCreationException(exp, traceLog);
      }
      if(traceLog != null)traceLog.info("Message decoded successfully: " + new Date());
    } else if(contentType.getBaseType().equalsIgnoreCase(FormDecoder.FORM_MULTIPART) ||
        contentType.getBaseType().equalsIgnoreCase(FormDecoder.FORM_URLENCODED)){
      FormDecoder decoder = new FormDecoder(this,in,packet, contentType);
      if(traceLog != null)traceLog.info("calling FORM data to ws message converter: "+ new Date());
      try{
        message = decoder.getWSMessage();
      }catch(Exception exp){
        if(traceLog != null)traceLog.error(exp.getMessage());
        if(packet.supports(MessageContext.SERVLET_RESPONSE)){
          ((HttpServletResponse)packet.get(MessageContext.SERVLET_RESPONSE)).setStatus(400);
        }
        throwMessageCreationException(exp, traceLog);
      }
      if(traceLog != null)traceLog.info("Message decoded successfully: " + new Date());
    } else {
      if(traceLog != null)traceLog.info("Supported content types: " + JSONContentType.JSON_MIME_TYPE);
      if(packet.supports(MessageContext.SERVLET_RESPONSE)){
        ((HttpServletResponse)packet.get(MessageContext.SERVLET_RESPONSE)).setStatus(WSHTTPConnection.UNSUPPORTED_MEDIA);
      }
      throwMessageCreationException(new UnsupportedMediaException(), traceLog);
    }
   
    if(message == null){
      if(traceLog != null)
        traceLog.error("Unexpected case in JSON codec. message still empty. Please report");
      packet.put(MessageContext.HTTP_RESPONSE_CODE, new Integer(400)); //BAD request
      message = Messages.createEmpty(soapVersion);
    }
    packet.setMessage(message);
  }
 
  /**
   * @param exp
   * @param traceLog
   * @throws MessageCreationException
   */
  private void throwMessageCreationException(Exception exp, final DebugTrace traceLog) throws MessageCreationException{
    if(traceLog == null){
      throw new MessageCreationException(this.soapVersion,exp);
    }else{
      throw new MessageCreationException(this.soapVersion,exp){
        private static final long serialVersionUID = 1L;

        public Message getFaultMessage() {
          return new TrackedMessage(super.getFaultMessage(),traceLog);
        }
      };
    }
  }

  /* (non-Javadoc)
   * @see com.sun.xml.ws.api.pipe.Codec#decode(java.nio.channels.ReadableByteChannel, java.lang.String, com.sun.xml.ws.api.message.Packet)
   */
  public void decode(ReadableByteChannel arg0, String arg1, Packet arg2) {
    throw new UnsupportedOperationException();
  }

  /**
   * Method converts JAX-WS message to JOSN and write it in output stream object.
   * @model
   */
  public ContentType encode(Packet packet, OutputStream out) throws IOException {
    if(gzip && packet.supports(MessageContext.SERVLET_REQUEST) &&
        isGzipInRequest((HttpServletRequest)packet.get(MessageContext.SERVLET_REQUEST))){
      HttpServletResponse response = (HttpServletResponse)packet.get(MessageContext.SERVLET_RESPONSE);
      if(!response.isCommitted()){
        response.addHeader("Content-Encoding", "gzip");
        out = new GZIPOutputStream(out);
      }
    }
    try {
      // MessageContext.MESSAGE_OUTBOUND_PROPERTY set by JAX_WS only if handler configured. But encode always a out bound.
      packet.invocationProperties.put(MessageContext.MESSAGE_OUTBOUND_PROPERTY,true);
      if(packet.invocationProperties.containsKey(ENCODER)){
        return ((Encoder)packet.invocationProperties.get(ENCODER)).encode(packet, out);
      } else {
        return new JSONEncoder(packet,this).encode(out);
      }
    } finally {
      if (out != null) {
        try {
          out.flush();
          if(out instanceof GZIPOutputStream)
            out.close();
        } catch (Exception xe) {
          // let the original exception get through
        }
      }
    }
  }
 
  /**
   *
   * @param methodImpl
   * @return List of properties need to be excluded specific to operation call.
   * This values defined in implementation operation JSONWebService annotation.
   *
   */
  public static String[][] getInExProperties(JavaMethodImpl methodImpl){
    JSONWebService jsonService = methodImpl.getMethod().getAnnotation(JSONWebService.class);
    if(jsonService != null){
      return new String[][]{jsonService.includeProperties(),jsonService.excludeProperties()};
    }
    // default codec level
    return new String[][]{{},{}};
  }

  /* (non-Javadoc)
   * @see com.sun.xml.ws.api.pipe.Codec#encode(com.sun.xml.ws.api.message.Packet, java.nio.channels.WritableByteChannel)
   */
  public ContentType encode(Packet packaet, WritableByteChannel byteChannel) {
    throw new UnsupportedOperationException();
  }

  /* (non-Javadoc)
   * @see com.sun.xml.ws.api.pipe.Codec#getMimeType()
   */
  public String getMimeType() {
    return JSONContentType.JSON_MIME_TYPE;
  }

  /* (non-Javadoc)
   * @see com.sun.xml.ws.api.pipe.Codec#getStaticContentType(com.sun.xml.ws.api.message.Packet)
   *
   * TIP 1: by sending accept http header with value "application/json" increase performance on finding relavent decoder.
   */
  public ContentType getStaticContentType(Packet packet) {
    /**
     * Check accept content type is not present.
     *
     * TODO header case sensitive. Multiple header values handling.
     */
    if(packet != null &&
        packet.invocationProperties != null){
      if(packet.invocationProperties.containsKey(FORCED_RESPONSE_CONTENT_TYPE)){
        return (ContentType)packet.invocationProperties.get(FORCED_RESPONSE_CONTENT_TYPE);
      } else if(packet.invocationProperties.containsKey(ENCODER)){
        return ((Encoder)packet.invocationProperties.get(ENCODER)).getStaticContentType(packet);
      } else if(packet.invocationProperties.containsKey("accept")
        && (!packet.invocationProperties.get("accept").equals(JSONContentType.JSON_MIME_TYPE))){
        // Accept content type is not JSON.
        // Test is this accept content type handled by custom response package handlers.
        // Example case: JSON request result with HTML/CSV/PDF etc response.
        /* FIXME if(customEncoder.containsKey(packet.invocationProperties.get("accept"))){
          return customEncoder.get(packet.invocationProperties.get("accept")).contentType();
        }*/
        //Worst perform
        Module modules = endpoint.getContainer().getSPI(com.sun.xml.ws.api.server.Module.class);
        //TODO document more here and increase performance.
        for(BoundEndpoint endPointObj : modules.getBoundEndpoints()){
          if(endPointObj.getEndpoint().getImplementationClass().equals(endpoint.getImplementationClass())
              && endPointObj.getEndpoint().getBinding().getBindingId() != binding.getBindingId()){
            Codec     codec     =  endPointObj.getEndpoint().createCodec();
            ContentType contentType =   codec.getStaticContentType(packet);
            if(contentType != null && contentType.getContentType().startsWith(packet.invocationProperties.get("accept").toString())){
              return endPointObj.getEndpoint().createCodec().getStaticContentType(packet);
            }
          }
        }
      }
    }
    return jsonContentType;
  }

  /**
   * @return
   */
  public SOAPVersion getSoapVersion() {
    return soapVersion;
  }

  public WSEndpoint<?> getEndpoint() {
    return endpoint;
  }
 
  public WSBinding getBinding() {
    return binding;
  }

  private static boolean isGzipInRequest(HttpServletRequest request) {
        String header = request.getHeader("Accept-Encoding");
        return header != null && header.indexOf("gzip") >= 0;
    }
 
  /**
   * Meta data publisher for get request.
   */
  public @Nullable <T> T getSPI(@NotNull Class<T> type) {
    if (type == HttpMetadataPublisher.class) {
      // Overwrite http end point document provider.
      if (metadataPublisher == null)
        metadataPublisher = new JSONHttpMetadataPublisher(this);
      return type.cast(metadataPublisher);
    }
    return null;
  }
}
TOP

Related Classes of com.jaxws.json.codec.JSONCodec

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.