You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2014/08/06 17:17:22 UTC

[1/5] git commit: [CXF-5925] First implementation of a JEXL Claims Mapper

Repository: cxf
Updated Branches:
  refs/heads/master b9c91a78a -> bf879ad99


[CXF-5925] First implementation of a JEXL Claims Mapper


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/17d077f6
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/17d077f6
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/17d077f6

Branch: refs/heads/master
Commit: 17d077f63edc024cbe1508c60148630a9b67b5d6
Parents: 13893ab
Author: Jan Bernhardt <jb...@talend.com>
Authored: Mon Aug 4 12:20:14 2014 +0200
Committer: Jan Bernhardt <jb...@talend.com>
Committed: Mon Aug 4 12:21:22 2014 +0200

----------------------------------------------------------------------
 services/sts/sts-core/pom.xml                   |   5 +
 .../apache/cxf/sts/claims/JexlClaimsMapper.java |  76 +++++++
 .../sts/claims/mapper/JexlClaimsMapperTest.java | 208 +++++++++++++++++++
 .../src/test/resources/jexlClaimMappings.script | 127 +++++++++++
 4 files changed, 416 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/17d077f6/services/sts/sts-core/pom.xml
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/pom.xml b/services/sts/sts-core/pom.xml
index a382944..f63f98b 100644
--- a/services/sts/sts-core/pom.xml
+++ b/services/sts/sts-core/pom.xml
@@ -121,6 +121,11 @@
             <scope>provided</scope>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-jexl</artifactId>
+            <version>2.1.1</version>
+        </dependency>
     </dependencies>
     <build>
         <plugins>

