You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2008/11/12 13:49:56 UTC
svn commit: r713358 -
/cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/
Author: sergeyb
Date: Wed Nov 12 04:49:56 2008
New Revision: 713358
URL: http://svn.apache.org/viewvc?rev=713358&view=rev
Log:
Adding code bits dealing with continuations for wider audience to comment
Added:
cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/
cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/AbstractPhaseInterceptor.java (with props)
cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/Phase.java (with props)
cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseChainCache.java (with props)
cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseComparator.java (with props)
cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptor.java (with props)
cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java (with props)
cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseManager.java (with props)
cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/package.html (with props)
Added: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/AbstractPhaseInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/AbstractPhaseInterceptor.java?rev=713358&view=auto
==============================================================================
--- cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/AbstractPhaseInterceptor.java (added)
+++ cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/AbstractPhaseInterceptor.java Wed Nov 12 04:49:56 2008
@@ -0,0 +1,110 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.phase;
+
+import java.util.Collection;
+import java.util.Set;
+
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.cxf.common.util.SortedArraySet;
+import org.apache.cxf.message.Message;
+
+public abstract class AbstractPhaseInterceptor<T extends Message> implements PhaseInterceptor<T> {
+ private final String id;
+ private final String phase;
+ private final Set<String> before = new SortedArraySet<String>();
+ private final Set<String> after = new SortedArraySet<String>();
+
+ public AbstractPhaseInterceptor(String phase) {
+ this(null, phase, false);
+ }
+ public AbstractPhaseInterceptor(String i, String p) {
+ this(i, p, false);
+ }
+ public AbstractPhaseInterceptor(String phase, boolean uniqueId) {
+ this(null, phase, uniqueId);
+ }
+ public AbstractPhaseInterceptor(String i, String p, boolean uniqueId) {
+ if (i == null) {
+ i = getClass().getName();
+ }
+ if (uniqueId) {
+ i += System.identityHashCode(this);
+ }
+ id = i;
+ phase = p;
+ }
+
+ public void setBefore(Collection<String> i) {
+ before.clear();
+ before.addAll(i);
+ }
+ public void setAfter(Collection<String> i) {
+ after.clear();
+ after.addAll(i);
+ }
+ public void addBefore(Collection<String> i) {
+ before.addAll(i);
+ }
+ public void addAfter(Collection<String> i) {
+ after.addAll(i);
+ }
+
+ public void addBefore(String i) {
+ before.add(i);
+ }
+
+ public void addAfter(String i) {
+ after.add(i);
+ }
+
+
+ public final Set<String> getAfter() {
+ return after;
+ }
+
+ public final Set<String> getBefore() {
+ return before;
+ }
+
+ public final String getId() {
+ return id;
+ }
+
+ public final String getPhase() {
+ return phase;
+ }
+
+
+ public void handleFault(T message) {
+ }
+
+ public boolean isGET(T message) {
+ String method = (String)message.get(Message.HTTP_REQUEST_METHOD);
+ return "GET".equals(method) && message.getContent(XMLStreamReader.class) == null;
+ }
+
+ protected boolean isRequestor(T message) {
+ return Boolean.TRUE.equals(message.containsKey(
+ org.apache.cxf.message.Message.REQUESTOR_ROLE));
+ }
+
+}
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/AbstractPhaseInterceptor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/AbstractPhaseInterceptor.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/Phase.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/Phase.java?rev=713358&view=auto
==============================================================================
--- cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/Phase.java (added)
+++ cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/Phase.java Wed Nov 12 04:49:56 2008
@@ -0,0 +1,112 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.phase;
+
+public class Phase implements Comparable {
+
+ // can be removed from once defined as default value in configuration metadata for bus
+
+ public static final String SETUP = "setup";
+ public static final String SETUP_ENDING = "setup-ending";
+ public static final String PRE_LOGICAL = "pre-logical";
+ public static final String PRE_LOGICAL_ENDING = "pre-logical-ending";
+ public static final String USER_LOGICAL = "user-logical";
+ public static final String USER_LOGICAL_ENDING = "user-logical-ending";
+ public static final String POST_LOGICAL = "post-logical";
+ public static final String POST_LOGICAL_ENDING = "post-logical-ending";
+ public static final String PRE_MARSHAL = "pre-marshal";
+ public static final String MARSHAL = "marshal";
+ public static final String POST_MARSHAL = "post-marshal";
+ public static final String MARSHAL_ENDING = "marshal-ending";
+ public static final String PRE_PROTOCOL = "pre-protocol";
+ public static final String PRE_PROTOCOL_ENDING = "pre-protocol-ending";
+ public static final String USER_PROTOCOL = "user-protocol";
+ public static final String USER_PROTOCOL_ENDING = "user-protocol-ending";
+ public static final String POST_PROTOCOL = "post-protocol";
+ public static final String POST_PROTOCOL_ENDING = "post-protocol-ending";
+ public static final String PREPARE_SEND = "prepare-send";
+ public static final String PREPARE_SEND_ENDING = "prepare-send-ending";
+ public static final String PRE_STREAM = "pre-stream";
+ public static final String PRE_STREAM_ENDING = "pre-stream-ending";
+ public static final String USER_STREAM = "user-stream";
+ public static final String USER_STREAM_ENDING = "user-stream-ending";
+ public static final String POST_STREAM = "post-stream";
+ public static final String POST_STREAM_ENDING = "post-stream-ending";
+ public static final String WRITE = "write";
+ public static final String WRITE_ENDING = "write-ending";
+ public static final String SEND = "send";
+ public static final String SEND_ENDING = "send-ending";
+
+ public static final String RECEIVE = "receive";
+ public static final String READ = "read";
+ public static final String PROTOCOL = "protocol";
+ public static final String UNMARSHAL = "unmarshal";
+ public static final String PRE_INVOKE = "pre-invoke";
+ public static final String INVOKE = "invoke";
+ public static final String POST_INVOKE = "post-invoke";
+
+
+ private String name;
+ private int priority;
+
+ public Phase() {
+ }
+
+ public Phase(String n, int p) {
+ this.name = n;
+ this.priority = p;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String n) {
+ this.name = n;
+ }
+ public int getPriority() {
+ return priority;
+ }
+ public void setPriority(int p) {
+ this.priority = p;
+ }
+
+ public int hashCode() {
+ return priority;
+ }
+ public boolean equals(Object o) {
+ Phase p = (Phase)o;
+
+ return p.priority == priority
+ && p.name.equals(name);
+ }
+
+ public int compareTo(Object o) {
+ Phase p = (Phase)o;
+
+ if (priority == p.priority) {
+ return name.compareTo(p.name);
+ }
+ return priority - p.priority;
+ }
+
+ public String toString() {
+ return "Phase(" + getName() + ")";
+ }
+}
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/Phase.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/Phase.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseChainCache.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseChainCache.java?rev=713358&view=auto
==============================================================================
--- cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseChainCache.java (added)
+++ cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseChainCache.java Wed Nov 12 04:49:56 2008
@@ -0,0 +1,137 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.phase;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.SortedSet;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.cxf.common.util.ModCountCopyOnWriteArrayList;
+import org.apache.cxf.interceptor.Interceptor;
+
+/**
+ * The PhaseChainCache provides default interceptor chains for SOAP requests
+ * and responses, both from the client and web service side. The list of
+ * phases supplied in the get() methods of this class are defined by default
+ * within org.apache.cxf.phase.PhaseManagerImpl. For an example of this class
+ * in use, check the sourcecode of org.apache.cxf.endpoint.ClientImpl.
+ */
+public final class PhaseChainCache {
+ AtomicReference<ChainHolder> lastData = new AtomicReference<ChainHolder>();
+
+
+ @SuppressWarnings("unchecked")
+ public PhaseInterceptorChain get(SortedSet<Phase> phaseList,
+ List<Interceptor> p1) {
+ return getChain(phaseList, p1);
+ }
+
+ @SuppressWarnings("unchecked")
+ public PhaseInterceptorChain get(SortedSet<Phase> phaseList,
+ List<Interceptor> p1,
+ List<Interceptor> p2) {
+ return getChain(phaseList, p1, p2);
+ }
+ @SuppressWarnings("unchecked")
+ public PhaseInterceptorChain get(SortedSet<Phase> phaseList,
+ List<Interceptor> p1,
+ List<Interceptor> p2,
+ List<Interceptor> p3) {
+ return getChain(phaseList, p1, p2, p3);
+ }
+ @SuppressWarnings("unchecked")
+ public PhaseInterceptorChain get(SortedSet<Phase> phaseList,
+ List<Interceptor> p1,
+ List<Interceptor> p2,
+ List<Interceptor> p3,
+ List<Interceptor> p4) {
+ return getChain(phaseList, p1, p2, p3, p4);
+ }
+ @SuppressWarnings("unchecked")
+ public PhaseInterceptorChain get(SortedSet<Phase> phaseList,
+ List<Interceptor> p1,
+ List<Interceptor> p2,
+ List<Interceptor> p3,
+ List<Interceptor> p4,
+ List<Interceptor> p5) {
+ return getChain(phaseList, p1, p2, p3, p4, p5);
+ }
+
+ private PhaseInterceptorChain getChain(SortedSet<Phase> phaseList, List<Interceptor> ... providers) {
+ ChainHolder last = lastData.get();
+
+ if (last == null
+ || !last.matches(providers)) {
+
+ PhaseInterceptorChain chain = new PhaseInterceptorChain(phaseList);
+ List<ModCountCopyOnWriteArrayList<Interceptor>> copy
+ = new ArrayList<ModCountCopyOnWriteArrayList<Interceptor>>(providers.length);
+ for (List<Interceptor> p : providers) {
+ copy.add(new ModCountCopyOnWriteArrayList<Interceptor>(p));
+ chain.add(p);
+ }
+ last = new ChainHolder(chain, copy);
+ lastData.set(last);
+ }
+
+
+ return last.chain.cloneChain();
+ }
+
+ private static class ChainHolder {
+ List<ModCountCopyOnWriteArrayList<Interceptor>> lists;
+ PhaseInterceptorChain chain;
+
+ ChainHolder(PhaseInterceptorChain c, List<ModCountCopyOnWriteArrayList<Interceptor>> l) {
+ lists = l;
+ chain = c;
+ }
+
+ boolean matches(List<Interceptor> ... providers) {
+ if (lists.size() == providers.length) {
+ for (int x = 0; x < providers.length; x++) {
+ if (lists.get(x).size() != providers[x].size()) {
+ return false;
+ }
+
+ if (providers[x].getClass() == ModCountCopyOnWriteArrayList.class) {
+ if (((ModCountCopyOnWriteArrayList)providers[x]).getModCount()
+ != lists.get(x).getModCount()) {
+ return false;
+ }
+ } else {
+ ListIterator<Interceptor> i1 = lists.get(x).listIterator();
+ ListIterator<Interceptor> i2 = providers[x].listIterator();
+
+ while (i1.hasNext()) {
+ if (i1.next() != i2.next()) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ }
+}
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseChainCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseChainCache.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseComparator.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseComparator.java?rev=713358&view=auto
==============================================================================
--- cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseComparator.java (added)
+++ cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseComparator.java Wed Nov 12 04:49:56 2008
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.phase;
+
+import java.util.Comparator;
+
+public class PhaseComparator implements Comparator<Phase> {
+
+ public int compare(Phase o1, Phase o2) {
+ return o1.getPriority() - o2.getPriority();
+ }
+
+}
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseComparator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseComparator.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptor.java?rev=713358&view=auto
==============================================================================
--- cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptor.java (added)
+++ cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptor.java Wed Nov 12 04:49:56 2008
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.phase;
+
+import java.util.Set;
+
+import org.apache.cxf.interceptor.Interceptor;
+import org.apache.cxf.message.Message;
+
+/**
+ * A phase interceptor participates in a PhaseInterceptorChain.
+ * <pre>
+ * The before and after properties contain a list of Ids that can control
+ * where in the chain the interceptor is placed relative to other interceptors
+ * </pre>
+ * @see org.apache.cxf.phase.PhaseInterceptorChain
+ * @author Dan Diephouse
+ */
+public interface PhaseInterceptor<T extends Message> extends Interceptor<T> {
+
+ /**
+ * Returns a set of IDs specifying the interceptors that this interceptor should
+ * be placed after in the interceptor chain
+ * @return the ids of the interceptors
+ */
+ Set<String> getAfter();
+
+ /**
+ * Returns a set of IDs specifying the interceptors that this interceptor needs
+ * to be before in the inteceptor chain.
+ * @return the ids of the interceptors
+ */
+ Set<String> getBefore();
+
+ /**
+ * The ID of this interceptor.
+ * @return the id
+ */
+ String getId();
+
+ /**
+ * The phase of this interceptor.
+ * @return the phase
+ */
+ String getPhase();
+
+}
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptor.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java?rev=713358&view=auto
==============================================================================
--- cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java (added)
+++ cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java Wed Nov 12 04:49:56 2008
@@ -0,0 +1,687 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.phase;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.continuations.SuspendedInvocationException;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.interceptor.Interceptor;
+import org.apache.cxf.interceptor.InterceptorChain;
+import org.apache.cxf.message.FaultMode;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.transport.MessageObserver;
+
+/**
+ * A PhaseInterceptorChain orders Interceptors according to the phase they
+ * participate in and also according to the before & after properties on an
+ * Interceptor.
+ * <p>
+ * A List of phases is supplied to the PhaseInterceptorChain in the constructor.
+ * This class is typically instantiated from the PhaseChainCache class in this
+ * package. Interceptors that are added to the chain are ordered by phase.
+ * Within a phase, interceptors can order themselves. Each PhaseInterceptor
+ * has an ID. PhaseInterceptors can supply a Collection of IDs which they
+ * should run before or after, supplying fine grained ordering.
+ * <p>
+ *
+ */
+public class PhaseInterceptorChain implements InterceptorChain {
+
+ private static final Logger LOG = LogUtils.getL7dLogger(PhaseInterceptorChain.class);
+
+
+ private final Map<String, Integer> nameMap;
+ private final Phase phases[];
+
+ // heads[phase] refers to the first interceptor of the given phase
+ private InterceptorHolder heads[];
+ // tails[phase] refers to the last interceptor of the given phase
+ private InterceptorHolder tails[];
+ // hasAfters[phase] indicates that the given phase has already inserted
+ // interceptors that may need to be placed after future to-be-inserted
+ // interceptors. This flag is used to activate ordering of interceptors
+ // when new ones are added to the list for this phase.
+ // Note no hasBefores[] is needed because implementation adds subsequent
+ // interceptors to the end of the list by default.
+ private boolean hasAfters[];
+
+
+ private State state;
+ private Message pausedMessage;
+ private MessageObserver faultObserver;
+ private PhaseInterceptorIterator iterator;
+
+ // currently one chain for one request/response, use below as signal
+ // to avoid duplicate fault processing on nested calling of
+ // doIntercept(), which will throw same fault multi-times
+ private boolean faultOccurred;
+
+
+ private PhaseInterceptorChain(PhaseInterceptorChain src) {
+ //only used for clone
+ state = State.EXECUTING;
+
+ //immutable, just repoint
+ nameMap = src.nameMap;
+ phases = src.phases;
+
+ int length = phases.length;
+ hasAfters = new boolean[length];
+ System.arraycopy(src.hasAfters, 0, hasAfters, 0, length);
+
+ heads = new InterceptorHolder[length];
+ tails = new InterceptorHolder[length];
+
+ InterceptorHolder last = null;
+ for (int x = 0; x < length; x++) {
+ InterceptorHolder ih = src.heads[x];
+ while (ih != null
+ && ih.phaseIdx == x) {
+ InterceptorHolder ih2 = new InterceptorHolder(ih);
+ ih2.prev = last;
+ if (last != null) {
+ last.next = ih2;
+ }
+ if (heads[x] == null) {
+ heads[x] = ih2;
+ }
+ tails[x] = ih2;
+ last = ih2;
+ ih = ih.next;
+ }
+ }
+ }
+
+ public PhaseInterceptorChain(SortedSet<Phase> ps) {
+ state = State.EXECUTING;
+
+ int numPhases = ps.size();
+ phases = new Phase[numPhases];
+ nameMap = new HashMap<String, Integer>();
+
+ heads = new InterceptorHolder[numPhases];
+ tails = new InterceptorHolder[numPhases];
+ hasAfters = new boolean[numPhases];
+
+ int idx = 0;
+ for (Phase phase : ps) {
+ phases[idx] = phase;
+ nameMap.put(phase.getName(), idx);
+ ++idx;
+ }
+ }
+
+ // this method should really be on the InterceptorChain interface
+ public State getState() {
+ return state;
+ }
+
+ public PhaseInterceptorChain cloneChain() {
+ return new PhaseInterceptorChain(this);
+ }
+
+ private void updateIterator() {
+ if (iterator == null) {
+ iterator = new PhaseInterceptorIterator(heads);
+ outputChainToLog(false);
+ //System.out.println(toString());
+ }
+ }
+
+ public void add(Collection<Interceptor> newhandlers) {
+ add(newhandlers, false);
+ }
+
+ public void add(Collection<Interceptor> newhandlers, boolean force) {
+ if (newhandlers == null) {
+ return;
+ }
+
+ for (Interceptor handler : newhandlers) {
+ add(handler, force);
+ }
+ }
+
+ public void add(Interceptor i) {
+ add(i, false);
+ }
+
+ public void add(Interceptor i, boolean force) {
+ PhaseInterceptor pi = (PhaseInterceptor)i;
+
+ String phaseName = pi.getPhase();
+ Integer phase = nameMap.get(phaseName);
+
+ if (phase == null) {
+ LOG.fine("Skipping interceptor " + i.getClass().getName()
+ + ((phaseName == null) ? ": Phase declaration is missing."
+ : ": Phase " + phaseName + " specified does not exist."));
+ } else {
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Adding interceptor " + i + " to phase " + phaseName);
+ }
+
+ insertInterceptor(phase, pi, force);
+ }
+ }
+
+
+ public synchronized void pause() {
+ state = State.PAUSED;
+ }
+
+ public synchronized void resume() {
+ if (state == State.PAUSED) {
+ state = State.EXECUTING;
+ doIntercept(pausedMessage);
+ }
+ }
+
+ /**
+ * Intercept a message, invoking each phase's handlers in turn.
+ *
+ * @param message the message
+ * @throws Exception
+ */
+ @SuppressWarnings("unchecked")
+ public synchronized boolean doIntercept(Message message) {
+ updateIterator();
+ boolean isFineLogging = LOG.isLoggable(Level.FINE);
+ pausedMessage = message;
+ while (state == State.EXECUTING && iterator.hasNext()) {
+ try {
+ Interceptor currentInterceptor = iterator.next();
+ if (isFineLogging) {
+ LOG.fine("Invoking handleMessage on interceptor " + currentInterceptor);
+ }
+ //System.out.println("-----------" + currentInterceptor);
+ currentInterceptor.handleMessage(message);
+ } catch (SuspendedInvocationException ex) {
+ // we need to resume from the same interceptor the exception got originated from
+ if (iterator.hasPrevious()) {
+ iterator.previous();
+ }
+ pause();
+ throw ex;
+ } catch (RuntimeException ex) {
+ if (!faultOccurred) {
+
+ faultOccurred = true;
+
+ FaultMode mode = message.get(FaultMode.class);
+ if (mode == FaultMode.CHECKED_APPLICATION_FAULT) {
+ if (LOG.isLoggable(Level.FINE)) {
+ LogUtils.log(LOG, Level.FINE,
+ "Application has thrown exception, unwinding now", ex);
+ } else if (LOG.isLoggable(Level.INFO)) {
+ Throwable t = ex;
+ if (ex instanceof Fault
+ && ex.getCause() != null) {
+ t = ex.getCause();
+ }
+
+ LogUtils.log(LOG, Level.INFO,
+ "Application has thrown exception, unwinding now: "
+ + t.getClass().getName()
+ + ": " + ex.getMessage());
+ }
+ } else if (LOG.isLoggable(Level.INFO)) {
+ if (mode == FaultMode.UNCHECKED_APPLICATION_FAULT) {
+ LogUtils.log(LOG, Level.INFO,
+ "Application has thrown exception, unwinding now", ex);
+ } else {
+ LogUtils.log(LOG, Level.INFO,
+ "Interceptor has thrown exception, unwinding now", ex);
+ }
+ }
+
+ message.setContent(Exception.class, ex);
+ if (message.getExchange() != null) {
+ message.getExchange().put(Exception.class, ex);
+ }
+ unwind(message);
+
+ if (faultObserver != null) {
+ faultObserver.onMessage(message);
+ }
+ }
+ state = State.ABORTED;
+ }
+ }
+ if (state == State.EXECUTING) {
+ state = State.COMPLETE;
+ pausedMessage = null;
+ }
+ return state == State.COMPLETE;
+ }
+
+ /**
+ * Intercept a message, invoking each phase's handlers in turn,
+ * starting after the specified interceptor.
+ *
+ * @param message the message
+ * @param startingAfterInterceptorID the id of the interceptor
+ * @throws Exception
+ */
+ public synchronized boolean doInterceptStartingAfter(Message message,
+ String startingAfterInterceptorID) {
+ updateIterator();
+ while (state == State.EXECUTING && iterator.hasNext()) {
+ PhaseInterceptor currentInterceptor = (PhaseInterceptor)iterator.next();
+ if (currentInterceptor.getId().equals(startingAfterInterceptorID)) {
+ break;
+ }
+ }
+ return doIntercept(message);
+ }
+
+ /**
+ * Intercept a message, invoking each phase's handlers in turn,
+ * starting at the specified interceptor.
+ *
+ * @param message the message
+ * @param startingAtInterceptorID the id of the interceptor
+ * @throws Exception
+ */
+ public synchronized boolean doInterceptStartingAt(Message message,
+ String startingAtInterceptorID) {
+ updateIterator();
+ while (state == State.EXECUTING && iterator.hasNext()) {
+ PhaseInterceptor currentInterceptor = (PhaseInterceptor)iterator.next();
+ if (currentInterceptor.getId().equals(startingAtInterceptorID)) {
+ iterator.previous();
+ break;
+ }
+ }
+ return doIntercept(message);
+ }
+
+ public synchronized void reset() {
+ updateIterator();
+ if (state == State.COMPLETE) {
+ state = State.EXECUTING;
+ iterator.reset();
+ } else {
+ iterator.reset();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void unwind(Message message) {
+ boolean isFineLogging = LOG.isLoggable(Level.FINE);
+ while (iterator.hasPrevious()) {
+ Interceptor currentInterceptor = iterator.previous();
+ if (isFineLogging) {
+ LOG.fine("Invoking handleFault on interceptor " + currentInterceptor);
+ }
+ currentInterceptor.handleFault(message);
+ }
+ }
+
+ public void remove(Interceptor i) {
+ PhaseInterceptorIterator it = new PhaseInterceptorIterator(heads);
+ while (it.hasNext()) {
+ InterceptorHolder holder = it.nextInterceptorHolder();
+ if (holder.interceptor == i) {
+ remove(holder);
+ return;
+ }
+ }
+ }
+
+ public synchronized void abort() {
+ this.state = InterceptorChain.State.ABORTED;
+ }
+
+ public Iterator<Interceptor<? extends Message>> iterator() {
+ return getIterator();
+ }
+ public ListIterator<Interceptor<? extends Message>> getIterator() {
+ return new PhaseInterceptorIterator(heads);
+ }
+
+ private void remove(InterceptorHolder i) {
+ if (i.prev != null) {
+ i.prev.next = i.next;
+ }
+ if (i.next != null) {
+ i.next.prev = i.prev;
+ }
+ int ph = i.phaseIdx;
+ if (heads[ph] == i) {
+ if (i.next != null
+ && i.next.phaseIdx == ph) {
+ heads[ph] = i.next;
+ } else {
+ heads[ph] = null;
+ tails[ph] = null;
+ }
+ }
+ if (tails[ph] == i) {
+ if (i.prev != null
+ && i.prev.phaseIdx == ph) {
+ tails[ph] = i.prev;
+ } else {
+ heads[ph] = null;
+ tails[ph] = null;
+ }
+ }
+ }
+
+ private void insertInterceptor(int phase, PhaseInterceptor interc, boolean force) {
+ InterceptorHolder ih = new InterceptorHolder(interc, phase);
+ if (heads[phase] == null) {
+ // no interceptors yet in this phase
+ heads[phase] = ih;
+ tails[phase] = ih;
+ hasAfters[phase] = !interc.getAfter().isEmpty();
+
+ int idx = phase - 1;
+ while (idx >= 0) {
+ if (tails[idx] != null) {
+ break;
+ }
+ --idx;
+ }
+ if (idx >= 0) {
+ //found something before us, in an earlier phase
+ ih.prev = tails[idx];
+ ih.next = tails[idx].next;
+ if (ih.next != null) {
+ ih.next.prev = ih;
+ }
+ tails[idx].next = ih;
+ } else {
+ //did not find something before us, try after
+ idx = phase + 1;
+ while (idx < heads.length) {
+ if (heads[idx] != null) {
+ break;
+ }
+ ++idx;
+ }
+
+ if (idx != heads.length) {
+ //found something after us
+ ih.next = heads[idx];
+ heads[idx].prev = ih;
+ }
+ }
+ } else { // this phase already has interceptors attached
+
+ // list of interceptors that the new interceptor should precede
+ Set beforeList = interc.getBefore();
+
+ // list of interceptors that the new interceptor should be after
+ Set afterList = interc.getAfter();
+
+ // firstBefore will hold the first interceptor of a given phase
+ // that the interceptor to be added must precede
+ InterceptorHolder firstBefore = null;
+
+ // lastAfter will hold the last interceptor of a given phase
+ // that the interceptor to be added must come after
+ InterceptorHolder lastAfter = null;
+
+ String id = interc.getId();
+ if (hasAfters[phase] || !beforeList.isEmpty()) {
+
+ InterceptorHolder ih2 = heads[phase];
+ while (ih2 != tails[phase].next) {
+ PhaseInterceptor cmp = ih2.interceptor;
+ String cmpId = cmp.getId();
+ if (cmpId != null && firstBefore == null
+ && (beforeList.contains(cmpId)
+ || cmp.getAfter().contains(id))) {
+ firstBefore = ih2;
+ }
+ if (cmpId != null && afterList.contains(cmpId)) {
+ lastAfter = ih2;
+ }
+ if (!force && cmpId.equals(id)) {
+ // interceptor is already in chain
+ return;
+ }
+ ih2 = ih2.next;
+ }
+ if (lastAfter == null && beforeList.contains("*")) {
+ firstBefore = heads[phase];
+ }
+ //System.out.print("Didn't skip: " + phase.toString());
+ //System.out.println(" " + interc.getId());
+ } else if (!force) {
+ // skip interceptor if already in chain
+ InterceptorHolder ih2 = heads[phase];
+ while (ih2 != tails[phase].next) {
+ if (ih2.interceptor.getId().equals(id)) {
+ return;
+ }
+ ih2 = ih2.next;
+ }
+
+ //System.out.print("Skipped: " + phase.toString());
+ //System.out.println(" " + interc.getId());
+ }
+ hasAfters[phase] |= !afterList.isEmpty();
+
+ if (firstBefore == null) {
+ //just add new interceptor at the end
+ ih.prev = tails[phase];
+ ih.next = tails[phase].next;
+ tails[phase].next = ih;
+
+ if (ih.next != null) {
+ ih.next.prev = ih;
+ }
+ tails[phase] = ih;
+ } else {
+ ih.prev = firstBefore.prev;
+ if (ih.prev != null) {
+ ih.prev.next = ih;
+ }
+ ih.next = firstBefore;
+ firstBefore.prev = ih;
+
+ if (heads[phase] == firstBefore) {
+ heads[phase] = ih;
+ }
+ }
+ }
+ if (iterator != null) {
+ outputChainToLog(true);
+ }
+ }
+
+ public String toString() {
+ return toString("");
+ }
+ private String toString(String message) {
+ StringBuilder chain = new StringBuilder();
+
+ chain.append("Chain ")
+ .append(super.toString())
+ .append(message)
+ .append(". Current flow:\n");
+
+ for (int x = 0; x < phases.length; x++) {
+ if (heads[x] != null) {
+ chain.append(" ");
+ printPhase(x, chain);
+ }
+ }
+ return chain.toString();
+ }
+ private void printPhase(int ph, StringBuilder chain) {
+
+ chain.append(phases[ph].getName())
+ .append(" [");
+ InterceptorHolder i = heads[ph];
+ boolean first = true;
+ while (i != tails[ph].next) {
+ if (first) {
+ first = false;
+ } else {
+ chain.append(", ");
+ }
+ chain.append(i.interceptor.getClass().getSimpleName());
+ i = i.next;
+ }
+ chain.append("]\n");
+ }
+
+ private void outputChainToLog(boolean modified) {
+ if (LOG.isLoggable(Level.FINE)) {
+ if (modified) {
+ LOG.fine(toString(" was modified"));
+ } else {
+ LOG.fine(toString(" was created"));
+ }
+ }
+ }
+
+ public MessageObserver getFaultObserver() {
+ return faultObserver;
+ }
+
+ public void setFaultObserver(MessageObserver faultObserver) {
+ this.faultObserver = faultObserver;
+ }
+
+ static final class PhaseInterceptorIterator implements ListIterator<Interceptor<? extends Message>> {
+ InterceptorHolder heads[];
+ InterceptorHolder prev;
+ InterceptorHolder first;
+
+ public PhaseInterceptorIterator(InterceptorHolder h[]) {
+ heads = h;
+ first = findFirst();
+ }
+
+ public void reset() {
+ prev = null;
+ first = findFirst();
+ }
+
+ private InterceptorHolder findFirst() {
+ for (int x = 0; x < heads.length; x++) {
+ if (heads[x] != null) {
+ return heads[x];
+ }
+ }
+ return null;
+ }
+
+
+ public boolean hasNext() {
+ if (prev == null) {
+ return first != null;
+ }
+ return prev.next != null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Interceptor<? extends Message> next() {
+ if (prev == null) {
+ if (first == null) {
+ throw new NoSuchElementException();
+ }
+ prev = first;
+ } else {
+ if (prev.next == null) {
+ throw new NoSuchElementException();
+ }
+ prev = prev.next;
+ }
+ return prev.interceptor;
+ }
+ public InterceptorHolder nextInterceptorHolder() {
+ if (prev == null) {
+ if (first == null) {
+ throw new NoSuchElementException();
+ }
+ prev = first;
+ } else {
+ if (prev.next == null) {
+ throw new NoSuchElementException();
+ }
+ prev = prev.next;
+ }
+ return prev;
+ }
+
+ public boolean hasPrevious() {
+ return prev != null;
+ }
+ @SuppressWarnings("unchecked")
+ public Interceptor<? extends Message> previous() {
+ if (prev == null) {
+ throw new NoSuchElementException();
+ }
+ InterceptorHolder tmp = prev;
+ prev = prev.prev;
+ return tmp.interceptor;
+ }
+
+ public int nextIndex() {
+ throw new UnsupportedOperationException();
+ }
+ public int previousIndex() {
+ throw new UnsupportedOperationException();
+ }
+ public void add(Interceptor o) {
+ throw new UnsupportedOperationException();
+ }
+ public void set(Interceptor o) {
+ throw new UnsupportedOperationException();
+ }
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
+ static final class InterceptorHolder {
+ PhaseInterceptor interceptor;
+ InterceptorHolder next;
+ InterceptorHolder prev;
+ int phaseIdx;
+
+ InterceptorHolder(PhaseInterceptor i, int p) {
+ interceptor = i;
+ phaseIdx = p;
+ }
+ InterceptorHolder(InterceptorHolder p) {
+ interceptor = p.interceptor;
+ phaseIdx = p.phaseIdx;
+ }
+ }
+
+}
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseInterceptorChain.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseManager.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseManager.java?rev=713358&view=auto
==============================================================================
--- cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseManager.java (added)
+++ cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseManager.java Wed Nov 12 04:49:56 2008
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.phase;
+
+import java.util.SortedSet;
+
+public interface PhaseManager {
+ SortedSet<Phase> getInPhases();
+
+ SortedSet<Phase> getOutPhases();
+}
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/PhaseManager.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/package.html
URL: http://svn.apache.org/viewvc/cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/package.html?rev=713358&view=auto
==============================================================================
--- cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/package.html (added)
+++ cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/package.html Wed Nov 12 04:49:56 2008
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+</head>
+<body bgcolor="white">
+
+An InterceptorChain implementation which uses the concept of
+Phases to order message chains.
+
+</body>
+</html>
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/package.html
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/package.html
------------------------------------------------------------------------------
svn:keywords = Rev Date
Propchange: cxf/sandbox/2.2.x-continuations/api/src/main/java/org/apache/cxf/phase/package.html
------------------------------------------------------------------------------
svn:mime-type = text/html