You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2017/11/06 12:57:20 UTC
[1/6] syncope git commit: More robust ConnObjectKey handling
Repository: syncope
Updated Branches:
refs/heads/2_0_X 149b91000 -> 1c469ae17
refs/heads/master 3d4f233cc -> 4989ffd04
More robust ConnObjectKey handling
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/b978fbec
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/b978fbec
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/b978fbec
Branch: refs/heads/2_0_X
Commit: b978fbecc404f992ea03b6eedfe344d68bdef164
Parents: 149b910
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Nov 6 09:08:33 2017 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Nov 6 09:08:33 2017 +0100
----------------------------------------------------------------------
.../provisioning/java/MappingManagerImpl.java | 24 ++++++++++----------
1 file changed, 12 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/b978fbec/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
index 40ebcd1..d640187 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
@@ -191,18 +191,18 @@ public class MappingManagerImpl implements MappingManager {
}
}
- Attribute connObjectKeyExtAttr =
- AttributeUtil.find(MappingUtils.getConnObjectKeyItem(provision).getExtAttrName(), attributes);
- if (connObjectKeyExtAttr != null) {
- attributes.remove(connObjectKeyExtAttr);
- attributes.add(AttributeBuilder.build(
- MappingUtils.getConnObjectKeyItem(provision).getExtAttrName(), connObjectKey));
- }
- Name name = MappingUtils.evaluateNAME(any, provision, connObjectKey);
- attributes.add(name);
- if (connObjectKey != null && !connObjectKey.equals(name.getNameValue()) && connObjectKeyExtAttr == null) {
- attributes.add(AttributeBuilder.build(
- MappingUtils.getConnObjectKeyItem(provision).getExtAttrName(), connObjectKey));
+ MappingItem connObjectKeyItem = MappingUtils.getConnObjectKeyItem(provision);
+ if (connObjectKeyItem != null) {
+ Attribute connObjectKeyExtAttr = AttributeUtil.find(connObjectKeyItem.getExtAttrName(), attributes);
+ if (connObjectKeyExtAttr != null) {
+ attributes.remove(connObjectKeyExtAttr);
+ attributes.add(AttributeBuilder.build(connObjectKeyItem.getExtAttrName(), connObjectKey));
+ }
+ Name name = MappingUtils.evaluateNAME(any, provision, connObjectKey);
+ attributes.add(name);
+ if (connObjectKey != null && !connObjectKey.equals(name.getNameValue()) && connObjectKeyExtAttr == null) {
+ attributes.add(AttributeBuilder.build(connObjectKeyItem.getExtAttrName(), connObjectKey));
+ }
}
if (enable != null) {
[2/6] syncope git commit: White noise: javadocs cleanup
Posted by il...@apache.org.
White noise: javadocs cleanup
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/99a9f1a7
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/99a9f1a7
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/99a9f1a7
Branch: refs/heads/2_0_X
Commit: 99a9f1a7fc1ff5e5bccea76536741d17db523744
Parents: b978fbe
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Nov 6 12:50:43 2017 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Nov 6 12:50:43 2017 +0100
----------------------------------------------------------------------
.../syncope/core/persistence/api/search/SearchCondConverter.java | 3 +--
.../syncope/core/persistence/api/search/SearchCondVisitor.java | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/99a9f1a7/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondConverter.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondConverter.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondConverter.java
index 1ec0f6f..257ba7f 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondConverter.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondConverter.java
@@ -35,12 +35,11 @@ import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
public final class SearchCondConverter {
/**
- * Parses a FIQL expression into Syncope's <tt>SearchCond</tt>, using CXF's <tt>FiqlParser</tt>.
+ * Parses a FIQL expression into Syncope's {@link SearchCond}, using {@link SyncopeFiqlParser}.
*
* @param fiql FIQL string
* @param realms optional realm to provide to {@link SearchCondVisitor}
* @return {@link SearchCond} instance for given FIQL expression
- * @see SyncopeFiqlParser
*/
public static SearchCond convert(final String fiql, final String... realms) {
SyncopeFiqlParser<SearchBean> parser = new SyncopeFiqlParser<>(
http://git-wip-us.apache.org/repos/asf/syncope/blob/99a9f1a7/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
index f81adc2..e9e5951 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
@@ -46,7 +46,7 @@ import org.apache.syncope.core.persistence.api.dao.search.RelationshipCond;
import org.apache.syncope.core.persistence.api.dao.search.RelationshipTypeCond;
/**
- * Converts CXF's <tt>SearchCondition</tt> into internal <tt>SearchCond</tt>.
+ * Visits CXF's {@link SearchBean} and produces {@link SearchCond}.
*/
public class SearchCondVisitor extends AbstractSearchConditionVisitor<SearchBean, SearchCond> {
[6/6] syncope git commit: [SYNCOPE-152] SCIM filter
Posted by il...@apache.org.
[SYNCOPE-152] SCIM filter
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/4989ffd0
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/4989ffd0
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/4989ffd0
Branch: refs/heads/master
Commit: 4989ffd040f82cd76fba0d52b61cb9b8bd405ee5
Parents: 9129ee0
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Nov 6 13:50:09 2017 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Nov 6 13:57:02 2017 +0100
----------------------------------------------------------------------
ext/scimv2/logic/pom.xml | 27 +++
.../syncope/core/logic/scim/SCIMFilter.g4 | 77 ++++++++
.../core/logic/scim/SCIMFilterErrorHandler.java | 42 +++++
.../core/logic/scim/SearchCondConverter.java | 56 ++++++
.../core/logic/scim/SearchCondVisitor.java | 174 +++++++++++++++++++
.../syncope/core/logic/scim/SCIMFilterTest.java | 125 +++++++++++++
.../syncope/ext/scimv2/api/data/Group.java | 2 +-
.../syncope/ext/scimv2/api/data/Member.java | 2 +-
.../syncope/ext/scimv2/api/data/SCIMError.java | 5 +
.../ext/scimv2/cxf/SCIMExceptionMapper.java | 10 +-
.../scimv2/cxf/service/AbstractSCIMService.java | 7 +-
.../org/apache/syncope/fit/core/SCIMITCase.java | 56 ++++++
pom.xml | 14 ++
13 files changed, 587 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/ext/scimv2/logic/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/pom.xml b/ext/scimv2/logic/pom.xml
index abc90b1..4569445 100644
--- a/ext/scimv2/logic/pom.xml
+++ b/ext/scimv2/logic/pom.xml
@@ -35,6 +35,7 @@ under the License.
<properties>
<rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ <antlr4.visitor>true</antlr4.visitor>
</properties>
<dependencies>
@@ -49,6 +50,17 @@ under the License.
<artifactId>syncope-ext-scimv2-scim-rest-api</artifactId>
<version>${project.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-runtime</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
@@ -56,6 +68,21 @@ under the License.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
+ <configuration>
+ <sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>antlr4</goal>
+ </goals>
+ </execution>
+ </executions>
</plugin>
</plugins>
</build>
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/ext/scimv2/logic/src/main/antlr4/org/apache/syncope/core/logic/scim/SCIMFilter.g4
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/antlr4/org/apache/syncope/core/logic/scim/SCIMFilter.g4 b/ext/scimv2/logic/src/main/antlr4/org/apache/syncope/core/logic/scim/SCIMFilter.g4
new file mode 100644
index 0000000..ffddf32
--- /dev/null
+++ b/ext/scimv2/logic/src/main/antlr4/org/apache/syncope/core/logic/scim/SCIMFilter.g4
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+grammar SCIMFilter;
+
+options
+{
+ language = Java;
+}
+
+scimFilter
+ : expression* EOF
+ ;
+
+expression
+ : NOT WS+? expression # NOT_EXPR
+ | expression WS+? AND WS+? expression # EXPR_AND_EXPR
+ | expression WS+? OR WS+ expression # EXPR_OR_EXPR
+ | expression WS+? operator WS+? expression # EXPR_OPER_EXPR
+ | ATTRNAME WS+? PR # ATTR_PR
+ | ATTRNAME WS+? operator WS+? expression # ATTR_OPER_EXPR
+ | ATTRNAME WS+? operator WS+? criteria # ATTR_OPER_CRITERIA
+ | LPAREN WS*? expression WS*? RPAREN # LPAREN_EXPR_RPAREN
+ | ATTRNAME LBRAC WS*? expression WS*? RBRAC # LBRAC_EXPR_RBRAC
+ ;
+
+criteria : '"' .+? '"';
+
+operator
+ : EQ | NE | CO | SW | EW | GT | LT | GE | LE
+ ;
+
+EQ : [eE][qQ];
+NE : [nN][eE];
+CO : [cC][oO];
+SW : [sS][wW];
+EW : [eE][wW];
+GT : [gG][tT];
+LT : [lL][tT];
+GE : [gG][eE];
+LE : [lL][eE];
+
+NOT : [nN][oO][tT];
+
+AND : [aA][nN][dD];
+OR : [oO][rR];
+
+PR : [pP][rR];
+
+LPAREN : '(';
+RPAREN : ')';
+
+LBRAC : '[';
+RBRAC : ']';
+
+WS : ' ';
+
+ATTRNAME : [-_.:a-zA-Z0-9]+;
+
+ANY : ~('"' | '(' | ')' | '[' | ']');
+
+EOL : [\t\r\n\u000C]+ -> skip;
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMFilterErrorHandler.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMFilterErrorHandler.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMFilterErrorHandler.java
new file mode 100644
index 0000000..db2bfbd
--- /dev/null
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMFilterErrorHandler.java
@@ -0,0 +1,42 @@
+/*
+ * 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.syncope.core.logic.scim;
+
+import org.antlr.v4.runtime.DefaultErrorStrategy;
+import org.antlr.v4.runtime.InputMismatchException;
+import org.antlr.v4.runtime.Parser;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Token;
+
+public class SCIMFilterErrorHandler extends DefaultErrorStrategy {
+
+ @Override
+ public void recover(final Parser recognizer, final RecognitionException e) {
+ throw e;
+ }
+
+ @Override
+ public Token recoverInline(final Parser recognizer) throws RecognitionException {
+ throw new InputMismatchException(recognizer);
+ }
+
+ @Override
+ public void sync(final Parser recognizer) throws RecognitionException {
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondConverter.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondConverter.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondConverter.java
new file mode 100644
index 0000000..fd45f43
--- /dev/null
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondConverter.java
@@ -0,0 +1,56 @@
+/*
+ * 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.syncope.core.logic.scim;
+
+import org.antlr.v4.runtime.CharStreams;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.ext.scimv2.api.SCIMBadRequestException;
+import org.apache.syncope.ext.scimv2.api.type.ErrorType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Converts SCIM filter expressions to Syncope's {@link SearchCond}.
+ */
+public final class SearchCondConverter {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SearchCondConverter.class);
+
+ public static SearchCond convert(final String filter) {
+ SCIMFilterParser parser = new SCIMFilterParser(new CommonTokenStream(
+ new SCIMFilterLexer(CharStreams.fromString(filter))));
+ parser.setBuildParseTree(true);
+ parser.setTrimParseTree(true);
+ parser.setProfile(true);
+ parser.removeErrorListeners();
+ parser.setErrorHandler(new SCIMFilterErrorHandler());
+
+ try {
+ return new SearchCondVisitor().visit(parser.scimFilter());
+ } catch (Exception e) {
+ LOG.error("Could not parse {}", filter, e);
+ throw new SCIMBadRequestException(ErrorType.invalidFilter, e.getMessage());
+ }
+ }
+
+ private SearchCondConverter() {
+ // empty constructor for static utility class
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondVisitor.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondVisitor.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondVisitor.java
new file mode 100644
index 0000000..1882505
--- /dev/null
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondVisitor.java
@@ -0,0 +1,174 @@
+/*
+ * 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.syncope.core.logic.scim;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
+import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.ext.scimv2.api.type.Resource;
+
+/**
+ * Visits SCIM filter expression and produces {@link SearchCond}.
+ */
+public class SearchCondVisitor extends SCIMFilterBaseVisitor<SearchCond> {
+
+ @Override
+ public SearchCond visitScimFilter(final SCIMFilterParser.ScimFilterContext ctx) {
+ return visit(ctx.expression(0));
+ }
+
+ private AttributeCond createAttributeCond(final String schema) {
+ AttributeCond attributeCond;
+ if ("userName".equalsIgnoreCase(schema)
+ || (Resource.User.schema() + ":userName").equalsIgnoreCase(schema)) {
+
+ attributeCond = new AnyCond();
+ attributeCond.setSchema("username");
+ } else if ("displayName".equalsIgnoreCase(schema)
+ || (Resource.Group.schema() + ":displayName").equalsIgnoreCase(schema)) {
+
+ attributeCond = new AnyCond();
+ attributeCond.setSchema("name");
+ } else if ("meta.created".equals(schema)) {
+ attributeCond = new AnyCond();
+ attributeCond.setSchema("creationDate");
+ } else if ("meta.lastModified".equals(schema)) {
+ attributeCond = new AnyCond();
+ attributeCond.setSchema("lastChangeDate");
+ } else {
+ attributeCond = new AttributeCond();
+ attributeCond.setSchema(schema);
+ }
+
+ return attributeCond;
+ }
+
+ private SearchCond transform(final String operator, final String left, final String right) {
+ AttributeCond attributeCond = createAttributeCond(left);
+ attributeCond.setExpression(StringUtils.strip(right, "\""));
+
+ switch (operator) {
+ case "eq":
+ default:
+ attributeCond.setType(AttributeCond.Type.IEQ);
+ break;
+
+ case "ne":
+ attributeCond.setType(AttributeCond.Type.IEQ);
+ break;
+
+ case "sw":
+ attributeCond.setType(AttributeCond.Type.ILIKE);
+ attributeCond.setExpression(attributeCond.getExpression() + "%");
+ break;
+
+ case "co":
+ attributeCond.setType(AttributeCond.Type.ILIKE);
+ attributeCond.setExpression("%" + attributeCond.getExpression() + "%");
+ break;
+
+ case "ew":
+ attributeCond.setType(AttributeCond.Type.ILIKE);
+ attributeCond.setExpression("%" + attributeCond.getExpression());
+ break;
+
+ case "gt":
+ attributeCond.setType(AttributeCond.Type.GT);
+ break;
+
+ case "ge":
+ attributeCond.setType(AttributeCond.Type.GE);
+ break;
+
+ case "lt":
+ attributeCond.setType(AttributeCond.Type.LT);
+ break;
+
+ case "le":
+ attributeCond.setType(AttributeCond.Type.LE);
+ break;
+
+ }
+
+ return "ne".equals(operator)
+ ? SearchCond.getNotLeafCond(attributeCond)
+ : SearchCond.getLeafCond(attributeCond);
+ }
+
+ @Override
+ public SearchCond visitEXPR_OPER_EXPR(final SCIMFilterParser.EXPR_OPER_EXPRContext ctx) {
+ return transform(ctx.operator().getText(), ctx.expression(0).getText(), ctx.expression(1).getText());
+ }
+
+ @Override
+ public SearchCond visitATTR_OPER_CRITERIA(final SCIMFilterParser.ATTR_OPER_CRITERIAContext ctx) {
+ return transform(ctx.operator().getText(), ctx.ATTRNAME().getText(), ctx.criteria().getText());
+ }
+
+ @Override
+ public SearchCond visitATTR_OPER_EXPR(final SCIMFilterParser.ATTR_OPER_EXPRContext ctx) {
+ return transform(ctx.operator().getText(), ctx.ATTRNAME().getText(), ctx.expression().getText());
+ }
+
+ @Override
+ public SearchCond visitATTR_PR(final SCIMFilterParser.ATTR_PRContext ctx) {
+ AttributeCond cond = createAttributeCond(ctx.ATTRNAME().getText());
+ cond.setType(AttributeCond.Type.ISNOTNULL);
+ return SearchCond.getLeafCond(cond);
+ }
+
+ @Override
+ public SearchCond visitLPAREN_EXPR_RPAREN(final SCIMFilterParser.LPAREN_EXPR_RPARENContext ctx) {
+ return visit(ctx.expression());
+ }
+
+ @Override
+ public SearchCond visitNOT_EXPR(final SCIMFilterParser.NOT_EXPRContext ctx) {
+ SearchCond cond = visit(ctx.expression());
+ if (cond.getAttributeCond() != null) {
+ if (cond.getAttributeCond().getType() == AttributeCond.Type.ISNULL) {
+ cond.getAttributeCond().setType(AttributeCond.Type.ISNOTNULL);
+ } else if (cond.getAttributeCond().getType() == AttributeCond.Type.ISNOTNULL) {
+ cond.getAttributeCond().setType(AttributeCond.Type.ISNULL);
+ }
+ } else if (cond.getAnyCond() != null) {
+ if (cond.getAnyCond().getType() == AnyCond.Type.ISNULL) {
+ cond.getAnyCond().setType(AnyCond.Type.ISNOTNULL);
+ } else if (cond.getAnyCond().getType() == AnyCond.Type.ISNOTNULL) {
+ cond.getAnyCond().setType(AnyCond.Type.ISNULL);
+ }
+ } else {
+ cond = SearchCond.getNotLeafCond(cond);
+ }
+
+ return cond;
+ }
+
+ @Override
+ public SearchCond visitEXPR_AND_EXPR(final SCIMFilterParser.EXPR_AND_EXPRContext ctx) {
+ return SearchCond.getAndCond(visit(ctx.expression(0)), visit(ctx.expression(1)));
+ }
+
+ @Override
+ public SearchCond visitEXPR_OR_EXPR(final SCIMFilterParser.EXPR_OR_EXPRContext ctx) {
+ return SearchCond.getOrCond(visit(ctx.expression(0)), visit(ctx.expression(1)));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/ext/scimv2/logic/src/test/java/org/apache/syncope/core/logic/scim/SCIMFilterTest.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/test/java/org/apache/syncope/core/logic/scim/SCIMFilterTest.java b/ext/scimv2/logic/src/test/java/org/apache/syncope/core/logic/scim/SCIMFilterTest.java
new file mode 100644
index 0000000..d488725
--- /dev/null
+++ b/ext/scimv2/logic/src/test/java/org/apache/syncope/core/logic/scim/SCIMFilterTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.syncope.core.logic.scim;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.junit.jupiter.api.Test;
+
+public class SCIMFilterTest {
+
+ @Test
+ public void eq() {
+ SearchCond cond = SearchCondConverter.convert("userName eq \"bjensen\"");
+ assertNotNull(cond);
+ assertNotNull(cond.getAnyCond());
+ assertEquals("username", cond.getAnyCond().getSchema());
+ assertEquals(AttributeCond.Type.IEQ, cond.getAnyCond().getType());
+ assertEquals("bjensen", cond.getAnyCond().getExpression());
+ }
+
+ @Test
+ public void sw() {
+ SearchCond cond = SearchCondConverter.convert("userName sw \"J\"");
+ assertNotNull(cond);
+ assertNotNull(cond.getAnyCond());
+ assertEquals("username", cond.getAnyCond().getSchema());
+ assertEquals(AttributeCond.Type.ILIKE, cond.getAnyCond().getType());
+ assertEquals("J%", cond.getAnyCond().getExpression());
+
+ SearchCond fqn = SearchCondConverter.convert("urn:ietf:params:scim:schemas:core:2.0:User:userName sw \"J\"");
+ assertEquals(cond, fqn);
+ }
+
+ @Test
+ public void pr() {
+ SearchCond cond = SearchCondConverter.convert("title pr");
+ assertNotNull(cond);
+ assertNotNull(cond.getAttributeCond());
+ assertEquals("title", cond.getAttributeCond().getSchema());
+ assertEquals(AttributeCond.Type.ISNOTNULL, cond.getAttributeCond().getType());
+ assertNull(cond.getAttributeCond().getExpression());
+ }
+
+ @Test
+ public void gt() {
+ SearchCond cond = SearchCondConverter.convert("meta.lastModified gt \"2011-05-13T04:42:34Z\"");
+ assertNotNull(cond);
+ assertNotNull(cond.getAnyCond());
+ assertEquals("lastChangeDate", cond.getAnyCond().getSchema());
+ assertEquals(AttributeCond.Type.GT, cond.getAnyCond().getType());
+ assertEquals("2011-05-13T04:42:34Z", cond.getAnyCond().getExpression());
+ }
+
+ @Test
+ public void not() {
+ SearchCond cond = SearchCondConverter.convert("not (title pr)");
+ assertNotNull(cond);
+ assertNotNull(cond.getAttributeCond());
+ assertEquals("title", cond.getAttributeCond().getSchema());
+ assertEquals(AttributeCond.Type.ISNULL, cond.getAttributeCond().getType());
+ assertNull(cond.getAttributeCond().getExpression());
+ }
+
+ @Test
+ public void and() {
+ SearchCond cond = SearchCondConverter.convert("title pr and userName sw \"J\"");
+ assertNotNull(cond);
+ assertEquals(SearchCond.Type.AND, cond.getType());
+
+ SearchCond left = cond.getLeftSearchCond();
+ assertNotNull(left);
+ assertNotNull(left.getAttributeCond());
+ assertEquals("title", left.getAttributeCond().getSchema());
+ assertEquals(AttributeCond.Type.ISNOTNULL, left.getAttributeCond().getType());
+ assertNull(left.getAttributeCond().getExpression());
+
+ SearchCond right = cond.getRightSearchCond();
+ assertNotNull(right);
+ assertNotNull(right.getAnyCond());
+ assertEquals("username", right.getAnyCond().getSchema());
+ assertEquals(AttributeCond.Type.ILIKE, right.getAnyCond().getType());
+ assertEquals("J%", right.getAnyCond().getExpression());
+ }
+
+ @Test
+ public void or() {
+ SearchCond cond = SearchCondConverter.convert("title pr or displayName eq \"Other\"");
+ assertNotNull(cond);
+ assertEquals(SearchCond.Type.OR, cond.getType());
+
+ SearchCond left = cond.getLeftSearchCond();
+ assertNotNull(left);
+ assertNotNull(left.getAttributeCond());
+ assertEquals("title", left.getAttributeCond().getSchema());
+ assertEquals(AttributeCond.Type.ISNOTNULL, left.getAttributeCond().getType());
+ assertNull(left.getAttributeCond().getExpression());
+
+ SearchCond right = cond.getRightSearchCond();
+ assertNotNull(right);
+ assertNotNull(right.getAnyCond());
+ assertEquals("name", right.getAnyCond().getSchema());
+ assertEquals(AttributeCond.Type.IEQ, right.getAnyCond().getType());
+ assertEquals("Other", right.getAnyCond().getExpression());
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Group.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Group.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Group.java
index f64b837..f84d559 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Group.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Group.java
@@ -39,7 +39,7 @@ public class Group extends Reference {
@JsonProperty("display") final String display,
@JsonProperty("type") final Function type) {
- super(value, ref, display);
+ super(value, display, ref);
this.type = type;
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Member.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Member.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Member.java
index aa2f5dd..902217d 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Member.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Member.java
@@ -37,7 +37,7 @@ public class Member extends Reference {
@JsonProperty("display") final String display,
@JsonProperty("type") final Resource type) {
- super(value, ref, display);
+ super(value, display, ref);
this.type = type;
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMError.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMError.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMError.java
index d7112d1..f0548c4 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMError.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMError.java
@@ -24,6 +24,7 @@ import com.fasterxml.jackson.annotation.JsonFormat.Shape;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Arrays;
import java.util.List;
+import org.apache.syncope.ext.scimv2.api.SCIMBadRequestException;
import org.apache.syncope.ext.scimv2.api.type.ErrorType;
import org.apache.syncope.ext.scimv2.api.type.Resource;
@@ -40,6 +41,10 @@ public class SCIMError extends SCIMBean {
@JsonFormat(shape = Shape.STRING)
private final int status = 400;
+ public SCIMError(final SCIMBadRequestException ex) {
+ this(ex.getErrorType(), ex.getMessage());
+ }
+
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public SCIMError(
@JsonProperty("scimType") final ErrorType scimType,
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/SCIMExceptionMapper.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/SCIMExceptionMapper.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/SCIMExceptionMapper.java
index e525e77..4525d82 100644
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/SCIMExceptionMapper.java
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/SCIMExceptionMapper.java
@@ -41,6 +41,7 @@ import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
import org.apache.syncope.core.workflow.api.WorkflowException;
import org.apache.syncope.ext.scimv2.api.ConflictException;
import org.apache.syncope.ext.scimv2.api.PayloadTooLargeException;
+import org.apache.syncope.ext.scimv2.api.SCIMBadRequestException;
import org.apache.syncope.ext.scimv2.api.data.SCIMError;
import org.apache.syncope.ext.scimv2.api.type.ErrorType;
import org.identityconnectors.framework.common.exceptions.ConfigurationException;
@@ -108,9 +109,7 @@ public class SCIMExceptionMapper implements ExceptionMapper<Exception> {
&& ENTITYEXISTS_EXCLASS.isAssignableFrom(ex.getCause().getClass())) {
builder = builder(ClientExceptionType.EntityExists, ExceptionUtils.getRootCauseMessage(ex));
- } else if (ex instanceof DataIntegrityViolationException
- || JPASYSTEM_EXCLASS.isAssignableFrom(ex.getClass())) {
-
+ } else if (ex instanceof DataIntegrityViolationException || JPASYSTEM_EXCLASS.isAssignableFrom(ex.getClass())) {
builder = builder(ClientExceptionType.DataIntegrityViolation, ExceptionUtils.getRootCauseMessage(ex));
} else if (CONNECTOR_EXCLASS.isAssignableFrom(ex.getClass())) {
builder = builder(ClientExceptionType.ConnectorException, ExceptionUtils.getRootCauseMessage(ex));
@@ -125,7 +124,8 @@ public class SCIMExceptionMapper implements ExceptionMapper<Exception> {
}
// ...or just report as InternalServerError
if (builder == null) {
- builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR);
+ builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR).
+ entity(ExceptionUtils.getRootCauseMessage(ex));
}
}
@@ -188,6 +188,8 @@ public class SCIMExceptionMapper implements ExceptionMapper<Exception> {
return builder(ClientExceptionType.InvalidValues, ExceptionUtils.getRootCauseMessage(ex));
} else if (ex instanceof MalformedPathException) {
return builder(ClientExceptionType.InvalidPath, ExceptionUtils.getRootCauseMessage(ex));
+ } else if (ex instanceof SCIMBadRequestException) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(new SCIMError((SCIMBadRequestException) ex));
}
return null;
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
index cd31e1f..73dbd5a 100644
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
@@ -32,6 +32,7 @@ import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.core.logic.AbstractAnyLogic;
import org.apache.syncope.core.logic.GroupLogic;
import org.apache.syncope.core.logic.UserLogic;
+import org.apache.syncope.core.logic.scim.SearchCondConverter;
import org.apache.syncope.core.persistence.api.dao.AnyDAO;
import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
@@ -189,11 +190,9 @@ abstract class AbstractSCIMService<R extends SCIMResource> implements SCIMServic
throw new UnsupportedOperationException();
}
- int page = startIndex == null || startIndex <= 1 ? 1 : (startIndex / AnyDAO.DEFAULT_PAGE_SIZE) + 1;
-
Pair<Integer, ? extends List<? extends AnyTO>> result = anyLogic(type).search(
- null,
- page,
+ StringUtils.isBlank(filter) ? null : SearchCondConverter.convert(filter),
+ startIndex == null || startIndex <= 1 ? 1 : (startIndex / AnyDAO.DEFAULT_PAGE_SIZE) + 1,
AnyDAO.DEFAULT_PAGE_SIZE,
Collections.<OrderByClause>emptyList(),
SyncopeConstants.ROOT_REALM,
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
index ecc75ba..cc8a92e 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
@@ -27,13 +27,18 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
+import java.text.SimpleDateFormat;
import java.util.Arrays;
+import java.util.Date;
import java.util.List;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.ext.scimv2.api.SCIMConstants;
import org.apache.syncope.ext.scimv2.api.data.ListResponse;
import org.apache.syncope.ext.scimv2.api.data.ResourceType;
@@ -50,6 +55,16 @@ public class SCIMITCase extends AbstractITCase {
public static final String SCIM_ADDRESS = "http://localhost:9080/syncope/scim/v2";
+ private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
+
+ @Override
+ protected SimpleDateFormat initialValue() {
+ SimpleDateFormat sdf = new SimpleDateFormat();
+ sdf.applyPattern(SyncopeConstants.DEFAULT_DATE_PATTERN);
+ return sdf;
+ }
+ };
+
private WebClient webClient() {
return WebClient.create(SCIM_ADDRESS, Arrays.asList(new JacksonSCIMJsonProvider())).
accept(SCIMConstants.APPLICATION_SCIM_JSON_TYPE).
@@ -159,4 +174,45 @@ public class SCIMITCase extends AbstractITCase {
assertNotNull(group.getDisplayName());
});
}
+
+ @Test
+ public void search() {
+ assumeTrue(SCIMDetector.isSCIMAvailable(webClient()));
+
+ // eq
+ Response response = webClient().path("Groups").query("filter", "displayName eq \"additional\"").get();
+ assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ assertEquals(
+ SCIMConstants.APPLICATION_SCIM_JSON,
+ StringUtils.substringBefore(response.getHeaderString(HttpHeaders.CONTENT_TYPE), ";"));
+
+ ListResponse<SCIMGroup> groups = response.readEntity(new GenericType<ListResponse<SCIMGroup>>() {
+ });
+ assertNotNull(groups);
+ assertEquals(1, groups.getTotalResults());
+
+ SCIMGroup additional = groups.getResources().get(0);
+ assertEquals("additional", additional.getDisplayName());
+
+ // gt
+ UserTO newUser = userService.create(UserITCase.getUniqueSampleTO("scimsearch@syncope.apache.org")).readEntity(
+ new GenericType<ProvisioningResult<UserTO>>() {
+ }).getEntity();
+
+ Date value = new Date(newUser.getCreationDate().getTime() - 1000);
+ response = webClient().path("Users").query("filter", "meta.created gt \""
+ + DATE_FORMAT.get().format(value) + "\"").get();
+ assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ assertEquals(
+ SCIMConstants.APPLICATION_SCIM_JSON,
+ StringUtils.substringBefore(response.getHeaderString(HttpHeaders.CONTENT_TYPE), ";"));
+
+ ListResponse<SCIMUser> users = response.readEntity(new GenericType<ListResponse<SCIMUser>>() {
+ });
+ assertNotNull(users);
+ assertEquals(1, users.getTotalResults());
+
+ SCIMUser newSCIMUser = users.getResources().get(0);
+ assertEquals(newUser.getUsername(), newSCIMUser.getUserName());
+ }
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/4989ffd0/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 51cfd7f..c8f6e52 100644
--- a/pom.xml
+++ b/pom.xml
@@ -462,6 +462,8 @@ under the License.
<tycho.version>1.0.0</tycho.version>
<netbeans.version>RELEASE82</netbeans.version>
+ <antlr4.version>4.7</antlr4.version>
+
<testds.port>1389</testds.port>
<testdb.webport>9082</testdb.webport>
@@ -1569,6 +1571,12 @@ under the License.
<version>${netbeans.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-runtime</artifactId>
+ <version>${antlr4.version}</version>
+ </dependency>
+
<!-- TEST -->
<dependency>
<groupId>com.github.detro</groupId>
@@ -1935,6 +1943,12 @@ under the License.
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
</plugin>
+
+ <plugin>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-maven-plugin</artifactId>
+ <version>${antlr4.version}</version>
+ </plugin>
</plugins>
</pluginManagement>
[3/6] syncope git commit: [SYNCOPE-152] SCIM filter
Posted by il...@apache.org.
[SYNCOPE-152] SCIM filter
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/1c469ae1
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/1c469ae1
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/1c469ae1
Branch: refs/heads/2_0_X
Commit: 1c469ae175d50acd88282b6bb7081e453157bb6f
Parents: 99a9f1a
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Nov 6 13:50:09 2017 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Nov 6 13:50:09 2017 +0100
----------------------------------------------------------------------
ext/scimv2/logic/pom.xml | 27 +++
.../syncope/core/logic/scim/SCIMFilter.g4 | 77 ++++++++
.../core/logic/scim/SCIMFilterErrorHandler.java | 42 +++++
.../core/logic/scim/SearchCondConverter.java | 56 ++++++
.../core/logic/scim/SearchCondVisitor.java | 174 +++++++++++++++++++
.../syncope/core/logic/scim/SCIMFilterTest.java | 125 +++++++++++++
.../syncope/ext/scimv2/api/data/Group.java | 2 +-
.../syncope/ext/scimv2/api/data/Member.java | 2 +-
.../syncope/ext/scimv2/api/data/SCIMError.java | 5 +
.../ext/scimv2/cxf/SCIMExceptionMapper.java | 10 +-
.../scimv2/cxf/service/AbstractSCIMService.java | 7 +-
.../org/apache/syncope/fit/core/SCIMITCase.java | 56 ++++++
pom.xml | 14 ++
13 files changed, 587 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/ext/scimv2/logic/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/pom.xml b/ext/scimv2/logic/pom.xml
index b127fb8..188d71e 100644
--- a/ext/scimv2/logic/pom.xml
+++ b/ext/scimv2/logic/pom.xml
@@ -35,6 +35,7 @@ under the License.
<properties>
<rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ <antlr4.visitor>true</antlr4.visitor>
</properties>
<dependencies>
@@ -49,6 +50,17 @@ under the License.
<artifactId>syncope-ext-scimv2-scim-rest-api</artifactId>
<version>${project.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-runtime</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
@@ -56,6 +68,21 @@ under the License.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
+ <configuration>
+ <sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>antlr4</goal>
+ </goals>
+ </execution>
+ </executions>
</plugin>
</plugins>
</build>
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/ext/scimv2/logic/src/main/antlr4/org/apache/syncope/core/logic/scim/SCIMFilter.g4
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/antlr4/org/apache/syncope/core/logic/scim/SCIMFilter.g4 b/ext/scimv2/logic/src/main/antlr4/org/apache/syncope/core/logic/scim/SCIMFilter.g4
new file mode 100644
index 0000000..ffddf32
--- /dev/null
+++ b/ext/scimv2/logic/src/main/antlr4/org/apache/syncope/core/logic/scim/SCIMFilter.g4
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+grammar SCIMFilter;
+
+options
+{
+ language = Java;
+}
+
+scimFilter
+ : expression* EOF
+ ;
+
+expression
+ : NOT WS+? expression # NOT_EXPR
+ | expression WS+? AND WS+? expression # EXPR_AND_EXPR
+ | expression WS+? OR WS+ expression # EXPR_OR_EXPR
+ | expression WS+? operator WS+? expression # EXPR_OPER_EXPR
+ | ATTRNAME WS+? PR # ATTR_PR
+ | ATTRNAME WS+? operator WS+? expression # ATTR_OPER_EXPR
+ | ATTRNAME WS+? operator WS+? criteria # ATTR_OPER_CRITERIA
+ | LPAREN WS*? expression WS*? RPAREN # LPAREN_EXPR_RPAREN
+ | ATTRNAME LBRAC WS*? expression WS*? RBRAC # LBRAC_EXPR_RBRAC
+ ;
+
+criteria : '"' .+? '"';
+
+operator
+ : EQ | NE | CO | SW | EW | GT | LT | GE | LE
+ ;
+
+EQ : [eE][qQ];
+NE : [nN][eE];
+CO : [cC][oO];
+SW : [sS][wW];
+EW : [eE][wW];
+GT : [gG][tT];
+LT : [lL][tT];
+GE : [gG][eE];
+LE : [lL][eE];
+
+NOT : [nN][oO][tT];
+
+AND : [aA][nN][dD];
+OR : [oO][rR];
+
+PR : [pP][rR];
+
+LPAREN : '(';
+RPAREN : ')';
+
+LBRAC : '[';
+RBRAC : ']';
+
+WS : ' ';
+
+ATTRNAME : [-_.:a-zA-Z0-9]+;
+
+ANY : ~('"' | '(' | ')' | '[' | ']');
+
+EOL : [\t\r\n\u000C]+ -> skip;
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMFilterErrorHandler.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMFilterErrorHandler.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMFilterErrorHandler.java
new file mode 100644
index 0000000..db2bfbd
--- /dev/null
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMFilterErrorHandler.java
@@ -0,0 +1,42 @@
+/*
+ * 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.syncope.core.logic.scim;
+
+import org.antlr.v4.runtime.DefaultErrorStrategy;
+import org.antlr.v4.runtime.InputMismatchException;
+import org.antlr.v4.runtime.Parser;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Token;
+
+public class SCIMFilterErrorHandler extends DefaultErrorStrategy {
+
+ @Override
+ public void recover(final Parser recognizer, final RecognitionException e) {
+ throw e;
+ }
+
+ @Override
+ public Token recoverInline(final Parser recognizer) throws RecognitionException {
+ throw new InputMismatchException(recognizer);
+ }
+
+ @Override
+ public void sync(final Parser recognizer) throws RecognitionException {
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondConverter.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondConverter.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondConverter.java
new file mode 100644
index 0000000..fd45f43
--- /dev/null
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondConverter.java
@@ -0,0 +1,56 @@
+/*
+ * 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.syncope.core.logic.scim;
+
+import org.antlr.v4.runtime.CharStreams;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.ext.scimv2.api.SCIMBadRequestException;
+import org.apache.syncope.ext.scimv2.api.type.ErrorType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Converts SCIM filter expressions to Syncope's {@link SearchCond}.
+ */
+public final class SearchCondConverter {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SearchCondConverter.class);
+
+ public static SearchCond convert(final String filter) {
+ SCIMFilterParser parser = new SCIMFilterParser(new CommonTokenStream(
+ new SCIMFilterLexer(CharStreams.fromString(filter))));
+ parser.setBuildParseTree(true);
+ parser.setTrimParseTree(true);
+ parser.setProfile(true);
+ parser.removeErrorListeners();
+ parser.setErrorHandler(new SCIMFilterErrorHandler());
+
+ try {
+ return new SearchCondVisitor().visit(parser.scimFilter());
+ } catch (Exception e) {
+ LOG.error("Could not parse {}", filter, e);
+ throw new SCIMBadRequestException(ErrorType.invalidFilter, e.getMessage());
+ }
+ }
+
+ private SearchCondConverter() {
+ // empty constructor for static utility class
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondVisitor.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondVisitor.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondVisitor.java
new file mode 100644
index 0000000..1882505
--- /dev/null
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SearchCondVisitor.java
@@ -0,0 +1,174 @@
+/*
+ * 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.syncope.core.logic.scim;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
+import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.ext.scimv2.api.type.Resource;
+
+/**
+ * Visits SCIM filter expression and produces {@link SearchCond}.
+ */
+public class SearchCondVisitor extends SCIMFilterBaseVisitor<SearchCond> {
+
+ @Override
+ public SearchCond visitScimFilter(final SCIMFilterParser.ScimFilterContext ctx) {
+ return visit(ctx.expression(0));
+ }
+
+ private AttributeCond createAttributeCond(final String schema) {
+ AttributeCond attributeCond;
+ if ("userName".equalsIgnoreCase(schema)
+ || (Resource.User.schema() + ":userName").equalsIgnoreCase(schema)) {
+
+ attributeCond = new AnyCond();
+ attributeCond.setSchema("username");
+ } else if ("displayName".equalsIgnoreCase(schema)
+ || (Resource.Group.schema() + ":displayName").equalsIgnoreCase(schema)) {
+
+ attributeCond = new AnyCond();
+ attributeCond.setSchema("name");
+ } else if ("meta.created".equals(schema)) {
+ attributeCond = new AnyCond();
+ attributeCond.setSchema("creationDate");
+ } else if ("meta.lastModified".equals(schema)) {
+ attributeCond = new AnyCond();
+ attributeCond.setSchema("lastChangeDate");
+ } else {
+ attributeCond = new AttributeCond();
+ attributeCond.setSchema(schema);
+ }
+
+ return attributeCond;
+ }
+
+ private SearchCond transform(final String operator, final String left, final String right) {
+ AttributeCond attributeCond = createAttributeCond(left);
+ attributeCond.setExpression(StringUtils.strip(right, "\""));
+
+ switch (operator) {
+ case "eq":
+ default:
+ attributeCond.setType(AttributeCond.Type.IEQ);
+ break;
+
+ case "ne":
+ attributeCond.setType(AttributeCond.Type.IEQ);
+ break;
+
+ case "sw":
+ attributeCond.setType(AttributeCond.Type.ILIKE);
+ attributeCond.setExpression(attributeCond.getExpression() + "%");
+ break;
+
+ case "co":
+ attributeCond.setType(AttributeCond.Type.ILIKE);
+ attributeCond.setExpression("%" + attributeCond.getExpression() + "%");
+ break;
+
+ case "ew":
+ attributeCond.setType(AttributeCond.Type.ILIKE);
+ attributeCond.setExpression("%" + attributeCond.getExpression());
+ break;
+
+ case "gt":
+ attributeCond.setType(AttributeCond.Type.GT);
+ break;
+
+ case "ge":
+ attributeCond.setType(AttributeCond.Type.GE);
+ break;
+
+ case "lt":
+ attributeCond.setType(AttributeCond.Type.LT);
+ break;
+
+ case "le":
+ attributeCond.setType(AttributeCond.Type.LE);
+ break;
+
+ }
+
+ return "ne".equals(operator)
+ ? SearchCond.getNotLeafCond(attributeCond)
+ : SearchCond.getLeafCond(attributeCond);
+ }
+
+ @Override
+ public SearchCond visitEXPR_OPER_EXPR(final SCIMFilterParser.EXPR_OPER_EXPRContext ctx) {
+ return transform(ctx.operator().getText(), ctx.expression(0).getText(), ctx.expression(1).getText());
+ }
+
+ @Override
+ public SearchCond visitATTR_OPER_CRITERIA(final SCIMFilterParser.ATTR_OPER_CRITERIAContext ctx) {
+ return transform(ctx.operator().getText(), ctx.ATTRNAME().getText(), ctx.criteria().getText());
+ }
+
+ @Override
+ public SearchCond visitATTR_OPER_EXPR(final SCIMFilterParser.ATTR_OPER_EXPRContext ctx) {
+ return transform(ctx.operator().getText(), ctx.ATTRNAME().getText(), ctx.expression().getText());
+ }
+
+ @Override
+ public SearchCond visitATTR_PR(final SCIMFilterParser.ATTR_PRContext ctx) {
+ AttributeCond cond = createAttributeCond(ctx.ATTRNAME().getText());
+ cond.setType(AttributeCond.Type.ISNOTNULL);
+ return SearchCond.getLeafCond(cond);
+ }
+
+ @Override
+ public SearchCond visitLPAREN_EXPR_RPAREN(final SCIMFilterParser.LPAREN_EXPR_RPARENContext ctx) {
+ return visit(ctx.expression());
+ }
+
+ @Override
+ public SearchCond visitNOT_EXPR(final SCIMFilterParser.NOT_EXPRContext ctx) {
+ SearchCond cond = visit(ctx.expression());
+ if (cond.getAttributeCond() != null) {
+ if (cond.getAttributeCond().getType() == AttributeCond.Type.ISNULL) {
+ cond.getAttributeCond().setType(AttributeCond.Type.ISNOTNULL);
+ } else if (cond.getAttributeCond().getType() == AttributeCond.Type.ISNOTNULL) {
+ cond.getAttributeCond().setType(AttributeCond.Type.ISNULL);
+ }
+ } else if (cond.getAnyCond() != null) {
+ if (cond.getAnyCond().getType() == AnyCond.Type.ISNULL) {
+ cond.getAnyCond().setType(AnyCond.Type.ISNOTNULL);
+ } else if (cond.getAnyCond().getType() == AnyCond.Type.ISNOTNULL) {
+ cond.getAnyCond().setType(AnyCond.Type.ISNULL);
+ }
+ } else {
+ cond = SearchCond.getNotLeafCond(cond);
+ }
+
+ return cond;
+ }
+
+ @Override
+ public SearchCond visitEXPR_AND_EXPR(final SCIMFilterParser.EXPR_AND_EXPRContext ctx) {
+ return SearchCond.getAndCond(visit(ctx.expression(0)), visit(ctx.expression(1)));
+ }
+
+ @Override
+ public SearchCond visitEXPR_OR_EXPR(final SCIMFilterParser.EXPR_OR_EXPRContext ctx) {
+ return SearchCond.getOrCond(visit(ctx.expression(0)), visit(ctx.expression(1)));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/ext/scimv2/logic/src/test/java/org/apache/syncope/core/logic/scim/SCIMFilterTest.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/test/java/org/apache/syncope/core/logic/scim/SCIMFilterTest.java b/ext/scimv2/logic/src/test/java/org/apache/syncope/core/logic/scim/SCIMFilterTest.java
new file mode 100644
index 0000000..08dbf1d
--- /dev/null
+++ b/ext/scimv2/logic/src/test/java/org/apache/syncope/core/logic/scim/SCIMFilterTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.syncope.core.logic.scim;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.junit.Test;
+
+public class SCIMFilterTest {
+
+ @Test
+ public void eq() {
+ SearchCond cond = SearchCondConverter.convert("userName eq \"bjensen\"");
+ assertNotNull(cond);
+ assertNotNull(cond.getAnyCond());
+ assertEquals("username", cond.getAnyCond().getSchema());
+ assertEquals(AttributeCond.Type.IEQ, cond.getAnyCond().getType());
+ assertEquals("bjensen", cond.getAnyCond().getExpression());
+ }
+
+ @Test
+ public void sw() {
+ SearchCond cond = SearchCondConverter.convert("userName sw \"J\"");
+ assertNotNull(cond);
+ assertNotNull(cond.getAnyCond());
+ assertEquals("username", cond.getAnyCond().getSchema());
+ assertEquals(AttributeCond.Type.ILIKE, cond.getAnyCond().getType());
+ assertEquals("J%", cond.getAnyCond().getExpression());
+
+ SearchCond fqn = SearchCondConverter.convert("urn:ietf:params:scim:schemas:core:2.0:User:userName sw \"J\"");
+ assertEquals(cond, fqn);
+ }
+
+ @Test
+ public void pr() {
+ SearchCond cond = SearchCondConverter.convert("title pr");
+ assertNotNull(cond);
+ assertNotNull(cond.getAttributeCond());
+ assertEquals("title", cond.getAttributeCond().getSchema());
+ assertEquals(AttributeCond.Type.ISNOTNULL, cond.getAttributeCond().getType());
+ assertNull(cond.getAttributeCond().getExpression());
+ }
+
+ @Test
+ public void gt() {
+ SearchCond cond = SearchCondConverter.convert("meta.lastModified gt \"2011-05-13T04:42:34Z\"");
+ assertNotNull(cond);
+ assertNotNull(cond.getAnyCond());
+ assertEquals("lastChangeDate", cond.getAnyCond().getSchema());
+ assertEquals(AttributeCond.Type.GT, cond.getAnyCond().getType());
+ assertEquals("2011-05-13T04:42:34Z", cond.getAnyCond().getExpression());
+ }
+
+ @Test
+ public void not() {
+ SearchCond cond = SearchCondConverter.convert("not (title pr)");
+ assertNotNull(cond);
+ assertNotNull(cond.getAttributeCond());
+ assertEquals("title", cond.getAttributeCond().getSchema());
+ assertEquals(AttributeCond.Type.ISNULL, cond.getAttributeCond().getType());
+ assertNull(cond.getAttributeCond().getExpression());
+ }
+
+ @Test
+ public void and() {
+ SearchCond cond = SearchCondConverter.convert("title pr and userName sw \"J\"");
+ assertNotNull(cond);
+ assertEquals(SearchCond.Type.AND, cond.getType());
+
+ SearchCond left = cond.getLeftSearchCond();
+ assertNotNull(left);
+ assertNotNull(left.getAttributeCond());
+ assertEquals("title", left.getAttributeCond().getSchema());
+ assertEquals(AttributeCond.Type.ISNOTNULL, left.getAttributeCond().getType());
+ assertNull(left.getAttributeCond().getExpression());
+
+ SearchCond right = cond.getRightSearchCond();
+ assertNotNull(right);
+ assertNotNull(right.getAnyCond());
+ assertEquals("username", right.getAnyCond().getSchema());
+ assertEquals(AttributeCond.Type.ILIKE, right.getAnyCond().getType());
+ assertEquals("J%", right.getAnyCond().getExpression());
+ }
+
+ @Test
+ public void or() {
+ SearchCond cond = SearchCondConverter.convert("title pr or displayName eq \"Other\"");
+ assertNotNull(cond);
+ assertEquals(SearchCond.Type.OR, cond.getType());
+
+ SearchCond left = cond.getLeftSearchCond();
+ assertNotNull(left);
+ assertNotNull(left.getAttributeCond());
+ assertEquals("title", left.getAttributeCond().getSchema());
+ assertEquals(AttributeCond.Type.ISNOTNULL, left.getAttributeCond().getType());
+ assertNull(left.getAttributeCond().getExpression());
+
+ SearchCond right = cond.getRightSearchCond();
+ assertNotNull(right);
+ assertNotNull(right.getAnyCond());
+ assertEquals("name", right.getAnyCond().getSchema());
+ assertEquals(AttributeCond.Type.IEQ, right.getAnyCond().getType());
+ assertEquals("Other", right.getAnyCond().getExpression());
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Group.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Group.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Group.java
index f64b837..f84d559 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Group.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Group.java
@@ -39,7 +39,7 @@ public class Group extends Reference {
@JsonProperty("display") final String display,
@JsonProperty("type") final Function type) {
- super(value, ref, display);
+ super(value, display, ref);
this.type = type;
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Member.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Member.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Member.java
index aa2f5dd..902217d 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Member.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Member.java
@@ -37,7 +37,7 @@ public class Member extends Reference {
@JsonProperty("display") final String display,
@JsonProperty("type") final Resource type) {
- super(value, ref, display);
+ super(value, display, ref);
this.type = type;
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMError.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMError.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMError.java
index d7112d1..f0548c4 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMError.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMError.java
@@ -24,6 +24,7 @@ import com.fasterxml.jackson.annotation.JsonFormat.Shape;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Arrays;
import java.util.List;
+import org.apache.syncope.ext.scimv2.api.SCIMBadRequestException;
import org.apache.syncope.ext.scimv2.api.type.ErrorType;
import org.apache.syncope.ext.scimv2.api.type.Resource;
@@ -40,6 +41,10 @@ public class SCIMError extends SCIMBean {
@JsonFormat(shape = Shape.STRING)
private final int status = 400;
+ public SCIMError(final SCIMBadRequestException ex) {
+ this(ex.getErrorType(), ex.getMessage());
+ }
+
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public SCIMError(
@JsonProperty("scimType") final ErrorType scimType,
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/SCIMExceptionMapper.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/SCIMExceptionMapper.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/SCIMExceptionMapper.java
index e525e77..4525d82 100644
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/SCIMExceptionMapper.java
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/SCIMExceptionMapper.java
@@ -41,6 +41,7 @@ import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
import org.apache.syncope.core.workflow.api.WorkflowException;
import org.apache.syncope.ext.scimv2.api.ConflictException;
import org.apache.syncope.ext.scimv2.api.PayloadTooLargeException;
+import org.apache.syncope.ext.scimv2.api.SCIMBadRequestException;
import org.apache.syncope.ext.scimv2.api.data.SCIMError;
import org.apache.syncope.ext.scimv2.api.type.ErrorType;
import org.identityconnectors.framework.common.exceptions.ConfigurationException;
@@ -108,9 +109,7 @@ public class SCIMExceptionMapper implements ExceptionMapper<Exception> {
&& ENTITYEXISTS_EXCLASS.isAssignableFrom(ex.getCause().getClass())) {
builder = builder(ClientExceptionType.EntityExists, ExceptionUtils.getRootCauseMessage(ex));
- } else if (ex instanceof DataIntegrityViolationException
- || JPASYSTEM_EXCLASS.isAssignableFrom(ex.getClass())) {
-
+ } else if (ex instanceof DataIntegrityViolationException || JPASYSTEM_EXCLASS.isAssignableFrom(ex.getClass())) {
builder = builder(ClientExceptionType.DataIntegrityViolation, ExceptionUtils.getRootCauseMessage(ex));
} else if (CONNECTOR_EXCLASS.isAssignableFrom(ex.getClass())) {
builder = builder(ClientExceptionType.ConnectorException, ExceptionUtils.getRootCauseMessage(ex));
@@ -125,7 +124,8 @@ public class SCIMExceptionMapper implements ExceptionMapper<Exception> {
}
// ...or just report as InternalServerError
if (builder == null) {
- builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR);
+ builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR).
+ entity(ExceptionUtils.getRootCauseMessage(ex));
}
}
@@ -188,6 +188,8 @@ public class SCIMExceptionMapper implements ExceptionMapper<Exception> {
return builder(ClientExceptionType.InvalidValues, ExceptionUtils.getRootCauseMessage(ex));
} else if (ex instanceof MalformedPathException) {
return builder(ClientExceptionType.InvalidPath, ExceptionUtils.getRootCauseMessage(ex));
+ } else if (ex instanceof SCIMBadRequestException) {
+ return Response.status(Response.Status.BAD_REQUEST).entity(new SCIMError((SCIMBadRequestException) ex));
}
return null;
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
index 41703a2..f2361d2 100644
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
@@ -33,6 +33,7 @@ import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.core.logic.AbstractAnyLogic;
import org.apache.syncope.core.logic.GroupLogic;
import org.apache.syncope.core.logic.UserLogic;
+import org.apache.syncope.core.logic.scim.SearchCondConverter;
import org.apache.syncope.core.persistence.api.dao.AnyDAO;
import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
@@ -190,11 +191,9 @@ abstract class AbstractSCIMService<R extends SCIMResource> implements SCIMServic
throw new UnsupportedOperationException();
}
- int page = startIndex == null || startIndex <= 1 ? 1 : (startIndex / AnyDAO.DEFAULT_PAGE_SIZE) + 1;
-
Pair<Integer, ? extends List<? extends AnyTO>> result = anyLogic(type).search(
- null,
- page,
+ StringUtils.isBlank(filter) ? null : SearchCondConverter.convert(filter),
+ startIndex == null || startIndex <= 1 ? 1 : (startIndex / AnyDAO.DEFAULT_PAGE_SIZE) + 1,
AnyDAO.DEFAULT_PAGE_SIZE,
Collections.<OrderByClause>emptyList(),
SyncopeConstants.ROOT_REALM,
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
index 2031da8..d7e19a2 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
@@ -26,13 +26,18 @@ import static org.junit.Assert.assertTrue;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
+import java.text.SimpleDateFormat;
import java.util.Arrays;
+import java.util.Date;
import java.util.List;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.ext.scimv2.api.SCIMConstants;
import org.apache.syncope.ext.scimv2.api.data.ListResponse;
import org.apache.syncope.ext.scimv2.api.data.ResourceType;
@@ -50,6 +55,16 @@ public class SCIMITCase extends AbstractITCase {
public static final String SCIM_ADDRESS = "http://localhost:9080/syncope/scim/v2";
+ private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
+
+ @Override
+ protected SimpleDateFormat initialValue() {
+ SimpleDateFormat sdf = new SimpleDateFormat();
+ sdf.applyPattern(SyncopeConstants.DEFAULT_DATE_PATTERN);
+ return sdf;
+ }
+ };
+
private WebClient webClient() {
return WebClient.create(SCIM_ADDRESS, Arrays.asList(new JacksonSCIMJsonProvider())).
accept(SCIMConstants.APPLICATION_SCIM_JSON_TYPE).
@@ -159,4 +174,45 @@ public class SCIMITCase extends AbstractITCase {
assertNotNull(group.getDisplayName());
}
}
+
+ @Test
+ public void search() {
+ Assume.assumeTrue(SCIMDetector.isSCIMAvailable(webClient()));
+
+ // eq
+ Response response = webClient().path("Groups").query("filter", "displayName eq \"additional\"").get();
+ assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ assertEquals(
+ SCIMConstants.APPLICATION_SCIM_JSON,
+ StringUtils.substringBefore(response.getHeaderString(HttpHeaders.CONTENT_TYPE), ";"));
+
+ ListResponse<SCIMGroup> groups = response.readEntity(new GenericType<ListResponse<SCIMGroup>>() {
+ });
+ assertNotNull(groups);
+ assertEquals(1, groups.getTotalResults());
+
+ SCIMGroup additional = groups.getResources().get(0);
+ assertEquals("additional", additional.getDisplayName());
+
+ // gt
+ UserTO newUser = userService.create(UserITCase.getUniqueSampleTO("scimsearch@syncope.apache.org")).readEntity(
+ new GenericType<ProvisioningResult<UserTO>>() {
+ }).getEntity();
+
+ Date value = new Date(newUser.getCreationDate().getTime() - 1000);
+ response = webClient().path("Users").query("filter", "meta.created gt \""
+ + DATE_FORMAT.get().format(value) + "\"").get();
+ assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ assertEquals(
+ SCIMConstants.APPLICATION_SCIM_JSON,
+ StringUtils.substringBefore(response.getHeaderString(HttpHeaders.CONTENT_TYPE), ";"));
+
+ ListResponse<SCIMUser> users = response.readEntity(new GenericType<ListResponse<SCIMUser>>() {
+ });
+ assertNotNull(users);
+ assertEquals(1, users.getTotalResults());
+
+ SCIMUser newSCIMUser = users.getResources().get(0);
+ assertEquals(newUser.getUsername(), newSCIMUser.getUserName());
+ }
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/1c469ae1/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 9d96234..c3133e0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -466,6 +466,8 @@ under the License.
<tycho.version>0.23.1</tycho.version>
<netbeans.version>RELEASE82</netbeans.version>
+ <antlr4.version>4.7</antlr4.version>
+
<testds.port>1389</testds.port>
<testdb.webport>9082</testdb.webport>
@@ -1656,6 +1658,12 @@ under the License.
<version>${netbeans.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-runtime</artifactId>
+ <version>${antlr4.version}</version>
+ </dependency>
+
<!-- TEST -->
<dependency>
<groupId>com.github.detro</groupId>
@@ -1986,6 +1994,12 @@ under the License.
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
</plugin>
+
+ <plugin>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-maven-plugin</artifactId>
+ <version>${antlr4.version}</version>
+ </plugin>
</plugins>
</pluginManagement>
[4/6] syncope git commit: More robust ConnObjectKey handling
Posted by il...@apache.org.
More robust ConnObjectKey handling
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/ad7bb322
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/ad7bb322
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/ad7bb322
Branch: refs/heads/master
Commit: ad7bb3225531b0382f3625fc6d4ed197c38325ce
Parents: 3d4f233
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Nov 6 09:08:33 2017 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Nov 6 13:52:18 2017 +0100
----------------------------------------------------------------------
.../provisioning/java/MappingManagerImpl.java | 24 ++++++++++----------
1 file changed, 12 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/ad7bb322/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
index a19d37f..dada9f1 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
@@ -190,18 +190,18 @@ public class MappingManagerImpl implements MappingManager {
}
}
- Attribute connObjectKeyExtAttr =
- AttributeUtil.find(MappingUtils.getConnObjectKeyItem(provision).get().getExtAttrName(), attributes);
- if (connObjectKeyExtAttr != null) {
- attributes.remove(connObjectKeyExtAttr);
- attributes.add(AttributeBuilder.build(
- MappingUtils.getConnObjectKeyItem(provision).get().getExtAttrName(), connObjectKey));
- }
- Name name = MappingUtils.evaluateNAME(any, provision, connObjectKey);
- attributes.add(name);
- if (connObjectKey != null && !connObjectKey.equals(name.getNameValue()) && connObjectKeyExtAttr == null) {
- attributes.add(AttributeBuilder.build(
- MappingUtils.getConnObjectKeyItem(provision).get().getExtAttrName(), connObjectKey));
+ Optional<MappingItem> connObjectKeyItem = MappingUtils.getConnObjectKeyItem(provision);
+ if (connObjectKeyItem.isPresent()) {
+ Attribute connObjectKeyExtAttr = AttributeUtil.find(connObjectKeyItem.get().getExtAttrName(), attributes);
+ if (connObjectKeyExtAttr != null) {
+ attributes.remove(connObjectKeyExtAttr);
+ attributes.add(AttributeBuilder.build(connObjectKeyItem.get().getExtAttrName(), connObjectKey));
+ }
+ Name name = MappingUtils.evaluateNAME(any, provision, connObjectKey);
+ attributes.add(name);
+ if (connObjectKey != null && !connObjectKey.equals(name.getNameValue()) && connObjectKeyExtAttr == null) {
+ attributes.add(AttributeBuilder.build(connObjectKeyItem.get().getExtAttrName(), connObjectKey));
+ }
}
if (enable != null) {
[5/6] syncope git commit: White noise: javadocs cleanup
Posted by il...@apache.org.
White noise: javadocs cleanup
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/9129ee05
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/9129ee05
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/9129ee05
Branch: refs/heads/master
Commit: 9129ee05f76ed6cd525622731c215ce3a4b5d781
Parents: ad7bb32
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Nov 6 12:50:43 2017 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Nov 6 13:52:49 2017 +0100
----------------------------------------------------------------------
.../syncope/core/persistence/api/search/SearchCondConverter.java | 3 +--
.../syncope/core/persistence/api/search/SearchCondVisitor.java | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/9129ee05/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondConverter.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondConverter.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondConverter.java
index 1ec0f6f..257ba7f 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondConverter.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondConverter.java
@@ -35,12 +35,11 @@ import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
public final class SearchCondConverter {
/**
- * Parses a FIQL expression into Syncope's <tt>SearchCond</tt>, using CXF's <tt>FiqlParser</tt>.
+ * Parses a FIQL expression into Syncope's {@link SearchCond}, using {@link SyncopeFiqlParser}.
*
* @param fiql FIQL string
* @param realms optional realm to provide to {@link SearchCondVisitor}
* @return {@link SearchCond} instance for given FIQL expression
- * @see SyncopeFiqlParser
*/
public static SearchCond convert(final String fiql, final String... realms) {
SyncopeFiqlParser<SearchBean> parser = new SyncopeFiqlParser<>(
http://git-wip-us.apache.org/repos/asf/syncope/blob/9129ee05/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
index 18d5766..4c8cd01 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
@@ -47,7 +47,7 @@ import org.apache.syncope.core.persistence.api.dao.search.RelationshipCond;
import org.apache.syncope.core.persistence.api.dao.search.RelationshipTypeCond;
/**
- * Converts CXF's <tt>SearchCondition</tt> into internal <tt>SearchCond</tt>.
+ * Visits CXF's {@link SearchBean} and produces {@link SearchCond}.
*/
public class SearchCondVisitor extends AbstractSearchConditionVisitor<SearchBean, SearchCond> {