Return-Path: X-Original-To: apmail-syncope-commits-archive@www.apache.org Delivered-To: apmail-syncope-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id C31C617D00 for ; Thu, 8 Jan 2015 13:17:20 +0000 (UTC) Received: (qmail 27045 invoked by uid 500); 8 Jan 2015 13:17:22 -0000 Delivered-To: apmail-syncope-commits-archive@syncope.apache.org Received: (qmail 26970 invoked by uid 500); 8 Jan 2015 13:17:22 -0000 Mailing-List: contact commits-help@syncope.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@syncope.apache.org Delivered-To: mailing list commits@syncope.apache.org Received: (qmail 26778 invoked by uid 99); 8 Jan 2015 13:17:21 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 08 Jan 2015 13:17:21 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 89BB431988A; Thu, 8 Jan 2015 13:17:21 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ilgrosso@apache.org To: commits@syncope.apache.org Date: Thu, 08 Jan 2015 13:17:30 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [10/13] syncope git commit: [SYNCOPE-620] server logic in, tests missing http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/PropagationActionClass.java ---------------------------------------------------------------------- diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/PropagationActionClass.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/PropagationActionClass.java new file mode 100644 index 0000000..f8e54b6 --- /dev/null +++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/PropagationActionClass.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.common.lib.wrap; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +@XmlRootElement(name = "propagationActionClass") +@XmlType +public class PropagationActionClass extends AbstractWrappable { + + private static final long serialVersionUID = 2187654394121198308L; + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/PushActionClass.java ---------------------------------------------------------------------- diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/PushActionClass.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/PushActionClass.java new file mode 100644 index 0000000..e12fd8e --- /dev/null +++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/PushActionClass.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.common.lib.wrap; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +@XmlRootElement(name = "pushActionClass") +@XmlType +public class PushActionClass extends AbstractWrappable { + + private static final long serialVersionUID = 1669581609310071906L; + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/ReportletConfClass.java ---------------------------------------------------------------------- diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/ReportletConfClass.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/ReportletConfClass.java new file mode 100644 index 0000000..24ba188 --- /dev/null +++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/ReportletConfClass.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.common.lib.wrap; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +@XmlRootElement(name = "reportletConfClass") +@XmlType +public class ReportletConfClass extends AbstractWrappable { + + private static final long serialVersionUID = 1343357929074360450L; + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/ResourceName.java ---------------------------------------------------------------------- diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/ResourceName.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/ResourceName.java new file mode 100644 index 0000000..42b77ca --- /dev/null +++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/ResourceName.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.common.lib.wrap; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +@XmlRootElement(name = "resourceName") +@XmlType +public class ResourceName extends AbstractWrappable { + + private static final long serialVersionUID = -175720097924079573L; + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/SubjectId.java ---------------------------------------------------------------------- diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/SubjectId.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/SubjectId.java new file mode 100644 index 0000000..d61f1d9 --- /dev/null +++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/SubjectId.java @@ -0,0 +1,25 @@ +/* + * 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.common.lib.wrap; + +public class SubjectId extends AbstractWrappable { + + private static final long serialVersionUID = -8664228651057889297L; + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/SyncActionClass.java ---------------------------------------------------------------------- diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/SyncActionClass.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/SyncActionClass.java new file mode 100644 index 0000000..d6c7a77 --- /dev/null +++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/SyncActionClass.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.common.lib.wrap; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +@XmlRootElement(name = "syncActionClass") +@XmlType +public class SyncActionClass extends AbstractWrappable { + + private static final long serialVersionUID = 1669581609310071905L; + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/Validator.java ---------------------------------------------------------------------- diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/Validator.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/Validator.java new file mode 100644 index 0000000..71cad00 --- /dev/null +++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/Validator.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.common.lib.wrap; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +@XmlRootElement(name = "validator") +@XmlType +public class Validator extends AbstractWrappable { + + private static final long serialVersionUID = 7233619557177034453L; + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/package-info.java ---------------------------------------------------------------------- diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/package-info.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/package-info.java new file mode 100644 index 0000000..397cb66 --- /dev/null +++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/wrap/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@XmlSchema(namespace = SyncopeConstants.NAMESPACE) +package org.apache.syncope.common.lib.wrap; + +import javax.xml.bind.annotation.XmlSchema; +import org.apache.syncope.common.lib.SyncopeConstants; http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/pom.xml ---------------------------------------------------------------------- diff --git a/syncope620/pom.xml b/syncope620/pom.xml index 82e910d..ad69b63 100644 --- a/syncope620/pom.xml +++ b/syncope620/pom.xml @@ -320,6 +320,8 @@ under the License. 1.4.0 1.2.1 + 3.0.3 + 2.5.0 4.1.4.RELEASE @@ -333,7 +335,9 @@ under the License. 2.2.1 - 1.7.9 + 3.0.0-alpha-3 + + 1.7.10 2.1 2.4 @@ -379,6 +383,49 @@ under the License. 3.0.0 provided + + javax.ws.rs + javax.ws.rs-api + 2.0.1 + + + org.apache.geronimo.javamail + geronimo-javamail_1.4_mail + 1.8.4 + + + + + org.apache.cxf + cxf-rt-frontend-jaxrs + ${cxf.version} + + + org.apache.cxf + cxf-rt-rs-extension-providers + ${cxf.version} + + + org.apache.cxf + cxf-rt-rs-extension-search + ${cxf.version} + + + org.apache.cxf + cxf-rt-frontend-jaxws + ${cxf.version} + + + org.apache.cxf + cxf-rt-rs-service-description + ${cxf.version} + + + org.apache.cxf + cxf-rt-rs-client + ${cxf.version} + + org.apache.openjpa @@ -436,6 +483,11 @@ under the License. org.springframework + spring-context-support + ${spring.version} + + + org.springframework spring-tx ${spring.version} @@ -454,6 +506,12 @@ under the License. spring-security-core ${spring-security.version} + + + org.aspectj + aspectjweaver + 1.8.4 + commons-io @@ -517,6 +575,87 @@ under the License. + org.apache.velocity + velocity + 1.7 + + + org.apache.velocity + velocity-tools + 2.0 + + + struts-core + org.apache.struts + + + struts-taglib + org.apache.struts + + + struts-tiles + org.apache.struts + + + sslext + sslext + + + + + + org.apache.cocoon.sax + cocoon-sax + ${cocoon.version} + + + org.apache.cocoon.optional + cocoon-optional + ${cocoon.version} + + + + org.apache.xmlgraphics + fop + 1.1 + + + org.apache.avalon.framework + avalon-framework-api + + + org.apache.avalon.framework + avalon-framework-impl + + + xalan + xalan + + + + + org.apache.avalon.framework + avalon-framework-api + 4.3.1 + + + org.apache.avalon.framework + avalon-framework-impl + 4.3.1 + + + + xalan + xalan + 2.7.1 + + + xerces + xercesImpl + 2.11.0 + + + org.slf4j slf4j-api ${slf4j.version} @@ -526,6 +665,11 @@ under the License. log4j-api ${log4j.version} + + org.apache.logging.log4j + log4j-core + ${log4j.version} + org.springframework http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/pom.xml ---------------------------------------------------------------------- diff --git a/syncope620/server/logic/pom.xml b/syncope620/server/logic/pom.xml new file mode 100644 index 0000000..fd8fc42 --- /dev/null +++ b/syncope620/server/logic/pom.xml @@ -0,0 +1,127 @@ + + + + + 4.0.0 + + + org.apache.syncope + syncope-server + 2.0.0-SNAPSHOT + + + Apache Syncope Server Logic + Apache Syncope Server Logic + org.apache.syncope.server + syncope-server-logic + jar + + + + org.apache.geronimo.javamail + geronimo-javamail_1.4_mail + + + + org.apache.commons + commons-dbcp2 + + + + org.springframework + spring-context + + + org.springframework + spring-context-support + + + org.springframework + spring-jdbc + + + + org.aspectj + aspectjweaver + + + + org.apache.velocity + velocity + + + org.apache.velocity + velocity-tools + + + + org.apache.cocoon.sax + cocoon-sax + + + org.apache.cocoon.optional + cocoon-optional + + + + org.apache.xmlgraphics + fop + + + org.apache.avalon.framework + avalon-framework-api + + + org.apache.avalon.framework + avalon-framework-impl + + + + xalan + xalan + + + xerces + xercesImpl + + + + org.apache.logging.log4j + log4j-core + + + + org.apache.syncope.server + syncope-persistence-api + ${project.version} + + + org.apache.syncope.server + syncope-workflow-api + ${project.version} + + + org.apache.syncope.server + syncope-server-utils + ${project.version} + + + + http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractLogic.java ---------------------------------------------------------------------- diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractLogic.java new file mode 100644 index 0000000..11686a2 --- /dev/null +++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractLogic.java @@ -0,0 +1,58 @@ +/* + * 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.server.logic; + +import java.lang.reflect.Method; +import org.apache.syncope.common.lib.AbstractBaseBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.transaction.annotation.Transactional; + +/** + * Superclass for all controllers. + * + * @param transfer object used for input / output + */ +abstract class AbstractLogic { + + /** + * Logger. + */ + protected static final Logger LOG = LoggerFactory.getLogger(AbstractLogic.class); + + /** + * Resolves stored bean (if existing) referred by the given CUD method. + *
+ * Read-only methods will be unresolved for performance reasons. + * + * @param method method. + * @param args method arguments. + * @return referred stored bean. + * @throws UnresolvedReferenceException in case of failures, read-only methods and unresolved bean. + */ + public T resolveBeanReference(final Method method, final Object... args) throws UnresolvedReferenceException { + final Transactional transactional = method.getAnnotation(Transactional.class); + if (transactional != null && transactional.readOnly()) { + throw new UnresolvedReferenceException(); + } + return resolveReference(method, args); + } + + protected abstract T resolveReference(Method method, Object... args) throws UnresolvedReferenceException; +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractResourceAssociator.java ---------------------------------------------------------------------- diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractResourceAssociator.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractResourceAssociator.java new file mode 100644 index 0000000..2a20d1f --- /dev/null +++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractResourceAssociator.java @@ -0,0 +1,37 @@ +/* + * 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.server.logic; + +import java.util.Collection; +import org.apache.syncope.common.lib.to.AbstractAttributableTO; + +public abstract class AbstractResourceAssociator extends AbstractLogic { + + public abstract T unlink(Long id, Collection resources); + + public abstract T link(Long id, Collection resources); + + public abstract T unassign(Long id, Collection resources); + + public abstract T assign(Long id, Collection resources, boolean changepwd, String password); + + public abstract T deprovision(Long userId, Collection resources); + + public abstract T provision(Long userId, Collection resources, boolean changepwd, String password); +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractSubjectLogic.java ---------------------------------------------------------------------- diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractSubjectLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractSubjectLogic.java new file mode 100644 index 0000000..a9117b8 --- /dev/null +++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractSubjectLogic.java @@ -0,0 +1,43 @@ +/* + * 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.server.logic; + +import java.util.List; +import org.apache.syncope.common.lib.mod.AbstractSubjectMod; +import org.apache.syncope.common.lib.to.AbstractSubjectTO; +import org.apache.syncope.persistence.api.dao.search.OrderByClause; +import org.apache.syncope.persistence.api.dao.search.SearchCond; + +public abstract class AbstractSubjectLogic + extends AbstractResourceAssociator { + + public abstract T read(Long key); + + public abstract int count(); + + public abstract T update(V attributableMod); + + public abstract T delete(Long key); + + public abstract List list(int page, int size, List orderBy); + + public abstract List search(SearchCond searchCondition, int page, int size, List orderBy); + + public abstract int searchCount(SearchCond searchCondition); +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractTransactionalLogic.java ---------------------------------------------------------------------- diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractTransactionalLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractTransactionalLogic.java new file mode 100644 index 0000000..00526b8 --- /dev/null +++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/AbstractTransactionalLogic.java @@ -0,0 +1,31 @@ +/* + * 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.server.logic; + +import org.apache.syncope.common.lib.AbstractBaseBean; +import org.springframework.transaction.annotation.Transactional; + +/** + * Adds Spring's transactional support to {@link AbstractLogic}. + * + * @param transfer object used for input / output + */ +@Transactional(rollbackFor = { Throwable.class }) +abstract class AbstractTransactionalLogic extends AbstractLogic { +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ConfigurationLogic.java ---------------------------------------------------------------------- diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ConfigurationLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ConfigurationLogic.java new file mode 100644 index 0000000..581f640 --- /dev/null +++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ConfigurationLogic.java @@ -0,0 +1,157 @@ +/* + * 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.server.logic; + +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Set; +import org.apache.syncope.common.lib.to.AttrTO; +import org.apache.syncope.common.lib.to.ConfTO; +import org.apache.syncope.common.lib.wrap.Validator; +import org.apache.syncope.persistence.api.content.ContentExporter; +import org.apache.syncope.persistence.api.dao.ConfDAO; +import org.apache.syncope.persistence.api.dao.NotFoundException; +import org.apache.syncope.persistence.api.dao.PlainSchemaDAO; +import org.apache.syncope.persistence.api.entity.conf.CPlainAttr; +import org.apache.syncope.persistence.api.entity.conf.CPlainSchema; +import org.apache.syncope.server.logic.data.ConfigurationDataBinder; +import org.apache.syncope.server.logic.init.ImplementationClassNamesLoader; +import org.apache.syncope.server.logic.init.WorkflowAdapterLoader; +import org.apache.syncope.server.logic.notification.NotificationManager; +import org.apache.syncope.server.spring.ResourceWithFallbackLoader; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +public class ConfigurationLogic extends AbstractTransactionalLogic { + + @Autowired + private ConfDAO confDAO; + + @Autowired + private PlainSchemaDAO plainSchemaDAO; + + @Autowired + private ConfigurationDataBinder binder; + + @Autowired + private ContentExporter exporter; + + @Autowired + private ImplementationClassNamesLoader classNamesLoader; + + @javax.annotation.Resource(name = "velocityResourceLoader") + private ResourceWithFallbackLoader resourceLoader; + + @Autowired + private WorkflowAdapterLoader wfAdapterLoader; + + @PreAuthorize("hasRole('CONFIGURATION_DELETE')") + public void delete(final String key) { + confDAO.delete(key); + } + + @PreAuthorize("hasRole('CONFIGURATION_LIST')") + public ConfTO list() { + return binder.getConfTO(confDAO.get()); + } + + @PreAuthorize("isAuthenticated()") + public AttrTO read(final String key) { + AttrTO result; + + CPlainAttr conf = confDAO.find(key); + if (conf == null) { + CPlainSchema schema = plainSchemaDAO.find(key, CPlainSchema.class); + if (schema == null) { + throw new NotFoundException("Configuration key " + key); + } + + result = new AttrTO(); + result.setSchema(key); + } else { + result = binder.getAttrTO(conf); + } + + return result; + } + + @PreAuthorize("hasRole('CONFIGURATION_SET')") + public void set(final AttrTO value) { + confDAO.save(binder.getAttribute(value)); + } + + @PreAuthorize("hasRole('CONFIGURATION_LIST')") + public Set getValidators() { + return classNamesLoader.getClassNames(ImplementationClassNamesLoader.Type.VALIDATOR); + } + + @PreAuthorize("hasRole('CONFIGURATION_LIST')") + public Set getMailTemplates() { + Set htmlTemplates = new HashSet(); + Set textTemplates = new HashSet(); + + try { + for (Resource resource : resourceLoader.getResources(NotificationManager.MAIL_TEMPLATES + "*.vm")) { + String template = resource.getURL().toExternalForm(); + if (template.endsWith(NotificationManager.MAIL_TEMPLATE_HTML_SUFFIX)) { + htmlTemplates.add( + template.substring(template.indexOf(NotificationManager.MAIL_TEMPLATES) + 14, + template.indexOf(NotificationManager.MAIL_TEMPLATE_HTML_SUFFIX))); + } else if (template.endsWith(NotificationManager.MAIL_TEMPLATE_TEXT_SUFFIX)) { + textTemplates.add( + template.substring(template.indexOf(NotificationManager.MAIL_TEMPLATES) + 14, + template.indexOf(NotificationManager.MAIL_TEMPLATE_TEXT_SUFFIX))); + } else { + LOG.warn("Unexpected template found: {}, ignoring...", template); + } + } + } catch (IOException e) { + LOG.error("While searching for class implementing {}", Validator.class.getName(), e); + } + + // Only templates available both as HTML and TEXT are considered + htmlTemplates.retainAll(textTemplates); + + return htmlTemplates; + } + + @PreAuthorize("hasRole('CONFIGURATION_EXPORT')") + @Transactional(readOnly = true) + public void export(final OutputStream os) { + try { + exporter.export(os, wfAdapterLoader.getTablePrefix()); + LOG.debug("Database content successfully exported"); + } catch (Exception e) { + LOG.error("While exporting database content", e); + } + } + + @Override + protected ConfTO resolveReference(final Method method, final Object... args) + throws UnresolvedReferenceException { + + throw new UnresolvedReferenceException(); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ConnectorLogic.java ---------------------------------------------------------------------- diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ConnectorLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ConnectorLogic.java new file mode 100644 index 0000000..ee550cd --- /dev/null +++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ConnectorLogic.java @@ -0,0 +1,341 @@ +/* + * 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.server.logic; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.to.BulkAction; +import org.apache.syncope.common.lib.to.BulkActionResult; +import org.apache.syncope.common.lib.to.ConnBundleTO; +import org.apache.syncope.common.lib.to.ConnInstanceTO; +import org.apache.syncope.common.lib.types.ClientExceptionType; +import org.apache.syncope.common.lib.types.ConnConfProperty; +import org.apache.syncope.persistence.api.dao.ConnInstanceDAO; +import org.apache.syncope.persistence.api.dao.ExternalResourceDAO; +import org.apache.syncope.persistence.api.dao.NotFoundException; +import org.apache.syncope.persistence.api.entity.ConnInstance; +import org.apache.syncope.persistence.api.entity.ExternalResource; +import org.apache.syncope.provisioning.api.ConnIdBundleManager; +import org.apache.syncope.provisioning.api.Connector; +import org.apache.syncope.provisioning.api.ConnectorFactory; +import org.apache.syncope.server.logic.data.ConnInstanceDataBinder; +import org.identityconnectors.common.l10n.CurrentLocale; +import org.identityconnectors.framework.api.ConfigurationProperties; +import org.identityconnectors.framework.api.ConnectorInfo; +import org.identityconnectors.framework.api.ConnectorKey; +import org.identityconnectors.framework.common.objects.ObjectClass; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +public class ConnectorLogic extends AbstractTransactionalLogic { + + @Autowired + private ConnIdBundleManager connIdBundleManager; + + @Autowired + private ExternalResourceDAO resourceDAO; + + @Autowired + private ConnInstanceDAO connInstanceDAO; + + @Autowired + private ConnInstanceDataBinder binder; + + @Autowired + private ConnectorFactory connFactory; + + @PreAuthorize("hasRole('CONNECTOR_CREATE')") + public ConnInstanceTO create(final ConnInstanceTO connInstanceTO) { + ConnInstance connInstance = binder.getConnInstance(connInstanceTO); + try { + connInstance = connInstanceDAO.save(connInstance); + } catch (SyncopeClientException e) { + throw e; + } catch (Exception e) { + SyncopeClientException ex = SyncopeClientException.build(ClientExceptionType.InvalidConnInstance); + ex.getElements().add(e.getMessage()); + throw ex; + } + + return binder.getConnInstanceTO(connInstance); + } + + @PreAuthorize("hasRole('CONNECTOR_UPDATE')") + public ConnInstanceTO update(final ConnInstanceTO connInstanceTO) { + ConnInstance connInstance = binder.updateConnInstance(connInstanceTO.getKey(), connInstanceTO); + try { + connInstance = connInstanceDAO.save(connInstance); + } catch (SyncopeClientException e) { + throw e; + } catch (Exception e) { + SyncopeClientException ex = SyncopeClientException.build(ClientExceptionType.InvalidConnInstance); + ex.getElements().add(e.getMessage()); + throw ex; + } + + return binder.getConnInstanceTO(connInstance); + } + + @PreAuthorize("hasRole('CONNECTOR_DELETE')") + public ConnInstanceTO delete(final Long connInstanceId) { + ConnInstance connInstance = connInstanceDAO.find(connInstanceId); + if (connInstance == null) { + throw new NotFoundException("Connector '" + connInstanceId + "'"); + } + + if (!connInstance.getResources().isEmpty()) { + SyncopeClientException associatedResources = SyncopeClientException.build( + ClientExceptionType.AssociatedResources); + for (ExternalResource resource : connInstance.getResources()) { + associatedResources.getElements().add(resource.getKey()); + } + throw associatedResources; + } + + ConnInstanceTO connToDelete = binder.getConnInstanceTO(connInstance); + + connInstanceDAO.delete(connInstanceId); + + return connToDelete; + } + + @PreAuthorize("hasRole('CONNECTOR_LIST')") + @Transactional(readOnly = true) + public List list(final String lang) { + if (StringUtils.isBlank(lang)) { + CurrentLocale.set(Locale.ENGLISH); + } else { + CurrentLocale.set(new Locale(lang)); + } + + List connInstances = connInstanceDAO.findAll(); + + final List connInstanceTOs = new ArrayList<>(); + + for (ConnInstance connector : connInstances) { + try { + connInstanceTOs.add(binder.getConnInstanceTO(connector)); + } catch (NotFoundException e) { + LOG.error("Connector '{}#{}' not found", connector.getBundleName(), connector.getVersion()); + } + } + + return connInstanceTOs; + } + + @PreAuthorize("hasRole('CONNECTOR_READ')") + @Transactional(readOnly = true) + public ConnInstanceTO read(final Long connInstanceId) { + ConnInstance connInstance = connInstanceDAO.find(connInstanceId); + if (connInstance == null) { + throw new NotFoundException("Connector '" + connInstanceId + "'"); + } + + return binder.getConnInstanceTO(connInstance); + } + + @PreAuthorize("hasRole('CONNECTOR_READ')") + @Transactional(readOnly = true) + public List getBundles(final String lang) { + if (StringUtils.isBlank(lang)) { + CurrentLocale.set(Locale.ENGLISH); + } else { + CurrentLocale.set(new Locale(lang)); + } + + List connectorBundleTOs = new ArrayList<>(); + for (Map.Entry> entry : connIdBundleManager.getConnectorInfos().entrySet()) { + for (ConnectorInfo bundle : entry.getValue()) { + ConnBundleTO connBundleTO = new ConnBundleTO(); + connBundleTO.setDisplayName(bundle.getConnectorDisplayName()); + + connBundleTO.setLocation(entry.getKey()); + + ConnectorKey key = bundle.getConnectorKey(); + connBundleTO.setBundleName(key.getBundleName()); + connBundleTO.setConnectorName(key.getConnectorName()); + connBundleTO.setVersion(key.getBundleVersion()); + + ConfigurationProperties properties = connIdBundleManager.getConfigurationProperties(bundle); + + for (String propName : properties.getPropertyNames()) { + connBundleTO.getProperties().add(binder.buildConnConfPropSchema(properties.getProperty(propName))); + } + + LOG.debug("Connector bundle: {}", connBundleTO); + + connectorBundleTOs.add(connBundleTO); + } + } + + return connectorBundleTOs; + } + + @PreAuthorize("hasRole('CONNECTOR_READ')") + @Transactional(readOnly = true) + public List getSchemaNames(final ConnInstanceTO connInstanceTO, final boolean includeSpecial) { + final ConnInstance connInstance = connInstanceDAO.find(connInstanceTO.getKey()); + if (connInstance == null) { + throw new NotFoundException("Connector '" + connInstanceTO.getKey() + "'"); + } + + // consider the possibility to receive overridden properties only + final Set conf = binder.mergeConnConfProperties(connInstanceTO.getConfiguration(), + connInstance.getConfiguration()); + + // We cannot use Spring bean because this method could be used during resource definition or modification: + // bean couldn't exist or couldn't be updated. + // This is the reason why we should take a "not mature" connector facade proxy to ask for schema names. + final List result = new ArrayList<>(connFactory.createConnector(connInstance, conf). + getSchemaNames(includeSpecial)); + + return result; + } + + @PreAuthorize("hasRole('CONNECTOR_READ')") + @Transactional(readOnly = true) + public List getSupportedObjectClasses(final ConnInstanceTO connInstanceTO) { + final ConnInstance connInstance = connInstanceDAO.find(connInstanceTO.getKey()); + if (connInstance == null) { + throw new NotFoundException("Connector '" + connInstanceTO.getKey() + "'"); + } + + // consider the possibility to receive overridden properties only + final Set conf = binder.mergeConnConfProperties(connInstanceTO.getConfiguration(), + connInstance.getConfiguration()); + + // We cannot use Spring bean because this method could be used during resource definition or modification: + // bean couldn't exist or couldn't be updated. + // This is the reason why we should take a "not mature" connector facade proxy to ask for object classes. + Set objectClasses = connFactory.createConnector(connInstance, conf).getSupportedObjectClasses(); + + List result = new ArrayList<>(objectClasses.size()); + for (ObjectClass objectClass : objectClasses) { + result.add(objectClass.getObjectClassValue()); + } + + return result; + } + + @PreAuthorize("hasRole('CONNECTOR_READ')") + @Transactional(readOnly = true) + public List getConfigurationProperties(final Long connInstanceId) { + + final ConnInstance connInstance = connInstanceDAO.find(connInstanceId); + if (connInstance == null) { + throw new NotFoundException("Connector '" + connInstanceId + "'"); + } + + return new ArrayList(connInstance.getConfiguration()); + } + + @PreAuthorize("hasRole('CONNECTOR_READ')") + @Transactional(readOnly = true) + public boolean check(final ConnInstanceTO connInstanceTO) { + final Connector connector = connFactory.createConnector( + binder.getConnInstance(connInstanceTO), connInstanceTO.getConfiguration()); + + boolean result; + try { + connector.test(); + result = true; + } catch (Exception ex) { + LOG.error("Test connection failure {}", ex); + result = false; + } + + return result; + } + + @PreAuthorize("hasRole('CONNECTOR_READ')") + @Transactional(readOnly = true) + public ConnInstanceTO readByResource(final String resourceName) { + ExternalResource resource = resourceDAO.find(resourceName); + if (resource == null) { + throw new NotFoundException("Resource '" + resourceName + "'"); + } + return binder.getConnInstanceTO(connFactory.getConnector(resource).getActiveConnInstance()); + } + + @PreAuthorize("hasRole('CONNECTOR_RELOAD')") + @Transactional(readOnly = true) + public void reload() { + connFactory.unload(); + connFactory.load(); + } + + @PreAuthorize("hasRole('CONNECTOR_DELETE') and #bulkAction.operation == #bulkAction.operation.DELETE") + public BulkActionResult bulk(final BulkAction bulkAction) { + BulkActionResult res = new BulkActionResult(); + + if (bulkAction.getOperation() == BulkAction.Type.DELETE) { + for (String id : bulkAction.getTargets()) { + try { + res.add(delete(Long.valueOf(id)).getKey(), BulkActionResult.Status.SUCCESS); + } catch (Exception e) { + LOG.error("Error performing delete for connector {}", id, e); + res.add(id, BulkActionResult.Status.FAILURE); + } + } + } + + return res; + } + + /** + * {@inheritDoc} + */ + @Override + protected ConnInstanceTO resolveReference(final Method method, final Object... args) + throws UnresolvedReferenceException { + + Long id = null; + + if (ArrayUtils.isNotEmpty(args)) { + for (int i = 0; id == null && i < args.length; i++) { + if (args[i] instanceof Long) { + id = (Long) args[i]; + } else if (args[i] instanceof ConnInstanceTO) { + id = ((ConnInstanceTO) args[i]).getKey(); + } + } + } + + if ((id != null) && !id.equals(0l)) { + try { + return binder.getConnInstanceTO(connInstanceDAO.find(id)); + } catch (Throwable ignore) { + LOG.debug("Unresolved reference", ignore); + throw new UnresolvedReferenceException(ignore); + } + } + + throw new UnresolvedReferenceException(); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/EntitlementLogic.java ---------------------------------------------------------------------- diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/EntitlementLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/EntitlementLogic.java new file mode 100644 index 0000000..e71fcb9 --- /dev/null +++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/EntitlementLogic.java @@ -0,0 +1,58 @@ +/* + * 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.server.logic; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import org.apache.syncope.common.lib.wrap.EntitlementTO; +import org.apache.syncope.persistence.api.dao.EntitlementDAO; +import org.apache.syncope.persistence.api.entity.Entitlement; +import org.apache.syncope.server.security.AuthContextUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class EntitlementLogic extends AbstractTransactionalLogic { + + @Autowired + private EntitlementDAO entitlementDAO; + + public List getAll() { + List entitlements = entitlementDAO.findAll(); + List result = new ArrayList(entitlements.size()); + for (Entitlement entitlement : entitlements) { + result.add(entitlement.getKey()); + } + + return result; + } + + public Set getOwn() { + return AuthContextUtil.getOwnedEntitlementNames(); + } + + @Override + protected EntitlementTO resolveReference(final Method method, final Object... args) + throws UnresolvedReferenceException { + + throw new UnresolvedReferenceException(); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/LoggerLogic.java ---------------------------------------------------------------------- diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/LoggerLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/LoggerLogic.java new file mode 100644 index 0000000..5356b86 --- /dev/null +++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/LoggerLogic.java @@ -0,0 +1,307 @@ +/* + * 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.server.logic; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.LoggerConfig; +import org.apache.syncope.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.SyncopeConstants; +import org.apache.syncope.common.lib.to.EventCategoryTO; +import org.apache.syncope.common.lib.to.LoggerTO; +import org.apache.syncope.common.lib.types.AttributableType; +import org.apache.syncope.common.lib.types.AuditElements.EventCategoryType; +import org.apache.syncope.common.lib.types.AuditLoggerName; +import org.apache.syncope.common.lib.types.ClientExceptionType; +import org.apache.syncope.common.lib.types.LoggerLevel; +import org.apache.syncope.common.lib.types.LoggerType; +import org.apache.syncope.common.lib.types.ResourceOperation; +import org.apache.syncope.common.lib.types.TaskType; +import org.apache.syncope.persistence.api.dao.ExternalResourceDAO; +import org.apache.syncope.persistence.api.dao.LoggerDAO; +import org.apache.syncope.persistence.api.dao.NotFoundException; +import org.apache.syncope.persistence.api.dao.TaskDAO; +import org.apache.syncope.persistence.api.entity.EntityFactory; +import org.apache.syncope.persistence.api.entity.ExternalResource; +import org.apache.syncope.persistence.api.entity.Logger; +import org.apache.syncope.persistence.api.entity.task.SchedTask; +import org.apache.syncope.persistence.api.entity.task.SyncTask; +import org.apache.syncope.server.spring.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.core.type.classreading.CachingMetadataReaderFactory; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ClassUtils; +import org.springframework.util.SystemPropertyUtils; + +@Component +public class LoggerLogic extends AbstractTransactionalLogic { + + @Autowired + private LoggerDAO loggerDAO; + + @Autowired + private ExternalResourceDAO resourceDAO; + + @Autowired + private TaskDAO taskDAO; + + @Autowired + private EntityFactory entityFactory; + + private List list(final LoggerType type) { + List result = new ArrayList<>(); + for (Logger syncopeLogger : loggerDAO.findAll(type)) { + LoggerTO loggerTO = new LoggerTO(); + BeanUtils.copyProperties(syncopeLogger, loggerTO); + result.add(loggerTO); + } + + return result; + } + + @PreAuthorize("hasRole('LOG_LIST')") + @Transactional(readOnly = true) + public List listLogs() { + return list(LoggerType.LOG); + } + + @PreAuthorize("hasRole('AUDIT_LIST')") + @Transactional(readOnly = true) + public List listAudits() { + List result = new ArrayList<>(); + + for (LoggerTO logger : list(LoggerType.AUDIT)) { + try { + result.add(AuditLoggerName.fromLoggerName(logger.getName())); + } catch (Exception e) { + LOG.warn("Unexpected audit logger name: {}", logger.getName(), e); + } + } + + return result; + } + + private void throwInvalidLogger(final LoggerType type) { + SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidLogger); + sce.getElements().add("Expected " + type.name()); + + throw sce; + } + + private LoggerTO setLevel(final String name, final Level level, final LoggerType expectedType) { + Logger syncopeLogger = loggerDAO.find(name); + if (syncopeLogger == null) { + LOG.debug("Logger {} not found: creating new...", name); + + syncopeLogger = entityFactory.newEntity(Logger.class); + syncopeLogger.setKey(name); + syncopeLogger.setType(name.startsWith(LoggerType.AUDIT.getPrefix()) + ? LoggerType.AUDIT + : LoggerType.LOG); + } + + if (expectedType != syncopeLogger.getType()) { + throwInvalidLogger(expectedType); + } + + syncopeLogger.setLevel(LoggerLevel.fromLevel(level)); + syncopeLogger = loggerDAO.save(syncopeLogger); + + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + LoggerConfig logConf = SyncopeConstants.ROOT_LOGGER.equals(name) + ? ctx.getConfiguration().getLoggerConfig(LogManager.ROOT_LOGGER_NAME) + : ctx.getConfiguration().getLoggerConfig(name); + logConf.setLevel(level); + ctx.updateLoggers(); + + LoggerTO result = new LoggerTO(); + BeanUtils.copyProperties(syncopeLogger, result); + + return result; + } + + @PreAuthorize("hasRole('LOG_SET_LEVEL')") + public LoggerTO setLogLevel(final String name, final Level level) { + return setLevel(name, level, LoggerType.LOG); + } + + @PreAuthorize("hasRole('AUDIT_ENABLE')") + public void enableAudit(final AuditLoggerName auditLoggerName) { + try { + setLevel(auditLoggerName.toLoggerName(), Level.DEBUG, LoggerType.AUDIT); + } catch (IllegalArgumentException e) { + SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidLogger); + sce.getElements().add(e.getMessage()); + throw sce; + } + } + + private LoggerTO delete(final String name, final LoggerType expectedType) throws NotFoundException { + Logger syncopeLogger = loggerDAO.find(name); + if (syncopeLogger == null) { + throw new NotFoundException("Logger " + name); + } else if (expectedType != syncopeLogger.getType()) { + throwInvalidLogger(expectedType); + } + + LoggerTO loggerToDelete = new LoggerTO(); + BeanUtils.copyProperties(syncopeLogger, loggerToDelete); + + // remove SyncopeLogger from local storage, so that LoggerLoader won't load this next time + loggerDAO.delete(syncopeLogger); + + // set log level to OFF in order to disable configured logger until next reboot + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + org.apache.logging.log4j.core.Logger logger = SyncopeConstants.ROOT_LOGGER.equals(name) + ? ctx.getLogger(LogManager.ROOT_LOGGER_NAME) : ctx.getLogger(name); + logger.setLevel(Level.OFF); + ctx.updateLoggers(); + + return loggerToDelete; + } + + @PreAuthorize("hasRole('LOG_DELETE')") + public LoggerTO deleteLog(final String name) throws NotFoundException { + return delete(name, LoggerType.LOG); + } + + @PreAuthorize("hasRole('AUDIT_DISABLE')") + public void disableAudit(final AuditLoggerName auditLoggerName) { + try { + delete(auditLoggerName.toLoggerName(), LoggerType.AUDIT); + } catch (NotFoundException e) { + LOG.debug("Ignoring disable of non existing logger {}", auditLoggerName.toLoggerName()); + } catch (IllegalArgumentException e) { + SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidLogger); + sce.getElements().add(e.getMessage()); + throw sce; + } + } + + @PreAuthorize("hasRole('AUDIT_LIST') or hasRole('NOTIFICATION_LIST')") + public List listAuditEvents() { + // use set to avoi duplications or null elements + final Set events = new HashSet(); + + try { + final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); + final MetadataReaderFactory metadataReaderFactory = + new CachingMetadataReaderFactory(resourcePatternResolver); + + final String packageSearchPath = + ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + + ClassUtils.convertClassNameToResourcePath( + SystemPropertyUtils.resolvePlaceholders(this.getClass().getPackage().getName())) + + "/" + "**/*.class"; + + final Resource[] resources = resourcePatternResolver.getResources(packageSearchPath); + for (Resource resource : resources) { + if (resource.isReadable()) { + final MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource); + final Class clazz = Class.forName(metadataReader.getClassMetadata().getClassName()); + + if (clazz.isAnnotationPresent(Component.class) + && AbstractLogic.class.isAssignableFrom(clazz)) { + final EventCategoryTO eventCategoryTO = new EventCategoryTO(); + eventCategoryTO.setCategory(clazz.getSimpleName()); + for (Method method : clazz.getDeclaredMethods()) { + if (Modifier.isPublic(method.getModifiers())) { + eventCategoryTO.getEvents().add(method.getName()); + } + } + events.add(eventCategoryTO); + } + } + } + + //SYNCOPE-608 + final EventCategoryTO authenticationControllerEvents = new EventCategoryTO(); + authenticationControllerEvents.setCategory("AuthenticationController"); + authenticationControllerEvents.getEvents().add("login"); + events.add(authenticationControllerEvents); + + events.add(new EventCategoryTO(EventCategoryType.PROPAGATION)); + events.add(new EventCategoryTO(EventCategoryType.SYNCHRONIZATION)); + events.add(new EventCategoryTO(EventCategoryType.PUSH)); + + for (AttributableType attributableType : AttributableType.values()) { + for (ExternalResource resource : resourceDAO.findAll()) { + final EventCategoryTO propEventCategoryTO = new EventCategoryTO(EventCategoryType.PROPAGATION); + final EventCategoryTO syncEventCategoryTO = new EventCategoryTO(EventCategoryType.SYNCHRONIZATION); + final EventCategoryTO pushEventCategoryTO = new EventCategoryTO(EventCategoryType.PUSH); + + propEventCategoryTO.setCategory(attributableType.name().toLowerCase()); + propEventCategoryTO.setSubcategory(resource.getKey()); + + syncEventCategoryTO.setCategory(attributableType.name().toLowerCase()); + pushEventCategoryTO.setCategory(attributableType.name().toLowerCase()); + syncEventCategoryTO.setSubcategory(resource.getKey()); + pushEventCategoryTO.setSubcategory(resource.getKey()); + + for (ResourceOperation resourceOperation : ResourceOperation.values()) { + propEventCategoryTO.getEvents().add(resourceOperation.name().toLowerCase()); + syncEventCategoryTO.getEvents().add(resourceOperation.name().toLowerCase()); + pushEventCategoryTO.getEvents().add(resourceOperation.name().toLowerCase()); + } + + events.add(propEventCategoryTO); + events.add(syncEventCategoryTO); + events.add(pushEventCategoryTO); + } + } + + for (SchedTask task : taskDAO.findAll(TaskType.SCHEDULED)) { + final EventCategoryTO eventCategoryTO = new EventCategoryTO(EventCategoryType.TASK); + eventCategoryTO.setCategory(Class.forName(task.getJobClassName()).getSimpleName()); + events.add(eventCategoryTO); + } + + for (SyncTask task : taskDAO.findAll(TaskType.SYNCHRONIZATION)) { + final EventCategoryTO eventCategoryTO = new EventCategoryTO(EventCategoryType.TASK); + eventCategoryTO.setCategory(Class.forName(task.getJobClassName()).getSimpleName()); + events.add(eventCategoryTO); + } + } catch (Exception e) { + LOG.error("Failure retrieving audit/notification events", e); + } + + return new ArrayList(events); + } + + @Override + protected LoggerTO resolveReference(final Method method, final Object... args) + throws UnresolvedReferenceException { + + throw new UnresolvedReferenceException(); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/LogicInvocationHandler.java ---------------------------------------------------------------------- diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/LogicInvocationHandler.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/LogicInvocationHandler.java new file mode 100644 index 0000000..81ca56f --- /dev/null +++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/LogicInvocationHandler.java @@ -0,0 +1,108 @@ +/* + * 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.server.logic; + +import java.lang.reflect.Method; +import java.util.Arrays; +import org.apache.syncope.common.lib.types.AuditElements; +import org.apache.syncope.server.logic.audit.AuditManager; +import org.apache.syncope.server.logic.notification.NotificationManager; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +@Aspect +public class LogicInvocationHandler { + + /** + * Logger. + */ + private static final Logger LOG = LoggerFactory.getLogger(LogicInvocationHandler.class); + + @Autowired + private NotificationManager notificationManager; + + @Autowired + private AuditManager auditManager; + + @Around("execution(* org.apache.syncope.server.logic.AbstractLogic+.*(..))") + public Object around(final ProceedingJoinPoint joinPoint) throws Throwable { + final Class clazz = joinPoint.getTarget().getClass(); + + final Object[] input = joinPoint.getArgs(); + + final String category = clazz.getSimpleName(); + + final MethodSignature ms = (MethodSignature) joinPoint.getSignature(); + Method method = ms.getMethod(); + + final String event = joinPoint.getSignature().getName(); + + AuditElements.Result result = null; + Object output = null; + Object before = null; + + try { + LOG.debug("Before {}.{}({})", clazz.getSimpleName(), event, + input == null || input.length == 0 ? "" : Arrays.asList(input)); + + try { + before = ((AbstractLogic) joinPoint.getTarget()).resolveBeanReference(method, input); + } catch (UnresolvedReferenceException ignore) { + LOG.debug("Unresolved bean reference ..."); + } + + output = joinPoint.proceed(); + result = AuditElements.Result.SUCCESS; + + LOG.debug("After returning {}.{}: {}", clazz.getSimpleName(), event, output); + return output; + } catch (Throwable t) { + output = t; + result = AuditElements.Result.FAILURE; + + LOG.debug("After throwing {}.{}", clazz.getSimpleName(), event); + throw t; + } finally { + notificationManager.createTasks( + AuditElements.EventCategoryType.REST, + category, + null, + event, + result, + before, + output, + input); + + auditManager.audit( + AuditElements.EventCategoryType.REST, + category, + null, + event, + result, + before, + output, + input); + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/NotificationController.java ---------------------------------------------------------------------- diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/NotificationController.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/NotificationController.java new file mode 100644 index 0000000..053cf3f --- /dev/null +++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/NotificationController.java @@ -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. + */ +package org.apache.syncope.server.logic; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.syncope.common.lib.to.NotificationTO; +import org.apache.syncope.persistence.api.dao.NotFoundException; +import org.apache.syncope.persistence.api.dao.NotificationDAO; +import org.apache.syncope.persistence.api.entity.Notification; +import org.apache.syncope.server.logic.data.NotificationDataBinder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Component; + +@Component +public class NotificationController extends AbstractTransactionalLogic { + + @Autowired + private NotificationDAO notificationDAO; + + @Autowired + private NotificationDataBinder binder; + + @PreAuthorize("hasRole('NOTIFICATION_READ')") + public NotificationTO read(final Long notificationId) { + Notification notification = notificationDAO.find(notificationId); + if (notification == null) { + LOG.error("Could not find notification '" + notificationId + "'"); + + throw new NotFoundException(String.valueOf(notificationId)); + } + + return binder.getNotificationTO(notification); + } + + @PreAuthorize("hasRole('NOTIFICATION_LIST')") + public List list() { + List notifications = notificationDAO.findAll(); + + List notificationTOs = new ArrayList(); + for (Notification notification : notifications) { + notificationTOs.add(binder.getNotificationTO(notification)); + } + + return notificationTOs; + } + + @PreAuthorize("hasRole('NOTIFICATION_CREATE')") + public NotificationTO create(final NotificationTO notificationTO) { + return binder.getNotificationTO(notificationDAO.save(binder.create(notificationTO))); + } + + @PreAuthorize("hasRole('NOTIFICATION_UPDATE')") + public NotificationTO update(final NotificationTO notificationTO) { + Notification notification = notificationDAO.find(notificationTO.getKey()); + if (notification == null) { + LOG.error("Could not find notification '" + notificationTO.getKey() + "'"); + throw new NotFoundException(String.valueOf(notificationTO.getKey())); + } + + binder.update(notification, notificationTO); + notification = notificationDAO.save(notification); + + return binder.getNotificationTO(notification); + } + + @PreAuthorize("hasRole('CONNECTOR_DELETE')") + public NotificationTO delete(final Long notificationId) { + Notification notification = notificationDAO.find(notificationId); + if (notification == null) { + LOG.error("Could not find notification '" + notificationId + "'"); + + throw new NotFoundException(String.valueOf(notificationId)); + } + + NotificationTO deleted = binder.getNotificationTO(notification); + notificationDAO.delete(notificationId); + return deleted; + } + + @Override + protected NotificationTO resolveReference(final Method method, final Object... args) + throws UnresolvedReferenceException { + + Long id = null; + + if (ArrayUtils.isNotEmpty(args)) { + for (int i = 0; id == null && i < args.length; i++) { + if (args[i] instanceof Long) { + id = (Long) args[i]; + } else if (args[i] instanceof NotificationTO) { + id = ((NotificationTO) args[i]).getKey(); + } + } + } + + if ((id != null) && !id.equals(0l)) { + try { + return binder.getNotificationTO(notificationDAO.find(id)); + } catch (Throwable ignore) { + LOG.debug("Unresolved reference", ignore); + throw new UnresolvedReferenceException(ignore); + } + } + + throw new UnresolvedReferenceException(); + } +}