You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@synapse.apache.org by hi...@apache.org on 2010/08/27 07:06:24 UTC

svn commit: r990019 - in /synapse/trunk/java/modules/core/src: main/java/org/apache/synapse/config/xml/ main/java/org/apache/synapse/mediators/transform/url/ test/java/org/apache/synapse/mediators/transform/url/

Author: hiranya
Date: Fri Aug 27 05:06:23 2010
New Revision: 990019

URL: http://svn.apache.org/viewvc?rev=990019&view=rev
Log:
Adding the new URL rewrite mediator (SYNAPSE-681) and some basic tests. More test cases and documentation to follow.


Added:
    synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/URLRewriteMediatorFactory.java
    synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/URLRewriteMediatorSerializer.java
    synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/
    synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/RewriteAction.java
    synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/RewriteRule.java
    synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/URIFragments.java
    synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/URLRewriteMediator.java
    synapse/trunk/java/modules/core/src/test/java/org/apache/synapse/mediators/transform/url/
    synapse/trunk/java/modules/core/src/test/java/org/apache/synapse/mediators/transform/url/URLRewriteMediatorTest.java
Modified:
    synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorFactoryFinder.java

Modified: synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorFactoryFinder.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorFactoryFinder.java?rev=990019&r1=990018&r2=990019&view=diff
==============================================================================
--- synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorFactoryFinder.java (original)
+++ synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/MediatorFactoryFinder.java Fri Aug 27 05:06:23 2010
@@ -76,7 +76,8 @@ public class MediatorFactoryFinder imple
         TransactionMediatorFactory.class,
         EnqueueMediatorFactory.class,
         ConditionalRouterMediatorFactory.class,
-        SamplingThrottleMediatorFactory.class
+        SamplingThrottleMediatorFactory.class,
+        URLRewriteMediatorFactory.class
     };
 
     private final static MediatorFactoryFinder instance  = new MediatorFactoryFinder();

