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
006 * (the "License"); you may not use this file except in compliance with
007 * the 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 */
017 package org.apache.servicemix.soap.core;
018
019 import java.util.ArrayList;
020 import java.util.Collection;
021 import java.util.List;
022 import java.util.ListIterator;
023
024 import org.apache.commons.logging.Log;
025 import org.apache.commons.logging.LogFactory;
026 import org.apache.servicemix.soap.api.Interceptor;
027 import org.apache.servicemix.soap.api.InterceptorChain;
028 import org.apache.servicemix.soap.api.Message;
029
030 /**
031 * A PhaseInterceptorChain orders Interceptors according
032 * to the before & after properties on an Interceptor.
033 *
034 * @author <a href="mailto:gnodet [at] gmail.com">Guillaume Nodet</a>
035 */
036 public class PhaseInterceptorChain implements InterceptorChain {
037
038 private static final Log LOG = LogFactory.getLog(PhaseInterceptorChain.class);
039
040 private final List<Interceptor> interceptors = new ArrayList<Interceptor>();
041
042 public PhaseInterceptorChain() {
043 }
044
045 public void add(Iterable<? extends Interceptor> newhandlers) {
046 if (newhandlers == null) {
047 return;
048 }
049 for (Interceptor handler : newhandlers) {
050 add(handler);
051 }
052 }
053
054 public Iterable<Interceptor> getInterceptors() {
055 return interceptors;
056 }
057
058 public void add(Interceptor i) {
059 if (LOG.isDebugEnabled()) {
060 LOG.debug("Adding interceptor " + i.getId());
061 }
062 insertInterceptor(i);
063 }
064
065 /**
066 * Invokes each phase's handler in turn.
067 *
068 * @param context
069 * @throws Exception
070 */
071 public void doIntercept(Message message) {
072 ListIterator<Interceptor> iterator = getState(message);
073
074 if (iterator == null) {
075 iterator = interceptors.listIterator();
076 setState(message, iterator);
077 }
078
079 try {
080 while (iterator.hasNext()) {
081 Interceptor currentInterceptor = iterator.next();
082 if (LOG.isDebugEnabled()) {
083 LOG.debug("Invoking handleMessage on interceptor " + currentInterceptor.getId());
084 }
085 currentInterceptor.handleMessage(message);
086 }
087 } catch (RuntimeException ex) {
088 if (LOG.isInfoEnabled()) {
089 LOG.info("Interceptor has thrown exception, unwinding now", ex);
090 }
091 message.setContent(Exception.class, ex);
092 // Unwind
093 while (iterator.hasPrevious()) {
094 Interceptor currentInterceptor = iterator.previous();
095 if (LOG.isDebugEnabled()) {
096 LOG.debug("Invoking handleFault on interceptor " + currentInterceptor.getId());
097 }
098 currentInterceptor.handleFault(message);
099 }
100 throw ex;
101 }
102 }
103
104 @SuppressWarnings("unchecked")
105 protected ListIterator<Interceptor> getState(Message message) {
106 Object state = message.get(this.toString());
107 return (ListIterator<Interceptor>) state;
108 }
109
110 protected void setState(Message message, ListIterator<Interceptor> state) {
111 message.put(this.toString(), state);
112 message.put(InterceptorChain.class, this);
113 }
114
115 protected void insertInterceptor(Interceptor interc) {
116 if (interceptors.size() == 0) {
117 interceptors.add(interc);
118 return;
119 }
120 int begin = -1;
121 int end = interceptors.size();
122 Collection before = interc.getBefore();
123 Collection after = interc.getAfter();
124 for (int i = 0; i < interceptors.size(); i++) {
125 Interceptor cmp = interceptors.get(i);
126 if (cmp.getId() == null) {
127 continue;
128 }
129 if (before.contains(cmp.getId()) && i < end) {
130 end = i;
131 }
132 if (cmp.getBefore().contains(interc.getId()) && i > begin) {
133 begin = i;
134 }
135 if (after.contains(cmp.getId()) && i > begin) {
136 begin = i;
137 }
138 if (cmp.getAfter().contains(interc.getId()) && i < end) {
139 end = i;
140 }
141 }
142 if (end < begin + 1) {
143 throw new IllegalStateException("Invalid ordering for interceptor " + interc.getId());
144 }
145 interceptors.add(end, interc);
146 }
147
148
149 }