/* * Copyright 2012 The Solmix Project * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.gnu.org/licenses/ * or see the FSF site: http://www.fsf.org. */ package org.solmix.web.interceptor; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.solmix.api.call.DSCall; import org.solmix.api.context.WebContext; import org.solmix.api.datasource.DSRequest; import org.solmix.api.datasource.DSResponse; import org.solmix.api.datasource.DataSourceManager; import org.solmix.api.exception.SlxException; import org.solmix.api.jaxb.request.Request; import org.solmix.api.jaxb.request.Roperation; import org.solmix.api.types.Texception; import org.solmix.api.types.Tmodule; import org.solmix.commons.collections.DataTypeMap; import org.solmix.fmk.SlxContext; /** * Interceptor for common Rest-style ajax communication. * * @author solmix.f@gmail.com * @version $Id$ 2013-12-24 */ public class DefaultRestInterceptor extends AbstractRestInterceptor { private static final Logger LOG = LoggerFactory.getLogger(DefaultRestInterceptor.class); public static final String DSC_TRANSPORT = "dsc_transport"; public static final String XML_PREFIX = "<"; public static final String JSON_PREFIX = "{"; public static final String REST_PARM = "_isRest"; private String payloadName = PAYLOAD_NAME; @Override public void configure(DataTypeMap config) { super.configure(config); payloadName = config.getString("payloadName", payloadName); } @Override public void prepareRequest(DSCall dsCall, WebContext context) throws SlxException { HttpServletRequest request = context.getRequest(); Object protocol = request.getParameter(PROTOCOL); if (protocol == null || PROTOCOL_POSTXML.equalsIgnoreCase(protocol.toString()) || PROTOCOL_POSTMESSAGE.equalsIgnoreCase(protocol.toString())) try { String payload = request.getParameter(payloadName); Request dsRequest = null; if (payload != null) { payload = payload.trim(); if (payload.startsWith(JSON_PREFIX)) { dsRequest = dsCall.getJSParser().toJavaObject(payload, Request.class); } else if (payload.startsWith(XML_PREFIX)) { dsRequest = dsCall.getXMLParser().unmarshalReq( new StringReader(payload)); } } else { if (JSON.equalsIgnoreCase(getDataformat(request))) { dsRequest = dsCall.getJSParser().toJavaObject( request.getReader(), Request.class); } else if (XML.equalsIgnoreCase(getDataformat(request))) { dsRequest = dsCall.getXMLParser().unmarshalReq( request.getReader()); } } if (dsRequest != null) { List<Roperation> operations = dsRequest.getOperations().getElem(); if (operations != null) { boolean freeOnExecute = operations.size() <= 1; for (Roperation operation : operations) { DSRequest dsr = SlxContext.getThreadSystemContext().getExtension( DataSourceManager.class).createDSRequest( operation, SlxContext.getWebContext()); dsr.getContext().setIsClientRequest(true); dsr.setFreeOnExecute(freeOnExecute); dsr.setCanJoinTransaction(!freeOnExecute); dsr.setDSCall(dsCall); dsr.setRequestContext(context); dsCall.addRequest(dsr); } } } } catch (IOException e) { throw new SlxException(Tmodule.DSC, Texception.DEFAULT, e); } } @Override public Action postInspect(DSCall dsCall, WebContext context) throws SlxException { // Object isRest = context.getAttribute(REST_PARM, Scope.LOCAL); HttpServletRequest request = context.getRequest(); if (/* isRest == null|| */request.getParameter(DSC_TRANSPORT) != null) return Action.CONTINUE; String dataFormat = getDataformat(context.getRequest()); String contentType = new StringBuilder().append("text/").append( dataFormat).append("; charset=").append(charset).toString(); context.setContentType(contentType); if (LOG.isTraceEnabled()) LOG.trace("Rest style output used ContentType:" + contentType); // find client responses List<Object> orderedResponseList = new ArrayList<Object>(); for (DSRequest req : dsCall.getRequests()) { DSResponse res = dsCall.getResponse(req); orderedResponseList.add(getClientResponse(res)); } Writer _out; try { if (showClientOutPut) _out = new StringWriter(); else _out = context.getOut(); // Data must no cached. context.setNoCacheHeaders(); Map<String, Object> restContainer = new HashMap<String, Object>(); if (orderedResponseList.size() == 1) restContainer.put("response", orderedResponseList.get(0)); else restContainer.put("responses", orderedResponseList); if (JSON.equalsIgnoreCase(dataFormat)) { dsCall.getJSParser().toJSON(_out, restContainer); } else if (XML.equalsIgnoreCase(dataFormat)) { dsCall.getXMLParser().toXML(_out, restContainer); } _out.flush(); if (showClientOutPut) { String output = _out.toString(); int outputSize = output.length(); if (LOG.isTraceEnabled()) { LOG.trace((new StringBuilder()).append( "Uncompressed result size: ").append(outputSize).append( " bytes").toString()); LOG.trace("output String :\n" + _out.toString()); } context.getOut().write(output); context.getOut().flush(); } } catch (IOException e) { throw new SlxException(Tmodule.BASIC, Texception.IO_EXCEPTION, e); } return Action.CANCELLED; } /** * @return the payloadName */ public String getPayloadName() { return payloadName; } /** * @param payloadName the payloadName to set */ public void setPayloadName(String payloadName) { this.payloadName = payloadName; } }