Added: synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/URLRewriteMediatorFactory.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/URLRewriteMediatorFactory.java?rev=990019&view=auto
==============================================================================
--- synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/URLRewriteMediatorFactory.java (added)
+++ synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/URLRewriteMediatorFactory.java Fri Aug 27 05:06:23 2010
@@ -0,0 +1,204 @@
+/*
+ *  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.synapse.config.xml;
+
+import org.apache.synapse.Mediator;
+import org.apache.synapse.util.xpath.SynapseXPath;
+import org.apache.synapse.commons.evaluators.Evaluator;
+import org.apache.synapse.commons.evaluators.EvaluatorException;
+import org.apache.synapse.commons.evaluators.config.EvaluatorFactoryFinder;
+import org.apache.synapse.mediators.transform.url.URLRewriteMediator;
+import org.apache.synapse.mediators.transform.url.RewriteRule;
+import org.apache.synapse.mediators.transform.url.RewriteAction;
+import org.apache.synapse.mediators.transform.url.URIFragments;
+import org.apache.axiom.om.OMElement;
+import org.jaxen.JaxenException;
+
+import javax.xml.namespace.QName;
+import java.util.Iterator;
+
+/**
+ * Creates an instance of the URLRewriteMediator given an XML configuration which
+ * adheres to the following grammar.
+ *
+ * <pre>
+ *  &lt;rewrite [inProperty="inputURL"] [outProperty="outputURL"]&gt;
+ *      &lt;rule&gt;
+ *          &lt;condition&gt;
+ *              evaluator configuration
+ *          &lt;/condition&gt; ?
+ *          &lt;action
+ *              value="value"
+ *              xpath="xpath"
+ *              [type="set | append | prepend | replace | remove"]
+ *              [fragment="protocol | user | host | port | path | query | ref | full"]
+ *              [regex="regex"] /&gt; +
+ *      &lt;/rule&gt; *
+ *  &lt;/rewrite&gt;
+ * </pre>
+ */
+public class URLRewriteMediatorFactory extends AbstractMediatorFactory {
+
+    private static final QName REWRITE_Q = new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, "rewrite");
+
+    private static final QName RULE_Q = new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, "rule");
+    private static final QName CONDITION_Q = new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, "condition");
+    private static final QName ACTION_Q = new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, "action");
+
+    private static final QName ATT_IN_PROPERTY = new QName("inProperty");
+    private static final QName ATT_OUT_PROPERTY = new QName("outProperty");
+    private static final QName ATT_TYPE = new QName("type");
+    private static final QName ATT_FRAGMENT = new QName("fragment");
+
+    public static final String ACTION_SET = "set";
+    public static final String ACTION_APPEND = "append";
+    public static final String ACTION_PREPEND = "prepend";
+    public static final String ACTION_REPLACE = "replace";
+    public static final String ACTION_REMOVE = "remove";
+
+    public static final String FRAGMENT_PROTOCOL = "protocol";
+    public static final String FRAGMENT_USER_INFO = "user";
+    public static final String FRAGMENT_HOST = "host";
+    public static final String FRAGMENT_PORT = "port";
+    public static final String FRAGMENT_PATH = "path";
+    public static final String FRAGMENT_QUERY = "query";
+    public static final String FRAGMENT_REF = "ref";
+    public static final String FRAGMENT_FULL_URI = "full";
+
+    protected Mediator createSpecificMediator(OMElement element) {
+        Iterator rules = element.getChildrenWithName(RULE_Q);
+        String inputProperty = element.getAttributeValue(ATT_IN_PROPERTY);
+        String outputProperty = element.getAttributeValue(ATT_OUT_PROPERTY);
+
+        URLRewriteMediator mediator = new URLRewriteMediator();
+        if (inputProperty != null) {
+            mediator.setInputProperty(inputProperty);
+        }
+        if (outputProperty != null) {
+            mediator.setOutputProperty(outputProperty);
+        }
+
+        while (rules.hasNext()) {
+            mediator.addRule(parseRule((OMElement) rules.next()));
+        }
+        processAuditStatus(mediator, element);
+        return mediator;
+    }
+
+    private RewriteRule parseRule(OMElement ruleElement) {
+        Iterator actions = ruleElement.getChildrenWithName(ACTION_Q);
+        if (actions == null) {
+            handleException("At least one rewrite action is required per rule");
+            return null;
+        }
+
+        RewriteRule rule = new RewriteRule();
+        while (actions.hasNext()) {
+            rule.addRewriteAction(parseAction((OMElement) actions.next()));
+        }
+
+        OMElement condition = ruleElement.getFirstChildWithName(CONDITION_Q);
+        if (condition != null) {
+            OMElement child = condition.getFirstElement();
+            if (child != null) {
+                try {
+                    Evaluator eval = EvaluatorFactoryFinder.getInstance().getEvaluator(child);
+                    rule.setCondition(eval);
+                } catch (EvaluatorException e) {
+                    handleException("Error while parsing the rule condition", e);
+                }
+            }
+        }
+
+        return rule;
+    }
+
+    private RewriteAction parseAction(OMElement actionElement) {
+        String value = actionElement.getAttributeValue(ATT_VALUE);
+        String xpath = actionElement.getAttributeValue(ATT_XPATH);
+        String type = actionElement.getAttributeValue(ATT_TYPE);
+
+        if (value == null && xpath == null && !ACTION_REMOVE.equals(type)) {
+            handleException("value or xpath attribute is required on the action element");
+        }
+
+        RewriteAction action = new RewriteAction();
+        if (xpath != null) {
+            try {
+                action.setXpath(new SynapseXPath(xpath));
+            } catch (JaxenException e) {
+                handleException("Error while parsing the XPath expression: " + xpath, e);
+            }
+        } else if (value != null) {
+            action.setValue(value);
+        }
+
+        String fragment = actionElement.getAttributeValue(ATT_FRAGMENT);
+        if (fragment != null) {
+            if (FRAGMENT_PROTOCOL.equals(fragment)) {
+                action.setFragmentIndex(URIFragments.PROTOCOL);
+            } else if (FRAGMENT_USER_INFO.equals(fragment)) {
+                action.setFragmentIndex(URIFragments.USER_INFO);
+            } else if (FRAGMENT_HOST.equals(fragment)) {
+                action.setFragmentIndex(URIFragments.HOST);
+            } else if (FRAGMENT_PORT.equals(fragment)) {
+                action.setFragmentIndex(URIFragments.PORT);
+            } else if (FRAGMENT_PATH.equals(fragment)) {
+                action.setFragmentIndex(URIFragments.PATH);
+            } else if (FRAGMENT_QUERY.equals(fragment)) {
+                action.setFragmentIndex(URIFragments.QUERY);
+            } else if (FRAGMENT_REF.equals(fragment)) {
+                action.setFragmentIndex(URIFragments.REF);
+            } else if (FRAGMENT_FULL_URI.equals(fragment)) {
+                action.setFragmentIndex(URIFragments.FULL_URI);
+            } else {
+                handleException("Unknown URL fragment name: " + fragment);
+            }
+        }
+
+        if (type != null) {
+            if (ACTION_SET.equals(type)) {
+                action.setActionType(RewriteAction.ACTION_SET);
+            } else if (ACTION_APPEND.equals(type)) {
+                action.setActionType(RewriteAction.ACTION_APPEND);
+            } else if (ACTION_PREPEND.equals(type)) {
+                action.setActionType(RewriteAction.ACTION_PREPEND);
+            } else if (ACTION_REPLACE.equals(type)) {
+                action.setActionType(RewriteAction.ACTION_REPLACE);
+                String regex = actionElement.getAttributeValue(ATT_REGEX);
+                if (regex != null) {
+                    action.setRegex(regex);
+                } else {
+                    handleException("regex attribute is required for replace action");
+                }
+            } else if (ACTION_REMOVE.equals(type)) {
+                action.setActionType(RewriteAction.ACTION_REMOVE);
+            } else {
+                handleException("Unknown URL rewrite action type: " + type);
+            }
+        }
+
+        return action;
+    }
+
+    public QName getTagQName() {
+        return REWRITE_Q;
+    }
+}