http://git-wip-us.apache.org/repos/asf/cxf/blob/17d077f6/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/JexlClaimsMapper.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/JexlClaimsMapper.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/JexlClaimsMapper.java
new file mode 100644
index 0000000..e11e112
--- /dev/null
+++ b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/JexlClaimsMapper.java
@@ -0,0 +1,76 @@
+/**
+ * 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.sts.claims;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import org.apache.commons.jexl2.JexlContext;
+import org.apache.commons.jexl2.JexlEngine;
+import org.apache.commons.jexl2.MapContext;
+import org.apache.commons.jexl2.Script;
+import org.apache.cxf.common.logging.LogUtils;
+
+public class JexlClaimsMapper implements ClaimsMapper {
+
+    private static final Logger LOG = LogUtils.getL7dLogger(JexlClaimsMapper.class);
+
+    JexlEngine jexl = new JexlEngine();
+    JexlContext context = new MapContext();
+    private Script script;
+
+    public JexlClaimsMapper() {
+        // jexl.setCache(512);
+        // jexl.setLenient(false);
+        jexl.setSilent(false);
+    }
+
+    public ProcessedClaimCollection mapClaims(String sourceRealm, ProcessedClaimCollection sourceClaims,
+        String targetRealm, ClaimsParameters parameters) {
+        context.set("sourceClaims", sourceClaims);
+        context.set("targetClaims", new ProcessedClaimCollection());
+        context.set("sourceRealm", sourceRealm);
+        context.set("targetRealm", targetRealm);
+        context.set("claimsParameters", parameters);
+
+        Script s = getScript();
+        if (s == null) {
+            LOG.warning("No claim mapping script defined");
+            return new ProcessedClaimCollection(); // TODO Check if null or an exception would be more
+                                                   // appropriate
+        } else {
+            return (ProcessedClaimCollection)s.execute(context);
+        }
+    }
+
+    public Script getScript() {
+        return script;
+    }
+
+    public void setScript(Script script) {
+        this.script = script;
+    }
+
+    public void setScript(String scriptPath) throws IOException {
+        this.script = jexl.createScript(new File(scriptPath));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/17d077f6/services/sts/sts-core/src/test/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapperTest.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapperTest.java b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapperTest.java
new file mode 100644
index 0000000..db530a5
--- /dev/null
+++ b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapperTest.java
@@ -0,0 +1,208 @@
+/**
+ * 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.sts.claims.mapper;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.cxf.sts.StaticSTSProperties;
+import org.apache.cxf.sts.claims.ClaimsParameters;
+import org.apache.cxf.sts.claims.JexlClaimsMapper;
+import org.apache.cxf.sts.claims.ProcessedClaim;
+import org.apache.cxf.sts.claims.ProcessedClaimCollection;
+import org.junit.Test;
+
+public class JexlClaimsMapperTest extends org.junit.Assert {
+
+    JexlClaimsMapper jcm;
+
+    public JexlClaimsMapperTest() throws IOException {
+        jcm = new JexlClaimsMapper();
+        jcm.setScript("src/test/resources/jexlClaimMappings.script");
+    }
+
+    @Test
+    public void testClaimMerge() throws IOException {
+        ProcessedClaimCollection result = jcm.mapClaims("A", createClaimCollection(), "B", createProperties());
+
+        assertNotNull(result);
+        assertTrue(result.size() >= 2);
+        assertEquals("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", result.get(1).getClaimType()
+            .toString());
+        assertEquals(1, result.get(1).getValues().size());
+        assertEquals("Jan Bernhardt", result.get(1).getValues().get(0));
+
+        for (ProcessedClaim c : result) {
+            if ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname".equals(c.getClaimType())) {
+                fail("Only merged claim should be in result set, but not the individual claims");
+            }
+        }
+    }
+
+    @Test
+    public void testRoleMappings() throws IOException {
+        ProcessedClaimCollection result = jcm.mapClaims("A", createClaimCollection(), "B", createProperties());
+
+        assertNotNull(result);
+        assertTrue(result.size() >= 1);
+        assertEquals(2, result.get(0).getValues().size());
+        assertTrue(result.get(0).getValues().contains("manager"));
+        assertTrue(result.get(0).getValues().contains("administrator"));
+    }
+
+    @Test
+    public void testUnusedClaims() throws IOException {
+        ProcessedClaimCollection result = jcm.mapClaims("A", createClaimCollection(), "B", createProperties());
+
+        for (ProcessedClaim c : result) {
+            URI claimType = c.getClaimType();
+            if (claimType != null
+                && "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/unused".equals(claimType.toString())) {
+                fail("Claims not handled within the script should not be copied to the target token");
+            }
+        }
+    }
+
+    @Test
+    public void testUpdateIssuer() throws IOException {
+        ProcessedClaimCollection result = jcm.mapClaims("A", createClaimCollection(), "B", createProperties());
+
+        assertNotNull(result);
+        assertEquals("STS-B", result.get(0).getOriginalIssuer());
+        assertEquals("NewIssuer", result.get(0).getIssuer());
+        assertEquals("STS-A", result.get(1).getOriginalIssuer());
+    }
+
+    @Test
+    public void testStaticClaim() throws IOException {
+        ProcessedClaimCollection result = jcm.mapClaims("A", createClaimCollection(), "B", createProperties());
+
+        assertNotNull(result);
+        ProcessedClaim staticClaim = findClaim(result, 
+                                               "http://schemas.microsoft.com/identity/claims/identityprovider");
+        assertNotNull(staticClaim);
+    }
+
+    @Test
+    public void testUpperCaseClaim() throws IOException {
+        ProcessedClaimCollection result = jcm.mapClaims("A", createClaimCollection(), "B", createProperties());
+
+        assertNotNull(result);
+        ProcessedClaim claim = findClaim(result, "http://my.schema.org/identity/claims/uppercase");
+        assertNotNull(claim);
+        assertNotNull(claim.getValues());
+        assertEquals(2, claim.getValues().size());
+        assertEquals("VALUE2", claim.getValues().get(1));
+    }
+
+    @Test
+    public void testLowerCaseClaim() throws IOException {
+        ProcessedClaimCollection result = jcm.mapClaims("A", createClaimCollection(), "B", createProperties());
+
+        assertNotNull(result);
+        ProcessedClaim claim = findClaim(result, "http://my.schema.org/identity/claims/lowercase");
+        assertNotNull(claim);
+        assertNotNull(claim.getValues());
+        assertEquals(2, claim.getValues().size());
+        assertEquals("value2", claim.getValues().get(1));
+    }
+
+    @Test
+    public void testWrappedUpperCaseClaim() throws IOException {
+        ProcessedClaimCollection result = jcm.mapClaims("A", createClaimCollection(), "B", createProperties());
+
+        assertNotNull(result);
+        ProcessedClaim claim = findClaim(result, "http://my.schema.org/identity/claims/wrappedUppercase");
+        assertNotNull(claim);
+        assertNotNull(claim.getValues());
+        assertEquals(1, claim.getValues().size());
+        assertEquals("PREFIX_VALUE_SUFFIX", claim.getValues().get(0));
+    }
+
+    @Test
+    public void testSimpleClaimCopy() throws IOException {
+        ProcessedClaimCollection result = jcm.mapClaims("A", createClaimCollection(), "B", createProperties());
+
+        assertNotNull(result);
+        ProcessedClaim claim = findClaim(result, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mail");
+        assertNotNull(claim);
+        assertNotNull(claim.getValues());
+        assertEquals(1, claim.getValues().size());
+        assertEquals("test@apache.com", claim.getValues().get(0));
+    }
+
+    @SuppressWarnings("unchecked")
+    protected ProcessedClaimCollection createClaimCollection() {
+        ProcessedClaimCollection cc = new ProcessedClaimCollection();
+        ProcessedClaim c = new ProcessedClaim();
+        c.setIssuer("STS-A");
+        c.setOriginalIssuer("STS-B");
+        c.setClaimType(URI.create("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role"));
+        c.setValues((List<Object>)(List<?>)Arrays.asList("admin", "manager", "tester"));
+        cc.add(c);
+
+        c = new ProcessedClaim();
+        c.setIssuer("STS-A");
+        c.setClaimType(URI.create("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"));
+        c.setValues((List<Object>)(List<?>)Arrays.asList("Jan"));
+        cc.add(c);
+
+        c = new ProcessedClaim();
+        c.setIssuer("STS-A");
+        c.setClaimType(URI.create("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"));
+        c.setValues((List<Object>)(List<?>)Arrays.asList("Bernhardt"));
+        cc.add(c);
+
+        c = new ProcessedClaim();
+        c.setClaimType(URI.create("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/unused"));
+        c.setValues((List<Object>)(List<?>)Arrays.asList("noValue"));
+        cc.add(c);
+
+        c = new ProcessedClaim();
+        c.setClaimType(URI.create("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mail"));
+        c.setValues((List<Object>)(List<?>)Arrays.asList("test@apache.com"));
+        cc.add(c);
+
+        return cc;
+    }
+
+    protected ClaimsParameters createProperties() {
+        StaticSTSProperties stsProp = new StaticSTSProperties();
+        stsProp.setIssuer("NewIssuer");
+        ClaimsParameters param = new ClaimsParameters();
+        param.setStsProperties(stsProp);
+        return param;
+    }
+
+    private ProcessedClaim findClaim(ProcessedClaimCollection claims, String claimType) {
+        if (claimType == null || claims == null) {
+            return null;
+        }
+        for (ProcessedClaim c : claims) {
+            if (c.getClaimType() != null && claimType.equals(c.getClaimType().toString())) {
+                return c;
+            }
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/17d077f6/services/sts/sts-core/src/test/resources/jexlClaimMappings.script
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/test/resources/jexlClaimMappings.script b/services/sts/sts-core/src/test/resources/jexlClaimMappings.script
new file mode 100644
index 0000000..6b5c4f3
--- /dev/null
+++ b/services/sts/sts-core/src/test/resources/jexlClaimMappings.script
@@ -0,0 +1,127 @@
+/**
+ * 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.
+ */
+
+{
+    // Role value mapping
+    var roleClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role';
+    var roleMappings = { "admin" : "administrator", "manager" : "manager" };
+    
+    for (c : sourceClaims) {
+    	if(c.claimType == roleClaimType) {
+	    	var mappedValues = new("java.util.ArrayList");
+	    	for (v : c.values) {
+	    		var newValue = roleMappings.get(v);
+	    		if (newValue != null) {
+	    			mappedValues.add(newValue);
+	    		}
+	    	}
+	    	c.values = mappedValues;
+	    	targetClaims.add(c);
+    	}
+    }
+    
+    // Claim merge
+    var firstNameClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname';
+    var lastNameClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname';
+    var firstName;
+    var lastName;
+    var issuer;
+    for (c : sourceClaims) {
+    	if(c.claimType == firstNameClaimType) {
+    		firstName = c.values[0];
+    		issuer = c.issuer;
+    	} else if(c.claimType == lastNameClaimType) {
+    		lastName = c.values[0];
+    	}
+    }
+    if (firstName != null && lastName != null) {
+    	var claim = new("org.apache.cxf.sts.claims.ProcessedClaim");
+    	claim.issuer = issuer;
+    	claim.claimType = new("java.net.URI", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name");
+    	claim.addValue(firstName + " " + lastName);
+    	targetClaims.add(claim);
+    }
+    
+    // Additional static claim
+    var idpClaim = new("org.apache.cxf.sts.claims.ProcessedClaim");
+    idpClaim.claimType = new("java.net.URI", "http://schemas.microsoft.com/identity/claims/identityprovider");
+    idpClaim.value = "https://idp.apache.org/cbb375d-33b-45fa-9bf5-f33bd8721a77/";
+    targetClaims.add(idpClaim);
+    
+    // Claim value updates
+    var uppercaseClaim = new("org.apache.cxf.sts.claims.ProcessedClaim");
+    uppercaseClaim.claimType = new("java.net.URI", "http://my.schema.org/identity/claims/uppercase");
+    uppercaseClaim.values.add("Value");
+    uppercaseClaim.values.add("Value2");
+    var newValues = new("java.util.ArrayList");
+    for (v : uppercaseClaim.values) {
+    	newValue = v.toUpperCase();
+    	newValues.add(newValue);
+    }
+    uppercaseClaim.values = newValues;
+    targetClaims.add(uppercaseClaim);
+    
+    var lowercaseClaim = new("org.apache.cxf.sts.claims.ProcessedClaim");
+    lowercaseClaim.claimType = new("java.net.URI", "http://my.schema.org/identity/claims/lowercase");
+    lowercaseClaim.values.add("Value");
+    lowercaseClaim.values.add("Value2");
+    var newValues = new("java.util.ArrayList");
+    for (v : lowercaseClaim.values) {
+    	newValue = v.toLowerCase();
+    	newValues.add(newValue);
+    }
+    lowercaseClaim.values = newValues;
+    targetClaims.add(lowercaseClaim);
+    
+    var wrappedUppercaseClaim = new("org.apache.cxf.sts.claims.ProcessedClaim");
+    wrappedUppercaseClaim.claimType = new("java.net.URI", "http://my.schema.org/identity/claims/wrappedUppercase");
+    wrappedUppercaseClaim.values.add("Value");
+    var newValues = new("java.util.ArrayList");
+    for (v : wrappedUppercaseClaim.values) {
+    	newValue = "Prefix_" + v + "_Suffix";
+    	newValues.add(newValue);
+    }
+    wrappedUppercaseClaim.values = newValues;
+    var newValues = new("java.util.ArrayList");
+    for (v : wrappedUppercaseClaim.values) {
+    	newValue = v.toUpperCase();
+    	newValues.add(newValue);
+    }
+    wrappedUppercaseClaim.values = newValues;
+    targetClaims.add(wrappedUppercaseClaim);
+    
+    // Direct copy
+    var emailClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mail';
+    for (c : sourceClaims) {
+    	if(c.claimType == emailClaimType) {
+    		targetClaims.add(c);
+    	}
+    }
+    
+    // Set correct issuer
+    for (c : targetClaims) {
+    	if(c.originalIssuer == null) {
+    		c.originalIssuer = c.issuer;
+    	}
+    	c.issuer = claimsParameters.stsProperties.issuer;
+    }
+    
+    // Return new claims
+    return targetClaims;
+}


[2/5] git commit: [CXF-5927] Providing claim mapping utils

Posted by co...@apache.org.
[CXF-5927] Providing claim mapping utils


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/31c80946
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/31c80946
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/31c80946

Branch: refs/heads/master
Commit: 31c80946f223a03eb827d56d07de7229d4bbe1b6
Parents: 17d077f
Author: Jan Bernhardt <jb...@talend.com>
Authored: Mon Aug 4 16:40:01 2014 +0200
Committer: Jan Bernhardt <jb...@talend.com>
Committed: Mon Aug 4 16:44:04 2014 +0200

----------------------------------------------------------------------
 .../apache/cxf/sts/claims/JexlClaimsMapper.java |  76 -----
 .../cxf/sts/claims/mapper/ClaimUtils.java       | 281 +++++++++++++++++++
 .../cxf/sts/claims/mapper/JexlClaimsMapper.java |  85 ++++++
 .../sts/claims/mapper/JexlClaimsMapperTest.java |  24 +-
 .../src/test/resources/jexlClaimMappings.script | 127 ---------
 .../jexlClaimMappingsWithFunctions.script       |  60 ++++
 .../jexlClaimMappingsWithoutFunctions.script    | 127 +++++++++
 7 files changed, 573 insertions(+), 207 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/31c80946/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/JexlClaimsMapper.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/JexlClaimsMapper.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/JexlClaimsMapper.java
deleted file mode 100644
index e11e112..0000000
--- a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/JexlClaimsMapper.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * 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.sts.claims;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.logging.Logger;
-
-import org.apache.commons.jexl2.JexlContext;
-import org.apache.commons.jexl2.JexlEngine;
-import org.apache.commons.jexl2.MapContext;
-import org.apache.commons.jexl2.Script;
-import org.apache.cxf.common.logging.LogUtils;
-
-public class JexlClaimsMapper implements ClaimsMapper {
-
-    private static final Logger LOG = LogUtils.getL7dLogger(JexlClaimsMapper.class);
-
-    JexlEngine jexl = new JexlEngine();
-    JexlContext context = new MapContext();
-    private Script script;
-
-    public JexlClaimsMapper() {
-        // jexl.setCache(512);
-        // jexl.setLenient(false);
-        jexl.setSilent(false);
-    }
-
-    public ProcessedClaimCollection mapClaims(String sourceRealm, ProcessedClaimCollection sourceClaims,
-        String targetRealm, ClaimsParameters parameters) {
-        context.set("sourceClaims", sourceClaims);
-        context.set("targetClaims", new ProcessedClaimCollection());
-        context.set("sourceRealm", sourceRealm);
-        context.set("targetRealm", targetRealm);
-        context.set("claimsParameters", parameters);
-
-        Script s = getScript();
-        if (s == null) {
-            LOG.warning("No claim mapping script defined");
-            return new ProcessedClaimCollection(); // TODO Check if null or an exception would be more
-                                                   // appropriate
-        } else {
-            return (ProcessedClaimCollection)s.execute(context);
-        }
-    }
-
-    public Script getScript() {
-        return script;
-    }
-
-    public void setScript(Script script) {
-        this.script = script;
-    }
-
-    public void setScript(String scriptPath) throws IOException {
-        this.script = jexl.createScript(new File(scriptPath));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cxf/blob/31c80946/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/mapper/ClaimUtils.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/mapper/ClaimUtils.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/mapper/ClaimUtils.java
new file mode 100644
index 0000000..b30354f
--- /dev/null
+++ b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/mapper/ClaimUtils.java
@@ -0,0 +1,281 @@
+/**
+ * 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.sts.claims.mapper;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.sts.claims.ProcessedClaim;
+import org.apache.cxf.sts.claims.ProcessedClaimCollection;
+
+public class ClaimUtils {
+
+    /**
+     * @param targetCollection Collection that should be used to add further claims to
+     * @param claims Claims to be added to the provided collection
+     * @return Returns provided collection including provided claims
+     */
+    public ProcessedClaimCollection add(ProcessedClaimCollection targetCollection, ProcessedClaim... claims) {
+        for (ProcessedClaim c : claims) {
+            if (c != null) {
+                targetCollection.add(c);
+            }
+        }
+        return targetCollection;
+    }
+
+    /**
+     * @param targetCollection Collection that should be used to add claims from the other provided claim
+     *            collections
+     * @param claimCollections All claims contained within the provided collections will be added to the
+     *            targetCollection
+     * @return Returns claim collection containing all claims that have been provided
+     */
+    public ProcessedClaimCollection add(ProcessedClaimCollection targetCollection,
+        ProcessedClaimCollection... claimCollections) {
+        for (ProcessedClaimCollection cc : claimCollections) {
+            targetCollection.addAll(cc);
+        }
+        return targetCollection;
+    }
+
+    /**
+     * @param claimTypeURI claim type URI
+     * @param values values of created claim. Can be null if no values shall be added to claim.
+     * @return Returns new claim with provided claim type and values
+     */
+    public ProcessedClaim create(String processedClaimTypeURI, String... values) {
+        ProcessedClaim processedClaim = new ProcessedClaim();
+        if (processedClaimTypeURI != null) {
+            processedClaim.setClaimType(URI.create(processedClaimTypeURI));
+        }
+        if (values != null) {
+            processedClaim.getValues().addAll(Arrays.asList(values));
+        }
+        return processedClaim;
+    }
+
+    /**
+     * @param claims Collection of multiple claims with different claim types
+     * @param claimType URI of claim type to be selected from claim collection
+     * @return Returns first claim from claims collection matching the provided claimType
+     */
+    public ProcessedClaim get(ProcessedClaimCollection processedClaims, String processedClaimType) {
+        if (processedClaimType == null || processedClaims == null) {
+            return null;
+        }
+        for (ProcessedClaim c : processedClaims) {
+            if (c.getClaimType() != null && processedClaimType.equals(c.getClaimType().toString())) {
+                return c;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @param claims Collection of claims to be mapped to a differnt claim type
+     * @param map Map of old:new claim types
+     * @param keepUnmapped if set to false only claims with a claim type contained in the map will be
+     *            returned. If set to false claims with an unmapped claim type will also be returned.
+     * @return Returns claim collection with mapped claim types
+     */
+    public ProcessedClaimCollection mapType(ProcessedClaimCollection processedClaims, Map<String, String> map,
+        boolean keepUnmapped) {
+        ProcessedClaimCollection mappedProcessedClaims = new ProcessedClaimCollection();
+        if (processedClaims != null && map != null) {
+            for (ProcessedClaim c : processedClaims) {
+                String processedClaimType = (c.getClaimType() != null)
+                    ? c.getClaimType().toString()
+                    : "";
+                String mappedProcessedClaimType = map.get(processedClaimType);
+                if (mappedProcessedClaimType != null) {
+                    ProcessedClaim processedClaim = c.clone();
+                    processedClaim.setClaimType(URI.create(mappedProcessedClaimType));
+                    mappedProcessedClaims.add(processedClaim);
+                } else if (keepUnmapped) {
+                    mappedProcessedClaims.add(c.clone());
+                }
+            }
+        }
+        return mappedProcessedClaims;
+    }
+
+    /**
+     * @param claim Claim providing values to be mapped
+     * @param map Map of old:new mapping values
+     * @param keepUnmapped if set to false only values contained in the map will be returned. If set to true,
+     *            values not contained in the map will also remain in the returned claim.
+     * @return Returns the provided claim with mapped values
+     */
+    public ProcessedClaim mapValues(ProcessedClaim processedClaim, Map<Object, Object> mapping, boolean keepUnmapped) {
+
+        if (processedClaim != null) {
+            List<Object> values = processedClaim.getValues();
+            List<Object> mappedValues = new ArrayList<Object>();
+
+            if (values == null || mapping == null || mapping.size() == 0) {
+                processedClaim.setValues(mappedValues);
+                return processedClaim;
+            }
+
+            for (Object value : values) {
+                Object newValue = mapping.get(value);
+                if (newValue != null) {
+                    mappedValues.add(newValue);
+                } else if (keepUnmapped) {
+                    mappedValues.add(value);
+                }
+            }
+            processedClaim.setValues(mappedValues);
+        }
+        return processedClaim;
+    }
+
+    /**
+     * @param claims Collection of claims containing claims with claim types of listed <code>claimType</code>
+     *            array
+     * @param targetClaimType claim type URI of merged result claim
+     * @param delimiter Delimiter added between multiple claim types. Value can be <code>null</code>.
+     * @param claimType URIs of claim types to be merged. Merging will be in the same order as the provided
+     *            claim type URIs. If a claim type is not found in the collection this claim type will be
+     *            omitted.
+     * @return Returns merged claim of all found claim types
+     */
+    public ProcessedClaim merge(ProcessedClaimCollection processedClaims, String targetClaimType, String delimiter,
+        String... processedClaimType) {
+        ProcessedClaim mergedProcessedClaim = null;
+        StringBuilder sbProcessedClaimValue = new StringBuilder();
+        for (String sc : processedClaimType) {
+            ProcessedClaim c = get(processedClaims, sc);
+            if (c != null) {
+                List<Object> values = c.getValues();
+                if (values != null && values.size() > 0) {
+                    if (mergedProcessedClaim == null) {
+                        // First match TODO refactor for better method override
+                        mergedProcessedClaim = c.clone();
+                        sbProcessedClaimValue.append(values.get(0));
+                        mergedProcessedClaim.getValues().clear();
+                    } else {
+                        sbProcessedClaimValue.append(delimiter).append(values.get(0));
+                    }
+                }
+            }
+        }
+        if (mergedProcessedClaim != null) {
+            mergedProcessedClaim.setClaimType(URI.create(targetClaimType));
+            mergedProcessedClaim.addValue(sbProcessedClaimValue.toString());
+        }
+
+        return mergedProcessedClaim;
+    }
+
+    /**
+     * @param claim Claim to be updated
+     * @param claimTypeURI URI as String to be set as claim type in provided claim
+     * @return Returns updated claim
+     */
+    public ProcessedClaim setType(ProcessedClaim processedClaim, String processedClaimTypeURI) {
+        processedClaim.setClaimType(URI.create(processedClaimTypeURI));
+        return processedClaim;
+    }
+
+    /**
+     * All claims within the provided collection will be updated in the following manner: If no original
+     * issuer is set, the issuer in the provided claims will be set as original issuer. If an original issuer
+     * was already set before, the original issuer will not be updated. All claims will be updated to have the
+     * provided issuer name be set as the claim issuer.
+     * 
+     * @param claims Collection of claims to be updated
+     * @param issuerName Issuer to be set for all claims within the collection
+     * @return Returns updated claim collection
+     */
+    public ProcessedClaimCollection updateIssuer(ProcessedClaimCollection processedClaims, String newIssuer) {
+        for (ProcessedClaim c : processedClaims) {
+            if (c.getOriginalIssuer() == null) {
+                c.setOriginalIssuer(c.getIssuer());
+            }
+            c.setIssuer(newIssuer);
+        }
+        return processedClaims;
+    }
+
+    /**
+     * @param claim values of this claim will be transformed to uppercase format
+     * @return Returns claim with values all in uppercase format
+     */
+    public ProcessedClaim upperCaseValues(ProcessedClaim processedClaim) {
+        if (processedClaim != null && processedClaim.getValues() != null) {
+            List<Object> oldValues = processedClaim.getValues();
+            List<Object> newValues = new ArrayList<Object>();
+            for (Object value : oldValues) {
+                newValues.add(value.toString().toUpperCase());
+            }
+            processedClaim.getValues().clear();
+            processedClaim.getValues().addAll(newValues);
+        }
+        return processedClaim;
+    }
+
+    /**
+     * @param claim values of this claim will be transformed to lowercase format
+     * @return Returns claim with values all in lowercase format
+     */
+    public ProcessedClaim lowerCaseValues(ProcessedClaim processedClaim) {
+        if (processedClaim != null && processedClaim.getValues() != null) {
+            List<Object> oldValues = processedClaim.getValues();
+            List<Object> newValues = new ArrayList<Object>();
+            for (Object value : oldValues) {
+                newValues.add(value.toString().toLowerCase());
+            }
+            processedClaim.getValues().clear();
+            processedClaim.getValues().addAll(newValues);
+        }
+        return processedClaim;
+    }
+
+    /**
+     * @param claim Claim providing values to be wrapped
+     * @param prefix Prefix to be added to each claim value. Can be null.
+     * @param suffix Suffix to be appended to each claim value. Can be null.
+     * @return Returns the provided claim with wrapped values
+     */
+    public ProcessedClaim wrapValues(ProcessedClaim processedClaim, String prefix, String suffix) {
+        prefix = (prefix == null)
+            ? ""
+            : prefix;
+        suffix = (suffix == null)
+            ? ""
+            : suffix;
+        if (processedClaim != null && processedClaim.getValues() != null) {
+            List<Object> oldValues = processedClaim.getValues();
+            List<Object> newValues = new ArrayList<Object>();
+            for (Object value : oldValues) {
+                newValues.add(prefix + value.toString() + suffix);
+            }
+            processedClaim.getValues().clear();
+            processedClaim.getValues().addAll(newValues);
+        }
+        return processedClaim;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/31c80946/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapper.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapper.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapper.java
new file mode 100644
index 0000000..8fbe59f
--- /dev/null
+++ b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapper.java
@@ -0,0 +1,85 @@
+/**
+ * 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.sts.claims.mapper;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.apache.commons.jexl2.JexlContext;
+import org.apache.commons.jexl2.JexlEngine;
+import org.apache.commons.jexl2.MapContext;
+import org.apache.commons.jexl2.Script;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.sts.claims.ClaimsMapper;
+import org.apache.cxf.sts.claims.ClaimsParameters;
+import org.apache.cxf.sts.claims.ProcessedClaimCollection;
+
+public class JexlClaimsMapper implements ClaimsMapper {
+
+    private static final Logger LOG = LogUtils.getL7dLogger(JexlClaimsMapper.class);
+
+    JexlEngine jexl = new JexlEngine();
+    JexlContext context = new MapContext();
+    private Script script;
+
+    public JexlClaimsMapper() {
+        // jexl.setCache(512);
+        // jexl.setLenient(false);
+        jexl.setSilent(false);
+        
+        Map<String, Object> functions = new HashMap<String, Object>();
+        functions.put("claims", new ClaimUtils());
+        jexl.setFunctions(functions);
+    }
+
+    public ProcessedClaimCollection mapClaims(String sourceRealm, ProcessedClaimCollection sourceClaims,
+        String targetRealm, ClaimsParameters parameters) {
+        context.set("sourceClaims", sourceClaims);
+        context.set("targetClaims", new ProcessedClaimCollection());
+        context.set("sourceRealm", sourceRealm);
+        context.set("targetRealm", targetRealm);
+        context.set("claimsParameters", parameters);
+
+        Script s = getScript();
+        if (s == null) {
+            LOG.warning("No claim mapping script defined");
+            return new ProcessedClaimCollection(); // TODO Check if null or an exception would be more
+                                                   // appropriate
+        } else {
+            return (ProcessedClaimCollection)s.execute(context);
+        }
+    }
+
+    public Script getScript() {
+        return script;
+    }
+
+    public void setScript(Script script) {
+        this.script = script;
+    }
+
+    public void setScript(String scriptPath) throws IOException {
+        this.script = jexl.createScript(new File(scriptPath));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/31c80946/services/sts/sts-core/src/test/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapperTest.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapperTest.java b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapperTest.java
index db530a5..cec247a 100644
--- a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapperTest.java
+++ b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/claims/mapper/JexlClaimsMapperTest.java
@@ -22,22 +22,38 @@ package org.apache.cxf.sts.claims.mapper;
 import java.io.IOException;
 import java.net.URI;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 
 import org.apache.cxf.sts.StaticSTSProperties;
 import org.apache.cxf.sts.claims.ClaimsParameters;
-import org.apache.cxf.sts.claims.JexlClaimsMapper;
 import org.apache.cxf.sts.claims.ProcessedClaim;
 import org.apache.cxf.sts.claims.ProcessedClaimCollection;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
+@RunWith(Parameterized.class)
 public class JexlClaimsMapperTest extends org.junit.Assert {
 
     JexlClaimsMapper jcm;
-
-    public JexlClaimsMapperTest() throws IOException {
+    
+    public JexlClaimsMapperTest(String scriptPath) throws IOException {
         jcm = new JexlClaimsMapper();
-        jcm.setScript("src/test/resources/jexlClaimMappings.script");
+        jcm.setScript(scriptPath);
+    }
+    
+    @Parameters
+    public static Collection<Object[]> data() {
+        Object[][] data = new Object[][] {
+            {
+                "src/test/resources/jexlClaimMappingsWithoutFunctions.script"
+            }, {
+                "src/test/resources/jexlClaimMappingsWithFunctions.script"
+            }
+        };
+        return Arrays.asList(data);
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/cxf/blob/31c80946/services/sts/sts-core/src/test/resources/jexlClaimMappings.script
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/test/resources/jexlClaimMappings.script b/services/sts/sts-core/src/test/resources/jexlClaimMappings.script
deleted file mode 100644
index 6b5c4f3..0000000
--- a/services/sts/sts-core/src/test/resources/jexlClaimMappings.script
+++ /dev/null
@@ -1,127 +0,0 @@
-/**
- * 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.
- */
-
-{
-    // Role value mapping
-    var roleClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role';
-    var roleMappings = { "admin" : "administrator", "manager" : "manager" };
-    
-    for (c : sourceClaims) {
-    	if(c.claimType == roleClaimType) {
-	    	var mappedValues = new("java.util.ArrayList");
-	    	for (v : c.values) {
-	    		var newValue = roleMappings.get(v);
-	    		if (newValue != null) {
-	    			mappedValues.add(newValue);
-	    		}
-	    	}
-	    	c.values = mappedValues;
-	    	targetClaims.add(c);
-    	}
-    }
-    
-    // Claim merge
-    var firstNameClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname';
-    var lastNameClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname';
-    var firstName;
-    var lastName;
-    var issuer;
-    for (c : sourceClaims) {
-    	if(c.claimType == firstNameClaimType) {
-    		firstName = c.values[0];
-    		issuer = c.issuer;
-    	} else if(c.claimType == lastNameClaimType) {
-    		lastName = c.values[0];
-    	}
-    }
-    if (firstName != null && lastName != null) {
-    	var claim = new("org.apache.cxf.sts.claims.ProcessedClaim");
-    	claim.issuer = issuer;
-    	claim.claimType = new("java.net.URI", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name");
-    	claim.addValue(firstName + " " + lastName);
-    	targetClaims.add(claim);
-    }
-    
-    // Additional static claim
-    var idpClaim = new("org.apache.cxf.sts.claims.ProcessedClaim");
-    idpClaim.claimType = new("java.net.URI", "http://schemas.microsoft.com/identity/claims/identityprovider");
-    idpClaim.value = "https://idp.apache.org/cbb375d-33b-45fa-9bf5-f33bd8721a77/";
-    targetClaims.add(idpClaim);
-    
-    // Claim value updates
-    var uppercaseClaim = new("org.apache.cxf.sts.claims.ProcessedClaim");
-    uppercaseClaim.claimType = new("java.net.URI", "http://my.schema.org/identity/claims/uppercase");
-    uppercaseClaim.values.add("Value");
-    uppercaseClaim.values.add("Value2");
-    var newValues = new("java.util.ArrayList");
-    for (v : uppercaseClaim.values) {
-    	newValue = v.toUpperCase();
-    	newValues.add(newValue);
-    }
-    uppercaseClaim.values = newValues;
-    targetClaims.add(uppercaseClaim);
-    
-    var lowercaseClaim = new("org.apache.cxf.sts.claims.ProcessedClaim");
-    lowercaseClaim.claimType = new("java.net.URI", "http://my.schema.org/identity/claims/lowercase");
-    lowercaseClaim.values.add("Value");
-    lowercaseClaim.values.add("Value2");
-    var newValues = new("java.util.ArrayList");
-    for (v : lowercaseClaim.values) {
-    	newValue = v.toLowerCase();
-    	newValues.add(newValue);
-    }
-    lowercaseClaim.values = newValues;
-    targetClaims.add(lowercaseClaim);
-    
-    var wrappedUppercaseClaim = new("org.apache.cxf.sts.claims.ProcessedClaim");
-    wrappedUppercaseClaim.claimType = new("java.net.URI", "http://my.schema.org/identity/claims/wrappedUppercase");
-    wrappedUppercaseClaim.values.add("Value");
-    var newValues = new("java.util.ArrayList");
-    for (v : wrappedUppercaseClaim.values) {
-    	newValue = "Prefix_" + v + "_Suffix";
-    	newValues.add(newValue);
-    }
-    wrappedUppercaseClaim.values = newValues;
-    var newValues = new("java.util.ArrayList");
-    for (v : wrappedUppercaseClaim.values) {
-    	newValue = v.toUpperCase();
-    	newValues.add(newValue);
-    }
-    wrappedUppercaseClaim.values = newValues;
-    targetClaims.add(wrappedUppercaseClaim);
-    
-    // Direct copy
-    var emailClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mail';
-    for (c : sourceClaims) {
-    	if(c.claimType == emailClaimType) {
-    		targetClaims.add(c);
-    	}
-    }
-    
-    // Set correct issuer
-    for (c : targetClaims) {
-    	if(c.originalIssuer == null) {
-    		c.originalIssuer = c.issuer;
-    	}
-    	c.issuer = claimsParameters.stsProperties.issuer;
-    }
-    
-    // Return new claims
-    return targetClaims;
-}

http://git-wip-us.apache.org/repos/asf/cxf/blob/31c80946/services/sts/sts-core/src/test/resources/jexlClaimMappingsWithFunctions.script
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/test/resources/jexlClaimMappingsWithFunctions.script b/services/sts/sts-core/src/test/resources/jexlClaimMappingsWithFunctions.script
new file mode 100644
index 0000000..af5bb35
--- /dev/null
+++ b/services/sts/sts-core/src/test/resources/jexlClaimMappingsWithFunctions.script
@@ -0,0 +1,60 @@
+/**
+ * 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.
+ */
+
+{
+    // Role value mapping
+    var roleClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role';
+    var roleClaim = claims:get(sourceClaims, roleClaimType);
+    var roleMappings = { "admin" : "administrator", "manager" : "manager" };
+    var mappedRoles = claims:mapValues(roleClaim, roleMappings, false);
+    
+    // Claim merge
+    var delimiter = ' ';
+    var firstNameClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname';
+    var lastNameClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname';
+    var fullNameClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name';
+    var mergedClaim = claims:merge(sourceClaims, fullNameClaimType, delimiter, firstNameClaimType, lastNameClaimType);
+    
+    // Additional static claim
+    var idpClaim = claims:create("http://schemas.microsoft.com/identity/claims/identityprovider",
+            "https://idp.apache.org/cbb375d-33b-45fa-9bf5-f33bd8721a77/");
+
+    // Claim value updates
+    var uppercaseClaim = claims:create("http://my.schema.org/identity/claims/uppercase", "Value", "Value2");
+    claims:upperCaseValues(uppercaseClaim);
+    var lowercaseClaim = claims:create("http://my.schema.org/identity/claims/lowercase", "Value", "Value2");
+    claims:lowerCaseValues(lowercaseClaim);
+    var wrappedUppercaseClaim = claims:create("http://my.schema.org/identity/claims/wrappedUppercase", "Value");
+    claims:wrapValues(wrappedUppercaseClaim, "Prefix_", "_Suffix");
+    claims:upperCaseValues(wrappedUppercaseClaim);
+
+    // Simple claim copy
+    var emailClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mail';
+    var emailClaim = claims:get(sourceClaims, emailClaimType);
+    
+    // Collect claims for new token
+    claims:add(targetClaims, mappedRoles, mergedClaim, idpClaim);
+    claims:add(targetClaims, uppercaseClaim, lowercaseClaim, wrappedUppercaseClaim, emailClaim);
+    
+    // Set correct issuer
+    claims:updateIssuer(targetClaims, claimsParameters.stsProperties.issuer);
+    
+    // Return new claims
+    return targetClaims;
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/31c80946/services/sts/sts-core/src/test/resources/jexlClaimMappingsWithoutFunctions.script
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/test/resources/jexlClaimMappingsWithoutFunctions.script b/services/sts/sts-core/src/test/resources/jexlClaimMappingsWithoutFunctions.script
new file mode 100644
index 0000000..6b5c4f3
--- /dev/null
+++ b/services/sts/sts-core/src/test/resources/jexlClaimMappingsWithoutFunctions.script
@@ -0,0 +1,127 @@
+/**
+ * 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.
+ */
+
+{
+    // Role value mapping
+    var roleClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role';
+    var roleMappings = { "admin" : "administrator", "manager" : "manager" };
+    
+    for (c : sourceClaims) {
+    	if(c.claimType == roleClaimType) {
+	    	var mappedValues = new("java.util.ArrayList");
+	    	for (v : c.values) {
+	    		var newValue = roleMappings.get(v);
+	    		if (newValue != null) {
+	    			mappedValues.add(newValue);
+	    		}
+	    	}
+	    	c.values = mappedValues;
+	    	targetClaims.add(c);
+    	}
+    }
+    
+    // Claim merge
+    var firstNameClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname';
+    var lastNameClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname';
+    var firstName;
+    var lastName;
+    var issuer;
+    for (c : sourceClaims) {
+    	if(c.claimType == firstNameClaimType) {
+    		firstName = c.values[0];
+    		issuer = c.issuer;
+    	} else if(c.claimType == lastNameClaimType) {
+    		lastName = c.values[0];
+    	}
+    }
+    if (firstName != null && lastName != null) {
+    	var claim = new("org.apache.cxf.sts.claims.ProcessedClaim");
+    	claim.issuer = issuer;
+    	claim.claimType = new("java.net.URI", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name");
+    	claim.addValue(firstName + " " + lastName);
+    	targetClaims.add(claim);
+    }
+    
+    // Additional static claim
+    var idpClaim = new("org.apache.cxf.sts.claims.ProcessedClaim");
+    idpClaim.claimType = new("java.net.URI", "http://schemas.microsoft.com/identity/claims/identityprovider");
+    idpClaim.value = "https://idp.apache.org/cbb375d-33b-45fa-9bf5-f33bd8721a77/";
+    targetClaims.add(idpClaim);
+    
+    // Claim value updates
+    var uppercaseClaim = new("org.apache.cxf.sts.claims.ProcessedClaim");
+    uppercaseClaim.claimType = new("java.net.URI", "http://my.schema.org/identity/claims/uppercase");
+    uppercaseClaim.values.add("Value");
+    uppercaseClaim.values.add("Value2");
+    var newValues = new("java.util.ArrayList");
+    for (v : uppercaseClaim.values) {
+    	newValue = v.toUpperCase();
+    	newValues.add(newValue);
+    }
+    uppercaseClaim.values = newValues;
+    targetClaims.add(uppercaseClaim);
+    
+    var lowercaseClaim = new("org.apache.cxf.sts.claims.ProcessedClaim");
+    lowercaseClaim.claimType = new("java.net.URI", "http://my.schema.org/identity/claims/lowercase");
+    lowercaseClaim.values.add("Value");
+    lowercaseClaim.values.add("Value2");
+    var newValues = new("java.util.ArrayList");
+    for (v : lowercaseClaim.values) {
+    	newValue = v.toLowerCase();
+    	newValues.add(newValue);
+    }
+    lowercaseClaim.values = newValues;
+    targetClaims.add(lowercaseClaim);
+    
+    var wrappedUppercaseClaim = new("org.apache.cxf.sts.claims.ProcessedClaim");
+    wrappedUppercaseClaim.claimType = new("java.net.URI", "http://my.schema.org/identity/claims/wrappedUppercase");
+    wrappedUppercaseClaim.values.add("Value");
+    var newValues = new("java.util.ArrayList");
+    for (v : wrappedUppercaseClaim.values) {
+    	newValue = "Prefix_" + v + "_Suffix";
+    	newValues.add(newValue);
+    }
+    wrappedUppercaseClaim.values = newValues;
+    var newValues = new("java.util.ArrayList");
+    for (v : wrappedUppercaseClaim.values) {
+    	newValue = v.toUpperCase();
+    	newValues.add(newValue);
+    }
+    wrappedUppercaseClaim.values = newValues;
+    targetClaims.add(wrappedUppercaseClaim);
+    
+    // Direct copy
+    var emailClaimType = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mail';
+    for (c : sourceClaims) {
+    	if(c.claimType == emailClaimType) {
+    		targetClaims.add(c);
+    	}
+    }
+    
+    // Set correct issuer
+    for (c : targetClaims) {
+    	if(c.originalIssuer == null) {
+    		c.originalIssuer = c.issuer;
+    	}
+    	c.issuer = claimsParameters.stsProperties.issuer;
+    }
+    
+    // Return new claims
+    return targetClaims;
+}


[4/5] git commit: Merge branch 'master' of https://github.com/janbernhardt/cxf

Posted by co...@apache.org.
Merge branch 'master' of https://github.com/janbernhardt/cxf


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/213b5024
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/213b5024
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/213b5024

Branch: refs/heads/master
Commit: 213b50240f49a141c507c07d127a4f5043eb77af
Parents: b9c91a7 fdb7dd8
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Wed Aug 6 16:03:46 2014 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Wed Aug 6 16:03:46 2014 +0100

----------------------------------------------------------------------
 parent/pom.xml                                  |   1 +
 services/sts/sts-core/pom.xml                   |   6 +
 .../cxf/sts/claims/mapper/ClaimUtils.java       | 281 +++++++++++++++++++
 .../cxf/sts/claims/mapper/JexlClaimsMapper.java |  85 ++++++
 .../sts/claims/mapper/JexlClaimsMapperTest.java | 224 +++++++++++++++
 .../jexlClaimMappingsWithFunctions.script       |  60 ++++
 .../jexlClaimMappingsWithoutFunctions.script    | 127 +++++++++
 7 files changed, 784 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/213b5024/parent/pom.xml
----------------------------------------------------------------------


[3/5] git commit: [CXF-5925] Making JEXL dependency optional and moving version to parent pom.xml

Posted by co...@apache.org.
[CXF-5925] Making JEXL dependency optional and moving version to parent pom.xml


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/fdb7dd81
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/fdb7dd81
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/fdb7dd81

Branch: refs/heads/master
Commit: fdb7dd81e047c20d7ef7aec156716c855615ea9c
Parents: 31c8094
Author: Jan Bernhardt <jb...@talend.com>
Authored: Tue Aug 5 11:48:16 2014 +0200
Committer: Jan Bernhardt <jb...@talend.com>
Committed: Tue Aug 5 11:48:16 2014 +0200

----------------------------------------------------------------------
 parent/pom.xml                | 1 +
 services/sts/sts-core/pom.xml | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/fdb7dd81/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index e010fbf..174333f 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -189,6 +189,7 @@
         <cxf.jdom.bundle.version>1.1_4</cxf.jdom.bundle.version>
         <cxf.olingo.version>1.2.0</cxf.olingo.version>
         <cxf.tika.version>1.5</cxf.tika.version>
+		<cxf.jexl.version>2.1.1</cxf.jexl.version>
         <cxf.checkstyle.extension />
         <cxf.jaxb.context.class />
         <cxf.spring.validation.mode>VALIDATION_AUTO</cxf.spring.validation.mode>

http://git-wip-us.apache.org/repos/asf/cxf/blob/fdb7dd81/services/sts/sts-core/pom.xml
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/pom.xml b/services/sts/sts-core/pom.xml
index f63f98b..e396384 100644
--- a/services/sts/sts-core/pom.xml
+++ b/services/sts/sts-core/pom.xml
@@ -124,7 +124,8 @@
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-jexl</artifactId>
-            <version>2.1.1</version>
+            <version>${cxf.jexl.version}</version>
+			<optional>true</optional>
         </dependency>
     </dependencies>
     <build>


[5/5] git commit: Removing some tabs

Posted by co...@apache.org.
Removing some tabs


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/bf879ad9
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/bf879ad9
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/bf879ad9

Branch: refs/heads/master
Commit: bf879ad99c873cb718b7ca2b1879270a44e03734
Parents: 213b502
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Wed Aug 6 16:17:12 2014 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Wed Aug 6 16:17:12 2014 +0100

----------------------------------------------------------------------
 parent/pom.xml                | 2 +-
 services/sts/sts-core/pom.xml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/bf879ad9/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index 04cfc8e..33b4b82 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -191,7 +191,7 @@
         <cxf.jdom.bundle.version>1.1_4</cxf.jdom.bundle.version>
         <cxf.olingo.version>1.2.0</cxf.olingo.version>
         <cxf.tika.version>1.5</cxf.tika.version>
-		<cxf.jexl.version>2.1.1</cxf.jexl.version>
+        <cxf.jexl.version>2.1.1</cxf.jexl.version>
         <cxf.checkstyle.extension />
         <cxf.jaxb.context.class />
         <cxf.spring.validation.mode>VALIDATION_AUTO</cxf.spring.validation.mode>

http://git-wip-us.apache.org/repos/asf/cxf/blob/bf879ad9/services/sts/sts-core/pom.xml
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/pom.xml b/services/sts/sts-core/pom.xml
index e396384..2319410 100644
--- a/services/sts/sts-core/pom.xml
+++ b/services/sts/sts-core/pom.xml
@@ -125,7 +125,7 @@
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-jexl</artifactId>
             <version>${cxf.jexl.version}</version>
-			<optional>true</optional>
+            <optional>true</optional>
         </dependency>
     </dependencies>
     <build>