Author: asoldano
Date: 2014-10-29 10:05:50 -0400 (Wed, 29 Oct 2014)
New Revision: 19036
Modified:
stack/cxf/trunk/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/ProviderImpl.java
stack/cxf/trunk/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/configuration/HandlerChainSortInterceptor.java
Log:
[JBWS-3848] Avoid resetting the handler-chain in the Binding; instead sort the chain copy
that's used to build the handler chain invoker; this hides the process from the user
and adds no processing overhead as the chain is already copied to build an invoker; sort
the chain upfront when building the client (after pre-defined config setup), to speed up
sorting in the best and most common scenario (no manual user change to the chain).
Modified:
stack/cxf/trunk/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/ProviderImpl.java
===================================================================
---
stack/cxf/trunk/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/ProviderImpl.java 2014-10-29
14:02:39 UTC (rev 19035)
+++
stack/cxf/trunk/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/ProviderImpl.java 2014-10-29
14:05:50 UTC (rev 19036)
@@ -579,13 +579,13 @@
protected void setupClient(Object obj, Class<?> seiClass,
WebServiceFeature... features) {
Binding binding = ((BindingProvider)obj).getBinding();
Client client = obj instanceof DispatchImpl<?> ?
((DispatchImpl<?>)obj).getClient() : ClientProxy.getClient(obj);
- client.getOutInterceptors().add(new HandlerChainSortInterceptor(binding));
ClientConfig config = readConfig(seiClass);
if (config != null) {
CXFClientConfigurer helper = new CXFClientConfigurer();
helper.setupConfigHandlers(binding, config);
helper.setConfigProperties(client, config.getProperties());
}
+ client.getOutInterceptors().add(new HandlerChainSortInterceptor(binding)); //add
this *after* the config has been set (if any)!
if (features != null) {
for (WebServiceFeature f : features) {
if (f instanceof AbstractClientFeature) {
Modified:
stack/cxf/trunk/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/configuration/HandlerChainSortInterceptor.java
===================================================================
---
stack/cxf/trunk/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/configuration/HandlerChainSortInterceptor.java 2014-10-29
14:02:39 UTC (rev 19035)
+++
stack/cxf/trunk/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/configuration/HandlerChainSortInterceptor.java 2014-10-29
14:05:50 UTC (rev 19036)
@@ -21,18 +21,20 @@
*/
package org.jboss.wsf.stack.cxf.client.configuration;
-import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import javax.xml.ws.Binding;
import javax.xml.ws.handler.Handler;
import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.jaxws.handler.HandlerChainInvoker;
+import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
-import org.jboss.ws.common.configuration.ConfigDelegateHandler;
-import org.jboss.wsf.spi.metadata.j2ee.serviceref.UnifiedHandlerMetaData.HandlerType;
+import org.jboss.ws.common.configuration.ConfigDelegateHandlerComparator;
/**
@@ -45,137 +47,46 @@
public class HandlerChainSortInterceptor extends AbstractPhaseInterceptor<Message>
{
private final Binding binding;
+ @SuppressWarnings("rawtypes")
+ private static final Comparator<Handler> comparator = new
ConfigDelegateHandlerComparator<Handler>();
public HandlerChainSortInterceptor(Binding b)
{
- super(Phase.SETUP);
+ super(Phase.PRE_PROTOCOL);
binding = b;
+ //initially sort and reset the handler chain; if the chain is not modified later,
the sort process
+ //in handleMessage() deals with an already ordered list and is very efficient (~
O(n) according to
+ //Collections.sort(..) javadoc.
+ @SuppressWarnings("rawtypes")
+ List<Handler> hc = binding.getHandlerChain();
+ if (hc.size() > 1) { //no need to sort etc if the chain is empty or has one
handler only
+ Collections.sort(hc, comparator);
+ binding.setHandlerChain(hc);
+ }
}
@Override
+ @SuppressWarnings("rawtypes")
public void handleMessage(Message message) throws Fault
{
if (binding != null) {
- @SuppressWarnings("rawtypes")
- List<Handler> list = binding.getHandlerChain();
- if (list != null && !list.isEmpty()) {
- HandlerSorter hs = new HandlerSorter();
- if (hs.split(list)) {
- binding.setHandlerChain(hs.merge());
+ Exchange ex = message.getExchange();
+ if (ex.get(HandlerChainInvoker.class) == null) {
+ List<Handler> hc = binding.getHandlerChain();
+ if (hc.size() > 1) { //no need to sort etc if the chain is empty or has
one handler only
+ Collections.sort(hc, comparator);
+ //install a new HandlerChainInvoker using the sorted handler chain;
+ //the AbstractJAXWSHandlerInterceptor will be using this invoker
+ //instead of creating a new one
+ ex.put(HandlerChainInvoker.class, new HandlerChainInvoker(hc,
isOutbound(message, ex)));
}
- hs.cleanup();
}
}
}
-
- /**
- * Utility class for efficiently sorting handlers so that PRE handlers always
- * come before user handlers and POST handlers always come after user handlers.
- *
- * We need to know if the sorted list is actually different from the original
- * list, as if they are the same we don't want to spend time on setting a new
- * handler chain, which can be expensive. Moreover we're not really interested
- * in sorting the whole chain, we only care about the PRE/user/POST requirement
- * and are fine with the relative order of handlers of the same type.
- *
- * So we process the list in two phases:
- *
- * 1) split phase: the handler list is scanned (O(n)) to split it into PRE, user
- * and POST handler sublists. The relative order of handlers of
- * the same type is not changed.
- * While splitting, the procedure also figures out if the list
- * actually requires sorting, that is whether the PRE-user-POST
- * order requirement is not satisfied; this allows avoiding
- * useless ordering if the list is already fine (which is the
- * most common scenario).
- * 2) merge phase: the sublists are merged together (O(n)) into an ordered
- * handlers list
- *
- * The overall time complexity is O(2n).
- *
- */
- @SuppressWarnings("rawtypes")
- private class HandlerSorter {
- private List<Handler> pre;
- private List<Handler> ep;
- private List<Handler> post;
-
- /**
- * Read the handlers list and figures out if it requires sorting.
- *
- * @param handlers
- * @return
- */
- public boolean split(List<Handler> handlers) {
- boolean requiresSort = false;
- HandlerType lastHandlerType = null;
- for (Handler h : handlers) {
- if (h instanceof ConfigDelegateHandler) {
- if (((ConfigDelegateHandler)h).isPre()) {
- add(h, HandlerType.PRE);
- if (lastHandlerType != null && lastHandlerType !=
HandlerType.PRE) {
- requiresSort = true;
- }
- lastHandlerType = HandlerType.PRE;
- } else {
- add(h, HandlerType.POST);
- lastHandlerType = HandlerType.POST;
- }
- } else {
- add(h, HandlerType.ENDPOINT);
- if (lastHandlerType != null && lastHandlerType ==
HandlerType.POST) {
- requiresSort = true;
- }
- lastHandlerType = HandlerType.ENDPOINT;
- }
- }
- return requiresSort;
- }
-
-
-
- public List<Handler> merge() {
- List<Handler> l = new ArrayList<Handler>();
- if (pre != null) {
- l.addAll(pre);
- }
- l.addAll(ep);
- if (post != null) {
- l.addAll(post);
- }
- return l;
- }
-
- public void cleanup() {
- this.pre = null;
- this.post = null;
- this.ep = null;
- }
-
- private void add(Handler h, HandlerType t) {
- switch (t)
- {
- case PRE :
- if (pre == null) {
- pre = new ArrayList<Handler>(4);
- }
- pre.add(h);
- break;
-
- case POST :
- if (post == null) {
- post = new ArrayList<Handler>(4);
- }
- post.add(h);
- break;
-
- default :
- if (ep == null) {
- ep = new ArrayList<Handler>();
- }
- ep.add(h);
- break;
- }
- }
+
+ private boolean isOutbound(Message message, Exchange ex) {
+ return message == ex.getOutMessage()
+ || message == ex.getOutFaultMessage();
}
+
}
Show replies by date