Added: synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/URLRewriteMediatorSerializer.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/URLRewriteMediatorSerializer.java?rev=990019&view=auto
==============================================================================
--- synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/URLRewriteMediatorSerializer.java (added)
+++ synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/URLRewriteMediatorSerializer.java Fri Aug 27 05:06:23 2010
@@ -0,0 +1,158 @@
+/*
+ *  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.synapse.config.xml;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.synapse.Mediator;
+import org.apache.synapse.commons.evaluators.Evaluator;
+import org.apache.synapse.commons.evaluators.EvaluatorException;
+import org.apache.synapse.commons.evaluators.config.EvaluatorSerializer;
+import org.apache.synapse.commons.evaluators.config.EvaluatorSerializerFinder;
+import org.apache.synapse.mediators.transform.url.URLRewriteMediator;
+import org.apache.synapse.mediators.transform.url.RewriteRule;
+import org.apache.synapse.mediators.transform.url.RewriteAction;
+import org.apache.synapse.mediators.transform.url.URIFragments;
+
+import java.util.List;
+
+public class URLRewriteMediatorSerializer extends AbstractMediatorSerializer {
+
+    protected OMElement serializeSpecificMediator(Mediator m) {
+        if (!(m instanceof URLRewriteMediator)) {
+            handleException("Unsupported mediator passed in for serialization : " + m.getType());
+            return null;
+        }
+
+        URLRewriteMediator mediator = (URLRewriteMediator) m;
+        OMElement rewrite = fac.createOMElement("rewrite", synNS);
+        saveTracingState(rewrite, mediator);
+
+        List<RewriteRule> rules = mediator.getRules();
+        try {
+            for (RewriteRule r : rules) {
+                OMElement rule = serializeRule(r);
+                rewrite.addChild(rule);
+            }
+        } catch (EvaluatorException e) {
+            handleException("Error while serializing the rewrite rule", e);
+        }
+
+        return rewrite;
+    }
+
+    private OMElement serializeRule(RewriteRule r) throws EvaluatorException {
+        OMElement rule = fac.createOMElement("rule", synNS);
+        Evaluator condition = r.getCondition();
+        if (condition != null) {
+            OMElement conditionElt = fac.createOMElement("condition", synNS);
+            EvaluatorSerializer serializer = EvaluatorSerializerFinder.getInstance().
+                    getSerializer(condition.getName());
+            serializer.serialize(conditionElt, condition);
+            rule.addChild(conditionElt);
+        }
+
+        List<RewriteAction> actions = r.getActions();
+        for (RewriteAction a : actions) {
+            OMElement action = serializeAction(a);
+            rule.addChild(action);
+        }
+
+        return rule;
+    }
+
+    private OMElement serializeAction(RewriteAction a) {
+        OMElement action = fac.createOMElement("action", synNS);
+        if (a.getValue() != null) {
+            action.addAttribute("value", a.getValue(), null);
+        } else if (a.getXpath() != null) {
+            action.addAttribute("xpath", a.getValue(), null);
+        }
+
+        if (a.getRegex() != null) {
+            action.addAttribute("regex", a.getRegex(), null);
+        }
+
+        int type = a.getActionType();
+        String typeStr;
+        switch (type) {
+            case RewriteAction.ACTION_APPEND:
+                typeStr = URLRewriteMediatorFactory.ACTION_APPEND;
+                break;
+
+            case RewriteAction.ACTION_PREPEND:
+                typeStr = URLRewriteMediatorFactory.ACTION_PREPEND;
+                break;
+
+            case RewriteAction.ACTION_REPLACE:
+                typeStr = URLRewriteMediatorFactory.ACTION_REPLACE;
+                break;
+
+            case RewriteAction.ACTION_REMOVE:
+                typeStr = URLRewriteMediatorFactory.ACTION_REMOVE;
+                break;
+
+            default:
+                typeStr = URLRewriteMediatorFactory.ACTION_SET;
+        }
+        action.addAttribute("type", typeStr, null);
+
+        int fragment = a.getFragmentIndex();
+        String fragmentStr;
+        switch (fragment) {
+            case URIFragments.PROTOCOL:
+                fragmentStr = URLRewriteMediatorFactory.FRAGMENT_PROTOCOL;
+                break;
+
+            case URIFragments.USER_INFO:
+                fragmentStr = URLRewriteMediatorFactory.FRAGMENT_USER_INFO;
+                break;
+
+            case URIFragments.HOST:
+                fragmentStr = URLRewriteMediatorFactory.FRAGMENT_HOST;
+                break;
+
+            case URIFragments.PORT:
+                fragmentStr = URLRewriteMediatorFactory.FRAGMENT_PORT;
+                break;
+
+            case URIFragments.PATH:
+                fragmentStr = URLRewriteMediatorFactory.FRAGMENT_PATH;
+                break;
+
+            case URIFragments.QUERY:
+                fragmentStr = URLRewriteMediatorFactory.FRAGMENT_QUERY;
+                break;
+
+            case URIFragments.REF:
+                fragmentStr = URLRewriteMediatorFactory.FRAGMENT_REF;
+                break;
+
+            default:
+                fragmentStr = URLRewriteMediatorFactory.FRAGMENT_FULL_URI;
+        }
+        action.addAttribute("fragment", fragmentStr, null);
+        
+        return action;
+    }
+
+    public String getMediatorClassName() {
+        return URLRewriteMediator.class.getName();
+    }
+}

Added: synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/RewriteAction.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/RewriteAction.java?rev=990019&view=auto
==============================================================================
--- synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/RewriteAction.java (added)
+++ synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/RewriteAction.java Fri Aug 27 05:06:23 2010
@@ -0,0 +1,138 @@
+/*
+ *  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.synapse.mediators.transform.url;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.synapse.util.xpath.SynapseXPath;
+import org.apache.synapse.MessageContext;
+
+import java.net.URISyntaxException;
+import java.net.URI;
+
+/**
+ * Represents a URL rewrite action. The action could be rewriting the entire URL
+ * or rewriting a fragment of the URL.
+ */
+public class RewriteAction {
+
+    private static final Log log = LogFactory.getLog(RewriteAction.class);
+
+    public static final int ACTION_SET      = 0;
+    public static final int ACTION_APPEND   = 1;
+    public static final int ACTION_PREPEND  = 2;
+    public static final int ACTION_REPLACE  = 3;
+    public static final int ACTION_REMOVE   = 4;
+
+    private String value;
+    private SynapseXPath xpath;
+    private String regex;
+    private int fragmentIndex = URIFragments.FULL_URI;
+    private int actionType = ACTION_SET;
+
+    public void execute(URIFragments fragments,
+                        MessageContext messageContext) throws URISyntaxException {
+
+        String result;
+        if (xpath != null) {
+            result = xpath.stringValueOf(messageContext);
+        } else {
+            result = value;
+        }
+
+        if (fragmentIndex == URIFragments.FULL_URI) {
+            URI uri;
+            if (result != null) {
+                uri = new URI(result);
+                if (log.isTraceEnabled()) {
+                    log.trace("Setting the URI to: " + result);
+                }
+            } else {
+                uri = new URI("");
+            }
+
+            // Since the entire URL has been rewritten we need to reinit all the fragments
+            fragments.setFragments(uri);
+
+        } else if (fragmentIndex == URIFragments.PORT) {
+            // When setting the port we must first convert the value into an integer
+            if (result != null) {
+                fragments.setPort(Integer.parseInt(result));
+            } else {
+                fragments.setPort(-1);
+            }
+        } else {
+            String str;
+            String currentValue = fragments.getStringFragment(fragmentIndex);
+            if (currentValue == null) {
+                currentValue = "";
+            }
+
+            switch (actionType) {
+                case ACTION_PREPEND : str = result.concat(currentValue); break;
+                case ACTION_APPEND  : str = currentValue.concat(result); break;
+                case ACTION_REPLACE : str = currentValue.replaceAll(regex, result); break;
+                case ACTION_REMOVE  : str = null; break;
+                default             : str = result;
+            }
+            fragments.setStringFragment(fragmentIndex, str);
+        }
+    }
+
+    public int getFragmentIndex() {
+        return fragmentIndex;
+    }
+
+    public void setFragmentIndex(int fragmentIndex) {
+        this.fragmentIndex = fragmentIndex;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public SynapseXPath getXpath() {
+        return xpath;
+    }
+
+    public void setXpath(SynapseXPath xpath) {
+        this.xpath = xpath;
+    }
+
+    public String getRegex() {
+        return regex;
+    }
+
+    public void setRegex(String regex) {
+        this.regex = regex;
+    }
+
+    public int getActionType() {
+        return actionType;
+    }
+
+    public void setActionType(int actionType) {
+        this.actionType = actionType;
+    }
+}

Added: synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/RewriteRule.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/RewriteRule.java?rev=990019&view=auto
==============================================================================
--- synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/RewriteRule.java (added)
+++ synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/RewriteRule.java Fri Aug 27 05:06:23 2010
@@ -0,0 +1,97 @@
+/*
+ *  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.synapse.mediators.transform.url;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.synapse.commons.evaluators.Evaluator;
+import org.apache.synapse.commons.evaluators.EvaluatorContext;
+import org.apache.synapse.commons.evaluators.EvaluatorException;
+import org.apache.synapse.MessageContext;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.net.URISyntaxException;
+
+/**
+ * Represents a URL rewrite rule. A rule can consist of an optional condition
+ * and one or more rewrite actions. If the condition is present, actions will be
+ * executed only when the condition evaluates to true. If the condition is not
+ * present, all the provided actions will be executed. If an error occurs while
+ * evaluating the condition, the condition is treated as evaluated to false.
+ * Condition evaluation is handled by Synapse evaluator framework. When executing
+ * multiple rewrite actions, they are executed in the specified order.
+ */
+public class RewriteRule {
+
+    private static final Log log = LogFactory.getLog(RewriteRule.class);
+
+    private Evaluator condition;
+    private List<RewriteAction> actions = new ArrayList<RewriteAction>();
+
+    public void rewrite(URIFragments fragments, MessageContext messageContext,
+                        Map<String,String> headers) throws URISyntaxException {
+
+        if (condition != null) {
+            String uriString = fragments.toURIString();
+            EvaluatorContext ctx = new EvaluatorContext(uriString, headers);
+            if (log.isTraceEnabled()) {
+                log.trace("Evaluating condition with URI: " + uriString);
+            }
+
+            try {
+                if (!condition.evaluate(ctx)) {
+                    if (log.isTraceEnabled()) {
+                        log.trace("Condition evaluated to 'false' - Skipping the current action");
+                    }
+                    return;
+                }
+
+                if (log.isTraceEnabled()) {
+                    log.trace("Condition evaluated to 'true' - Performing the stated action");
+                }
+            } catch (EvaluatorException e) {
+                log.warn("Error while evaluating the condition - Skipping the rule as it failed", e);
+                return;
+            }
+        }
+
+        for (RewriteAction action : actions) {
+            action.execute(fragments, messageContext);
+        }
+    }
+
+    public Evaluator getCondition() {
+        return condition;
+    }
+
+    public void setCondition(Evaluator condition) {
+        this.condition = condition;
+    }
+
+    public void addRewriteAction(RewriteAction action) {
+        actions.add(action);
+    }
+
+    public List<RewriteAction> getActions() {
+        return actions;
+    }
+}

Added: synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/URIFragments.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/URIFragments.java?rev=990019&view=auto
==============================================================================
--- synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/URIFragments.java (added)
+++ synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/URIFragments.java Fri Aug 27 05:06:23 2010
@@ -0,0 +1,117 @@
+/*
+ *  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.synapse.mediators.transform.url;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * This class represents a URI, fragmented into 7 major components. These components are
+ * namely scheme, user info, host, port, path, query and ref. Out of these seven components,
+ * port is an integer whereas all other components are strings. These fragments can be
+ * combined to form a valid URI according to RFC-2396. This collection strictly deals
+ * with URI fragments and not URL fragments. Therefore this abstraction can be used to
+ * represent any URI, URL or URN thus allowing room for a wider range of usecases.
+ */
+public class URIFragments {
+
+    public static final int FULL_URI    = -2;
+    public static final int PORT        = -1;
+
+    public static final int PROTOCOL    = 0;
+    public static final int USER_INFO   = 1;
+    public static final int HOST        = 2;
+    public static final int PATH        = 3;
+    public static final int QUERY       = 4;
+    public static final int REF         = 5;
+
+    private int port = -1;
+    // Using an array is lightweight and enables fast lookup through array indexing
+    private String[] fragments = new String[6];
+
+    public URIFragments() {
+
+    }
+
+    public URIFragments(URI uri) {
+        setFragments(uri);
+    }
+
+    /**
+     * Break down the given URI into fragments and reinitialize the current
+     * fragments set
+     *
+     * @param uri the URI to be assigned to the fragments
+     */
+    public void setFragments(URI uri) {
+        fragments[PROTOCOL] = uri.getScheme();
+        fragments[USER_INFO] = uri.getUserInfo();
+        fragments[HOST] = uri.getHost();
+        // getPath method returns empty string when a path is not present
+        // Better to set 'null' instead
+        fragments[PATH] = ("".equals(uri.getPath()) ? null : uri.getPath());
+        fragments[QUERY] = uri.getQuery();
+        fragments[REF] = uri.getFragment();
+        port = uri.getPort();
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setStringFragment(int index, String value) {
+        fragments[index] = value;
+    }
+
+    public String getStringFragment(int index) {
+        return fragments[index];
+    }
+
+    /**
+     * Construct a valid URI by combining the current fragment values
+     *
+     * @return a valid URI instance
+     * @throws URISyntaxException if the fragments form a malformed URI
+     */
+    public URI toURI() throws URISyntaxException {
+        return new URI(
+                fragments[PROTOCOL],
+                fragments[USER_INFO],
+                fragments[HOST],
+                port,
+                fragments[PATH],
+                fragments[QUERY],
+                fragments[REF]);
+    }
+
+    /**
+     * Construct a valid URI string by combining the current fragment values
+     *
+     * @return a string representation of a valid URI
+     * @throws URISyntaxException if the fragments form a malformed URI
+     */
+    public String toURIString() throws URISyntaxException {
+        return toURI().toString();
+    }
+}

Added: synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/URLRewriteMediator.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/URLRewriteMediator.java?rev=990019&view=auto
==============================================================================
--- synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/URLRewriteMediator.java (added)
+++ synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/mediators/transform/url/URLRewriteMediator.java Fri Aug 27 05:06:23 2010
@@ -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.synapse.mediators.transform.url;
+
+import org.apache.synapse.mediators.AbstractMediator;
+import org.apache.synapse.MessageContext;
+import org.apache.synapse.core.axis2.Axis2MessageContext;
+import org.apache.axis2.addressing.EndpointReference;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * A mediator capable of rewriting URLs in messages. The input URL can be
+ * extracted from the To header of the message or any of the message properties.
+ * The rewritten URL can be set as the To header or a message property. URL
+ * rewriting is carried out based on a user defined set of rules. This mediator
+ * support rewriting entire URLs as well as URL fragments.
+ */
+public class URLRewriteMediator extends AbstractMediator {
+
+    private List<RewriteRule> rules = new ArrayList<RewriteRule>();
+    private String inputProperty;
+    private String outputProperty;
+
+    public boolean mediate(MessageContext messageContext) {
+        URIFragments fragments;
+        URI inputURI = getInputAddress(messageContext);
+        if (inputURI != null) {
+            fragments = new URIFragments(inputURI);
+        } else {
+            fragments = new URIFragments();
+        }
+
+        Map<String, String> headers = getHeaders(messageContext);
+
+        try {
+            for (RewriteRule r : rules) {
+                r.rewrite(fragments, messageContext, headers);
+            }
+
+            if (outputProperty != null) {
+                messageContext.setProperty(outputProperty, fragments.toURIString());
+            } else {
+                messageContext.setTo(new EndpointReference(fragments.toURIString()));
+            }
+        } catch (URISyntaxException e) {
+            handleException("Error while constructing a URI from the fragments", e, messageContext);
+        }
+        return true;
+    }
+
+    private URI getInputAddress(MessageContext messageContext) {
+        String uriString = null;
+        if (inputProperty != null) {
+            Object prop = messageContext.getProperty(inputProperty);
+            if (prop != null && prop instanceof String) {
+                uriString = (String) prop;
+            }
+        } else if (messageContext.getTo() != null) {
+            uriString = messageContext.getTo().getAddress();
+        }
+
+        if (uriString != null) {
+            try {
+                return new URI(uriString);
+            } catch (URISyntaxException e) {
+                handleException("Malformed input URI: " + uriString, e, messageContext);
+            }
+        }
+        return null;
+    }
+
+    private Map<String, String> getHeaders(MessageContext synCtx) {
+        Axis2MessageContext axis2smc = (Axis2MessageContext) synCtx;
+        org.apache.axis2.context.MessageContext axis2MessageCtx =
+                axis2smc.getAxis2MessageContext();
+        Object headers = axis2MessageCtx.getProperty(
+                org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
+        Map<String, String> evaluatorHeaders = new HashMap<String, String>();
+
+        if (headers != null && headers instanceof Map) {
+            Map headersMap = (Map) headers;
+            for (Object key : headersMap.keySet()) {
+                if (key instanceof String && headersMap.get(key) instanceof String) {
+                    evaluatorHeaders.put((String) key, (String) headersMap.get(key));
+                }
+            }
+        }
+        return evaluatorHeaders;
+    }
+
+    public void addRule(RewriteRule rule) {
+        rules.add(rule);
+    }
+
+    public List<RewriteRule> getRules() {
+        return rules;
+    }
+
+    public String getInputProperty() {
+        return inputProperty;
+    }
+
+    public void setInputProperty(String inputProperty) {
+        this.inputProperty = inputProperty;
+    }
+
+    public String getOutputProperty() {
+        return outputProperty;
+    }
+
+    public void setOutputProperty(String outputProperty) {
+        this.outputProperty = outputProperty;
+    }
+}

Added: synapse/trunk/java/modules/core/src/test/java/org/apache/synapse/mediators/transform/url/URLRewriteMediatorTest.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/test/java/org/apache/synapse/mediators/transform/url/URLRewriteMediatorTest.java?rev=990019&view=auto
==============================================================================
--- synapse/trunk/java/modules/core/src/test/java/org/apache/synapse/mediators/transform/url/URLRewriteMediatorTest.java (added)
+++ synapse/trunk/java/modules/core/src/test/java/org/apache/synapse/mediators/transform/url/URLRewriteMediatorTest.java Fri Aug 27 05:06:23 2010
@@ -0,0 +1,192 @@
+/*
+ *  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.synapse.mediators.transform.url;
+
+import junit.framework.TestCase;
+import org.apache.synapse.MessageContext;
+import org.apache.synapse.commons.evaluators.EqualEvaluator;
+import org.apache.synapse.commons.evaluators.EvaluatorConstants;
+import org.apache.synapse.commons.evaluators.MatchEvaluator;
+import org.apache.synapse.commons.evaluators.source.URLTextRetriever;
+import org.apache.synapse.util.xpath.SynapseXPath;
+import org.apache.synapse.mediators.TestUtils;
+import org.apache.axis2.addressing.EndpointReference;
+
+import java.util.regex.Pattern;
+
+public class URLRewriteMediatorTest extends TestCase {
+
+    private String targetURL =  "http://localhost:9000/services/SimpleStockQuoteService";
+
+    public void testUnconditionalRewriteScenario1() throws Exception {
+        URLRewriteMediator mediator = new URLRewriteMediator();
+
+        RewriteAction action = new RewriteAction();
+        action.setValue(targetURL);
+
+        RewriteRule rule = new RewriteRule();
+        rule.addRewriteAction(action);
+        mediator.addRule(rule);
+
+        MessageContext msgCtx = TestUtils.createLightweightSynapseMessageContext("<empty/>");
+        mediator.mediate(msgCtx);
+
+        assertEquals(targetURL, msgCtx.getTo().getAddress());
+    }
+
+    public void testUnconditionalRewriteScenario2() throws Exception {
+        URLRewriteMediator mediator = new URLRewriteMediator();
+        mediator.setOutputProperty("outURL");
+
+        RewriteAction action = new RewriteAction();
+        action.setValue(targetURL);
+
+        RewriteRule rule = new RewriteRule();
+        rule.addRewriteAction(action);
+        mediator.addRule(rule);
+
+        MessageContext msgCtx = TestUtils.createLightweightSynapseMessageContext("<empty/>");
+        mediator.mediate(msgCtx);
+
+        assertEquals(targetURL, msgCtx.getProperty("outURL"));
+    }
+
+    public void testUnconditionalRewriteScenario3() throws Exception {
+        URLRewriteMediator mediator = new URLRewriteMediator();
+        mediator.setOutputProperty("outURL");
+
+        RewriteAction action1 = new RewriteAction();
+        action1.setValue(targetURL);
+        RewriteRule rule1 = new RewriteRule();
+        rule1.addRewriteAction(action1);
+        mediator.addRule(rule1);
+
+        RewriteAction action2 = new RewriteAction();
+        action2.setValue("/services/SimpleStockQuoteService");
+        action2.setFragmentIndex(URIFragments.PATH);
+
+        RewriteAction action3 = new RewriteAction();
+        action3.setXpath(new SynapseXPath("get-property('port')"));
+        action3.setFragmentIndex(URIFragments.PORT);
+
+        RewriteRule rule2 = new RewriteRule();
+        rule2.addRewriteAction(action2);
+        rule2.addRewriteAction(action3);
+        mediator.addRule(rule2);
+
+        MessageContext msgCtx = TestUtils.createLightweightSynapseMessageContext("<empty/>");
+        msgCtx.setTo(new EndpointReference("http://localhost:8280"));
+        msgCtx.setProperty("port", 9000);
+        mediator.mediate(msgCtx);
+
+        assertEquals(targetURL, msgCtx.getProperty("outURL"));
+    }
+
+    public void testConditionalRewriteScenario1() throws Exception {
+        URLRewriteMediator mediator = new URLRewriteMediator();
+
+        RewriteAction action = new RewriteAction();
+        action.setValue(targetURL);
+
+        RewriteRule rule = new RewriteRule();
+        EqualEvaluator eval = new EqualEvaluator();
+        URLTextRetriever txtRtvr = new URLTextRetriever();
+        txtRtvr.setFragment(EvaluatorConstants.URI_FRAGMENTS.port.name());
+        eval.setTextRetriever(txtRtvr);
+        eval.setValue("8280");
+        rule.setCondition(eval);
+        rule.addRewriteAction(action);
+        mediator.addRule(rule);
+
+        MessageContext msgCtx = TestUtils.createLightweightSynapseMessageContext("<empty/>");
+        msgCtx.setTo(new EndpointReference("http://localhost:8280"));
+        mediator.mediate(msgCtx);
+
+        assertEquals(targetURL, msgCtx.getTo().getAddress());
+    }
+
+    public void testConditionalRewriteScenario2() throws Exception {
+        URLRewriteMediator mediator = new URLRewriteMediator();
+        mediator.setOutputProperty("outURL");
+
+        RewriteAction action = new RewriteAction();
+        action.setValue(targetURL);
+
+        RewriteRule rule = new RewriteRule();
+        EqualEvaluator eval = new EqualEvaluator();
+        URLTextRetriever txtRtvr = new URLTextRetriever();
+        txtRtvr.setFragment(EvaluatorConstants.URI_FRAGMENTS.port.name());
+        eval.setTextRetriever(txtRtvr);
+        eval.setValue("8280");
+        rule.setCondition(eval);
+        rule.addRewriteAction(action);
+        mediator.addRule(rule);
+
+        MessageContext msgCtx = TestUtils.createLightweightSynapseMessageContext("<empty/>");
+        msgCtx.setTo(new EndpointReference("http://localhost:8280"));
+        mediator.mediate(msgCtx);
+
+        assertEquals(targetURL, msgCtx.getProperty("outURL"));
+    }
+
+    public void testConditionalRewriteScenario3() throws Exception {
+        URLRewriteMediator mediator = new URLRewriteMediator();
+        mediator.setOutputProperty("outURL");
+
+        RewriteAction action1 = new RewriteAction();
+        action1.setValue("localhost");
+        action1.setFragmentIndex(URIFragments.HOST);
+        RewriteRule rule1 = new RewriteRule();
+        rule1.addRewriteAction(action1);
+        EqualEvaluator eval1 = new EqualEvaluator();
+        URLTextRetriever txtRtvr1 = new URLTextRetriever();
+        txtRtvr1.setFragment(EvaluatorConstants.URI_FRAGMENTS.host.name());
+        eval1.setTextRetriever(txtRtvr1);
+        eval1.setValue("myhost");
+        rule1.setCondition(eval1);
+        mediator.addRule(rule1);
+
+        RewriteAction action2 = new RewriteAction();
+        action2.setValue("/services/SimpleStockQuoteService");
+        action2.setFragmentIndex(URIFragments.PATH);
+
+        RewriteAction action3 = new RewriteAction();
+        action3.setXpath(new SynapseXPath("get-property('port')"));
+        action3.setFragmentIndex(URIFragments.PORT);
+
+        RewriteRule rule2 = new RewriteRule();
+        rule2.addRewriteAction(action2);
+        rule2.addRewriteAction(action3);
+        MatchEvaluator eval2 = new MatchEvaluator();
+        URLTextRetriever txtRtvr2 = new URLTextRetriever();
+        txtRtvr2.setFragment(EvaluatorConstants.URI_FRAGMENTS.path.name());
+        eval2.setTextRetriever(txtRtvr2);
+        eval2.setRegex(Pattern.compile(".*/MyService"));
+        rule2.setCondition(eval2);
+        mediator.addRule(rule2);
+
+        MessageContext msgCtx = TestUtils.createLightweightSynapseMessageContext("<empty/>");
+        msgCtx.setTo(new EndpointReference("http://myhost:8280/MyService"));
+        msgCtx.setProperty("port", 9000);
+        mediator.mediate(msgCtx);
+
+        assertEquals(targetURL, msgCtx.getProperty("outURL"));
+    }
+}