Author: gdaniels Date: Sun Dec 30 20:33:22 2007 New Revision: 607662 URL: http://svn.apache.org/viewvc?rev=607662&view=rev Log: Reimplementing dynamic phases, part 1. This is a slightly more architectural approach.
* A Deployable is something that fits into a DeployableChain in an ordered fashion. Each Deployable has a name, and may be marked "first", "last", and/or may have a list of "successor" names (indicating other deployables). Each Deployable also contains a "target" which is the real thing (i.e. a Phase or a Handler) that wants to be ordered. * A DeployableChain represents an ordered list of Deployables, which are inserted with the deploy() method - some basic consistency checking happens then, but the actual complete order is not calculated until rebuild() is called, at which time all the existing constraints are walked and a complete chain is built. After rebuild(), the getChain() API will return an ordered list of the targets. * Some tests for the above. * Hook up the dynamic phase mechanism for module.xml using the above code. This enables multiple befores and afters (i.e. before="foo,bar") and multiple deployments (in different modules, say) of a given new phase. * Few small fixes in testDynamicPhase() Next steps: - More tests! - Improve JavaDoc a bit. - Explore revamping the PhaseRule stuff to use this technique as well (within a Phase), which will allow for more flexible handler deployment and clean-up/unify some code. Added: webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Deployable.java webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/DeployableChain.java webservices/axis2/trunk/java/modules/kernel/test/org/apache/axis2/engine/DeployableChainTest.java Modified: webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/deployment/ModuleBuilder.java webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/AxisConfiguration.java webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/phaseresolver/PhaseHolder.java webservices/axis2/trunk/java/modules/kernel/test/org/apache/axis2/deployment/DeploymentTotalTest.java Modified: webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/deployment/ModuleBuilder.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/deployment/ModuleBuilder.java?rev=607662&r1=607661&r2=607662&view=diff ============================================================================== --- webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/deployment/ModuleBuilder.java (original) +++ webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/deployment/ModuleBuilder.java Sun Dec 30 20:33:22 2007 @@ -28,6 +28,7 @@ import org.apache.axis2.description.*; import org.apache.axis2.engine.AxisConfiguration; import org.apache.axis2.engine.MessageReceiver; +import org.apache.axis2.engine.Deployable; import org.apache.axis2.i18n.Messages; import org.apache.axis2.java.security.AccessController; import org.apache.axis2.modules.Module; @@ -297,7 +298,7 @@ // processing <wsp:PolicyReference> .. </..> elements Iterator policyRefElements = operation.getChildrenWithName(new QName(POLICY_NS_URI, TAG_POLICY_REF)); - if (policyRefElements != null && policyElements.hasNext()) { + if (policyRefElements != null && policyRefElements.hasNext()) { processPolicyRefElements(PolicyInclude.AXIS_MODULE_OPERATION_POLICY, policyRefElements, module.getPolicyInclude()); } @@ -333,22 +334,38 @@ while (phases.hasNext()) { OMElement element = (OMElement) phases.next(); String phaseName = element.getAttributeValue(new QName(ATTRIBUTE_NAME)); + + Deployable d = new Deployable(phaseName); String after = element.getAttributeValue(new QName(TAG_AFTER)); + if (after != null) { + String [] afters = after.split(","); + for (int i = 0; i < afters.length; i++) { + String s = afters[i]; + d.addPredecessor(s); + } + } String before = element.getAttributeValue(new QName(TAG_BEFORE)); + if (before != null) { + String [] befores = before.split(","); + for (int i = 0; i < befores.length; i++) { + String s = befores[i]; + d.addSuccessor(s); + } + } String flowName = element.getAttributeValue(new QName("flow")); - int flowInex ; + int flowIndex ; if (TAG_FLOW_IN.equals(flowName)){ - flowInex = PhaseMetadata.IN_FLOW ; + flowIndex = PhaseMetadata.IN_FLOW ; } else if (TAG_FLOW_OUT.equals(flowName)) { - flowInex = PhaseMetadata.OUT_FLOW ; + flowIndex = PhaseMetadata.OUT_FLOW ; } else if (TAG_FLOW_OUT_FAULT.equals(flowName)) { - flowInex = PhaseMetadata.FAULT_OUT_FLOW; + flowIndex = PhaseMetadata.FAULT_OUT_FLOW; } else if (TAG_FLOW_IN_FAULT.equals(flowName)) { - flowInex = PhaseMetadata.FAULT_IN_FLOW; + flowIndex = PhaseMetadata.FAULT_IN_FLOW; } else { throw new DeploymentException(" Flow can not be null for the phase name " + phaseName); } - axisConfig.insertPhase(phaseName,before,after,flowInex); + axisConfig.insertPhase(d, flowIndex); } } } Modified: webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/AxisConfiguration.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/AxisConfiguration.java?rev=607662&r1=607661&r2=607662&view=diff ============================================================================== --- webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/AxisConfiguration.java (original) +++ webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/AxisConfiguration.java Sun Dec 30 20:33:22 2007 @@ -1122,48 +1122,42 @@ * 3 - fault in flow * 4 - fault out flow * - * @param phaseName : Not null parameter , specifying the phase name - * @param beforePhase : can be null , will tell the name of before phase - * @param afterPhase : Can be null and will tell the name of after phase - * @param flow : Type of the flow + * @param d the Deployable representing the Phase to deploy + * @param flow the type of the flow * @throws org.apache.axis2.AxisFault : If something went wrong */ - public void insertPhase(String phaseName , - String beforePhase, - String afterPhase , - int flow) throws AxisFault { - + public void insertPhase(Deployable d, int flow) throws AxisFault { switch (flow) { case PhaseMetadata.IN_FLOW : { - ArrayList phaseList = phasesinfo.getINPhases(); - phaseList = findAndInsertPhase(beforePhase, phaseList, afterPhase, phaseName); + List phaseList = phasesinfo.getINPhases(); + phaseList = findAndInsertPhase(d, phaseList); if (phaseList != null) { - phasesinfo.setINPhases(phaseList); + phasesinfo.setINPhases((ArrayList)phaseList); } break; } case PhaseMetadata.OUT_FLOW : { - ArrayList phaseList = phasesinfo.getOUTPhases(); - phaseList = findAndInsertPhase(beforePhase, phaseList, afterPhase, phaseName); + List phaseList = phasesinfo.getOUTPhases(); + phaseList = findAndInsertPhase(d, phaseList); if (phaseList != null) { - phasesinfo.setOUTPhases(phaseList); + phasesinfo.setOUTPhases((ArrayList)phaseList); } break; } case PhaseMetadata.FAULT_OUT_FLOW : { - ArrayList phaseList = phasesinfo.getOutFaultPhaseList(); - phaseList = findAndInsertPhase(beforePhase, phaseList, afterPhase, phaseName); + List phaseList = phasesinfo.getOutFaultPhaseList(); + phaseList = findAndInsertPhase(d, phaseList); if (phaseList != null) { - phasesinfo.setOUT_FaultPhases(phaseList); + phasesinfo.setOUT_FaultPhases((ArrayList)phaseList); } break; } case PhaseMetadata.FAULT_IN_FLOW : { - ArrayList phaseList = phasesinfo.getIN_FaultPhases(); - phaseList = findAndInsertPhase(beforePhase, phaseList, afterPhase, phaseName); + List phaseList = phasesinfo.getIN_FaultPhases(); + phaseList = findAndInsertPhase(d, phaseList); if (phaseList != null) { - phasesinfo.setIN_FaultPhases(phaseList); + phasesinfo.setIN_FaultPhases((ArrayList)phaseList); } break; } @@ -1171,63 +1165,45 @@ } /** - * This method will added a given phase into the location specified by the phase before - * and phase after. If given phase are not found then an exception will be thrown. - * @param beforePhase : Name of the before phase - * @param phaseList : ArrayList of phase - * @param afterPhase : Name of the after phase - * @param phaseName : name of the phase we need to add - * @throws AxisFault : If something went wrong - * @return : Modified list + * Insert a Phase + * @param d + * @param phaseList + * @return + * @throws AxisFault */ - private ArrayList findAndInsertPhase(String beforePhase, - ArrayList phaseList, - String afterPhase, - String phaseName) throws AxisFault { - int beforeIndex = -1; - int afterIndex = -1; - for (int i = 0; i < phaseList.size(); i++) { - Phase phase = (Phase) phaseList.get(i); - if (phase.getPhaseName().equals(beforePhase)) { - beforeIndex = i; - } else if (phase.getPhaseName().equals(afterPhase)){ - afterIndex = i; - } else if (phase.getPhaseName().equals(phaseName)){ - return null; + private List findAndInsertPhase(Deployable d, List phaseList) throws AxisFault { + DeployableChain ec = new DeployableChain(); + String last = null; + for (Iterator i = phaseList.iterator(); i.hasNext();) { + Phase phase = (Phase)i.next(); + String name = phase.getName(); + Deployable existing = new Deployable(name); + existing.setTarget(phase); + if (last != null) { + // Set up explicit chain relationship for preexisting phases, for now. + ec.addRelationship(last, name); + } + last = name; + try { + ec.deploy(existing); + } catch (Exception e) { + // This should never happen when building a simple list like the above + throw AxisFault.makeFault(e); } } - if (beforeIndex == -1 && afterIndex == -1) { - throw new AxisFault("Trying to add a phase " + phaseName + " before " - + beforePhase + " and after " + afterPhase + " but none of the phases " + - "found in the system please refer to axis2.xml for available phases"); - } - - if (afterIndex > beforeIndex) { - throw new AxisFault("Trying to add a phase " + phaseName + " before " - + beforePhase + " and after " + afterPhase + " phase order is invalid , " + - "please refer axis2.xml for the correct phase order"); - } Phase phase = new Phase(); - phase.setName(phaseName); - if (beforeIndex == -1){ - if (afterIndex == phaseList.size() -1) { - // Need to add to the last phase since the after phase is the - // last phase in the system - phaseList.add(phase); - } else { - phaseList.add(afterIndex, phase); - } - } else if (afterIndex == -1) { - if (beforeIndex == 0) { - // Need to add to the first place of the phase since the before - // phase index is 0 - phaseList.add(0, phase); - } else { - phaseList.add(beforeIndex, phase); - } - } else { - phaseList.add(afterIndex, phase); + phase.setName(d.getName()); + d.setTarget(phase); + + try { + ec.deploy(d); + ec.rebuild(); + } catch (Exception e) { + throw AxisFault.makeFault(e); } + + phaseList = ec.getChain(); + return phaseList; } } Added: webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Deployable.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Deployable.java?rev=607662&view=auto ============================================================================== --- webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Deployable.java (added) +++ webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/Deployable.java Sun Dec 30 20:33:22 2007 @@ -0,0 +1,107 @@ +/* + * 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.axis2.engine; + +import java.util.HashSet; +import java.util.Set; + +/** + * A Deployable is a container for something (Phases, Handlers) which wants + * to be deployed in an ordered and constrained fashion via a + * DeployableChain. + */ +public class Deployable { + private String name; + private String phase; + private Set successors; + private Set predecessors; + + boolean first; + boolean last; + + Object target; + + public Deployable(String name) { + this.name = name; + } + + public Deployable(String name, Object target) { + this.name = name; + this.target = target; + } + + public String getName() { + return name; + } + + public void addSuccessor(String name) { + if (successors == null) { + successors = new HashSet(); + } + successors.add(name); + } + + public void addPredecessor(String name) { + if (predecessors == null) { + predecessors = new HashSet(); + } + predecessors.add(name); + } + + public Set getPredecessors() { + return predecessors; + } + + public Set getSuccessors() { + return successors; + } + + public String getPhase() { + return phase; + } + + public void setPhase(String phase) { + this.phase = phase; + } + + public boolean isFirst() { + return first; + } + + public void setFirst(boolean first) { + this.first = first; + } + + public boolean isLast() { + return last; + } + + public void setLast(boolean last) { + this.last = last; + } + + public void setTarget(Object target) { + this.target = target; + } + + public Object getTarget() { + return target; + } +} Added: webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/DeployableChain.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/DeployableChain.java?rev=607662&view=auto ============================================================================== --- webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/DeployableChain.java (added) +++ webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/engine/DeployableChain.java Sun Dec 30 20:33:22 2007 @@ -0,0 +1,243 @@ +/* + * 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.axis2.engine; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.Collection; +import java.util.Set; +import java.util.HashSet; +import java.util.Iterator; + +public class DeployableChain { + /** The actual things (handlers or phases) */ + List chain = new ArrayList(); + + Deployable first; + Deployable last; + + Map activeConstraints = new HashMap(); + private Map deployed = new HashMap(); + + Map activePhaseConstraints = new HashMap(); + + /** + * Deploy a Deployable into this chain. Note that this does NOT order yet. The idea + * is to deploy everything first, then call rebuild() to generate the fully ordered chain. + * This method will validate the Deployable, including confirming that it's compatible with + * any previously deployed item of the same name. + * + * @param deployable Deployable to deploy. + * @throws Exception if there is a deployment error. + */ + public void deploy(Deployable deployable) throws Exception { + String name = deployable.getName(); + + if (deployable.isFirst()) { + if (first != null) { + throw new Exception("'" + first.getName() + "' is already first, can't deploy '" + + name + "' as first also."); + } + first = deployable; + } + + if (deployable.isLast()) { + if (last != null) { + throw new Exception("'" + last.getName() + "' is already last, can't deploy '" + + name + "' as last also."); + } + last = deployable; + } + + // Now check internal consistency + Set mySuccessors = deployable.getSuccessors(); + Set myPredecessors = deployable.getPredecessors(); + + if (mySuccessors != null && deployable.isLast()) { + throw new Exception("Deploying '" + name + + "' - can't both be last and have successors!"); + } + if (myPredecessors != null && deployable.isFirst()) { + throw new Exception("Deploying '" + name + + "' - can't both be first and have predecessors!"); + } + + Deployable previous = (Deployable)deployed.get(name); + if (previous == null) { + deployed.put(name, deployable); + } else { + // If something by this name already exists, ensure it's compatible + if (previous.isFirst() != deployable.isFirst()) { + throw new Exception(); + } + if (previous.isLast() != deployable.isLast()) { + throw new Exception(); + } + Object target = previous.getTarget(); + if (target != null) { + if (deployable.getTarget() != null && !target.equals(deployable.getTarget())) { + throw new Exception(); + } + } else { + previous.setTarget(deployable.getTarget()); + } + } + + if (mySuccessors != null && !mySuccessors.isEmpty()) { + Set successors = (Set)activeConstraints.get(name); + if (successors == null) { + successors = new HashSet(); + activeConstraints.put(name, successors); + } + successors.addAll(mySuccessors); + } + + if (myPredecessors != null) { + for (Iterator i = myPredecessors.iterator(); i.hasNext();) { + String predecessor = (String)i.next(); + // define relationship for each one + addRelationship(predecessor, name); + } + } + } + + /** + * Find the correct (minimum) index for a given name. Finds the active constraints + * for the name, then walks that list, making sure that each one is already placed. + * If a given successor isn't yet placed, we recursively call this method to place it, + * passing a set of "what's left to do" and a set of "what we've seen". + * + * This results in chain containing the names (Strings). + * + * TODO: investigate optimizing this algorithm a bit + * + * @param name the target deployable's name + * @param remaining a Set of the names of things we have yet to deploy + * @param seen a Set of the names of things we've already seen (to detect loops) + * @return an index >=0 or -1 if there was a dependency cycle + * @throws Exception if there's a cyclic dependency + */ + private int getMinIndex(String name, Set remaining, Set seen) throws Exception { + if (seen.contains(name)) { + // We return -1 here instead of throwing the Exception so we can build a better + // error message below. + return -1; + } + + Collection successors = (Collection)activeConstraints.get(name); + if (successors == null || successors.isEmpty()) { + // Never put anything after the thing marked "last"... + int index = (last == null) ? chain.size() : chain.size() - 1; + chain.add(index, name); + remaining.remove(name); + return index; + } + + int minIndex = -1; + for (Iterator i = successors.iterator(); i.hasNext();) { + String otherName = (String)i.next(); + int otherIdx = chain.indexOf(otherName); + if (otherIdx > -1) { + if ((minIndex == -1) || (minIndex > otherIdx)) { + minIndex = otherIdx; + } + } else { + // This guy isn't in our list yet - put him in IF he's real (exists in + // the deployed list) and we haven't already placed him (exists in + // the remaining set). + if ((deployed.get(otherName) != null) && remaining.contains(otherName)) { + seen.add(name); + // Not in list yet, go place it + int min = getMinIndex(otherName, remaining, seen); + if (minIndex == -1 || min < minIndex) { + minIndex = min; + } + if (minIndex == -1) { + throw new Exception("Trying to put '" + name + "' before '" + + otherName + "' - incompatible constraints!"); + } + } + } + } + + if (minIndex == -1) minIndex = 0; + + chain.add(minIndex, name); + remaining.remove(name); + + return minIndex; + } + + /** + * Taking into account all the active constraints, order the list. This blows + * away the old order. Could improve this slightly with a "dirty" flag. + * + * @throws Exception if there's an ordering conflict + */ + public void rebuild() throws Exception { + chain.clear(); + + Set keys = new HashSet(); + keys.addAll(deployed.keySet()); + + // First goes first. + if (first != null) { + chain.add(first.getName()); + keys.remove(first.getName()); + } + + // Last goes next, and everything else will get inserted before it if it exists. + if (last != null) { + Collection afterLast = (Collection)activeConstraints.get(last.getName()); + if (afterLast != null) { + throw new Exception("Can't have anything which goes after '" + last.getName() + + "', which has been declared last."); + } + chain.add(last.getName()); + keys.remove(last.getName()); + } + + while (!keys.isEmpty()) { + String name = (String)keys.iterator().next(); + getMinIndex(name, keys, new HashSet()); + } + + // Now we've got a chain of names. Convert to actual things before we return. + for (int i = 0; i < chain.size(); i++) { + String name = (String)chain.get(i); + chain.set(i, ((Deployable)deployed.get(name)).getTarget()); + } + } + + public void addRelationship(String before, String after) { + Set successors = (Set)activeConstraints.get(before); + if (successors == null) { + successors = new HashSet(); + activeConstraints.put(before, successors); + } + successors.add(after); + } + + public List getChain() { + return chain; + } +} Modified: webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/phaseresolver/PhaseHolder.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/phaseresolver/PhaseHolder.java?rev=607662&r1=607661&r2=607662&view=diff ============================================================================== --- webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/phaseresolver/PhaseHolder.java (original) +++ webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/phaseresolver/PhaseHolder.java Sun Dec 30 20:33:22 2007 @@ -26,7 +26,6 @@ import org.apache.axis2.engine.Phase; import org.apache.axis2.i18n.Messages; -import java.util.ArrayList; import java.util.List; /** @@ -45,15 +44,15 @@ /** * If the phase name is equal to "*" that implies , the handler should be * added to each and every phase in the system for a given flow , and at that - * point if the phase rule contains any before or aftere then they will be + * point if the phase rule contains any befores or afters then they will be * ignored. Phase first and phase last are supported , but make sure you dont * break any of the phase rules. * <p/> * If the phase name is not above then the hadler will be added to the phase * specified by the phase rule , and no rules will be ignored. * - * @param handlerDesc - * @throws PhaseException + * @param handlerDesc HandlerDescription to deploy + * @throws PhaseException if there's a problem */ public void addHandler(HandlerDescription handlerDesc) throws PhaseException { PhaseRule rule = handlerDesc.getRules(); @@ -82,7 +81,8 @@ /** * this method is used to get the actual phase object given in the phase array list * - * @param phaseName + * @param phaseName the name of the desired Phase + * @return the matching Phase, or null */ private Phase getPhase(String phaseName) { for (int i = 0; i < phaseList.size(); i++) { Modified: webservices/axis2/trunk/java/modules/kernel/test/org/apache/axis2/deployment/DeploymentTotalTest.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/test/org/apache/axis2/deployment/DeploymentTotalTest.java?rev=607662&r1=607661&r2=607662&view=diff ============================================================================== --- webservices/axis2/trunk/java/modules/kernel/test/org/apache/axis2/deployment/DeploymentTotalTest.java (original) +++ webservices/axis2/trunk/java/modules/kernel/test/org/apache/axis2/deployment/DeploymentTotalTest.java Sun Dec 30 20:33:22 2007 @@ -50,26 +50,24 @@ public void testDynamicPhase() { ArrayList inFlow = er.getInFlowPhases(); - boolean found = false; int index = 0; for (int i = 0; i < inFlow.size(); i++) { Phase phase = (Phase) inFlow.get(i); if (phase.getName().equals("NewPhase")) { - found = true; index = i; } } - assertEquals("Phase has insert into a wrong location" ,index,3); - assertTrue("Problem in Dynamic Phases for Inflow", found); + assertEquals("Wrong index for NewPhase!", 3, index); + inFlow = er.getInFaultFlowPhases(); - found = false; + boolean found = false; for (int i = 0; i < inFlow.size(); i++) { Phase phase = (Phase) inFlow.get(i); if (phase.getName().equals("NewPhase")) { found = true; } } - assertTrue("Problem in Dynamic Phases for InFaultflow", found); + assertTrue("NewPhase wasn't found in InFaultFlow", found); } } Added: webservices/axis2/trunk/java/modules/kernel/test/org/apache/axis2/engine/DeployableChainTest.java URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/test/org/apache/axis2/engine/DeployableChainTest.java?rev=607662&view=auto ============================================================================== --- webservices/axis2/trunk/java/modules/kernel/test/org/apache/axis2/engine/DeployableChainTest.java (added) +++ webservices/axis2/trunk/java/modules/kernel/test/org/apache/axis2/engine/DeployableChainTest.java Sun Dec 30 20:33:22 2007 @@ -0,0 +1,102 @@ +/* + * 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.axis2.engine; + +import junit.framework.TestCase; + +import java.util.List; + +public class DeployableChainTest extends TestCase { + static final Object A_TARGET = new Object(); + static final Object B_TARGET = new Object(); + static final Object C_TARGET = new Object(); + static final Object D_TARGET = new Object(); + static final Object E_TARGET = new Object(); + + private Deployable a; + private Deployable b; + private Deployable c; + private Deployable d; + private Deployable e; + DeployableChain ec; + + protected void setUp() throws Exception { + a = new Deployable("a", A_TARGET); + b = new Deployable("b", B_TARGET); + c = new Deployable("c", C_TARGET); + d = new Deployable("d", D_TARGET); + e = new Deployable("e", E_TARGET); + ec = new DeployableChain(); + } + + public void testDuplicateDeploy() throws Exception { + a.addSuccessor("b"); + ec.deploy(a); + + // Should be ok to do this again as long as everything matches. + ec.deploy(a); + } + + public void testOrdering() throws Exception { + a.addSuccessor("b"); + ec.deploy(b); + ec.deploy(a); + ec.rebuild(); + List chain = ec.getChain(); + assertEquals("Wrong number of items", 2, chain.size()); + assertEquals("Wrong order", A_TARGET, chain.get(0)); + + ec.addRelationship("b", "a"); + boolean caught = false; + try { + ec.rebuild(); + } catch (Exception e1) { + // Expected Exception, yay! + caught = true; + } + if (!caught) fail("Didn't catch exception for cyclic dependency"); + + ec = new DeployableChain(); + b.addSuccessor("c"); + d.addSuccessor("e"); + e.addPredecessor("b"); + + e.setLast(true); + + ec.deploy(b); + ec.deploy(a); + ec.deploy(c); + ec.deploy(d); + ec.deploy(e); + ec.rebuild(); + chain = ec.getChain(); + + assertEquals("Wrong number of items", 5, chain.size()); + int aIndex = chain.indexOf(A_TARGET); + int bIndex = chain.indexOf(B_TARGET); + int cIndex = chain.indexOf(C_TARGET); + int dIndex = chain.indexOf(D_TARGET); + int eIndex = chain.indexOf(E_TARGET); + assertTrue(aIndex < bIndex); + assertTrue(bIndex < cIndex); + assertTrue(dIndex < eIndex); + assertTrue(bIndex < eIndex); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]